]> git.sur5r.net Git - openldap/blob - libraries/libldap/getdn.c
Sync with 2.x
[openldap] / libraries / libldap / getdn.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /*  Portions
7  *  Copyright (c) 1994 Regents of the University of Michigan.
8  *  All rights reserved.
9  *
10  *  getdn.c
11  */
12
13 #include "portable.h"
14
15 #include <stdio.h>
16
17 #include <ac/stdlib.h>
18
19 #include <ac/ctype.h>
20 #include <ac/socket.h>
21 #include <ac/string.h>
22 #include <ac/time.h>
23
24 #include "ldap-int.h"
25
26 #define NAME_TYPE_LDAP_RDN      0
27 #define NAME_TYPE_LDAP_DN       1
28 #define NAME_TYPE_DCE_DN        2
29
30 static char **explode_name( const char *name, int notypes, int is_type );
31
32 char *
33 ldap_get_dn( LDAP *ld, LDAPMessage *entry )
34 {
35         char            *dn;
36         BerElement      tmp;
37
38         Debug( LDAP_DEBUG_TRACE, "ldap_get_dn\n", 0, 0, 0 );
39
40         if ( entry == NULL ) {
41                 ld->ld_errno = LDAP_PARAM_ERROR;
42                 return( NULL );
43         }
44
45         tmp = *entry->lm_ber;   /* struct copy */
46         if ( ber_scanf( &tmp, "{a" /*}*/, &dn ) == LBER_ERROR ) {
47                 ld->ld_errno = LDAP_DECODING_ERROR;
48                 return( NULL );
49         }
50
51         return( dn );
52 }
53
54 char *
55 ldap_dn2ufn( LDAP_CONST char *dn )
56 {
57         char    *ufn;
58         char    **vals;
59
60         Debug( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n", 0, 0, 0 );
61
62         /* produces completely untyped UFNs */
63
64         if( dn == NULL ) {
65                 return NULL;
66         }
67
68         vals = ldap_explode_dn( dn , 1 );
69         if( vals == NULL ) {
70                 return NULL;
71         }
72
73         ufn = ldap_charray2str( vals, ", " );
74
75         LDAP_VFREE( vals );
76         return ufn;
77 }
78
79 char **
80 ldap_explode_dn( LDAP_CONST char *dn, int notypes )
81 {
82         Debug( LDAP_DEBUG_TRACE, "ldap_explode_dn\n", 0, 0, 0 );
83
84         return explode_name( dn, notypes, NAME_TYPE_LDAP_DN );
85 }
86
87 char **
88 ldap_explode_rdn( LDAP_CONST char *rdn, int notypes )
89 {
90         Debug( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n", 0, 0, 0 );
91         return explode_name( rdn, notypes, NAME_TYPE_LDAP_RDN );
92 }
93
94 char *
95 ldap_dn2dcedn( LDAP_CONST char *dn )
96 {
97         char *dce, *q, **rdns, **p;
98         int len = 0;
99
100         Debug( LDAP_DEBUG_TRACE, "ldap_dn2dcedn\n", 0, 0, 0 );
101
102         rdns = explode_name( dn, 0, NAME_TYPE_LDAP_DN );
103         if ( rdns == NULL ) {
104                 return NULL;
105         }
106         
107         for ( p = rdns; *p != NULL; p++ ) {
108                 len += strlen( *p ) + 1;
109         }
110
111         q = dce = LDAP_MALLOC( len + 1 );
112         if ( dce == NULL ) {
113                 return NULL;
114         }
115
116         p--; /* get back past NULL */
117
118         for ( ; p != rdns; p-- ) {
119                 strcpy( q, "/" );
120                 q++;
121                 strcpy( q, *p );
122                 q += strlen( *p );
123         }
124
125         strcpy( q, "/" );
126         q++;
127         strcpy( q, *p );
128         
129         return dce;
130 }
131
132 char *
133 ldap_dcedn2dn( LDAP_CONST char *dce )
134 {
135         char *dn, *q, **rdns, **p;
136         int len;
137
138         Debug( LDAP_DEBUG_TRACE, "ldap_dcedn2dn\n", 0, 0, 0 );
139
140         rdns = explode_name( dce, 0, NAME_TYPE_DCE_DN );
141         if ( rdns == NULL ) {
142                 return NULL;
143         }
144
145         len = 0;
146
147         for ( p = rdns; *p != NULL; p++ ) {
148                 len += strlen( *p ) + 1;
149         }
150
151         q = dn = LDAP_MALLOC( len );
152         if ( dn == NULL ) {
153                 return NULL;
154         }
155
156         p--;
157
158         for ( ; p != rdns; p-- ) {
159                 strcpy( q, *p );
160                 q += strlen( *p );
161                 strcpy( q, "," );
162                 q++;
163         }
164
165         if ( *dce == '/' ) {
166                 /* the name was fully qualified, thus the most-significant
167                  * RDN was empty. trash the last comma */
168                 q--;
169                 *q = '\0';
170         } else {
171                 /* the name was relative. copy the most significant RDN */
172                 strcpy( q, *p );
173         }
174
175         return dn;
176 }
177
178 #define INQUOTE         1
179 #define OUTQUOTE        2
180
181 static char **
182 explode_name( const char *name, int notypes, int is_type )
183 {
184         const char *p, *q, *rdn;
185         char **parts = NULL;
186         int     offset, state, have_equals, count = 0, endquote, len;
187
188         /* safe guard */
189         if(name == NULL) name = "";
190
191         /* skip leading whitespace */
192         while( ldap_utf8_isspace( name )) {
193                 LDAP_UTF8_INCR( name );
194         }
195
196         p = rdn = name;
197         offset = 0;
198         state = OUTQUOTE;
199         have_equals=0;
200
201         do {
202                 /* step forward */
203                 p += offset;
204                 offset = 1;
205
206                 switch ( *p ) {
207                 case '\\':
208                         if ( p[1] != '\0' ) {
209                                 offset = LDAP_UTF8_OFFSET(++p);
210                         }
211                         break;
212                 case '"':
213                         if ( state == INQUOTE )
214                                 state = OUTQUOTE;
215                         else
216                                 state = INQUOTE;
217                         break;
218                 case '=':
219                         if( state == OUTQUOTE ) have_equals++;
220                         break;
221                 case '+':
222                         if (is_type == NAME_TYPE_LDAP_RDN)
223                                 goto end_part;
224                         break;
225                 case '/':
226                         if (is_type == NAME_TYPE_DCE_DN)
227                                 goto end_part;
228                         break;
229                 case ';':
230                 case ',':
231                         if (is_type == NAME_TYPE_LDAP_DN)
232                                 goto end_part;
233                         break;
234                 case '\0':
235                 end_part:
236                         if ( state == OUTQUOTE ) {
237                                 ++count;
238                                 have_equals=0;
239
240                                 if ( parts == NULL ) {
241                                         if (( parts = (char **)LDAP_MALLOC( 8
242                                                  * sizeof( char *))) == NULL )
243                                                 return( NULL );
244                                 } else if ( count >= 8 ) {
245                                         if (( parts = (char **)LDAP_REALLOC( parts,
246                                                 (count+1) * sizeof( char *)))
247                                                 == NULL )
248                                                 return( NULL );
249                                 }
250
251                                 parts[ count ] = NULL;
252                                 endquote = 0;
253
254                                 if ( notypes ) {
255                                         for ( q = rdn; q < p && *q != '='; ++q ) {
256                                                 /* EMPTY */;
257                                         }
258
259                                         if ( q < p ) {
260                                                 rdn = ++q;
261                                         }
262
263                                         if ( *rdn == '"' ) {
264                                                 ++rdn;
265                                         }
266                                         
267                                         if ( p[-1] == '"' ) {
268                                                 endquote = 1;
269                                                 --p;
270                                         }
271                                 }
272
273                                 len = p - rdn;
274
275                                 if (( parts[ count-1 ] = (char *)LDAP_CALLOC( 1,
276                                     len + 1 )) != NULL )
277                                 {
278                                         AC_MEMCPY( parts[ count-1 ], rdn, len );
279
280                                         if( !endquote ) {
281                                                 /* skip trailing spaces */
282                                                 while( len > 0 && ldap_utf8_isspace(
283                                                         &parts[count-1][len-1] ) )
284                                                 {
285                                                         --len;
286                                                 }
287                                         }
288
289                                         parts[ count-1 ][ len ] = '\0';
290                                 }
291
292                                 /*
293                                  *  Don't forget to increment 'p' back to where
294                                  *  it should be.  If we don't, then we will
295                                  *  never get past an "end quote."
296                                  */
297                                 if ( endquote == 1 )
298                                         p++;
299
300                                 rdn = *p ? &p[1] : p;
301                                 while ( ldap_utf8_isspace( rdn ) )
302                                         ++rdn;
303                         } break;
304                 }
305         } while ( *p );
306
307         return( parts );
308 }