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