Back to index

openldap  2.4.31
syntax.c
Go to the documentation of this file.
00001 /* syntax.c - routines to manage syntax definitions */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 
00017 #include "portable.h"
00018 
00019 #include <stdio.h>
00020 
00021 #include <ac/ctype.h>
00022 #include <ac/string.h>
00023 #include <ac/socket.h>
00024 
00025 #include "slap.h"
00026 
00027 struct sindexrec {
00028        char          *sir_name;
00029        Syntax        *sir_syn;
00030 };
00031 
00032 static Avlnode       *syn_index = NULL;
00033 static LDAP_STAILQ_HEAD(SyntaxList, Syntax) syn_list
00034        = LDAP_STAILQ_HEAD_INITIALIZER(syn_list);
00035 
00036 /* Last hardcoded attribute registered */
00037 Syntax *syn_sys_tail;
00038 
00039 static int
00040 syn_index_cmp(
00041        const void *v_sir1,
00042        const void *v_sir2
00043 )
00044 {
00045        const struct sindexrec *sir1 = v_sir1, *sir2 = v_sir2;
00046        return (strcmp( sir1->sir_name, sir2->sir_name ));
00047 }
00048 
00049 static int
00050 syn_index_name_cmp(
00051        const void *name,
00052        const void *sir
00053 )
00054 {
00055        return (strcmp( name, ((const struct sindexrec *)sir)->sir_name ));
00056 }
00057 
00058 Syntax *
00059 syn_find( const char *synname )
00060 {
00061        struct sindexrec     *sir = NULL;
00062 
00063        if ( (sir = avl_find( syn_index, synname, syn_index_name_cmp )) != NULL ) {
00064               return( sir->sir_syn );
00065        }
00066        return( NULL );
00067 }
00068 
00069 Syntax *
00070 syn_find_desc( const char *syndesc, int *len )
00071 {
00072        Syntax        *synp;
00073 
00074        LDAP_STAILQ_FOREACH(synp, &syn_list, ssyn_next) {
00075               if ((*len = dscompare( synp->ssyn_syn.syn_desc, syndesc, '{' /*'}'*/ ))) {
00076                      return synp;
00077               }
00078        }
00079        return( NULL );
00080 }
00081 
00082 int
00083 syn_is_sup( Syntax *syn, Syntax *sup )
00084 {
00085        int    i;
00086 
00087        assert( syn != NULL );
00088        assert( sup != NULL );
00089 
00090        if ( syn == sup ) {
00091               return 1;
00092        }
00093 
00094        if ( syn->ssyn_sups == NULL ) {
00095               return 0;
00096        }
00097 
00098        for ( i = 0; syn->ssyn_sups[i]; i++ ) {
00099               if ( syn->ssyn_sups[i] == sup ) {
00100                      return 1;
00101               }
00102 
00103               if ( syn_is_sup( syn->ssyn_sups[i], sup ) ) {
00104                      return 1;
00105               }
00106        }
00107 
00108        return 0;
00109 }
00110 
00111 void
00112 syn_destroy( void )
00113 {
00114        Syntax *s;
00115 
00116        avl_free( syn_index, ldap_memfree );
00117        while( !LDAP_STAILQ_EMPTY( &syn_list ) ) {
00118               s = LDAP_STAILQ_FIRST( &syn_list );
00119               LDAP_STAILQ_REMOVE_HEAD( &syn_list, ssyn_next );
00120               if ( s->ssyn_sups ) {
00121                      SLAP_FREE( s->ssyn_sups );
00122               }
00123               ldap_syntax_free( (LDAPSyntax *)s );
00124        }
00125 }
00126 
00127 static int
00128 syn_insert(
00129        Syntax        *ssyn,
00130        Syntax        *prev,
00131        const char    **err )
00132 {
00133        struct sindexrec     *sir;
00134 
00135        LDAP_STAILQ_NEXT( ssyn, ssyn_next ) = NULL;
00136  
00137        if ( ssyn->ssyn_oid ) {
00138               sir = (struct sindexrec *)
00139                      SLAP_CALLOC( 1, sizeof(struct sindexrec) );
00140               if( sir == NULL ) {
00141                      Debug( LDAP_DEBUG_ANY, "SLAP_CALLOC Error\n", 0, 0, 0 );
00142                      return LDAP_OTHER;
00143               }
00144               sir->sir_name = ssyn->ssyn_oid;
00145               sir->sir_syn = ssyn;
00146               if ( avl_insert( &syn_index, (caddr_t) sir,
00147                                syn_index_cmp, avl_dup_error ) ) {
00148                      *err = ssyn->ssyn_oid;
00149                      ldap_memfree(sir);
00150                      return SLAP_SCHERR_SYN_DUP;
00151               }
00152               /* FIX: temporal consistency check */
00153               syn_find(sir->sir_name);
00154        }
00155 
00156        if ( ssyn->ssyn_flags & SLAP_AT_HARDCODE ) {
00157               prev = syn_sys_tail;
00158               syn_sys_tail = ssyn;
00159        }
00160 
00161        if ( prev ) {
00162               LDAP_STAILQ_INSERT_AFTER( &syn_list, prev, ssyn, ssyn_next );
00163        } else {
00164               LDAP_STAILQ_INSERT_TAIL( &syn_list, ssyn, ssyn_next );
00165        }
00166        return 0;
00167 }
00168 
00169 int
00170 syn_add(
00171        LDAPSyntax           *syn,
00172        int                  user,
00173        slap_syntax_defs_rec *def,
00174        Syntax               **ssynp,
00175        Syntax               *prev,
00176        const char           **err )
00177 {
00178        Syntax        *ssyn;
00179        int           code = 0;
00180 
00181        if ( ssynp != NULL ) {
00182               *ssynp = NULL;
00183        }
00184 
00185        ssyn = (Syntax *) SLAP_CALLOC( 1, sizeof(Syntax) );
00186        if ( ssyn == NULL ) {
00187               Debug( LDAP_DEBUG_ANY, "SLAP_CALLOC Error\n", 0, 0, 0 );
00188               return SLAP_SCHERR_OUTOFMEM;
00189        }
00190 
00191        AC_MEMCPY( &ssyn->ssyn_syn, syn, sizeof(LDAPSyntax) );
00192 
00193        LDAP_STAILQ_NEXT(ssyn,ssyn_next) = NULL;
00194 
00195        /*
00196         * note: ssyn_bvoid uses the same memory of ssyn_syn.syn_oid;
00197         * ssyn_oidlen is #defined as ssyn_bvoid.bv_len
00198         */
00199        ssyn->ssyn_bvoid.bv_val = ssyn->ssyn_syn.syn_oid;
00200        ssyn->ssyn_oidlen = strlen(syn->syn_oid);
00201        ssyn->ssyn_flags = def->sd_flags;
00202        ssyn->ssyn_validate = def->sd_validate;
00203        ssyn->ssyn_pretty = def->sd_pretty;
00204 
00205        ssyn->ssyn_sups = NULL;
00206 
00207 #ifdef SLAPD_BINARY_CONVERSION
00208        ssyn->ssyn_ber2str = def->sd_ber2str;
00209        ssyn->ssyn_str2ber = def->sd_str2ber;
00210 #endif
00211 
00212        if ( def->sd_validate == NULL && def->sd_pretty == NULL && syn->syn_extensions != NULL ) {
00213               LDAPSchemaExtensionItem **lsei;
00214               Syntax *subst = NULL;
00215 
00216               for ( lsei = syn->syn_extensions; *lsei != NULL; lsei++) {
00217                      if ( strcmp( (*lsei)->lsei_name, "X-SUBST" ) != 0 ) {
00218                             continue;
00219                      }
00220 
00221                      assert( (*lsei)->lsei_values != NULL );
00222                      if ( (*lsei)->lsei_values[0] == '\0'
00223                             || (*lsei)->lsei_values[1] != '\0' )
00224                      {
00225                             Debug( LDAP_DEBUG_ANY, "syn_add(%s): exactly one substitute syntax must be present\n",
00226                                    ssyn->ssyn_syn.syn_oid, 0, 0 );
00227                             return SLAP_SCHERR_SYN_SUBST_NOT_SPECIFIED;
00228                      }
00229 
00230                      subst = syn_find( (*lsei)->lsei_values[0] );
00231                      if ( subst == NULL ) {
00232                             Debug( LDAP_DEBUG_ANY, "syn_add(%s): substitute syntax %s not found\n",
00233                                    ssyn->ssyn_syn.syn_oid, (*lsei)->lsei_values[0], 0 );
00234                             return SLAP_SCHERR_SYN_SUBST_NOT_FOUND;
00235                      }
00236                      break;
00237               }
00238 
00239               if ( subst != NULL ) {
00240                      ssyn->ssyn_flags = subst->ssyn_flags;
00241                      ssyn->ssyn_validate = subst->ssyn_validate;
00242                      ssyn->ssyn_pretty = subst->ssyn_pretty;
00243 
00244                      ssyn->ssyn_sups = NULL;
00245 
00246 #ifdef SLAPD_BINARY_CONVERSION
00247                      ssyn->ssyn_ber2str = subst->ssyn_ber2str;
00248                      ssyn->ssyn_str2ber = subst->ssyn_str2ber;
00249 #endif
00250               }
00251        }
00252 
00253        if ( def->sd_sups != NULL ) {
00254               int    cnt;
00255 
00256               for ( cnt = 0; def->sd_sups[cnt] != NULL; cnt++ )
00257                      ;
00258               
00259               ssyn->ssyn_sups = (Syntax **)SLAP_CALLOC( cnt + 1,
00260                      sizeof( Syntax * ) );
00261               if ( ssyn->ssyn_sups == NULL ) {
00262                      Debug( LDAP_DEBUG_ANY, "SLAP_CALLOC Error\n", 0, 0, 0 );
00263                      code = SLAP_SCHERR_OUTOFMEM;
00264 
00265               } else {
00266                      for ( cnt = 0; def->sd_sups[cnt] != NULL; cnt++ ) {
00267                             ssyn->ssyn_sups[cnt] = syn_find( def->sd_sups[cnt] );
00268                             if ( ssyn->ssyn_sups[cnt] == NULL ) {
00269                                    *err = def->sd_sups[cnt];
00270                                    code = SLAP_SCHERR_SYN_SUP_NOT_FOUND;
00271                             }
00272                      }
00273               }
00274        }
00275 
00276        if ( !user )
00277               ssyn->ssyn_flags |= SLAP_SYNTAX_HARDCODE;
00278 
00279        if ( code == 0 ) {
00280               code = syn_insert( ssyn, prev, err );
00281        }
00282 
00283        if ( code != 0 && ssyn != NULL ) {
00284               if ( ssyn->ssyn_sups != NULL ) {
00285                      SLAP_FREE( ssyn->ssyn_sups );
00286               }
00287               SLAP_FREE( ssyn );
00288               ssyn = NULL;
00289        }
00290 
00291        if (ssynp ) {
00292               *ssynp = ssyn;
00293        }
00294 
00295        return code;
00296 }
00297 
00298 int
00299 register_syntax(
00300        slap_syntax_defs_rec *def )
00301 {
00302        LDAPSyntax    *syn;
00303        int           code;
00304        const char    *err;
00305 
00306        syn = ldap_str2syntax( def->sd_desc, &code, &err, LDAP_SCHEMA_ALLOW_ALL);
00307        if ( !syn ) {
00308               Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s before %s in %s\n",
00309                   ldap_scherr2str(code), err, def->sd_desc );
00310 
00311               return( -1 );
00312        }
00313 
00314        code = syn_add( syn, 0, def, NULL, NULL, &err );
00315 
00316        if ( code ) {
00317               Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s %s in %s\n",
00318                   scherr2str(code), err, def->sd_desc );
00319               ldap_syntax_free( syn );
00320 
00321               return( -1 );
00322        }
00323 
00324        ldap_memfree( syn );
00325 
00326        return( 0 );
00327 }
00328 
00329 int
00330 syn_schema_info( Entry *e )
00331 {
00332        AttributeDescription *ad_ldapSyntaxes = slap_schema.si_ad_ldapSyntaxes;
00333        Syntax        *syn;
00334        struct berval val;
00335        struct berval nval;
00336 
00337        LDAP_STAILQ_FOREACH(syn, &syn_list, ssyn_next ) {
00338               if ( ! syn->ssyn_validate ) {
00339                      /* skip syntaxes without validators */
00340                      continue;
00341               }
00342               if ( syn->ssyn_flags & SLAP_SYNTAX_HIDE ) {
00343                      /* hide syntaxes */
00344                      continue;
00345               }
00346 
00347               if ( ldap_syntax2bv( &syn->ssyn_syn, &val ) == NULL ) {
00348                      return -1;
00349               }
00350 #if 0
00351               Debug( LDAP_DEBUG_TRACE, "Merging syn [%ld] %s\n",
00352               (long) val.bv_len, val.bv_val, 0 );
00353 #endif
00354 
00355               nval.bv_val = syn->ssyn_oid;
00356               nval.bv_len = strlen(syn->ssyn_oid);
00357 
00358               if( attr_merge_one( e, ad_ldapSyntaxes, &val, &nval ) )
00359               {
00360                      return -1;
00361               }
00362               ldap_memfree( val.bv_val );
00363        }
00364        return 0;
00365 }
00366 
00367 void
00368 syn_delete( Syntax *syn )
00369 {
00370        LDAP_STAILQ_REMOVE(&syn_list, syn, Syntax, ssyn_next);
00371 }
00372 
00373 int
00374 syn_start( Syntax **syn )
00375 {
00376        assert( syn != NULL );
00377 
00378        *syn = LDAP_STAILQ_FIRST(&syn_list);
00379 
00380        return (*syn != NULL);
00381 }
00382 
00383 int
00384 syn_next( Syntax **syn )
00385 {
00386        assert( syn != NULL );
00387 
00388 #if 0  /* pedantic check: don't use this */
00389        {
00390               Syntax *tmp = NULL;
00391 
00392               LDAP_STAILQ_FOREACH(tmp,&syn_list,ssyn_next) {
00393                      if ( tmp == *syn ) {
00394                             break;
00395                      }
00396               }
00397 
00398               assert( tmp != NULL );
00399        }
00400 #endif
00401 
00402        *syn = LDAP_STAILQ_NEXT(*syn,ssyn_next);
00403 
00404        return (*syn != NULL);
00405 }
00406 
00407 void
00408 syn_unparse( BerVarray *res, Syntax *start, Syntax *end, int sys )
00409 {
00410        Syntax *syn;
00411        int i, num;
00412        struct berval bv, *bva = NULL, idx;
00413        char ibuf[32];
00414 
00415        if ( !start )
00416               start = LDAP_STAILQ_FIRST( &syn_list );
00417 
00418        /* count the result size */
00419        i = 0;
00420        for ( syn = start; syn; syn = LDAP_STAILQ_NEXT( syn, ssyn_next ) ) {
00421               if ( sys && !( syn->ssyn_flags & SLAP_SYNTAX_HARDCODE ) ) break;
00422               i++;
00423               if ( syn == end ) break;
00424        }
00425        if ( !i ) return;
00426 
00427        num = i;
00428        bva = ch_malloc( (num+1) * sizeof(struct berval) );
00429        BER_BVZERO( bva );
00430        idx.bv_val = ibuf;
00431        if ( sys ) {
00432               idx.bv_len = 0;
00433               ibuf[0] = '\0';
00434        }
00435        i = 0;
00436        for ( syn = start; syn; syn = LDAP_STAILQ_NEXT( syn, ssyn_next ) ) {
00437               if ( sys && !( syn->ssyn_flags & SLAP_SYNTAX_HARDCODE ) ) break;
00438               if ( ldap_syntax2bv( &syn->ssyn_syn, &bv ) == NULL ) {
00439                      ber_bvarray_free( bva );
00440               }
00441               if ( !sys ) {
00442                      idx.bv_len = sprintf(idx.bv_val, "{%d}", i);
00443               }
00444               bva[i].bv_len = idx.bv_len + bv.bv_len;
00445               bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
00446               strcpy( bva[i].bv_val, ibuf );
00447               strcpy( bva[i].bv_val + idx.bv_len, bv.bv_val );
00448               i++;
00449               bva[i].bv_val = NULL;
00450               ldap_memfree( bv.bv_val );
00451               if ( syn == end ) break;
00452        }
00453        *res = bva;
00454 }
00455