Back to index

lightning-sunbird  0.9+nobinonly
getdn.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla Communicator client code, released
00015  * March 31, 1998.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 /*
00038  *  Copyright (c) 1994 Regents of the University of Michigan.
00039  *  All rights reserved.
00040  */
00041 /*
00042  *  getdn.c
00043  */
00044 
00045 #if 0
00046 #ifndef lint 
00047 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
00048 #endif
00049 #endif
00050 
00051 #include "ldap-int.h"
00052 
00053 char *
00054 LDAP_CALL
00055 ldap_get_dn( LDAP *ld, LDAPMessage *entry )
00056 {
00057        char                 *dn;
00058        struct berelement    tmp;
00059 
00060        LDAPDebug( LDAP_DEBUG_TRACE, "ldap_get_dn\n", 0, 0, 0 );
00061 
00062        if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
00063               return( NULL );             /* punt */
00064        }
00065 
00066        if ( !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry )) {
00067               LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
00068               return( NULL );
00069        }
00070 
00071        tmp = *entry->lm_ber;       /* struct copy */
00072        if ( ber_scanf( &tmp, "{a", &dn ) == LBER_ERROR ) {
00073               LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL );
00074               return( NULL );
00075        }
00076 
00077        return( dn );
00078 }
00079 
00080 char *
00081 LDAP_CALL
00082 ldap_dn2ufn( const char *dn )
00083 {
00084        char   *p, *ufn, *r;
00085        size_t plen;
00086        int    state;
00087 
00088        LDAPDebug( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n", 0, 0, 0 );
00089 
00090        if ( dn == NULL ) {
00091               dn = "";
00092        }
00093 
00094        if ( ldap_is_dns_dn( dn ) || ( p = strchr( dn, '=' )) == NULL )
00095               return( nsldapi_strdup( (char *)dn ));
00096 
00097        ufn = nsldapi_strdup( ++p );
00098 
00099 #define INQUOTE             1
00100 #define OUTQUOTE     2
00101        state = OUTQUOTE;
00102        for ( p = ufn, r = ufn; *p; p += plen ) {
00103            plen = 1;
00104               switch ( *p ) {
00105               case '\\':
00106                      if ( *++p == '\0' )
00107                             plen=0;
00108                      else {
00109                             *r++ = '\\';
00110                             r += (plen = LDAP_UTF8COPY(r,p));
00111                      }
00112                      break;
00113               case '"':
00114                      if ( state == INQUOTE )
00115                             state = OUTQUOTE;
00116                      else
00117                             state = INQUOTE;
00118                      *r++ = *p;
00119                      break;
00120               case ';':
00121               case ',':
00122                      if ( state == OUTQUOTE )
00123                             *r++ = ',';
00124                      else
00125                             *r++ = *p;
00126                      break;
00127               case '=':
00128                      if ( state == INQUOTE )
00129                             *r++ = *p;
00130                      else {
00131                             char   *rsave = r;
00132                             LDAP_UTF8DEC(r);
00133                             *rsave = '\0';
00134                             while ( !ldap_utf8isspace( r ) && *r != ';'
00135                                 && *r != ',' && r > ufn )
00136                                    LDAP_UTF8DEC(r);
00137                             LDAP_UTF8INC(r);
00138 
00139                             if ( strcasecmp( r, "c" )
00140                                 && strcasecmp( r, "o" )
00141                                 && strcasecmp( r, "ou" )
00142                                 && strcasecmp( r, "st" )
00143                                 && strcasecmp( r, "l" )
00144                                 && strcasecmp( r, "dc" )
00145                                 && strcasecmp( r, "uid" )
00146                                 && strcasecmp( r, "cn" ) ) {
00147                                    r = rsave;
00148                                    *r++ = '=';
00149                             }
00150                      }
00151                      break;
00152               default:
00153                      r += (plen = LDAP_UTF8COPY(r,p));
00154                      break;
00155               }
00156        }
00157        *r = '\0';
00158 
00159        return( ufn );
00160 }
00161 
00162 char **
00163 LDAP_CALL
00164 ldap_explode_dns( const char *dn )
00165 {
00166        int    ncomps, maxcomps;
00167        char   *s, *cpydn;
00168        char   **rdns;
00169 #ifdef HAVE_STRTOK_R /* defined in portable.h */
00170        char   *lasts;
00171 #endif
00172 
00173        if ( dn == NULL ) {
00174               dn = "";
00175        }
00176 
00177        if ( (rdns = (char **)NSLDAPI_MALLOC( 8 * sizeof(char *) )) == NULL ) {
00178               return( NULL );
00179        }
00180 
00181        maxcomps = 8;
00182        ncomps = 0;
00183        cpydn = nsldapi_strdup( (char *)dn );
00184        for ( s = STRTOK( cpydn, "@.", &lasts ); s != NULL;
00185            s = STRTOK( NULL, "@.", &lasts ) ) {
00186               if ( ncomps == maxcomps ) {
00187                      maxcomps *= 2;
00188                      if ( (rdns = (char **)NSLDAPI_REALLOC( rdns, maxcomps *
00189                          sizeof(char *) )) == NULL ) {
00190                             NSLDAPI_FREE( cpydn );
00191                             return( NULL );
00192                      }
00193               }
00194               rdns[ncomps++] = nsldapi_strdup( s );
00195        }
00196        rdns[ncomps] = NULL;
00197        NSLDAPI_FREE( cpydn );
00198 
00199        return( rdns );
00200 }
00201 
00202 #define LDAP_DN             1
00203 #define LDAP_RDN     2
00204 
00205 static char **
00206 ldap_explode( const char *dn, const int notypes, const int nametype )
00207 {
00208        char   *p, *q, *rdnstart, **rdns = NULL;
00209        size_t plen = 0;
00210        int    state, count = 0, endquote, len, goteq;
00211 
00212        LDAPDebug( LDAP_DEBUG_TRACE, "ldap_explode\n", 0, 0, 0 );
00213 
00214        if ( dn == NULL ) {
00215               dn = "";
00216        }
00217 
00218 #if 0
00219        if ( ldap_is_dns_dn( dn ) ) {
00220               return( ldap_explode_dns( dn ) );
00221        }
00222 #endif
00223 
00224        while ( ldap_utf8isspace( (char *)dn )) { /* ignore leading spaces */
00225               ++dn;
00226        }
00227 
00228        p = rdnstart = (char *) dn;
00229        state = OUTQUOTE;
00230        goteq = 0;
00231 
00232        do {
00233               p += plen;
00234               plen = 1;
00235               switch ( *p ) {
00236               case '\\':
00237                      if ( *++p == '\0' )
00238                             p--;
00239                      else
00240                             plen = LDAP_UTF8LEN(p);
00241                      break;
00242               case '"':
00243                      if ( state == INQUOTE )
00244                             state = OUTQUOTE;
00245                      else
00246                             state = INQUOTE;
00247                      break;
00248               case '+': if ( nametype != LDAP_RDN ) break;
00249               case ';':
00250               case ',':
00251               case '\0':
00252                      if ( state == OUTQUOTE ) {
00253                             /*
00254                              * semicolon and comma are not valid RDN
00255                              * separators.
00256                              */
00257                             if ( nametype == LDAP_RDN && 
00258                                    ( *p == ';' || *p == ',' || !goteq)) {
00259                                    ldap_charray_free( rdns );
00260                                    return NULL;
00261                             }
00262                             if ( (*p == ',' || *p == ';') && !goteq ) {
00263                                    /* If we get here, we have a case similar
00264                                 * to <attr>=<value>,<string>,<attr>=<value>
00265                                 * This is not a valid dn */
00266                                 ldap_charray_free( rdns );
00267                                 return NULL;
00268                             }
00269                             goteq = 0;
00270                             ++count;
00271                             if ( rdns == NULL ) {
00272                                    if (( rdns = (char **)NSLDAPI_MALLOC( 8
00273                                            * sizeof( char *))) == NULL )
00274                                           return( NULL );
00275                             } else if ( count >= 8 ) {
00276                                    if (( rdns = (char **)NSLDAPI_REALLOC(
00277                                        rdns, (count+1) *
00278                                        sizeof( char *))) == NULL )
00279                                           return( NULL );
00280                             }
00281                             rdns[ count ] = NULL;
00282                             endquote = 0;
00283                             if ( notypes ) {
00284                                    for ( q = rdnstart;
00285                                        q < p && *q != '='; ++q ) {
00286                                           ;
00287                                    }
00288                                    if ( q < p ) { /* *q == '=' */
00289                                           rdnstart = ++q;
00290                                    }
00291                                    if ( *rdnstart == '"' ) {
00292                                           ++rdnstart;
00293                                    }
00294                                    
00295                                    if ( *(p-1) == '"' ) {
00296                                           endquote = 1;
00297                                           --p;
00298                                    }
00299                             }
00300 
00301                             len = p - rdnstart;
00302                             if (( rdns[ count-1 ] = (char *)NSLDAPI_CALLOC(
00303                                 1, len + 1 )) != NULL ) {
00304                                    SAFEMEMCPY( rdns[ count-1 ], rdnstart,
00305                                        len );
00306                                    if ( !endquote ) {
00307                                           /* trim trailing spaces */
00308                                           while ( len > 0 &&
00309                                               ldap_utf8isspace(
00310                                               &rdns[count-1][len-1] )) {
00311                                                  --len;
00312                                           }
00313                                    }
00314                                    rdns[ count-1 ][ len ] = '\0';
00315                             }
00316 
00317                             /*
00318                              *  Don't forget to increment 'p' back to where
00319                              *  it should be.  If we don't, then we will
00320                              *  never get past an "end quote."
00321                              */
00322                             if ( endquote == 1 )
00323                                    p++;
00324 
00325                             rdnstart = *p ? p + 1 : p;
00326                             while ( ldap_utf8isspace( rdnstart ))
00327                                    ++rdnstart;
00328                      }
00329                      break;
00330               case '=':
00331                      if ( state == OUTQUOTE ) {
00332                             goteq = 1;
00333                      }
00334                      /* FALL */
00335               default:
00336                      plen = LDAP_UTF8LEN(p);
00337                      break;
00338               }
00339        } while ( *p );
00340 
00341        return( rdns );
00342 }
00343 
00344 char **
00345 LDAP_CALL
00346 ldap_explode_dn( const char *dn, const int notypes )
00347 {
00348        return( ldap_explode( dn, notypes, LDAP_DN ) );
00349 }
00350 
00351 char **
00352 LDAP_CALL
00353 ldap_explode_rdn( const char *rdn, const int notypes )
00354 {
00355        return( ldap_explode( rdn, notypes, LDAP_RDN ) );
00356 }
00357 
00358 int
00359 LDAP_CALL
00360 ldap_is_dns_dn( const char *dn )
00361 {
00362        return( dn != NULL && dn[ 0 ] != '\0' && strchr( dn, '=' ) == NULL &&
00363            strchr( dn, ',' ) == NULL );
00364 }