2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2014 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
17 * schema.c: parsing routines used by servers and clients to process
24 #include <ac/stdlib.h>
26 #include <ac/string.h>
31 #include <ldap_schema.h>
33 static const char EndOfInput[] = "end of input";
36 choose_name( char *names[], const char *fallback )
38 return (names != NULL && names[0] != NULL) ? names[0] : fallback;
42 ldap_syntax2name( LDAPSyntax * syn )
44 if (!syn) return NULL;
45 return( syn->syn_oid );
49 ldap_matchingrule2name( LDAPMatchingRule * mr )
52 return( choose_name( mr->mr_names, mr->mr_oid ) );
56 ldap_matchingruleuse2name( LDAPMatchingRuleUse * mru )
58 if (!mru) return NULL;
59 return( choose_name( mru->mru_names, mru->mru_oid ) );
63 ldap_attributetype2name( LDAPAttributeType * at )
66 return( choose_name( at->at_names, at->at_oid ) );
70 ldap_objectclass2name( LDAPObjectClass * oc )
73 return( choose_name( oc->oc_names, oc->oc_oid ) );
77 ldap_contentrule2name( LDAPContentRule * cr )
80 return( choose_name( cr->cr_names, cr->cr_oid ) );
84 ldap_nameform2name( LDAPNameForm * nf )
87 return( choose_name( nf->nf_names, nf->nf_oid ) );
91 ldap_structurerule2name( LDAPStructureRule * sr )
94 return( choose_name( sr->sr_names, NULL ) );
98 * When pretty printing the entities we will be appending to a buffer.
99 * Since checking for overflow, realloc'ing and checking if no error
100 * is extremely boring, we will use a protection layer that will let
101 * us blissfully ignore the error until the end. This layer is
102 * implemented with the help of the next type.
105 typedef struct safe_string {
113 new_safe_string(int size)
117 ss = LDAP_MALLOC(sizeof(safe_string));
121 ss->val = LDAP_MALLOC(size);
135 safe_string_free(safe_string * ss)
145 safe_string_val(safe_string * ss)
147 ss->val[ss->pos] = '\0';
153 safe_strdup(safe_string * ss)
155 char *ret = LDAP_MALLOC(ss->pos+1);
158 AC_MEMCPY(ret, ss->val, ss->pos);
164 append_to_safe_string(safe_string * ss, char * s)
170 * Some runaway process is trying to append to a string that
171 * overflowed and we could not extend.
176 /* We always make sure there is at least one position available */
177 if ( ss->pos + l >= ss->size-1 ) {
179 if ( ss->pos + l >= ss->size-1 ) {
180 ss->size = ss->pos + l + 1;
183 temp = LDAP_REALLOC(ss->val, ss->size);
185 /* Trouble, out of memory */
191 strncpy(&ss->val[ss->pos], s, l);
193 if ( ss->pos > 0 && LDAP_SPACE(ss->val[ss->pos-1]) )
202 print_literal(safe_string *ss, char *s)
204 return(append_to_safe_string(ss,s));
208 print_whsp(safe_string *ss)
211 return(append_to_safe_string(ss,""));
213 return(append_to_safe_string(ss," "));
217 print_numericoid(safe_string *ss, char *s)
220 return(append_to_safe_string(ss,s));
222 return(append_to_safe_string(ss,""));
225 /* This one is identical to print_qdescr */
227 print_qdstring(safe_string *ss, char *s)
230 print_literal(ss,"'");
231 append_to_safe_string(ss,s);
232 print_literal(ss,"'");
233 return(print_whsp(ss));
237 print_qdescr(safe_string *ss, char *s)
240 print_literal(ss,"'");
241 append_to_safe_string(ss,s);
242 print_literal(ss,"'");
243 return(print_whsp(ss));
247 print_qdescrlist(safe_string *ss, char **sa)
252 for (sp=sa; *sp; sp++) {
253 ret = print_qdescr(ss,*sp);
255 /* If the list was empty, we return zero that is potentially
256 * incorrect, but since we will be still appending things, the
257 * overflow will be detected later. Maybe FIX.
263 print_qdescrs(safe_string *ss, char **sa)
265 /* The only way to represent an empty list is as a qdescrlist
266 * so, if the list is empty we treat it as a long list.
267 * Really, this is what the syntax mandates. We should not
268 * be here if the list was empty, but if it happens, a label
269 * has already been output and we cannot undo it.
271 if ( !sa[0] || ( sa[0] && sa[1] ) ) {
273 print_literal(ss,"("/*)*/);
274 print_qdescrlist(ss,sa);
275 print_literal(ss,/*(*/")");
276 return(print_whsp(ss));
278 return(print_qdescr(ss,*sa));
283 print_woid(safe_string *ss, char *s)
286 append_to_safe_string(ss,s);
287 return print_whsp(ss);
291 print_oidlist(safe_string *ss, char **sa)
295 for (sp=sa; *(sp+1); sp++) {
297 print_literal(ss,"$");
299 return(print_woid(ss,*sp));
303 print_oids(safe_string *ss, char **sa)
305 if ( sa[0] && sa[1] ) {
306 print_literal(ss,"("/*)*/);
307 print_oidlist(ss,sa);
309 return(print_literal(ss,/*(*/")"));
311 return(print_woid(ss,*sa));
316 print_noidlen(safe_string *ss, char *s, int l)
321 ret = print_numericoid(ss,s);
323 snprintf(buf, sizeof buf, "{%d}",l);
324 ret = print_literal(ss,buf);
330 print_ruleid(safe_string *ss, int rid)
333 snprintf(buf, sizeof buf, "%d", rid);
334 return print_literal(ss,buf);
338 print_ruleids(safe_string *ss, int n, int *rids)
343 print_ruleid(ss,rids[0]);
344 return print_whsp(ss);
346 print_literal(ss,"("/*)*/);
347 for( i=0; i<n; i++ ) {
349 print_ruleid(ss,rids[i]);
352 return print_literal(ss,/*(*/")");
358 print_extensions(safe_string *ss, LDAPSchemaExtensionItem **extensions)
360 LDAPSchemaExtensionItem **ext;
364 for ( ext = extensions; *ext != NULL; ext++ ) {
365 print_literal(ss, (*ext)->lsei_name);
367 /* Should be print_qdstrings */
368 print_qdescrs(ss, (*ext)->lsei_values);
377 ldap_syntax2str( LDAPSyntax * syn )
380 if (ldap_syntax2bv( syn, &bv ))
387 ldap_syntax2bv( LDAPSyntax * syn, struct berval *bv )
394 ss = new_safe_string(256);
398 print_literal(ss,"("/*)*/);
401 print_numericoid(ss, syn->syn_oid);
404 if ( syn->syn_desc ) {
405 print_literal(ss,"DESC");
406 print_qdstring(ss,syn->syn_desc);
411 print_extensions(ss, syn->syn_extensions);
413 print_literal(ss,/*(*/ ")");
415 bv->bv_val = safe_strdup(ss);
416 bv->bv_len = ss->pos;
417 safe_string_free(ss);
422 ldap_matchingrule2str( LDAPMatchingRule * mr )
425 if (ldap_matchingrule2bv( mr, &bv ))
432 ldap_matchingrule2bv( LDAPMatchingRule * mr, struct berval *bv )
439 ss = new_safe_string(256);
443 print_literal(ss,"(" /*)*/);
446 print_numericoid(ss, mr->mr_oid);
449 if ( mr->mr_names ) {
450 print_literal(ss,"NAME");
451 print_qdescrs(ss,mr->mr_names);
455 print_literal(ss,"DESC");
456 print_qdstring(ss,mr->mr_desc);
459 if ( mr->mr_obsolete ) {
460 print_literal(ss, "OBSOLETE");
464 if ( mr->mr_syntax_oid ) {
465 print_literal(ss,"SYNTAX");
467 print_literal(ss, mr->mr_syntax_oid);
473 print_extensions(ss, mr->mr_extensions);
475 print_literal(ss,/*(*/")");
477 bv->bv_val = safe_strdup(ss);
478 bv->bv_len = ss->pos;
479 safe_string_free(ss);
484 ldap_matchingruleuse2str( LDAPMatchingRuleUse * mru )
487 if (ldap_matchingruleuse2bv( mru, &bv ))
494 ldap_matchingruleuse2bv( LDAPMatchingRuleUse * mru, struct berval *bv )
501 ss = new_safe_string(256);
505 print_literal(ss,"(" /*)*/);
508 print_numericoid(ss, mru->mru_oid);
511 if ( mru->mru_names ) {
512 print_literal(ss,"NAME");
513 print_qdescrs(ss,mru->mru_names);
516 if ( mru->mru_desc ) {
517 print_literal(ss,"DESC");
518 print_qdstring(ss,mru->mru_desc);
521 if ( mru->mru_obsolete ) {
522 print_literal(ss, "OBSOLETE");
526 if ( mru->mru_applies_oids ) {
527 print_literal(ss,"APPLIES");
529 print_oids(ss, mru->mru_applies_oids);
535 print_extensions(ss, mru->mru_extensions);
537 print_literal(ss,/*(*/")");
539 bv->bv_val = safe_strdup(ss);
540 bv->bv_len = ss->pos;
541 safe_string_free(ss);
546 ldap_objectclass2str( LDAPObjectClass * oc )
549 if (ldap_objectclass2bv( oc, &bv ))
556 ldap_objectclass2bv( LDAPObjectClass * oc, struct berval *bv )
563 ss = new_safe_string(256);
567 print_literal(ss,"("/*)*/);
570 print_numericoid(ss, oc->oc_oid);
573 if ( oc->oc_names ) {
574 print_literal(ss,"NAME");
575 print_qdescrs(ss,oc->oc_names);
579 print_literal(ss,"DESC");
580 print_qdstring(ss,oc->oc_desc);
583 if ( oc->oc_obsolete ) {
584 print_literal(ss, "OBSOLETE");
588 if ( oc->oc_sup_oids ) {
589 print_literal(ss,"SUP");
591 print_oids(ss,oc->oc_sup_oids);
595 switch (oc->oc_kind) {
596 case LDAP_SCHEMA_ABSTRACT:
597 print_literal(ss,"ABSTRACT");
599 case LDAP_SCHEMA_STRUCTURAL:
600 print_literal(ss,"STRUCTURAL");
602 case LDAP_SCHEMA_AUXILIARY:
603 print_literal(ss,"AUXILIARY");
606 print_literal(ss,"KIND-UNKNOWN");
611 if ( oc->oc_at_oids_must ) {
612 print_literal(ss,"MUST");
614 print_oids(ss,oc->oc_at_oids_must);
618 if ( oc->oc_at_oids_may ) {
619 print_literal(ss,"MAY");
621 print_oids(ss,oc->oc_at_oids_may);
627 print_extensions(ss, oc->oc_extensions);
629 print_literal(ss, /*(*/")");
631 bv->bv_val = safe_strdup(ss);
632 bv->bv_len = ss->pos;
633 safe_string_free(ss);
638 ldap_contentrule2str( LDAPContentRule * cr )
641 if (ldap_contentrule2bv( cr, &bv ))
648 ldap_contentrule2bv( LDAPContentRule * cr, struct berval *bv )
655 ss = new_safe_string(256);
659 print_literal(ss,"("/*)*/);
662 print_numericoid(ss, cr->cr_oid);
665 if ( cr->cr_names ) {
666 print_literal(ss,"NAME");
667 print_qdescrs(ss,cr->cr_names);
671 print_literal(ss,"DESC");
672 print_qdstring(ss,cr->cr_desc);
675 if ( cr->cr_obsolete ) {
676 print_literal(ss, "OBSOLETE");
680 if ( cr->cr_oc_oids_aux ) {
681 print_literal(ss,"AUX");
683 print_oids(ss,cr->cr_oc_oids_aux);
687 if ( cr->cr_at_oids_must ) {
688 print_literal(ss,"MUST");
690 print_oids(ss,cr->cr_at_oids_must);
694 if ( cr->cr_at_oids_may ) {
695 print_literal(ss,"MAY");
697 print_oids(ss,cr->cr_at_oids_may);
701 if ( cr->cr_at_oids_not ) {
702 print_literal(ss,"NOT");
704 print_oids(ss,cr->cr_at_oids_not);
709 print_extensions(ss, cr->cr_extensions);
711 print_literal(ss, /*(*/")");
713 bv->bv_val = safe_strdup(ss);
714 bv->bv_len = ss->pos;
715 safe_string_free(ss);
720 ldap_structurerule2str( LDAPStructureRule * sr )
723 if (ldap_structurerule2bv( sr, &bv ))
730 ldap_structurerule2bv( LDAPStructureRule * sr, struct berval *bv )
737 ss = new_safe_string(256);
741 print_literal(ss,"("/*)*/);
744 print_ruleid(ss, sr->sr_ruleid);
747 if ( sr->sr_names ) {
748 print_literal(ss,"NAME");
749 print_qdescrs(ss,sr->sr_names);
753 print_literal(ss,"DESC");
754 print_qdstring(ss,sr->sr_desc);
757 if ( sr->sr_obsolete ) {
758 print_literal(ss, "OBSOLETE");
762 print_literal(ss,"FORM");
764 print_woid(ss,sr->sr_nameform);
767 if ( sr->sr_nsup_ruleids ) {
768 print_literal(ss,"SUP");
770 print_ruleids(ss,sr->sr_nsup_ruleids,sr->sr_sup_ruleids);
775 print_extensions(ss, sr->sr_extensions);
777 print_literal(ss, /*(*/")");
779 bv->bv_val = safe_strdup(ss);
780 bv->bv_len = ss->pos;
781 safe_string_free(ss);
787 ldap_nameform2str( LDAPNameForm * nf )
790 if (ldap_nameform2bv( nf, &bv ))
797 ldap_nameform2bv( LDAPNameForm * nf, struct berval *bv )
804 ss = new_safe_string(256);
808 print_literal(ss,"("/*)*/);
811 print_numericoid(ss, nf->nf_oid);
814 if ( nf->nf_names ) {
815 print_literal(ss,"NAME");
816 print_qdescrs(ss,nf->nf_names);
820 print_literal(ss,"DESC");
821 print_qdstring(ss,nf->nf_desc);
824 if ( nf->nf_obsolete ) {
825 print_literal(ss, "OBSOLETE");
829 print_literal(ss,"OC");
831 print_woid(ss,nf->nf_objectclass);
834 print_literal(ss,"MUST");
836 print_oids(ss,nf->nf_at_oids_must);
840 if ( nf->nf_at_oids_may ) {
841 print_literal(ss,"MAY");
843 print_oids(ss,nf->nf_at_oids_may);
848 print_extensions(ss, nf->nf_extensions);
850 print_literal(ss, /*(*/")");
852 bv->bv_val = safe_strdup(ss);
853 bv->bv_len = ss->pos;
854 safe_string_free(ss);
859 ldap_attributetype2str( LDAPAttributeType * at )
862 if (ldap_attributetype2bv( at, &bv ))
869 ldap_attributetype2bv( LDAPAttributeType * at, struct berval *bv )
876 ss = new_safe_string(256);
880 print_literal(ss,"("/*)*/);
883 print_numericoid(ss, at->at_oid);
886 if ( at->at_names ) {
887 print_literal(ss,"NAME");
888 print_qdescrs(ss,at->at_names);
892 print_literal(ss,"DESC");
893 print_qdstring(ss,at->at_desc);
896 if ( at->at_obsolete ) {
897 print_literal(ss, "OBSOLETE");
901 if ( at->at_sup_oid ) {
902 print_literal(ss,"SUP");
903 print_woid(ss,at->at_sup_oid);
906 if ( at->at_equality_oid ) {
907 print_literal(ss,"EQUALITY");
908 print_woid(ss,at->at_equality_oid);
911 if ( at->at_ordering_oid ) {
912 print_literal(ss,"ORDERING");
913 print_woid(ss,at->at_ordering_oid);
916 if ( at->at_substr_oid ) {
917 print_literal(ss,"SUBSTR");
918 print_woid(ss,at->at_substr_oid);
921 if ( at->at_syntax_oid ) {
922 print_literal(ss,"SYNTAX");
924 print_noidlen(ss,at->at_syntax_oid,at->at_syntax_len);
928 if ( at->at_single_value == LDAP_SCHEMA_YES ) {
929 print_literal(ss,"SINGLE-VALUE");
933 if ( at->at_collective == LDAP_SCHEMA_YES ) {
934 print_literal(ss,"COLLECTIVE");
938 if ( at->at_no_user_mod == LDAP_SCHEMA_YES ) {
939 print_literal(ss,"NO-USER-MODIFICATION");
943 if ( at->at_usage != LDAP_SCHEMA_USER_APPLICATIONS ) {
944 print_literal(ss,"USAGE");
946 switch (at->at_usage) {
947 case LDAP_SCHEMA_DIRECTORY_OPERATION:
948 print_literal(ss,"directoryOperation");
950 case LDAP_SCHEMA_DISTRIBUTED_OPERATION:
951 print_literal(ss,"distributedOperation");
953 case LDAP_SCHEMA_DSA_OPERATION:
954 print_literal(ss,"dSAOperation");
957 print_literal(ss,"UNKNOWN");
964 print_extensions(ss, at->at_extensions);
966 print_literal(ss,/*(*/")");
968 bv->bv_val = safe_strdup(ss);
969 bv->bv_len = ss->pos;
970 safe_string_free(ss);
975 * Now come the parsers. There is one parser for each entity type:
976 * objectclasses, attributetypes, etc.
978 * Each of them is written as a recursive-descent parser, except that
979 * none of them is really recursive. But the idea is kept: there
980 * is one routine per non-terminal that eithers gobbles lexical tokens
981 * or calls lower-level routines, etc.
983 * The scanner is implemented in the routine get_token. Actually,
984 * get_token is more than a scanner and will return tokens that are
985 * in fact non-terminals in the grammar. So you can see the whole
986 * approach as the combination of a low-level bottom-up recognizer
987 * combined with a scanner and a number of top-down parsers. Or just
988 * consider that the real grammars recognized by the parsers are not
989 * those of the standards. As a matter of fact, our parsers are more
990 * liberal than the spec when there is no ambiguity.
992 * The difference is pretty academic (modulo bugs or incorrect
993 * interpretation of the specs).
1006 TK_QDESCR = TK_QDSTRING
1010 get_token( const char ** sp, char ** token_val )
1024 kind = TK_LEFTPAREN;
1028 kind = TK_RIGHTPAREN;
1039 while ( **sp != '\'' && **sp != '\0' )
1041 if ( **sp == '\'' ) {
1043 res = LDAP_MALLOC(q-p+1);
1053 kind = TK_NOENDQUOTE;
1059 while ( !LDAP_SPACE(**sp) &&
1064 /* for suggested minimum upper bound on the number
1065 * of characters (RFC 4517) */
1070 res = LDAP_MALLOC(q-p+1);
1079 /* kind = TK_UNEXPCHAR; */
1086 /* Gobble optional whitespace */
1088 parse_whsp(const char **sp)
1090 while (LDAP_SPACE(**sp))
1095 * General note for all parsers: to guarantee the algorithm halts they
1096 * must always advance the pointer even when an error is found. For
1097 * this one is not that important since an error here is fatal at the
1098 * upper layers, but it is a simple strategy that will not get in
1102 /* Parse a sequence of dot-separated decimal strings */
1104 ldap_int_parse_numericoid(const char **sp, int *code, const int flags)
1107 const char * start = *sp;
1111 /* Netscape puts the SYNTAX value in quotes (incorrectly) */
1112 if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && **sp == '\'' ) {
1117 /* Each iteration of this loop gets one decimal string */
1119 if ( !LDAP_DIGIT(**sp) ) {
1121 * Initial char is not a digit or char after dot is
1124 *code = LDAP_SCHERR_NODIGIT;
1128 while ( LDAP_DIGIT(**sp) )
1132 /* Otherwise, gobble the dot and loop again */
1135 /* Now *sp points at the char past the numericoid. Perfect. */
1137 if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && quoted ) {
1138 if ( **sp == '\'' ) {
1141 *code = LDAP_SCHERR_UNEXPTOKEN;
1145 if (flags & LDAP_SCHEMA_SKIP) {
1146 res = (char *)start;
1148 res = LDAP_MALLOC(len+1);
1150 *code = LDAP_SCHERR_OUTOFMEM;
1153 strncpy(res,start,len);
1159 /* Parse a sequence of dot-separated decimal strings */
1161 ldap_int_parse_ruleid(const char **sp, int *code, const int flags, int *ruleid)
1165 if ( !LDAP_DIGIT(**sp) ) {
1166 *code = LDAP_SCHERR_NODIGIT;
1169 *ruleid = (**sp) - '0';
1172 while ( LDAP_DIGIT(**sp) ) {
1174 *ruleid += (**sp) - '0';
1181 /* Parse a qdescr or a list of them enclosed in () */
1183 parse_qdescrs(const char **sp, int *code)
1193 kind = get_token(sp,&sval);
1194 if ( kind == TK_LEFTPAREN ) {
1195 /* Let's presume there will be at least 2 entries */
1197 res = LDAP_CALLOC(3,sizeof(char *));
1199 *code = LDAP_SCHERR_OUTOFMEM;
1205 kind = get_token(sp,&sval);
1206 if ( kind == TK_RIGHTPAREN )
1208 if ( kind == TK_QDESCR ) {
1209 if ( pos == size-2 ) {
1211 res1 = LDAP_REALLOC(res,size*sizeof(char *));
1215 *code = LDAP_SCHERR_OUTOFMEM;
1226 *code = LDAP_SCHERR_UNEXPTOKEN;
1232 } else if ( kind == TK_QDESCR ) {
1233 res = LDAP_CALLOC(2,sizeof(char *));
1235 *code = LDAP_SCHERR_OUTOFMEM;
1244 *code = LDAP_SCHERR_BADNAME;
1251 parse_woid(const char **sp, int *code)
1257 kind = get_token(sp, &sval);
1258 if ( kind != TK_BAREWORD ) {
1260 *code = LDAP_SCHERR_UNEXPTOKEN;
1267 /* Parse a noidlen */
1269 parse_noidlen(const char **sp, int *code, int *len, int flags)
1272 const char *savepos;
1274 int allow_quoted = ( flags & LDAP_SCHEMA_ALLOW_QUOTED );
1275 int allow_oidmacro = ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO );
1278 /* Netscape puts the SYNTAX value in quotes (incorrectly) */
1279 if ( allow_quoted && **sp == '\'' ) {
1284 sval = ldap_int_parse_numericoid(sp, code, 0);
1288 && *code == LDAP_SCHERR_NODIGIT )
1290 if ( get_token(sp, &sval) != TK_BAREWORD ) {
1291 if ( sval != NULL ) {
1300 if ( **sp == '{' /*}*/ ) {
1303 while ( LDAP_DIGIT(**sp) )
1305 if ( **sp != /*{*/ '}' ) {
1306 *code = LDAP_SCHERR_UNEXPTOKEN;
1312 if ( allow_quoted && quoted ) {
1313 if ( **sp == '\'' ) {
1316 *code = LDAP_SCHERR_UNEXPTOKEN;
1325 * Next routine will accept a qdstring in place of an oid if
1326 * allow_quoted is set. This is necessary to interoperate with
1327 * Netscape Directory server that will improperly quote each oid (at
1328 * least those of the descr kind) in the SUP clause.
1331 /* Parse a woid or a $-separated list of them enclosed in () */
1333 parse_oids(const char **sp, int *code, const int allow_quoted)
1343 * Strictly speaking, doing this here accepts whsp before the
1344 * ( at the begining of an oidlist, but this is harmless. Also,
1345 * we are very liberal in what we accept as an OID. Maybe
1349 kind = get_token(sp,&sval);
1350 if ( kind == TK_LEFTPAREN ) {
1351 /* Let's presume there will be at least 2 entries */
1353 res = LDAP_CALLOC(3,sizeof(char *));
1355 *code = LDAP_SCHERR_OUTOFMEM;
1360 kind = get_token(sp,&sval);
1361 if ( kind == TK_BAREWORD ||
1362 ( allow_quoted && kind == TK_QDSTRING ) ) {
1365 } else if ( kind == TK_RIGHTPAREN ) {
1366 /* FIXME: be liberal in what we accept... */
1371 *code = LDAP_SCHERR_UNEXPTOKEN;
1378 kind = get_token(sp,&sval);
1379 if ( kind == TK_RIGHTPAREN )
1381 if ( kind == TK_DOLLAR ) {
1383 kind = get_token(sp,&sval);
1384 if ( kind == TK_BAREWORD ||
1386 kind == TK_QDSTRING ) ) {
1387 if ( pos == size-2 ) {
1389 res1 = LDAP_REALLOC(res,size*sizeof(char *));
1393 *code = LDAP_SCHERR_OUTOFMEM;
1401 *code = LDAP_SCHERR_UNEXPTOKEN;
1408 *code = LDAP_SCHERR_UNEXPTOKEN;
1416 } else if ( kind == TK_BAREWORD ||
1417 ( allow_quoted && kind == TK_QDSTRING ) ) {
1418 res = LDAP_CALLOC(2,sizeof(char *));
1421 *code = LDAP_SCHERR_OUTOFMEM;
1430 *code = LDAP_SCHERR_BADNAME;
1436 add_extension(LDAPSchemaExtensionItem ***extensions,
1437 char * name, char ** values)
1440 LDAPSchemaExtensionItem **tmp, *ext;
1442 ext = LDAP_CALLOC(1, sizeof(LDAPSchemaExtensionItem));
1445 ext->lsei_name = name;
1446 ext->lsei_values = values;
1448 if ( !*extensions ) {
1450 LDAP_CALLOC(2, sizeof(LDAPSchemaExtensionItem *));
1451 if ( !*extensions ) {
1457 for ( n=0; (*extensions)[n] != NULL; n++ )
1459 tmp = LDAP_REALLOC(*extensions,
1460 (n+2)*sizeof(LDAPSchemaExtensionItem *));
1467 (*extensions)[n] = ext;
1468 (*extensions)[n+1] = NULL;
1473 free_extensions(LDAPSchemaExtensionItem **extensions)
1475 LDAPSchemaExtensionItem **ext;
1478 for ( ext = extensions; *ext != NULL; ext++ ) {
1479 LDAP_FREE((*ext)->lsei_name);
1480 LDAP_VFREE((*ext)->lsei_values);
1483 LDAP_FREE(extensions);
1488 ldap_syntax_free( LDAPSyntax * syn )
1491 LDAP_FREE(syn->syn_oid);
1492 if (syn->syn_names) LDAP_VFREE(syn->syn_names);
1493 if (syn->syn_desc) LDAP_FREE(syn->syn_desc);
1494 free_extensions(syn->syn_extensions);
1499 ldap_str2syntax( LDAP_CONST char * s,
1501 LDAP_CONST char ** errp,
1502 LDAP_CONST unsigned flags )
1505 const char * ss = s;
1513 *code = LDAP_SCHERR_EMPTY;
1519 syn = LDAP_CALLOC(1,sizeof(LDAPSyntax));
1522 *code = LDAP_SCHERR_OUTOFMEM;
1526 kind = get_token(&ss,&sval);
1527 if ( kind != TK_LEFTPAREN ) {
1529 *code = LDAP_SCHERR_NOLEFTPAREN;
1530 ldap_syntax_free(syn);
1535 syn->syn_oid = ldap_int_parse_numericoid(&ss,code,0);
1536 if ( !syn->syn_oid ) {
1538 ldap_syntax_free(syn);
1544 * Beyond this point we will be liberal and accept the items
1548 kind = get_token(&ss,&sval);
1551 *code = LDAP_SCHERR_NORIGHTPAREN;
1553 ldap_syntax_free(syn);
1558 if ( !strcasecmp(sval,"NAME") ) {
1561 *code = LDAP_SCHERR_DUPOPT;
1563 ldap_syntax_free(syn);
1567 syn->syn_names = parse_qdescrs(&ss,code);
1568 if ( !syn->syn_names ) {
1569 if ( *code != LDAP_SCHERR_OUTOFMEM )
1570 *code = LDAP_SCHERR_BADNAME;
1572 ldap_syntax_free(syn);
1575 } else if ( !strcasecmp(sval,"DESC") ) {
1578 *code = LDAP_SCHERR_DUPOPT;
1580 ldap_syntax_free(syn);
1585 kind = get_token(&ss,&sval);
1586 if ( kind != TK_QDSTRING ) {
1587 *code = LDAP_SCHERR_UNEXPTOKEN;
1590 ldap_syntax_free(syn);
1593 syn->syn_desc = sval;
1595 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
1596 /* Should be parse_qdstrings */
1597 ext_vals = parse_qdescrs(&ss, code);
1600 ldap_syntax_free(syn);
1603 if ( add_extension(&syn->syn_extensions,
1605 *code = LDAP_SCHERR_OUTOFMEM;
1608 ldap_syntax_free(syn);
1612 *code = LDAP_SCHERR_UNEXPTOKEN;
1615 ldap_syntax_free(syn);
1620 *code = LDAP_SCHERR_UNEXPTOKEN;
1623 ldap_syntax_free(syn);
1630 ldap_matchingrule_free( LDAPMatchingRule * mr )
1633 LDAP_FREE(mr->mr_oid);
1634 if (mr->mr_names) LDAP_VFREE(mr->mr_names);
1635 if (mr->mr_desc) LDAP_FREE(mr->mr_desc);
1636 if (mr->mr_syntax_oid) LDAP_FREE(mr->mr_syntax_oid);
1637 free_extensions(mr->mr_extensions);
1642 ldap_str2matchingrule( LDAP_CONST char * s,
1644 LDAP_CONST char ** errp,
1645 LDAP_CONST unsigned flags )
1648 const char * ss = s;
1652 int seen_obsolete = 0;
1653 int seen_syntax = 0;
1654 LDAPMatchingRule * mr;
1656 const char * savepos;
1659 *code = LDAP_SCHERR_EMPTY;
1665 mr = LDAP_CALLOC(1,sizeof(LDAPMatchingRule));
1668 *code = LDAP_SCHERR_OUTOFMEM;
1672 kind = get_token(&ss,&sval);
1673 if ( kind != TK_LEFTPAREN ) {
1674 *code = LDAP_SCHERR_NOLEFTPAREN;
1676 ldap_matchingrule_free(mr);
1682 mr->mr_oid = ldap_int_parse_numericoid(&ss,code,flags);
1683 if ( !mr->mr_oid ) {
1684 if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) {
1687 kind = get_token(&ss,&sval);
1688 if ( kind == TK_BAREWORD ) {
1689 if ( !strcasecmp(sval, "NAME") ||
1690 !strcasecmp(sval, "DESC") ||
1691 !strcasecmp(sval, "OBSOLETE") ||
1692 !strcasecmp(sval, "SYNTAX") ||
1693 !strncasecmp(sval, "X-", 2) ) {
1694 /* Missing OID, backtrack */
1697 /* Non-numerical OID, ignore */
1703 ldap_matchingrule_free(mr);
1710 * Beyond this point we will be liberal and accept the items
1714 kind = get_token(&ss,&sval);
1717 *code = LDAP_SCHERR_NORIGHTPAREN;
1719 ldap_matchingrule_free(mr);
1722 if( !seen_syntax ) {
1723 *code = LDAP_SCHERR_MISSING;
1724 ldap_matchingrule_free(mr);
1729 if ( !strcasecmp(sval,"NAME") ) {
1732 *code = LDAP_SCHERR_DUPOPT;
1734 ldap_matchingrule_free(mr);
1738 mr->mr_names = parse_qdescrs(&ss,code);
1739 if ( !mr->mr_names ) {
1740 if ( *code != LDAP_SCHERR_OUTOFMEM )
1741 *code = LDAP_SCHERR_BADNAME;
1743 ldap_matchingrule_free(mr);
1746 } else if ( !strcasecmp(sval,"DESC") ) {
1749 *code = LDAP_SCHERR_DUPOPT;
1751 ldap_matchingrule_free(mr);
1756 kind = get_token(&ss,&sval);
1757 if ( kind != TK_QDSTRING ) {
1758 *code = LDAP_SCHERR_UNEXPTOKEN;
1761 ldap_matchingrule_free(mr);
1766 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
1768 if ( seen_obsolete ) {
1769 *code = LDAP_SCHERR_DUPOPT;
1771 ldap_matchingrule_free(mr);
1775 mr->mr_obsolete = LDAP_SCHEMA_YES;
1777 } else if ( !strcasecmp(sval,"SYNTAX") ) {
1779 if ( seen_syntax ) {
1780 *code = LDAP_SCHERR_DUPOPT;
1782 ldap_matchingrule_free(mr);
1788 ldap_int_parse_numericoid(&ss,code,flags);
1789 if ( !mr->mr_syntax_oid ) {
1791 ldap_matchingrule_free(mr);
1795 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
1796 /* Should be parse_qdstrings */
1797 ext_vals = parse_qdescrs(&ss, code);
1800 ldap_matchingrule_free(mr);
1803 if ( add_extension(&mr->mr_extensions,
1805 *code = LDAP_SCHERR_OUTOFMEM;
1808 ldap_matchingrule_free(mr);
1812 *code = LDAP_SCHERR_UNEXPTOKEN;
1815 ldap_matchingrule_free(mr);
1820 *code = LDAP_SCHERR_UNEXPTOKEN;
1823 ldap_matchingrule_free(mr);
1830 ldap_matchingruleuse_free( LDAPMatchingRuleUse * mru )
1833 LDAP_FREE(mru->mru_oid);
1834 if (mru->mru_names) LDAP_VFREE(mru->mru_names);
1835 if (mru->mru_desc) LDAP_FREE(mru->mru_desc);
1836 if (mru->mru_applies_oids) LDAP_VFREE(mru->mru_applies_oids);
1837 free_extensions(mru->mru_extensions);
1841 LDAPMatchingRuleUse *
1842 ldap_str2matchingruleuse( LDAP_CONST char * s,
1844 LDAP_CONST char ** errp,
1845 LDAP_CONST unsigned flags )
1848 const char * ss = s;
1852 int seen_obsolete = 0;
1853 int seen_applies = 0;
1854 LDAPMatchingRuleUse * mru;
1856 const char * savepos;
1859 *code = LDAP_SCHERR_EMPTY;
1865 mru = LDAP_CALLOC(1,sizeof(LDAPMatchingRuleUse));
1868 *code = LDAP_SCHERR_OUTOFMEM;
1872 kind = get_token(&ss,&sval);
1873 if ( kind != TK_LEFTPAREN ) {
1874 *code = LDAP_SCHERR_NOLEFTPAREN;
1876 ldap_matchingruleuse_free(mru);
1882 mru->mru_oid = ldap_int_parse_numericoid(&ss,code,flags);
1883 if ( !mru->mru_oid ) {
1884 if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) {
1887 kind = get_token(&ss,&sval);
1888 if ( kind == TK_BAREWORD ) {
1889 if ( !strcasecmp(sval, "NAME") ||
1890 !strcasecmp(sval, "DESC") ||
1891 !strcasecmp(sval, "OBSOLETE") ||
1892 !strcasecmp(sval, "APPLIES") ||
1893 !strncasecmp(sval, "X-", 2) ) {
1894 /* Missing OID, backtrack */
1897 /* Non-numerical OID, ignore */
1903 ldap_matchingruleuse_free(mru);
1910 * Beyond this point we will be liberal and accept the items
1914 kind = get_token(&ss,&sval);
1917 *code = LDAP_SCHERR_NORIGHTPAREN;
1919 ldap_matchingruleuse_free(mru);
1922 if( !seen_applies ) {
1923 *code = LDAP_SCHERR_MISSING;
1924 ldap_matchingruleuse_free(mru);
1929 if ( !strcasecmp(sval,"NAME") ) {
1932 *code = LDAP_SCHERR_DUPOPT;
1934 ldap_matchingruleuse_free(mru);
1938 mru->mru_names = parse_qdescrs(&ss,code);
1939 if ( !mru->mru_names ) {
1940 if ( *code != LDAP_SCHERR_OUTOFMEM )
1941 *code = LDAP_SCHERR_BADNAME;
1943 ldap_matchingruleuse_free(mru);
1946 } else if ( !strcasecmp(sval,"DESC") ) {
1949 *code = LDAP_SCHERR_DUPOPT;
1951 ldap_matchingruleuse_free(mru);
1956 kind = get_token(&ss,&sval);
1957 if ( kind != TK_QDSTRING ) {
1958 *code = LDAP_SCHERR_UNEXPTOKEN;
1961 ldap_matchingruleuse_free(mru);
1964 mru->mru_desc = sval;
1966 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
1968 if ( seen_obsolete ) {
1969 *code = LDAP_SCHERR_DUPOPT;
1971 ldap_matchingruleuse_free(mru);
1975 mru->mru_obsolete = LDAP_SCHEMA_YES;
1977 } else if ( !strcasecmp(sval,"APPLIES") ) {
1979 if ( seen_applies ) {
1980 *code = LDAP_SCHERR_DUPOPT;
1982 ldap_matchingruleuse_free(mru);
1986 mru->mru_applies_oids = parse_oids(&ss,
1989 if ( !mru->mru_applies_oids && *code != LDAP_SUCCESS ) {
1991 ldap_matchingruleuse_free(mru);
1994 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
1995 /* Should be parse_qdstrings */
1996 ext_vals = parse_qdescrs(&ss, code);
1999 ldap_matchingruleuse_free(mru);
2002 if ( add_extension(&mru->mru_extensions,
2004 *code = LDAP_SCHERR_OUTOFMEM;
2007 ldap_matchingruleuse_free(mru);
2011 *code = LDAP_SCHERR_UNEXPTOKEN;
2014 ldap_matchingruleuse_free(mru);
2019 *code = LDAP_SCHERR_UNEXPTOKEN;
2022 ldap_matchingruleuse_free(mru);
2029 ldap_attributetype_free(LDAPAttributeType * at)
2032 LDAP_FREE(at->at_oid);
2033 if (at->at_names) LDAP_VFREE(at->at_names);
2034 if (at->at_desc) LDAP_FREE(at->at_desc);
2035 if (at->at_sup_oid) LDAP_FREE(at->at_sup_oid);
2036 if (at->at_equality_oid) LDAP_FREE(at->at_equality_oid);
2037 if (at->at_ordering_oid) LDAP_FREE(at->at_ordering_oid);
2038 if (at->at_substr_oid) LDAP_FREE(at->at_substr_oid);
2039 if (at->at_syntax_oid) LDAP_FREE(at->at_syntax_oid);
2040 free_extensions(at->at_extensions);
2045 ldap_str2attributetype( LDAP_CONST char * s,
2047 LDAP_CONST char ** errp,
2048 LDAP_CONST unsigned flags )
2051 const char * ss = s;
2055 int seen_obsolete = 0;
2057 int seen_equality = 0;
2058 int seen_ordering = 0;
2059 int seen_substr = 0;
2060 int seen_syntax = 0;
2062 LDAPAttributeType * at;
2064 const char * savepos;
2067 *code = LDAP_SCHERR_EMPTY;
2073 at = LDAP_CALLOC(1,sizeof(LDAPAttributeType));
2076 *code = LDAP_SCHERR_OUTOFMEM;
2080 kind = get_token(&ss,&sval);
2081 if ( kind != TK_LEFTPAREN ) {
2082 *code = LDAP_SCHERR_NOLEFTPAREN;
2084 ldap_attributetype_free(at);
2089 * Definitions MUST begin with an OID in the numericoid format.
2090 * However, this routine is used by clients to parse the response
2091 * from servers and very well known servers will provide an OID
2092 * in the wrong format or even no OID at all. We do our best to
2093 * extract info from those servers.
2097 at->at_oid = ldap_int_parse_numericoid(&ss,code,0);
2098 if ( !at->at_oid ) {
2099 if ( ( flags & ( LDAP_SCHEMA_ALLOW_NO_OID
2100 | LDAP_SCHEMA_ALLOW_OID_MACRO ) )
2101 && (ss == savepos) )
2105 kind = get_token(&ss,&sval);
2106 if ( kind == TK_BAREWORD ) {
2107 if ( !strcasecmp(sval, "NAME") ||
2108 !strcasecmp(sval, "DESC") ||
2109 !strcasecmp(sval, "OBSOLETE") ||
2110 !strcasecmp(sval, "SUP") ||
2111 !strcasecmp(sval, "EQUALITY") ||
2112 !strcasecmp(sval, "ORDERING") ||
2113 !strcasecmp(sval, "SUBSTR") ||
2114 !strcasecmp(sval, "SYNTAX") ||
2115 !strcasecmp(sval, "SINGLE-VALUE") ||
2116 !strcasecmp(sval, "COLLECTIVE") ||
2117 !strcasecmp(sval, "NO-USER-MODIFICATION") ||
2118 !strcasecmp(sval, "USAGE") ||
2119 !strncasecmp(sval, "X-", 2) )
2121 /* Missing OID, backtrack */
2124 & LDAP_SCHEMA_ALLOW_OID_MACRO)
2126 /* Non-numerical OID ... */
2127 int len = ss-savepos;
2128 at->at_oid = LDAP_MALLOC(len+1);
2129 strncpy(at->at_oid, savepos, len);
2130 at->at_oid[len] = 0;
2136 ldap_attributetype_free(at);
2143 * Beyond this point we will be liberal and accept the items
2147 kind = get_token(&ss,&sval);
2150 *code = LDAP_SCHERR_NORIGHTPAREN;
2152 ldap_attributetype_free(at);
2157 if ( !strcasecmp(sval,"NAME") ) {
2160 *code = LDAP_SCHERR_DUPOPT;
2162 ldap_attributetype_free(at);
2166 at->at_names = parse_qdescrs(&ss,code);
2167 if ( !at->at_names ) {
2168 if ( *code != LDAP_SCHERR_OUTOFMEM )
2169 *code = LDAP_SCHERR_BADNAME;
2171 ldap_attributetype_free(at);
2174 } else if ( !strcasecmp(sval,"DESC") ) {
2177 *code = LDAP_SCHERR_DUPOPT;
2179 ldap_attributetype_free(at);
2184 kind = get_token(&ss,&sval);
2185 if ( kind != TK_QDSTRING ) {
2186 *code = LDAP_SCHERR_UNEXPTOKEN;
2189 ldap_attributetype_free(at);
2194 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
2196 if ( seen_obsolete ) {
2197 *code = LDAP_SCHERR_DUPOPT;
2199 ldap_attributetype_free(at);
2203 at->at_obsolete = LDAP_SCHEMA_YES;
2205 } else if ( !strcasecmp(sval,"SUP") ) {
2208 *code = LDAP_SCHERR_DUPOPT;
2210 ldap_attributetype_free(at);
2214 at->at_sup_oid = parse_woid(&ss,code);
2215 if ( !at->at_sup_oid ) {
2217 ldap_attributetype_free(at);
2220 } else if ( !strcasecmp(sval,"EQUALITY") ) {
2222 if ( seen_equality ) {
2223 *code = LDAP_SCHERR_DUPOPT;
2225 ldap_attributetype_free(at);
2229 at->at_equality_oid = parse_woid(&ss,code);
2230 if ( !at->at_equality_oid ) {
2232 ldap_attributetype_free(at);
2235 } else if ( !strcasecmp(sval,"ORDERING") ) {
2237 if ( seen_ordering ) {
2238 *code = LDAP_SCHERR_DUPOPT;
2240 ldap_attributetype_free(at);
2244 at->at_ordering_oid = parse_woid(&ss,code);
2245 if ( !at->at_ordering_oid ) {
2247 ldap_attributetype_free(at);
2250 } else if ( !strcasecmp(sval,"SUBSTR") ) {
2252 if ( seen_substr ) {
2253 *code = LDAP_SCHERR_DUPOPT;
2255 ldap_attributetype_free(at);
2259 at->at_substr_oid = parse_woid(&ss,code);
2260 if ( !at->at_substr_oid ) {
2262 ldap_attributetype_free(at);
2265 } else if ( !strcasecmp(sval,"SYNTAX") ) {
2267 if ( seen_syntax ) {
2268 *code = LDAP_SCHERR_DUPOPT;
2270 ldap_attributetype_free(at);
2281 if ( !at->at_syntax_oid ) {
2282 if ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2283 kind = get_token(&ss,&sval);
2284 if (kind == TK_BAREWORD)
2286 char *sp = strchr(sval, '{');
2287 at->at_syntax_oid = sval;
2291 at->at_syntax_len = atoi(sp);
2292 while ( LDAP_DIGIT(*sp) )
2295 *code = LDAP_SCHERR_UNEXPTOKEN;
2297 ldap_attributetype_free(at);
2304 ldap_attributetype_free(at);
2309 } else if ( !strcasecmp(sval,"SINGLE-VALUE") ) {
2311 if ( at->at_single_value ) {
2312 *code = LDAP_SCHERR_DUPOPT;
2314 ldap_attributetype_free(at);
2317 at->at_single_value = LDAP_SCHEMA_YES;
2319 } else if ( !strcasecmp(sval,"COLLECTIVE") ) {
2321 if ( at->at_collective ) {
2322 *code = LDAP_SCHERR_DUPOPT;
2324 ldap_attributetype_free(at);
2327 at->at_collective = LDAP_SCHEMA_YES;
2329 } else if ( !strcasecmp(sval,"NO-USER-MODIFICATION") ) {
2331 if ( at->at_no_user_mod ) {
2332 *code = LDAP_SCHERR_DUPOPT;
2334 ldap_attributetype_free(at);
2337 at->at_no_user_mod = LDAP_SCHEMA_YES;
2339 } else if ( !strcasecmp(sval,"USAGE") ) {
2342 *code = LDAP_SCHERR_DUPOPT;
2344 ldap_attributetype_free(at);
2349 kind = get_token(&ss,&sval);
2350 if ( kind != TK_BAREWORD ) {
2351 *code = LDAP_SCHERR_UNEXPTOKEN;
2354 ldap_attributetype_free(at);
2357 if ( !strcasecmp(sval,"userApplications") )
2359 LDAP_SCHEMA_USER_APPLICATIONS;
2360 else if ( !strcasecmp(sval,"directoryOperation") )
2362 LDAP_SCHEMA_DIRECTORY_OPERATION;
2363 else if ( !strcasecmp(sval,"distributedOperation") )
2365 LDAP_SCHEMA_DISTRIBUTED_OPERATION;
2366 else if ( !strcasecmp(sval,"dSAOperation") )
2368 LDAP_SCHEMA_DSA_OPERATION;
2370 *code = LDAP_SCHERR_UNEXPTOKEN;
2373 ldap_attributetype_free(at);
2378 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
2379 /* Should be parse_qdstrings */
2380 ext_vals = parse_qdescrs(&ss, code);
2383 ldap_attributetype_free(at);
2386 if ( add_extension(&at->at_extensions,
2388 *code = LDAP_SCHERR_OUTOFMEM;
2391 ldap_attributetype_free(at);
2395 *code = LDAP_SCHERR_UNEXPTOKEN;
2398 ldap_attributetype_free(at);
2403 *code = LDAP_SCHERR_UNEXPTOKEN;
2406 ldap_attributetype_free(at);
2413 ldap_objectclass_free(LDAPObjectClass * oc)
2416 LDAP_FREE(oc->oc_oid);
2417 if (oc->oc_names) LDAP_VFREE(oc->oc_names);
2418 if (oc->oc_desc) LDAP_FREE(oc->oc_desc);
2419 if (oc->oc_sup_oids) LDAP_VFREE(oc->oc_sup_oids);
2420 if (oc->oc_at_oids_must) LDAP_VFREE(oc->oc_at_oids_must);
2421 if (oc->oc_at_oids_may) LDAP_VFREE(oc->oc_at_oids_may);
2422 free_extensions(oc->oc_extensions);
2427 ldap_str2objectclass( LDAP_CONST char * s,
2429 LDAP_CONST char ** errp,
2430 LDAP_CONST unsigned flags )
2433 const char * ss = s;
2437 int seen_obsolete = 0;
2442 LDAPObjectClass * oc;
2444 const char * savepos;
2447 *code = LDAP_SCHERR_EMPTY;
2453 oc = LDAP_CALLOC(1,sizeof(LDAPObjectClass));
2456 *code = LDAP_SCHERR_OUTOFMEM;
2459 oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
2461 kind = get_token(&ss,&sval);
2462 if ( kind != TK_LEFTPAREN ) {
2463 *code = LDAP_SCHERR_NOLEFTPAREN;
2465 ldap_objectclass_free(oc);
2470 * Definitions MUST begin with an OID in the numericoid format.
2471 * However, this routine is used by clients to parse the response
2472 * from servers and very well known servers will provide an OID
2473 * in the wrong format or even no OID at all. We do our best to
2474 * extract info from those servers.
2478 oc->oc_oid = ldap_int_parse_numericoid(&ss,code,0);
2479 if ( !oc->oc_oid ) {
2480 if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) {
2483 kind = get_token(&ss,&sval);
2484 if ( kind == TK_BAREWORD ) {
2485 if ( !strcasecmp(sval, "NAME") ||
2486 !strcasecmp(sval, "DESC") ||
2487 !strcasecmp(sval, "OBSOLETE") ||
2488 !strcasecmp(sval, "SUP") ||
2489 !strcasecmp(sval, "ABSTRACT") ||
2490 !strcasecmp(sval, "STRUCTURAL") ||
2491 !strcasecmp(sval, "AUXILIARY") ||
2492 !strcasecmp(sval, "MUST") ||
2493 !strcasecmp(sval, "MAY") ||
2494 !strncasecmp(sval, "X-", 2) ) {
2495 /* Missing OID, backtrack */
2498 LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2499 /* Non-numerical OID, ignore */
2500 int len = ss-savepos;
2501 oc->oc_oid = LDAP_MALLOC(len+1);
2502 strncpy(oc->oc_oid, savepos, len);
2503 oc->oc_oid[len] = 0;
2510 ldap_objectclass_free(oc);
2517 * Beyond this point we will be liberal an accept the items
2521 kind = get_token(&ss,&sval);
2524 *code = LDAP_SCHERR_NORIGHTPAREN;
2526 ldap_objectclass_free(oc);
2531 if ( !strcasecmp(sval,"NAME") ) {
2534 *code = LDAP_SCHERR_DUPOPT;
2536 ldap_objectclass_free(oc);
2540 oc->oc_names = parse_qdescrs(&ss,code);
2541 if ( !oc->oc_names ) {
2542 if ( *code != LDAP_SCHERR_OUTOFMEM )
2543 *code = LDAP_SCHERR_BADNAME;
2545 ldap_objectclass_free(oc);
2548 } else if ( !strcasecmp(sval,"DESC") ) {
2551 *code = LDAP_SCHERR_DUPOPT;
2553 ldap_objectclass_free(oc);
2558 kind = get_token(&ss,&sval);
2559 if ( kind != TK_QDSTRING ) {
2560 *code = LDAP_SCHERR_UNEXPTOKEN;
2563 ldap_objectclass_free(oc);
2568 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
2570 if ( seen_obsolete ) {
2571 *code = LDAP_SCHERR_DUPOPT;
2573 ldap_objectclass_free(oc);
2577 oc->oc_obsolete = LDAP_SCHEMA_YES;
2579 } else if ( !strcasecmp(sval,"SUP") ) {
2582 *code = LDAP_SCHERR_DUPOPT;
2584 ldap_objectclass_free(oc);
2588 oc->oc_sup_oids = parse_oids(&ss,
2591 if ( !oc->oc_sup_oids && *code != LDAP_SUCCESS ) {
2593 ldap_objectclass_free(oc);
2597 } else if ( !strcasecmp(sval,"ABSTRACT") ) {
2600 *code = LDAP_SCHERR_DUPOPT;
2602 ldap_objectclass_free(oc);
2606 oc->oc_kind = LDAP_SCHEMA_ABSTRACT;
2608 } else if ( !strcasecmp(sval,"STRUCTURAL") ) {
2611 *code = LDAP_SCHERR_DUPOPT;
2613 ldap_objectclass_free(oc);
2617 oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
2619 } else if ( !strcasecmp(sval,"AUXILIARY") ) {
2622 *code = LDAP_SCHERR_DUPOPT;
2624 ldap_objectclass_free(oc);
2628 oc->oc_kind = LDAP_SCHEMA_AUXILIARY;
2630 } else if ( !strcasecmp(sval,"MUST") ) {
2633 *code = LDAP_SCHERR_DUPOPT;
2635 ldap_objectclass_free(oc);
2639 oc->oc_at_oids_must = parse_oids(&ss,code,0);
2640 if ( !oc->oc_at_oids_must && *code != LDAP_SUCCESS ) {
2642 ldap_objectclass_free(oc);
2647 } else if ( !strcasecmp(sval,"MAY") ) {
2650 *code = LDAP_SCHERR_DUPOPT;
2652 ldap_objectclass_free(oc);
2656 oc->oc_at_oids_may = parse_oids(&ss,code,0);
2657 if ( !oc->oc_at_oids_may && *code != LDAP_SUCCESS ) {
2659 ldap_objectclass_free(oc);
2664 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
2665 /* Should be parse_qdstrings */
2666 ext_vals = parse_qdescrs(&ss, code);
2670 ldap_objectclass_free(oc);
2673 if ( add_extension(&oc->oc_extensions,
2675 *code = LDAP_SCHERR_OUTOFMEM;
2678 ldap_objectclass_free(oc);
2682 *code = LDAP_SCHERR_UNEXPTOKEN;
2685 ldap_objectclass_free(oc);
2690 *code = LDAP_SCHERR_UNEXPTOKEN;
2693 ldap_objectclass_free(oc);
2700 ldap_contentrule_free(LDAPContentRule * cr)
2703 LDAP_FREE(cr->cr_oid);
2704 if (cr->cr_names) LDAP_VFREE(cr->cr_names);
2705 if (cr->cr_desc) LDAP_FREE(cr->cr_desc);
2706 if (cr->cr_oc_oids_aux) LDAP_VFREE(cr->cr_oc_oids_aux);
2707 if (cr->cr_at_oids_must) LDAP_VFREE(cr->cr_at_oids_must);
2708 if (cr->cr_at_oids_may) LDAP_VFREE(cr->cr_at_oids_may);
2709 if (cr->cr_at_oids_not) LDAP_VFREE(cr->cr_at_oids_not);
2710 free_extensions(cr->cr_extensions);
2715 ldap_str2contentrule( LDAP_CONST char * s,
2717 LDAP_CONST char ** errp,
2718 LDAP_CONST unsigned flags )
2721 const char * ss = s;
2725 int seen_obsolete = 0;
2730 LDAPContentRule * cr;
2732 const char * savepos;
2735 *code = LDAP_SCHERR_EMPTY;
2741 cr = LDAP_CALLOC(1,sizeof(LDAPContentRule));
2744 *code = LDAP_SCHERR_OUTOFMEM;
2748 kind = get_token(&ss,&sval);
2749 if ( kind != TK_LEFTPAREN ) {
2750 *code = LDAP_SCHERR_NOLEFTPAREN;
2752 ldap_contentrule_free(cr);
2757 * Definitions MUST begin with an OID in the numericoid format.
2761 cr->cr_oid = ldap_int_parse_numericoid(&ss,code,0);
2762 if ( !cr->cr_oid ) {
2763 if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) {
2766 kind = get_token(&ss,&sval);
2767 if ( kind == TK_BAREWORD ) {
2768 if ( !strcasecmp(sval, "NAME") ||
2769 !strcasecmp(sval, "DESC") ||
2770 !strcasecmp(sval, "OBSOLETE") ||
2771 !strcasecmp(sval, "AUX") ||
2772 !strcasecmp(sval, "MUST") ||
2773 !strcasecmp(sval, "MAY") ||
2774 !strcasecmp(sval, "NOT") ||
2775 !strncasecmp(sval, "X-", 2) ) {
2776 /* Missing OID, backtrack */
2779 LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2780 /* Non-numerical OID, ignore */
2781 int len = ss-savepos;
2782 cr->cr_oid = LDAP_MALLOC(len+1);
2783 strncpy(cr->cr_oid, savepos, len);
2784 cr->cr_oid[len] = 0;
2790 ldap_contentrule_free(cr);
2797 * Beyond this point we will be liberal an accept the items
2801 kind = get_token(&ss,&sval);
2804 *code = LDAP_SCHERR_NORIGHTPAREN;
2806 ldap_contentrule_free(cr);
2811 if ( !strcasecmp(sval,"NAME") ) {
2814 *code = LDAP_SCHERR_DUPOPT;
2816 ldap_contentrule_free(cr);
2820 cr->cr_names = parse_qdescrs(&ss,code);
2821 if ( !cr->cr_names ) {
2822 if ( *code != LDAP_SCHERR_OUTOFMEM )
2823 *code = LDAP_SCHERR_BADNAME;
2825 ldap_contentrule_free(cr);
2828 } else if ( !strcasecmp(sval,"DESC") ) {
2831 *code = LDAP_SCHERR_DUPOPT;
2833 ldap_contentrule_free(cr);
2838 kind = get_token(&ss,&sval);
2839 if ( kind != TK_QDSTRING ) {
2840 *code = LDAP_SCHERR_UNEXPTOKEN;
2843 ldap_contentrule_free(cr);
2848 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
2850 if ( seen_obsolete ) {
2851 *code = LDAP_SCHERR_DUPOPT;
2853 ldap_contentrule_free(cr);
2857 cr->cr_obsolete = LDAP_SCHEMA_YES;
2859 } else if ( !strcasecmp(sval,"AUX") ) {
2862 *code = LDAP_SCHERR_DUPOPT;
2864 ldap_contentrule_free(cr);
2868 cr->cr_oc_oids_aux = parse_oids(&ss,code,0);
2869 if ( !cr->cr_oc_oids_aux ) {
2871 ldap_contentrule_free(cr);
2875 } else if ( !strcasecmp(sval,"MUST") ) {
2878 *code = LDAP_SCHERR_DUPOPT;
2880 ldap_contentrule_free(cr);
2884 cr->cr_at_oids_must = parse_oids(&ss,code,0);
2885 if ( !cr->cr_at_oids_must && *code != LDAP_SUCCESS ) {
2887 ldap_contentrule_free(cr);
2891 } else if ( !strcasecmp(sval,"MAY") ) {
2894 *code = LDAP_SCHERR_DUPOPT;
2896 ldap_contentrule_free(cr);
2900 cr->cr_at_oids_may = parse_oids(&ss,code,0);
2901 if ( !cr->cr_at_oids_may && *code != LDAP_SUCCESS ) {
2903 ldap_contentrule_free(cr);
2907 } else if ( !strcasecmp(sval,"NOT") ) {
2910 *code = LDAP_SCHERR_DUPOPT;
2912 ldap_contentrule_free(cr);
2916 cr->cr_at_oids_not = parse_oids(&ss,code,0);
2917 if ( !cr->cr_at_oids_not && *code != LDAP_SUCCESS ) {
2919 ldap_contentrule_free(cr);
2923 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
2924 /* Should be parse_qdstrings */
2925 ext_vals = parse_qdescrs(&ss, code);
2928 ldap_contentrule_free(cr);
2931 if ( add_extension(&cr->cr_extensions,
2933 *code = LDAP_SCHERR_OUTOFMEM;
2936 ldap_contentrule_free(cr);
2940 *code = LDAP_SCHERR_UNEXPTOKEN;
2943 ldap_contentrule_free(cr);
2948 *code = LDAP_SCHERR_UNEXPTOKEN;
2951 ldap_contentrule_free(cr);
2958 ldap_structurerule_free(LDAPStructureRule * sr)
2961 if (sr->sr_names) LDAP_VFREE(sr->sr_names);
2962 if (sr->sr_desc) LDAP_FREE(sr->sr_desc);
2963 if (sr->sr_nameform) LDAP_FREE(sr->sr_nameform);
2964 if (sr->sr_sup_ruleids) LDAP_FREE(sr->sr_sup_ruleids);
2965 free_extensions(sr->sr_extensions);
2970 ldap_str2structurerule( LDAP_CONST char * s,
2972 LDAP_CONST char ** errp,
2973 LDAP_CONST unsigned flags )
2977 const char * ss = s;
2981 int seen_obsolete = 0;
2982 int seen_nameform = 0;
2983 LDAPStructureRule * sr;
2985 const char * savepos;
2988 *code = LDAP_SCHERR_EMPTY;
2994 sr = LDAP_CALLOC(1,sizeof(LDAPStructureRule));
2997 *code = LDAP_SCHERR_OUTOFMEM;
3001 kind = get_token(&ss,&sval);
3002 if ( kind != TK_LEFTPAREN ) {
3003 *code = LDAP_SCHERR_NOLEFTPAREN;
3005 ldap_structurerule_free(sr);
3010 * Definitions MUST begin with a ruleid.
3014 ret = ldap_int_parse_ruleid(&ss,code,0,&sr->sr_ruleid);
3017 ldap_structurerule_free(sr);
3023 * Beyond this point we will be liberal an accept the items
3027 kind = get_token(&ss,&sval);
3030 *code = LDAP_SCHERR_NORIGHTPAREN;
3032 ldap_structurerule_free(sr);
3035 if( !seen_nameform ) {
3036 *code = LDAP_SCHERR_MISSING;
3037 ldap_structurerule_free(sr);
3042 if ( !strcasecmp(sval,"NAME") ) {
3045 *code = LDAP_SCHERR_DUPOPT;
3047 ldap_structurerule_free(sr);
3051 sr->sr_names = parse_qdescrs(&ss,code);
3052 if ( !sr->sr_names ) {
3053 if ( *code != LDAP_SCHERR_OUTOFMEM )
3054 *code = LDAP_SCHERR_BADNAME;
3056 ldap_structurerule_free(sr);
3059 } else if ( !strcasecmp(sval,"DESC") ) {
3062 *code = LDAP_SCHERR_DUPOPT;
3064 ldap_structurerule_free(sr);
3069 kind = get_token(&ss,&sval);
3070 if ( kind != TK_QDSTRING ) {
3071 *code = LDAP_SCHERR_UNEXPTOKEN;
3074 ldap_structurerule_free(sr);
3079 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
3081 if ( seen_obsolete ) {
3082 *code = LDAP_SCHERR_DUPOPT;
3084 ldap_structurerule_free(sr);
3088 sr->sr_obsolete = LDAP_SCHEMA_YES;
3090 } else if ( !strcasecmp(sval,"FORM") ) {
3092 if ( seen_nameform ) {
3093 *code = LDAP_SCHERR_DUPOPT;
3095 ldap_structurerule_free(sr);
3099 sr->sr_nameform = parse_woid(&ss,code);
3100 if ( !sr->sr_nameform ) {
3102 ldap_structurerule_free(sr);
3106 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
3107 /* Should be parse_qdstrings */
3108 ext_vals = parse_qdescrs(&ss, code);
3111 ldap_structurerule_free(sr);
3114 if ( add_extension(&sr->sr_extensions,
3116 *code = LDAP_SCHERR_OUTOFMEM;
3119 ldap_structurerule_free(sr);
3123 *code = LDAP_SCHERR_UNEXPTOKEN;
3126 ldap_structurerule_free(sr);
3131 *code = LDAP_SCHERR_UNEXPTOKEN;
3134 ldap_structurerule_free(sr);
3141 ldap_nameform_free(LDAPNameForm * nf)
3144 LDAP_FREE(nf->nf_oid);
3145 if (nf->nf_names) LDAP_VFREE(nf->nf_names);
3146 if (nf->nf_desc) LDAP_FREE(nf->nf_desc);
3147 if (nf->nf_objectclass) LDAP_FREE(nf->nf_objectclass);
3148 if (nf->nf_at_oids_must) LDAP_VFREE(nf->nf_at_oids_must);
3149 if (nf->nf_at_oids_may) LDAP_VFREE(nf->nf_at_oids_may);
3150 free_extensions(nf->nf_extensions);
3155 ldap_str2nameform( LDAP_CONST char * s,
3157 LDAP_CONST char ** errp,
3158 LDAP_CONST unsigned flags )
3161 const char * ss = s;
3165 int seen_obsolete = 0;
3171 const char * savepos;
3174 *code = LDAP_SCHERR_EMPTY;
3180 nf = LDAP_CALLOC(1,sizeof(LDAPNameForm));
3183 *code = LDAP_SCHERR_OUTOFMEM;
3187 kind = get_token(&ss,&sval);
3188 if ( kind != TK_LEFTPAREN ) {
3189 *code = LDAP_SCHERR_NOLEFTPAREN;
3191 ldap_nameform_free(nf);
3196 * Definitions MUST begin with an OID in the numericoid format.
3197 * However, this routine is used by clients to parse the response
3198 * from servers and very well known servers will provide an OID
3199 * in the wrong format or even no OID at all. We do our best to
3200 * extract info from those servers.
3204 nf->nf_oid = ldap_int_parse_numericoid(&ss,code,0);
3205 if ( !nf->nf_oid ) {
3207 ldap_nameform_free(nf);
3213 * Beyond this point we will be liberal an accept the items
3217 kind = get_token(&ss,&sval);
3220 *code = LDAP_SCHERR_NORIGHTPAREN;
3222 ldap_nameform_free(nf);
3225 if( !seen_class || !seen_must ) {
3226 *code = LDAP_SCHERR_MISSING;
3227 ldap_nameform_free(nf);
3232 if ( !strcasecmp(sval,"NAME") ) {
3235 *code = LDAP_SCHERR_DUPOPT;
3237 ldap_nameform_free(nf);
3241 nf->nf_names = parse_qdescrs(&ss,code);
3242 if ( !nf->nf_names ) {
3243 if ( *code != LDAP_SCHERR_OUTOFMEM )
3244 *code = LDAP_SCHERR_BADNAME;
3246 ldap_nameform_free(nf);
3249 } else if ( !strcasecmp(sval,"DESC") ) {
3252 *code = LDAP_SCHERR_DUPOPT;
3254 ldap_nameform_free(nf);
3259 kind = get_token(&ss,&sval);
3260 if ( kind != TK_QDSTRING ) {
3261 *code = LDAP_SCHERR_UNEXPTOKEN;
3264 ldap_nameform_free(nf);
3269 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
3271 if ( seen_obsolete ) {
3272 *code = LDAP_SCHERR_DUPOPT;
3274 ldap_nameform_free(nf);
3278 nf->nf_obsolete = LDAP_SCHEMA_YES;
3280 } else if ( !strcasecmp(sval,"OC") ) {
3283 *code = LDAP_SCHERR_DUPOPT;
3285 ldap_nameform_free(nf);
3289 nf->nf_objectclass = parse_woid(&ss,code);
3290 if ( !nf->nf_objectclass ) {
3292 ldap_nameform_free(nf);
3295 } else if ( !strcasecmp(sval,"MUST") ) {
3298 *code = LDAP_SCHERR_DUPOPT;
3300 ldap_nameform_free(nf);
3304 nf->nf_at_oids_must = parse_oids(&ss,code,0);
3305 if ( !nf->nf_at_oids_must && *code != LDAP_SUCCESS ) {
3307 ldap_nameform_free(nf);
3311 } else if ( !strcasecmp(sval,"MAY") ) {
3314 *code = LDAP_SCHERR_DUPOPT;
3316 ldap_nameform_free(nf);
3320 nf->nf_at_oids_may = parse_oids(&ss,code,0);
3321 if ( !nf->nf_at_oids_may && *code != LDAP_SUCCESS ) {
3323 ldap_nameform_free(nf);
3327 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
3328 /* Should be parse_qdstrings */
3329 ext_vals = parse_qdescrs(&ss, code);
3332 ldap_nameform_free(nf);
3335 if ( add_extension(&nf->nf_extensions,
3337 *code = LDAP_SCHERR_OUTOFMEM;
3340 ldap_nameform_free(nf);
3344 *code = LDAP_SCHERR_UNEXPTOKEN;
3347 ldap_nameform_free(nf);
3352 *code = LDAP_SCHERR_UNEXPTOKEN;
3355 ldap_nameform_free(nf);
3361 static char *const err2text[] = {
3363 N_("Out of memory"),
3364 N_("Unexpected token"),
3365 N_("Missing opening parenthesis"),
3366 N_("Missing closing parenthesis"),
3367 N_("Expecting digit"),
3368 N_("Expecting a name"),
3369 N_("Bad description"),
3370 N_("Bad superiors"),
3371 N_("Duplicate option"),
3372 N_("Unexpected end of data"),
3373 N_("Missing required field"),
3374 N_("Out of order field")
3378 ldap_scherr2str(int code)
3380 if ( code < 0 || code >= (int)(sizeof(err2text)/sizeof(char *)) ) {
3381 return _("Unknown error");
3383 return _(err2text[code]);