]> git.sur5r.net Git - openldap/blob - libraries/libldap/getdn.c
Add strdup.c from -llutil, renamed to ldap_strdup() and always used.
[openldap] / libraries / libldap / getdn.c
1 /*
2  *  Copyright (c) 1994 Regents of the University of Michigan.
3  *  All rights reserved.
4  *
5  *  getdn.c
6  */
7
8 #include "portable.h"
9
10 #ifndef lint 
11 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
12 #endif
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( 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( 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( *r ) && *r != ';'
96                                     && *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( char *dn )
123 {
124         int     ncomps, maxcomps;
125         char    *s;
126         char    **rdns;
127
128         if ( (rdns = (char **) malloc( 8 * sizeof(char *) )) == NULL ) {
129                 return( NULL );
130         }
131
132         maxcomps = 8;
133         ncomps = 0;
134         for ( s = strtok( dn, "@." ); s != NULL; s = strtok( NULL, "@." ) ) {
135                 if ( ncomps == maxcomps ) {
136                         maxcomps *= 2;
137                         if ( (rdns = (char **) realloc( rdns, maxcomps *
138                             sizeof(char *) )) == NULL ) {
139                                 return( NULL );
140                         }
141                 }
142                 rdns[ncomps++] = ldap_strdup( s );
143         }
144         rdns[ncomps] = NULL;
145
146         return( rdns );
147 }
148
149 char **
150 ldap_explode_dn( char *dn, int notypes )
151 {
152         Debug( LDAP_DEBUG_TRACE, "ldap_explode_dn\n", 0, 0, 0 );
153
154         if ( ldap_is_dns_dn( dn ) ) {
155                 return( ldap_explode_dns( dn ) );
156         }
157         return explode_name( dn, notypes, 1 );
158 }
159
160 char **
161 ldap_explode_rdn( char *rdn, int notypes )
162 {
163         Debug( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n", 0, 0, 0 );
164         return explode_name( rdn, notypes, 0 );
165 }
166
167 static char **
168 explode_name( char *name, int notypes, int is_dn )
169 {
170         char    *p, *q, **parts = NULL;
171         int     state, count = 0, endquote, len;
172
173         p = name-1;
174         state = OUTQUOTE;
175
176         do {
177
178                 ++p;
179                 switch ( *p ) {
180                 case '\\':
181                         if ( *++p == '\0' )
182                                 p--;
183                         break;
184                 case '"':
185                         if ( state == INQUOTE )
186                                 state = OUTQUOTE;
187                         else
188                                 state = INQUOTE;
189                         break;
190                 case '+':
191                         if (!is_dn)
192                                 goto end_part;
193                         break;
194                 case ';':
195                 case ',':
196                         if (!is_dn)
197                                 break;
198                         goto end_part;
199                 case '\0':
200                 end_part:
201                         if ( state == OUTQUOTE ) {
202                                 ++count;
203                                 if ( parts == NULL ) {
204                                         if (( parts = (char **)malloc( 8
205                                                  * sizeof( char *))) == NULL )
206                                                 return( NULL );
207                                 } else if ( count >= 8 ) {
208                                         if (( parts = (char **)realloc( parts,
209                                                 (count+1) * sizeof( char *)))
210                                                 == NULL )
211                                                 return( NULL );
212                                 }
213                                 parts[ count ] = NULL;
214                                 endquote = 0;
215                                 if ( notypes ) {
216                                         for ( q = name;
217                                             q < p && *q != '='; ++q ) {
218                                                 ;
219                                         }
220                                         if ( q < p ) {
221                                                 name = ++q;
222                                         }
223                                         if ( *name == '"' ) {
224                                                 ++name;
225                                         }
226                                         
227                                         if ( *(p-1) == '"' ) {
228                                                 endquote = 1;
229                                                 --p;
230                                         }
231                                 }
232
233                                 len = p - name;
234                                 if (( parts[ count-1 ] = (char *)calloc( 1,
235                                     len + 1 )) != NULL ) {
236                                         SAFEMEMCPY( parts[ count-1 ], name,
237                                             len );
238                                         parts[ count-1 ][ len ] = '\0';
239                                 }
240
241                                 /*
242                                  *  Don't forget to increment 'p' back to where
243                                  *  it should be.  If we don't, then we will
244                                  *  never get past an "end quote."
245                                  */
246                                 if ( endquote == 1 )
247                                         p++;
248
249                                 name = *p ? p + 1 : p;
250                                 while ( isascii( *name ) && isspace( *name ) )
251                                         ++name;
252                         }
253                         break;
254                 }
255         } while ( *p );
256
257         return( parts );
258 }
259
260
261 int
262 ldap_is_dns_dn( char *dn )
263 {
264         return( dn[ 0 ] != '\0' && strchr( dn, '=' ) == NULL &&
265             strchr( dn, ',' ) == NULL );
266 }
267