]> git.sur5r.net Git - openldap/blob - libraries/libldap/getdn.c
Merge in all devel changes since 2.0-alpha2.
[openldap] / libraries / libldap / getdn.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-1999 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 static char **explode_name( const char *name, int notypes, int is_dn );
27
28 char *
29 ldap_get_dn( LDAP *ld, LDAPMessage *entry )
30 {
31         char            *dn;
32         BerElement      tmp;
33
34         Debug( LDAP_DEBUG_TRACE, "ldap_get_dn\n", 0, 0, 0 );
35
36         if ( entry == NULL ) {
37                 ld->ld_errno = LDAP_PARAM_ERROR;
38                 return( NULL );
39         }
40
41         tmp = *entry->lm_ber;   /* struct copy */
42         if ( ber_scanf( &tmp, "{a" /*}*/, &dn ) == LBER_ERROR ) {
43                 ld->ld_errno = LDAP_DECODING_ERROR;
44                 return( NULL );
45         }
46
47         return( dn );
48 }
49
50 char *
51 ldap_dn2ufn( LDAP_CONST char *dn )
52 {
53         char    *p, *ufn, *r;
54         int     state;
55
56         Debug( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n", 0, 0, 0 );
57
58         if( dn == NULL ) {
59                 return NULL;
60         }
61
62         if ( ldap_is_dns_dn( dn ) ||
63                 ( p = strchr( dn, '=' ) ) == NULL )
64         {
65                 return( LDAP_STRDUP( dn ) );
66         }
67
68
69         ufn = LDAP_STRDUP( ++p );
70
71 #define INQUOTE         1
72 #define OUTQUOTE        2
73         state = OUTQUOTE;
74         for ( p = ufn, r = ufn; *p; p++ ) {
75                 switch ( *p ) {
76                 case '\\':
77                         if ( *++p == '\0' )
78                                 p--;
79                         else {
80                                 *r++ = '\\';
81                                 *r++ = *p;
82                         }
83                         break;
84                 case '"':
85                         if ( state == INQUOTE )
86                                 state = OUTQUOTE;
87                         else
88                                 state = INQUOTE;
89                         *r++ = *p;
90                         break;
91                 case ';':
92                 case ',':
93                         if ( state == OUTQUOTE )
94                                 *r++ = ',';
95                         else
96                                 *r++ = *p;
97                         break;
98                 case '=':
99                         if ( state == INQUOTE )
100                                 *r++ = *p;
101                         else {
102                                 char    *rsave = r;
103
104                                 *r-- = '\0';
105                                 while ( !isspace( (unsigned char) *r )
106                                         && *r != ';' && *r != ',' && r > ufn )
107                                         r--;
108                                 r++;
109
110                                 if ( strcasecmp( r, "c" )
111                                     && strcasecmp( r, "o" )
112                                     && strcasecmp( r, "ou" )
113                                     && strcasecmp( r, "st" )
114                                     && strcasecmp( r, "l" )
115                                     && strcasecmp( r, "cn" ) ) {
116                                         r = rsave;
117                                         *r++ = '=';
118                                 }
119                         }
120                         break;
121                 default:
122                         *r++ = *p;
123                         break;
124                 }
125         }
126         *r = '\0';
127
128         return( ufn );
129 }
130
131 char **
132 ldap_explode_dns( LDAP_CONST char *dn_in )
133 {
134         char    *s;
135         char    **rdns;
136         char    *tok_r;
137         char    *dn;
138
139         int ncomps;
140         int maxcomps = 8;
141
142         if ( (dn = LDAP_STRDUP( dn_in )) == NULL ) {
143                 return( NULL );
144         }
145
146         if ( (rdns = (char **) LDAP_MALLOC( maxcomps * sizeof(char *) )) == NULL ) {
147                 LDAP_FREE( dn );
148                 return( NULL );
149         }
150
151         ncomps = 0;
152         for ( s = ldap_pvt_strtok( dn, "@.", &tok_r ); s != NULL; 
153               s = ldap_pvt_strtok( NULL, "@.", &tok_r ) )
154         {
155                 if ( ncomps == maxcomps ) {
156                         maxcomps *= 2;
157                         if ( (rdns = (char **) LDAP_REALLOC( rdns, maxcomps *
158                             sizeof(char *) )) == NULL )
159                         {
160                                 LDAP_FREE( dn );
161                                 return NULL;
162                         }
163                 }
164                 rdns[ncomps++] = LDAP_STRDUP( s );
165         }
166         LDAP_FREE(dn);
167
168         rdns[ncomps] = NULL;
169
170         /* trim rdns */
171         rdns = (char **) LDAP_REALLOC( rdns, (ncomps+1) * sizeof(char*) );
172         return( rdns );
173 }
174
175 char **
176 ldap_explode_dn( LDAP_CONST char *dn, int notypes )
177 {
178         Debug( LDAP_DEBUG_TRACE, "ldap_explode_dn\n", 0, 0, 0 );
179
180         if ( ldap_is_dns_dn( dn ) ) {
181                 return( ldap_explode_dns( dn ) );
182         }
183         return explode_name( dn, notypes, 1 );
184 }
185
186 char **
187 ldap_explode_rdn( LDAP_CONST char *rdn, int notypes )
188 {
189         Debug( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n", 0, 0, 0 );
190         return explode_name( rdn, notypes, 0 );
191 }
192
193 static char **
194 explode_name( const char *name, int notypes, int is_dn )
195 {
196         const char *p, *q;
197         char **parts = NULL;
198         int     state, count = 0, endquote, len;
199
200         p = name-1;
201         state = OUTQUOTE;
202
203         do {
204
205                 ++p;
206                 switch ( *p ) {
207                 case '\\':
208                         if ( *++p == '\0' )
209                                 p--;
210                         break;
211                 case '"':
212                         if ( state == INQUOTE )
213                                 state = OUTQUOTE;
214                         else
215                                 state = INQUOTE;
216                         break;
217                 case '+':
218                         if (!is_dn)
219                                 goto end_part;
220                         break;
221                 case ';':
222                 case ',':
223                         if (!is_dn)
224                                 break;
225                         goto end_part;
226                 case '\0':
227                 end_part:
228                         if ( state == OUTQUOTE ) {
229                                 ++count;
230                                 if ( parts == NULL ) {
231                                         if (( parts = (char **)LDAP_MALLOC( 8
232                                                  * sizeof( char *))) == NULL )
233                                                 return( NULL );
234                                 } else if ( count >= 8 ) {
235                                         if (( parts = (char **)LDAP_REALLOC( parts,
236                                                 (count+1) * sizeof( char *)))
237                                                 == NULL )
238                                                 return( NULL );
239                                 }
240                                 parts[ count ] = NULL;
241                                 endquote = 0;
242                                 if ( notypes ) {
243                                         for ( q = name;
244                                             q < p && *q != '='; ++q ) {
245                                                 ;
246                                         }
247                                         if ( q < p ) {
248                                                 name = ++q;
249                                         }
250                                         if ( *name == '"' ) {
251                                                 ++name;
252                                         }
253                                         
254                                         if ( *(p-1) == '"' ) {
255                                                 endquote = 1;
256                                                 --p;
257                                         }
258                                 }
259
260                                 len = p - name;
261                                 if (( parts[ count-1 ] = (char *)LDAP_CALLOC( 1,
262                                     len + 1 )) != NULL ) {
263                                         SAFEMEMCPY( parts[ count-1 ], name,
264                                             len );
265                                         parts[ count-1 ][ len ] = '\0';
266                                 }
267
268                                 /*
269                                  *  Don't forget to increment 'p' back to where
270                                  *  it should be.  If we don't, then we will
271                                  *  never get past an "end quote."
272                                  */
273                                 if ( endquote == 1 )
274                                         p++;
275
276                                 name = *p ? p + 1 : p;
277                                 while ( isascii( *name ) && isspace( *name ) )
278                                         ++name;
279                         }
280                         break;
281                 }
282         } while ( *p );
283
284         return( parts );
285 }
286
287
288 int
289 ldap_is_dns_dn( LDAP_CONST char *dn )
290 {
291         return( dn[ 0 ] != '\0'
292                 && strchr( dn, '=' ) == NULL
293                 && strchr( dn, ',' ) == NULL
294                 && strchr( dn, ';' ) == NULL );
295 }
296