]> git.sur5r.net Git - openldap/blob - servers/slapd/tools/ldapsyntax.c
Import minor trace output cleanup
[openldap] / servers / slapd / tools / ldapsyntax.c
1 /*
2  * Copyright (c) 1995 Regents of the University of Michigan.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that this notice is preserved and that due credit is given
7  * to the University of Michigan at Ann Arbor. The name of the University
8  * may not be used to endorse or promote products derived from this
9  * software without specific prior written permission. This software
10  * is provided ``as is'' without express or implied warranty.
11  */
12
13 #include "portable.h"
14
15 #include <stdio.h>
16
17 #include <ac/ctype.h>
18 #include <ac/string.h>
19
20 #include <quipu/commonarg.h>
21 #include <quipu/attrvalue.h>
22 #include <quipu/ds_error.h>
23 #include <quipu/ds_search.h>
24 /* #include <quipu/dap2.h> */
25 #include <quipu/dua.h>
26 #include <sys/types.h>
27
28 #include "lber.h"
29 #include "ldap.h"
30 #include "ldif.h"
31 #include "ldapsyntax.h"
32
33 short   ldap_dn_syntax;
34 short   ldap_password_syntax;
35 short   ldap_photo_syntax;
36 short   ldap_jpeg_syntax;
37 short   ldap_audio_syntax;
38
39 static int      dn2ldif( PS ps, DN dn );
40 static int      jpeg2ldif( PS ps, AttributeValue av );
41 static int      audio2ldif( PS ps, AttributeValue av );
42 static int      photo2ldif( PS ps, AttributeValue av );
43 static int      fileattr2ldif( PS ps, AttributeValue av );
44 static void     de_t61( char *s, int t61mark );
45 static void     de_crypt( char *s );
46
47 extern char     *progname;
48
49 #define SEPARATOR(c)    (c == ',' || c == ';')
50 #define SPACE(c)        (c == ' ' || c == '\n')
51
52
53 int
54 init_syntaxes()
55 {
56     if (( ldap_dn_syntax = str2syntax( "DN" )) == 0 ) {
57         return( -1 );   /* must have this syntax handler */
58     }
59     ldap_password_syntax = str2syntax( "password" );
60     ldap_photo_syntax = str2syntax( "photo" );
61     ldap_jpeg_syntax = str2syntax( "jpeg" );
62     ldap_audio_syntax = str2syntax( "audio" );
63
64     return( 0 );
65 }
66
67
68 /*
69  * av2ldif:  convert attribute value contained in "av" to ldif format
70  * and write to "outfp".  If "dn" is not NULL, convert it instead of "av".
71  */
72 int
73 av2ldif( FILE *outfp, AV_Sequence av, DN dn, short syntax, char *attrname,
74     PS str_ps )
75 {
76     char                *buf;
77     int                 rc;
78     struct file_syntax  *fsyntax;
79
80     if ( av != NULLAV ) {
81         fsyntax = (struct file_syntax *) av->avseq_av.av_struct;
82     }
83
84     rc = 0;     /* optimistic */
85     str_ps->ps_ptr = str_ps->ps_base;   /* reset string PS */
86
87     if ( dn != NULL || syntax == ldap_dn_syntax ) {     /* DNs */
88         rc = dn2ldif( str_ps, ( dn != NULLDN ) ? dn :
89                 (DN)(av->avseq_av.av_struct));
90
91     } else if ( syntax == ldap_jpeg_syntax || ( syntax > AV_WRITE_FILE &&
92             fsyntax->fs_real_syntax == ldap_jpeg_syntax )) {
93         rc = jpeg2ldif( str_ps, &av->avseq_av );
94
95     } else if ( syntax == ldap_photo_syntax || ( syntax > AV_WRITE_FILE &&
96             fsyntax->fs_real_syntax == ldap_photo_syntax )) {
97         rc = photo2ldif( str_ps, &av->avseq_av );
98
99     } else if ( syntax == ldap_audio_syntax || ( syntax > AV_WRITE_FILE &&
100             fsyntax->fs_real_syntax == ldap_audio_syntax )) {
101         rc = audio2ldif( str_ps, &av->avseq_av );
102
103     } else if ( syntax > AV_WRITE_FILE ) {
104         rc = fileattr2ldif( str_ps, &av->avseq_av );
105
106     } else {
107         AttrV_print( str_ps, &av->avseq_av, EDBOUT );
108         *str_ps->ps_ptr = '\0';
109         de_t61( str_ps->ps_base, 0 );
110
111         if ( syntax == ldap_password_syntax ) {
112             de_crypt( str_ps->ps_base );
113         }
114
115         str_ps->ps_ptr = str_ps->ps_base + strlen( str_ps->ps_base );
116     }
117
118     if ( rc == 0 && str_ps->ps_ptr > str_ps->ps_base ) {
119         *str_ps->ps_ptr = '\0';
120         if (( buf = ldif_type_and_value( attrname, str_ps->ps_base,
121                 str_ps->ps_ptr - str_ps->ps_base )) == NULL ) {
122             rc = -1;
123         } else {
124             if ( fputs( buf, outfp ) == EOF ) {
125                 rc = -1;
126             }
127             free( buf );
128         }
129     }
130
131     if ( rc == -2 ) {
132         if ( syntax > AV_WRITE_FILE ) {
133             fprintf( stderr,
134                     "%s: attribute file '%s' not found (skipping value)\n",
135                      progname, fsyntax->fs_name );
136         }
137         rc = 0; /* treat as "soft" error -- keep going */
138     }
139
140     return( rc );
141 }
142
143
144 static int
145 dn2ldif( PS ps, DN dn )
146 {
147     RDN rdn;
148     int firstrdn, rc;
149     char        *value;
150     PS  rps;
151
152     if ( dn == NULLDN ) {
153         return( 0 );
154     }
155
156     if ( dn->dn_parent != NULLDN ) {
157         if (( rc = dn2ldif( ps, dn->dn_parent )) != 0 ) {
158             return( rc );
159         }
160         ps_print( ps, ", " );
161     }
162
163     if ( (rps = ps_alloc( str_open )) == NULLPS ||
164             str_setup( rps, NULLCP, 0, 0 ) == NOTOK ) {
165         return( -1 );
166     }
167
168     firstrdn = 1;
169     for ( rdn = dn->dn_rdn; rdn != NULLRDN; rdn = rdn->rdn_next ) {
170         if ( firstrdn ) {
171             firstrdn = 0;
172         } else {
173             ps_print( ps, " + " );
174         }
175
176         AttrT_print( ps, rdn->rdn_at, EDBOUT );
177         ps_print( ps, "=" );
178
179         if ( rdn->rdn_at->oa_syntax == ldap_dn_syntax ) {
180             if (( rc = dn2ldif( rps, (DN) rdn->rdn_av.av_struct )) != 0 ) {
181                 return( rc );
182             }
183             *rps->ps_ptr = '\0';
184             value = rps->ps_base;
185         } else {
186             AttrV_print( rps, &rdn->rdn_av, EDBOUT );
187             *rps->ps_ptr = '\0';
188             value = rps->ps_base;
189             de_t61( value, 0 );
190         }
191
192         /*
193          * ,+="\\\n all go in quotes.  " and \\ need to
194          * be preceeded by \\.
195          */
196
197         if ( strpbrk( value, ",+=\"\\\n" ) != NULL || SPACE( value[0] )
198                 || SPACE( value[max( strlen(value) - 1, 0 )] ) ) {
199             char        *p, *t, *tmp;
200             int specialcount;
201
202             ps_print( ps, "\"" );
203
204             specialcount = 0;
205             for ( p = value; *p != '\0'; p++ ) {
206                 if ( *p == '"' || *p == '\\' ) {
207                     specialcount++;
208                 }
209             }
210             if ( specialcount > 0 ) {
211                 tmp = smalloc( strlen( value ) + specialcount + 1 );
212                 for ( p = value, t = tmp; *p != '\0'; p++ ) {
213                     switch ( *p ) {
214                     case '"':
215                     case '\\':
216                             *t++ = '\\';
217                             /* FALL THROUGH */
218                     default:
219                             *t++ = *p;
220                     }
221                 }
222                 *t = '\0';
223                 ps_print( ps, tmp );
224                 free( tmp );
225             } else {
226                 ps_print( ps, value );
227             }
228
229             ps_print( ps, "\"" );
230         } else {
231             ps_print( ps, value );
232         }
233
234         rps->ps_ptr = rps->ps_base;
235     }
236
237     ps_free( rps );
238
239     return( 0 );
240 }
241
242 #define T61     "{T.61}"
243 #define T61LEN  6
244
245 static void
246 de_t61( s, t61mark )
247 char    *s;
248 int     t61mark;
249 {
250         char    *next = s;
251         int     c, hex;
252
253         while ( *s ) {
254                 switch ( *s ) {
255                 case '{' :
256                         if ( strncasecmp( s, T61, T61LEN) == 0 ) {
257                                 s += T61LEN;
258                                 if ( t61mark )
259                                         *next++ = '@';
260                         } else {
261                                 *next++ = *s++;
262                         }
263                         break;
264
265                 case '\\':
266                         c = *(s + 1);
267                         if ( c == '\n' ) {
268                                 s += 2;
269                                 if ( *s == '\t' )
270                                         s++;
271                                 break;
272                         }
273                         if ( isdigit( c ) )
274                                 hex = c - '0';
275                         else if ( c >= 'A' && c <= 'F' )
276                                 hex = c - 'A' + 10;
277                         else if ( c >= 'a' && c <= 'f' )
278                                 hex = c - 'a' + 10;
279                         else {
280                                 *next++ = *s++;
281                                 break;
282                         }
283                         hex <<= 4;
284                         c = *(s + 2);
285                         if ( isdigit( c ) )
286                                 hex += c - '0';
287                         else if ( c >= 'A' && c <= 'F' )
288                                 hex += c - 'A' + 10;
289                         else if ( c >= 'a' && c <= 'f' )
290                                 hex += c - 'a' + 10;
291                         else {
292                                 *next++ = *s++;
293                                 *next++ = *s++;
294                                 break;
295                         }
296
297                         *next++ = hex;
298                         s += 3;
299                         break;
300
301                 default:
302                         *next++ = *s++;
303                         break;
304                 }
305         }
306         *next = '\0';
307 }
308
309
310 #define CRYPT_MASK 0x23
311
312 static void
313 de_crypt( char *s )
314 {
315     char *p;
316
317     if ( strncmp( s, "{CRYPT}", 7 ) == 0 ) {
318         SAFEMEMCPY( s, s + 7, strlen( s + 7 ) + 1 ); /* strip off "{CRYPT}" */
319
320         for ( p = s; *p != '\0'; ++p) {         /* "decrypt" each byte */
321             if ( *p != CRYPT_MASK ) {
322                 *p ^= CRYPT_MASK;
323             }
324         }
325     }
326 }
327
328
329 static int
330 jpeg2ldif( PS ps, AttributeValue av )
331 {
332     PE  pe;
333     int len;
334
335     if (( pe = grab_pe( av )) == NULLPE || pe->pe_id == PE_PRIM_NULL ) {
336         return( -2 );   /* signal soft error */
337     }
338
339     if (( pe->pe_class != PE_CLASS_UNIV && pe->pe_class != PE_CLASS_CONT )
340             || pe->pe_form != PE_FORM_PRIM || pe->pe_id != PE_PRIM_OCTS ) {
341         return( -1 );
342     }
343
344     if ( pe_pullup( pe ) == NOTOK ) {
345         return( -1 );
346     }
347
348     len = ps_get_abs( pe );
349
350     if ( ps_write( ps, (PElementData)pe->pe_prim, len ) == NOTOK ) {
351         return( -1 );
352     }
353
354     return( 0 );
355 }
356
357
358 static int
359 audio2ldif( PS ps, AttributeValue av )
360 {
361     PE          pe;
362     struct qbuf *qb, *p;
363     int         rc, len;
364     char        *buf;
365
366     return( 0 );        /* for now */
367
368     if (( pe = grab_pe( av )) == NULLPE || pe->pe_id == PE_PRIM_NULL ) {
369         return( -2 );   /* signal soft error */
370     }
371
372     qb = (struct qbuf *)pe;
373
374     len = 0;
375     for ( p = qb->qb_forw; p != qb; p = p->qb_forw ) {
376         len += p->qb_len;
377     }
378
379     if (( buf = (char *) malloc( len )) == NULL ) {
380         return( -1 );
381     }
382
383     len = 0;
384     for ( p = qb->qb_forw; p != qb; p = p->qb_forw ) {
385         SAFEMEMCPY( buf + len, p->qb_data, p->qb_len );
386         len += p->qb_len;
387     }
388
389     if ( ps_write( ps, (PElementData)buf, len ) == NOTOK ) {
390         rc = -1;
391     } else {
392         rc = 0;
393     }
394
395     free( buf );
396
397     return( rc );
398 }
399
400
401 static int
402 photo2ldif( PS ps, AttributeValue av )
403 {
404     PE          pe;
405     int         len;
406     char        *faxparamset = "\000\300\000\000";
407     BerElement  *phber;
408
409     if (( pe = grab_pe( av )) == NULLPE || pe->pe_id == PE_PRIM_NULL ) {
410         return( -2 );   /* signal soft error */
411     }
412
413     /* old bit string-like format - only handle this for now */
414     if ( pe->pe_class == PE_CLASS_UNIV && pe->pe_form == PE_FORM_PRIM
415             && pe->pe_id == PE_PRIM_BITS ) {
416         len = ps_get_abs( pe );
417         if (( phber = der_alloc()) == NULLBER ) {
418             return( -1 );
419         }
420         if ( ber_printf( phber, "t{[tB]{B}}", 0xA3, 0x81, faxparamset,
421                 31, (char *)pe->pe_prim, len * 8 ) == -1 ) {
422             ber_free( phber, 1 );
423             return( -1 );
424         }
425         if ( ps_write( ps, (PElementData)phber->ber_buf,
426                 phber->ber_ptr - phber->ber_buf ) == NOTOK ) {
427             ber_free( phber, 1 );
428             return( -1 );
429         }
430         ber_free( phber, 1 );
431     } else {
432         /*
433          * try just writing this into a PS and sending it along
434          */
435         if ( pe2ps( ps, pe ) == NOTOK ) {
436             return( -1 );
437         }
438     }
439
440     return( 0 );
441 }
442
443
444 static int
445 fileattr2ldif( PS ps, AttributeValue av )
446 {
447     PE          pe;
448
449     if (( pe = grab_pe( av )) == NULLPE || pe->pe_id == PE_PRIM_NULL ) {
450         return( -2 );   /* signal soft error */
451     }
452
453     /*
454      * try just writing this into a PS and sending it along
455      */
456     if ( pe2ps( ps, pe ) == NOTOK ) {
457         return( -1 );
458     }
459
460     return( 0 );
461 }