2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2022 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 if (!syn
) return NULL
;
45 return( syn
->syn_oid
);
49 ldap_matchingrule2name( LDAPMatchingRule
* mr
)
52 return( choose_name( mr
->mr_names
, mr
->mr_oid
) );
56 ldap_matchingruleuse2name( LDAPMatchingRuleUse
* mru
)
58 if (!mru
) return NULL
;
59 return( choose_name( mru
->mru_names
, mru
->mru_oid
) );
63 ldap_attributetype2name( LDAPAttributeType
* at
)
66 return( choose_name( at
->at_names
, at
->at_oid
) );
70 ldap_objectclass2name( LDAPObjectClass
* oc
)
73 return( choose_name( oc
->oc_names
, oc
->oc_oid
) );
77 ldap_contentrule2name( LDAPContentRule
* cr
)
80 return( choose_name( cr
->cr_names
, cr
->cr_oid
) );
84 ldap_nameform2name( LDAPNameForm
* nf
)
87 return( choose_name( nf
->nf_names
, nf
->nf_oid
) );
91 ldap_structurerule2name( LDAPStructureRule
* sr
)
94 return( choose_name( sr
->sr_names
, NULL
) );
98 * When pretty printing the entities we will be appending to a buffer.
99 * Since checking for overflow, realloc'ing and checking if no error
100 * is extremely boring, we will use a protection layer that will let
101 * us blissfully ignore the error until the end. This layer is
102 * implemented with the help of the next type.
105 typedef struct safe_string
{
113 new_safe_string(int size
)
117 ss
= LDAP_MALLOC(sizeof(safe_string
));
121 ss
->val
= LDAP_MALLOC(size
);
135 safe_string_free(safe_string
* ss
)
145 safe_string_val(safe_string
* ss
)
147 ss
->val
[ss
->pos
] = '\0';
153 safe_strdup(safe_string
* ss
)
155 char *ret
= LDAP_MALLOC(ss
->pos
+1);
158 AC_MEMCPY(ret
, ss
->val
, ss
->pos
);
164 append_to_safe_string(safe_string
* ss
, char * s
)
170 * Some runaway process is trying to append to a string that
171 * overflowed and we could not extend.
176 /* We always make sure there is at least one position available */
177 if ( ss
->pos
+ l
>= ss
->size
-1 ) {
179 if ( ss
->pos
+ l
>= ss
->size
-1 ) {
180 ss
->size
= ss
->pos
+ l
+ 1;
183 temp
= LDAP_REALLOC(ss
->val
, ss
->size
);
185 /* Trouble, out of memory */
191 strncpy(&ss
->val
[ss
->pos
], s
, l
);
193 if ( ss
->pos
> 0 && LDAP_SPACE(ss
->val
[ss
->pos
-1]) )
202 print_literal(safe_string
*ss
, char *s
)
204 return(append_to_safe_string(ss
,s
));
208 print_whsp(safe_string
*ss
)
211 return(append_to_safe_string(ss
,""));
213 return(append_to_safe_string(ss
," "));
217 print_numericoid(safe_string
*ss
, char *s
)
220 return(append_to_safe_string(ss
,s
));
222 return(append_to_safe_string(ss
,""));
225 /* This one is identical to print_qdescr */
227 print_qdstring(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_qdescr(safe_string
*ss
, char *s
)
240 print_literal(ss
,"'");
241 append_to_safe_string(ss
,s
);
242 print_literal(ss
,"'");
243 return(print_whsp(ss
));
247 print_qdescrlist(safe_string
*ss
, char **sa
)
252 for (sp
=sa
; *sp
; sp
++) {
253 ret
= print_qdescr(ss
,*sp
);
255 /* If the list was empty, we return zero that is potentially
256 * incorrect, but since we will be still appending things, the
257 * overflow will be detected later. Maybe FIX.
263 print_qdescrs(safe_string
*ss
, char **sa
)
265 /* The only way to represent an empty list is as a qdescrlist
266 * so, if the list is empty we treat it as a long list.
267 * Really, this is what the syntax mandates. We should not
268 * be here if the list was empty, but if it happens, a label
269 * has already been output and we cannot undo it.
271 if ( !sa
[0] || ( sa
[0] && sa
[1] ) ) {
273 print_literal(ss
,"("/*)*/);
274 print_qdescrlist(ss
,sa
);
275 print_literal(ss
,/*(*/")");
276 return(print_whsp(ss
));
278 return(print_qdescr(ss
,*sa
));
283 print_woid(safe_string
*ss
, char *s
)
286 append_to_safe_string(ss
,s
);
287 return print_whsp(ss
);
291 print_oidlist(safe_string
*ss
, char **sa
)
295 for (sp
=sa
; *(sp
+1); sp
++) {
297 print_literal(ss
,"$");
299 return(print_woid(ss
,*sp
));
303 print_oids(safe_string
*ss
, char **sa
)
305 if ( sa
[0] && sa
[1] ) {
306 print_literal(ss
,"("/*)*/);
307 print_oidlist(ss
,sa
);
309 return(print_literal(ss
,/*(*/")"));
311 return(print_woid(ss
,*sa
));
316 print_noidlen(safe_string
*ss
, char *s
, int l
)
321 ret
= print_numericoid(ss
,s
);
323 snprintf(buf
, sizeof buf
, "{%d}",l
);
324 ret
= print_literal(ss
,buf
);
330 print_ruleid(safe_string
*ss
, int rid
)
333 snprintf(buf
, sizeof buf
, "%d", rid
);
334 return print_literal(ss
,buf
);
338 print_ruleids(safe_string
*ss
, int n
, int *rids
)
343 print_ruleid(ss
,rids
[0]);
344 return print_whsp(ss
);
346 print_literal(ss
,"("/*)*/);
347 for( i
=0; i
<n
; i
++ ) {
349 print_ruleid(ss
,rids
[i
]);
352 return print_literal(ss
,/*(*/")");
358 print_extensions(safe_string
*ss
, LDAPSchemaExtensionItem
**extensions
)
360 LDAPSchemaExtensionItem
**ext
;
364 for ( ext
= extensions
; *ext
!= NULL
; ext
++ ) {
365 print_literal(ss
, (*ext
)->lsei_name
);
367 /* Should be print_qdstrings */
368 print_qdescrs(ss
, (*ext
)->lsei_values
);
377 ldap_syntax2str( LDAPSyntax
* syn
)
380 if (ldap_syntax2bv( syn
, &bv
))
387 ldap_syntax2bv( LDAPSyntax
* syn
, struct berval
*bv
)
394 ss
= new_safe_string(256);
398 print_literal(ss
,"("/*)*/);
401 print_numericoid(ss
, syn
->syn_oid
);
404 if ( syn
->syn_desc
) {
405 print_literal(ss
,"DESC");
406 print_qdstring(ss
,syn
->syn_desc
);
411 print_extensions(ss
, syn
->syn_extensions
);
413 print_literal(ss
,/*(*/ ")");
415 bv
->bv_val
= safe_strdup(ss
);
416 bv
->bv_len
= ss
->pos
;
417 safe_string_free(ss
);
422 ldap_matchingrule2str( LDAPMatchingRule
* mr
)
425 if (ldap_matchingrule2bv( mr
, &bv
))
432 ldap_matchingrule2bv( LDAPMatchingRule
* mr
, struct berval
*bv
)
439 ss
= new_safe_string(256);
443 print_literal(ss
,"(" /*)*/);
446 print_numericoid(ss
, mr
->mr_oid
);
449 if ( mr
->mr_names
) {
450 print_literal(ss
,"NAME");
451 print_qdescrs(ss
,mr
->mr_names
);
455 print_literal(ss
,"DESC");
456 print_qdstring(ss
,mr
->mr_desc
);
459 if ( mr
->mr_obsolete
) {
460 print_literal(ss
, "OBSOLETE");
464 if ( mr
->mr_syntax_oid
) {
465 print_literal(ss
,"SYNTAX");
467 print_literal(ss
, mr
->mr_syntax_oid
);
473 print_extensions(ss
, mr
->mr_extensions
);
475 print_literal(ss
,/*(*/")");
477 bv
->bv_val
= safe_strdup(ss
);
478 bv
->bv_len
= ss
->pos
;
479 safe_string_free(ss
);
484 ldap_matchingruleuse2str( LDAPMatchingRuleUse
* mru
)
487 if (ldap_matchingruleuse2bv( mru
, &bv
))
494 ldap_matchingruleuse2bv( LDAPMatchingRuleUse
* mru
, struct berval
*bv
)
501 ss
= new_safe_string(256);
505 print_literal(ss
,"(" /*)*/);
508 print_numericoid(ss
, mru
->mru_oid
);
511 if ( mru
->mru_names
) {
512 print_literal(ss
,"NAME");
513 print_qdescrs(ss
,mru
->mru_names
);
516 if ( mru
->mru_desc
) {
517 print_literal(ss
,"DESC");
518 print_qdstring(ss
,mru
->mru_desc
);
521 if ( mru
->mru_obsolete
) {
522 print_literal(ss
, "OBSOLETE");
526 if ( mru
->mru_applies_oids
) {
527 print_literal(ss
,"APPLIES");
529 print_oids(ss
, mru
->mru_applies_oids
);
535 print_extensions(ss
, mru
->mru_extensions
);
537 print_literal(ss
,/*(*/")");
539 bv
->bv_val
= safe_strdup(ss
);
540 bv
->bv_len
= ss
->pos
;
541 safe_string_free(ss
);
546 ldap_objectclass2str( LDAPObjectClass
* oc
)
549 if (ldap_objectclass2bv( oc
, &bv
))
556 ldap_objectclass2bv( LDAPObjectClass
* oc
, struct berval
*bv
)
563 ss
= new_safe_string(256);
567 print_literal(ss
,"("/*)*/);
570 print_numericoid(ss
, oc
->oc_oid
);
573 if ( oc
->oc_names
) {
574 print_literal(ss
,"NAME");
575 print_qdescrs(ss
,oc
->oc_names
);
579 print_literal(ss
,"DESC");
580 print_qdstring(ss
,oc
->oc_desc
);
583 if ( oc
->oc_obsolete
) {
584 print_literal(ss
, "OBSOLETE");
588 if ( oc
->oc_sup_oids
) {
589 print_literal(ss
,"SUP");
591 print_oids(ss
,oc
->oc_sup_oids
);
595 switch (oc
->oc_kind
) {
596 case LDAP_SCHEMA_ABSTRACT
:
597 print_literal(ss
,"ABSTRACT");
599 case LDAP_SCHEMA_STRUCTURAL
:
600 print_literal(ss
,"STRUCTURAL");
602 case LDAP_SCHEMA_AUXILIARY
:
603 print_literal(ss
,"AUXILIARY");
606 print_literal(ss
,"KIND-UNKNOWN");
611 if ( oc
->oc_at_oids_must
) {
612 print_literal(ss
,"MUST");
614 print_oids(ss
,oc
->oc_at_oids_must
);
618 if ( oc
->oc_at_oids_may
) {
619 print_literal(ss
,"MAY");
621 print_oids(ss
,oc
->oc_at_oids_may
);
627 print_extensions(ss
, oc
->oc_extensions
);
629 print_literal(ss
, /*(*/")");
631 bv
->bv_val
= safe_strdup(ss
);
632 bv
->bv_len
= ss
->pos
;
633 safe_string_free(ss
);
638 ldap_contentrule2str( LDAPContentRule
* cr
)
641 if (ldap_contentrule2bv( cr
, &bv
))
648 ldap_contentrule2bv( LDAPContentRule
* cr
, struct berval
*bv
)
655 ss
= new_safe_string(256);
659 print_literal(ss
,"("/*)*/);
662 print_numericoid(ss
, cr
->cr_oid
);
665 if ( cr
->cr_names
) {
666 print_literal(ss
,"NAME");
667 print_qdescrs(ss
,cr
->cr_names
);
671 print_literal(ss
,"DESC");
672 print_qdstring(ss
,cr
->cr_desc
);
675 if ( cr
->cr_obsolete
) {
676 print_literal(ss
, "OBSOLETE");
680 if ( cr
->cr_oc_oids_aux
) {
681 print_literal(ss
,"AUX");
683 print_oids(ss
,cr
->cr_oc_oids_aux
);
687 if ( cr
->cr_at_oids_must
) {
688 print_literal(ss
,"MUST");
690 print_oids(ss
,cr
->cr_at_oids_must
);
694 if ( cr
->cr_at_oids_may
) {
695 print_literal(ss
,"MAY");
697 print_oids(ss
,cr
->cr_at_oids_may
);
701 if ( cr
->cr_at_oids_not
) {
702 print_literal(ss
,"NOT");
704 print_oids(ss
,cr
->cr_at_oids_not
);
709 print_extensions(ss
, cr
->cr_extensions
);
711 print_literal(ss
, /*(*/")");
713 bv
->bv_val
= safe_strdup(ss
);
714 bv
->bv_len
= ss
->pos
;
715 safe_string_free(ss
);
720 ldap_structurerule2str( LDAPStructureRule
* sr
)
723 if (ldap_structurerule2bv( sr
, &bv
))
730 ldap_structurerule2bv( LDAPStructureRule
* sr
, struct berval
*bv
)
737 ss
= new_safe_string(256);
741 print_literal(ss
,"("/*)*/);
744 print_ruleid(ss
, sr
->sr_ruleid
);
747 if ( sr
->sr_names
) {
748 print_literal(ss
,"NAME");
749 print_qdescrs(ss
,sr
->sr_names
);
753 print_literal(ss
,"DESC");
754 print_qdstring(ss
,sr
->sr_desc
);
757 if ( sr
->sr_obsolete
) {
758 print_literal(ss
, "OBSOLETE");
762 print_literal(ss
,"FORM");
764 print_woid(ss
,sr
->sr_nameform
);
767 if ( sr
->sr_nsup_ruleids
) {
768 print_literal(ss
,"SUP");
770 print_ruleids(ss
,sr
->sr_nsup_ruleids
,sr
->sr_sup_ruleids
);
775 print_extensions(ss
, sr
->sr_extensions
);
777 print_literal(ss
, /*(*/")");
779 bv
->bv_val
= safe_strdup(ss
);
780 bv
->bv_len
= ss
->pos
;
781 safe_string_free(ss
);
787 ldap_nameform2str( LDAPNameForm
* nf
)
790 if (ldap_nameform2bv( nf
, &bv
))
797 ldap_nameform2bv( LDAPNameForm
* nf
, struct berval
*bv
)
804 ss
= new_safe_string(256);
808 print_literal(ss
,"("/*)*/);
811 print_numericoid(ss
, nf
->nf_oid
);
814 if ( nf
->nf_names
) {
815 print_literal(ss
,"NAME");
816 print_qdescrs(ss
,nf
->nf_names
);
820 print_literal(ss
,"DESC");
821 print_qdstring(ss
,nf
->nf_desc
);
824 if ( nf
->nf_obsolete
) {
825 print_literal(ss
, "OBSOLETE");
829 print_literal(ss
,"OC");
831 print_woid(ss
,nf
->nf_objectclass
);
834 print_literal(ss
,"MUST");
836 print_oids(ss
,nf
->nf_at_oids_must
);
840 if ( nf
->nf_at_oids_may
) {
841 print_literal(ss
,"MAY");
843 print_oids(ss
,nf
->nf_at_oids_may
);
848 print_extensions(ss
, nf
->nf_extensions
);
850 print_literal(ss
, /*(*/")");
852 bv
->bv_val
= safe_strdup(ss
);
853 bv
->bv_len
= ss
->pos
;
854 safe_string_free(ss
);
859 ldap_attributetype2str( LDAPAttributeType
* at
)
862 if (ldap_attributetype2bv( at
, &bv
))
869 ldap_attributetype2bv( LDAPAttributeType
* at
, struct berval
*bv
)
876 ss
= new_safe_string(256);
880 print_literal(ss
,"("/*)*/);
883 print_numericoid(ss
, at
->at_oid
);
886 if ( at
->at_names
) {
887 print_literal(ss
,"NAME");
888 print_qdescrs(ss
,at
->at_names
);
892 print_literal(ss
,"DESC");
893 print_qdstring(ss
,at
->at_desc
);
896 if ( at
->at_obsolete
) {
897 print_literal(ss
, "OBSOLETE");
901 if ( at
->at_sup_oid
) {
902 print_literal(ss
,"SUP");
903 print_woid(ss
,at
->at_sup_oid
);
906 if ( at
->at_equality_oid
) {
907 print_literal(ss
,"EQUALITY");
908 print_woid(ss
,at
->at_equality_oid
);
911 if ( at
->at_ordering_oid
) {
912 print_literal(ss
,"ORDERING");
913 print_woid(ss
,at
->at_ordering_oid
);
916 if ( at
->at_substr_oid
) {
917 print_literal(ss
,"SUBSTR");
918 print_woid(ss
,at
->at_substr_oid
);
921 if ( at
->at_syntax_oid
) {
922 print_literal(ss
,"SYNTAX");
924 print_noidlen(ss
,at
->at_syntax_oid
,at
->at_syntax_len
);
928 if ( at
->at_single_value
== LDAP_SCHEMA_YES
) {
929 print_literal(ss
,"SINGLE-VALUE");
933 if ( at
->at_collective
== LDAP_SCHEMA_YES
) {
934 print_literal(ss
,"COLLECTIVE");
938 if ( at
->at_no_user_mod
== LDAP_SCHEMA_YES
) {
939 print_literal(ss
,"NO-USER-MODIFICATION");
943 if ( at
->at_usage
!= LDAP_SCHEMA_USER_APPLICATIONS
) {
944 print_literal(ss
,"USAGE");
946 switch (at
->at_usage
) {
947 case LDAP_SCHEMA_DIRECTORY_OPERATION
:
948 print_literal(ss
,"directoryOperation");
950 case LDAP_SCHEMA_DISTRIBUTED_OPERATION
:
951 print_literal(ss
,"distributedOperation");
953 case LDAP_SCHEMA_DSA_OPERATION
:
954 print_literal(ss
,"dSAOperation");
957 print_literal(ss
,"UNKNOWN");
964 print_extensions(ss
, at
->at_extensions
);
966 print_literal(ss
,/*(*/")");
968 bv
->bv_val
= safe_strdup(ss
);
969 bv
->bv_len
= ss
->pos
;
970 safe_string_free(ss
);
975 * Now come the parsers. There is one parser for each entity type:
976 * objectclasses, attributetypes, etc.
978 * Each of them is written as a recursive-descent parser, except that
979 * none of them is really recursive. But the idea is kept: there
980 * is one routine per non-terminal that either gobbles lexical tokens
981 * or calls lower-level routines, etc.
983 * The scanner is implemented in the routine get_token. Actually,
984 * get_token is more than a scanner and will return tokens that are
985 * in fact non-terminals in the grammar. So you can see the whole
986 * approach as the combination of a low-level bottom-up recognizer
987 * combined with a scanner and a number of top-down parsers. Or just
988 * consider that the real grammars recognized by the parsers are not
989 * those of the standards. As a matter of fact, our parsers are more
990 * liberal than the spec when there is no ambiguity.
992 * The difference is pretty academic (modulo bugs or incorrect
993 * interpretation of the specs).
1006 TK_QDESCR
= TK_QDSTRING
1010 get_token( const char ** sp
, char ** token_val
)
1024 kind
= TK_LEFTPAREN
;
1028 kind
= TK_RIGHTPAREN
;
1039 while ( **sp
!= '\'' && **sp
!= '\0' )
1041 if ( **sp
== '\'' ) {
1043 res
= LDAP_MALLOC(q
-p
+1);
1053 kind
= TK_NOENDQUOTE
;
1059 while ( !LDAP_SPACE(**sp
) &&
1064 /* for suggested minimum upper bound on the number
1065 * of characters (RFC 4517) */
1070 res
= LDAP_MALLOC(q
-p
+1);
1079 /* kind = TK_UNEXPCHAR; */
1086 /* Gobble optional whitespace */
1088 parse_whsp(const char **sp
)
1090 while (LDAP_SPACE(**sp
))
1095 * General note for all parsers: to guarantee the algorithm halts they
1096 * must always advance the pointer even when an error is found. For
1097 * this one is not that important since an error here is fatal at the
1098 * upper layers, but it is a simple strategy that will not get in
1102 /* Parse a sequence of dot-separated decimal strings */
1104 ldap_int_parse_numericoid(const char **sp
, int *code
, const int flags
)
1107 const char * start
= *sp
;
1111 /* Netscape puts the SYNTAX value in quotes (incorrectly) */
1112 if ( flags
& LDAP_SCHEMA_ALLOW_QUOTED
&& **sp
== '\'' ) {
1117 /* Each iteration of this loop gets one decimal string */
1119 if ( !LDAP_DIGIT(**sp
) ) {
1121 * Initial char is not a digit or char after dot is
1124 *code
= LDAP_SCHERR_NODIGIT
;
1128 while ( LDAP_DIGIT(**sp
) )
1132 /* Otherwise, gobble the dot and loop again */
1135 /* Now *sp points at the char past the numericoid. Perfect. */
1137 if ( flags
& LDAP_SCHEMA_ALLOW_QUOTED
&& quoted
) {
1138 if ( **sp
== '\'' ) {
1141 *code
= LDAP_SCHERR_UNEXPTOKEN
;
1145 if (flags
& LDAP_SCHEMA_SKIP
) {
1146 res
= (char *)start
;
1148 res
= LDAP_MALLOC(len
+1);
1150 *code
= LDAP_SCHERR_OUTOFMEM
;
1153 strncpy(res
,start
,len
);
1159 /* Parse a sequence of dot-separated decimal strings */
1161 ldap_int_parse_ruleid(const char **sp
, int *code
, const int flags
, int *ruleid
)
1165 if ( !LDAP_DIGIT(**sp
) ) {
1166 *code
= LDAP_SCHERR_NODIGIT
;
1169 *ruleid
= (**sp
) - '0';
1172 while ( LDAP_DIGIT(**sp
) ) {
1174 *ruleid
+= (**sp
) - '0';
1181 /* Parse a qdescr or a list of them enclosed in () */
1183 parse_qdescrs(const char **sp
, int *code
)
1193 kind
= get_token(sp
,&sval
);
1194 if ( kind
== TK_LEFTPAREN
) {
1195 /* Let's presume there will be at least 2 entries */
1197 res
= LDAP_CALLOC(3,sizeof(char *));
1199 *code
= LDAP_SCHERR_OUTOFMEM
;
1205 kind
= get_token(sp
,&sval
);
1206 if ( kind
== TK_RIGHTPAREN
)
1208 if ( kind
== TK_QDESCR
) {
1209 if ( pos
== size
-2 ) {
1211 res1
= LDAP_REALLOC(res
,size
*sizeof(char *));
1215 *code
= LDAP_SCHERR_OUTOFMEM
;
1226 *code
= LDAP_SCHERR_UNEXPTOKEN
;
1232 } else if ( kind
== TK_QDESCR
) {
1233 res
= LDAP_CALLOC(2,sizeof(char *));
1235 *code
= LDAP_SCHERR_OUTOFMEM
;
1244 *code
= LDAP_SCHERR_BADNAME
;
1251 parse_woid(const char **sp
, int *code
)
1257 kind
= get_token(sp
, &sval
);
1258 if ( kind
!= TK_BAREWORD
) {
1260 *code
= LDAP_SCHERR_UNEXPTOKEN
;
1267 /* Parse a noidlen */
1269 parse_noidlen(const char **sp
, int *code
, int *len
, int flags
)
1272 const char *savepos
;
1274 int allow_quoted
= ( flags
& LDAP_SCHEMA_ALLOW_QUOTED
);
1275 int allow_oidmacro
= ( flags
& LDAP_SCHEMA_ALLOW_OID_MACRO
);
1278 /* Netscape puts the SYNTAX value in quotes (incorrectly) */
1279 if ( allow_quoted
&& **sp
== '\'' ) {
1284 sval
= ldap_int_parse_numericoid(sp
, code
, 0);
1288 && *code
== LDAP_SCHERR_NODIGIT
)
1290 if ( get_token(sp
, &sval
) != TK_BAREWORD
) {
1291 if ( sval
!= NULL
) {
1300 if ( **sp
== '{' /*}*/ ) {
1303 while ( LDAP_DIGIT(**sp
) )
1305 if ( **sp
!= /*{*/ '}' ) {
1306 *code
= LDAP_SCHERR_UNEXPTOKEN
;
1312 if ( allow_quoted
&& quoted
) {
1313 if ( **sp
== '\'' ) {
1316 *code
= LDAP_SCHERR_UNEXPTOKEN
;
1325 * Next routine will accept a qdstring in place of an oid if
1326 * allow_quoted is set. This is necessary to interoperate with
1327 * Netscape Directory server that will improperly quote each oid (at
1328 * least those of the descr kind) in the SUP clause.
1331 /* Parse a woid or a $-separated list of them enclosed in () */
1333 parse_oids(const char **sp
, int *code
, const int allow_quoted
)
1343 * Strictly speaking, doing this here accepts whsp before the
1344 * ( at the beginning of an oidlist, but this is harmless. Also,
1345 * we are very liberal in what we accept as an OID. Maybe
1349 kind
= get_token(sp
,&sval
);
1350 if ( kind
== TK_LEFTPAREN
) {
1351 /* Let's presume there will be at least 2 entries */
1353 res
= LDAP_CALLOC(3,sizeof(char *));
1355 *code
= LDAP_SCHERR_OUTOFMEM
;
1360 kind
= get_token(sp
,&sval
);
1361 if ( kind
== TK_BAREWORD
||
1362 ( allow_quoted
&& kind
== TK_QDSTRING
) ) {
1365 } else if ( kind
== TK_RIGHTPAREN
) {
1366 /* FIXME: be liberal in what we accept... */
1371 *code
= LDAP_SCHERR_UNEXPTOKEN
;
1378 kind
= get_token(sp
,&sval
);
1379 if ( kind
== TK_RIGHTPAREN
)
1381 if ( kind
== TK_DOLLAR
) {
1383 kind
= get_token(sp
,&sval
);
1384 if ( kind
== TK_BAREWORD
||
1386 kind
== TK_QDSTRING
) ) {
1387 if ( pos
== size
-2 ) {
1389 res1
= LDAP_REALLOC(res
,size
*sizeof(char *));
1393 *code
= LDAP_SCHERR_OUTOFMEM
;
1401 *code
= LDAP_SCHERR_UNEXPTOKEN
;
1408 *code
= LDAP_SCHERR_UNEXPTOKEN
;
1416 } else if ( kind
== TK_BAREWORD
||
1417 ( allow_quoted
&& kind
== TK_QDSTRING
) ) {
1418 res
= LDAP_CALLOC(2,sizeof(char *));
1421 *code
= LDAP_SCHERR_OUTOFMEM
;
1430 *code
= LDAP_SCHERR_BADNAME
;
1436 add_extension(LDAPSchemaExtensionItem
***extensions
,
1437 char * name
, char ** values
)
1440 LDAPSchemaExtensionItem
**tmp
, *ext
;
1442 ext
= LDAP_CALLOC(1, sizeof(LDAPSchemaExtensionItem
));
1445 ext
->lsei_name
= name
;
1446 ext
->lsei_values
= values
;
1448 if ( !*extensions
) {
1450 LDAP_CALLOC(2, sizeof(LDAPSchemaExtensionItem
*));
1451 if ( !*extensions
) {
1457 for ( n
=0; (*extensions
)[n
] != NULL
; n
++ )
1459 tmp
= LDAP_REALLOC(*extensions
,
1460 (n
+2)*sizeof(LDAPSchemaExtensionItem
*));
1467 (*extensions
)[n
] = ext
;
1468 (*extensions
)[n
+1] = NULL
;
1473 free_extensions(LDAPSchemaExtensionItem
**extensions
)
1475 LDAPSchemaExtensionItem
**ext
;
1478 for ( ext
= extensions
; *ext
!= NULL
; ext
++ ) {
1479 LDAP_FREE((*ext
)->lsei_name
);
1480 LDAP_VFREE((*ext
)->lsei_values
);
1483 LDAP_FREE(extensions
);
1488 ldap_syntax_free( LDAPSyntax
* syn
)
1491 LDAP_FREE(syn
->syn_oid
);
1492 if (syn
->syn_names
) LDAP_VFREE(syn
->syn_names
);
1493 if (syn
->syn_desc
) LDAP_FREE(syn
->syn_desc
);
1494 free_extensions(syn
->syn_extensions
);
1499 ldap_str2syntax( LDAP_CONST
char * s
,
1501 LDAP_CONST
char ** errp
,
1502 LDAP_CONST
unsigned flags
)
1505 const char * ss
= s
;
1513 *code
= LDAP_SCHERR_EMPTY
;
1519 syn
= LDAP_CALLOC(1,sizeof(LDAPSyntax
));
1522 *code
= LDAP_SCHERR_OUTOFMEM
;
1526 kind
= get_token(&ss
,&sval
);
1527 if ( kind
!= TK_LEFTPAREN
) {
1529 *code
= LDAP_SCHERR_NOLEFTPAREN
;
1530 ldap_syntax_free(syn
);
1535 syn
->syn_oid
= ldap_int_parse_numericoid(&ss
,code
,0);
1536 if ( !syn
->syn_oid
) {
1538 ldap_syntax_free(syn
);
1544 * Beyond this point we will be liberal and accept the items
1548 kind
= get_token(&ss
,&sval
);
1551 *code
= LDAP_SCHERR_NORIGHTPAREN
;
1553 ldap_syntax_free(syn
);
1558 if ( !strcasecmp(sval
,"NAME") ) {
1561 *code
= LDAP_SCHERR_DUPOPT
;
1563 ldap_syntax_free(syn
);
1567 syn
->syn_names
= parse_qdescrs(&ss
,code
);
1568 if ( !syn
->syn_names
) {
1569 if ( *code
!= LDAP_SCHERR_OUTOFMEM
)
1570 *code
= LDAP_SCHERR_BADNAME
;
1572 ldap_syntax_free(syn
);
1575 } else if ( !strcasecmp(sval
,"DESC") ) {
1578 *code
= LDAP_SCHERR_DUPOPT
;
1580 ldap_syntax_free(syn
);
1585 kind
= get_token(&ss
,&sval
);
1586 if ( kind
!= TK_QDSTRING
) {
1587 *code
= LDAP_SCHERR_UNEXPTOKEN
;
1590 ldap_syntax_free(syn
);
1593 syn
->syn_desc
= sval
;
1595 } else if ( sval
[0] == 'X' && sval
[1] == '-' ) {
1596 /* Should be parse_qdstrings */
1597 ext_vals
= parse_qdescrs(&ss
, code
);
1600 ldap_syntax_free(syn
);
1603 if ( add_extension(&syn
->syn_extensions
,
1605 *code
= LDAP_SCHERR_OUTOFMEM
;
1608 ldap_syntax_free(syn
);
1612 *code
= LDAP_SCHERR_UNEXPTOKEN
;
1615 ldap_syntax_free(syn
);
1620 *code
= LDAP_SCHERR_UNEXPTOKEN
;
1623 ldap_syntax_free(syn
);
1630 ldap_matchingrule_free( LDAPMatchingRule
* mr
)
1633 LDAP_FREE(mr
->mr_oid
);
1634 if (mr
->mr_names
) LDAP_VFREE(mr
->mr_names
);
1635 if (mr
->mr_desc
) LDAP_FREE(mr
->mr_desc
);
1636 if (mr
->mr_syntax_oid
) LDAP_FREE(mr
->mr_syntax_oid
);
1637 free_extensions(mr
->mr_extensions
);
1642 ldap_str2matchingrule( LDAP_CONST
char * s
,
1644 LDAP_CONST
char ** errp
,
1645 LDAP_CONST
unsigned flags
)
1648 const char * ss
= s
;
1652 int seen_obsolete
= 0;
1653 int seen_syntax
= 0;
1654 LDAPMatchingRule
* mr
;
1656 const char * savepos
;
1659 *code
= LDAP_SCHERR_EMPTY
;
1665 mr
= LDAP_CALLOC(1,sizeof(LDAPMatchingRule
));
1668 *code
= LDAP_SCHERR_OUTOFMEM
;
1672 kind
= get_token(&ss
,&sval
);
1673 if ( kind
!= TK_LEFTPAREN
) {
1674 *code
= LDAP_SCHERR_NOLEFTPAREN
;
1676 ldap_matchingrule_free(mr
);
1682 mr
->mr_oid
= ldap_int_parse_numericoid(&ss
,code
,flags
);
1683 if ( !mr
->mr_oid
) {
1684 if ( flags
& LDAP_SCHEMA_ALLOW_NO_OID
) {
1687 kind
= get_token(&ss
,&sval
);
1688 if ( kind
== TK_BAREWORD
) {
1689 if ( !strcasecmp(sval
, "NAME") ||
1690 !strcasecmp(sval
, "DESC") ||
1691 !strcasecmp(sval
, "OBSOLETE") ||
1692 !strcasecmp(sval
, "SYNTAX") ||
1693 !strncasecmp(sval
, "X-", 2) ) {
1694 /* Missing OID, backtrack */
1697 /* Non-numerical OID, ignore */
1703 ldap_matchingrule_free(mr
);
1710 * Beyond this point we will be liberal and accept the items
1714 kind
= get_token(&ss
,&sval
);
1717 *code
= LDAP_SCHERR_NORIGHTPAREN
;
1719 ldap_matchingrule_free(mr
);
1722 if( !seen_syntax
) {
1723 *code
= LDAP_SCHERR_MISSING
;
1724 ldap_matchingrule_free(mr
);
1729 if ( !strcasecmp(sval
,"NAME") ) {
1732 *code
= LDAP_SCHERR_DUPOPT
;
1734 ldap_matchingrule_free(mr
);
1738 mr
->mr_names
= parse_qdescrs(&ss
,code
);
1739 if ( !mr
->mr_names
) {
1740 if ( *code
!= LDAP_SCHERR_OUTOFMEM
)
1741 *code
= LDAP_SCHERR_BADNAME
;
1743 ldap_matchingrule_free(mr
);
1746 } else if ( !strcasecmp(sval
,"DESC") ) {
1749 *code
= LDAP_SCHERR_DUPOPT
;
1751 ldap_matchingrule_free(mr
);
1756 kind
= get_token(&ss
,&sval
);
1757 if ( kind
!= TK_QDSTRING
) {
1758 *code
= LDAP_SCHERR_UNEXPTOKEN
;
1761 ldap_matchingrule_free(mr
);
1766 } else if ( !strcasecmp(sval
,"OBSOLETE") ) {
1768 if ( seen_obsolete
) {
1769 *code
= LDAP_SCHERR_DUPOPT
;
1771 ldap_matchingrule_free(mr
);
1775 mr
->mr_obsolete
= LDAP_SCHEMA_YES
;
1777 } else if ( !strcasecmp(sval
,"SYNTAX") ) {
1779 if ( seen_syntax
) {
1780 *code
= LDAP_SCHERR_DUPOPT
;
1782 ldap_matchingrule_free(mr
);
1788 ldap_int_parse_numericoid(&ss
,code
,flags
);
1789 if ( !mr
->mr_syntax_oid
) {
1791 ldap_matchingrule_free(mr
);
1795 } else if ( sval
[0] == 'X' && sval
[1] == '-' ) {
1796 /* Should be parse_qdstrings */
1797 ext_vals
= parse_qdescrs(&ss
, code
);
1800 ldap_matchingrule_free(mr
);
1803 if ( add_extension(&mr
->mr_extensions
,
1805 *code
= LDAP_SCHERR_OUTOFMEM
;
1808 ldap_matchingrule_free(mr
);
1812 *code
= LDAP_SCHERR_UNEXPTOKEN
;
1815 ldap_matchingrule_free(mr
);
1820 *code
= LDAP_SCHERR_UNEXPTOKEN
;
1823 ldap_matchingrule_free(mr
);
1830 ldap_matchingruleuse_free( LDAPMatchingRuleUse
* mru
)
1833 LDAP_FREE(mru
->mru_oid
);
1834 if (mru
->mru_names
) LDAP_VFREE(mru
->mru_names
);
1835 if (mru
->mru_desc
) LDAP_FREE(mru
->mru_desc
);
1836 if (mru
->mru_applies_oids
) LDAP_VFREE(mru
->mru_applies_oids
);
1837 free_extensions(mru
->mru_extensions
);
1841 LDAPMatchingRuleUse
*
1842 ldap_str2matchingruleuse( LDAP_CONST
char * s
,
1844 LDAP_CONST
char ** errp
,
1845 LDAP_CONST
unsigned flags
)
1848 const char * ss
= s
;
1852 int seen_obsolete
= 0;
1853 int seen_applies
= 0;
1854 LDAPMatchingRuleUse
* mru
;
1856 const char * savepos
;
1859 *code
= LDAP_SCHERR_EMPTY
;
1865 mru
= LDAP_CALLOC(1,sizeof(LDAPMatchingRuleUse
));
1868 *code
= LDAP_SCHERR_OUTOFMEM
;
1872 kind
= get_token(&ss
,&sval
);
1873 if ( kind
!= TK_LEFTPAREN
) {
1874 *code
= LDAP_SCHERR_NOLEFTPAREN
;
1876 ldap_matchingruleuse_free(mru
);
1882 mru
->mru_oid
= ldap_int_parse_numericoid(&ss
,code
,flags
);
1883 if ( !mru
->mru_oid
) {
1884 if ( flags
& LDAP_SCHEMA_ALLOW_NO_OID
) {
1887 kind
= get_token(&ss
,&sval
);
1888 if ( kind
== TK_BAREWORD
) {
1889 if ( !strcasecmp(sval
, "NAME") ||
1890 !strcasecmp(sval
, "DESC") ||
1891 !strcasecmp(sval
, "OBSOLETE") ||
1892 !strcasecmp(sval
, "APPLIES") ||
1893 !strncasecmp(sval
, "X-", 2) ) {
1894 /* Missing OID, backtrack */
1897 /* Non-numerical OID, ignore */
1903 ldap_matchingruleuse_free(mru
);
1910 * Beyond this point we will be liberal and accept the items
1914 kind
= get_token(&ss
,&sval
);
1917 *code
= LDAP_SCHERR_NORIGHTPAREN
;
1919 ldap_matchingruleuse_free(mru
);
1922 if( !seen_applies
) {
1923 *code
= LDAP_SCHERR_MISSING
;
1924 ldap_matchingruleuse_free(mru
);
1929 if ( !strcasecmp(sval
,"NAME") ) {
1932 *code
= LDAP_SCHERR_DUPOPT
;
1934 ldap_matchingruleuse_free(mru
);
1938 mru
->mru_names
= parse_qdescrs(&ss
,code
);
1939 if ( !mru
->mru_names
) {
1940 if ( *code
!= LDAP_SCHERR_OUTOFMEM
)
1941 *code
= LDAP_SCHERR_BADNAME
;
1943 ldap_matchingruleuse_free(mru
);
1946 } else if ( !strcasecmp(sval
,"DESC") ) {
1949 *code
= LDAP_SCHERR_DUPOPT
;
1951 ldap_matchingruleuse_free(mru
);
1956 kind
= get_token(&ss
,&sval
);
1957 if ( kind
!= TK_QDSTRING
) {
1958 *code
= LDAP_SCHERR_UNEXPTOKEN
;
1961 ldap_matchingruleuse_free(mru
);
1964 mru
->mru_desc
= sval
;
1966 } else if ( !strcasecmp(sval
,"OBSOLETE") ) {
1968 if ( seen_obsolete
) {
1969 *code
= LDAP_SCHERR_DUPOPT
;
1971 ldap_matchingruleuse_free(mru
);
1975 mru
->mru_obsolete
= LDAP_SCHEMA_YES
;
1977 } else if ( !strcasecmp(sval
,"APPLIES") ) {
1979 if ( seen_applies
) {
1980 *code
= LDAP_SCHERR_DUPOPT
;
1982 ldap_matchingruleuse_free(mru
);
1986 mru
->mru_applies_oids
= parse_oids(&ss
,
1989 if ( !mru
->mru_applies_oids
&& *code
!= LDAP_SUCCESS
) {
1991 ldap_matchingruleuse_free(mru
);
1994 } else if ( sval
[0] == 'X' && sval
[1] == '-' ) {
1995 /* Should be parse_qdstrings */
1996 ext_vals
= parse_qdescrs(&ss
, code
);
1999 ldap_matchingruleuse_free(mru
);
2002 if ( add_extension(&mru
->mru_extensions
,
2004 *code
= LDAP_SCHERR_OUTOFMEM
;
2007 ldap_matchingruleuse_free(mru
);
2011 *code
= LDAP_SCHERR_UNEXPTOKEN
;
2014 ldap_matchingruleuse_free(mru
);
2019 *code
= LDAP_SCHERR_UNEXPTOKEN
;
2022 ldap_matchingruleuse_free(mru
);
2029 ldap_attributetype_free(LDAPAttributeType
* at
)
2032 LDAP_FREE(at
->at_oid
);
2033 if (at
->at_names
) LDAP_VFREE(at
->at_names
);
2034 if (at
->at_desc
) LDAP_FREE(at
->at_desc
);
2035 if (at
->at_sup_oid
) LDAP_FREE(at
->at_sup_oid
);
2036 if (at
->at_equality_oid
) LDAP_FREE(at
->at_equality_oid
);
2037 if (at
->at_ordering_oid
) LDAP_FREE(at
->at_ordering_oid
);
2038 if (at
->at_substr_oid
) LDAP_FREE(at
->at_substr_oid
);
2039 if (at
->at_syntax_oid
) LDAP_FREE(at
->at_syntax_oid
);
2040 free_extensions(at
->at_extensions
);
2045 ldap_str2attributetype( LDAP_CONST
char * s
,
2047 LDAP_CONST
char ** errp
,
2048 LDAP_CONST
unsigned flags
)
2051 const char * ss
= s
;
2055 int seen_obsolete
= 0;
2057 int seen_equality
= 0;
2058 int seen_ordering
= 0;
2059 int seen_substr
= 0;
2060 int seen_syntax
= 0;
2062 LDAPAttributeType
* at
;
2064 const char * savepos
;
2067 *code
= LDAP_SCHERR_EMPTY
;
2073 at
= LDAP_CALLOC(1,sizeof(LDAPAttributeType
));
2076 *code
= LDAP_SCHERR_OUTOFMEM
;
2080 kind
= get_token(&ss
,&sval
);
2081 if ( kind
!= TK_LEFTPAREN
) {
2082 *code
= LDAP_SCHERR_NOLEFTPAREN
;
2084 ldap_attributetype_free(at
);
2089 * Definitions MUST begin with an OID in the numericoid format.
2090 * However, this routine is used by clients to parse the response
2091 * from servers and very well known servers will provide an OID
2092 * in the wrong format or even no OID at all. We do our best to
2093 * extract info from those servers.
2097 at
->at_oid
= ldap_int_parse_numericoid(&ss
,code
,0);
2098 if ( !at
->at_oid
) {
2099 if ( ( flags
& ( LDAP_SCHEMA_ALLOW_NO_OID
2100 | LDAP_SCHEMA_ALLOW_OID_MACRO
) )
2101 && (ss
== savepos
) )
2105 kind
= get_token(&ss
,&sval
);
2106 if ( kind
== TK_BAREWORD
) {
2107 if ( !strcasecmp(sval
, "NAME") ||
2108 !strcasecmp(sval
, "DESC") ||
2109 !strcasecmp(sval
, "OBSOLETE") ||
2110 !strcasecmp(sval
, "SUP") ||
2111 !strcasecmp(sval
, "EQUALITY") ||
2112 !strcasecmp(sval
, "ORDERING") ||
2113 !strcasecmp(sval
, "SUBSTR") ||
2114 !strcasecmp(sval
, "SYNTAX") ||
2115 !strcasecmp(sval
, "SINGLE-VALUE") ||
2116 !strcasecmp(sval
, "COLLECTIVE") ||
2117 !strcasecmp(sval
, "NO-USER-MODIFICATION") ||
2118 !strcasecmp(sval
, "USAGE") ||
2119 !strncasecmp(sval
, "X-", 2) )
2121 /* Missing OID, backtrack */
2124 & LDAP_SCHEMA_ALLOW_OID_MACRO
)
2126 /* Non-numerical OID ... */
2127 int len
= ss
-savepos
;
2128 at
->at_oid
= LDAP_MALLOC(len
+1);
2129 if ( !at
->at_oid
) {
2130 ldap_attributetype_free(at
);
2134 strncpy(at
->at_oid
, savepos
, len
);
2135 at
->at_oid
[len
] = 0;
2141 ldap_attributetype_free(at
);
2148 * Beyond this point we will be liberal and accept the items
2152 kind
= get_token(&ss
,&sval
);
2155 *code
= LDAP_SCHERR_NORIGHTPAREN
;
2157 ldap_attributetype_free(at
);
2162 if ( !strcasecmp(sval
,"NAME") ) {
2165 *code
= LDAP_SCHERR_DUPOPT
;
2167 ldap_attributetype_free(at
);
2171 at
->at_names
= parse_qdescrs(&ss
,code
);
2172 if ( !at
->at_names
) {
2173 if ( *code
!= LDAP_SCHERR_OUTOFMEM
)
2174 *code
= LDAP_SCHERR_BADNAME
;
2176 ldap_attributetype_free(at
);
2179 } else if ( !strcasecmp(sval
,"DESC") ) {
2182 *code
= LDAP_SCHERR_DUPOPT
;
2184 ldap_attributetype_free(at
);
2189 kind
= get_token(&ss
,&sval
);
2190 if ( kind
!= TK_QDSTRING
) {
2191 *code
= LDAP_SCHERR_UNEXPTOKEN
;
2194 ldap_attributetype_free(at
);
2199 } else if ( !strcasecmp(sval
,"OBSOLETE") ) {
2201 if ( seen_obsolete
) {
2202 *code
= LDAP_SCHERR_DUPOPT
;
2204 ldap_attributetype_free(at
);
2208 at
->at_obsolete
= LDAP_SCHEMA_YES
;
2210 } else if ( !strcasecmp(sval
,"SUP") ) {
2213 *code
= LDAP_SCHERR_DUPOPT
;
2215 ldap_attributetype_free(at
);
2219 at
->at_sup_oid
= parse_woid(&ss
,code
);
2220 if ( !at
->at_sup_oid
) {
2222 ldap_attributetype_free(at
);
2225 } else if ( !strcasecmp(sval
,"EQUALITY") ) {
2227 if ( seen_equality
) {
2228 *code
= LDAP_SCHERR_DUPOPT
;
2230 ldap_attributetype_free(at
);
2234 at
->at_equality_oid
= parse_woid(&ss
,code
);
2235 if ( !at
->at_equality_oid
) {
2237 ldap_attributetype_free(at
);
2240 } else if ( !strcasecmp(sval
,"ORDERING") ) {
2242 if ( seen_ordering
) {
2243 *code
= LDAP_SCHERR_DUPOPT
;
2245 ldap_attributetype_free(at
);
2249 at
->at_ordering_oid
= parse_woid(&ss
,code
);
2250 if ( !at
->at_ordering_oid
) {
2252 ldap_attributetype_free(at
);
2255 } else if ( !strcasecmp(sval
,"SUBSTR") ) {
2257 if ( seen_substr
) {
2258 *code
= LDAP_SCHERR_DUPOPT
;
2260 ldap_attributetype_free(at
);
2264 at
->at_substr_oid
= parse_woid(&ss
,code
);
2265 if ( !at
->at_substr_oid
) {
2267 ldap_attributetype_free(at
);
2270 } else if ( !strcasecmp(sval
,"SYNTAX") ) {
2272 if ( seen_syntax
) {
2273 *code
= LDAP_SCHERR_DUPOPT
;
2275 ldap_attributetype_free(at
);
2286 if ( !at
->at_syntax_oid
) {
2287 if ( flags
& LDAP_SCHEMA_ALLOW_OID_MACRO
) {
2288 kind
= get_token(&ss
,&sval
);
2289 if (kind
== TK_BAREWORD
)
2291 char *sp
= strchr(sval
, '{');
2292 at
->at_syntax_oid
= sval
;
2296 at
->at_syntax_len
= atoi(sp
);
2297 while ( LDAP_DIGIT(*sp
) )
2300 *code
= LDAP_SCHERR_UNEXPTOKEN
;
2302 ldap_attributetype_free(at
);
2309 ldap_attributetype_free(at
);
2314 } else if ( !strcasecmp(sval
,"SINGLE-VALUE") ) {
2316 if ( at
->at_single_value
) {
2317 *code
= LDAP_SCHERR_DUPOPT
;
2319 ldap_attributetype_free(at
);
2322 at
->at_single_value
= LDAP_SCHEMA_YES
;
2324 } else if ( !strcasecmp(sval
,"COLLECTIVE") ) {
2326 if ( at
->at_collective
) {
2327 *code
= LDAP_SCHERR_DUPOPT
;
2329 ldap_attributetype_free(at
);
2332 at
->at_collective
= LDAP_SCHEMA_YES
;
2334 } else if ( !strcasecmp(sval
,"NO-USER-MODIFICATION") ) {
2336 if ( at
->at_no_user_mod
) {
2337 *code
= LDAP_SCHERR_DUPOPT
;
2339 ldap_attributetype_free(at
);
2342 at
->at_no_user_mod
= LDAP_SCHEMA_YES
;
2344 } else if ( !strcasecmp(sval
,"USAGE") ) {
2347 *code
= LDAP_SCHERR_DUPOPT
;
2349 ldap_attributetype_free(at
);
2354 kind
= get_token(&ss
,&sval
);
2355 if ( kind
!= TK_BAREWORD
) {
2356 *code
= LDAP_SCHERR_UNEXPTOKEN
;
2359 ldap_attributetype_free(at
);
2362 if ( !strcasecmp(sval
,"userApplications") )
2364 LDAP_SCHEMA_USER_APPLICATIONS
;
2365 else if ( !strcasecmp(sval
,"directoryOperation") )
2367 LDAP_SCHEMA_DIRECTORY_OPERATION
;
2368 else if ( !strcasecmp(sval
,"distributedOperation") )
2370 LDAP_SCHEMA_DISTRIBUTED_OPERATION
;
2371 else if ( !strcasecmp(sval
,"dSAOperation") )
2373 LDAP_SCHEMA_DSA_OPERATION
;
2375 *code
= LDAP_SCHERR_UNEXPTOKEN
;
2378 ldap_attributetype_free(at
);
2383 } else if ( sval
[0] == 'X' && sval
[1] == '-' ) {
2384 /* Should be parse_qdstrings */
2385 ext_vals
= parse_qdescrs(&ss
, code
);
2388 ldap_attributetype_free(at
);
2391 if ( add_extension(&at
->at_extensions
,
2393 *code
= LDAP_SCHERR_OUTOFMEM
;
2396 ldap_attributetype_free(at
);
2400 *code
= LDAP_SCHERR_UNEXPTOKEN
;
2403 ldap_attributetype_free(at
);
2408 *code
= LDAP_SCHERR_UNEXPTOKEN
;
2411 ldap_attributetype_free(at
);
2418 ldap_objectclass_free(LDAPObjectClass
* oc
)
2421 LDAP_FREE(oc
->oc_oid
);
2422 if (oc
->oc_names
) LDAP_VFREE(oc
->oc_names
);
2423 if (oc
->oc_desc
) LDAP_FREE(oc
->oc_desc
);
2424 if (oc
->oc_sup_oids
) LDAP_VFREE(oc
->oc_sup_oids
);
2425 if (oc
->oc_at_oids_must
) LDAP_VFREE(oc
->oc_at_oids_must
);
2426 if (oc
->oc_at_oids_may
) LDAP_VFREE(oc
->oc_at_oids_may
);
2427 free_extensions(oc
->oc_extensions
);
2432 ldap_str2objectclass( LDAP_CONST
char * s
,
2434 LDAP_CONST
char ** errp
,
2435 LDAP_CONST
unsigned flags
)
2438 const char * ss
= s
;
2442 int seen_obsolete
= 0;
2447 LDAPObjectClass
* oc
;
2449 const char * savepos
;
2452 *code
= LDAP_SCHERR_EMPTY
;
2458 oc
= LDAP_CALLOC(1,sizeof(LDAPObjectClass
));
2461 *code
= LDAP_SCHERR_OUTOFMEM
;
2464 oc
->oc_kind
= LDAP_SCHEMA_STRUCTURAL
;
2466 kind
= get_token(&ss
,&sval
);
2467 if ( kind
!= TK_LEFTPAREN
) {
2468 *code
= LDAP_SCHERR_NOLEFTPAREN
;
2470 ldap_objectclass_free(oc
);
2475 * Definitions MUST begin with an OID in the numericoid format.
2476 * However, this routine is used by clients to parse the response
2477 * from servers and very well known servers will provide an OID
2478 * in the wrong format or even no OID at all. We do our best to
2479 * extract info from those servers.
2483 oc
->oc_oid
= ldap_int_parse_numericoid(&ss
,code
,0);
2484 if ( !oc
->oc_oid
) {
2485 if ( (flags
& LDAP_SCHEMA_ALLOW_ALL
) && (ss
== savepos
) ) {
2488 kind
= get_token(&ss
,&sval
);
2489 if ( kind
== TK_BAREWORD
) {
2490 if ( !strcasecmp(sval
, "NAME") ||
2491 !strcasecmp(sval
, "DESC") ||
2492 !strcasecmp(sval
, "OBSOLETE") ||
2493 !strcasecmp(sval
, "SUP") ||
2494 !strcasecmp(sval
, "ABSTRACT") ||
2495 !strcasecmp(sval
, "STRUCTURAL") ||
2496 !strcasecmp(sval
, "AUXILIARY") ||
2497 !strcasecmp(sval
, "MUST") ||
2498 !strcasecmp(sval
, "MAY") ||
2499 !strncasecmp(sval
, "X-", 2) ) {
2500 /* Missing OID, backtrack */
2503 LDAP_SCHEMA_ALLOW_OID_MACRO
) {
2504 /* Non-numerical OID, ignore */
2505 int len
= ss
-savepos
;
2506 oc
->oc_oid
= LDAP_MALLOC(len
+1);
2507 if ( !oc
->oc_oid
) {
2508 ldap_objectclass_free(oc
);
2512 strncpy(oc
->oc_oid
, savepos
, len
);
2513 oc
->oc_oid
[len
] = 0;
2520 ldap_objectclass_free(oc
);
2527 * Beyond this point we will be liberal an accept the items
2531 kind
= get_token(&ss
,&sval
);
2534 *code
= LDAP_SCHERR_NORIGHTPAREN
;
2536 ldap_objectclass_free(oc
);
2541 if ( !strcasecmp(sval
,"NAME") ) {
2544 *code
= LDAP_SCHERR_DUPOPT
;
2546 ldap_objectclass_free(oc
);
2550 oc
->oc_names
= parse_qdescrs(&ss
,code
);
2551 if ( !oc
->oc_names
) {
2552 if ( *code
!= LDAP_SCHERR_OUTOFMEM
)
2553 *code
= LDAP_SCHERR_BADNAME
;
2555 ldap_objectclass_free(oc
);
2558 } else if ( !strcasecmp(sval
,"DESC") ) {
2561 *code
= LDAP_SCHERR_DUPOPT
;
2563 ldap_objectclass_free(oc
);
2568 kind
= get_token(&ss
,&sval
);
2569 if ( kind
!= TK_QDSTRING
) {
2570 *code
= LDAP_SCHERR_UNEXPTOKEN
;
2573 ldap_objectclass_free(oc
);
2578 } else if ( !strcasecmp(sval
,"OBSOLETE") ) {
2580 if ( seen_obsolete
) {
2581 *code
= LDAP_SCHERR_DUPOPT
;
2583 ldap_objectclass_free(oc
);
2587 oc
->oc_obsolete
= LDAP_SCHEMA_YES
;
2589 } else if ( !strcasecmp(sval
,"SUP") ) {
2592 *code
= LDAP_SCHERR_DUPOPT
;
2594 ldap_objectclass_free(oc
);
2598 oc
->oc_sup_oids
= parse_oids(&ss
,
2601 if ( !oc
->oc_sup_oids
&& *code
!= LDAP_SUCCESS
) {
2603 ldap_objectclass_free(oc
);
2607 } else if ( !strcasecmp(sval
,"ABSTRACT") ) {
2610 *code
= LDAP_SCHERR_DUPOPT
;
2612 ldap_objectclass_free(oc
);
2616 oc
->oc_kind
= LDAP_SCHEMA_ABSTRACT
;
2618 } else if ( !strcasecmp(sval
,"STRUCTURAL") ) {
2621 *code
= LDAP_SCHERR_DUPOPT
;
2623 ldap_objectclass_free(oc
);
2627 oc
->oc_kind
= LDAP_SCHEMA_STRUCTURAL
;
2629 } else if ( !strcasecmp(sval
,"AUXILIARY") ) {
2632 *code
= LDAP_SCHERR_DUPOPT
;
2634 ldap_objectclass_free(oc
);
2638 oc
->oc_kind
= LDAP_SCHEMA_AUXILIARY
;
2640 } else if ( !strcasecmp(sval
,"MUST") ) {
2643 *code
= LDAP_SCHERR_DUPOPT
;
2645 ldap_objectclass_free(oc
);
2649 oc
->oc_at_oids_must
= parse_oids(&ss
,code
,0);
2650 if ( !oc
->oc_at_oids_must
&& *code
!= LDAP_SUCCESS
) {
2652 ldap_objectclass_free(oc
);
2657 } else if ( !strcasecmp(sval
,"MAY") ) {
2660 *code
= LDAP_SCHERR_DUPOPT
;
2662 ldap_objectclass_free(oc
);
2666 oc
->oc_at_oids_may
= parse_oids(&ss
,code
,0);
2667 if ( !oc
->oc_at_oids_may
&& *code
!= LDAP_SUCCESS
) {
2669 ldap_objectclass_free(oc
);
2674 } else if ( sval
[0] == 'X' && sval
[1] == '-' ) {
2675 /* Should be parse_qdstrings */
2676 ext_vals
= parse_qdescrs(&ss
, code
);
2680 ldap_objectclass_free(oc
);
2683 if ( add_extension(&oc
->oc_extensions
,
2685 *code
= LDAP_SCHERR_OUTOFMEM
;
2688 ldap_objectclass_free(oc
);
2692 *code
= LDAP_SCHERR_UNEXPTOKEN
;
2695 ldap_objectclass_free(oc
);
2700 *code
= LDAP_SCHERR_UNEXPTOKEN
;
2703 ldap_objectclass_free(oc
);
2710 ldap_contentrule_free(LDAPContentRule
* cr
)
2713 LDAP_FREE(cr
->cr_oid
);
2714 if (cr
->cr_names
) LDAP_VFREE(cr
->cr_names
);
2715 if (cr
->cr_desc
) LDAP_FREE(cr
->cr_desc
);
2716 if (cr
->cr_oc_oids_aux
) LDAP_VFREE(cr
->cr_oc_oids_aux
);
2717 if (cr
->cr_at_oids_must
) LDAP_VFREE(cr
->cr_at_oids_must
);
2718 if (cr
->cr_at_oids_may
) LDAP_VFREE(cr
->cr_at_oids_may
);
2719 if (cr
->cr_at_oids_not
) LDAP_VFREE(cr
->cr_at_oids_not
);
2720 free_extensions(cr
->cr_extensions
);
2725 ldap_str2contentrule( LDAP_CONST
char * s
,
2727 LDAP_CONST
char ** errp
,
2728 LDAP_CONST
unsigned flags
)
2731 const char * ss
= s
;
2735 int seen_obsolete
= 0;
2740 LDAPContentRule
* cr
;
2742 const char * savepos
;
2745 *code
= LDAP_SCHERR_EMPTY
;
2751 cr
= LDAP_CALLOC(1,sizeof(LDAPContentRule
));
2754 *code
= LDAP_SCHERR_OUTOFMEM
;
2758 kind
= get_token(&ss
,&sval
);
2759 if ( kind
!= TK_LEFTPAREN
) {
2760 *code
= LDAP_SCHERR_NOLEFTPAREN
;
2762 ldap_contentrule_free(cr
);
2767 * Definitions MUST begin with an OID in the numericoid format.
2771 cr
->cr_oid
= ldap_int_parse_numericoid(&ss
,code
,0);
2772 if ( !cr
->cr_oid
) {
2773 if ( (flags
& LDAP_SCHEMA_ALLOW_ALL
) && (ss
== savepos
) ) {
2776 kind
= get_token(&ss
,&sval
);
2777 if ( kind
== TK_BAREWORD
) {
2778 if ( !strcasecmp(sval
, "NAME") ||
2779 !strcasecmp(sval
, "DESC") ||
2780 !strcasecmp(sval
, "OBSOLETE") ||
2781 !strcasecmp(sval
, "AUX") ||
2782 !strcasecmp(sval
, "MUST") ||
2783 !strcasecmp(sval
, "MAY") ||
2784 !strcasecmp(sval
, "NOT") ||
2785 !strncasecmp(sval
, "X-", 2) ) {
2786 /* Missing OID, backtrack */
2789 LDAP_SCHEMA_ALLOW_OID_MACRO
) {
2790 /* Non-numerical OID, ignore */
2791 int len
= ss
-savepos
;
2792 cr
->cr_oid
= LDAP_MALLOC(len
+1);
2793 if ( !cr
->cr_oid
) {
2794 ldap_contentrule_free(cr
);
2798 strncpy(cr
->cr_oid
, savepos
, len
);
2799 cr
->cr_oid
[len
] = 0;
2805 ldap_contentrule_free(cr
);
2812 * Beyond this point we will be liberal an accept the items
2816 kind
= get_token(&ss
,&sval
);
2819 *code
= LDAP_SCHERR_NORIGHTPAREN
;
2821 ldap_contentrule_free(cr
);
2826 if ( !strcasecmp(sval
,"NAME") ) {
2829 *code
= LDAP_SCHERR_DUPOPT
;
2831 ldap_contentrule_free(cr
);
2835 cr
->cr_names
= parse_qdescrs(&ss
,code
);
2836 if ( !cr
->cr_names
) {
2837 if ( *code
!= LDAP_SCHERR_OUTOFMEM
)
2838 *code
= LDAP_SCHERR_BADNAME
;
2840 ldap_contentrule_free(cr
);
2843 } else if ( !strcasecmp(sval
,"DESC") ) {
2846 *code
= LDAP_SCHERR_DUPOPT
;
2848 ldap_contentrule_free(cr
);
2853 kind
= get_token(&ss
,&sval
);
2854 if ( kind
!= TK_QDSTRING
) {
2855 *code
= LDAP_SCHERR_UNEXPTOKEN
;
2858 ldap_contentrule_free(cr
);
2863 } else if ( !strcasecmp(sval
,"OBSOLETE") ) {
2865 if ( seen_obsolete
) {
2866 *code
= LDAP_SCHERR_DUPOPT
;
2868 ldap_contentrule_free(cr
);
2872 cr
->cr_obsolete
= LDAP_SCHEMA_YES
;
2874 } else if ( !strcasecmp(sval
,"AUX") ) {
2877 *code
= LDAP_SCHERR_DUPOPT
;
2879 ldap_contentrule_free(cr
);
2883 cr
->cr_oc_oids_aux
= parse_oids(&ss
,code
,0);
2884 if ( !cr
->cr_oc_oids_aux
) {
2886 ldap_contentrule_free(cr
);
2890 } else if ( !strcasecmp(sval
,"MUST") ) {
2893 *code
= LDAP_SCHERR_DUPOPT
;
2895 ldap_contentrule_free(cr
);
2899 cr
->cr_at_oids_must
= parse_oids(&ss
,code
,0);
2900 if ( !cr
->cr_at_oids_must
&& *code
!= LDAP_SUCCESS
) {
2902 ldap_contentrule_free(cr
);
2906 } else if ( !strcasecmp(sval
,"MAY") ) {
2909 *code
= LDAP_SCHERR_DUPOPT
;
2911 ldap_contentrule_free(cr
);
2915 cr
->cr_at_oids_may
= parse_oids(&ss
,code
,0);
2916 if ( !cr
->cr_at_oids_may
&& *code
!= LDAP_SUCCESS
) {
2918 ldap_contentrule_free(cr
);
2922 } else if ( !strcasecmp(sval
,"NOT") ) {
2925 *code
= LDAP_SCHERR_DUPOPT
;
2927 ldap_contentrule_free(cr
);
2931 cr
->cr_at_oids_not
= parse_oids(&ss
,code
,0);
2932 if ( !cr
->cr_at_oids_not
&& *code
!= LDAP_SUCCESS
) {
2934 ldap_contentrule_free(cr
);
2938 } else if ( sval
[0] == 'X' && sval
[1] == '-' ) {
2939 /* Should be parse_qdstrings */
2940 ext_vals
= parse_qdescrs(&ss
, code
);
2943 ldap_contentrule_free(cr
);
2946 if ( add_extension(&cr
->cr_extensions
,
2948 *code
= LDAP_SCHERR_OUTOFMEM
;
2951 ldap_contentrule_free(cr
);
2955 *code
= LDAP_SCHERR_UNEXPTOKEN
;
2958 ldap_contentrule_free(cr
);
2963 *code
= LDAP_SCHERR_UNEXPTOKEN
;
2966 ldap_contentrule_free(cr
);
2973 ldap_structurerule_free(LDAPStructureRule
* sr
)
2976 if (sr
->sr_names
) LDAP_VFREE(sr
->sr_names
);
2977 if (sr
->sr_desc
) LDAP_FREE(sr
->sr_desc
);
2978 if (sr
->sr_nameform
) LDAP_FREE(sr
->sr_nameform
);
2979 if (sr
->sr_sup_ruleids
) LDAP_FREE(sr
->sr_sup_ruleids
);
2980 free_extensions(sr
->sr_extensions
);
2985 ldap_str2structurerule( LDAP_CONST
char * s
,
2987 LDAP_CONST
char ** errp
,
2988 LDAP_CONST
unsigned flags
)
2992 const char * ss
= s
;
2996 int seen_obsolete
= 0;
2997 int seen_nameform
= 0;
2998 LDAPStructureRule
* sr
;
3000 const char * savepos
;
3003 *code
= LDAP_SCHERR_EMPTY
;
3009 sr
= LDAP_CALLOC(1,sizeof(LDAPStructureRule
));
3012 *code
= LDAP_SCHERR_OUTOFMEM
;
3016 kind
= get_token(&ss
,&sval
);
3017 if ( kind
!= TK_LEFTPAREN
) {
3018 *code
= LDAP_SCHERR_NOLEFTPAREN
;
3020 ldap_structurerule_free(sr
);
3025 * Definitions MUST begin with a ruleid.
3029 ret
= ldap_int_parse_ruleid(&ss
,code
,0,&sr
->sr_ruleid
);
3032 ldap_structurerule_free(sr
);
3038 * Beyond this point we will be liberal an accept the items
3042 kind
= get_token(&ss
,&sval
);
3045 *code
= LDAP_SCHERR_NORIGHTPAREN
;
3047 ldap_structurerule_free(sr
);
3050 if( !seen_nameform
) {
3051 *code
= LDAP_SCHERR_MISSING
;
3052 ldap_structurerule_free(sr
);
3057 if ( !strcasecmp(sval
,"NAME") ) {
3060 *code
= LDAP_SCHERR_DUPOPT
;
3062 ldap_structurerule_free(sr
);
3066 sr
->sr_names
= parse_qdescrs(&ss
,code
);
3067 if ( !sr
->sr_names
) {
3068 if ( *code
!= LDAP_SCHERR_OUTOFMEM
)
3069 *code
= LDAP_SCHERR_BADNAME
;
3071 ldap_structurerule_free(sr
);
3074 } else if ( !strcasecmp(sval
,"DESC") ) {
3077 *code
= LDAP_SCHERR_DUPOPT
;
3079 ldap_structurerule_free(sr
);
3084 kind
= get_token(&ss
,&sval
);
3085 if ( kind
!= TK_QDSTRING
) {
3086 *code
= LDAP_SCHERR_UNEXPTOKEN
;
3089 ldap_structurerule_free(sr
);
3094 } else if ( !strcasecmp(sval
,"OBSOLETE") ) {
3096 if ( seen_obsolete
) {
3097 *code
= LDAP_SCHERR_DUPOPT
;
3099 ldap_structurerule_free(sr
);
3103 sr
->sr_obsolete
= LDAP_SCHEMA_YES
;
3105 } else if ( !strcasecmp(sval
,"FORM") ) {
3107 if ( seen_nameform
) {
3108 *code
= LDAP_SCHERR_DUPOPT
;
3110 ldap_structurerule_free(sr
);
3114 sr
->sr_nameform
= parse_woid(&ss
,code
);
3115 if ( !sr
->sr_nameform
) {
3117 ldap_structurerule_free(sr
);
3121 } else if ( sval
[0] == 'X' && sval
[1] == '-' ) {
3122 /* Should be parse_qdstrings */
3123 ext_vals
= parse_qdescrs(&ss
, code
);
3126 ldap_structurerule_free(sr
);
3129 if ( add_extension(&sr
->sr_extensions
,
3131 *code
= LDAP_SCHERR_OUTOFMEM
;
3134 ldap_structurerule_free(sr
);
3138 *code
= LDAP_SCHERR_UNEXPTOKEN
;
3141 ldap_structurerule_free(sr
);
3146 *code
= LDAP_SCHERR_UNEXPTOKEN
;
3149 ldap_structurerule_free(sr
);
3156 ldap_nameform_free(LDAPNameForm
* nf
)
3159 LDAP_FREE(nf
->nf_oid
);
3160 if (nf
->nf_names
) LDAP_VFREE(nf
->nf_names
);
3161 if (nf
->nf_desc
) LDAP_FREE(nf
->nf_desc
);
3162 if (nf
->nf_objectclass
) LDAP_FREE(nf
->nf_objectclass
);
3163 if (nf
->nf_at_oids_must
) LDAP_VFREE(nf
->nf_at_oids_must
);
3164 if (nf
->nf_at_oids_may
) LDAP_VFREE(nf
->nf_at_oids_may
);
3165 free_extensions(nf
->nf_extensions
);
3170 ldap_str2nameform( LDAP_CONST
char * s
,
3172 LDAP_CONST
char ** errp
,
3173 LDAP_CONST
unsigned flags
)
3176 const char * ss
= s
;
3180 int seen_obsolete
= 0;
3186 const char * savepos
;
3189 *code
= LDAP_SCHERR_EMPTY
;
3195 nf
= LDAP_CALLOC(1,sizeof(LDAPNameForm
));
3198 *code
= LDAP_SCHERR_OUTOFMEM
;
3202 kind
= get_token(&ss
,&sval
);
3203 if ( kind
!= TK_LEFTPAREN
) {
3204 *code
= LDAP_SCHERR_NOLEFTPAREN
;
3206 ldap_nameform_free(nf
);
3211 * Definitions MUST begin with an OID in the numericoid format.
3212 * However, this routine is used by clients to parse the response
3213 * from servers and very well known servers will provide an OID
3214 * in the wrong format or even no OID at all. We do our best to
3215 * extract info from those servers.
3219 nf
->nf_oid
= ldap_int_parse_numericoid(&ss
,code
,0);
3220 if ( !nf
->nf_oid
) {
3222 ldap_nameform_free(nf
);
3228 * Beyond this point we will be liberal an accept the items
3232 kind
= get_token(&ss
,&sval
);
3235 *code
= LDAP_SCHERR_NORIGHTPAREN
;
3237 ldap_nameform_free(nf
);
3240 if( !seen_class
|| !seen_must
) {
3241 *code
= LDAP_SCHERR_MISSING
;
3242 ldap_nameform_free(nf
);
3247 if ( !strcasecmp(sval
,"NAME") ) {
3250 *code
= LDAP_SCHERR_DUPOPT
;
3252 ldap_nameform_free(nf
);
3256 nf
->nf_names
= parse_qdescrs(&ss
,code
);
3257 if ( !nf
->nf_names
) {
3258 if ( *code
!= LDAP_SCHERR_OUTOFMEM
)
3259 *code
= LDAP_SCHERR_BADNAME
;
3261 ldap_nameform_free(nf
);
3264 } else if ( !strcasecmp(sval
,"DESC") ) {
3267 *code
= LDAP_SCHERR_DUPOPT
;
3269 ldap_nameform_free(nf
);
3274 kind
= get_token(&ss
,&sval
);
3275 if ( kind
!= TK_QDSTRING
) {
3276 *code
= LDAP_SCHERR_UNEXPTOKEN
;
3279 ldap_nameform_free(nf
);
3284 } else if ( !strcasecmp(sval
,"OBSOLETE") ) {
3286 if ( seen_obsolete
) {
3287 *code
= LDAP_SCHERR_DUPOPT
;
3289 ldap_nameform_free(nf
);
3293 nf
->nf_obsolete
= LDAP_SCHEMA_YES
;
3295 } else if ( !strcasecmp(sval
,"OC") ) {
3298 *code
= LDAP_SCHERR_DUPOPT
;
3300 ldap_nameform_free(nf
);
3304 nf
->nf_objectclass
= parse_woid(&ss
,code
);
3305 if ( !nf
->nf_objectclass
) {
3307 ldap_nameform_free(nf
);
3310 } else if ( !strcasecmp(sval
,"MUST") ) {
3313 *code
= LDAP_SCHERR_DUPOPT
;
3315 ldap_nameform_free(nf
);
3319 nf
->nf_at_oids_must
= parse_oids(&ss
,code
,0);
3320 if ( !nf
->nf_at_oids_must
&& *code
!= LDAP_SUCCESS
) {
3322 ldap_nameform_free(nf
);
3326 } else if ( !strcasecmp(sval
,"MAY") ) {
3329 *code
= LDAP_SCHERR_DUPOPT
;
3331 ldap_nameform_free(nf
);
3335 nf
->nf_at_oids_may
= parse_oids(&ss
,code
,0);
3336 if ( !nf
->nf_at_oids_may
&& *code
!= LDAP_SUCCESS
) {
3338 ldap_nameform_free(nf
);
3342 } else if ( sval
[0] == 'X' && sval
[1] == '-' ) {
3343 /* Should be parse_qdstrings */
3344 ext_vals
= parse_qdescrs(&ss
, code
);
3347 ldap_nameform_free(nf
);
3350 if ( add_extension(&nf
->nf_extensions
,
3352 *code
= LDAP_SCHERR_OUTOFMEM
;
3355 ldap_nameform_free(nf
);
3359 *code
= LDAP_SCHERR_UNEXPTOKEN
;
3362 ldap_nameform_free(nf
);
3367 *code
= LDAP_SCHERR_UNEXPTOKEN
;
3370 ldap_nameform_free(nf
);
3376 static char *const err2text
[] = {
3378 N_("Out of memory"),
3379 N_("Unexpected token"),
3380 N_("Missing opening parenthesis"),
3381 N_("Missing closing parenthesis"),
3382 N_("Expecting digit"),
3383 N_("Expecting a name"),
3384 N_("Bad description"),
3385 N_("Bad superiors"),
3386 N_("Duplicate option"),
3387 N_("Unexpected end of data"),
3388 N_("Missing required field"),
3389 N_("Out of order field")
3393 ldap_scherr2str(int code
)
3395 if ( code
< 0 || code
>= (int)(sizeof(err2text
)/sizeof(char *)) ) {
3396 return _("Unknown error");
3398 return _(err2text
[code
]);