2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2010 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 return( syn->syn_oid );
48 ldap_matchingrule2name( LDAPMatchingRule * mr )
50 return( choose_name( mr->mr_names, mr->mr_oid ) );
54 ldap_matchingruleuse2name( LDAPMatchingRuleUse * mru )
56 return( choose_name( mru->mru_names, mru->mru_oid ) );
60 ldap_attributetype2name( LDAPAttributeType * at )
62 return( choose_name( at->at_names, at->at_oid ) );
66 ldap_objectclass2name( LDAPObjectClass * oc )
68 return( choose_name( oc->oc_names, oc->oc_oid ) );
72 ldap_contentrule2name( LDAPContentRule * cr )
74 return( choose_name( cr->cr_names, cr->cr_oid ) );
78 ldap_nameform2name( LDAPNameForm * nf )
80 return( choose_name( nf->nf_names, nf->nf_oid ) );
84 ldap_structurerule2name( LDAPStructureRule * sr )
86 return( choose_name( sr->sr_names, NULL ) );
90 * When pretty printing the entities we will be appending to a buffer.
91 * Since checking for overflow, realloc'ing and checking if no error
92 * is extremely boring, we will use a protection layer that will let
93 * us blissfully ignore the error until the end. This layer is
94 * implemented with the help of the next type.
97 typedef struct safe_string {
105 new_safe_string(int size)
109 ss = LDAP_MALLOC(sizeof(safe_string));
113 ss->val = LDAP_MALLOC(size);
127 safe_string_free(safe_string * ss)
137 safe_string_val(safe_string * ss)
139 ss->val[ss->pos] = '\0';
145 safe_strdup(safe_string * ss)
147 char *ret = LDAP_MALLOC(ss->pos+1);
150 AC_MEMCPY(ret, ss->val, ss->pos);
156 append_to_safe_string(safe_string * ss, char * s)
162 * Some runaway process is trying to append to a string that
163 * overflowed and we could not extend.
168 /* We always make sure there is at least one position available */
169 if ( ss->pos + l >= ss->size-1 ) {
171 if ( ss->pos + l >= ss->size-1 ) {
172 ss->size = ss->pos + l + 1;
175 temp = LDAP_REALLOC(ss->val, ss->size);
177 /* Trouble, out of memory */
183 strncpy(&ss->val[ss->pos], s, l);
185 if ( ss->pos > 0 && LDAP_SPACE(ss->val[ss->pos-1]) )
194 print_literal(safe_string *ss, char *s)
196 return(append_to_safe_string(ss,s));
200 print_whsp(safe_string *ss)
203 return(append_to_safe_string(ss,""));
205 return(append_to_safe_string(ss," "));
209 print_numericoid(safe_string *ss, char *s)
212 return(append_to_safe_string(ss,s));
214 return(append_to_safe_string(ss,""));
217 /* This one is identical to print_qdescr */
219 print_qdstring(safe_string *ss, char *s)
222 print_literal(ss,"'");
223 append_to_safe_string(ss,s);
224 print_literal(ss,"'");
225 return(print_whsp(ss));
229 print_qdescr(safe_string *ss, char *s)
232 print_literal(ss,"'");
233 append_to_safe_string(ss,s);
234 print_literal(ss,"'");
235 return(print_whsp(ss));
239 print_qdescrlist(safe_string *ss, char **sa)
244 for (sp=sa; *sp; sp++) {
245 ret = print_qdescr(ss,*sp);
247 /* If the list was empty, we return zero that is potentially
248 * incorrect, but since we will be still appending things, the
249 * overflow will be detected later. Maybe FIX.
255 print_qdescrs(safe_string *ss, char **sa)
257 /* The only way to represent an empty list is as a qdescrlist
258 * so, if the list is empty we treat it as a long list.
259 * Really, this is what the syntax mandates. We should not
260 * be here if the list was empty, but if it happens, a label
261 * has already been output and we cannot undo it.
263 if ( !sa[0] || ( sa[0] && sa[1] ) ) {
265 print_literal(ss,"("/*)*/);
266 print_qdescrlist(ss,sa);
267 print_literal(ss,/*(*/")");
268 return(print_whsp(ss));
270 return(print_qdescr(ss,*sa));
275 print_woid(safe_string *ss, char *s)
278 append_to_safe_string(ss,s);
279 return print_whsp(ss);
283 print_oidlist(safe_string *ss, char **sa)
287 for (sp=sa; *(sp+1); sp++) {
289 print_literal(ss,"$");
291 return(print_woid(ss,*sp));
295 print_oids(safe_string *ss, char **sa)
297 if ( sa[0] && sa[1] ) {
298 print_literal(ss,"("/*)*/);
299 print_oidlist(ss,sa);
301 return(print_literal(ss,/*(*/")"));
303 return(print_woid(ss,*sa));
308 print_noidlen(safe_string *ss, char *s, int l)
313 ret = print_numericoid(ss,s);
315 snprintf(buf, sizeof buf, "{%d}",l);
316 ret = print_literal(ss,buf);
322 print_ruleid(safe_string *ss, int rid)
325 snprintf(buf, sizeof buf, "%d", rid);
326 return print_literal(ss,buf);
330 print_ruleids(safe_string *ss, int n, int *rids)
335 print_ruleid(ss,rids[0]);
336 return print_whsp(ss);
338 print_literal(ss,"("/*)*/);
339 for( i=0; i<n; i++ ) {
341 print_ruleid(ss,rids[i]);
344 return print_literal(ss,/*(*/")");
350 print_extensions(safe_string *ss, LDAPSchemaExtensionItem **extensions)
352 LDAPSchemaExtensionItem **ext;
356 for ( ext = extensions; *ext != NULL; ext++ ) {
357 print_literal(ss, (*ext)->lsei_name);
359 /* Should be print_qdstrings */
360 print_qdescrs(ss, (*ext)->lsei_values);
369 ldap_syntax2str( LDAPSyntax * syn )
372 if (ldap_syntax2bv( syn, &bv ))
379 ldap_syntax2bv( LDAPSyntax * syn, struct berval *bv )
383 ss = new_safe_string(256);
387 print_literal(ss,"("/*)*/);
390 print_numericoid(ss, syn->syn_oid);
393 if ( syn->syn_desc ) {
394 print_literal(ss,"DESC");
395 print_qdstring(ss,syn->syn_desc);
400 print_extensions(ss, syn->syn_extensions);
402 print_literal(ss,/*(*/ ")");
404 bv->bv_val = safe_strdup(ss);
405 bv->bv_len = ss->pos;
406 safe_string_free(ss);
411 ldap_matchingrule2str( LDAPMatchingRule * mr )
414 if (ldap_matchingrule2bv( mr, &bv ))
421 ldap_matchingrule2bv( LDAPMatchingRule * mr, struct berval *bv )
425 ss = new_safe_string(256);
429 print_literal(ss,"(" /*)*/);
432 print_numericoid(ss, mr->mr_oid);
435 if ( mr->mr_names ) {
436 print_literal(ss,"NAME");
437 print_qdescrs(ss,mr->mr_names);
441 print_literal(ss,"DESC");
442 print_qdstring(ss,mr->mr_desc);
445 if ( mr->mr_obsolete ) {
446 print_literal(ss, "OBSOLETE");
450 if ( mr->mr_syntax_oid ) {
451 print_literal(ss,"SYNTAX");
453 print_literal(ss, mr->mr_syntax_oid);
459 print_extensions(ss, mr->mr_extensions);
461 print_literal(ss,/*(*/")");
463 bv->bv_val = safe_strdup(ss);
464 bv->bv_len = ss->pos;
465 safe_string_free(ss);
470 ldap_matchingruleuse2str( LDAPMatchingRuleUse * mru )
473 if (ldap_matchingruleuse2bv( mru, &bv ))
480 ldap_matchingruleuse2bv( LDAPMatchingRuleUse * mru, struct berval *bv )
484 ss = new_safe_string(256);
488 print_literal(ss,"(" /*)*/);
491 print_numericoid(ss, mru->mru_oid);
494 if ( mru->mru_names ) {
495 print_literal(ss,"NAME");
496 print_qdescrs(ss,mru->mru_names);
499 if ( mru->mru_desc ) {
500 print_literal(ss,"DESC");
501 print_qdstring(ss,mru->mru_desc);
504 if ( mru->mru_obsolete ) {
505 print_literal(ss, "OBSOLETE");
509 if ( mru->mru_applies_oids ) {
510 print_literal(ss,"APPLIES");
512 print_oids(ss, mru->mru_applies_oids);
518 print_extensions(ss, mru->mru_extensions);
520 print_literal(ss,/*(*/")");
522 bv->bv_val = safe_strdup(ss);
523 bv->bv_len = ss->pos;
524 safe_string_free(ss);
529 ldap_objectclass2str( LDAPObjectClass * oc )
532 if (ldap_objectclass2bv( oc, &bv ))
539 ldap_objectclass2bv( LDAPObjectClass * oc, struct berval *bv )
543 ss = new_safe_string(256);
547 print_literal(ss,"("/*)*/);
550 print_numericoid(ss, oc->oc_oid);
553 if ( oc->oc_names ) {
554 print_literal(ss,"NAME");
555 print_qdescrs(ss,oc->oc_names);
559 print_literal(ss,"DESC");
560 print_qdstring(ss,oc->oc_desc);
563 if ( oc->oc_obsolete ) {
564 print_literal(ss, "OBSOLETE");
568 if ( oc->oc_sup_oids ) {
569 print_literal(ss,"SUP");
571 print_oids(ss,oc->oc_sup_oids);
575 switch (oc->oc_kind) {
576 case LDAP_SCHEMA_ABSTRACT:
577 print_literal(ss,"ABSTRACT");
579 case LDAP_SCHEMA_STRUCTURAL:
580 print_literal(ss,"STRUCTURAL");
582 case LDAP_SCHEMA_AUXILIARY:
583 print_literal(ss,"AUXILIARY");
586 print_literal(ss,"KIND-UNKNOWN");
591 if ( oc->oc_at_oids_must ) {
592 print_literal(ss,"MUST");
594 print_oids(ss,oc->oc_at_oids_must);
598 if ( oc->oc_at_oids_may ) {
599 print_literal(ss,"MAY");
601 print_oids(ss,oc->oc_at_oids_may);
607 print_extensions(ss, oc->oc_extensions);
609 print_literal(ss, /*(*/")");
611 bv->bv_val = safe_strdup(ss);
612 bv->bv_len = ss->pos;
613 safe_string_free(ss);
618 ldap_contentrule2str( LDAPContentRule * cr )
621 if (ldap_contentrule2bv( cr, &bv ))
628 ldap_contentrule2bv( LDAPContentRule * cr, struct berval *bv )
632 ss = new_safe_string(256);
636 print_literal(ss,"("/*)*/);
639 print_numericoid(ss, cr->cr_oid);
642 if ( cr->cr_names ) {
643 print_literal(ss,"NAME");
644 print_qdescrs(ss,cr->cr_names);
648 print_literal(ss,"DESC");
649 print_qdstring(ss,cr->cr_desc);
652 if ( cr->cr_obsolete ) {
653 print_literal(ss, "OBSOLETE");
657 if ( cr->cr_oc_oids_aux ) {
658 print_literal(ss,"AUX");
660 print_oids(ss,cr->cr_oc_oids_aux);
664 if ( cr->cr_at_oids_must ) {
665 print_literal(ss,"MUST");
667 print_oids(ss,cr->cr_at_oids_must);
671 if ( cr->cr_at_oids_may ) {
672 print_literal(ss,"MAY");
674 print_oids(ss,cr->cr_at_oids_may);
678 if ( cr->cr_at_oids_not ) {
679 print_literal(ss,"NOT");
681 print_oids(ss,cr->cr_at_oids_not);
686 print_extensions(ss, cr->cr_extensions);
688 print_literal(ss, /*(*/")");
690 bv->bv_val = safe_strdup(ss);
691 bv->bv_len = ss->pos;
692 safe_string_free(ss);
697 ldap_structurerule2str( LDAPStructureRule * sr )
700 if (ldap_structurerule2bv( sr, &bv ))
707 ldap_structurerule2bv( LDAPStructureRule * sr, struct berval *bv )
711 ss = new_safe_string(256);
715 print_literal(ss,"("/*)*/);
718 print_ruleid(ss, sr->sr_ruleid);
721 if ( sr->sr_names ) {
722 print_literal(ss,"NAME");
723 print_qdescrs(ss,sr->sr_names);
727 print_literal(ss,"DESC");
728 print_qdstring(ss,sr->sr_desc);
731 if ( sr->sr_obsolete ) {
732 print_literal(ss, "OBSOLETE");
736 print_literal(ss,"FORM");
738 print_woid(ss,sr->sr_nameform);
741 if ( sr->sr_nsup_ruleids ) {
742 print_literal(ss,"SUP");
744 print_ruleids(ss,sr->sr_nsup_ruleids,sr->sr_sup_ruleids);
749 print_extensions(ss, sr->sr_extensions);
751 print_literal(ss, /*(*/")");
753 bv->bv_val = safe_strdup(ss);
754 bv->bv_len = ss->pos;
755 safe_string_free(ss);
761 ldap_nameform2str( LDAPNameForm * nf )
764 if (ldap_nameform2bv( nf, &bv ))
771 ldap_nameform2bv( LDAPNameForm * nf, struct berval *bv )
775 ss = new_safe_string(256);
779 print_literal(ss,"("/*)*/);
782 print_numericoid(ss, nf->nf_oid);
785 if ( nf->nf_names ) {
786 print_literal(ss,"NAME");
787 print_qdescrs(ss,nf->nf_names);
791 print_literal(ss,"DESC");
792 print_qdstring(ss,nf->nf_desc);
795 if ( nf->nf_obsolete ) {
796 print_literal(ss, "OBSOLETE");
800 print_literal(ss,"OC");
802 print_woid(ss,nf->nf_objectclass);
805 print_literal(ss,"MUST");
807 print_oids(ss,nf->nf_at_oids_must);
811 if ( nf->nf_at_oids_may ) {
812 print_literal(ss,"MAY");
814 print_oids(ss,nf->nf_at_oids_may);
819 print_extensions(ss, nf->nf_extensions);
821 print_literal(ss, /*(*/")");
823 bv->bv_val = safe_strdup(ss);
824 bv->bv_len = ss->pos;
825 safe_string_free(ss);
830 ldap_attributetype2str( LDAPAttributeType * at )
833 if (ldap_attributetype2bv( at, &bv ))
840 ldap_attributetype2bv( LDAPAttributeType * at, struct berval *bv )
844 ss = new_safe_string(256);
848 print_literal(ss,"("/*)*/);
851 print_numericoid(ss, at->at_oid);
854 if ( at->at_names ) {
855 print_literal(ss,"NAME");
856 print_qdescrs(ss,at->at_names);
860 print_literal(ss,"DESC");
861 print_qdstring(ss,at->at_desc);
864 if ( at->at_obsolete ) {
865 print_literal(ss, "OBSOLETE");
869 if ( at->at_sup_oid ) {
870 print_literal(ss,"SUP");
871 print_woid(ss,at->at_sup_oid);
874 if ( at->at_equality_oid ) {
875 print_literal(ss,"EQUALITY");
876 print_woid(ss,at->at_equality_oid);
879 if ( at->at_ordering_oid ) {
880 print_literal(ss,"ORDERING");
881 print_woid(ss,at->at_ordering_oid);
884 if ( at->at_substr_oid ) {
885 print_literal(ss,"SUBSTR");
886 print_woid(ss,at->at_substr_oid);
889 if ( at->at_syntax_oid ) {
890 print_literal(ss,"SYNTAX");
892 print_noidlen(ss,at->at_syntax_oid,at->at_syntax_len);
896 if ( at->at_single_value == LDAP_SCHEMA_YES ) {
897 print_literal(ss,"SINGLE-VALUE");
901 if ( at->at_collective == LDAP_SCHEMA_YES ) {
902 print_literal(ss,"COLLECTIVE");
906 if ( at->at_no_user_mod == LDAP_SCHEMA_YES ) {
907 print_literal(ss,"NO-USER-MODIFICATION");
911 if ( at->at_usage != LDAP_SCHEMA_USER_APPLICATIONS ) {
912 print_literal(ss,"USAGE");
914 switch (at->at_usage) {
915 case LDAP_SCHEMA_DIRECTORY_OPERATION:
916 print_literal(ss,"directoryOperation");
918 case LDAP_SCHEMA_DISTRIBUTED_OPERATION:
919 print_literal(ss,"distributedOperation");
921 case LDAP_SCHEMA_DSA_OPERATION:
922 print_literal(ss,"dSAOperation");
925 print_literal(ss,"UNKNOWN");
932 print_extensions(ss, at->at_extensions);
934 print_literal(ss,/*(*/")");
936 bv->bv_val = safe_strdup(ss);
937 bv->bv_len = ss->pos;
938 safe_string_free(ss);
943 * Now come the parsers. There is one parser for each entity type:
944 * objectclasses, attributetypes, etc.
946 * Each of them is written as a recursive-descent parser, except that
947 * none of them is really recursive. But the idea is kept: there
948 * is one routine per non-terminal that eithers gobbles lexical tokens
949 * or calls lower-level routines, etc.
951 * The scanner is implemented in the routine get_token. Actually,
952 * get_token is more than a scanner and will return tokens that are
953 * in fact non-terminals in the grammar. So you can see the whole
954 * approach as the combination of a low-level bottom-up recognizer
955 * combined with a scanner and a number of top-down parsers. Or just
956 * consider that the real grammars recognized by the parsers are not
957 * those of the standards. As a matter of fact, our parsers are more
958 * liberal than the spec when there is no ambiguity.
960 * The difference is pretty academic (modulo bugs or incorrect
961 * interpretation of the specs).
974 TK_QDESCR = TK_QDSTRING
978 get_token( const char ** sp, char ** token_val )
996 kind = TK_RIGHTPAREN;
1007 while ( **sp != '\'' && **sp != '\0' )
1009 if ( **sp == '\'' ) {
1011 res = LDAP_MALLOC(q-p+1);
1021 kind = TK_NOENDQUOTE;
1027 while ( !LDAP_SPACE(**sp) &&
1032 /* for suggested minimum upper bound on the number
1033 * of characters (RFC 4517) */
1038 res = LDAP_MALLOC(q-p+1);
1047 /* kind = TK_UNEXPCHAR; */
1054 /* Gobble optional whitespace */
1056 parse_whsp(const char **sp)
1058 while (LDAP_SPACE(**sp))
1063 * General note for all parsers: to guarantee the algorithm halts they
1064 * must always advance the pointer even when an error is found. For
1065 * this one is not that important since an error here is fatal at the
1066 * upper layers, but it is a simple strategy that will not get in
1070 /* Parse a sequence of dot-separated decimal strings */
1072 ldap_int_parse_numericoid(const char **sp, int *code, const int flags)
1075 const char * start = *sp;
1079 /* Netscape puts the SYNTAX value in quotes (incorrectly) */
1080 if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && **sp == '\'' ) {
1085 /* Each iteration of this loop gets one decimal string */
1087 if ( !LDAP_DIGIT(**sp) ) {
1089 * Initial char is not a digit or char after dot is
1092 *code = LDAP_SCHERR_NODIGIT;
1096 while ( LDAP_DIGIT(**sp) )
1100 /* Otherwise, gobble the dot and loop again */
1103 /* Now *sp points at the char past the numericoid. Perfect. */
1105 if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && quoted ) {
1106 if ( **sp == '\'' ) {
1109 *code = LDAP_SCHERR_UNEXPTOKEN;
1113 if (flags & LDAP_SCHEMA_SKIP) {
1114 res = (char *)start;
1116 res = LDAP_MALLOC(len+1);
1118 *code = LDAP_SCHERR_OUTOFMEM;
1121 strncpy(res,start,len);
1127 /* Parse a sequence of dot-separated decimal strings */
1129 ldap_int_parse_ruleid(const char **sp, int *code, const int flags, int *ruleid)
1133 if ( !LDAP_DIGIT(**sp) ) {
1134 *code = LDAP_SCHERR_NODIGIT;
1137 *ruleid = (**sp) - '0';
1140 while ( LDAP_DIGIT(**sp) ) {
1142 *ruleid += (**sp) - '0';
1149 /* Parse a qdescr or a list of them enclosed in () */
1151 parse_qdescrs(const char **sp, int *code)
1161 kind = get_token(sp,&sval);
1162 if ( kind == TK_LEFTPAREN ) {
1163 /* Let's presume there will be at least 2 entries */
1165 res = LDAP_CALLOC(3,sizeof(char *));
1167 *code = LDAP_SCHERR_OUTOFMEM;
1173 kind = get_token(sp,&sval);
1174 if ( kind == TK_RIGHTPAREN )
1176 if ( kind == TK_QDESCR ) {
1177 if ( pos == size-2 ) {
1179 res1 = LDAP_REALLOC(res,size*sizeof(char *));
1183 *code = LDAP_SCHERR_OUTOFMEM;
1194 *code = LDAP_SCHERR_UNEXPTOKEN;
1200 } else if ( kind == TK_QDESCR ) {
1201 res = LDAP_CALLOC(2,sizeof(char *));
1203 *code = LDAP_SCHERR_OUTOFMEM;
1212 *code = LDAP_SCHERR_BADNAME;
1219 parse_woid(const char **sp, int *code)
1225 kind = get_token(sp, &sval);
1226 if ( kind != TK_BAREWORD ) {
1228 *code = LDAP_SCHERR_UNEXPTOKEN;
1235 /* Parse a noidlen */
1237 parse_noidlen(const char **sp, int *code, int *len, int flags)
1240 const char *savepos;
1242 int allow_quoted = ( flags & LDAP_SCHEMA_ALLOW_QUOTED );
1243 int allow_oidmacro = ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO );
1246 /* Netscape puts the SYNTAX value in quotes (incorrectly) */
1247 if ( allow_quoted && **sp == '\'' ) {
1252 sval = ldap_int_parse_numericoid(sp, code, 0);
1256 && *code == LDAP_SCHERR_NODIGIT )
1258 if ( get_token(sp, &sval) != TK_BAREWORD ) {
1259 if ( sval != NULL ) {
1268 if ( **sp == '{' /*}*/ ) {
1271 while ( LDAP_DIGIT(**sp) )
1273 if ( **sp != /*{*/ '}' ) {
1274 *code = LDAP_SCHERR_UNEXPTOKEN;
1280 if ( allow_quoted && quoted ) {
1281 if ( **sp == '\'' ) {
1284 *code = LDAP_SCHERR_UNEXPTOKEN;
1293 * Next routine will accept a qdstring in place of an oid if
1294 * allow_quoted is set. This is necessary to interoperate with
1295 * Netscape Directory server that will improperly quote each oid (at
1296 * least those of the descr kind) in the SUP clause.
1299 /* Parse a woid or a $-separated list of them enclosed in () */
1301 parse_oids(const char **sp, int *code, const int allow_quoted)
1311 * Strictly speaking, doing this here accepts whsp before the
1312 * ( at the begining of an oidlist, but this is harmless. Also,
1313 * we are very liberal in what we accept as an OID. Maybe
1317 kind = get_token(sp,&sval);
1318 if ( kind == TK_LEFTPAREN ) {
1319 /* Let's presume there will be at least 2 entries */
1321 res = LDAP_CALLOC(3,sizeof(char *));
1323 *code = LDAP_SCHERR_OUTOFMEM;
1328 kind = get_token(sp,&sval);
1329 if ( kind == TK_BAREWORD ||
1330 ( allow_quoted && kind == TK_QDSTRING ) ) {
1333 } else if ( kind == TK_RIGHTPAREN ) {
1334 /* FIXME: be liberal in what we accept... */
1339 *code = LDAP_SCHERR_UNEXPTOKEN;
1346 kind = get_token(sp,&sval);
1347 if ( kind == TK_RIGHTPAREN )
1349 if ( kind == TK_DOLLAR ) {
1351 kind = get_token(sp,&sval);
1352 if ( kind == TK_BAREWORD ||
1354 kind == TK_QDSTRING ) ) {
1355 if ( pos == size-2 ) {
1357 res1 = LDAP_REALLOC(res,size*sizeof(char *));
1361 *code = LDAP_SCHERR_OUTOFMEM;
1369 *code = LDAP_SCHERR_UNEXPTOKEN;
1376 *code = LDAP_SCHERR_UNEXPTOKEN;
1384 } else if ( kind == TK_BAREWORD ||
1385 ( allow_quoted && kind == TK_QDSTRING ) ) {
1386 res = LDAP_CALLOC(2,sizeof(char *));
1389 *code = LDAP_SCHERR_OUTOFMEM;
1398 *code = LDAP_SCHERR_BADNAME;
1404 add_extension(LDAPSchemaExtensionItem ***extensions,
1405 char * name, char ** values)
1408 LDAPSchemaExtensionItem **tmp, *ext;
1410 ext = LDAP_CALLOC(1, sizeof(LDAPSchemaExtensionItem));
1413 ext->lsei_name = name;
1414 ext->lsei_values = values;
1416 if ( !*extensions ) {
1418 LDAP_CALLOC(2, sizeof(LDAPSchemaExtensionItem *));
1419 if ( !*extensions ) {
1425 for ( n=0; (*extensions)[n] != NULL; n++ )
1427 tmp = LDAP_REALLOC(*extensions,
1428 (n+2)*sizeof(LDAPSchemaExtensionItem *));
1435 (*extensions)[n] = ext;
1436 (*extensions)[n+1] = NULL;
1441 free_extensions(LDAPSchemaExtensionItem **extensions)
1443 LDAPSchemaExtensionItem **ext;
1446 for ( ext = extensions; *ext != NULL; ext++ ) {
1447 LDAP_FREE((*ext)->lsei_name);
1448 LDAP_VFREE((*ext)->lsei_values);
1451 LDAP_FREE(extensions);
1456 ldap_syntax_free( LDAPSyntax * syn )
1458 LDAP_FREE(syn->syn_oid);
1459 if (syn->syn_names) LDAP_VFREE(syn->syn_names);
1460 if (syn->syn_desc) LDAP_FREE(syn->syn_desc);
1461 free_extensions(syn->syn_extensions);
1466 ldap_str2syntax( LDAP_CONST char * s,
1468 LDAP_CONST char ** errp,
1469 LDAP_CONST unsigned flags )
1472 const char * ss = s;
1480 *code = LDAP_SCHERR_EMPTY;
1486 syn = LDAP_CALLOC(1,sizeof(LDAPSyntax));
1489 *code = LDAP_SCHERR_OUTOFMEM;
1493 kind = get_token(&ss,&sval);
1494 if ( kind != TK_LEFTPAREN ) {
1496 *code = LDAP_SCHERR_NOLEFTPAREN;
1497 ldap_syntax_free(syn);
1502 syn->syn_oid = ldap_int_parse_numericoid(&ss,code,0);
1503 if ( !syn->syn_oid ) {
1505 ldap_syntax_free(syn);
1511 * Beyond this point we will be liberal and accept the items
1515 kind = get_token(&ss,&sval);
1518 *code = LDAP_SCHERR_NORIGHTPAREN;
1520 ldap_syntax_free(syn);
1525 if ( !strcasecmp(sval,"NAME") ) {
1528 *code = LDAP_SCHERR_DUPOPT;
1530 ldap_syntax_free(syn);
1534 syn->syn_names = parse_qdescrs(&ss,code);
1535 if ( !syn->syn_names ) {
1536 if ( *code != LDAP_SCHERR_OUTOFMEM )
1537 *code = LDAP_SCHERR_BADNAME;
1539 ldap_syntax_free(syn);
1542 } else if ( !strcasecmp(sval,"DESC") ) {
1545 *code = LDAP_SCHERR_DUPOPT;
1547 ldap_syntax_free(syn);
1552 kind = get_token(&ss,&sval);
1553 if ( kind != TK_QDSTRING ) {
1554 *code = LDAP_SCHERR_UNEXPTOKEN;
1557 ldap_syntax_free(syn);
1560 syn->syn_desc = sval;
1562 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
1563 /* Should be parse_qdstrings */
1564 ext_vals = parse_qdescrs(&ss, code);
1567 ldap_syntax_free(syn);
1570 if ( add_extension(&syn->syn_extensions,
1572 *code = LDAP_SCHERR_OUTOFMEM;
1575 ldap_syntax_free(syn);
1579 *code = LDAP_SCHERR_UNEXPTOKEN;
1582 ldap_syntax_free(syn);
1587 *code = LDAP_SCHERR_UNEXPTOKEN;
1590 ldap_syntax_free(syn);
1597 ldap_matchingrule_free( LDAPMatchingRule * mr )
1599 LDAP_FREE(mr->mr_oid);
1600 if (mr->mr_names) LDAP_VFREE(mr->mr_names);
1601 if (mr->mr_desc) LDAP_FREE(mr->mr_desc);
1602 if (mr->mr_syntax_oid) LDAP_FREE(mr->mr_syntax_oid);
1603 free_extensions(mr->mr_extensions);
1608 ldap_str2matchingrule( LDAP_CONST char * s,
1610 LDAP_CONST char ** errp,
1611 LDAP_CONST unsigned flags )
1614 const char * ss = s;
1618 int seen_obsolete = 0;
1619 int seen_syntax = 0;
1620 LDAPMatchingRule * mr;
1622 const char * savepos;
1625 *code = LDAP_SCHERR_EMPTY;
1631 mr = LDAP_CALLOC(1,sizeof(LDAPMatchingRule));
1634 *code = LDAP_SCHERR_OUTOFMEM;
1638 kind = get_token(&ss,&sval);
1639 if ( kind != TK_LEFTPAREN ) {
1640 *code = LDAP_SCHERR_NOLEFTPAREN;
1642 ldap_matchingrule_free(mr);
1648 mr->mr_oid = ldap_int_parse_numericoid(&ss,code,flags);
1649 if ( !mr->mr_oid ) {
1650 if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) {
1653 kind = get_token(&ss,&sval);
1654 if ( kind == TK_BAREWORD ) {
1655 if ( !strcasecmp(sval, "NAME") ||
1656 !strcasecmp(sval, "DESC") ||
1657 !strcasecmp(sval, "OBSOLETE") ||
1658 !strcasecmp(sval, "SYNTAX") ||
1659 !strncasecmp(sval, "X-", 2) ) {
1660 /* Missing OID, backtrack */
1663 /* Non-numerical OID, ignore */
1669 ldap_matchingrule_free(mr);
1676 * Beyond this point we will be liberal and accept the items
1680 kind = get_token(&ss,&sval);
1683 *code = LDAP_SCHERR_NORIGHTPAREN;
1685 ldap_matchingrule_free(mr);
1688 if( !seen_syntax ) {
1689 *code = LDAP_SCHERR_MISSING;
1690 ldap_matchingrule_free(mr);
1695 if ( !strcasecmp(sval,"NAME") ) {
1698 *code = LDAP_SCHERR_DUPOPT;
1700 ldap_matchingrule_free(mr);
1704 mr->mr_names = parse_qdescrs(&ss,code);
1705 if ( !mr->mr_names ) {
1706 if ( *code != LDAP_SCHERR_OUTOFMEM )
1707 *code = LDAP_SCHERR_BADNAME;
1709 ldap_matchingrule_free(mr);
1712 } else if ( !strcasecmp(sval,"DESC") ) {
1715 *code = LDAP_SCHERR_DUPOPT;
1717 ldap_matchingrule_free(mr);
1722 kind = get_token(&ss,&sval);
1723 if ( kind != TK_QDSTRING ) {
1724 *code = LDAP_SCHERR_UNEXPTOKEN;
1727 ldap_matchingrule_free(mr);
1732 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
1734 if ( seen_obsolete ) {
1735 *code = LDAP_SCHERR_DUPOPT;
1737 ldap_matchingrule_free(mr);
1741 mr->mr_obsolete = LDAP_SCHEMA_YES;
1743 } else if ( !strcasecmp(sval,"SYNTAX") ) {
1745 if ( seen_syntax ) {
1746 *code = LDAP_SCHERR_DUPOPT;
1748 ldap_matchingrule_free(mr);
1754 ldap_int_parse_numericoid(&ss,code,flags);
1755 if ( !mr->mr_syntax_oid ) {
1757 ldap_matchingrule_free(mr);
1761 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
1762 /* Should be parse_qdstrings */
1763 ext_vals = parse_qdescrs(&ss, code);
1766 ldap_matchingrule_free(mr);
1769 if ( add_extension(&mr->mr_extensions,
1771 *code = LDAP_SCHERR_OUTOFMEM;
1774 ldap_matchingrule_free(mr);
1778 *code = LDAP_SCHERR_UNEXPTOKEN;
1781 ldap_matchingrule_free(mr);
1786 *code = LDAP_SCHERR_UNEXPTOKEN;
1789 ldap_matchingrule_free(mr);
1796 ldap_matchingruleuse_free( LDAPMatchingRuleUse * mru )
1798 LDAP_FREE(mru->mru_oid);
1799 if (mru->mru_names) LDAP_VFREE(mru->mru_names);
1800 if (mru->mru_desc) LDAP_FREE(mru->mru_desc);
1801 if (mru->mru_applies_oids) LDAP_VFREE(mru->mru_applies_oids);
1802 free_extensions(mru->mru_extensions);
1806 LDAPMatchingRuleUse *
1807 ldap_str2matchingruleuse( LDAP_CONST char * s,
1809 LDAP_CONST char ** errp,
1810 LDAP_CONST unsigned flags )
1813 const char * ss = s;
1817 int seen_obsolete = 0;
1818 int seen_applies = 0;
1819 LDAPMatchingRuleUse * mru;
1821 const char * savepos;
1824 *code = LDAP_SCHERR_EMPTY;
1830 mru = LDAP_CALLOC(1,sizeof(LDAPMatchingRuleUse));
1833 *code = LDAP_SCHERR_OUTOFMEM;
1837 kind = get_token(&ss,&sval);
1838 if ( kind != TK_LEFTPAREN ) {
1839 *code = LDAP_SCHERR_NOLEFTPAREN;
1841 ldap_matchingruleuse_free(mru);
1847 mru->mru_oid = ldap_int_parse_numericoid(&ss,code,flags);
1848 if ( !mru->mru_oid ) {
1849 if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) {
1852 kind = get_token(&ss,&sval);
1853 if ( kind == TK_BAREWORD ) {
1854 if ( !strcasecmp(sval, "NAME") ||
1855 !strcasecmp(sval, "DESC") ||
1856 !strcasecmp(sval, "OBSOLETE") ||
1857 !strcasecmp(sval, "APPLIES") ||
1858 !strncasecmp(sval, "X-", 2) ) {
1859 /* Missing OID, backtrack */
1862 /* Non-numerical OID, ignore */
1868 ldap_matchingruleuse_free(mru);
1875 * Beyond this point we will be liberal and accept the items
1879 kind = get_token(&ss,&sval);
1882 *code = LDAP_SCHERR_NORIGHTPAREN;
1884 ldap_matchingruleuse_free(mru);
1887 if( !seen_applies ) {
1888 *code = LDAP_SCHERR_MISSING;
1889 ldap_matchingruleuse_free(mru);
1894 if ( !strcasecmp(sval,"NAME") ) {
1897 *code = LDAP_SCHERR_DUPOPT;
1899 ldap_matchingruleuse_free(mru);
1903 mru->mru_names = parse_qdescrs(&ss,code);
1904 if ( !mru->mru_names ) {
1905 if ( *code != LDAP_SCHERR_OUTOFMEM )
1906 *code = LDAP_SCHERR_BADNAME;
1908 ldap_matchingruleuse_free(mru);
1911 } else if ( !strcasecmp(sval,"DESC") ) {
1914 *code = LDAP_SCHERR_DUPOPT;
1916 ldap_matchingruleuse_free(mru);
1921 kind = get_token(&ss,&sval);
1922 if ( kind != TK_QDSTRING ) {
1923 *code = LDAP_SCHERR_UNEXPTOKEN;
1926 ldap_matchingruleuse_free(mru);
1929 mru->mru_desc = sval;
1931 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
1933 if ( seen_obsolete ) {
1934 *code = LDAP_SCHERR_DUPOPT;
1936 ldap_matchingruleuse_free(mru);
1940 mru->mru_obsolete = LDAP_SCHEMA_YES;
1942 } else if ( !strcasecmp(sval,"APPLIES") ) {
1944 if ( seen_applies ) {
1945 *code = LDAP_SCHERR_DUPOPT;
1947 ldap_matchingruleuse_free(mru);
1951 mru->mru_applies_oids = parse_oids(&ss,
1954 if ( !mru->mru_applies_oids && *code != LDAP_SUCCESS ) {
1956 ldap_matchingruleuse_free(mru);
1959 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
1960 /* Should be parse_qdstrings */
1961 ext_vals = parse_qdescrs(&ss, code);
1964 ldap_matchingruleuse_free(mru);
1967 if ( add_extension(&mru->mru_extensions,
1969 *code = LDAP_SCHERR_OUTOFMEM;
1972 ldap_matchingruleuse_free(mru);
1976 *code = LDAP_SCHERR_UNEXPTOKEN;
1979 ldap_matchingruleuse_free(mru);
1984 *code = LDAP_SCHERR_UNEXPTOKEN;
1987 ldap_matchingruleuse_free(mru);
1994 ldap_attributetype_free(LDAPAttributeType * at)
1996 LDAP_FREE(at->at_oid);
1997 if (at->at_names) LDAP_VFREE(at->at_names);
1998 if (at->at_desc) LDAP_FREE(at->at_desc);
1999 if (at->at_sup_oid) LDAP_FREE(at->at_sup_oid);
2000 if (at->at_equality_oid) LDAP_FREE(at->at_equality_oid);
2001 if (at->at_ordering_oid) LDAP_FREE(at->at_ordering_oid);
2002 if (at->at_substr_oid) LDAP_FREE(at->at_substr_oid);
2003 if (at->at_syntax_oid) LDAP_FREE(at->at_syntax_oid);
2004 free_extensions(at->at_extensions);
2009 ldap_str2attributetype( LDAP_CONST char * s,
2011 LDAP_CONST char ** errp,
2012 LDAP_CONST unsigned flags )
2015 const char * ss = s;
2019 int seen_obsolete = 0;
2021 int seen_equality = 0;
2022 int seen_ordering = 0;
2023 int seen_substr = 0;
2024 int seen_syntax = 0;
2026 LDAPAttributeType * at;
2028 const char * savepos;
2031 *code = LDAP_SCHERR_EMPTY;
2037 at = LDAP_CALLOC(1,sizeof(LDAPAttributeType));
2040 *code = LDAP_SCHERR_OUTOFMEM;
2044 kind = get_token(&ss,&sval);
2045 if ( kind != TK_LEFTPAREN ) {
2046 *code = LDAP_SCHERR_NOLEFTPAREN;
2048 ldap_attributetype_free(at);
2053 * Definitions MUST begin with an OID in the numericoid format.
2054 * However, this routine is used by clients to parse the response
2055 * from servers and very well known servers will provide an OID
2056 * in the wrong format or even no OID at all. We do our best to
2057 * extract info from those servers.
2061 at->at_oid = ldap_int_parse_numericoid(&ss,code,0);
2062 if ( !at->at_oid ) {
2063 if ( ( flags & ( LDAP_SCHEMA_ALLOW_NO_OID
2064 | LDAP_SCHEMA_ALLOW_OID_MACRO ) )
2065 && (ss == savepos) )
2069 kind = get_token(&ss,&sval);
2070 if ( kind == TK_BAREWORD ) {
2071 if ( !strcasecmp(sval, "NAME") ||
2072 !strcasecmp(sval, "DESC") ||
2073 !strcasecmp(sval, "OBSOLETE") ||
2074 !strcasecmp(sval, "SUP") ||
2075 !strcasecmp(sval, "EQUALITY") ||
2076 !strcasecmp(sval, "ORDERING") ||
2077 !strcasecmp(sval, "SUBSTR") ||
2078 !strcasecmp(sval, "SYNTAX") ||
2079 !strcasecmp(sval, "SINGLE-VALUE") ||
2080 !strcasecmp(sval, "COLLECTIVE") ||
2081 !strcasecmp(sval, "NO-USER-MODIFICATION") ||
2082 !strcasecmp(sval, "USAGE") ||
2083 !strncasecmp(sval, "X-", 2) )
2085 /* Missing OID, backtrack */
2088 & LDAP_SCHEMA_ALLOW_OID_MACRO)
2090 /* Non-numerical OID ... */
2091 int len = ss-savepos;
2092 at->at_oid = LDAP_MALLOC(len+1);
2093 strncpy(at->at_oid, savepos, len);
2094 at->at_oid[len] = 0;
2100 ldap_attributetype_free(at);
2107 * Beyond this point we will be liberal and accept the items
2111 kind = get_token(&ss,&sval);
2114 *code = LDAP_SCHERR_NORIGHTPAREN;
2116 ldap_attributetype_free(at);
2121 if ( !strcasecmp(sval,"NAME") ) {
2124 *code = LDAP_SCHERR_DUPOPT;
2126 ldap_attributetype_free(at);
2130 at->at_names = parse_qdescrs(&ss,code);
2131 if ( !at->at_names ) {
2132 if ( *code != LDAP_SCHERR_OUTOFMEM )
2133 *code = LDAP_SCHERR_BADNAME;
2135 ldap_attributetype_free(at);
2138 } else if ( !strcasecmp(sval,"DESC") ) {
2141 *code = LDAP_SCHERR_DUPOPT;
2143 ldap_attributetype_free(at);
2148 kind = get_token(&ss,&sval);
2149 if ( kind != TK_QDSTRING ) {
2150 *code = LDAP_SCHERR_UNEXPTOKEN;
2153 ldap_attributetype_free(at);
2158 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
2160 if ( seen_obsolete ) {
2161 *code = LDAP_SCHERR_DUPOPT;
2163 ldap_attributetype_free(at);
2167 at->at_obsolete = LDAP_SCHEMA_YES;
2169 } else if ( !strcasecmp(sval,"SUP") ) {
2172 *code = LDAP_SCHERR_DUPOPT;
2174 ldap_attributetype_free(at);
2178 at->at_sup_oid = parse_woid(&ss,code);
2179 if ( !at->at_sup_oid ) {
2181 ldap_attributetype_free(at);
2184 } else if ( !strcasecmp(sval,"EQUALITY") ) {
2186 if ( seen_equality ) {
2187 *code = LDAP_SCHERR_DUPOPT;
2189 ldap_attributetype_free(at);
2193 at->at_equality_oid = parse_woid(&ss,code);
2194 if ( !at->at_equality_oid ) {
2196 ldap_attributetype_free(at);
2199 } else if ( !strcasecmp(sval,"ORDERING") ) {
2201 if ( seen_ordering ) {
2202 *code = LDAP_SCHERR_DUPOPT;
2204 ldap_attributetype_free(at);
2208 at->at_ordering_oid = parse_woid(&ss,code);
2209 if ( !at->at_ordering_oid ) {
2211 ldap_attributetype_free(at);
2214 } else if ( !strcasecmp(sval,"SUBSTR") ) {
2216 if ( seen_substr ) {
2217 *code = LDAP_SCHERR_DUPOPT;
2219 ldap_attributetype_free(at);
2223 at->at_substr_oid = parse_woid(&ss,code);
2224 if ( !at->at_substr_oid ) {
2226 ldap_attributetype_free(at);
2229 } else if ( !strcasecmp(sval,"SYNTAX") ) {
2231 if ( seen_syntax ) {
2232 *code = LDAP_SCHERR_DUPOPT;
2234 ldap_attributetype_free(at);
2245 if ( !at->at_syntax_oid ) {
2246 if ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2247 kind = get_token(&ss,&sval);
2248 if (kind == TK_BAREWORD)
2250 char *sp = strchr(sval, '{');
2251 at->at_syntax_oid = sval;
2255 at->at_syntax_len = atoi(sp);
2256 while ( LDAP_DIGIT(*sp) )
2259 *code = LDAP_SCHERR_UNEXPTOKEN;
2261 ldap_attributetype_free(at);
2268 ldap_attributetype_free(at);
2273 } else if ( !strcasecmp(sval,"SINGLE-VALUE") ) {
2275 if ( at->at_single_value ) {
2276 *code = LDAP_SCHERR_DUPOPT;
2278 ldap_attributetype_free(at);
2281 at->at_single_value = LDAP_SCHEMA_YES;
2283 } else if ( !strcasecmp(sval,"COLLECTIVE") ) {
2285 if ( at->at_collective ) {
2286 *code = LDAP_SCHERR_DUPOPT;
2288 ldap_attributetype_free(at);
2291 at->at_collective = LDAP_SCHEMA_YES;
2293 } else if ( !strcasecmp(sval,"NO-USER-MODIFICATION") ) {
2295 if ( at->at_no_user_mod ) {
2296 *code = LDAP_SCHERR_DUPOPT;
2298 ldap_attributetype_free(at);
2301 at->at_no_user_mod = LDAP_SCHEMA_YES;
2303 } else if ( !strcasecmp(sval,"USAGE") ) {
2306 *code = LDAP_SCHERR_DUPOPT;
2308 ldap_attributetype_free(at);
2313 kind = get_token(&ss,&sval);
2314 if ( kind != TK_BAREWORD ) {
2315 *code = LDAP_SCHERR_UNEXPTOKEN;
2318 ldap_attributetype_free(at);
2321 if ( !strcasecmp(sval,"userApplications") )
2323 LDAP_SCHEMA_USER_APPLICATIONS;
2324 else if ( !strcasecmp(sval,"directoryOperation") )
2326 LDAP_SCHEMA_DIRECTORY_OPERATION;
2327 else if ( !strcasecmp(sval,"distributedOperation") )
2329 LDAP_SCHEMA_DISTRIBUTED_OPERATION;
2330 else if ( !strcasecmp(sval,"dSAOperation") )
2332 LDAP_SCHEMA_DSA_OPERATION;
2334 *code = LDAP_SCHERR_UNEXPTOKEN;
2337 ldap_attributetype_free(at);
2342 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
2343 /* Should be parse_qdstrings */
2344 ext_vals = parse_qdescrs(&ss, code);
2347 ldap_attributetype_free(at);
2350 if ( add_extension(&at->at_extensions,
2352 *code = LDAP_SCHERR_OUTOFMEM;
2355 ldap_attributetype_free(at);
2359 *code = LDAP_SCHERR_UNEXPTOKEN;
2362 ldap_attributetype_free(at);
2367 *code = LDAP_SCHERR_UNEXPTOKEN;
2370 ldap_attributetype_free(at);
2377 ldap_objectclass_free(LDAPObjectClass * oc)
2379 LDAP_FREE(oc->oc_oid);
2380 if (oc->oc_names) LDAP_VFREE(oc->oc_names);
2381 if (oc->oc_desc) LDAP_FREE(oc->oc_desc);
2382 if (oc->oc_sup_oids) LDAP_VFREE(oc->oc_sup_oids);
2383 if (oc->oc_at_oids_must) LDAP_VFREE(oc->oc_at_oids_must);
2384 if (oc->oc_at_oids_may) LDAP_VFREE(oc->oc_at_oids_may);
2385 free_extensions(oc->oc_extensions);
2390 ldap_str2objectclass( LDAP_CONST char * s,
2392 LDAP_CONST char ** errp,
2393 LDAP_CONST unsigned flags )
2396 const char * ss = s;
2400 int seen_obsolete = 0;
2405 LDAPObjectClass * oc;
2407 const char * savepos;
2410 *code = LDAP_SCHERR_EMPTY;
2416 oc = LDAP_CALLOC(1,sizeof(LDAPObjectClass));
2419 *code = LDAP_SCHERR_OUTOFMEM;
2422 oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
2424 kind = get_token(&ss,&sval);
2425 if ( kind != TK_LEFTPAREN ) {
2426 *code = LDAP_SCHERR_NOLEFTPAREN;
2428 ldap_objectclass_free(oc);
2433 * Definitions MUST begin with an OID in the numericoid format.
2434 * However, this routine is used by clients to parse the response
2435 * from servers and very well known servers will provide an OID
2436 * in the wrong format or even no OID at all. We do our best to
2437 * extract info from those servers.
2441 oc->oc_oid = ldap_int_parse_numericoid(&ss,code,0);
2442 if ( !oc->oc_oid ) {
2443 if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) {
2446 kind = get_token(&ss,&sval);
2447 if ( kind == TK_BAREWORD ) {
2448 if ( !strcasecmp(sval, "NAME") ||
2449 !strcasecmp(sval, "DESC") ||
2450 !strcasecmp(sval, "OBSOLETE") ||
2451 !strcasecmp(sval, "SUP") ||
2452 !strcasecmp(sval, "ABSTRACT") ||
2453 !strcasecmp(sval, "STRUCTURAL") ||
2454 !strcasecmp(sval, "AUXILIARY") ||
2455 !strcasecmp(sval, "MUST") ||
2456 !strcasecmp(sval, "MAY") ||
2457 !strncasecmp(sval, "X-", 2) ) {
2458 /* Missing OID, backtrack */
2461 LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2462 /* Non-numerical OID, ignore */
2463 int len = ss-savepos;
2464 oc->oc_oid = LDAP_MALLOC(len+1);
2465 strncpy(oc->oc_oid, savepos, len);
2466 oc->oc_oid[len] = 0;
2473 ldap_objectclass_free(oc);
2480 * Beyond this point we will be liberal an accept the items
2484 kind = get_token(&ss,&sval);
2487 *code = LDAP_SCHERR_NORIGHTPAREN;
2489 ldap_objectclass_free(oc);
2494 if ( !strcasecmp(sval,"NAME") ) {
2497 *code = LDAP_SCHERR_DUPOPT;
2499 ldap_objectclass_free(oc);
2503 oc->oc_names = parse_qdescrs(&ss,code);
2504 if ( !oc->oc_names ) {
2505 if ( *code != LDAP_SCHERR_OUTOFMEM )
2506 *code = LDAP_SCHERR_BADNAME;
2508 ldap_objectclass_free(oc);
2511 } else if ( !strcasecmp(sval,"DESC") ) {
2514 *code = LDAP_SCHERR_DUPOPT;
2516 ldap_objectclass_free(oc);
2521 kind = get_token(&ss,&sval);
2522 if ( kind != TK_QDSTRING ) {
2523 *code = LDAP_SCHERR_UNEXPTOKEN;
2526 ldap_objectclass_free(oc);
2531 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
2533 if ( seen_obsolete ) {
2534 *code = LDAP_SCHERR_DUPOPT;
2536 ldap_objectclass_free(oc);
2540 oc->oc_obsolete = LDAP_SCHEMA_YES;
2542 } else if ( !strcasecmp(sval,"SUP") ) {
2545 *code = LDAP_SCHERR_DUPOPT;
2547 ldap_objectclass_free(oc);
2551 oc->oc_sup_oids = parse_oids(&ss,
2554 if ( !oc->oc_sup_oids && *code != LDAP_SUCCESS ) {
2556 ldap_objectclass_free(oc);
2560 } else if ( !strcasecmp(sval,"ABSTRACT") ) {
2563 *code = LDAP_SCHERR_DUPOPT;
2565 ldap_objectclass_free(oc);
2569 oc->oc_kind = LDAP_SCHEMA_ABSTRACT;
2571 } else if ( !strcasecmp(sval,"STRUCTURAL") ) {
2574 *code = LDAP_SCHERR_DUPOPT;
2576 ldap_objectclass_free(oc);
2580 oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
2582 } else if ( !strcasecmp(sval,"AUXILIARY") ) {
2585 *code = LDAP_SCHERR_DUPOPT;
2587 ldap_objectclass_free(oc);
2591 oc->oc_kind = LDAP_SCHEMA_AUXILIARY;
2593 } else if ( !strcasecmp(sval,"MUST") ) {
2596 *code = LDAP_SCHERR_DUPOPT;
2598 ldap_objectclass_free(oc);
2602 oc->oc_at_oids_must = parse_oids(&ss,code,0);
2603 if ( !oc->oc_at_oids_must && *code != LDAP_SUCCESS ) {
2605 ldap_objectclass_free(oc);
2610 } else if ( !strcasecmp(sval,"MAY") ) {
2613 *code = LDAP_SCHERR_DUPOPT;
2615 ldap_objectclass_free(oc);
2619 oc->oc_at_oids_may = parse_oids(&ss,code,0);
2620 if ( !oc->oc_at_oids_may && *code != LDAP_SUCCESS ) {
2622 ldap_objectclass_free(oc);
2627 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
2628 /* Should be parse_qdstrings */
2629 ext_vals = parse_qdescrs(&ss, code);
2633 ldap_objectclass_free(oc);
2636 if ( add_extension(&oc->oc_extensions,
2638 *code = LDAP_SCHERR_OUTOFMEM;
2641 ldap_objectclass_free(oc);
2645 *code = LDAP_SCHERR_UNEXPTOKEN;
2648 ldap_objectclass_free(oc);
2653 *code = LDAP_SCHERR_UNEXPTOKEN;
2656 ldap_objectclass_free(oc);
2663 ldap_contentrule_free(LDAPContentRule * cr)
2665 LDAP_FREE(cr->cr_oid);
2666 if (cr->cr_names) LDAP_VFREE(cr->cr_names);
2667 if (cr->cr_desc) LDAP_FREE(cr->cr_desc);
2668 if (cr->cr_oc_oids_aux) LDAP_VFREE(cr->cr_oc_oids_aux);
2669 if (cr->cr_at_oids_must) LDAP_VFREE(cr->cr_at_oids_must);
2670 if (cr->cr_at_oids_may) LDAP_VFREE(cr->cr_at_oids_may);
2671 if (cr->cr_at_oids_not) LDAP_VFREE(cr->cr_at_oids_not);
2672 free_extensions(cr->cr_extensions);
2677 ldap_str2contentrule( LDAP_CONST char * s,
2679 LDAP_CONST char ** errp,
2680 LDAP_CONST unsigned flags )
2683 const char * ss = s;
2687 int seen_obsolete = 0;
2692 LDAPContentRule * cr;
2694 const char * savepos;
2697 *code = LDAP_SCHERR_EMPTY;
2703 cr = LDAP_CALLOC(1,sizeof(LDAPContentRule));
2706 *code = LDAP_SCHERR_OUTOFMEM;
2710 kind = get_token(&ss,&sval);
2711 if ( kind != TK_LEFTPAREN ) {
2712 *code = LDAP_SCHERR_NOLEFTPAREN;
2714 ldap_contentrule_free(cr);
2719 * Definitions MUST begin with an OID in the numericoid format.
2723 cr->cr_oid = ldap_int_parse_numericoid(&ss,code,0);
2724 if ( !cr->cr_oid ) {
2725 if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) {
2728 kind = get_token(&ss,&sval);
2729 if ( kind == TK_BAREWORD ) {
2730 if ( !strcasecmp(sval, "NAME") ||
2731 !strcasecmp(sval, "DESC") ||
2732 !strcasecmp(sval, "OBSOLETE") ||
2733 !strcasecmp(sval, "AUX") ||
2734 !strcasecmp(sval, "MUST") ||
2735 !strcasecmp(sval, "MAY") ||
2736 !strcasecmp(sval, "NOT") ||
2737 !strncasecmp(sval, "X-", 2) ) {
2738 /* Missing OID, backtrack */
2741 LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2742 /* Non-numerical OID, ignore */
2743 int len = ss-savepos;
2744 cr->cr_oid = LDAP_MALLOC(len+1);
2745 strncpy(cr->cr_oid, savepos, len);
2746 cr->cr_oid[len] = 0;
2752 ldap_contentrule_free(cr);
2759 * Beyond this point we will be liberal an accept the items
2763 kind = get_token(&ss,&sval);
2766 *code = LDAP_SCHERR_NORIGHTPAREN;
2768 ldap_contentrule_free(cr);
2773 if ( !strcasecmp(sval,"NAME") ) {
2776 *code = LDAP_SCHERR_DUPOPT;
2778 ldap_contentrule_free(cr);
2782 cr->cr_names = parse_qdescrs(&ss,code);
2783 if ( !cr->cr_names ) {
2784 if ( *code != LDAP_SCHERR_OUTOFMEM )
2785 *code = LDAP_SCHERR_BADNAME;
2787 ldap_contentrule_free(cr);
2790 } else if ( !strcasecmp(sval,"DESC") ) {
2793 *code = LDAP_SCHERR_DUPOPT;
2795 ldap_contentrule_free(cr);
2800 kind = get_token(&ss,&sval);
2801 if ( kind != TK_QDSTRING ) {
2802 *code = LDAP_SCHERR_UNEXPTOKEN;
2805 ldap_contentrule_free(cr);
2810 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
2812 if ( seen_obsolete ) {
2813 *code = LDAP_SCHERR_DUPOPT;
2815 ldap_contentrule_free(cr);
2819 cr->cr_obsolete = LDAP_SCHEMA_YES;
2821 } else if ( !strcasecmp(sval,"AUX") ) {
2824 *code = LDAP_SCHERR_DUPOPT;
2826 ldap_contentrule_free(cr);
2830 cr->cr_oc_oids_aux = parse_oids(&ss,code,0);
2831 if ( !cr->cr_oc_oids_aux ) {
2833 ldap_contentrule_free(cr);
2837 } else if ( !strcasecmp(sval,"MUST") ) {
2840 *code = LDAP_SCHERR_DUPOPT;
2842 ldap_contentrule_free(cr);
2846 cr->cr_at_oids_must = parse_oids(&ss,code,0);
2847 if ( !cr->cr_at_oids_must && *code != LDAP_SUCCESS ) {
2849 ldap_contentrule_free(cr);
2853 } else if ( !strcasecmp(sval,"MAY") ) {
2856 *code = LDAP_SCHERR_DUPOPT;
2858 ldap_contentrule_free(cr);
2862 cr->cr_at_oids_may = parse_oids(&ss,code,0);
2863 if ( !cr->cr_at_oids_may && *code != LDAP_SUCCESS ) {
2865 ldap_contentrule_free(cr);
2869 } else if ( !strcasecmp(sval,"NOT") ) {
2872 *code = LDAP_SCHERR_DUPOPT;
2874 ldap_contentrule_free(cr);
2878 cr->cr_at_oids_not = parse_oids(&ss,code,0);
2879 if ( !cr->cr_at_oids_not && *code != LDAP_SUCCESS ) {
2881 ldap_contentrule_free(cr);
2885 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
2886 /* Should be parse_qdstrings */
2887 ext_vals = parse_qdescrs(&ss, code);
2890 ldap_contentrule_free(cr);
2893 if ( add_extension(&cr->cr_extensions,
2895 *code = LDAP_SCHERR_OUTOFMEM;
2898 ldap_contentrule_free(cr);
2902 *code = LDAP_SCHERR_UNEXPTOKEN;
2905 ldap_contentrule_free(cr);
2910 *code = LDAP_SCHERR_UNEXPTOKEN;
2913 ldap_contentrule_free(cr);
2920 ldap_structurerule_free(LDAPStructureRule * sr)
2922 if (sr->sr_names) LDAP_VFREE(sr->sr_names);
2923 if (sr->sr_desc) LDAP_FREE(sr->sr_desc);
2924 if (sr->sr_nameform) LDAP_FREE(sr->sr_nameform);
2925 if (sr->sr_sup_ruleids) LDAP_FREE(sr->sr_sup_ruleids);
2926 free_extensions(sr->sr_extensions);
2931 ldap_str2structurerule( LDAP_CONST char * s,
2933 LDAP_CONST char ** errp,
2934 LDAP_CONST unsigned flags )
2938 const char * ss = s;
2942 int seen_obsolete = 0;
2943 int seen_nameform = 0;
2944 LDAPStructureRule * sr;
2946 const char * savepos;
2949 *code = LDAP_SCHERR_EMPTY;
2955 sr = LDAP_CALLOC(1,sizeof(LDAPStructureRule));
2958 *code = LDAP_SCHERR_OUTOFMEM;
2962 kind = get_token(&ss,&sval);
2963 if ( kind != TK_LEFTPAREN ) {
2964 *code = LDAP_SCHERR_NOLEFTPAREN;
2966 ldap_structurerule_free(sr);
2971 * Definitions MUST begin with a ruleid.
2975 ret = ldap_int_parse_ruleid(&ss,code,0,&sr->sr_ruleid);
2978 ldap_structurerule_free(sr);
2984 * Beyond this point we will be liberal an accept the items
2988 kind = get_token(&ss,&sval);
2991 *code = LDAP_SCHERR_NORIGHTPAREN;
2993 ldap_structurerule_free(sr);
2996 if( !seen_nameform ) {
2997 *code = LDAP_SCHERR_MISSING;
2998 ldap_structurerule_free(sr);
3003 if ( !strcasecmp(sval,"NAME") ) {
3006 *code = LDAP_SCHERR_DUPOPT;
3008 ldap_structurerule_free(sr);
3012 sr->sr_names = parse_qdescrs(&ss,code);
3013 if ( !sr->sr_names ) {
3014 if ( *code != LDAP_SCHERR_OUTOFMEM )
3015 *code = LDAP_SCHERR_BADNAME;
3017 ldap_structurerule_free(sr);
3020 } else if ( !strcasecmp(sval,"DESC") ) {
3023 *code = LDAP_SCHERR_DUPOPT;
3025 ldap_structurerule_free(sr);
3030 kind = get_token(&ss,&sval);
3031 if ( kind != TK_QDSTRING ) {
3032 *code = LDAP_SCHERR_UNEXPTOKEN;
3035 ldap_structurerule_free(sr);
3040 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
3042 if ( seen_obsolete ) {
3043 *code = LDAP_SCHERR_DUPOPT;
3045 ldap_structurerule_free(sr);
3049 sr->sr_obsolete = LDAP_SCHEMA_YES;
3051 } else if ( !strcasecmp(sval,"FORM") ) {
3053 if ( seen_nameform ) {
3054 *code = LDAP_SCHERR_DUPOPT;
3056 ldap_structurerule_free(sr);
3060 sr->sr_nameform = parse_woid(&ss,code);
3061 if ( !sr->sr_nameform ) {
3063 ldap_structurerule_free(sr);
3067 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
3068 /* Should be parse_qdstrings */
3069 ext_vals = parse_qdescrs(&ss, code);
3072 ldap_structurerule_free(sr);
3075 if ( add_extension(&sr->sr_extensions,
3077 *code = LDAP_SCHERR_OUTOFMEM;
3080 ldap_structurerule_free(sr);
3084 *code = LDAP_SCHERR_UNEXPTOKEN;
3087 ldap_structurerule_free(sr);
3092 *code = LDAP_SCHERR_UNEXPTOKEN;
3095 ldap_structurerule_free(sr);
3102 ldap_nameform_free(LDAPNameForm * nf)
3104 LDAP_FREE(nf->nf_oid);
3105 if (nf->nf_names) LDAP_VFREE(nf->nf_names);
3106 if (nf->nf_desc) LDAP_FREE(nf->nf_desc);
3107 if (nf->nf_objectclass) LDAP_FREE(nf->nf_objectclass);
3108 if (nf->nf_at_oids_must) LDAP_VFREE(nf->nf_at_oids_must);
3109 if (nf->nf_at_oids_may) LDAP_VFREE(nf->nf_at_oids_may);
3110 free_extensions(nf->nf_extensions);
3115 ldap_str2nameform( LDAP_CONST char * s,
3117 LDAP_CONST char ** errp,
3118 LDAP_CONST unsigned flags )
3121 const char * ss = s;
3125 int seen_obsolete = 0;
3131 const char * savepos;
3134 *code = LDAP_SCHERR_EMPTY;
3140 nf = LDAP_CALLOC(1,sizeof(LDAPNameForm));
3143 *code = LDAP_SCHERR_OUTOFMEM;
3147 kind = get_token(&ss,&sval);
3148 if ( kind != TK_LEFTPAREN ) {
3149 *code = LDAP_SCHERR_NOLEFTPAREN;
3151 ldap_nameform_free(nf);
3156 * Definitions MUST begin with an OID in the numericoid format.
3157 * However, this routine is used by clients to parse the response
3158 * from servers and very well known servers will provide an OID
3159 * in the wrong format or even no OID at all. We do our best to
3160 * extract info from those servers.
3164 nf->nf_oid = ldap_int_parse_numericoid(&ss,code,0);
3165 if ( !nf->nf_oid ) {
3167 ldap_nameform_free(nf);
3173 * Beyond this point we will be liberal an accept the items
3177 kind = get_token(&ss,&sval);
3180 *code = LDAP_SCHERR_NORIGHTPAREN;
3182 ldap_nameform_free(nf);
3185 if( !seen_class || !seen_must ) {
3186 *code = LDAP_SCHERR_MISSING;
3187 ldap_nameform_free(nf);
3192 if ( !strcasecmp(sval,"NAME") ) {
3195 *code = LDAP_SCHERR_DUPOPT;
3197 ldap_nameform_free(nf);
3201 nf->nf_names = parse_qdescrs(&ss,code);
3202 if ( !nf->nf_names ) {
3203 if ( *code != LDAP_SCHERR_OUTOFMEM )
3204 *code = LDAP_SCHERR_BADNAME;
3206 ldap_nameform_free(nf);
3209 } else if ( !strcasecmp(sval,"DESC") ) {
3212 *code = LDAP_SCHERR_DUPOPT;
3214 ldap_nameform_free(nf);
3219 kind = get_token(&ss,&sval);
3220 if ( kind != TK_QDSTRING ) {
3221 *code = LDAP_SCHERR_UNEXPTOKEN;
3224 ldap_nameform_free(nf);
3229 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
3231 if ( seen_obsolete ) {
3232 *code = LDAP_SCHERR_DUPOPT;
3234 ldap_nameform_free(nf);
3238 nf->nf_obsolete = LDAP_SCHEMA_YES;
3240 } else if ( !strcasecmp(sval,"OC") ) {
3243 *code = LDAP_SCHERR_DUPOPT;
3245 ldap_nameform_free(nf);
3249 nf->nf_objectclass = parse_woid(&ss,code);
3250 if ( !nf->nf_objectclass ) {
3252 ldap_nameform_free(nf);
3255 } else if ( !strcasecmp(sval,"MUST") ) {
3258 *code = LDAP_SCHERR_DUPOPT;
3260 ldap_nameform_free(nf);
3264 nf->nf_at_oids_must = parse_oids(&ss,code,0);
3265 if ( !nf->nf_at_oids_must && *code != LDAP_SUCCESS ) {
3267 ldap_nameform_free(nf);
3271 } else if ( !strcasecmp(sval,"MAY") ) {
3274 *code = LDAP_SCHERR_DUPOPT;
3276 ldap_nameform_free(nf);
3280 nf->nf_at_oids_may = parse_oids(&ss,code,0);
3281 if ( !nf->nf_at_oids_may && *code != LDAP_SUCCESS ) {
3283 ldap_nameform_free(nf);
3287 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
3288 /* Should be parse_qdstrings */
3289 ext_vals = parse_qdescrs(&ss, code);
3292 ldap_nameform_free(nf);
3295 if ( add_extension(&nf->nf_extensions,
3297 *code = LDAP_SCHERR_OUTOFMEM;
3300 ldap_nameform_free(nf);
3304 *code = LDAP_SCHERR_UNEXPTOKEN;
3307 ldap_nameform_free(nf);
3312 *code = LDAP_SCHERR_UNEXPTOKEN;
3315 ldap_nameform_free(nf);
3321 static char *const err2text[] = {
3323 N_("Out of memory"),
3324 N_("Unexpected token"),
3325 N_("Missing opening parenthesis"),
3326 N_("Missing closing parenthesis"),
3327 N_("Expecting digit"),
3328 N_("Expecting a name"),
3329 N_("Bad description"),
3330 N_("Bad superiors"),
3331 N_("Duplicate option"),
3332 N_("Unexpected end of data"),
3333 N_("Missing required field"),
3334 N_("Out of order field")
3338 ldap_scherr2str(int code)
3340 if ( code < 0 || code >= (int)(sizeof(err2text)/sizeof(char *)) ) {
3341 return _("Unknown error");
3343 return _(err2text[code]);