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