]> git.sur5r.net Git - openldap/blob - libraries/libldap/dn.c
d0ba92f886f5752d06d12fcb594465b0412ccd3a
[openldap] / libraries / libldap / dn.c
1 /* dn.c - routines for dealing with distinguished names */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/ctype.h>
13 #include <ac/socket.h>
14 #include <ac/string.h>
15 #include <ac/time.h>
16
17 #include "ldap-int.h"
18
19 #if 0
20 /* this should wait for UTF-8 routines */
21
22 #define B4LEADTYPE              0
23 #define B4TYPE                  1
24 #define INOIDTYPE               2
25 #define INKEYTYPE               3
26 #define B4EQUAL                 4
27 #define B4VALUE                 5
28 #define INVALUE                 6
29 #define INQUOTEDVALUE   7
30 #define B4SEPARATOR             8
31
32 /*
33  * ldap_dn_normalize - put dn into a canonical format
34  * and return it.
35  */
36
37 char *
38 ldap_dn_normalize( const char *dn )
39 {
40         char    *d, *s;
41         int     state, gotesc;
42         char *ndn;
43
44         if( dn == NULL ) {
45                 return NULL;
46         }
47
48         ndn = LDAP_STRDUP( dn );
49
50         if( ndn == NULL ) {
51                 return NULL;
52         }
53
54         gotesc = 0;
55         state = B4LEADTYPE;
56         for ( d = s = ndn; *s; s++ ) {
57                 switch ( state ) {
58                 case B4LEADTYPE:
59                 case B4TYPE:
60                         if ( LDAP_LEADOIDCHAR(*s) ) {
61                                 state = INOIDTYPE;
62                                 *d++ = *s;
63                         } else if ( LDAP_LEADKEYCHAR(*s) ) {
64                                 state = INKEYTYPE;
65                                 *d++ = *s;
66                         } else if ( ! LDAP_SPACE( *s ) ) {
67                                 dn = NULL;
68                                 state = INKEYTYPE;
69                                 *d++ = *s;
70                         }
71                         break;
72
73                 case INOIDTYPE:
74                         if ( LDAP_OIDCHAR(*s) ) {
75                                 *d++ = *s;
76                         } else if ( *s == '=' ) {
77                                 state = B4VALUE;
78                                 *d++ = *s;
79                         } else if ( LDAP_SPACE( *s ) ) {
80                                 state = B4EQUAL;
81                         } else {
82                                 dn = NULL;
83                                 *d++ = *s;
84                         }
85                         break;
86
87                 case INKEYTYPE:
88                         if ( LDAP_KEYCHAR(*s) ) {
89                                 *d++ = *s;
90                         } else if ( *s == '=' ) {
91                                 state = B4VALUE;
92                                 *d++ = *s;
93                         } else if ( LDAP_SPACE( *s ) ) {
94                                 state = B4EQUAL;
95                         } else {
96                                 dn = NULL;
97                                 *d++ = *s;
98                         }
99                         break;
100
101                 case B4EQUAL:
102                         if ( *s == '=' ) {
103                                 state = B4VALUE;
104                                 *d++ = *s;
105                         } else if ( ! LDAP_SPACE( *s ) ) {
106                                 /* not a valid dn - but what can we do here? */
107                                 *d++ = *s;
108                                 dn = NULL;
109                         }
110                         break;
111
112                 case B4VALUE:
113                         if ( *s == '"' ) {
114                                 state = INQUOTEDVALUE;
115                                 *d++ = *s;
116                         } else if ( ! LDAP_SPACE( *s ) ) { 
117                                 state = INVALUE;
118                                 *d++ = *s;
119                         }
120                         break;
121
122                 case INVALUE:
123                         if ( !gotesc && LDAP_SEPARATOR( *s ) ) {
124                                 while ( LDAP_SPACE( *(d - 1) ) )
125                                         d--;
126                                 state = B4TYPE;
127                                 if ( *s == '+' ) {
128                                         *d++ = *s;
129                                 } else {
130                                         *d++ = ',';
131                                 }
132                         } else if ( gotesc && !LDAP_NEEDSESCAPE( *s ) &&
133                             !LDAP_SEPARATOR( *s ) ) {
134                                 *--d = *s;
135                                 d++;
136                         } else {
137                                 *d++ = *s;
138                         }
139                         break;
140
141                 case INQUOTEDVALUE:
142                         if ( !gotesc && *s == '"' ) {
143                                 state = B4SEPARATOR;
144                                 *d++ = *s;
145                         } else if ( gotesc && !LDAP_NEEDSESCAPE( *s ) ) {
146                                 *--d = *s;
147                                 d++;
148                         } else {
149                                 *d++ = *s;
150                         }
151                         break;
152                 case B4SEPARATOR:
153                         if ( LDAP_SEPARATOR( *s ) ) {
154                                 state = B4TYPE;
155                                 *d++ = *s;
156                         }
157                         break;
158                 default:
159                         dn = NULL;
160                         Debug( LDAP_DEBUG_ANY,
161                             "dn_normalize - unknown state %d\n", state, 0, 0 );
162                         break;
163                 }
164                 if ( *s == '\\' ) {
165                         gotesc = 1;
166                 } else {
167                         gotesc = 0;
168                 }
169         }
170         *d = '\0';
171
172         if( gotesc ) {
173                 /* shouldn't be left in escape */
174                 dn = NULL;
175         }
176
177         /* check end state */
178         switch( state ) {
179         case B4LEADTYPE:        /* looking for first type */
180         case B4SEPARATOR:       /* looking for separator */
181         case INVALUE:           /* inside value */
182                 break;
183         default:
184                 dn = NULL;
185         }
186
187         if( dn == NULL ) {
188                 return( ndn );
189                 ndn = NULL;
190         }
191
192         return( ndn );
193 }
194
195 /*
196  * ldap_dn_parent - return a copy of the dn of dn's parent
197  */
198
199 char *
200 ldap_dn_parent(
201     const char *dn
202 )
203 {
204         const char      *s;
205         int     inquote;
206
207         if( dn == NULL ) {
208                 return NULL;
209         }
210
211         while(*dn && LDAP_SPACE(*dn)) {
212                 dn++;
213         }
214
215         if( *dn == '\0' ) {
216                 return( NULL );
217         }
218
219         /*
220          * assume it is an X.500-style name, which looks like
221          * foo=bar,sha=baz,...
222          */
223
224         inquote = 0;
225         for ( s = dn; *s; s++ ) {
226                 if ( *s == '\\' ) {
227                         if ( *(s + 1) ) {
228                                 s++;
229                         }
230                         continue;
231                 }
232                 if ( inquote ) {
233                         if ( *s == '"' ) {
234                                 inquote = 0;
235                         }
236                 } else {
237                         if ( *s == '"' ) {
238                                 inquote = 1;
239                         } else if ( LDAP_DNSEPARATOR( *s ) ) {
240                                 return( LDAP_STRDUP( &s[1] ) );
241                         }
242                 }
243         }
244
245         return( LDAP_STRDUP( "" ) );
246 }
247
248 char * ldap_dn_rdn( 
249     const char  *dn )
250 {
251         char    *s;
252         char    *rdn;
253         int     inquote;
254
255         if( dn == NULL ) {
256                 return NULL;
257         }
258
259         while(*dn && LDAP_SPACE(*dn)) {
260                 dn++;
261         }
262
263         if( *dn == '\0' ) {
264                 return( NULL );
265         }
266
267         rdn = LDAP_STRDUP( dn );
268
269         if( rdn == NULL ) {
270                 return NULL;
271         }
272
273         /*
274          * assume it is an X.500-style name, which looks like
275          * foo=bar,sha=baz,...
276          */
277
278         inquote = 0;
279
280         for ( s = rdn; *s; s++ ) {
281                 if ( *s == '\\' ) {
282                         if ( *(s + 1) ) {
283                                 s++;
284                         }
285                         continue;
286                 }
287                 if ( inquote ) {
288                         if ( *s == '"' ) {
289                                 inquote = 0;
290                         }
291                 } else {
292                         if ( *s == '"' ) {
293                                 inquote = 1;
294                         } else if ( LDAP_DNSEPARATOR( *s ) ) {
295                                 *s = '\0';
296                                 return( rdn );
297                         }
298                 }
299         }
300
301         return( rdn );
302 }
303
304 #endif