3 * Copyright 1999-2003 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
7 * schema.c: parsing routines used by servers and clients to process
14 #include <ac/stdlib.h>
16 #include <ac/string.h>
21 #include <ldap_schema.h>
24 choose_name( char *names[], const char *fallback )
26 return (names != NULL && names[0] != NULL) ? names[0] : fallback;
30 ldap_syntax2name( LDAPSyntax * syn )
32 return( syn->syn_oid );
36 ldap_matchingrule2name( LDAPMatchingRule * mr )
38 return( choose_name( mr->mr_names, mr->mr_oid ) );
42 ldap_matchingruleuse2name( LDAPMatchingRuleUse * mru )
44 return( choose_name( mru->mru_names, mru->mru_oid ) );
48 ldap_attributetype2name( LDAPAttributeType * at )
50 return( choose_name( at->at_names, at->at_oid ) );
54 ldap_objectclass2name( LDAPObjectClass * oc )
56 return( choose_name( oc->oc_names, oc->oc_oid ) );
60 ldap_contentrule2name( LDAPContentRule * cr )
62 return( choose_name( cr->cr_names, cr->cr_oid ) );
66 ldap_nameform2name( LDAPNameForm * nf )
68 return( choose_name( nf->nf_names, nf->nf_oid ) );
72 ldap_structurerule2name( LDAPStructureRule * sr )
74 return( choose_name( sr->sr_names, NULL ) );
78 * When pretty printing the entities we will be appending to a buffer.
79 * Since checking for overflow, realloc'ing and checking if no error
80 * is extremely boring, we will use a protection layer that will let
81 * us blissfully ignore the error until the end. This layer is
82 * implemented with the help of the next type.
85 typedef struct safe_string {
93 new_safe_string(int size)
97 ss = LDAP_MALLOC(sizeof(safe_string));
101 ss->val = LDAP_MALLOC(size);
115 safe_string_free(safe_string * ss)
125 safe_string_val(safe_string * ss)
127 ss->val[ss->pos] = '\0';
133 safe_strdup(safe_string * ss)
135 char *ret = LDAP_MALLOC(ss->pos+1);
138 AC_MEMCPY(ret, ss->val, ss->pos);
144 append_to_safe_string(safe_string * ss, char * s)
150 * Some runaway process is trying to append to a string that
151 * overflowed and we could not extend.
156 /* We always make sure there is at least one position available */
157 if ( ss->pos + l >= ss->size-1 ) {
159 if ( ss->pos + l >= ss->size-1 ) {
160 ss->size = ss->pos + l + 1;
163 temp = LDAP_REALLOC(ss->val, ss->size);
165 /* Trouble, out of memory */
171 strncpy(&ss->val[ss->pos], s, l);
173 if ( ss->pos > 0 && LDAP_SPACE(ss->val[ss->pos-1]) )
182 print_literal(safe_string *ss, char *s)
184 return(append_to_safe_string(ss,s));
188 print_whsp(safe_string *ss)
191 return(append_to_safe_string(ss,""));
193 return(append_to_safe_string(ss," "));
197 print_numericoid(safe_string *ss, char *s)
200 return(append_to_safe_string(ss,s));
202 return(append_to_safe_string(ss,""));
205 /* This one is identical to print_qdescr */
207 print_qdstring(safe_string *ss, char *s)
210 print_literal(ss,"'");
211 append_to_safe_string(ss,s);
212 print_literal(ss,"'");
213 return(print_whsp(ss));
217 print_qdescr(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_qdescrlist(safe_string *ss, char **sa)
232 for (sp=sa; *sp; sp++) {
233 ret = print_qdescr(ss,*sp);
235 /* If the list was empty, we return zero that is potentially
236 * incorrect, but since we will be still appending things, the
237 * overflow will be detected later. Maybe FIX.
243 print_qdescrs(safe_string *ss, char **sa)
245 /* The only way to represent an empty list is as a qdescrlist
246 * so, if the list is empty we treat it as a long list.
247 * Really, this is what the syntax mandates. We should not
248 * be here if the list was empty, but if it happens, a label
249 * has already been output and we cannot undo it.
251 if ( !sa[0] || ( sa[0] && sa[1] ) ) {
253 print_literal(ss,"("/*)*/);
254 print_qdescrlist(ss,sa);
255 print_literal(ss,/*(*/")");
256 return(print_whsp(ss));
258 return(print_qdescr(ss,*sa));
263 print_woid(safe_string *ss, char *s)
266 append_to_safe_string(ss,s);
267 return print_whsp(ss);
271 print_oidlist(safe_string *ss, char **sa)
275 for (sp=sa; *(sp+1); sp++) {
277 print_literal(ss,"$");
279 return(print_woid(ss,*sp));
283 print_oids(safe_string *ss, char **sa)
285 if ( sa[0] && sa[1] ) {
286 print_literal(ss,"("/*)*/);
287 print_oidlist(ss,sa);
289 return(print_literal(ss,/*(*/")"));
291 return(print_woid(ss,*sa));
296 print_noidlen(safe_string *ss, char *s, int l)
301 ret = print_numericoid(ss,s);
303 snprintf(buf, sizeof buf, "{%d}",l);
304 ret = print_literal(ss,buf);
310 print_ruleid(safe_string *ss, int rid)
313 snprintf(buf, sizeof buf, "%d", rid);
314 return print_literal(ss,buf);
318 print_ruleids(safe_string *ss, int n, int *rids)
323 print_ruleid(ss,rids[0]);
324 return print_whsp(ss);
326 print_literal(ss,"("/*)*/);
327 for( i=0; i<n; i++ ) {
329 print_ruleid(ss,rids[i]);
332 return print_literal(ss,/*(*/")");
338 print_extensions(safe_string *ss, LDAPSchemaExtensionItem **extensions)
340 LDAPSchemaExtensionItem **ext;
344 for ( ext = extensions; *ext != NULL; ext++ ) {
345 print_literal(ss, (*ext)->lsei_name);
347 /* Should be print_qdstrings */
348 print_qdescrs(ss, (*ext)->lsei_values);
357 ldap_syntax2str( LDAPSyntax * syn )
360 if (ldap_syntax2bv( syn, &bv ))
367 ldap_syntax2bv( LDAPSyntax * syn, struct berval *bv )
371 ss = new_safe_string(256);
375 print_literal(ss,"("/*)*/);
378 print_numericoid(ss, syn->syn_oid);
381 if ( syn->syn_desc ) {
382 print_literal(ss,"DESC");
383 print_qdstring(ss,syn->syn_desc);
388 print_extensions(ss, syn->syn_extensions);
390 print_literal(ss,/*(*/ ")");
392 bv->bv_val = safe_strdup(ss);
393 bv->bv_len = ss->pos;
394 safe_string_free(ss);
399 ldap_matchingrule2str( LDAPMatchingRule * mr )
402 if (ldap_matchingrule2bv( mr, &bv ))
409 ldap_matchingrule2bv( LDAPMatchingRule * mr, struct berval *bv )
413 ss = new_safe_string(256);
417 print_literal(ss,"(" /*)*/);
420 print_numericoid(ss, mr->mr_oid);
423 if ( mr->mr_names ) {
424 print_literal(ss,"NAME");
425 print_qdescrs(ss,mr->mr_names);
429 print_literal(ss,"DESC");
430 print_qdstring(ss,mr->mr_desc);
433 if ( mr->mr_obsolete ) {
434 print_literal(ss, "OBSOLETE");
438 if ( mr->mr_syntax_oid ) {
439 print_literal(ss,"SYNTAX");
441 print_literal(ss, mr->mr_syntax_oid);
447 print_extensions(ss, mr->mr_extensions);
449 print_literal(ss,/*(*/")");
451 bv->bv_val = safe_strdup(ss);
452 bv->bv_len = ss->pos;
453 safe_string_free(ss);
458 ldap_matchingruleuse2str( LDAPMatchingRuleUse * mru )
461 if (ldap_matchingruleuse2bv( mru, &bv ))
468 ldap_matchingruleuse2bv( LDAPMatchingRuleUse * mru, struct berval *bv )
472 ss = new_safe_string(256);
476 print_literal(ss,"(" /*)*/);
479 print_numericoid(ss, mru->mru_oid);
482 if ( mru->mru_names ) {
483 print_literal(ss,"NAME");
484 print_qdescrs(ss,mru->mru_names);
487 if ( mru->mru_desc ) {
488 print_literal(ss,"DESC");
489 print_qdstring(ss,mru->mru_desc);
492 if ( mru->mru_obsolete ) {
493 print_literal(ss, "OBSOLETE");
497 if ( mru->mru_applies_oids ) {
498 print_literal(ss,"APPLIES");
500 print_oids(ss, mru->mru_applies_oids);
506 print_extensions(ss, mru->mru_extensions);
508 print_literal(ss,/*(*/")");
510 bv->bv_val = safe_strdup(ss);
511 bv->bv_len = ss->pos;
512 safe_string_free(ss);
517 ldap_objectclass2str( LDAPObjectClass * oc )
520 if (ldap_objectclass2bv( oc, &bv ))
527 ldap_objectclass2bv( LDAPObjectClass * oc, struct berval *bv )
531 ss = new_safe_string(256);
535 print_literal(ss,"("/*)*/);
538 print_numericoid(ss, oc->oc_oid);
541 if ( oc->oc_names ) {
542 print_literal(ss,"NAME");
543 print_qdescrs(ss,oc->oc_names);
547 print_literal(ss,"DESC");
548 print_qdstring(ss,oc->oc_desc);
551 if ( oc->oc_obsolete ) {
552 print_literal(ss, "OBSOLETE");
556 if ( oc->oc_sup_oids ) {
557 print_literal(ss,"SUP");
559 print_oids(ss,oc->oc_sup_oids);
563 switch (oc->oc_kind) {
564 case LDAP_SCHEMA_ABSTRACT:
565 print_literal(ss,"ABSTRACT");
567 case LDAP_SCHEMA_STRUCTURAL:
568 print_literal(ss,"STRUCTURAL");
570 case LDAP_SCHEMA_AUXILIARY:
571 print_literal(ss,"AUXILIARY");
574 print_literal(ss,"KIND-UNKNOWN");
579 if ( oc->oc_at_oids_must ) {
580 print_literal(ss,"MUST");
582 print_oids(ss,oc->oc_at_oids_must);
586 if ( oc->oc_at_oids_may ) {
587 print_literal(ss,"MAY");
589 print_oids(ss,oc->oc_at_oids_may);
595 print_extensions(ss, oc->oc_extensions);
597 print_literal(ss, /*(*/")");
599 bv->bv_val = safe_strdup(ss);
600 bv->bv_len = ss->pos;
601 safe_string_free(ss);
606 ldap_contentrule2str( LDAPContentRule * cr )
609 if (ldap_contentrule2bv( cr, &bv ))
616 ldap_contentrule2bv( LDAPContentRule * cr, struct berval *bv )
620 ss = new_safe_string(256);
624 print_literal(ss,"("/*)*/);
627 print_numericoid(ss, cr->cr_oid);
630 if ( cr->cr_names ) {
631 print_literal(ss,"NAME");
632 print_qdescrs(ss,cr->cr_names);
636 print_literal(ss,"DESC");
637 print_qdstring(ss,cr->cr_desc);
640 if ( cr->cr_obsolete ) {
641 print_literal(ss, "OBSOLETE");
645 if ( cr->cr_oc_oids_aux ) {
646 print_literal(ss,"AUX");
648 print_oids(ss,cr->cr_oc_oids_aux);
652 if ( cr->cr_at_oids_must ) {
653 print_literal(ss,"MUST");
655 print_oids(ss,cr->cr_at_oids_must);
659 if ( cr->cr_at_oids_may ) {
660 print_literal(ss,"MAY");
662 print_oids(ss,cr->cr_at_oids_may);
666 if ( cr->cr_at_oids_not ) {
667 print_literal(ss,"NOT");
669 print_oids(ss,cr->cr_at_oids_not);
674 print_extensions(ss, cr->cr_extensions);
676 print_literal(ss, /*(*/")");
678 bv->bv_val = safe_strdup(ss);
679 bv->bv_len = ss->pos;
680 safe_string_free(ss);
685 ldap_structurerule2str( LDAPStructureRule * sr )
688 if (ldap_structurerule2bv( sr, &bv ))
695 ldap_structurerule2bv( LDAPStructureRule * sr, struct berval *bv )
699 ss = new_safe_string(256);
703 print_literal(ss,"("/*)*/);
706 print_ruleid(ss, sr->sr_ruleid);
709 if ( sr->sr_names ) {
710 print_literal(ss,"NAME");
711 print_qdescrs(ss,sr->sr_names);
715 print_literal(ss,"DESC");
716 print_qdstring(ss,sr->sr_desc);
719 if ( sr->sr_obsolete ) {
720 print_literal(ss, "OBSOLETE");
724 print_literal(ss,"FORM");
726 print_woid(ss,sr->sr_nameform);
729 if ( sr->sr_nsup_ruleids ) {
730 print_literal(ss,"SUP");
732 print_ruleids(ss,sr->sr_nsup_ruleids,sr->sr_sup_ruleids);
737 print_extensions(ss, sr->sr_extensions);
739 print_literal(ss, /*(*/")");
741 bv->bv_val = safe_strdup(ss);
742 bv->bv_len = ss->pos;
743 safe_string_free(ss);
749 ldap_nameform2str( LDAPNameForm * nf )
752 if (ldap_nameform2bv( nf, &bv ))
759 ldap_nameform2bv( LDAPNameForm * nf, struct berval *bv )
763 ss = new_safe_string(256);
767 print_literal(ss,"("/*)*/);
770 print_numericoid(ss, nf->nf_oid);
773 if ( nf->nf_names ) {
774 print_literal(ss,"NAME");
775 print_qdescrs(ss,nf->nf_names);
779 print_literal(ss,"DESC");
780 print_qdstring(ss,nf->nf_desc);
783 if ( nf->nf_obsolete ) {
784 print_literal(ss, "OBSOLETE");
788 print_literal(ss,"OC");
790 print_woid(ss,nf->nf_objectclass);
793 print_literal(ss,"MUST");
795 print_oids(ss,nf->nf_at_oids_must);
799 if ( nf->nf_at_oids_may ) {
800 print_literal(ss,"MAY");
802 print_oids(ss,nf->nf_at_oids_may);
807 print_extensions(ss, nf->nf_extensions);
809 print_literal(ss, /*(*/")");
811 bv->bv_val = safe_strdup(ss);
812 bv->bv_len = ss->pos;
813 safe_string_free(ss);
818 ldap_attributetype2str( LDAPAttributeType * at )
821 if (ldap_attributetype2bv( at, &bv ))
828 ldap_attributetype2bv( LDAPAttributeType * at, struct berval *bv )
832 ss = new_safe_string(256);
836 print_literal(ss,"("/*)*/);
839 print_numericoid(ss, at->at_oid);
842 if ( at->at_names ) {
843 print_literal(ss,"NAME");
844 print_qdescrs(ss,at->at_names);
848 print_literal(ss,"DESC");
849 print_qdstring(ss,at->at_desc);
852 if ( at->at_obsolete ) {
853 print_literal(ss, "OBSOLETE");
857 if ( at->at_sup_oid ) {
858 print_literal(ss,"SUP");
859 print_woid(ss,at->at_sup_oid);
862 if ( at->at_equality_oid ) {
863 print_literal(ss,"EQUALITY");
864 print_woid(ss,at->at_equality_oid);
867 if ( at->at_ordering_oid ) {
868 print_literal(ss,"ORDERING");
869 print_woid(ss,at->at_ordering_oid);
872 if ( at->at_substr_oid ) {
873 print_literal(ss,"SUBSTR");
874 print_woid(ss,at->at_substr_oid);
877 if ( at->at_syntax_oid ) {
878 print_literal(ss,"SYNTAX");
880 print_noidlen(ss,at->at_syntax_oid,at->at_syntax_len);
884 if ( at->at_single_value == LDAP_SCHEMA_YES ) {
885 print_literal(ss,"SINGLE-VALUE");
889 if ( at->at_collective == LDAP_SCHEMA_YES ) {
890 print_literal(ss,"COLLECTIVE");
894 if ( at->at_no_user_mod == LDAP_SCHEMA_YES ) {
895 print_literal(ss,"NO-USER-MODIFICATION");
899 if ( at->at_usage != LDAP_SCHEMA_USER_APPLICATIONS ) {
900 print_literal(ss,"USAGE");
902 switch (at->at_usage) {
903 case LDAP_SCHEMA_DIRECTORY_OPERATION:
904 print_literal(ss,"directoryOperation");
906 case LDAP_SCHEMA_DISTRIBUTED_OPERATION:
907 print_literal(ss,"distributedOperation");
909 case LDAP_SCHEMA_DSA_OPERATION:
910 print_literal(ss,"dSAOperation");
913 print_literal(ss,"UNKNOWN");
920 print_extensions(ss, at->at_extensions);
922 print_literal(ss,/*(*/")");
924 bv->bv_val = safe_strdup(ss);
925 bv->bv_len = ss->pos;
926 safe_string_free(ss);
931 * Now come the parsers. There is one parser for each entity type:
932 * objectclasses, attributetypes, etc.
934 * Each of them is written as a recursive-descent parser, except that
935 * none of them is really recursive. But the idea is kept: there
936 * is one routine per non-terminal that eithers gobbles lexical tokens
937 * or calls lower-level routines, etc.
939 * The scanner is implemented in the routine get_token. Actually,
940 * get_token is more than a scanner and will return tokens that are
941 * in fact non-terminals in the grammar. So you can see the whole
942 * approach as the combination of a low-level bottom-up recognizer
943 * combined with a scanner and a number of top-down parsers. Or just
944 * consider that the real grammars recognized by the parsers are not
945 * those of the standards. As a matter of fact, our parsers are more
946 * liberal than the spec when there is no ambiguity.
948 * The difference is pretty academic (modulo bugs or incorrect
949 * interpretation of the specs).
952 #define TK_NOENDQUOTE -2
953 #define TK_OUTOFMEM -1
955 #define TK_UNEXPCHAR 1
956 #define TK_BAREWORD 2
957 #define TK_QDSTRING 3
958 #define TK_LEFTPAREN 4
959 #define TK_RIGHTPAREN 5
961 #define TK_QDESCR TK_QDSTRING
969 get_token( const char ** sp, char ** token_val )
987 kind = TK_RIGHTPAREN;
998 while ( **sp != '\'' && **sp != '\0' )
1000 if ( **sp == '\'' ) {
1002 res = LDAP_MALLOC(q-p+1);
1012 kind = TK_NOENDQUOTE;
1018 while ( !LDAP_SPACE(**sp) &&
1026 res = LDAP_MALLOC(q-p+1);
1035 /* kind = TK_UNEXPCHAR; */
1042 /* Gobble optional whitespace */
1044 parse_whsp(const char **sp)
1046 while (LDAP_SPACE(**sp))
1051 * General note for all parsers: to guarantee the algorithm halts they
1052 * must always advance the pointer even when an error is found. For
1053 * this one is not that important since an error here is fatal at the
1054 * upper layers, but it is a simple strategy that will not get in
1058 /* Parse a sequence of dot-separated decimal strings */
1060 ldap_int_parse_numericoid(const char **sp, int *code, const int flags)
1063 const char * start = *sp;
1067 /* Netscape puts the SYNTAX value in quotes (incorrectly) */
1068 if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && **sp == '\'' ) {
1073 /* Each iteration of this loop gets one decimal string */
1075 if ( !LDAP_DIGIT(**sp) ) {
1077 * Initial char is not a digit or char after dot is
1080 *code = LDAP_SCHERR_NODIGIT;
1084 while ( LDAP_DIGIT(**sp) )
1088 /* Otherwise, gobble the dot and loop again */
1091 /* Now *sp points at the char past the numericoid. Perfect. */
1093 if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && quoted ) {
1094 if ( **sp == '\'' ) {
1097 *code = LDAP_SCHERR_UNEXPTOKEN;
1101 if (flags & LDAP_SCHEMA_SKIP) {
1102 res = (char *)start;
1104 res = LDAP_MALLOC(len+1);
1106 *code = LDAP_SCHERR_OUTOFMEM;
1109 strncpy(res,start,len);
1115 /* Parse a sequence of dot-separated decimal strings */
1117 ldap_int_parse_ruleid(const char **sp, int *code, const int flags, int *ruleid)
1121 if ( !LDAP_DIGIT(**sp) ) {
1122 *code = LDAP_SCHERR_NODIGIT;
1125 *ruleid = (**sp) - '0';
1128 while ( LDAP_DIGIT(**sp) ) {
1130 *ruleid += (**sp) - '0';
1137 /* Parse a qdescr or a list of them enclosed in () */
1139 parse_qdescrs(const char **sp, int *code)
1149 kind = get_token(sp,&sval);
1150 if ( kind == TK_LEFTPAREN ) {
1151 /* Let's presume there will be at least 2 entries */
1153 res = LDAP_CALLOC(3,sizeof(char *));
1155 *code = LDAP_SCHERR_OUTOFMEM;
1161 kind = get_token(sp,&sval);
1162 if ( kind == TK_RIGHTPAREN )
1164 if ( kind == TK_QDESCR ) {
1165 if ( pos == size-2 ) {
1167 res1 = LDAP_REALLOC(res,size*sizeof(char *));
1171 *code = LDAP_SCHERR_OUTOFMEM;
1182 *code = LDAP_SCHERR_UNEXPTOKEN;
1189 } else if ( kind == TK_QDESCR ) {
1190 res = LDAP_CALLOC(2,sizeof(char *));
1192 *code = LDAP_SCHERR_OUTOFMEM;
1201 *code = LDAP_SCHERR_BADNAME;
1208 parse_woid(const char **sp, int *code)
1214 kind = get_token(sp, &sval);
1215 if ( kind != TK_BAREWORD ) {
1217 *code = LDAP_SCHERR_UNEXPTOKEN;
1224 /* Parse a noidlen */
1226 parse_noidlen(const char **sp, int *code, int *len, int allow_quoted)
1232 /* Netscape puts the SYNTAX value in quotes (incorrectly) */
1233 if ( allow_quoted && **sp == '\'' ) {
1237 sval = ldap_int_parse_numericoid(sp, code, 0);
1241 if ( **sp == '{' /*}*/ ) {
1244 while ( LDAP_DIGIT(**sp) )
1246 if ( **sp != /*{*/ '}' ) {
1247 *code = LDAP_SCHERR_UNEXPTOKEN;
1253 if ( allow_quoted && quoted ) {
1254 if ( **sp == '\'' ) {
1257 *code = LDAP_SCHERR_UNEXPTOKEN;
1266 * Next routine will accept a qdstring in place of an oid if
1267 * allow_quoted is set. This is necessary to interoperate with
1268 * Netscape Directory server that will improperly quote each oid (at
1269 * least those of the descr kind) in the SUP clause.
1272 /* Parse a woid or a $-separated list of them enclosed in () */
1274 parse_oids(const char **sp, int *code, const int allow_quoted)
1284 * Strictly speaking, doing this here accepts whsp before the
1285 * ( at the begining of an oidlist, but this is harmless. Also,
1286 * we are very liberal in what we accept as an OID. Maybe
1290 kind = get_token(sp,&sval);
1291 if ( kind == TK_LEFTPAREN ) {
1292 /* Let's presume there will be at least 2 entries */
1294 res = LDAP_CALLOC(3,sizeof(char *));
1296 *code = LDAP_SCHERR_OUTOFMEM;
1301 kind = get_token(sp,&sval);
1302 if ( kind == TK_BAREWORD ||
1303 ( allow_quoted && kind == TK_QDSTRING ) ) {
1307 *code = LDAP_SCHERR_UNEXPTOKEN;
1314 kind = get_token(sp,&sval);
1315 if ( kind == TK_RIGHTPAREN )
1317 if ( kind == TK_DOLLAR ) {
1319 kind = get_token(sp,&sval);
1320 if ( kind == TK_BAREWORD ||
1322 kind == TK_QDSTRING ) ) {
1323 if ( pos == size-2 ) {
1325 res1 = LDAP_REALLOC(res,size*sizeof(char *));
1329 *code = LDAP_SCHERR_OUTOFMEM;
1337 *code = LDAP_SCHERR_UNEXPTOKEN;
1344 *code = LDAP_SCHERR_UNEXPTOKEN;
1353 } else if ( kind == TK_BAREWORD ||
1354 ( allow_quoted && kind == TK_QDSTRING ) ) {
1355 res = LDAP_CALLOC(2,sizeof(char *));
1358 *code = LDAP_SCHERR_OUTOFMEM;
1367 *code = LDAP_SCHERR_BADNAME;
1373 add_extension(LDAPSchemaExtensionItem ***extensions,
1374 char * name, char ** values)
1377 LDAPSchemaExtensionItem **tmp, *ext;
1379 ext = LDAP_CALLOC(1, sizeof(LDAPSchemaExtensionItem));
1382 ext->lsei_name = name;
1383 ext->lsei_values = values;
1385 if ( !*extensions ) {
1387 LDAP_CALLOC(2, sizeof(LDAPSchemaExtensionItem *));
1392 for ( n=0; (*extensions)[n] != NULL; n++ )
1394 tmp = LDAP_REALLOC(*extensions,
1395 (n+2)*sizeof(LDAPSchemaExtensionItem *));
1400 (*extensions)[n] = ext;
1401 (*extensions)[n+1] = NULL;
1406 free_extensions(LDAPSchemaExtensionItem **extensions)
1408 LDAPSchemaExtensionItem **ext;
1411 for ( ext = extensions; *ext != NULL; ext++ ) {
1412 LDAP_FREE((*ext)->lsei_name);
1413 LDAP_VFREE((*ext)->lsei_values);
1416 LDAP_FREE(extensions);
1421 ldap_syntax_free( LDAPSyntax * syn )
1423 LDAP_FREE(syn->syn_oid);
1424 if (syn->syn_names) LDAP_VFREE(syn->syn_names);
1425 if (syn->syn_desc) LDAP_FREE(syn->syn_desc);
1426 free_extensions(syn->syn_extensions);
1431 ldap_str2syntax( LDAP_CONST char * s,
1433 LDAP_CONST char ** errp,
1434 LDAP_CONST unsigned flags )
1437 const char * ss = s;
1445 *code = LDAP_SCHERR_EMPTY;
1451 syn = LDAP_CALLOC(1,sizeof(LDAPSyntax));
1454 *code = LDAP_SCHERR_OUTOFMEM;
1458 kind = get_token(&ss,&sval);
1459 if ( kind != TK_LEFTPAREN ) {
1461 *code = LDAP_SCHERR_NOLEFTPAREN;
1462 ldap_syntax_free(syn);
1467 syn->syn_oid = ldap_int_parse_numericoid(&ss,code,0);
1468 if ( !syn->syn_oid ) {
1470 ldap_syntax_free(syn);
1476 * Beyond this point we will be liberal and accept the items
1480 kind = get_token(&ss,&sval);
1483 *code = LDAP_SCHERR_NORIGHTPAREN;
1485 ldap_syntax_free(syn);
1490 if ( !strcmp(sval,"NAME") ) {
1493 *code = LDAP_SCHERR_DUPOPT;
1495 ldap_syntax_free(syn);
1499 syn->syn_names = parse_qdescrs(&ss,code);
1500 if ( !syn->syn_names ) {
1501 if ( *code != LDAP_SCHERR_OUTOFMEM )
1502 *code = LDAP_SCHERR_BADNAME;
1504 ldap_syntax_free(syn);
1507 } else if ( !strcmp(sval,"DESC") ) {
1510 *code = LDAP_SCHERR_DUPOPT;
1512 ldap_syntax_free(syn);
1517 kind = get_token(&ss,&sval);
1518 if ( kind != TK_QDSTRING ) {
1519 *code = LDAP_SCHERR_UNEXPTOKEN;
1522 ldap_syntax_free(syn);
1525 syn->syn_desc = sval;
1527 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
1528 /* Should be parse_qdstrings */
1529 ext_vals = parse_qdescrs(&ss, code);
1532 ldap_syntax_free(syn);
1535 if ( add_extension(&syn->syn_extensions,
1537 *code = LDAP_SCHERR_OUTOFMEM;
1540 ldap_syntax_free(syn);
1544 *code = LDAP_SCHERR_UNEXPTOKEN;
1547 ldap_syntax_free(syn);
1552 *code = LDAP_SCHERR_UNEXPTOKEN;
1555 ldap_syntax_free(syn);
1562 ldap_matchingrule_free( LDAPMatchingRule * mr )
1564 LDAP_FREE(mr->mr_oid);
1565 if (mr->mr_names) LDAP_VFREE(mr->mr_names);
1566 if (mr->mr_desc) LDAP_FREE(mr->mr_desc);
1567 if (mr->mr_syntax_oid) LDAP_FREE(mr->mr_syntax_oid);
1568 free_extensions(mr->mr_extensions);
1573 ldap_str2matchingrule( LDAP_CONST char * s,
1575 LDAP_CONST char ** errp,
1576 LDAP_CONST unsigned flags )
1579 const char * ss = s;
1583 int seen_obsolete = 0;
1584 int seen_syntax = 0;
1585 LDAPMatchingRule * mr;
1587 const char * savepos;
1590 *code = LDAP_SCHERR_EMPTY;
1596 mr = LDAP_CALLOC(1,sizeof(LDAPMatchingRule));
1599 *code = LDAP_SCHERR_OUTOFMEM;
1603 kind = get_token(&ss,&sval);
1604 if ( kind != TK_LEFTPAREN ) {
1605 *code = LDAP_SCHERR_NOLEFTPAREN;
1607 ldap_matchingrule_free(mr);
1613 mr->mr_oid = ldap_int_parse_numericoid(&ss,code,flags);
1614 if ( !mr->mr_oid ) {
1615 if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) {
1618 kind = get_token(&ss,&sval);
1619 if ( kind == TK_BAREWORD ) {
1620 if ( !strcmp(sval, "NAME") ||
1621 !strcmp(sval, "DESC") ||
1622 !strcmp(sval, "OBSOLETE") ||
1623 !strcmp(sval, "SYNTAX") ||
1624 !strncmp(sval, "X-", 2) ) {
1625 /* Missing OID, backtrack */
1628 /* Non-numerical OID, ignore */
1634 ldap_matchingrule_free(mr);
1641 * Beyond this point we will be liberal and accept the items
1645 kind = get_token(&ss,&sval);
1648 *code = LDAP_SCHERR_NORIGHTPAREN;
1650 ldap_matchingrule_free(mr);
1653 if( !seen_syntax ) {
1654 *code = LDAP_SCHERR_MISSING;
1655 ldap_matchingrule_free(mr);
1660 if ( !strcmp(sval,"NAME") ) {
1663 *code = LDAP_SCHERR_DUPOPT;
1665 ldap_matchingrule_free(mr);
1669 mr->mr_names = parse_qdescrs(&ss,code);
1670 if ( !mr->mr_names ) {
1671 if ( *code != LDAP_SCHERR_OUTOFMEM )
1672 *code = LDAP_SCHERR_BADNAME;
1674 ldap_matchingrule_free(mr);
1677 } else if ( !strcmp(sval,"DESC") ) {
1680 *code = LDAP_SCHERR_DUPOPT;
1682 ldap_matchingrule_free(mr);
1687 kind = get_token(&ss,&sval);
1688 if ( kind != TK_QDSTRING ) {
1689 *code = LDAP_SCHERR_UNEXPTOKEN;
1692 ldap_matchingrule_free(mr);
1697 } else if ( !strcmp(sval,"OBSOLETE") ) {
1699 if ( seen_obsolete ) {
1700 *code = LDAP_SCHERR_DUPOPT;
1702 ldap_matchingrule_free(mr);
1706 mr->mr_obsolete = LDAP_SCHEMA_YES;
1708 } else if ( !strcmp(sval,"SYNTAX") ) {
1710 if ( seen_syntax ) {
1711 *code = LDAP_SCHERR_DUPOPT;
1713 ldap_matchingrule_free(mr);
1719 ldap_int_parse_numericoid(&ss,code,flags);
1720 if ( !mr->mr_syntax_oid ) {
1722 ldap_matchingrule_free(mr);
1726 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
1727 /* Should be parse_qdstrings */
1728 ext_vals = parse_qdescrs(&ss, code);
1731 ldap_matchingrule_free(mr);
1734 if ( add_extension(&mr->mr_extensions,
1736 *code = LDAP_SCHERR_OUTOFMEM;
1739 ldap_matchingrule_free(mr);
1743 *code = LDAP_SCHERR_UNEXPTOKEN;
1746 ldap_matchingrule_free(mr);
1751 *code = LDAP_SCHERR_UNEXPTOKEN;
1754 ldap_matchingrule_free(mr);
1761 ldap_matchingruleuse_free( LDAPMatchingRuleUse * mru )
1763 LDAP_FREE(mru->mru_oid);
1764 if (mru->mru_names) LDAP_VFREE(mru->mru_names);
1765 if (mru->mru_desc) LDAP_FREE(mru->mru_desc);
1766 if (mru->mru_applies_oids) LDAP_VFREE(mru->mru_applies_oids);
1767 free_extensions(mru->mru_extensions);
1771 LDAPMatchingRuleUse *
1772 ldap_str2matchingruleuse( LDAP_CONST char * s,
1774 LDAP_CONST char ** errp,
1775 LDAP_CONST unsigned flags )
1778 const char * ss = s;
1782 int seen_obsolete = 0;
1783 int seen_applies = 0;
1784 LDAPMatchingRuleUse * mru;
1786 const char * savepos;
1789 *code = LDAP_SCHERR_EMPTY;
1795 mru = LDAP_CALLOC(1,sizeof(LDAPMatchingRuleUse));
1798 *code = LDAP_SCHERR_OUTOFMEM;
1802 kind = get_token(&ss,&sval);
1803 if ( kind != TK_LEFTPAREN ) {
1804 *code = LDAP_SCHERR_NOLEFTPAREN;
1806 ldap_matchingruleuse_free(mru);
1812 mru->mru_oid = ldap_int_parse_numericoid(&ss,code,flags);
1813 if ( !mru->mru_oid ) {
1814 if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) {
1817 kind = get_token(&ss,&sval);
1818 if ( kind == TK_BAREWORD ) {
1819 if ( !strcmp(sval, "NAME") ||
1820 !strcmp(sval, "DESC") ||
1821 !strcmp(sval, "OBSOLETE") ||
1822 !strcmp(sval, "APPLIES") ||
1823 !strncmp(sval, "X-", 2) ) {
1824 /* Missing OID, backtrack */
1827 /* Non-numerical OID, ignore */
1833 ldap_matchingruleuse_free(mru);
1840 * Beyond this point we will be liberal and accept the items
1844 kind = get_token(&ss,&sval);
1847 *code = LDAP_SCHERR_NORIGHTPAREN;
1849 ldap_matchingruleuse_free(mru);
1852 if( !seen_applies ) {
1853 *code = LDAP_SCHERR_MISSING;
1854 ldap_matchingruleuse_free(mru);
1859 if ( !strcmp(sval,"NAME") ) {
1862 *code = LDAP_SCHERR_DUPOPT;
1864 ldap_matchingruleuse_free(mru);
1868 mru->mru_names = parse_qdescrs(&ss,code);
1869 if ( !mru->mru_names ) {
1870 if ( *code != LDAP_SCHERR_OUTOFMEM )
1871 *code = LDAP_SCHERR_BADNAME;
1873 ldap_matchingruleuse_free(mru);
1876 } else if ( !strcmp(sval,"DESC") ) {
1879 *code = LDAP_SCHERR_DUPOPT;
1881 ldap_matchingruleuse_free(mru);
1886 kind = get_token(&ss,&sval);
1887 if ( kind != TK_QDSTRING ) {
1888 *code = LDAP_SCHERR_UNEXPTOKEN;
1891 ldap_matchingruleuse_free(mru);
1894 mru->mru_desc = sval;
1896 } else if ( !strcmp(sval,"OBSOLETE") ) {
1898 if ( seen_obsolete ) {
1899 *code = LDAP_SCHERR_DUPOPT;
1901 ldap_matchingruleuse_free(mru);
1905 mru->mru_obsolete = LDAP_SCHEMA_YES;
1907 } else if ( !strcmp(sval,"APPLIES") ) {
1909 if ( seen_applies ) {
1910 *code = LDAP_SCHERR_DUPOPT;
1912 ldap_matchingruleuse_free(mru);
1916 mru->mru_applies_oids = parse_oids(&ss,
1919 if ( !mru->mru_applies_oids ) {
1921 ldap_matchingruleuse_free(mru);
1924 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
1925 /* Should be parse_qdstrings */
1926 ext_vals = parse_qdescrs(&ss, code);
1929 ldap_matchingruleuse_free(mru);
1932 if ( add_extension(&mru->mru_extensions,
1934 *code = LDAP_SCHERR_OUTOFMEM;
1937 ldap_matchingruleuse_free(mru);
1941 *code = LDAP_SCHERR_UNEXPTOKEN;
1944 ldap_matchingruleuse_free(mru);
1949 *code = LDAP_SCHERR_UNEXPTOKEN;
1952 ldap_matchingruleuse_free(mru);
1959 ldap_attributetype_free(LDAPAttributeType * at)
1961 LDAP_FREE(at->at_oid);
1962 if (at->at_names) LDAP_VFREE(at->at_names);
1963 if (at->at_desc) LDAP_FREE(at->at_desc);
1964 if (at->at_sup_oid) LDAP_FREE(at->at_sup_oid);
1965 if (at->at_equality_oid) LDAP_FREE(at->at_equality_oid);
1966 if (at->at_ordering_oid) LDAP_FREE(at->at_ordering_oid);
1967 if (at->at_substr_oid) LDAP_FREE(at->at_substr_oid);
1968 if (at->at_syntax_oid) LDAP_FREE(at->at_syntax_oid);
1969 free_extensions(at->at_extensions);
1974 ldap_str2attributetype( LDAP_CONST char * s,
1976 LDAP_CONST char ** errp,
1977 LDAP_CONST unsigned flags )
1980 const char * ss = s;
1984 int seen_obsolete = 0;
1986 int seen_equality = 0;
1987 int seen_ordering = 0;
1988 int seen_substr = 0;
1989 int seen_syntax = 0;
1991 LDAPAttributeType * at;
1993 const char * savepos;
1996 *code = LDAP_SCHERR_EMPTY;
2002 at = LDAP_CALLOC(1,sizeof(LDAPAttributeType));
2005 *code = LDAP_SCHERR_OUTOFMEM;
2009 kind = get_token(&ss,&sval);
2010 if ( kind != TK_LEFTPAREN ) {
2011 *code = LDAP_SCHERR_NOLEFTPAREN;
2013 ldap_attributetype_free(at);
2018 * Definitions MUST begin with an OID in the numericoid format.
2019 * However, this routine is used by clients to parse the response
2020 * from servers and very well known servers will provide an OID
2021 * in the wrong format or even no OID at all. We do our best to
2022 * extract info from those servers.
2026 at->at_oid = ldap_int_parse_numericoid(&ss,code,0);
2027 if ( !at->at_oid ) {
2028 if ( ( flags & ( LDAP_SCHEMA_ALLOW_NO_OID
2029 | LDAP_SCHEMA_ALLOW_OID_MACRO ) )
2030 && (ss == savepos) ) {
2033 kind = get_token(&ss,&sval);
2034 if ( kind == TK_BAREWORD ) {
2035 if ( !strcmp(sval, "NAME") ||
2036 !strcmp(sval, "DESC") ||
2037 !strcmp(sval, "OBSOLETE") ||
2038 !strcmp(sval, "SUP") ||
2039 !strcmp(sval, "EQUALITY") ||
2040 !strcmp(sval, "ORDERING") ||
2041 !strcmp(sval, "SUBSTR") ||
2042 !strcmp(sval, "SYNTAX") ||
2043 !strcmp(sval, "SINGLE-VALUE") ||
2044 !strcmp(sval, "COLLECTIVE") ||
2045 !strcmp(sval, "NO-USER-MODIFICATION") ||
2046 !strcmp(sval, "USAGE") ||
2047 !strncmp(sval, "X-", 2) ) {
2048 /* Missing OID, backtrack */
2051 & LDAP_SCHEMA_ALLOW_OID_MACRO) {
2052 /* Non-numerical OID ... */
2053 int len = ss-savepos;
2054 at->at_oid = LDAP_MALLOC(len+1);
2055 strncpy(at->at_oid, savepos, len);
2056 at->at_oid[len] = 0;
2062 ldap_attributetype_free(at);
2069 * Beyond this point we will be liberal and accept the items
2073 kind = get_token(&ss,&sval);
2076 *code = LDAP_SCHERR_NORIGHTPAREN;
2078 ldap_attributetype_free(at);
2083 if ( !strcmp(sval,"NAME") ) {
2086 *code = LDAP_SCHERR_DUPOPT;
2088 ldap_attributetype_free(at);
2092 at->at_names = parse_qdescrs(&ss,code);
2093 if ( !at->at_names ) {
2094 if ( *code != LDAP_SCHERR_OUTOFMEM )
2095 *code = LDAP_SCHERR_BADNAME;
2097 ldap_attributetype_free(at);
2100 } else if ( !strcmp(sval,"DESC") ) {
2103 *code = LDAP_SCHERR_DUPOPT;
2105 ldap_attributetype_free(at);
2110 kind = get_token(&ss,&sval);
2111 if ( kind != TK_QDSTRING ) {
2112 *code = LDAP_SCHERR_UNEXPTOKEN;
2115 ldap_attributetype_free(at);
2120 } else if ( !strcmp(sval,"OBSOLETE") ) {
2122 if ( seen_obsolete ) {
2123 *code = LDAP_SCHERR_DUPOPT;
2125 ldap_attributetype_free(at);
2129 at->at_obsolete = LDAP_SCHEMA_YES;
2131 } else if ( !strcmp(sval,"SUP") ) {
2134 *code = LDAP_SCHERR_DUPOPT;
2136 ldap_attributetype_free(at);
2140 at->at_sup_oid = parse_woid(&ss,code);
2141 if ( !at->at_sup_oid ) {
2143 ldap_attributetype_free(at);
2146 } else if ( !strcmp(sval,"EQUALITY") ) {
2148 if ( seen_equality ) {
2149 *code = LDAP_SCHERR_DUPOPT;
2151 ldap_attributetype_free(at);
2155 at->at_equality_oid = parse_woid(&ss,code);
2156 if ( !at->at_equality_oid ) {
2158 ldap_attributetype_free(at);
2161 } else if ( !strcmp(sval,"ORDERING") ) {
2163 if ( seen_ordering ) {
2164 *code = LDAP_SCHERR_DUPOPT;
2166 ldap_attributetype_free(at);
2170 at->at_ordering_oid = parse_woid(&ss,code);
2171 if ( !at->at_ordering_oid ) {
2173 ldap_attributetype_free(at);
2176 } else if ( !strcmp(sval,"SUBSTR") ) {
2178 if ( seen_substr ) {
2179 *code = LDAP_SCHERR_DUPOPT;
2181 ldap_attributetype_free(at);
2185 at->at_substr_oid = parse_woid(&ss,code);
2186 if ( !at->at_substr_oid ) {
2188 ldap_attributetype_free(at);
2191 } else if ( !strcmp(sval,"SYNTAX") ) {
2193 if ( seen_syntax ) {
2194 *code = LDAP_SCHERR_DUPOPT;
2196 ldap_attributetype_free(at);
2207 if ( !at->at_syntax_oid ) {
2208 if ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2209 kind = get_token(&ss,&sval);
2210 if (kind == TK_BAREWORD)
2212 char *sp = strchr(sval, '{');
2213 at->at_syntax_oid = sval;
2217 at->at_syntax_len = atoi(sp);
2218 while ( LDAP_DIGIT(*sp) )
2221 *code = LDAP_SCHERR_UNEXPTOKEN;
2223 ldap_attributetype_free(at);
2230 ldap_attributetype_free(at);
2235 } else if ( !strcmp(sval,"SINGLE-VALUE") ) {
2237 if ( at->at_single_value ) {
2238 *code = LDAP_SCHERR_DUPOPT;
2240 ldap_attributetype_free(at);
2243 at->at_single_value = LDAP_SCHEMA_YES;
2245 } else if ( !strcmp(sval,"COLLECTIVE") ) {
2247 if ( at->at_collective ) {
2248 *code = LDAP_SCHERR_DUPOPT;
2250 ldap_attributetype_free(at);
2253 at->at_collective = LDAP_SCHEMA_YES;
2255 } else if ( !strcmp(sval,"NO-USER-MODIFICATION") ) {
2257 if ( at->at_no_user_mod ) {
2258 *code = LDAP_SCHERR_DUPOPT;
2260 ldap_attributetype_free(at);
2263 at->at_no_user_mod = LDAP_SCHEMA_YES;
2265 } else if ( !strcmp(sval,"USAGE") ) {
2268 *code = LDAP_SCHERR_DUPOPT;
2270 ldap_attributetype_free(at);
2275 kind = get_token(&ss,&sval);
2276 if ( kind != TK_BAREWORD ) {
2277 *code = LDAP_SCHERR_UNEXPTOKEN;
2280 ldap_attributetype_free(at);
2283 if ( !strcasecmp(sval,"userApplications") )
2285 LDAP_SCHEMA_USER_APPLICATIONS;
2286 else if ( !strcasecmp(sval,"directoryOperation") )
2288 LDAP_SCHEMA_DIRECTORY_OPERATION;
2289 else if ( !strcasecmp(sval,"distributedOperation") )
2291 LDAP_SCHEMA_DISTRIBUTED_OPERATION;
2292 else if ( !strcasecmp(sval,"dSAOperation") )
2294 LDAP_SCHEMA_DSA_OPERATION;
2296 *code = LDAP_SCHERR_UNEXPTOKEN;
2299 ldap_attributetype_free(at);
2304 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
2305 /* Should be parse_qdstrings */
2306 ext_vals = parse_qdescrs(&ss, code);
2309 ldap_attributetype_free(at);
2312 if ( add_extension(&at->at_extensions,
2314 *code = LDAP_SCHERR_OUTOFMEM;
2317 ldap_attributetype_free(at);
2321 *code = LDAP_SCHERR_UNEXPTOKEN;
2324 ldap_attributetype_free(at);
2329 *code = LDAP_SCHERR_UNEXPTOKEN;
2332 ldap_attributetype_free(at);
2339 ldap_objectclass_free(LDAPObjectClass * oc)
2341 LDAP_FREE(oc->oc_oid);
2342 if (oc->oc_names) LDAP_VFREE(oc->oc_names);
2343 if (oc->oc_desc) LDAP_FREE(oc->oc_desc);
2344 if (oc->oc_sup_oids) LDAP_VFREE(oc->oc_sup_oids);
2345 if (oc->oc_at_oids_must) LDAP_VFREE(oc->oc_at_oids_must);
2346 if (oc->oc_at_oids_may) LDAP_VFREE(oc->oc_at_oids_may);
2347 free_extensions(oc->oc_extensions);
2352 ldap_str2objectclass( LDAP_CONST char * s,
2354 LDAP_CONST char ** errp,
2355 LDAP_CONST unsigned flags )
2358 const char * ss = s;
2362 int seen_obsolete = 0;
2367 LDAPObjectClass * oc;
2369 const char * savepos;
2372 *code = LDAP_SCHERR_EMPTY;
2378 oc = LDAP_CALLOC(1,sizeof(LDAPObjectClass));
2381 *code = LDAP_SCHERR_OUTOFMEM;
2384 oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
2386 kind = get_token(&ss,&sval);
2387 if ( kind != TK_LEFTPAREN ) {
2388 *code = LDAP_SCHERR_NOLEFTPAREN;
2390 ldap_objectclass_free(oc);
2395 * Definitions MUST begin with an OID in the numericoid format.
2396 * However, this routine is used by clients to parse the response
2397 * from servers and very well known servers will provide an OID
2398 * in the wrong format or even no OID at all. We do our best to
2399 * extract info from those servers.
2403 oc->oc_oid = ldap_int_parse_numericoid(&ss,code,0);
2404 if ( !oc->oc_oid ) {
2405 if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) {
2408 kind = get_token(&ss,&sval);
2409 if ( kind == TK_BAREWORD ) {
2410 if ( !strcmp(sval, "NAME") ||
2411 !strcmp(sval, "DESC") ||
2412 !strcmp(sval, "OBSOLETE") ||
2413 !strcmp(sval, "SUP") ||
2414 !strcmp(sval, "ABSTRACT") ||
2415 !strcmp(sval, "STRUCTURAL") ||
2416 !strcmp(sval, "AUXILIARY") ||
2417 !strcmp(sval, "MUST") ||
2418 !strcmp(sval, "MAY") ||
2419 !strncmp(sval, "X-", 2) ) {
2420 /* Missing OID, backtrack */
2423 LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2424 /* Non-numerical OID, ignore */
2425 int len = ss-savepos;
2426 oc->oc_oid = LDAP_MALLOC(len+1);
2427 strncpy(oc->oc_oid, savepos, len);
2428 oc->oc_oid[len] = 0;
2434 ldap_objectclass_free(oc);
2441 * Beyond this point we will be liberal an accept the items
2445 kind = get_token(&ss,&sval);
2448 *code = LDAP_SCHERR_NORIGHTPAREN;
2450 ldap_objectclass_free(oc);
2455 if ( !strcmp(sval,"NAME") ) {
2458 *code = LDAP_SCHERR_DUPOPT;
2460 ldap_objectclass_free(oc);
2464 oc->oc_names = parse_qdescrs(&ss,code);
2465 if ( !oc->oc_names ) {
2466 if ( *code != LDAP_SCHERR_OUTOFMEM )
2467 *code = LDAP_SCHERR_BADNAME;
2469 ldap_objectclass_free(oc);
2472 } else if ( !strcmp(sval,"DESC") ) {
2475 *code = LDAP_SCHERR_DUPOPT;
2477 ldap_objectclass_free(oc);
2482 kind = get_token(&ss,&sval);
2483 if ( kind != TK_QDSTRING ) {
2484 *code = LDAP_SCHERR_UNEXPTOKEN;
2487 ldap_objectclass_free(oc);
2492 } else if ( !strcmp(sval,"OBSOLETE") ) {
2494 if ( seen_obsolete ) {
2495 *code = LDAP_SCHERR_DUPOPT;
2497 ldap_objectclass_free(oc);
2501 oc->oc_obsolete = LDAP_SCHEMA_YES;
2503 } else if ( !strcmp(sval,"SUP") ) {
2506 *code = LDAP_SCHERR_DUPOPT;
2508 ldap_objectclass_free(oc);
2512 oc->oc_sup_oids = parse_oids(&ss,
2515 if ( !oc->oc_sup_oids ) {
2517 ldap_objectclass_free(oc);
2520 } else if ( !strcmp(sval,"ABSTRACT") ) {
2523 *code = LDAP_SCHERR_DUPOPT;
2525 ldap_objectclass_free(oc);
2529 oc->oc_kind = LDAP_SCHEMA_ABSTRACT;
2531 } else if ( !strcmp(sval,"STRUCTURAL") ) {
2534 *code = LDAP_SCHERR_DUPOPT;
2536 ldap_objectclass_free(oc);
2540 oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
2542 } else if ( !strcmp(sval,"AUXILIARY") ) {
2545 *code = LDAP_SCHERR_DUPOPT;
2547 ldap_objectclass_free(oc);
2551 oc->oc_kind = LDAP_SCHEMA_AUXILIARY;
2553 } else if ( !strcmp(sval,"MUST") ) {
2556 *code = LDAP_SCHERR_DUPOPT;
2558 ldap_objectclass_free(oc);
2562 oc->oc_at_oids_must = parse_oids(&ss,code,0);
2563 if ( !oc->oc_at_oids_must ) {
2565 ldap_objectclass_free(oc);
2569 } else if ( !strcmp(sval,"MAY") ) {
2572 *code = LDAP_SCHERR_DUPOPT;
2574 ldap_objectclass_free(oc);
2578 oc->oc_at_oids_may = parse_oids(&ss,code,0);
2579 if ( !oc->oc_at_oids_may ) {
2581 ldap_objectclass_free(oc);
2585 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
2586 /* Should be parse_qdstrings */
2587 ext_vals = parse_qdescrs(&ss, code);
2590 ldap_objectclass_free(oc);
2593 if ( add_extension(&oc->oc_extensions,
2595 *code = LDAP_SCHERR_OUTOFMEM;
2598 ldap_objectclass_free(oc);
2602 *code = LDAP_SCHERR_UNEXPTOKEN;
2605 ldap_objectclass_free(oc);
2610 *code = LDAP_SCHERR_UNEXPTOKEN;
2613 ldap_objectclass_free(oc);
2620 ldap_contentrule_free(LDAPContentRule * cr)
2622 LDAP_FREE(cr->cr_oid);
2623 if (cr->cr_names) LDAP_VFREE(cr->cr_names);
2624 if (cr->cr_desc) LDAP_FREE(cr->cr_desc);
2625 if (cr->cr_oc_oids_aux) LDAP_VFREE(cr->cr_oc_oids_aux);
2626 if (cr->cr_at_oids_must) LDAP_VFREE(cr->cr_at_oids_must);
2627 if (cr->cr_at_oids_may) LDAP_VFREE(cr->cr_at_oids_may);
2628 if (cr->cr_at_oids_not) LDAP_VFREE(cr->cr_at_oids_not);
2629 free_extensions(cr->cr_extensions);
2634 ldap_str2contentrule( LDAP_CONST char * s,
2636 LDAP_CONST char ** errp,
2637 LDAP_CONST unsigned flags )
2640 const char * ss = s;
2644 int seen_obsolete = 0;
2649 LDAPContentRule * cr;
2651 const char * savepos;
2654 *code = LDAP_SCHERR_EMPTY;
2660 cr = LDAP_CALLOC(1,sizeof(LDAPContentRule));
2663 *code = LDAP_SCHERR_OUTOFMEM;
2667 kind = get_token(&ss,&sval);
2668 if ( kind != TK_LEFTPAREN ) {
2669 *code = LDAP_SCHERR_NOLEFTPAREN;
2671 ldap_contentrule_free(cr);
2676 * Definitions MUST begin with an OID in the numericoid format.
2680 cr->cr_oid = ldap_int_parse_numericoid(&ss,code,0);
2681 if ( !cr->cr_oid ) {
2683 ldap_contentrule_free(cr);
2689 * Beyond this point we will be liberal an accept the items
2693 kind = get_token(&ss,&sval);
2696 *code = LDAP_SCHERR_NORIGHTPAREN;
2698 ldap_contentrule_free(cr);
2703 if ( !strcmp(sval,"NAME") ) {
2706 *code = LDAP_SCHERR_DUPOPT;
2708 ldap_contentrule_free(cr);
2712 cr->cr_names = parse_qdescrs(&ss,code);
2713 if ( !cr->cr_names ) {
2714 if ( *code != LDAP_SCHERR_OUTOFMEM )
2715 *code = LDAP_SCHERR_BADNAME;
2717 ldap_contentrule_free(cr);
2720 } else if ( !strcmp(sval,"DESC") ) {
2723 *code = LDAP_SCHERR_DUPOPT;
2725 ldap_contentrule_free(cr);
2730 kind = get_token(&ss,&sval);
2731 if ( kind != TK_QDSTRING ) {
2732 *code = LDAP_SCHERR_UNEXPTOKEN;
2735 ldap_contentrule_free(cr);
2740 } else if ( !strcmp(sval,"OBSOLETE") ) {
2742 if ( seen_obsolete ) {
2743 *code = LDAP_SCHERR_DUPOPT;
2745 ldap_contentrule_free(cr);
2749 cr->cr_obsolete = LDAP_SCHEMA_YES;
2751 } else if ( !strcmp(sval,"AUX") ) {
2754 *code = LDAP_SCHERR_DUPOPT;
2756 ldap_contentrule_free(cr);
2760 cr->cr_oc_oids_aux = parse_oids(&ss,code,0);
2761 if ( !cr->cr_oc_oids_aux ) {
2763 ldap_contentrule_free(cr);
2767 } else if ( !strcmp(sval,"MUST") ) {
2770 *code = LDAP_SCHERR_DUPOPT;
2772 ldap_contentrule_free(cr);
2776 cr->cr_at_oids_must = parse_oids(&ss,code,0);
2777 if ( !cr->cr_at_oids_must ) {
2779 ldap_contentrule_free(cr);
2783 } else if ( !strcmp(sval,"MAY") ) {
2786 *code = LDAP_SCHERR_DUPOPT;
2788 ldap_contentrule_free(cr);
2792 cr->cr_at_oids_may = parse_oids(&ss,code,0);
2793 if ( !cr->cr_at_oids_may ) {
2795 ldap_contentrule_free(cr);
2799 } else if ( !strcmp(sval,"NOT") ) {
2802 *code = LDAP_SCHERR_DUPOPT;
2804 ldap_contentrule_free(cr);
2808 cr->cr_at_oids_not = parse_oids(&ss,code,0);
2809 if ( !cr->cr_at_oids_not ) {
2811 ldap_contentrule_free(cr);
2815 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
2816 /* Should be parse_qdstrings */
2817 ext_vals = parse_qdescrs(&ss, code);
2820 ldap_contentrule_free(cr);
2823 if ( add_extension(&cr->cr_extensions,
2825 *code = LDAP_SCHERR_OUTOFMEM;
2828 ldap_contentrule_free(cr);
2832 *code = LDAP_SCHERR_UNEXPTOKEN;
2835 ldap_contentrule_free(cr);
2840 *code = LDAP_SCHERR_UNEXPTOKEN;
2843 ldap_contentrule_free(cr);
2850 ldap_structurerule_free(LDAPStructureRule * sr)
2852 if (sr->sr_names) LDAP_VFREE(sr->sr_names);
2853 if (sr->sr_desc) LDAP_FREE(sr->sr_desc);
2854 if (sr->sr_nameform) LDAP_FREE(sr->sr_nameform);
2855 if (sr->sr_sup_ruleids) LDAP_FREE(sr->sr_sup_ruleids);
2856 free_extensions(sr->sr_extensions);
2861 ldap_str2structurerule( LDAP_CONST char * s,
2863 LDAP_CONST char ** errp,
2864 LDAP_CONST unsigned flags )
2867 const char * ss = s;
2871 int seen_obsolete = 0;
2872 int seen_nameform = 0;
2873 LDAPStructureRule * sr;
2875 const char * savepos;
2878 *code = LDAP_SCHERR_EMPTY;
2884 sr = LDAP_CALLOC(1,sizeof(LDAPStructureRule));
2887 *code = LDAP_SCHERR_OUTOFMEM;
2891 kind = get_token(&ss,&sval);
2892 if ( kind != TK_LEFTPAREN ) {
2893 *code = LDAP_SCHERR_NOLEFTPAREN;
2895 ldap_structurerule_free(sr);
2900 * Definitions MUST begin with a ruleid.
2904 ret = ldap_int_parse_ruleid(&ss,code,0,&sr->sr_ruleid);
2907 ldap_structurerule_free(sr);
2913 * Beyond this point we will be liberal an accept the items
2917 kind = get_token(&ss,&sval);
2920 *code = LDAP_SCHERR_NORIGHTPAREN;
2922 ldap_structurerule_free(sr);
2925 if( !seen_nameform ) {
2926 *code = LDAP_SCHERR_MISSING;
2927 ldap_structurerule_free(sr);
2932 if ( !strcmp(sval,"NAME") ) {
2935 *code = LDAP_SCHERR_DUPOPT;
2937 ldap_structurerule_free(sr);
2941 sr->sr_names = parse_qdescrs(&ss,code);
2942 if ( !sr->sr_names ) {
2943 if ( *code != LDAP_SCHERR_OUTOFMEM )
2944 *code = LDAP_SCHERR_BADNAME;
2946 ldap_structurerule_free(sr);
2949 } else if ( !strcmp(sval,"DESC") ) {
2952 *code = LDAP_SCHERR_DUPOPT;
2954 ldap_structurerule_free(sr);
2959 kind = get_token(&ss,&sval);
2960 if ( kind != TK_QDSTRING ) {
2961 *code = LDAP_SCHERR_UNEXPTOKEN;
2964 ldap_structurerule_free(sr);
2969 } else if ( !strcmp(sval,"OBSOLETE") ) {
2971 if ( seen_obsolete ) {
2972 *code = LDAP_SCHERR_DUPOPT;
2974 ldap_structurerule_free(sr);
2978 sr->sr_obsolete = LDAP_SCHEMA_YES;
2980 } else if ( !strcmp(sval,"FORM") ) {
2982 if ( seen_nameform ) {
2983 *code = LDAP_SCHERR_DUPOPT;
2985 ldap_structurerule_free(sr);
2989 sr->sr_nameform = parse_woid(&ss,code);
2990 if ( !sr->sr_nameform ) {
2992 ldap_structurerule_free(sr);
2996 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
2997 /* Should be parse_qdstrings */
2998 ext_vals = parse_qdescrs(&ss, code);
3001 ldap_structurerule_free(sr);
3004 if ( add_extension(&sr->sr_extensions,
3006 *code = LDAP_SCHERR_OUTOFMEM;
3009 ldap_structurerule_free(sr);
3013 *code = LDAP_SCHERR_UNEXPTOKEN;
3016 ldap_structurerule_free(sr);
3021 *code = LDAP_SCHERR_UNEXPTOKEN;
3024 ldap_structurerule_free(sr);
3031 ldap_nameform_free(LDAPNameForm * nf)
3033 LDAP_FREE(nf->nf_oid);
3034 if (nf->nf_names) LDAP_VFREE(nf->nf_names);
3035 if (nf->nf_desc) LDAP_FREE(nf->nf_desc);
3036 if (nf->nf_objectclass) LDAP_FREE(nf->nf_objectclass);
3037 if (nf->nf_at_oids_must) LDAP_VFREE(nf->nf_at_oids_must);
3038 if (nf->nf_at_oids_may) LDAP_VFREE(nf->nf_at_oids_may);
3039 free_extensions(nf->nf_extensions);
3044 ldap_str2nameform( LDAP_CONST char * s,
3046 LDAP_CONST char ** errp,
3047 LDAP_CONST unsigned flags )
3050 const char * ss = s;
3054 int seen_obsolete = 0;
3060 const char * savepos;
3063 *code = LDAP_SCHERR_EMPTY;
3069 nf = LDAP_CALLOC(1,sizeof(LDAPNameForm));
3072 *code = LDAP_SCHERR_OUTOFMEM;
3076 kind = get_token(&ss,&sval);
3077 if ( kind != TK_LEFTPAREN ) {
3078 *code = LDAP_SCHERR_NOLEFTPAREN;
3080 ldap_nameform_free(nf);
3085 * Definitions MUST begin with an OID in the numericoid format.
3086 * However, this routine is used by clients to parse the response
3087 * from servers and very well known servers will provide an OID
3088 * in the wrong format or even no OID at all. We do our best to
3089 * extract info from those servers.
3093 nf->nf_oid = ldap_int_parse_numericoid(&ss,code,0);
3094 if ( !nf->nf_oid ) {
3096 ldap_nameform_free(nf);
3102 * Beyond this point we will be liberal an accept the items
3106 kind = get_token(&ss,&sval);
3109 *code = LDAP_SCHERR_NORIGHTPAREN;
3111 ldap_nameform_free(nf);
3114 if( !seen_class || !seen_must ) {
3115 *code = LDAP_SCHERR_MISSING;
3116 ldap_nameform_free(nf);
3121 if ( !strcmp(sval,"NAME") ) {
3124 *code = LDAP_SCHERR_DUPOPT;
3126 ldap_nameform_free(nf);
3130 nf->nf_names = parse_qdescrs(&ss,code);
3131 if ( !nf->nf_names ) {
3132 if ( *code != LDAP_SCHERR_OUTOFMEM )
3133 *code = LDAP_SCHERR_BADNAME;
3135 ldap_nameform_free(nf);
3138 } else if ( !strcmp(sval,"DESC") ) {
3141 *code = LDAP_SCHERR_DUPOPT;
3143 ldap_nameform_free(nf);
3148 kind = get_token(&ss,&sval);
3149 if ( kind != TK_QDSTRING ) {
3150 *code = LDAP_SCHERR_UNEXPTOKEN;
3153 ldap_nameform_free(nf);
3158 } else if ( !strcmp(sval,"OBSOLETE") ) {
3160 if ( seen_obsolete ) {
3161 *code = LDAP_SCHERR_DUPOPT;
3163 ldap_nameform_free(nf);
3167 nf->nf_obsolete = LDAP_SCHEMA_YES;
3169 } else if ( !strcmp(sval,"MUST") ) {
3172 *code = LDAP_SCHERR_DUPOPT;
3174 ldap_nameform_free(nf);
3178 nf->nf_at_oids_must = parse_oids(&ss,code,0);
3179 if ( !nf->nf_at_oids_must ) {
3181 ldap_nameform_free(nf);
3185 } else if ( !strcmp(sval,"MAY") ) {
3188 *code = LDAP_SCHERR_DUPOPT;
3190 ldap_nameform_free(nf);
3194 nf->nf_at_oids_may = parse_oids(&ss,code,0);
3195 if ( !nf->nf_at_oids_may ) {
3197 ldap_nameform_free(nf);
3201 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
3202 /* Should be parse_qdstrings */
3203 ext_vals = parse_qdescrs(&ss, code);
3206 ldap_nameform_free(nf);
3209 if ( add_extension(&nf->nf_extensions,
3211 *code = LDAP_SCHERR_OUTOFMEM;
3214 ldap_nameform_free(nf);
3218 *code = LDAP_SCHERR_UNEXPTOKEN;
3221 ldap_nameform_free(nf);
3226 *code = LDAP_SCHERR_UNEXPTOKEN;
3229 ldap_nameform_free(nf);
3235 static char *const err2text[] = {
3237 N_("Out of memory"),
3238 N_("Unexpected token"),
3239 N_("Missing opening parenthesis"),
3240 N_("Missing closing parenthesis"),
3241 N_("Expecting digit"),
3242 N_("Expecting a name"),
3243 N_("Bad description"),
3244 N_("Bad superiors"),
3245 N_("Duplicate option"),
3246 N_("Unexpected end of data"),
3247 N_("Missing required field"),
3248 N_("Out of order field")
3252 ldap_scherr2str(int code)
3254 if ( code < 0 || code >= (int)(sizeof(err2text)/sizeof(char *)) ) {
3255 return _("Unknown error");
3257 return _(err2text[code]);