[Date Prev][Date Next] [Chronological] [Thread] [Top]

[PATCH-sorta] telephoneNumberMatch and an introduction

Hi folks,

My name is Dennis Grant. I've been the chief LDAP codemonkey here at
DaimlerChrysler since 1998 or so. I'm the guy who built the DCX corporate
directory, all the various utilities that go with its daily operation, and
I'm still the chief coal-shoveller when it comes to all things LDAP.

Some of my utilities have made it into PerLDAP, I believe.

Anyway, our infrastructure is based on the fine family of Netscape
products, and will likely remain so for some time. However, we've come up
with an expansion plan whereby replicas of the main Directory will be
pushed out to all of our manufacturing plants. The plan is that these
servers will be Linux boxen running OpenLDAP as the server software.

Accordingly, my attention has become highly focussed on Netscape->OpenLDAP
interoperability issues. I want - as much as possible - our Directory
Services infrastructure server-neutral. The same utilities, the same
configurations, the same LDIF core content on all servers, no matter if the
platform is Netscape or OpenLDAP.

Given that they share the same codebase (to a certain extent) this isn't as
unrealistic as one might otherwise fear. ;)

Failing that, I can live with conversion tools, so that (for example) when
extending the schema, we edit the slapd.user_at.conf on the Netscape
servers, and then run a utility that spits out an OpenLDAP .schema file -
or even more useful, a tool that reads the Netscape ACIs from the Directory
and spits out OpenLDAP ACI config files.

I'm not afraid of coding, and I believe in sharing what we write, so as my
itches get scratched, I will be forwarding them back here for inclusion
into OpenLDAP.

This is the first such itch. Our schema has a few attributes with the
telephoneNumber syntax OID, and these attributes are indexed. However, the
telephoneNumberMatch match type is not yet implimented. (As of OpenLDAP
2.0.7 at least) Accordingly, the attempt to load our Directory into
OpenLDAP barfed on the invalid equality indicies.

So I had a look at the code, and figured I'd try tackling implementing it.

WARNING: Although, once upon a time, I did a lot of C work, in the last 10
years or so I've been living in a mostly perl world. Perl spoils you with
things like variable-length strings and regular expressions. So my C code
is a little... workmanlike. Perhaps even "basic".

Attached is what I think is an implementation of the telephoneNumberMatch
subroutine. It goes in slapd/schema_init.c It compiles. :)

I'm sending it in for review (before I get too deep) and for further
instructions on what do do next. The slapd code isn't as commented as I'd
like, it's hard at times to see where all the flow points are. This much I
figured out, so here's the patch. :)

Assistance with how to go forward from this point would be greatly
appreciated. Code critique - no matter how brutal - is also solicited. ;)



Insert this into "schema_init.c"

static int
     int *matchp,
     slap_mask_t flags,
     Syntax *syntax,
     MatchingRule *mr,
     struct berval *value,
     void *assertedValue )
     /* Added May 02/2001 by DG (dg50@dcx.com)

        Match a telephone number.

        Strip out anything not a decimal digit, and then compare the
        numbers that remain. Eliminates human-readable formatting
        characters not germane to the actual number.

        For example:

        (604) 555-5555
        (604) 555 5555
        604 555 5555

        are all the same number, and should match.

        FIXME: Maybe we could bake some more intelligence in here, should

        1 (604) 555-5555
           +1 604 555 5555

           all match? Would have to do some parsing and some DWIM processing.

          *value         The actual value berval
          *assertedValue The value we're checking against berval
          *matchp        Result code (or something)


     /* Buffers for the filtered strings */
     char filtered_value[value->bv_len];
     char filtered_assertedValue[((struct berval *) assertedValue)->bv_len];

     /* counters */
     int n = 0;
     int i = 0;

     /* match flag of some sort... not sure what nonzero means */
     int match = 0;

     /* Loop over the value string, copy over digits */
     for (n = 0; n < value->bv_len; n++) {
          if (isdigit(value->bv_val[n])) {
               filtered_value[i] = value->bv_val[n];

     /* Ditto the assertedValue string */
     i = 0;
     for (n = 0; n < ((struct berval *) assertedValue)->bv_len; n++) {
          if (isdigit(((struct berval *) assertedValue)->bv_val[n])) {
               filtered_assertedValue[i] = ((struct berval *) assertedValue)->bv_val[n];

     /* if both filtered values are the same length, we can check them
        otherwise, skip the check */

     match = strlen(filtered_value) - strlen(filtered_assertedValue);

     if( match == 0 ) {
          /* same length! So check them.
             FIXME: the counter i as the length argument to strncmp
                    to save another strlen call. Is this valid?
             FIXME: Why strncmp? Why not just strcmp? */

          match = strncmp( filtered_value,
                     i );

     /* Not sure where this is defined, but all the other *Match routines
        use it, so we'll Steal With Pride here */

     *matchp = match;
     return LDAP_SUCCESS;