2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2006 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>
34 choose_name( char *names[], const char *fallback )
36 return (names != NULL && names[0] != NULL) ? names[0] : fallback;
40 ldap_syntax2name( LDAPSyntax * syn )
42 return( syn->syn_oid );
46 ldap_matchingrule2name( LDAPMatchingRule * mr )
48 return( choose_name( mr->mr_names, mr->mr_oid ) );
52 ldap_matchingruleuse2name( LDAPMatchingRuleUse * mru )
54 return( choose_name( mru->mru_names, mru->mru_oid ) );
58 ldap_attributetype2name( LDAPAttributeType * at )
60 return( choose_name( at->at_names, at->at_oid ) );
64 ldap_objectclass2name( LDAPObjectClass * oc )
66 return( choose_name( oc->oc_names, oc->oc_oid ) );
70 ldap_contentrule2name( LDAPContentRule * cr )
72 return( choose_name( cr->cr_names, cr->cr_oid ) );
76 ldap_nameform2name( LDAPNameForm * nf )
78 return( choose_name( nf->nf_names, nf->nf_oid ) );
82 ldap_structurerule2name( LDAPStructureRule * sr )
84 return( choose_name( sr->sr_names, NULL ) );
88 * When pretty printing the entities we will be appending to a buffer.
89 * Since checking for overflow, realloc'ing and checking if no error
90 * is extremely boring, we will use a protection layer that will let
91 * us blissfully ignore the error until the end. This layer is
92 * implemented with the help of the next type.
95 typedef struct safe_string {
103 new_safe_string(int size)
107 ss = LDAP_MALLOC(sizeof(safe_string));
111 ss->val = LDAP_MALLOC(size);
125 safe_string_free(safe_string * ss)
135 safe_string_val(safe_string * ss)
137 ss->val[ss->pos] = '\0';
143 safe_strdup(safe_string * ss)
145 char *ret = LDAP_MALLOC(ss->pos+1);
148 AC_MEMCPY(ret, ss->val, ss->pos);
154 append_to_safe_string(safe_string * ss, char * s)
160 * Some runaway process is trying to append to a string that
161 * overflowed and we could not extend.
166 /* We always make sure there is at least one position available */
167 if ( ss->pos + l >= ss->size-1 ) {
169 if ( ss->pos + l >= ss->size-1 ) {
170 ss->size = ss->pos + l + 1;
173 temp = LDAP_REALLOC(ss->val, ss->size);
175 /* Trouble, out of memory */
181 strncpy(&ss->val[ss->pos], s, l);
183 if ( ss->pos > 0 && LDAP_SPACE(ss->val[ss->pos-1]) )
192 print_literal(safe_string *ss, char *s)
194 return(append_to_safe_string(ss,s));
198 print_whsp(safe_string *ss)
201 return(append_to_safe_string(ss,""));
203 return(append_to_safe_string(ss," "));
207 print_numericoid(safe_string *ss, char *s)
210 return(append_to_safe_string(ss,s));
212 return(append_to_safe_string(ss,""));
215 /* This one is identical to print_qdescr */
217 print_qdstring(safe_string *ss, char *s)
220 print_literal(ss,"'");
221 append_to_safe_string(ss,s);
222 print_literal(ss,"'");
223 return(print_whsp(ss));
227 print_qdescr(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_qdescrlist(safe_string *ss, char **sa)
242 for (sp=sa; *sp; sp++) {
243 ret = print_qdescr(ss,*sp);
245 /* If the list was empty, we return zero that is potentially
246 * incorrect, but since we will be still appending things, the
247 * overflow will be detected later. Maybe FIX.
253 print_qdescrs(safe_string *ss, char **sa)
255 /* The only way to represent an empty list is as a qdescrlist
256 * so, if the list is empty we treat it as a long list.
257 * Really, this is what the syntax mandates. We should not
258 * be here if the list was empty, but if it happens, a label
259 * has already been output and we cannot undo it.
261 if ( !sa[0] || ( sa[0] && sa[1] ) ) {
263 print_literal(ss,"("/*)*/);
264 print_qdescrlist(ss,sa);
265 print_literal(ss,/*(*/")");
266 return(print_whsp(ss));
268 return(print_qdescr(ss,*sa));
273 print_woid(safe_string *ss, char *s)
276 append_to_safe_string(ss,s);
277 return print_whsp(ss);
281 print_oidlist(safe_string *ss, char **sa)
285 for (sp=sa; *(sp+1); sp++) {
287 print_literal(ss,"$");
289 return(print_woid(ss,*sp));
293 print_oids(safe_string *ss, char **sa)
295 if ( sa[0] && sa[1] ) {
296 print_literal(ss,"("/*)*/);
297 print_oidlist(ss,sa);
299 return(print_literal(ss,/*(*/")"));
301 return(print_woid(ss,*sa));
306 print_noidlen(safe_string *ss, char *s, int l)
311 ret = print_numericoid(ss,s);
313 snprintf(buf, sizeof buf, "{%d}",l);
314 ret = print_literal(ss,buf);
320 print_ruleid(safe_string *ss, int rid)
323 snprintf(buf, sizeof buf, "%d", rid);
324 return print_literal(ss,buf);
328 print_ruleids(safe_string *ss, int n, int *rids)
333 print_ruleid(ss,rids[0]);
334 return print_whsp(ss);
336 print_literal(ss,"("/*)*/);
337 for( i=0; i<n; i++ ) {
339 print_ruleid(ss,rids[i]);
342 return print_literal(ss,/*(*/")");
348 print_extensions(safe_string *ss, LDAPSchemaExtensionItem **extensions)
350 LDAPSchemaExtensionItem **ext;
354 for ( ext = extensions; *ext != NULL; ext++ ) {
355 print_literal(ss, (*ext)->lsei_name);
357 /* Should be print_qdstrings */
358 print_qdescrs(ss, (*ext)->lsei_values);
367 ldap_syntax2str( LDAPSyntax * syn )
370 if (ldap_syntax2bv( syn, &bv ))
377 ldap_syntax2bv( LDAPSyntax * syn, struct berval *bv )
381 ss = new_safe_string(256);
385 print_literal(ss,"("/*)*/);
388 print_numericoid(ss, syn->syn_oid);
391 if ( syn->syn_desc ) {
392 print_literal(ss,"DESC");
393 print_qdstring(ss,syn->syn_desc);
398 print_extensions(ss, syn->syn_extensions);
400 print_literal(ss,/*(*/ ")");
402 bv->bv_val = safe_strdup(ss);
403 bv->bv_len = ss->pos;
404 safe_string_free(ss);
409 ldap_matchingrule2str( LDAPMatchingRule * mr )
412 if (ldap_matchingrule2bv( mr, &bv ))
419 ldap_matchingrule2bv( LDAPMatchingRule * mr, struct berval *bv )
423 ss = new_safe_string(256);
427 print_literal(ss,"(" /*)*/);
430 print_numericoid(ss, mr->mr_oid);
433 if ( mr->mr_names ) {
434 print_literal(ss,"NAME");
435 print_qdescrs(ss,mr->mr_names);
439 print_literal(ss,"DESC");
440 print_qdstring(ss,mr->mr_desc);
443 if ( mr->mr_obsolete ) {
444 print_literal(ss, "OBSOLETE");
448 if ( mr->mr_syntax_oid ) {
449 print_literal(ss,"SYNTAX");
451 print_literal(ss, mr->mr_syntax_oid);
457 print_extensions(ss, mr->mr_extensions);
459 print_literal(ss,/*(*/")");
461 bv->bv_val = safe_strdup(ss);
462 bv->bv_len = ss->pos;
463 safe_string_free(ss);
468 ldap_matchingruleuse2str( LDAPMatchingRuleUse * mru )
471 if (ldap_matchingruleuse2bv( mru, &bv ))
478 ldap_matchingruleuse2bv( LDAPMatchingRuleUse * mru, struct berval *bv )
482 ss = new_safe_string(256);
486 print_literal(ss,"(" /*)*/);
489 print_numericoid(ss, mru->mru_oid);
492 if ( mru->mru_names ) {
493 print_literal(ss,"NAME");
494 print_qdescrs(ss,mru->mru_names);
497 if ( mru->mru_desc ) {
498 print_literal(ss,"DESC");
499 print_qdstring(ss,mru->mru_desc);
502 if ( mru->mru_obsolete ) {
503 print_literal(ss, "OBSOLETE");
507 if ( mru->mru_applies_oids ) {
508 print_literal(ss,"APPLIES");
510 print_oids(ss, mru->mru_applies_oids);
516 print_extensions(ss, mru->mru_extensions);
518 print_literal(ss,/*(*/")");
520 bv->bv_val = safe_strdup(ss);
521 bv->bv_len = ss->pos;
522 safe_string_free(ss);
527 ldap_objectclass2str( LDAPObjectClass * oc )
530 if (ldap_objectclass2bv( oc, &bv ))
537 ldap_objectclass2bv( LDAPObjectClass * oc, struct berval *bv )
541 ss = new_safe_string(256);
545 print_literal(ss,"("/*)*/);
548 print_numericoid(ss, oc->oc_oid);
551 if ( oc->oc_names ) {
552 print_literal(ss,"NAME");
553 print_qdescrs(ss,oc->oc_names);
557 print_literal(ss,"DESC");
558 print_qdstring(ss,oc->oc_desc);
561 if ( oc->oc_obsolete ) {
562 print_literal(ss, "OBSOLETE");
566 if ( oc->oc_sup_oids ) {
567 print_literal(ss,"SUP");
569 print_oids(ss,oc->oc_sup_oids);
573 switch (oc->oc_kind) {
574 case LDAP_SCHEMA_ABSTRACT:
575 print_literal(ss,"ABSTRACT");
577 case LDAP_SCHEMA_STRUCTURAL:
578 print_literal(ss,"STRUCTURAL");
580 case LDAP_SCHEMA_AUXILIARY:
581 print_literal(ss,"AUXILIARY");
584 print_literal(ss,"KIND-UNKNOWN");
589 if ( oc->oc_at_oids_must ) {
590 print_literal(ss,"MUST");
592 print_oids(ss,oc->oc_at_oids_must);
596 if ( oc->oc_at_oids_may ) {
597 print_literal(ss,"MAY");
599 print_oids(ss,oc->oc_at_oids_may);
605 print_extensions(ss, oc->oc_extensions);
607 print_literal(ss, /*(*/")");
609 bv->bv_val = safe_strdup(ss);
610 bv->bv_len = ss->pos;
611 safe_string_free(ss);
616 ldap_contentrule2str( LDAPContentRule * cr )
619 if (ldap_contentrule2bv( cr, &bv ))
626 ldap_contentrule2bv( LDAPContentRule * cr, struct berval *bv )
630 ss = new_safe_string(256);
634 print_literal(ss,"("/*)*/);
637 print_numericoid(ss, cr->cr_oid);
640 if ( cr->cr_names ) {
641 print_literal(ss,"NAME");
642 print_qdescrs(ss,cr->cr_names);
646 print_literal(ss,"DESC");
647 print_qdstring(ss,cr->cr_desc);
650 if ( cr->cr_obsolete ) {
651 print_literal(ss, "OBSOLETE");
655 if ( cr->cr_oc_oids_aux ) {
656 print_literal(ss,"AUX");
658 print_oids(ss,cr->cr_oc_oids_aux);
662 if ( cr->cr_at_oids_must ) {
663 print_literal(ss,"MUST");
665 print_oids(ss,cr->cr_at_oids_must);
669 if ( cr->cr_at_oids_may ) {
670 print_literal(ss,"MAY");
672 print_oids(ss,cr->cr_at_oids_may);
676 if ( cr->cr_at_oids_not ) {
677 print_literal(ss,"NOT");
679 print_oids(ss,cr->cr_at_oids_not);
684 print_extensions(ss, cr->cr_extensions);
686 print_literal(ss, /*(*/")");
688 bv->bv_val = safe_strdup(ss);
689 bv->bv_len = ss->pos;
690 safe_string_free(ss);
695 ldap_structurerule2str( LDAPStructureRule * sr )
698 if (ldap_structurerule2bv( sr, &bv ))
705 ldap_structurerule2bv( LDAPStructureRule * sr, struct berval *bv )
709 ss = new_safe_string(256);
713 print_literal(ss,"("/*)*/);
716 print_ruleid(ss, sr->sr_ruleid);
719 if ( sr->sr_names ) {
720 print_literal(ss,"NAME");
721 print_qdescrs(ss,sr->sr_names);
725 print_literal(ss,"DESC");
726 print_qdstring(ss,sr->sr_desc);
729 if ( sr->sr_obsolete ) {
730 print_literal(ss, "OBSOLETE");
734 print_literal(ss,"FORM");
736 print_woid(ss,sr->sr_nameform);
739 if ( sr->sr_nsup_ruleids ) {
740 print_literal(ss,"SUP");
742 print_ruleids(ss,sr->sr_nsup_ruleids,sr->sr_sup_ruleids);
747 print_extensions(ss, sr->sr_extensions);
749 print_literal(ss, /*(*/")");
751 bv->bv_val = safe_strdup(ss);
752 bv->bv_len = ss->pos;
753 safe_string_free(ss);
759 ldap_nameform2str( LDAPNameForm * nf )
762 if (ldap_nameform2bv( nf, &bv ))
769 ldap_nameform2bv( LDAPNameForm * nf, struct berval *bv )
773 ss = new_safe_string(256);
777 print_literal(ss,"("/*)*/);
780 print_numericoid(ss, nf->nf_oid);
783 if ( nf->nf_names ) {
784 print_literal(ss,"NAME");
785 print_qdescrs(ss,nf->nf_names);
789 print_literal(ss,"DESC");
790 print_qdstring(ss,nf->nf_desc);
793 if ( nf->nf_obsolete ) {
794 print_literal(ss, "OBSOLETE");
798 print_literal(ss,"OC");
800 print_woid(ss,nf->nf_objectclass);
803 print_literal(ss,"MUST");
805 print_oids(ss,nf->nf_at_oids_must);
809 if ( nf->nf_at_oids_may ) {
810 print_literal(ss,"MAY");
812 print_oids(ss,nf->nf_at_oids_may);
817 print_extensions(ss, nf->nf_extensions);
819 print_literal(ss, /*(*/")");
821 bv->bv_val = safe_strdup(ss);
822 bv->bv_len = ss->pos;
823 safe_string_free(ss);
828 ldap_attributetype2str( LDAPAttributeType * at )
831 if (ldap_attributetype2bv( at, &bv ))
838 ldap_attributetype2bv( LDAPAttributeType * at, struct berval *bv )
842 ss = new_safe_string(256);
846 print_literal(ss,"("/*)*/);
849 print_numericoid(ss, at->at_oid);
852 if ( at->at_names ) {
853 print_literal(ss,"NAME");
854 print_qdescrs(ss,at->at_names);
858 print_literal(ss,"DESC");
859 print_qdstring(ss,at->at_desc);
862 if ( at->at_obsolete ) {
863 print_literal(ss, "OBSOLETE");
867 if ( at->at_sup_oid ) {
868 print_literal(ss,"SUP");
869 print_woid(ss,at->at_sup_oid);
872 if ( at->at_equality_oid ) {
873 print_literal(ss,"EQUALITY");
874 print_woid(ss,at->at_equality_oid);
877 if ( at->at_ordering_oid ) {
878 print_literal(ss,"ORDERING");
879 print_woid(ss,at->at_ordering_oid);
882 if ( at->at_substr_oid ) {
883 print_literal(ss,"SUBSTR");
884 print_woid(ss,at->at_substr_oid);
887 if ( at->at_syntax_oid ) {
888 print_literal(ss,"SYNTAX");
890 print_noidlen(ss,at->at_syntax_oid,at->at_syntax_len);
894 if ( at->at_single_value == LDAP_SCHEMA_YES ) {
895 print_literal(ss,"SINGLE-VALUE");
899 if ( at->at_collective == LDAP_SCHEMA_YES ) {
900 print_literal(ss,"COLLECTIVE");
904 if ( at->at_no_user_mod == LDAP_SCHEMA_YES ) {
905 print_literal(ss,"NO-USER-MODIFICATION");
909 if ( at->at_usage != LDAP_SCHEMA_USER_APPLICATIONS ) {
910 print_literal(ss,"USAGE");
912 switch (at->at_usage) {
913 case LDAP_SCHEMA_DIRECTORY_OPERATION:
914 print_literal(ss,"directoryOperation");
916 case LDAP_SCHEMA_DISTRIBUTED_OPERATION:
917 print_literal(ss,"distributedOperation");
919 case LDAP_SCHEMA_DSA_OPERATION:
920 print_literal(ss,"dSAOperation");
923 print_literal(ss,"UNKNOWN");
930 print_extensions(ss, at->at_extensions);
932 print_literal(ss,/*(*/")");
934 bv->bv_val = safe_strdup(ss);
935 bv->bv_len = ss->pos;
936 safe_string_free(ss);
941 * Now come the parsers. There is one parser for each entity type:
942 * objectclasses, attributetypes, etc.
944 * Each of them is written as a recursive-descent parser, except that
945 * none of them is really recursive. But the idea is kept: there
946 * is one routine per non-terminal that eithers gobbles lexical tokens
947 * or calls lower-level routines, etc.
949 * The scanner is implemented in the routine get_token. Actually,
950 * get_token is more than a scanner and will return tokens that are
951 * in fact non-terminals in the grammar. So you can see the whole
952 * approach as the combination of a low-level bottom-up recognizer
953 * combined with a scanner and a number of top-down parsers. Or just
954 * consider that the real grammars recognized by the parsers are not
955 * those of the standards. As a matter of fact, our parsers are more
956 * liberal than the spec when there is no ambiguity.
958 * The difference is pretty academic (modulo bugs or incorrect
959 * interpretation of the specs).
972 TK_QDESCR = TK_QDSTRING
976 get_token( const char ** sp, char ** token_val )
994 kind = TK_RIGHTPAREN;
1005 while ( **sp != '\'' && **sp != '\0' )
1007 if ( **sp == '\'' ) {
1009 res = LDAP_MALLOC(q-p+1);
1019 kind = TK_NOENDQUOTE;
1025 while ( !LDAP_SPACE(**sp) &&
1030 /* for suggested minimum upper bound on the number
1031 * of characters <draft-ietf-ldapbis-syntaxes> */
1036 res = LDAP_MALLOC(q-p+1);
1045 /* kind = TK_UNEXPCHAR; */
1052 /* Gobble optional whitespace */
1054 parse_whsp(const char **sp)
1056 while (LDAP_SPACE(**sp))
1061 * General note for all parsers: to guarantee the algorithm halts they
1062 * must always advance the pointer even when an error is found. For
1063 * this one is not that important since an error here is fatal at the
1064 * upper layers, but it is a simple strategy that will not get in
1068 /* Parse a sequence of dot-separated decimal strings */
1070 ldap_int_parse_numericoid(const char **sp, int *code, const int flags)
1073 const char * start = *sp;
1077 /* Netscape puts the SYNTAX value in quotes (incorrectly) */
1078 if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && **sp == '\'' ) {
1083 /* Each iteration of this loop gets one decimal string */
1085 if ( !LDAP_DIGIT(**sp) ) {
1087 * Initial char is not a digit or char after dot is
1090 *code = LDAP_SCHERR_NODIGIT;
1094 while ( LDAP_DIGIT(**sp) )
1098 /* Otherwise, gobble the dot and loop again */
1101 /* Now *sp points at the char past the numericoid. Perfect. */
1103 if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && quoted ) {
1104 if ( **sp == '\'' ) {
1107 *code = LDAP_SCHERR_UNEXPTOKEN;
1111 if (flags & LDAP_SCHEMA_SKIP) {
1112 res = (char *)start;
1114 res = LDAP_MALLOC(len+1);
1116 *code = LDAP_SCHERR_OUTOFMEM;
1119 strncpy(res,start,len);
1125 /* Parse a sequence of dot-separated decimal strings */
1127 ldap_int_parse_ruleid(const char **sp, int *code, const int flags, int *ruleid)
1131 if ( !LDAP_DIGIT(**sp) ) {
1132 *code = LDAP_SCHERR_NODIGIT;
1135 *ruleid = (**sp) - '0';
1138 while ( LDAP_DIGIT(**sp) ) {
1140 *ruleid += (**sp) - '0';
1147 /* Parse a qdescr or a list of them enclosed in () */
1149 parse_qdescrs(const char **sp, int *code)
1159 kind = get_token(sp,&sval);
1160 if ( kind == TK_LEFTPAREN ) {
1161 /* Let's presume there will be at least 2 entries */
1163 res = LDAP_CALLOC(3,sizeof(char *));
1165 *code = LDAP_SCHERR_OUTOFMEM;
1171 kind = get_token(sp,&sval);
1172 if ( kind == TK_RIGHTPAREN )
1174 if ( kind == TK_QDESCR ) {
1175 if ( pos == size-2 ) {
1177 res1 = LDAP_REALLOC(res,size*sizeof(char *));
1181 *code = LDAP_SCHERR_OUTOFMEM;
1192 *code = LDAP_SCHERR_UNEXPTOKEN;
1198 } else if ( kind == TK_QDESCR ) {
1199 res = LDAP_CALLOC(2,sizeof(char *));
1201 *code = LDAP_SCHERR_OUTOFMEM;
1210 *code = LDAP_SCHERR_BADNAME;
1217 parse_woid(const char **sp, int *code)
1223 kind = get_token(sp, &sval);
1224 if ( kind != TK_BAREWORD ) {
1226 *code = LDAP_SCHERR_UNEXPTOKEN;
1233 /* Parse a noidlen */
1235 parse_noidlen(const char **sp, int *code, int *len, int flags)
1238 const char *savepos;
1240 int allow_quoted = ( flags & LDAP_SCHEMA_ALLOW_QUOTED );
1241 int allow_oidmacro = ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO );
1244 /* Netscape puts the SYNTAX value in quotes (incorrectly) */
1245 if ( allow_quoted && **sp == '\'' ) {
1250 sval = ldap_int_parse_numericoid(sp, code, 0);
1254 && *code == LDAP_SCHERR_NODIGIT )
1256 if ( get_token(sp, &sval) != TK_BAREWORD ) {
1257 if ( sval != NULL ) {
1266 if ( **sp == '{' /*}*/ ) {
1269 while ( LDAP_DIGIT(**sp) )
1271 if ( **sp != /*{*/ '}' ) {
1272 *code = LDAP_SCHERR_UNEXPTOKEN;
1278 if ( allow_quoted && quoted ) {
1279 if ( **sp == '\'' ) {
1282 *code = LDAP_SCHERR_UNEXPTOKEN;
1291 * Next routine will accept a qdstring in place of an oid if
1292 * allow_quoted is set. This is necessary to interoperate with
1293 * Netscape Directory server that will improperly quote each oid (at
1294 * least those of the descr kind) in the SUP clause.
1297 /* Parse a woid or a $-separated list of them enclosed in () */
1299 parse_oids(const char **sp, int *code, const int allow_quoted)
1309 * Strictly speaking, doing this here accepts whsp before the
1310 * ( at the begining of an oidlist, but this is harmless. Also,
1311 * we are very liberal in what we accept as an OID. Maybe
1315 kind = get_token(sp,&sval);
1316 if ( kind == TK_LEFTPAREN ) {
1317 /* Let's presume there will be at least 2 entries */
1319 res = LDAP_CALLOC(3,sizeof(char *));
1321 *code = LDAP_SCHERR_OUTOFMEM;
1326 kind = get_token(sp,&sval);
1327 if ( kind == TK_BAREWORD ||
1328 ( allow_quoted && kind == TK_QDSTRING ) ) {
1331 } else if ( kind == TK_RIGHTPAREN ) {
1332 /* FIXME: be liberal in what we accept... */
1337 *code = LDAP_SCHERR_UNEXPTOKEN;
1344 kind = get_token(sp,&sval);
1345 if ( kind == TK_RIGHTPAREN )
1347 if ( kind == TK_DOLLAR ) {
1349 kind = get_token(sp,&sval);
1350 if ( kind == TK_BAREWORD ||
1352 kind == TK_QDSTRING ) ) {
1353 if ( pos == size-2 ) {
1355 res1 = LDAP_REALLOC(res,size*sizeof(char *));
1359 *code = LDAP_SCHERR_OUTOFMEM;
1367 *code = LDAP_SCHERR_UNEXPTOKEN;
1374 *code = LDAP_SCHERR_UNEXPTOKEN;
1382 } else if ( kind == TK_BAREWORD ||
1383 ( allow_quoted && kind == TK_QDSTRING ) ) {
1384 res = LDAP_CALLOC(2,sizeof(char *));
1387 *code = LDAP_SCHERR_OUTOFMEM;
1396 *code = LDAP_SCHERR_BADNAME;
1402 add_extension(LDAPSchemaExtensionItem ***extensions,
1403 char * name, char ** values)
1406 LDAPSchemaExtensionItem **tmp, *ext;
1408 ext = LDAP_CALLOC(1, sizeof(LDAPSchemaExtensionItem));
1411 ext->lsei_name = name;
1412 ext->lsei_values = values;
1414 if ( !*extensions ) {
1416 LDAP_CALLOC(2, sizeof(LDAPSchemaExtensionItem *));
1417 if ( !*extensions ) {
1423 for ( n=0; (*extensions)[n] != NULL; n++ )
1425 tmp = LDAP_REALLOC(*extensions,
1426 (n+2)*sizeof(LDAPSchemaExtensionItem *));
1433 (*extensions)[n] = ext;
1434 (*extensions)[n+1] = NULL;
1439 free_extensions(LDAPSchemaExtensionItem **extensions)
1441 LDAPSchemaExtensionItem **ext;
1444 for ( ext = extensions; *ext != NULL; ext++ ) {
1445 LDAP_FREE((*ext)->lsei_name);
1446 LDAP_VFREE((*ext)->lsei_values);
1449 LDAP_FREE(extensions);
1454 ldap_syntax_free( LDAPSyntax * syn )
1456 LDAP_FREE(syn->syn_oid);
1457 if (syn->syn_names) LDAP_VFREE(syn->syn_names);
1458 if (syn->syn_desc) LDAP_FREE(syn->syn_desc);
1459 free_extensions(syn->syn_extensions);
1464 ldap_str2syntax( LDAP_CONST char * s,
1466 LDAP_CONST char ** errp,
1467 LDAP_CONST unsigned flags )
1470 const char * ss = s;
1478 *code = LDAP_SCHERR_EMPTY;
1484 syn = LDAP_CALLOC(1,sizeof(LDAPSyntax));
1487 *code = LDAP_SCHERR_OUTOFMEM;
1491 kind = get_token(&ss,&sval);
1492 if ( kind != TK_LEFTPAREN ) {
1494 *code = LDAP_SCHERR_NOLEFTPAREN;
1495 ldap_syntax_free(syn);
1500 syn->syn_oid = ldap_int_parse_numericoid(&ss,code,0);
1501 if ( !syn->syn_oid ) {
1503 ldap_syntax_free(syn);
1509 * Beyond this point we will be liberal and accept the items
1513 kind = get_token(&ss,&sval);
1516 *code = LDAP_SCHERR_NORIGHTPAREN;
1518 ldap_syntax_free(syn);
1523 if ( !strcasecmp(sval,"NAME") ) {
1526 *code = LDAP_SCHERR_DUPOPT;
1528 ldap_syntax_free(syn);
1532 syn->syn_names = parse_qdescrs(&ss,code);
1533 if ( !syn->syn_names ) {
1534 if ( *code != LDAP_SCHERR_OUTOFMEM )
1535 *code = LDAP_SCHERR_BADNAME;
1537 ldap_syntax_free(syn);
1540 } else if ( !strcasecmp(sval,"DESC") ) {
1543 *code = LDAP_SCHERR_DUPOPT;
1545 ldap_syntax_free(syn);
1550 kind = get_token(&ss,&sval);
1551 if ( kind != TK_QDSTRING ) {
1552 *code = LDAP_SCHERR_UNEXPTOKEN;
1555 ldap_syntax_free(syn);
1558 syn->syn_desc = sval;
1560 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
1561 /* Should be parse_qdstrings */
1562 ext_vals = parse_qdescrs(&ss, code);
1565 ldap_syntax_free(syn);
1568 if ( add_extension(&syn->syn_extensions,
1570 *code = LDAP_SCHERR_OUTOFMEM;
1573 ldap_syntax_free(syn);
1577 *code = LDAP_SCHERR_UNEXPTOKEN;
1580 ldap_syntax_free(syn);
1585 *code = LDAP_SCHERR_UNEXPTOKEN;
1588 ldap_syntax_free(syn);
1595 ldap_matchingrule_free( LDAPMatchingRule * mr )
1597 LDAP_FREE(mr->mr_oid);
1598 if (mr->mr_names) LDAP_VFREE(mr->mr_names);
1599 if (mr->mr_desc) LDAP_FREE(mr->mr_desc);
1600 if (mr->mr_syntax_oid) LDAP_FREE(mr->mr_syntax_oid);
1601 free_extensions(mr->mr_extensions);
1606 ldap_str2matchingrule( LDAP_CONST char * s,
1608 LDAP_CONST char ** errp,
1609 LDAP_CONST unsigned flags )
1612 const char * ss = s;
1616 int seen_obsolete = 0;
1617 int seen_syntax = 0;
1618 LDAPMatchingRule * mr;
1620 const char * savepos;
1623 *code = LDAP_SCHERR_EMPTY;
1629 mr = LDAP_CALLOC(1,sizeof(LDAPMatchingRule));
1632 *code = LDAP_SCHERR_OUTOFMEM;
1636 kind = get_token(&ss,&sval);
1637 if ( kind != TK_LEFTPAREN ) {
1638 *code = LDAP_SCHERR_NOLEFTPAREN;
1640 ldap_matchingrule_free(mr);
1646 mr->mr_oid = ldap_int_parse_numericoid(&ss,code,flags);
1647 if ( !mr->mr_oid ) {
1648 if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) {
1651 kind = get_token(&ss,&sval);
1652 if ( kind == TK_BAREWORD ) {
1653 if ( !strcasecmp(sval, "NAME") ||
1654 !strcasecmp(sval, "DESC") ||
1655 !strcasecmp(sval, "OBSOLETE") ||
1656 !strcasecmp(sval, "SYNTAX") ||
1657 !strncasecmp(sval, "X-", 2) ) {
1658 /* Missing OID, backtrack */
1661 /* Non-numerical OID, ignore */
1667 ldap_matchingrule_free(mr);
1674 * Beyond this point we will be liberal and accept the items
1678 kind = get_token(&ss,&sval);
1681 *code = LDAP_SCHERR_NORIGHTPAREN;
1683 ldap_matchingrule_free(mr);
1686 if( !seen_syntax ) {
1687 *code = LDAP_SCHERR_MISSING;
1688 ldap_matchingrule_free(mr);
1693 if ( !strcasecmp(sval,"NAME") ) {
1696 *code = LDAP_SCHERR_DUPOPT;
1698 ldap_matchingrule_free(mr);
1702 mr->mr_names = parse_qdescrs(&ss,code);
1703 if ( !mr->mr_names ) {
1704 if ( *code != LDAP_SCHERR_OUTOFMEM )
1705 *code = LDAP_SCHERR_BADNAME;
1707 ldap_matchingrule_free(mr);
1710 } else if ( !strcasecmp(sval,"DESC") ) {
1713 *code = LDAP_SCHERR_DUPOPT;
1715 ldap_matchingrule_free(mr);
1720 kind = get_token(&ss,&sval);
1721 if ( kind != TK_QDSTRING ) {
1722 *code = LDAP_SCHERR_UNEXPTOKEN;
1725 ldap_matchingrule_free(mr);
1730 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
1732 if ( seen_obsolete ) {
1733 *code = LDAP_SCHERR_DUPOPT;
1735 ldap_matchingrule_free(mr);
1739 mr->mr_obsolete = LDAP_SCHEMA_YES;
1741 } else if ( !strcasecmp(sval,"SYNTAX") ) {
1743 if ( seen_syntax ) {
1744 *code = LDAP_SCHERR_DUPOPT;
1746 ldap_matchingrule_free(mr);
1752 ldap_int_parse_numericoid(&ss,code,flags);
1753 if ( !mr->mr_syntax_oid ) {
1755 ldap_matchingrule_free(mr);
1759 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
1760 /* Should be parse_qdstrings */
1761 ext_vals = parse_qdescrs(&ss, code);
1764 ldap_matchingrule_free(mr);
1767 if ( add_extension(&mr->mr_extensions,
1769 *code = LDAP_SCHERR_OUTOFMEM;
1772 ldap_matchingrule_free(mr);
1776 *code = LDAP_SCHERR_UNEXPTOKEN;
1779 ldap_matchingrule_free(mr);
1784 *code = LDAP_SCHERR_UNEXPTOKEN;
1787 ldap_matchingrule_free(mr);
1794 ldap_matchingruleuse_free( LDAPMatchingRuleUse * mru )
1796 LDAP_FREE(mru->mru_oid);
1797 if (mru->mru_names) LDAP_VFREE(mru->mru_names);
1798 if (mru->mru_desc) LDAP_FREE(mru->mru_desc);
1799 if (mru->mru_applies_oids) LDAP_VFREE(mru->mru_applies_oids);
1800 free_extensions(mru->mru_extensions);
1804 LDAPMatchingRuleUse *
1805 ldap_str2matchingruleuse( LDAP_CONST char * s,
1807 LDAP_CONST char ** errp,
1808 LDAP_CONST unsigned flags )
1811 const char * ss = s;
1815 int seen_obsolete = 0;
1816 int seen_applies = 0;
1817 LDAPMatchingRuleUse * mru;
1819 const char * savepos;
1822 *code = LDAP_SCHERR_EMPTY;
1828 mru = LDAP_CALLOC(1,sizeof(LDAPMatchingRuleUse));
1831 *code = LDAP_SCHERR_OUTOFMEM;
1835 kind = get_token(&ss,&sval);
1836 if ( kind != TK_LEFTPAREN ) {
1837 *code = LDAP_SCHERR_NOLEFTPAREN;
1839 ldap_matchingruleuse_free(mru);
1845 mru->mru_oid = ldap_int_parse_numericoid(&ss,code,flags);
1846 if ( !mru->mru_oid ) {
1847 if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) {
1850 kind = get_token(&ss,&sval);
1851 if ( kind == TK_BAREWORD ) {
1852 if ( !strcasecmp(sval, "NAME") ||
1853 !strcasecmp(sval, "DESC") ||
1854 !strcasecmp(sval, "OBSOLETE") ||
1855 !strcasecmp(sval, "APPLIES") ||
1856 !strncasecmp(sval, "X-", 2) ) {
1857 /* Missing OID, backtrack */
1860 /* Non-numerical OID, ignore */
1866 ldap_matchingruleuse_free(mru);
1873 * Beyond this point we will be liberal and accept the items
1877 kind = get_token(&ss,&sval);
1880 *code = LDAP_SCHERR_NORIGHTPAREN;
1882 ldap_matchingruleuse_free(mru);
1885 if( !seen_applies ) {
1886 *code = LDAP_SCHERR_MISSING;
1887 ldap_matchingruleuse_free(mru);
1892 if ( !strcasecmp(sval,"NAME") ) {
1895 *code = LDAP_SCHERR_DUPOPT;
1897 ldap_matchingruleuse_free(mru);
1901 mru->mru_names = parse_qdescrs(&ss,code);
1902 if ( !mru->mru_names ) {
1903 if ( *code != LDAP_SCHERR_OUTOFMEM )
1904 *code = LDAP_SCHERR_BADNAME;
1906 ldap_matchingruleuse_free(mru);
1909 } else if ( !strcasecmp(sval,"DESC") ) {
1912 *code = LDAP_SCHERR_DUPOPT;
1914 ldap_matchingruleuse_free(mru);
1919 kind = get_token(&ss,&sval);
1920 if ( kind != TK_QDSTRING ) {
1921 *code = LDAP_SCHERR_UNEXPTOKEN;
1924 ldap_matchingruleuse_free(mru);
1927 mru->mru_desc = sval;
1929 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
1931 if ( seen_obsolete ) {
1932 *code = LDAP_SCHERR_DUPOPT;
1934 ldap_matchingruleuse_free(mru);
1938 mru->mru_obsolete = LDAP_SCHEMA_YES;
1940 } else if ( !strcasecmp(sval,"APPLIES") ) {
1942 if ( seen_applies ) {
1943 *code = LDAP_SCHERR_DUPOPT;
1945 ldap_matchingruleuse_free(mru);
1949 mru->mru_applies_oids = parse_oids(&ss,
1952 if ( !mru->mru_applies_oids && *code != LDAP_SUCCESS ) {
1954 ldap_matchingruleuse_free(mru);
1957 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
1958 /* Should be parse_qdstrings */
1959 ext_vals = parse_qdescrs(&ss, code);
1962 ldap_matchingruleuse_free(mru);
1965 if ( add_extension(&mru->mru_extensions,
1967 *code = LDAP_SCHERR_OUTOFMEM;
1970 ldap_matchingruleuse_free(mru);
1974 *code = LDAP_SCHERR_UNEXPTOKEN;
1977 ldap_matchingruleuse_free(mru);
1982 *code = LDAP_SCHERR_UNEXPTOKEN;
1985 ldap_matchingruleuse_free(mru);
1992 ldap_attributetype_free(LDAPAttributeType * at)
1994 LDAP_FREE(at->at_oid);
1995 if (at->at_names) LDAP_VFREE(at->at_names);
1996 if (at->at_desc) LDAP_FREE(at->at_desc);
1997 if (at->at_sup_oid) LDAP_FREE(at->at_sup_oid);
1998 if (at->at_equality_oid) LDAP_FREE(at->at_equality_oid);
1999 if (at->at_ordering_oid) LDAP_FREE(at->at_ordering_oid);
2000 if (at->at_substr_oid) LDAP_FREE(at->at_substr_oid);
2001 if (at->at_syntax_oid) LDAP_FREE(at->at_syntax_oid);
2002 free_extensions(at->at_extensions);
2007 ldap_str2attributetype( LDAP_CONST char * s,
2009 LDAP_CONST char ** errp,
2010 LDAP_CONST unsigned flags )
2013 const char * ss = s;
2017 int seen_obsolete = 0;
2019 int seen_equality = 0;
2020 int seen_ordering = 0;
2021 int seen_substr = 0;
2022 int seen_syntax = 0;
2024 LDAPAttributeType * at;
2026 const char * savepos;
2029 *code = LDAP_SCHERR_EMPTY;
2035 at = LDAP_CALLOC(1,sizeof(LDAPAttributeType));
2038 *code = LDAP_SCHERR_OUTOFMEM;
2042 kind = get_token(&ss,&sval);
2043 if ( kind != TK_LEFTPAREN ) {
2044 *code = LDAP_SCHERR_NOLEFTPAREN;
2046 ldap_attributetype_free(at);
2051 * Definitions MUST begin with an OID in the numericoid format.
2052 * However, this routine is used by clients to parse the response
2053 * from servers and very well known servers will provide an OID
2054 * in the wrong format or even no OID at all. We do our best to
2055 * extract info from those servers.
2059 at->at_oid = ldap_int_parse_numericoid(&ss,code,0);
2060 if ( !at->at_oid ) {
2061 if ( ( flags & ( LDAP_SCHEMA_ALLOW_NO_OID
2062 | LDAP_SCHEMA_ALLOW_OID_MACRO ) )
2063 && (ss == savepos) )
2067 kind = get_token(&ss,&sval);
2068 if ( kind == TK_BAREWORD ) {
2069 if ( !strcasecmp(sval, "NAME") ||
2070 !strcasecmp(sval, "DESC") ||
2071 !strcasecmp(sval, "OBSOLETE") ||
2072 !strcasecmp(sval, "SUP") ||
2073 !strcasecmp(sval, "EQUALITY") ||
2074 !strcasecmp(sval, "ORDERING") ||
2075 !strcasecmp(sval, "SUBSTR") ||
2076 !strcasecmp(sval, "SYNTAX") ||
2077 !strcasecmp(sval, "SINGLE-VALUE") ||
2078 !strcasecmp(sval, "COLLECTIVE") ||
2079 !strcasecmp(sval, "NO-USER-MODIFICATION") ||
2080 !strcasecmp(sval, "USAGE") ||
2081 !strncasecmp(sval, "X-", 2) )
2083 /* Missing OID, backtrack */
2086 & LDAP_SCHEMA_ALLOW_OID_MACRO)
2088 /* Non-numerical OID ... */
2089 int len = ss-savepos;
2090 at->at_oid = LDAP_MALLOC(len+1);
2091 strncpy(at->at_oid, savepos, len);
2092 at->at_oid[len] = 0;
2098 ldap_attributetype_free(at);
2105 * Beyond this point we will be liberal and accept the items
2109 kind = get_token(&ss,&sval);
2112 *code = LDAP_SCHERR_NORIGHTPAREN;
2114 ldap_attributetype_free(at);
2119 if ( !strcasecmp(sval,"NAME") ) {
2122 *code = LDAP_SCHERR_DUPOPT;
2124 ldap_attributetype_free(at);
2128 at->at_names = parse_qdescrs(&ss,code);
2129 if ( !at->at_names ) {
2130 if ( *code != LDAP_SCHERR_OUTOFMEM )
2131 *code = LDAP_SCHERR_BADNAME;
2133 ldap_attributetype_free(at);
2136 } else if ( !strcasecmp(sval,"DESC") ) {
2139 *code = LDAP_SCHERR_DUPOPT;
2141 ldap_attributetype_free(at);
2146 kind = get_token(&ss,&sval);
2147 if ( kind != TK_QDSTRING ) {
2148 *code = LDAP_SCHERR_UNEXPTOKEN;
2151 ldap_attributetype_free(at);
2156 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
2158 if ( seen_obsolete ) {
2159 *code = LDAP_SCHERR_DUPOPT;
2161 ldap_attributetype_free(at);
2165 at->at_obsolete = LDAP_SCHEMA_YES;
2167 } else if ( !strcasecmp(sval,"SUP") ) {
2170 *code = LDAP_SCHERR_DUPOPT;
2172 ldap_attributetype_free(at);
2176 at->at_sup_oid = parse_woid(&ss,code);
2177 if ( !at->at_sup_oid ) {
2179 ldap_attributetype_free(at);
2182 } else if ( !strcasecmp(sval,"EQUALITY") ) {
2184 if ( seen_equality ) {
2185 *code = LDAP_SCHERR_DUPOPT;
2187 ldap_attributetype_free(at);
2191 at->at_equality_oid = parse_woid(&ss,code);
2192 if ( !at->at_equality_oid ) {
2194 ldap_attributetype_free(at);
2197 } else if ( !strcasecmp(sval,"ORDERING") ) {
2199 if ( seen_ordering ) {
2200 *code = LDAP_SCHERR_DUPOPT;
2202 ldap_attributetype_free(at);
2206 at->at_ordering_oid = parse_woid(&ss,code);
2207 if ( !at->at_ordering_oid ) {
2209 ldap_attributetype_free(at);
2212 } else if ( !strcasecmp(sval,"SUBSTR") ) {
2214 if ( seen_substr ) {
2215 *code = LDAP_SCHERR_DUPOPT;
2217 ldap_attributetype_free(at);
2221 at->at_substr_oid = parse_woid(&ss,code);
2222 if ( !at->at_substr_oid ) {
2224 ldap_attributetype_free(at);
2227 } else if ( !strcasecmp(sval,"SYNTAX") ) {
2229 if ( seen_syntax ) {
2230 *code = LDAP_SCHERR_DUPOPT;
2232 ldap_attributetype_free(at);
2243 if ( !at->at_syntax_oid ) {
2244 if ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2245 kind = get_token(&ss,&sval);
2246 if (kind == TK_BAREWORD)
2248 char *sp = strchr(sval, '{');
2249 at->at_syntax_oid = sval;
2253 at->at_syntax_len = atoi(sp);
2254 while ( LDAP_DIGIT(*sp) )
2257 *code = LDAP_SCHERR_UNEXPTOKEN;
2259 ldap_attributetype_free(at);
2266 ldap_attributetype_free(at);
2271 } else if ( !strcasecmp(sval,"SINGLE-VALUE") ) {
2273 if ( at->at_single_value ) {
2274 *code = LDAP_SCHERR_DUPOPT;
2276 ldap_attributetype_free(at);
2279 at->at_single_value = LDAP_SCHEMA_YES;
2281 } else if ( !strcasecmp(sval,"COLLECTIVE") ) {
2283 if ( at->at_collective ) {
2284 *code = LDAP_SCHERR_DUPOPT;
2286 ldap_attributetype_free(at);
2289 at->at_collective = LDAP_SCHEMA_YES;
2291 } else if ( !strcasecmp(sval,"NO-USER-MODIFICATION") ) {
2293 if ( at->at_no_user_mod ) {
2294 *code = LDAP_SCHERR_DUPOPT;
2296 ldap_attributetype_free(at);
2299 at->at_no_user_mod = LDAP_SCHEMA_YES;
2301 } else if ( !strcasecmp(sval,"USAGE") ) {
2304 *code = LDAP_SCHERR_DUPOPT;
2306 ldap_attributetype_free(at);
2311 kind = get_token(&ss,&sval);
2312 if ( kind != TK_BAREWORD ) {
2313 *code = LDAP_SCHERR_UNEXPTOKEN;
2316 ldap_attributetype_free(at);
2319 if ( !strcasecmp(sval,"userApplications") )
2321 LDAP_SCHEMA_USER_APPLICATIONS;
2322 else if ( !strcasecmp(sval,"directoryOperation") )
2324 LDAP_SCHEMA_DIRECTORY_OPERATION;
2325 else if ( !strcasecmp(sval,"distributedOperation") )
2327 LDAP_SCHEMA_DISTRIBUTED_OPERATION;
2328 else if ( !strcasecmp(sval,"dSAOperation") )
2330 LDAP_SCHEMA_DSA_OPERATION;
2332 *code = LDAP_SCHERR_UNEXPTOKEN;
2335 ldap_attributetype_free(at);
2340 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
2341 /* Should be parse_qdstrings */
2342 ext_vals = parse_qdescrs(&ss, code);
2345 ldap_attributetype_free(at);
2348 if ( add_extension(&at->at_extensions,
2350 *code = LDAP_SCHERR_OUTOFMEM;
2353 ldap_attributetype_free(at);
2357 *code = LDAP_SCHERR_UNEXPTOKEN;
2360 ldap_attributetype_free(at);
2365 *code = LDAP_SCHERR_UNEXPTOKEN;
2368 ldap_attributetype_free(at);
2375 ldap_objectclass_free(LDAPObjectClass * oc)
2377 LDAP_FREE(oc->oc_oid);
2378 if (oc->oc_names) LDAP_VFREE(oc->oc_names);
2379 if (oc->oc_desc) LDAP_FREE(oc->oc_desc);
2380 if (oc->oc_sup_oids) LDAP_VFREE(oc->oc_sup_oids);
2381 if (oc->oc_at_oids_must) LDAP_VFREE(oc->oc_at_oids_must);
2382 if (oc->oc_at_oids_may) LDAP_VFREE(oc->oc_at_oids_may);
2383 free_extensions(oc->oc_extensions);
2388 ldap_str2objectclass( LDAP_CONST char * s,
2390 LDAP_CONST char ** errp,
2391 LDAP_CONST unsigned flags )
2394 const char * ss = s;
2398 int seen_obsolete = 0;
2403 LDAPObjectClass * oc;
2405 const char * savepos;
2408 *code = LDAP_SCHERR_EMPTY;
2414 oc = LDAP_CALLOC(1,sizeof(LDAPObjectClass));
2417 *code = LDAP_SCHERR_OUTOFMEM;
2420 oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
2422 kind = get_token(&ss,&sval);
2423 if ( kind != TK_LEFTPAREN ) {
2424 *code = LDAP_SCHERR_NOLEFTPAREN;
2426 ldap_objectclass_free(oc);
2431 * Definitions MUST begin with an OID in the numericoid format.
2432 * However, this routine is used by clients to parse the response
2433 * from servers and very well known servers will provide an OID
2434 * in the wrong format or even no OID at all. We do our best to
2435 * extract info from those servers.
2439 oc->oc_oid = ldap_int_parse_numericoid(&ss,code,0);
2440 if ( !oc->oc_oid ) {
2441 if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) {
2444 kind = get_token(&ss,&sval);
2445 if ( kind == TK_BAREWORD ) {
2446 if ( !strcasecmp(sval, "NAME") ||
2447 !strcasecmp(sval, "DESC") ||
2448 !strcasecmp(sval, "OBSOLETE") ||
2449 !strcasecmp(sval, "SUP") ||
2450 !strcasecmp(sval, "ABSTRACT") ||
2451 !strcasecmp(sval, "STRUCTURAL") ||
2452 !strcasecmp(sval, "AUXILIARY") ||
2453 !strcasecmp(sval, "MUST") ||
2454 !strcasecmp(sval, "MAY") ||
2455 !strncasecmp(sval, "X-", 2) ) {
2456 /* Missing OID, backtrack */
2459 LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2460 /* Non-numerical OID, ignore */
2461 int len = ss-savepos;
2462 oc->oc_oid = LDAP_MALLOC(len+1);
2463 strncpy(oc->oc_oid, savepos, len);
2464 oc->oc_oid[len] = 0;
2471 ldap_objectclass_free(oc);
2478 * Beyond this point we will be liberal an accept the items
2482 kind = get_token(&ss,&sval);
2485 *code = LDAP_SCHERR_NORIGHTPAREN;
2487 ldap_objectclass_free(oc);
2492 if ( !strcasecmp(sval,"NAME") ) {
2495 *code = LDAP_SCHERR_DUPOPT;
2497 ldap_objectclass_free(oc);
2501 oc->oc_names = parse_qdescrs(&ss,code);
2502 if ( !oc->oc_names ) {
2503 if ( *code != LDAP_SCHERR_OUTOFMEM )
2504 *code = LDAP_SCHERR_BADNAME;
2506 ldap_objectclass_free(oc);
2509 } else if ( !strcasecmp(sval,"DESC") ) {
2512 *code = LDAP_SCHERR_DUPOPT;
2514 ldap_objectclass_free(oc);
2519 kind = get_token(&ss,&sval);
2520 if ( kind != TK_QDSTRING ) {
2521 *code = LDAP_SCHERR_UNEXPTOKEN;
2524 ldap_objectclass_free(oc);
2529 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
2531 if ( seen_obsolete ) {
2532 *code = LDAP_SCHERR_DUPOPT;
2534 ldap_objectclass_free(oc);
2538 oc->oc_obsolete = LDAP_SCHEMA_YES;
2540 } else if ( !strcasecmp(sval,"SUP") ) {
2543 *code = LDAP_SCHERR_DUPOPT;
2545 ldap_objectclass_free(oc);
2549 oc->oc_sup_oids = parse_oids(&ss,
2552 if ( !oc->oc_sup_oids && *code != LDAP_SUCCESS ) {
2554 ldap_objectclass_free(oc);
2558 } else if ( !strcasecmp(sval,"ABSTRACT") ) {
2561 *code = LDAP_SCHERR_DUPOPT;
2563 ldap_objectclass_free(oc);
2567 oc->oc_kind = LDAP_SCHEMA_ABSTRACT;
2569 } else if ( !strcasecmp(sval,"STRUCTURAL") ) {
2572 *code = LDAP_SCHERR_DUPOPT;
2574 ldap_objectclass_free(oc);
2578 oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
2580 } else if ( !strcasecmp(sval,"AUXILIARY") ) {
2583 *code = LDAP_SCHERR_DUPOPT;
2585 ldap_objectclass_free(oc);
2589 oc->oc_kind = LDAP_SCHEMA_AUXILIARY;
2591 } else if ( !strcasecmp(sval,"MUST") ) {
2594 *code = LDAP_SCHERR_DUPOPT;
2596 ldap_objectclass_free(oc);
2600 oc->oc_at_oids_must = parse_oids(&ss,code,0);
2601 if ( !oc->oc_at_oids_must && *code != LDAP_SUCCESS ) {
2603 ldap_objectclass_free(oc);
2608 } else if ( !strcasecmp(sval,"MAY") ) {
2611 *code = LDAP_SCHERR_DUPOPT;
2613 ldap_objectclass_free(oc);
2617 oc->oc_at_oids_may = parse_oids(&ss,code,0);
2618 if ( !oc->oc_at_oids_may && *code != LDAP_SUCCESS ) {
2620 ldap_objectclass_free(oc);
2625 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
2626 /* Should be parse_qdstrings */
2627 ext_vals = parse_qdescrs(&ss, code);
2631 ldap_objectclass_free(oc);
2634 if ( add_extension(&oc->oc_extensions,
2636 *code = LDAP_SCHERR_OUTOFMEM;
2639 ldap_objectclass_free(oc);
2643 *code = LDAP_SCHERR_UNEXPTOKEN;
2646 ldap_objectclass_free(oc);
2651 *code = LDAP_SCHERR_UNEXPTOKEN;
2654 ldap_objectclass_free(oc);
2661 ldap_contentrule_free(LDAPContentRule * cr)
2663 LDAP_FREE(cr->cr_oid);
2664 if (cr->cr_names) LDAP_VFREE(cr->cr_names);
2665 if (cr->cr_desc) LDAP_FREE(cr->cr_desc);
2666 if (cr->cr_oc_oids_aux) LDAP_VFREE(cr->cr_oc_oids_aux);
2667 if (cr->cr_at_oids_must) LDAP_VFREE(cr->cr_at_oids_must);
2668 if (cr->cr_at_oids_may) LDAP_VFREE(cr->cr_at_oids_may);
2669 if (cr->cr_at_oids_not) LDAP_VFREE(cr->cr_at_oids_not);
2670 free_extensions(cr->cr_extensions);
2675 ldap_str2contentrule( LDAP_CONST char * s,
2677 LDAP_CONST char ** errp,
2678 LDAP_CONST unsigned flags )
2681 const char * ss = s;
2685 int seen_obsolete = 0;
2690 LDAPContentRule * cr;
2692 const char * savepos;
2695 *code = LDAP_SCHERR_EMPTY;
2701 cr = LDAP_CALLOC(1,sizeof(LDAPContentRule));
2704 *code = LDAP_SCHERR_OUTOFMEM;
2708 kind = get_token(&ss,&sval);
2709 if ( kind != TK_LEFTPAREN ) {
2710 *code = LDAP_SCHERR_NOLEFTPAREN;
2712 ldap_contentrule_free(cr);
2717 * Definitions MUST begin with an OID in the numericoid format.
2721 cr->cr_oid = ldap_int_parse_numericoid(&ss,code,0);
2722 if ( !cr->cr_oid ) {
2723 if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) {
2726 kind = get_token(&ss,&sval);
2727 if ( kind == TK_BAREWORD ) {
2728 if ( !strcasecmp(sval, "NAME") ||
2729 !strcasecmp(sval, "DESC") ||
2730 !strcasecmp(sval, "OBSOLETE") ||
2731 !strcasecmp(sval, "AUX") ||
2732 !strcasecmp(sval, "MUST") ||
2733 !strcasecmp(sval, "MAY") ||
2734 !strcasecmp(sval, "NOT") ||
2735 !strncasecmp(sval, "X-", 2) ) {
2736 /* Missing OID, backtrack */
2739 LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2740 /* Non-numerical OID, ignore */
2741 int len = ss-savepos;
2742 cr->cr_oid = LDAP_MALLOC(len+1);
2743 strncpy(cr->cr_oid, savepos, len);
2744 cr->cr_oid[len] = 0;
2750 ldap_contentrule_free(cr);
2757 * Beyond this point we will be liberal an accept the items
2761 kind = get_token(&ss,&sval);
2764 *code = LDAP_SCHERR_NORIGHTPAREN;
2766 ldap_contentrule_free(cr);
2771 if ( !strcasecmp(sval,"NAME") ) {
2774 *code = LDAP_SCHERR_DUPOPT;
2776 ldap_contentrule_free(cr);
2780 cr->cr_names = parse_qdescrs(&ss,code);
2781 if ( !cr->cr_names ) {
2782 if ( *code != LDAP_SCHERR_OUTOFMEM )
2783 *code = LDAP_SCHERR_BADNAME;
2785 ldap_contentrule_free(cr);
2788 } else if ( !strcasecmp(sval,"DESC") ) {
2791 *code = LDAP_SCHERR_DUPOPT;
2793 ldap_contentrule_free(cr);
2798 kind = get_token(&ss,&sval);
2799 if ( kind != TK_QDSTRING ) {
2800 *code = LDAP_SCHERR_UNEXPTOKEN;
2803 ldap_contentrule_free(cr);
2808 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
2810 if ( seen_obsolete ) {
2811 *code = LDAP_SCHERR_DUPOPT;
2813 ldap_contentrule_free(cr);
2817 cr->cr_obsolete = LDAP_SCHEMA_YES;
2819 } else if ( !strcasecmp(sval,"AUX") ) {
2822 *code = LDAP_SCHERR_DUPOPT;
2824 ldap_contentrule_free(cr);
2828 cr->cr_oc_oids_aux = parse_oids(&ss,code,0);
2829 if ( !cr->cr_oc_oids_aux ) {
2831 ldap_contentrule_free(cr);
2835 } else if ( !strcasecmp(sval,"MUST") ) {
2838 *code = LDAP_SCHERR_DUPOPT;
2840 ldap_contentrule_free(cr);
2844 cr->cr_at_oids_must = parse_oids(&ss,code,0);
2845 if ( !cr->cr_at_oids_must && *code != LDAP_SUCCESS ) {
2847 ldap_contentrule_free(cr);
2851 } else if ( !strcasecmp(sval,"MAY") ) {
2854 *code = LDAP_SCHERR_DUPOPT;
2856 ldap_contentrule_free(cr);
2860 cr->cr_at_oids_may = parse_oids(&ss,code,0);
2861 if ( !cr->cr_at_oids_may && *code != LDAP_SUCCESS ) {
2863 ldap_contentrule_free(cr);
2867 } else if ( !strcasecmp(sval,"NOT") ) {
2870 *code = LDAP_SCHERR_DUPOPT;
2872 ldap_contentrule_free(cr);
2876 cr->cr_at_oids_not = parse_oids(&ss,code,0);
2877 if ( !cr->cr_at_oids_not && *code != LDAP_SUCCESS ) {
2879 ldap_contentrule_free(cr);
2883 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
2884 /* Should be parse_qdstrings */
2885 ext_vals = parse_qdescrs(&ss, code);
2888 ldap_contentrule_free(cr);
2891 if ( add_extension(&cr->cr_extensions,
2893 *code = LDAP_SCHERR_OUTOFMEM;
2896 ldap_contentrule_free(cr);
2900 *code = LDAP_SCHERR_UNEXPTOKEN;
2903 ldap_contentrule_free(cr);
2908 *code = LDAP_SCHERR_UNEXPTOKEN;
2911 ldap_contentrule_free(cr);
2918 ldap_structurerule_free(LDAPStructureRule * sr)
2920 if (sr->sr_names) LDAP_VFREE(sr->sr_names);
2921 if (sr->sr_desc) LDAP_FREE(sr->sr_desc);
2922 if (sr->sr_nameform) LDAP_FREE(sr->sr_nameform);
2923 if (sr->sr_sup_ruleids) LDAP_FREE(sr->sr_sup_ruleids);
2924 free_extensions(sr->sr_extensions);
2929 ldap_str2structurerule( LDAP_CONST char * s,
2931 LDAP_CONST char ** errp,
2932 LDAP_CONST unsigned flags )
2936 const char * ss = s;
2940 int seen_obsolete = 0;
2941 int seen_nameform = 0;
2942 LDAPStructureRule * sr;
2944 const char * savepos;
2947 *code = LDAP_SCHERR_EMPTY;
2953 sr = LDAP_CALLOC(1,sizeof(LDAPStructureRule));
2956 *code = LDAP_SCHERR_OUTOFMEM;
2960 kind = get_token(&ss,&sval);
2961 if ( kind != TK_LEFTPAREN ) {
2962 *code = LDAP_SCHERR_NOLEFTPAREN;
2964 ldap_structurerule_free(sr);
2969 * Definitions MUST begin with a ruleid.
2973 ret = ldap_int_parse_ruleid(&ss,code,0,&sr->sr_ruleid);
2976 ldap_structurerule_free(sr);
2982 * Beyond this point we will be liberal an accept the items
2986 kind = get_token(&ss,&sval);
2989 *code = LDAP_SCHERR_NORIGHTPAREN;
2991 ldap_structurerule_free(sr);
2994 if( !seen_nameform ) {
2995 *code = LDAP_SCHERR_MISSING;
2996 ldap_structurerule_free(sr);
3001 if ( !strcasecmp(sval,"NAME") ) {
3004 *code = LDAP_SCHERR_DUPOPT;
3006 ldap_structurerule_free(sr);
3010 sr->sr_names = parse_qdescrs(&ss,code);
3011 if ( !sr->sr_names ) {
3012 if ( *code != LDAP_SCHERR_OUTOFMEM )
3013 *code = LDAP_SCHERR_BADNAME;
3015 ldap_structurerule_free(sr);
3018 } else if ( !strcasecmp(sval,"DESC") ) {
3021 *code = LDAP_SCHERR_DUPOPT;
3023 ldap_structurerule_free(sr);
3028 kind = get_token(&ss,&sval);
3029 if ( kind != TK_QDSTRING ) {
3030 *code = LDAP_SCHERR_UNEXPTOKEN;
3033 ldap_structurerule_free(sr);
3038 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
3040 if ( seen_obsolete ) {
3041 *code = LDAP_SCHERR_DUPOPT;
3043 ldap_structurerule_free(sr);
3047 sr->sr_obsolete = LDAP_SCHEMA_YES;
3049 } else if ( !strcasecmp(sval,"FORM") ) {
3051 if ( seen_nameform ) {
3052 *code = LDAP_SCHERR_DUPOPT;
3054 ldap_structurerule_free(sr);
3058 sr->sr_nameform = parse_woid(&ss,code);
3059 if ( !sr->sr_nameform ) {
3061 ldap_structurerule_free(sr);
3065 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
3066 /* Should be parse_qdstrings */
3067 ext_vals = parse_qdescrs(&ss, code);
3070 ldap_structurerule_free(sr);
3073 if ( add_extension(&sr->sr_extensions,
3075 *code = LDAP_SCHERR_OUTOFMEM;
3078 ldap_structurerule_free(sr);
3082 *code = LDAP_SCHERR_UNEXPTOKEN;
3085 ldap_structurerule_free(sr);
3090 *code = LDAP_SCHERR_UNEXPTOKEN;
3093 ldap_structurerule_free(sr);
3100 ldap_nameform_free(LDAPNameForm * nf)
3102 LDAP_FREE(nf->nf_oid);
3103 if (nf->nf_names) LDAP_VFREE(nf->nf_names);
3104 if (nf->nf_desc) LDAP_FREE(nf->nf_desc);
3105 if (nf->nf_objectclass) LDAP_FREE(nf->nf_objectclass);
3106 if (nf->nf_at_oids_must) LDAP_VFREE(nf->nf_at_oids_must);
3107 if (nf->nf_at_oids_may) LDAP_VFREE(nf->nf_at_oids_may);
3108 free_extensions(nf->nf_extensions);
3113 ldap_str2nameform( LDAP_CONST char * s,
3115 LDAP_CONST char ** errp,
3116 LDAP_CONST unsigned flags )
3119 const char * ss = s;
3123 int seen_obsolete = 0;
3129 const char * savepos;
3132 *code = LDAP_SCHERR_EMPTY;
3138 nf = LDAP_CALLOC(1,sizeof(LDAPNameForm));
3141 *code = LDAP_SCHERR_OUTOFMEM;
3145 kind = get_token(&ss,&sval);
3146 if ( kind != TK_LEFTPAREN ) {
3147 *code = LDAP_SCHERR_NOLEFTPAREN;
3149 ldap_nameform_free(nf);
3154 * Definitions MUST begin with an OID in the numericoid format.
3155 * However, this routine is used by clients to parse the response
3156 * from servers and very well known servers will provide an OID
3157 * in the wrong format or even no OID at all. We do our best to
3158 * extract info from those servers.
3162 nf->nf_oid = ldap_int_parse_numericoid(&ss,code,0);
3163 if ( !nf->nf_oid ) {
3165 ldap_nameform_free(nf);
3171 * Beyond this point we will be liberal an accept the items
3175 kind = get_token(&ss,&sval);
3178 *code = LDAP_SCHERR_NORIGHTPAREN;
3180 ldap_nameform_free(nf);
3183 if( !seen_class || !seen_must ) {
3184 *code = LDAP_SCHERR_MISSING;
3185 ldap_nameform_free(nf);
3190 if ( !strcasecmp(sval,"NAME") ) {
3193 *code = LDAP_SCHERR_DUPOPT;
3195 ldap_nameform_free(nf);
3199 nf->nf_names = parse_qdescrs(&ss,code);
3200 if ( !nf->nf_names ) {
3201 if ( *code != LDAP_SCHERR_OUTOFMEM )
3202 *code = LDAP_SCHERR_BADNAME;
3204 ldap_nameform_free(nf);
3207 } else if ( !strcasecmp(sval,"DESC") ) {
3210 *code = LDAP_SCHERR_DUPOPT;
3212 ldap_nameform_free(nf);
3217 kind = get_token(&ss,&sval);
3218 if ( kind != TK_QDSTRING ) {
3219 *code = LDAP_SCHERR_UNEXPTOKEN;
3222 ldap_nameform_free(nf);
3227 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
3229 if ( seen_obsolete ) {
3230 *code = LDAP_SCHERR_DUPOPT;
3232 ldap_nameform_free(nf);
3236 nf->nf_obsolete = LDAP_SCHEMA_YES;
3238 } else if ( !strcasecmp(sval,"OC") ) {
3241 *code = LDAP_SCHERR_DUPOPT;
3243 ldap_nameform_free(nf);
3247 nf->nf_objectclass = parse_woid(&ss,code);
3248 if ( !nf->nf_objectclass ) {
3250 ldap_nameform_free(nf);
3253 } else if ( !strcasecmp(sval,"MUST") ) {
3256 *code = LDAP_SCHERR_DUPOPT;
3258 ldap_nameform_free(nf);
3262 nf->nf_at_oids_must = parse_oids(&ss,code,0);
3263 if ( !nf->nf_at_oids_must && *code != LDAP_SUCCESS ) {
3265 ldap_nameform_free(nf);
3269 } else if ( !strcasecmp(sval,"MAY") ) {
3272 *code = LDAP_SCHERR_DUPOPT;
3274 ldap_nameform_free(nf);
3278 nf->nf_at_oids_may = parse_oids(&ss,code,0);
3279 if ( !nf->nf_at_oids_may && *code != LDAP_SUCCESS ) {
3281 ldap_nameform_free(nf);
3285 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
3286 /* Should be parse_qdstrings */
3287 ext_vals = parse_qdescrs(&ss, code);
3290 ldap_nameform_free(nf);
3293 if ( add_extension(&nf->nf_extensions,
3295 *code = LDAP_SCHERR_OUTOFMEM;
3298 ldap_nameform_free(nf);
3302 *code = LDAP_SCHERR_UNEXPTOKEN;
3305 ldap_nameform_free(nf);
3310 *code = LDAP_SCHERR_UNEXPTOKEN;
3313 ldap_nameform_free(nf);
3319 static char *const err2text[] = {
3321 N_("Out of memory"),
3322 N_("Unexpected token"),
3323 N_("Missing opening parenthesis"),
3324 N_("Missing closing parenthesis"),
3325 N_("Expecting digit"),
3326 N_("Expecting a name"),
3327 N_("Bad description"),
3328 N_("Bad superiors"),
3329 N_("Duplicate option"),
3330 N_("Unexpected end of data"),
3331 N_("Missing required field"),
3332 N_("Out of order field")
3336 ldap_scherr2str(int code)
3338 if ( code < 0 || code >= (int)(sizeof(err2text)/sizeof(char *)) ) {
3339 return _("Unknown error");
3341 return _(err2text[code]);