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