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