]> git.sur5r.net Git - openldap/blob - servers/slapd/dn.c
ndn & strcasecmp cleanup
[openldap] / servers / slapd / dn.c
1 /* dn.c - routines for dealing with distinguished names */
2
3 #include "portable.h"
4
5 #include <stdio.h>
6
7 #include <ac/ctype.h>
8 #include <ac/socket.h>
9 #include <ac/string.h>
10 #include <ac/time.h>
11
12 #include "slap.h"
13
14 #define B4TYPE          0
15 #define INTYPE          1
16 #define B4EQUAL         2
17 #define B4VALUE         3
18 #define INVALUE         4
19 #define INQUOTEDVALUE   5
20 #define B4SEPARATOR     6
21
22 /*
23  * dn_normalize - put dn into a canonical format.  the dn is
24  * normalized in place, as well as returned.
25  */
26
27 char *
28 dn_normalize( char *dn )
29 {
30         char    *d, *s;
31         int     state, gotesc;
32
33         /* Debug( LDAP_DEBUG_TRACE, "=> dn_normalize \"%s\"\n", dn, 0, 0 ); */
34
35         gotesc = 0;
36         state = B4TYPE;
37         for ( d = s = dn; *s; s++ ) {
38                 switch ( state ) {
39                 case B4TYPE:
40                         if ( ! SPACE( *s ) ) {
41                                 state = INTYPE;
42                                 *d++ = *s;
43                         }
44                         break;
45                 case INTYPE:
46                         if ( *s == '=' ) {
47                                 state = B4VALUE;
48                                 *d++ = *s;
49                         } else if ( SPACE( *s ) ) {
50                                 state = B4EQUAL;
51                         } else {
52                                 *d++ = *s;
53                         }
54                         break;
55                 case B4EQUAL:
56                         if ( *s == '=' ) {
57                                 state = B4VALUE;
58                                 *d++ = *s;
59                         } else if ( ! SPACE( *s ) ) {
60                                 /* not a valid dn - but what can we do here? */
61                                 *d++ = *s;
62                         }
63                         break;
64                 case B4VALUE:
65                         if ( *s == '"' ) {
66                                 state = INQUOTEDVALUE;
67                                 *d++ = *s;
68                         } else if ( ! SPACE( *s ) ) { 
69                                 state = INVALUE;
70                                 *d++ = *s;
71                         }
72                         break;
73                 case INVALUE:
74                         if ( !gotesc && SEPARATOR( *s ) ) {
75                                 while ( SPACE( *(d - 1) ) )
76                                         d--;
77                                 state = B4TYPE;
78                                 if ( *s == '+' ) {
79                                         *d++ = *s;
80                                 } else {
81                                         *d++ = ',';
82                                 }
83                         } else if ( gotesc && !NEEDSESCAPE( *s ) &&
84                             !SEPARATOR( *s ) ) {
85                                 *--d = *s;
86                                 d++;
87                         } else {
88                                 *d++ = *s;
89                         }
90                         break;
91                 case INQUOTEDVALUE:
92                         if ( !gotesc && *s == '"' ) {
93                                 state = B4SEPARATOR;
94                                 *d++ = *s;
95                         } else if ( gotesc && !NEEDSESCAPE( *s ) ) {
96                                 *--d = *s;
97                                 d++;
98                         } else {
99                                 *d++ = *s;
100                         }
101                         break;
102                 case B4SEPARATOR:
103                         if ( SEPARATOR( *s ) ) {
104                                 state = B4TYPE;
105                                 *d++ = *s;
106                         }
107                         break;
108                 default:
109                         Debug( LDAP_DEBUG_ANY,
110                             "dn_normalize - unknown state %d\n", state, 0, 0 );
111                         break;
112                 }
113                 if ( *s == '\\' ) {
114                         gotesc = 1;
115                 } else {
116                         gotesc = 0;
117                 }
118         }
119         *d = '\0';
120
121         /* Debug( LDAP_DEBUG_TRACE, "<= dn_normalize \"%s\"\n", dn, 0, 0 ); */
122         return( dn );
123 }
124
125 /*
126  * dn_normalize_case - put dn into a canonical form suitable for storing
127  * in a hash database.  this involves normalizing the case as well as
128  * the format.  the dn is normalized in place as well as returned.
129  */
130
131 char *
132 dn_normalize_case( char *dn )
133 {
134         char    *s;
135
136         /* normalize format */
137         dn_normalize( dn );
138
139         /* normalize case */
140         for ( s = dn; *s; s++ ) {
141                 *s = TOUPPER( *s );
142         }
143
144         return( dn );
145 }
146
147 /*
148  * dn_parent - return a copy of the dn of dn's parent
149  */
150
151 char *
152 dn_parent(
153     Backend     *be,
154     char        *dn
155 )
156 {
157         char    *s;
158         int     inquote, gotesc;
159
160         if ( dn == NULL || *dn == '\0' || be_issuffix( be, dn ) ) {
161                 return( NULL );
162         }
163
164         /*
165          * no =, assume it is a dns name, like blah@some.domain.name
166          * if the blah@ part is there, return some.domain.name.  if
167          * it's just some.domain.name, return domain.name.
168          */
169         if ( strchr( dn, '=' ) == NULL ) {
170                 if ( (s = strchr( dn, '@' )) == NULL ) {
171                         if ( (s = strchr( dn, '.' )) == NULL ) {
172                                 return( NULL );
173                         }
174                 }
175                 if ( *(s + 1) == '\0' ) {
176                         return( NULL );
177                 } else {
178                         return( ch_strdup( s + 1 ) );
179                 }
180         }
181
182         /*
183          * else assume it is an X.500-style name, which looks like
184          * foo=bar,sha=baz,...
185          */
186
187         inquote = 0;
188         for ( s = dn; *s; s++ ) {
189                 if ( *s == '\\' ) {
190                         if ( *(s + 1) )
191                                 s++;
192                         continue;
193                 }
194                 if ( inquote ) {
195                         if ( *s == '"' )
196                                 inquote = 0;
197                 } else {
198                         if ( *s == '"' )
199                                 inquote = 1;
200                         else if ( DNSEPARATOR( *s ) )
201                                 return( ch_strdup( s + 1 ) );
202                 }
203         }
204
205         return( ch_strdup("") );
206 }
207
208 /*
209  * dn_issuffix - tells whether suffix is a suffix of dn.  both dn
210  * and suffix must be normalized.
211  */
212
213 int
214 dn_issuffix(
215     char        *dn,
216     char        *suffix
217 )
218 {
219         int     dnlen, suffixlen;
220
221         if ( dn == NULL ) {
222                 return( 0 );
223         }
224
225         suffixlen = strlen( suffix );
226         dnlen = strlen( dn );
227
228         if ( suffixlen > dnlen ) {
229                 return( 0 );
230         }
231
232         return( strcmp( dn + dnlen - suffixlen, suffix ) == 0 );
233 }
234
235 /*
236  * dn_type - tells whether the given dn is an X.500 thing or DNS thing
237  * returns (defined in slap.h): DN_DNS          dns-style thing
238  *                              DN_X500         x500-style thing
239  */
240
241 int
242 dn_type( char *dn )
243 {
244         return( strchr( dn, '=' ) == NULL ? DN_DNS : DN_X500 );
245 }
246
247 char *
248 dn_upcase( char *dn )
249 {
250         char    *s;
251
252         /* normalize case */
253         for ( s = dn; *s; s++ ) {
254                 *s = TOUPPER( *s );
255         }
256
257         return( dn );
258 }