2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2005 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).
962 #define TK_NOENDQUOTE -2
963 #define TK_OUTOFMEM -1
965 #define TK_UNEXPCHAR 1
966 #define TK_BAREWORD 2
967 #define TK_QDSTRING 3
968 #define TK_LEFTPAREN 4
969 #define TK_RIGHTPAREN 5
971 #define TK_QDESCR TK_QDSTRING
979 get_token( const char ** sp, char ** token_val )
997 kind = TK_RIGHTPAREN;
1008 while ( **sp != '\'' && **sp != '\0' )
1010 if ( **sp == '\'' ) {
1012 res = LDAP_MALLOC(q-p+1);
1022 kind = TK_NOENDQUOTE;
1028 while ( !LDAP_SPACE(**sp) &&
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 allow_quoted)
1241 /* Netscape puts the SYNTAX value in quotes (incorrectly) */
1242 if ( allow_quoted && **sp == '\'' ) {
1246 sval = ldap_int_parse_numericoid(sp, code, 0);
1250 if ( **sp == '{' /*}*/ ) {
1253 while ( LDAP_DIGIT(**sp) )
1255 if ( **sp != /*{*/ '}' ) {
1256 *code = LDAP_SCHERR_UNEXPTOKEN;
1262 if ( allow_quoted && quoted ) {
1263 if ( **sp == '\'' ) {
1266 *code = LDAP_SCHERR_UNEXPTOKEN;
1275 * Next routine will accept a qdstring in place of an oid if
1276 * allow_quoted is set. This is necessary to interoperate with
1277 * Netscape Directory server that will improperly quote each oid (at
1278 * least those of the descr kind) in the SUP clause.
1281 /* Parse a woid or a $-separated list of them enclosed in () */
1283 parse_oids(const char **sp, int *code, const int allow_quoted)
1293 * Strictly speaking, doing this here accepts whsp before the
1294 * ( at the begining of an oidlist, but this is harmless. Also,
1295 * we are very liberal in what we accept as an OID. Maybe
1299 kind = get_token(sp,&sval);
1300 if ( kind == TK_LEFTPAREN ) {
1301 /* Let's presume there will be at least 2 entries */
1303 res = LDAP_CALLOC(3,sizeof(char *));
1305 *code = LDAP_SCHERR_OUTOFMEM;
1310 kind = get_token(sp,&sval);
1311 if ( kind == TK_BAREWORD ||
1312 ( allow_quoted && kind == TK_QDSTRING ) ) {
1315 } else if ( kind == TK_RIGHTPAREN ) {
1316 /* FIXME: be liberal in what we accept... */
1321 *code = LDAP_SCHERR_UNEXPTOKEN;
1328 kind = get_token(sp,&sval);
1329 if ( kind == TK_RIGHTPAREN )
1331 if ( kind == TK_DOLLAR ) {
1333 kind = get_token(sp,&sval);
1334 if ( kind == TK_BAREWORD ||
1336 kind == TK_QDSTRING ) ) {
1337 if ( pos == size-2 ) {
1339 res1 = LDAP_REALLOC(res,size*sizeof(char *));
1343 *code = LDAP_SCHERR_OUTOFMEM;
1351 *code = LDAP_SCHERR_UNEXPTOKEN;
1358 *code = LDAP_SCHERR_UNEXPTOKEN;
1366 } else if ( kind == TK_BAREWORD ||
1367 ( allow_quoted && kind == TK_QDSTRING ) ) {
1368 res = LDAP_CALLOC(2,sizeof(char *));
1371 *code = LDAP_SCHERR_OUTOFMEM;
1380 *code = LDAP_SCHERR_BADNAME;
1386 add_extension(LDAPSchemaExtensionItem ***extensions,
1387 char * name, char ** values)
1390 LDAPSchemaExtensionItem **tmp, *ext;
1392 ext = LDAP_CALLOC(1, sizeof(LDAPSchemaExtensionItem));
1395 ext->lsei_name = name;
1396 ext->lsei_values = values;
1398 if ( !*extensions ) {
1400 LDAP_CALLOC(2, sizeof(LDAPSchemaExtensionItem *));
1405 for ( n=0; (*extensions)[n] != NULL; n++ )
1407 tmp = LDAP_REALLOC(*extensions,
1408 (n+2)*sizeof(LDAPSchemaExtensionItem *));
1413 (*extensions)[n] = ext;
1414 (*extensions)[n+1] = NULL;
1419 free_extensions(LDAPSchemaExtensionItem **extensions)
1421 LDAPSchemaExtensionItem **ext;
1424 for ( ext = extensions; *ext != NULL; ext++ ) {
1425 LDAP_FREE((*ext)->lsei_name);
1426 LDAP_VFREE((*ext)->lsei_values);
1429 LDAP_FREE(extensions);
1434 ldap_syntax_free( LDAPSyntax * syn )
1436 LDAP_FREE(syn->syn_oid);
1437 if (syn->syn_names) LDAP_VFREE(syn->syn_names);
1438 if (syn->syn_desc) LDAP_FREE(syn->syn_desc);
1439 free_extensions(syn->syn_extensions);
1444 ldap_str2syntax( LDAP_CONST char * s,
1446 LDAP_CONST char ** errp,
1447 LDAP_CONST unsigned flags )
1450 const char * ss = s;
1458 *code = LDAP_SCHERR_EMPTY;
1464 syn = LDAP_CALLOC(1,sizeof(LDAPSyntax));
1467 *code = LDAP_SCHERR_OUTOFMEM;
1471 kind = get_token(&ss,&sval);
1472 if ( kind != TK_LEFTPAREN ) {
1474 *code = LDAP_SCHERR_NOLEFTPAREN;
1475 ldap_syntax_free(syn);
1480 syn->syn_oid = ldap_int_parse_numericoid(&ss,code,0);
1481 if ( !syn->syn_oid ) {
1483 ldap_syntax_free(syn);
1489 * Beyond this point we will be liberal and accept the items
1493 kind = get_token(&ss,&sval);
1496 *code = LDAP_SCHERR_NORIGHTPAREN;
1498 ldap_syntax_free(syn);
1503 if ( !strcasecmp(sval,"NAME") ) {
1506 *code = LDAP_SCHERR_DUPOPT;
1508 ldap_syntax_free(syn);
1512 syn->syn_names = parse_qdescrs(&ss,code);
1513 if ( !syn->syn_names ) {
1514 if ( *code != LDAP_SCHERR_OUTOFMEM )
1515 *code = LDAP_SCHERR_BADNAME;
1517 ldap_syntax_free(syn);
1520 } else if ( !strcasecmp(sval,"DESC") ) {
1523 *code = LDAP_SCHERR_DUPOPT;
1525 ldap_syntax_free(syn);
1530 kind = get_token(&ss,&sval);
1531 if ( kind != TK_QDSTRING ) {
1532 *code = LDAP_SCHERR_UNEXPTOKEN;
1535 ldap_syntax_free(syn);
1538 syn->syn_desc = sval;
1540 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
1541 /* Should be parse_qdstrings */
1542 ext_vals = parse_qdescrs(&ss, code);
1545 ldap_syntax_free(syn);
1548 if ( add_extension(&syn->syn_extensions,
1550 *code = LDAP_SCHERR_OUTOFMEM;
1553 ldap_syntax_free(syn);
1557 *code = LDAP_SCHERR_UNEXPTOKEN;
1560 ldap_syntax_free(syn);
1565 *code = LDAP_SCHERR_UNEXPTOKEN;
1568 ldap_syntax_free(syn);
1575 ldap_matchingrule_free( LDAPMatchingRule * mr )
1577 LDAP_FREE(mr->mr_oid);
1578 if (mr->mr_names) LDAP_VFREE(mr->mr_names);
1579 if (mr->mr_desc) LDAP_FREE(mr->mr_desc);
1580 if (mr->mr_syntax_oid) LDAP_FREE(mr->mr_syntax_oid);
1581 free_extensions(mr->mr_extensions);
1586 ldap_str2matchingrule( LDAP_CONST char * s,
1588 LDAP_CONST char ** errp,
1589 LDAP_CONST unsigned flags )
1592 const char * ss = s;
1596 int seen_obsolete = 0;
1597 int seen_syntax = 0;
1598 LDAPMatchingRule * mr;
1600 const char * savepos;
1603 *code = LDAP_SCHERR_EMPTY;
1609 mr = LDAP_CALLOC(1,sizeof(LDAPMatchingRule));
1612 *code = LDAP_SCHERR_OUTOFMEM;
1616 kind = get_token(&ss,&sval);
1617 if ( kind != TK_LEFTPAREN ) {
1618 *code = LDAP_SCHERR_NOLEFTPAREN;
1620 ldap_matchingrule_free(mr);
1626 mr->mr_oid = ldap_int_parse_numericoid(&ss,code,flags);
1627 if ( !mr->mr_oid ) {
1628 if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) {
1631 kind = get_token(&ss,&sval);
1632 if ( kind == TK_BAREWORD ) {
1633 if ( !strcasecmp(sval, "NAME") ||
1634 !strcasecmp(sval, "DESC") ||
1635 !strcasecmp(sval, "OBSOLETE") ||
1636 !strcasecmp(sval, "SYNTAX") ||
1637 !strncasecmp(sval, "X-", 2) ) {
1638 /* Missing OID, backtrack */
1641 /* Non-numerical OID, ignore */
1647 ldap_matchingrule_free(mr);
1654 * Beyond this point we will be liberal and accept the items
1658 kind = get_token(&ss,&sval);
1661 *code = LDAP_SCHERR_NORIGHTPAREN;
1663 ldap_matchingrule_free(mr);
1666 if( !seen_syntax ) {
1667 *code = LDAP_SCHERR_MISSING;
1668 ldap_matchingrule_free(mr);
1673 if ( !strcasecmp(sval,"NAME") ) {
1676 *code = LDAP_SCHERR_DUPOPT;
1678 ldap_matchingrule_free(mr);
1682 mr->mr_names = parse_qdescrs(&ss,code);
1683 if ( !mr->mr_names ) {
1684 if ( *code != LDAP_SCHERR_OUTOFMEM )
1685 *code = LDAP_SCHERR_BADNAME;
1687 ldap_matchingrule_free(mr);
1690 } else if ( !strcasecmp(sval,"DESC") ) {
1693 *code = LDAP_SCHERR_DUPOPT;
1695 ldap_matchingrule_free(mr);
1700 kind = get_token(&ss,&sval);
1701 if ( kind != TK_QDSTRING ) {
1702 *code = LDAP_SCHERR_UNEXPTOKEN;
1705 ldap_matchingrule_free(mr);
1710 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
1712 if ( seen_obsolete ) {
1713 *code = LDAP_SCHERR_DUPOPT;
1715 ldap_matchingrule_free(mr);
1719 mr->mr_obsolete = LDAP_SCHEMA_YES;
1721 } else if ( !strcasecmp(sval,"SYNTAX") ) {
1723 if ( seen_syntax ) {
1724 *code = LDAP_SCHERR_DUPOPT;
1726 ldap_matchingrule_free(mr);
1732 ldap_int_parse_numericoid(&ss,code,flags);
1733 if ( !mr->mr_syntax_oid ) {
1735 ldap_matchingrule_free(mr);
1739 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
1740 /* Should be parse_qdstrings */
1741 ext_vals = parse_qdescrs(&ss, code);
1744 ldap_matchingrule_free(mr);
1747 if ( add_extension(&mr->mr_extensions,
1749 *code = LDAP_SCHERR_OUTOFMEM;
1752 ldap_matchingrule_free(mr);
1756 *code = LDAP_SCHERR_UNEXPTOKEN;
1759 ldap_matchingrule_free(mr);
1764 *code = LDAP_SCHERR_UNEXPTOKEN;
1767 ldap_matchingrule_free(mr);
1774 ldap_matchingruleuse_free( LDAPMatchingRuleUse * mru )
1776 LDAP_FREE(mru->mru_oid);
1777 if (mru->mru_names) LDAP_VFREE(mru->mru_names);
1778 if (mru->mru_desc) LDAP_FREE(mru->mru_desc);
1779 if (mru->mru_applies_oids) LDAP_VFREE(mru->mru_applies_oids);
1780 free_extensions(mru->mru_extensions);
1784 LDAPMatchingRuleUse *
1785 ldap_str2matchingruleuse( LDAP_CONST char * s,
1787 LDAP_CONST char ** errp,
1788 LDAP_CONST unsigned flags )
1791 const char * ss = s;
1795 int seen_obsolete = 0;
1796 int seen_applies = 0;
1797 LDAPMatchingRuleUse * mru;
1799 const char * savepos;
1802 *code = LDAP_SCHERR_EMPTY;
1808 mru = LDAP_CALLOC(1,sizeof(LDAPMatchingRuleUse));
1811 *code = LDAP_SCHERR_OUTOFMEM;
1815 kind = get_token(&ss,&sval);
1816 if ( kind != TK_LEFTPAREN ) {
1817 *code = LDAP_SCHERR_NOLEFTPAREN;
1819 ldap_matchingruleuse_free(mru);
1825 mru->mru_oid = ldap_int_parse_numericoid(&ss,code,flags);
1826 if ( !mru->mru_oid ) {
1827 if ( flags & LDAP_SCHEMA_ALLOW_NO_OID ) {
1830 kind = get_token(&ss,&sval);
1831 if ( kind == TK_BAREWORD ) {
1832 if ( !strcasecmp(sval, "NAME") ||
1833 !strcasecmp(sval, "DESC") ||
1834 !strcasecmp(sval, "OBSOLETE") ||
1835 !strcasecmp(sval, "APPLIES") ||
1836 !strncasecmp(sval, "X-", 2) ) {
1837 /* Missing OID, backtrack */
1840 /* Non-numerical OID, ignore */
1846 ldap_matchingruleuse_free(mru);
1853 * Beyond this point we will be liberal and accept the items
1857 kind = get_token(&ss,&sval);
1860 *code = LDAP_SCHERR_NORIGHTPAREN;
1862 ldap_matchingruleuse_free(mru);
1865 if( !seen_applies ) {
1866 *code = LDAP_SCHERR_MISSING;
1867 ldap_matchingruleuse_free(mru);
1872 if ( !strcasecmp(sval,"NAME") ) {
1875 *code = LDAP_SCHERR_DUPOPT;
1877 ldap_matchingruleuse_free(mru);
1881 mru->mru_names = parse_qdescrs(&ss,code);
1882 if ( !mru->mru_names ) {
1883 if ( *code != LDAP_SCHERR_OUTOFMEM )
1884 *code = LDAP_SCHERR_BADNAME;
1886 ldap_matchingruleuse_free(mru);
1889 } else if ( !strcasecmp(sval,"DESC") ) {
1892 *code = LDAP_SCHERR_DUPOPT;
1894 ldap_matchingruleuse_free(mru);
1899 kind = get_token(&ss,&sval);
1900 if ( kind != TK_QDSTRING ) {
1901 *code = LDAP_SCHERR_UNEXPTOKEN;
1904 ldap_matchingruleuse_free(mru);
1907 mru->mru_desc = sval;
1909 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
1911 if ( seen_obsolete ) {
1912 *code = LDAP_SCHERR_DUPOPT;
1914 ldap_matchingruleuse_free(mru);
1918 mru->mru_obsolete = LDAP_SCHEMA_YES;
1920 } else if ( !strcasecmp(sval,"APPLIES") ) {
1922 if ( seen_applies ) {
1923 *code = LDAP_SCHERR_DUPOPT;
1925 ldap_matchingruleuse_free(mru);
1929 mru->mru_applies_oids = parse_oids(&ss,
1932 if ( !mru->mru_applies_oids && *code != LDAP_SUCCESS ) {
1934 ldap_matchingruleuse_free(mru);
1937 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
1938 /* Should be parse_qdstrings */
1939 ext_vals = parse_qdescrs(&ss, code);
1942 ldap_matchingruleuse_free(mru);
1945 if ( add_extension(&mru->mru_extensions,
1947 *code = LDAP_SCHERR_OUTOFMEM;
1950 ldap_matchingruleuse_free(mru);
1954 *code = LDAP_SCHERR_UNEXPTOKEN;
1957 ldap_matchingruleuse_free(mru);
1962 *code = LDAP_SCHERR_UNEXPTOKEN;
1965 ldap_matchingruleuse_free(mru);
1972 ldap_attributetype_free(LDAPAttributeType * at)
1974 LDAP_FREE(at->at_oid);
1975 if (at->at_names) LDAP_VFREE(at->at_names);
1976 if (at->at_desc) LDAP_FREE(at->at_desc);
1977 if (at->at_sup_oid) LDAP_FREE(at->at_sup_oid);
1978 if (at->at_equality_oid) LDAP_FREE(at->at_equality_oid);
1979 if (at->at_ordering_oid) LDAP_FREE(at->at_ordering_oid);
1980 if (at->at_substr_oid) LDAP_FREE(at->at_substr_oid);
1981 if (at->at_syntax_oid) LDAP_FREE(at->at_syntax_oid);
1982 free_extensions(at->at_extensions);
1987 ldap_str2attributetype( LDAP_CONST char * s,
1989 LDAP_CONST char ** errp,
1990 LDAP_CONST unsigned flags )
1993 const char * ss = s;
1997 int seen_obsolete = 0;
1999 int seen_equality = 0;
2000 int seen_ordering = 0;
2001 int seen_substr = 0;
2002 int seen_syntax = 0;
2004 LDAPAttributeType * at;
2006 const char * savepos;
2009 *code = LDAP_SCHERR_EMPTY;
2015 at = LDAP_CALLOC(1,sizeof(LDAPAttributeType));
2018 *code = LDAP_SCHERR_OUTOFMEM;
2022 kind = get_token(&ss,&sval);
2023 if ( kind != TK_LEFTPAREN ) {
2024 *code = LDAP_SCHERR_NOLEFTPAREN;
2026 ldap_attributetype_free(at);
2031 * Definitions MUST begin with an OID in the numericoid format.
2032 * However, this routine is used by clients to parse the response
2033 * from servers and very well known servers will provide an OID
2034 * in the wrong format or even no OID at all. We do our best to
2035 * extract info from those servers.
2039 at->at_oid = ldap_int_parse_numericoid(&ss,code,0);
2040 if ( !at->at_oid ) {
2041 if ( ( flags & ( LDAP_SCHEMA_ALLOW_NO_OID
2042 | LDAP_SCHEMA_ALLOW_OID_MACRO ) )
2043 && (ss == savepos) ) {
2046 kind = get_token(&ss,&sval);
2047 if ( kind == TK_BAREWORD ) {
2048 if ( !strcasecmp(sval, "NAME") ||
2049 !strcasecmp(sval, "DESC") ||
2050 !strcasecmp(sval, "OBSOLETE") ||
2051 !strcasecmp(sval, "SUP") ||
2052 !strcasecmp(sval, "EQUALITY") ||
2053 !strcasecmp(sval, "ORDERING") ||
2054 !strcasecmp(sval, "SUBSTR") ||
2055 !strcasecmp(sval, "SYNTAX") ||
2056 !strcasecmp(sval, "SINGLE-VALUE") ||
2057 !strcasecmp(sval, "COLLECTIVE") ||
2058 !strcasecmp(sval, "NO-USER-MODIFICATION") ||
2059 !strcasecmp(sval, "USAGE") ||
2060 !strncasecmp(sval, "X-", 2) ) {
2061 /* Missing OID, backtrack */
2064 & LDAP_SCHEMA_ALLOW_OID_MACRO) {
2065 /* Non-numerical OID ... */
2066 int len = ss-savepos;
2067 at->at_oid = LDAP_MALLOC(len+1);
2068 strncpy(at->at_oid, savepos, len);
2069 at->at_oid[len] = 0;
2075 ldap_attributetype_free(at);
2082 * Beyond this point we will be liberal and accept the items
2086 kind = get_token(&ss,&sval);
2089 *code = LDAP_SCHERR_NORIGHTPAREN;
2091 ldap_attributetype_free(at);
2096 if ( !strcasecmp(sval,"NAME") ) {
2099 *code = LDAP_SCHERR_DUPOPT;
2101 ldap_attributetype_free(at);
2105 at->at_names = parse_qdescrs(&ss,code);
2106 if ( !at->at_names ) {
2107 if ( *code != LDAP_SCHERR_OUTOFMEM )
2108 *code = LDAP_SCHERR_BADNAME;
2110 ldap_attributetype_free(at);
2113 } else if ( !strcasecmp(sval,"DESC") ) {
2116 *code = LDAP_SCHERR_DUPOPT;
2118 ldap_attributetype_free(at);
2123 kind = get_token(&ss,&sval);
2124 if ( kind != TK_QDSTRING ) {
2125 *code = LDAP_SCHERR_UNEXPTOKEN;
2128 ldap_attributetype_free(at);
2133 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
2135 if ( seen_obsolete ) {
2136 *code = LDAP_SCHERR_DUPOPT;
2138 ldap_attributetype_free(at);
2142 at->at_obsolete = LDAP_SCHEMA_YES;
2144 } else if ( !strcasecmp(sval,"SUP") ) {
2147 *code = LDAP_SCHERR_DUPOPT;
2149 ldap_attributetype_free(at);
2153 at->at_sup_oid = parse_woid(&ss,code);
2154 if ( !at->at_sup_oid ) {
2156 ldap_attributetype_free(at);
2159 } else if ( !strcasecmp(sval,"EQUALITY") ) {
2161 if ( seen_equality ) {
2162 *code = LDAP_SCHERR_DUPOPT;
2164 ldap_attributetype_free(at);
2168 at->at_equality_oid = parse_woid(&ss,code);
2169 if ( !at->at_equality_oid ) {
2171 ldap_attributetype_free(at);
2174 } else if ( !strcasecmp(sval,"ORDERING") ) {
2176 if ( seen_ordering ) {
2177 *code = LDAP_SCHERR_DUPOPT;
2179 ldap_attributetype_free(at);
2183 at->at_ordering_oid = parse_woid(&ss,code);
2184 if ( !at->at_ordering_oid ) {
2186 ldap_attributetype_free(at);
2189 } else if ( !strcasecmp(sval,"SUBSTR") ) {
2191 if ( seen_substr ) {
2192 *code = LDAP_SCHERR_DUPOPT;
2194 ldap_attributetype_free(at);
2198 at->at_substr_oid = parse_woid(&ss,code);
2199 if ( !at->at_substr_oid ) {
2201 ldap_attributetype_free(at);
2204 } else if ( !strcasecmp(sval,"SYNTAX") ) {
2206 if ( seen_syntax ) {
2207 *code = LDAP_SCHERR_DUPOPT;
2209 ldap_attributetype_free(at);
2220 if ( !at->at_syntax_oid ) {
2221 if ( flags & LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2222 kind = get_token(&ss,&sval);
2223 if (kind == TK_BAREWORD)
2225 char *sp = strchr(sval, '{');
2226 at->at_syntax_oid = sval;
2230 at->at_syntax_len = atoi(sp);
2231 while ( LDAP_DIGIT(*sp) )
2234 *code = LDAP_SCHERR_UNEXPTOKEN;
2236 ldap_attributetype_free(at);
2243 ldap_attributetype_free(at);
2248 } else if ( !strcasecmp(sval,"SINGLE-VALUE") ) {
2250 if ( at->at_single_value ) {
2251 *code = LDAP_SCHERR_DUPOPT;
2253 ldap_attributetype_free(at);
2256 at->at_single_value = LDAP_SCHEMA_YES;
2258 } else if ( !strcasecmp(sval,"COLLECTIVE") ) {
2260 if ( at->at_collective ) {
2261 *code = LDAP_SCHERR_DUPOPT;
2263 ldap_attributetype_free(at);
2266 at->at_collective = LDAP_SCHEMA_YES;
2268 } else if ( !strcasecmp(sval,"NO-USER-MODIFICATION") ) {
2270 if ( at->at_no_user_mod ) {
2271 *code = LDAP_SCHERR_DUPOPT;
2273 ldap_attributetype_free(at);
2276 at->at_no_user_mod = LDAP_SCHEMA_YES;
2278 } else if ( !strcasecmp(sval,"USAGE") ) {
2281 *code = LDAP_SCHERR_DUPOPT;
2283 ldap_attributetype_free(at);
2288 kind = get_token(&ss,&sval);
2289 if ( kind != TK_BAREWORD ) {
2290 *code = LDAP_SCHERR_UNEXPTOKEN;
2293 ldap_attributetype_free(at);
2296 if ( !strcasecmp(sval,"userApplications") )
2298 LDAP_SCHEMA_USER_APPLICATIONS;
2299 else if ( !strcasecmp(sval,"directoryOperation") )
2301 LDAP_SCHEMA_DIRECTORY_OPERATION;
2302 else if ( !strcasecmp(sval,"distributedOperation") )
2304 LDAP_SCHEMA_DISTRIBUTED_OPERATION;
2305 else if ( !strcasecmp(sval,"dSAOperation") )
2307 LDAP_SCHEMA_DSA_OPERATION;
2309 *code = LDAP_SCHERR_UNEXPTOKEN;
2312 ldap_attributetype_free(at);
2317 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
2318 /* Should be parse_qdstrings */
2319 ext_vals = parse_qdescrs(&ss, code);
2322 ldap_attributetype_free(at);
2325 if ( add_extension(&at->at_extensions,
2327 *code = LDAP_SCHERR_OUTOFMEM;
2330 ldap_attributetype_free(at);
2334 *code = LDAP_SCHERR_UNEXPTOKEN;
2337 ldap_attributetype_free(at);
2342 *code = LDAP_SCHERR_UNEXPTOKEN;
2345 ldap_attributetype_free(at);
2352 ldap_objectclass_free(LDAPObjectClass * oc)
2354 LDAP_FREE(oc->oc_oid);
2355 if (oc->oc_names) LDAP_VFREE(oc->oc_names);
2356 if (oc->oc_desc) LDAP_FREE(oc->oc_desc);
2357 if (oc->oc_sup_oids) LDAP_VFREE(oc->oc_sup_oids);
2358 if (oc->oc_at_oids_must) LDAP_VFREE(oc->oc_at_oids_must);
2359 if (oc->oc_at_oids_may) LDAP_VFREE(oc->oc_at_oids_may);
2360 free_extensions(oc->oc_extensions);
2365 ldap_str2objectclass( LDAP_CONST char * s,
2367 LDAP_CONST char ** errp,
2368 LDAP_CONST unsigned flags )
2371 const char * ss = s;
2375 int seen_obsolete = 0;
2380 LDAPObjectClass * oc;
2382 const char * savepos;
2385 *code = LDAP_SCHERR_EMPTY;
2391 oc = LDAP_CALLOC(1,sizeof(LDAPObjectClass));
2394 *code = LDAP_SCHERR_OUTOFMEM;
2397 oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
2399 kind = get_token(&ss,&sval);
2400 if ( kind != TK_LEFTPAREN ) {
2401 *code = LDAP_SCHERR_NOLEFTPAREN;
2403 ldap_objectclass_free(oc);
2408 * Definitions MUST begin with an OID in the numericoid format.
2409 * However, this routine is used by clients to parse the response
2410 * from servers and very well known servers will provide an OID
2411 * in the wrong format or even no OID at all. We do our best to
2412 * extract info from those servers.
2416 oc->oc_oid = ldap_int_parse_numericoid(&ss,code,0);
2417 if ( !oc->oc_oid ) {
2418 if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) {
2421 kind = get_token(&ss,&sval);
2422 if ( kind == TK_BAREWORD ) {
2423 if ( !strcasecmp(sval, "NAME") ||
2424 !strcasecmp(sval, "DESC") ||
2425 !strcasecmp(sval, "OBSOLETE") ||
2426 !strcasecmp(sval, "SUP") ||
2427 !strcasecmp(sval, "ABSTRACT") ||
2428 !strcasecmp(sval, "STRUCTURAL") ||
2429 !strcasecmp(sval, "AUXILIARY") ||
2430 !strcasecmp(sval, "MUST") ||
2431 !strcasecmp(sval, "MAY") ||
2432 !strncasecmp(sval, "X-", 2) ) {
2433 /* Missing OID, backtrack */
2436 LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2437 /* Non-numerical OID, ignore */
2438 int len = ss-savepos;
2439 oc->oc_oid = LDAP_MALLOC(len+1);
2440 strncpy(oc->oc_oid, savepos, len);
2441 oc->oc_oid[len] = 0;
2447 ldap_objectclass_free(oc);
2454 * Beyond this point we will be liberal an accept the items
2458 kind = get_token(&ss,&sval);
2461 *code = LDAP_SCHERR_NORIGHTPAREN;
2463 ldap_objectclass_free(oc);
2468 if ( !strcasecmp(sval,"NAME") ) {
2471 *code = LDAP_SCHERR_DUPOPT;
2473 ldap_objectclass_free(oc);
2477 oc->oc_names = parse_qdescrs(&ss,code);
2478 if ( !oc->oc_names ) {
2479 if ( *code != LDAP_SCHERR_OUTOFMEM )
2480 *code = LDAP_SCHERR_BADNAME;
2482 ldap_objectclass_free(oc);
2485 } else if ( !strcasecmp(sval,"DESC") ) {
2488 *code = LDAP_SCHERR_DUPOPT;
2490 ldap_objectclass_free(oc);
2495 kind = get_token(&ss,&sval);
2496 if ( kind != TK_QDSTRING ) {
2497 *code = LDAP_SCHERR_UNEXPTOKEN;
2500 ldap_objectclass_free(oc);
2505 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
2507 if ( seen_obsolete ) {
2508 *code = LDAP_SCHERR_DUPOPT;
2510 ldap_objectclass_free(oc);
2514 oc->oc_obsolete = LDAP_SCHEMA_YES;
2516 } else if ( !strcasecmp(sval,"SUP") ) {
2519 *code = LDAP_SCHERR_DUPOPT;
2521 ldap_objectclass_free(oc);
2525 oc->oc_sup_oids = parse_oids(&ss,
2528 if ( !oc->oc_sup_oids && *code != LDAP_SUCCESS ) {
2530 ldap_objectclass_free(oc);
2533 } else if ( !strcasecmp(sval,"ABSTRACT") ) {
2536 *code = LDAP_SCHERR_DUPOPT;
2538 ldap_objectclass_free(oc);
2542 oc->oc_kind = LDAP_SCHEMA_ABSTRACT;
2544 } else if ( !strcasecmp(sval,"STRUCTURAL") ) {
2547 *code = LDAP_SCHERR_DUPOPT;
2549 ldap_objectclass_free(oc);
2553 oc->oc_kind = LDAP_SCHEMA_STRUCTURAL;
2555 } else if ( !strcasecmp(sval,"AUXILIARY") ) {
2558 *code = LDAP_SCHERR_DUPOPT;
2560 ldap_objectclass_free(oc);
2564 oc->oc_kind = LDAP_SCHEMA_AUXILIARY;
2566 } else if ( !strcasecmp(sval,"MUST") ) {
2569 *code = LDAP_SCHERR_DUPOPT;
2571 ldap_objectclass_free(oc);
2575 oc->oc_at_oids_must = parse_oids(&ss,code,0);
2576 if ( !oc->oc_at_oids_must && *code != LDAP_SUCCESS ) {
2578 ldap_objectclass_free(oc);
2582 } else if ( !strcasecmp(sval,"MAY") ) {
2585 *code = LDAP_SCHERR_DUPOPT;
2587 ldap_objectclass_free(oc);
2591 oc->oc_at_oids_may = parse_oids(&ss,code,0);
2592 if ( !oc->oc_at_oids_may && *code != LDAP_SUCCESS ) {
2594 ldap_objectclass_free(oc);
2598 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
2599 /* Should be parse_qdstrings */
2600 ext_vals = parse_qdescrs(&ss, code);
2603 ldap_objectclass_free(oc);
2606 if ( add_extension(&oc->oc_extensions,
2608 *code = LDAP_SCHERR_OUTOFMEM;
2611 ldap_objectclass_free(oc);
2615 *code = LDAP_SCHERR_UNEXPTOKEN;
2618 ldap_objectclass_free(oc);
2623 *code = LDAP_SCHERR_UNEXPTOKEN;
2626 ldap_objectclass_free(oc);
2633 ldap_contentrule_free(LDAPContentRule * cr)
2635 LDAP_FREE(cr->cr_oid);
2636 if (cr->cr_names) LDAP_VFREE(cr->cr_names);
2637 if (cr->cr_desc) LDAP_FREE(cr->cr_desc);
2638 if (cr->cr_oc_oids_aux) LDAP_VFREE(cr->cr_oc_oids_aux);
2639 if (cr->cr_at_oids_must) LDAP_VFREE(cr->cr_at_oids_must);
2640 if (cr->cr_at_oids_may) LDAP_VFREE(cr->cr_at_oids_may);
2641 if (cr->cr_at_oids_not) LDAP_VFREE(cr->cr_at_oids_not);
2642 free_extensions(cr->cr_extensions);
2647 ldap_str2contentrule( LDAP_CONST char * s,
2649 LDAP_CONST char ** errp,
2650 LDAP_CONST unsigned flags )
2653 const char * ss = s;
2657 int seen_obsolete = 0;
2662 LDAPContentRule * cr;
2664 const char * savepos;
2667 *code = LDAP_SCHERR_EMPTY;
2673 cr = LDAP_CALLOC(1,sizeof(LDAPContentRule));
2676 *code = LDAP_SCHERR_OUTOFMEM;
2680 kind = get_token(&ss,&sval);
2681 if ( kind != TK_LEFTPAREN ) {
2682 *code = LDAP_SCHERR_NOLEFTPAREN;
2684 ldap_contentrule_free(cr);
2689 * Definitions MUST begin with an OID in the numericoid format.
2693 cr->cr_oid = ldap_int_parse_numericoid(&ss,code,0);
2694 if ( !cr->cr_oid ) {
2695 if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) {
2698 kind = get_token(&ss,&sval);
2699 if ( kind == TK_BAREWORD ) {
2700 if ( !strcasecmp(sval, "NAME") ||
2701 !strcasecmp(sval, "DESC") ||
2702 !strcasecmp(sval, "OBSOLETE") ||
2703 !strcasecmp(sval, "AUX") ||
2704 !strcasecmp(sval, "MUST") ||
2705 !strcasecmp(sval, "MAY") ||
2706 !strcasecmp(sval, "NOT") ||
2707 !strncasecmp(sval, "X-", 2) ) {
2708 /* Missing OID, backtrack */
2711 LDAP_SCHEMA_ALLOW_OID_MACRO ) {
2712 /* Non-numerical OID, ignore */
2713 int len = ss-savepos;
2714 cr->cr_oid = LDAP_MALLOC(len+1);
2715 strncpy(cr->cr_oid, savepos, len);
2716 cr->cr_oid[len] = 0;
2722 ldap_contentrule_free(cr);
2729 * Beyond this point we will be liberal an accept the items
2733 kind = get_token(&ss,&sval);
2736 *code = LDAP_SCHERR_NORIGHTPAREN;
2738 ldap_contentrule_free(cr);
2743 if ( !strcasecmp(sval,"NAME") ) {
2746 *code = LDAP_SCHERR_DUPOPT;
2748 ldap_contentrule_free(cr);
2752 cr->cr_names = parse_qdescrs(&ss,code);
2753 if ( !cr->cr_names ) {
2754 if ( *code != LDAP_SCHERR_OUTOFMEM )
2755 *code = LDAP_SCHERR_BADNAME;
2757 ldap_contentrule_free(cr);
2760 } else if ( !strcasecmp(sval,"DESC") ) {
2763 *code = LDAP_SCHERR_DUPOPT;
2765 ldap_contentrule_free(cr);
2770 kind = get_token(&ss,&sval);
2771 if ( kind != TK_QDSTRING ) {
2772 *code = LDAP_SCHERR_UNEXPTOKEN;
2775 ldap_contentrule_free(cr);
2780 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
2782 if ( seen_obsolete ) {
2783 *code = LDAP_SCHERR_DUPOPT;
2785 ldap_contentrule_free(cr);
2789 cr->cr_obsolete = LDAP_SCHEMA_YES;
2791 } else if ( !strcasecmp(sval,"AUX") ) {
2794 *code = LDAP_SCHERR_DUPOPT;
2796 ldap_contentrule_free(cr);
2800 cr->cr_oc_oids_aux = parse_oids(&ss,code,0);
2801 if ( !cr->cr_oc_oids_aux ) {
2803 ldap_contentrule_free(cr);
2807 } else if ( !strcasecmp(sval,"MUST") ) {
2810 *code = LDAP_SCHERR_DUPOPT;
2812 ldap_contentrule_free(cr);
2816 cr->cr_at_oids_must = parse_oids(&ss,code,0);
2817 if ( !cr->cr_at_oids_must && *code != LDAP_SUCCESS ) {
2819 ldap_contentrule_free(cr);
2823 } else if ( !strcasecmp(sval,"MAY") ) {
2826 *code = LDAP_SCHERR_DUPOPT;
2828 ldap_contentrule_free(cr);
2832 cr->cr_at_oids_may = parse_oids(&ss,code,0);
2833 if ( !cr->cr_at_oids_may && *code != LDAP_SUCCESS ) {
2835 ldap_contentrule_free(cr);
2839 } else if ( !strcasecmp(sval,"NOT") ) {
2842 *code = LDAP_SCHERR_DUPOPT;
2844 ldap_contentrule_free(cr);
2848 cr->cr_at_oids_not = parse_oids(&ss,code,0);
2849 if ( !cr->cr_at_oids_not && *code != LDAP_SUCCESS ) {
2851 ldap_contentrule_free(cr);
2855 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
2856 /* Should be parse_qdstrings */
2857 ext_vals = parse_qdescrs(&ss, code);
2860 ldap_contentrule_free(cr);
2863 if ( add_extension(&cr->cr_extensions,
2865 *code = LDAP_SCHERR_OUTOFMEM;
2868 ldap_contentrule_free(cr);
2872 *code = LDAP_SCHERR_UNEXPTOKEN;
2875 ldap_contentrule_free(cr);
2880 *code = LDAP_SCHERR_UNEXPTOKEN;
2883 ldap_contentrule_free(cr);
2890 ldap_structurerule_free(LDAPStructureRule * sr)
2892 if (sr->sr_names) LDAP_VFREE(sr->sr_names);
2893 if (sr->sr_desc) LDAP_FREE(sr->sr_desc);
2894 if (sr->sr_nameform) LDAP_FREE(sr->sr_nameform);
2895 if (sr->sr_sup_ruleids) LDAP_FREE(sr->sr_sup_ruleids);
2896 free_extensions(sr->sr_extensions);
2901 ldap_str2structurerule( LDAP_CONST char * s,
2903 LDAP_CONST char ** errp,
2904 LDAP_CONST unsigned flags )
2907 const char * ss = s;
2911 int seen_obsolete = 0;
2912 int seen_nameform = 0;
2913 LDAPStructureRule * sr;
2915 const char * savepos;
2918 *code = LDAP_SCHERR_EMPTY;
2924 sr = LDAP_CALLOC(1,sizeof(LDAPStructureRule));
2927 *code = LDAP_SCHERR_OUTOFMEM;
2931 kind = get_token(&ss,&sval);
2932 if ( kind != TK_LEFTPAREN ) {
2933 *code = LDAP_SCHERR_NOLEFTPAREN;
2935 ldap_structurerule_free(sr);
2940 * Definitions MUST begin with a ruleid.
2944 ret = ldap_int_parse_ruleid(&ss,code,0,&sr->sr_ruleid);
2947 ldap_structurerule_free(sr);
2953 * Beyond this point we will be liberal an accept the items
2957 kind = get_token(&ss,&sval);
2960 *code = LDAP_SCHERR_NORIGHTPAREN;
2962 ldap_structurerule_free(sr);
2965 if( !seen_nameform ) {
2966 *code = LDAP_SCHERR_MISSING;
2967 ldap_structurerule_free(sr);
2972 if ( !strcasecmp(sval,"NAME") ) {
2975 *code = LDAP_SCHERR_DUPOPT;
2977 ldap_structurerule_free(sr);
2981 sr->sr_names = parse_qdescrs(&ss,code);
2982 if ( !sr->sr_names ) {
2983 if ( *code != LDAP_SCHERR_OUTOFMEM )
2984 *code = LDAP_SCHERR_BADNAME;
2986 ldap_structurerule_free(sr);
2989 } else if ( !strcasecmp(sval,"DESC") ) {
2992 *code = LDAP_SCHERR_DUPOPT;
2994 ldap_structurerule_free(sr);
2999 kind = get_token(&ss,&sval);
3000 if ( kind != TK_QDSTRING ) {
3001 *code = LDAP_SCHERR_UNEXPTOKEN;
3004 ldap_structurerule_free(sr);
3009 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
3011 if ( seen_obsolete ) {
3012 *code = LDAP_SCHERR_DUPOPT;
3014 ldap_structurerule_free(sr);
3018 sr->sr_obsolete = LDAP_SCHEMA_YES;
3020 } else if ( !strcasecmp(sval,"FORM") ) {
3022 if ( seen_nameform ) {
3023 *code = LDAP_SCHERR_DUPOPT;
3025 ldap_structurerule_free(sr);
3029 sr->sr_nameform = parse_woid(&ss,code);
3030 if ( !sr->sr_nameform ) {
3032 ldap_structurerule_free(sr);
3036 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
3037 /* Should be parse_qdstrings */
3038 ext_vals = parse_qdescrs(&ss, code);
3041 ldap_structurerule_free(sr);
3044 if ( add_extension(&sr->sr_extensions,
3046 *code = LDAP_SCHERR_OUTOFMEM;
3049 ldap_structurerule_free(sr);
3053 *code = LDAP_SCHERR_UNEXPTOKEN;
3056 ldap_structurerule_free(sr);
3061 *code = LDAP_SCHERR_UNEXPTOKEN;
3064 ldap_structurerule_free(sr);
3071 ldap_nameform_free(LDAPNameForm * nf)
3073 LDAP_FREE(nf->nf_oid);
3074 if (nf->nf_names) LDAP_VFREE(nf->nf_names);
3075 if (nf->nf_desc) LDAP_FREE(nf->nf_desc);
3076 if (nf->nf_objectclass) LDAP_FREE(nf->nf_objectclass);
3077 if (nf->nf_at_oids_must) LDAP_VFREE(nf->nf_at_oids_must);
3078 if (nf->nf_at_oids_may) LDAP_VFREE(nf->nf_at_oids_may);
3079 free_extensions(nf->nf_extensions);
3084 ldap_str2nameform( LDAP_CONST char * s,
3086 LDAP_CONST char ** errp,
3087 LDAP_CONST unsigned flags )
3090 const char * ss = s;
3094 int seen_obsolete = 0;
3100 const char * savepos;
3103 *code = LDAP_SCHERR_EMPTY;
3109 nf = LDAP_CALLOC(1,sizeof(LDAPNameForm));
3112 *code = LDAP_SCHERR_OUTOFMEM;
3116 kind = get_token(&ss,&sval);
3117 if ( kind != TK_LEFTPAREN ) {
3118 *code = LDAP_SCHERR_NOLEFTPAREN;
3120 ldap_nameform_free(nf);
3125 * Definitions MUST begin with an OID in the numericoid format.
3126 * However, this routine is used by clients to parse the response
3127 * from servers and very well known servers will provide an OID
3128 * in the wrong format or even no OID at all. We do our best to
3129 * extract info from those servers.
3133 nf->nf_oid = ldap_int_parse_numericoid(&ss,code,0);
3134 if ( !nf->nf_oid ) {
3136 ldap_nameform_free(nf);
3142 * Beyond this point we will be liberal an accept the items
3146 kind = get_token(&ss,&sval);
3149 *code = LDAP_SCHERR_NORIGHTPAREN;
3151 ldap_nameform_free(nf);
3154 if( !seen_class || !seen_must ) {
3155 *code = LDAP_SCHERR_MISSING;
3156 ldap_nameform_free(nf);
3161 if ( !strcasecmp(sval,"NAME") ) {
3164 *code = LDAP_SCHERR_DUPOPT;
3166 ldap_nameform_free(nf);
3170 nf->nf_names = parse_qdescrs(&ss,code);
3171 if ( !nf->nf_names ) {
3172 if ( *code != LDAP_SCHERR_OUTOFMEM )
3173 *code = LDAP_SCHERR_BADNAME;
3175 ldap_nameform_free(nf);
3178 } else if ( !strcasecmp(sval,"DESC") ) {
3181 *code = LDAP_SCHERR_DUPOPT;
3183 ldap_nameform_free(nf);
3188 kind = get_token(&ss,&sval);
3189 if ( kind != TK_QDSTRING ) {
3190 *code = LDAP_SCHERR_UNEXPTOKEN;
3193 ldap_nameform_free(nf);
3198 } else if ( !strcasecmp(sval,"OBSOLETE") ) {
3200 if ( seen_obsolete ) {
3201 *code = LDAP_SCHERR_DUPOPT;
3203 ldap_nameform_free(nf);
3207 nf->nf_obsolete = LDAP_SCHEMA_YES;
3209 } else if ( !strcasecmp(sval,"MUST") ) {
3212 *code = LDAP_SCHERR_DUPOPT;
3214 ldap_nameform_free(nf);
3218 nf->nf_at_oids_must = parse_oids(&ss,code,0);
3219 if ( !nf->nf_at_oids_must && *code != LDAP_SUCCESS ) {
3221 ldap_nameform_free(nf);
3225 } else if ( !strcasecmp(sval,"MAY") ) {
3228 *code = LDAP_SCHERR_DUPOPT;
3230 ldap_nameform_free(nf);
3234 nf->nf_at_oids_may = parse_oids(&ss,code,0);
3235 if ( !nf->nf_at_oids_may && *code != LDAP_SUCCESS ) {
3237 ldap_nameform_free(nf);
3241 } else if ( sval[0] == 'X' && sval[1] == '-' ) {
3242 /* Should be parse_qdstrings */
3243 ext_vals = parse_qdescrs(&ss, code);
3246 ldap_nameform_free(nf);
3249 if ( add_extension(&nf->nf_extensions,
3251 *code = LDAP_SCHERR_OUTOFMEM;
3254 ldap_nameform_free(nf);
3258 *code = LDAP_SCHERR_UNEXPTOKEN;
3261 ldap_nameform_free(nf);
3266 *code = LDAP_SCHERR_UNEXPTOKEN;
3269 ldap_nameform_free(nf);
3275 static char *const err2text[] = {
3277 N_("Out of memory"),
3278 N_("Unexpected token"),
3279 N_("Missing opening parenthesis"),
3280 N_("Missing closing parenthesis"),
3281 N_("Expecting digit"),
3282 N_("Expecting a name"),
3283 N_("Bad description"),
3284 N_("Bad superiors"),
3285 N_("Duplicate option"),
3286 N_("Unexpected end of data"),
3287 N_("Missing required field"),
3288 N_("Out of order field")
3292 ldap_scherr2str(int code)
3294 if ( code < 0 || code >= (int)(sizeof(err2text)/sizeof(char *)) ) {
3295 return _("Unknown error");
3297 return _(err2text[code]);