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