]> git.sur5r.net Git - openldap/blob - servers/slapd/tools/ldapsyntax.c
Very crude LDIF changes:
[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
27 #include "lber.h"
28 #include "ldap.h"
29 #include "ldif.h"
30 #include "ldapsyntax.h"
31
32 short   ldap_dn_syntax;
33 short   ldap_password_syntax;
34 short   ldap_photo_syntax;
35 short   ldap_jpeg_syntax;
36 short   ldap_audio_syntax;
37
38 static int      dn2ldif( PS ps, DN dn );
39 static int      jpeg2ldif( PS ps, AttributeValue av );
40 static int      audio2ldif( PS ps, AttributeValue av );
41 static int      photo2ldif( PS ps, AttributeValue av );
42 static int      fileattr2ldif( PS ps, AttributeValue av );
43 static void     de_t61( char *s, int t61mark );
44 static void     de_crypt( char *s );
45
46 extern char     *progname;
47
48 #define SEPARATOR(c)    ((c) == ',' || (c) == ';')
49 #define SPACE(c)        ((c) == ' ' || (c) == '\n')
50
51
52 int
53 init_syntaxes()
54 {
55     if (( ldap_dn_syntax = str2syntax( "DN" )) == 0 ) {
56         return( -1 );   /* must have this syntax handler */
57     }
58     ldap_password_syntax = str2syntax( "password" );
59     ldap_photo_syntax = str2syntax( "photo" );
60     ldap_jpeg_syntax = str2syntax( "jpeg" );
61     ldap_audio_syntax = str2syntax( "audio" );
62
63     return( 0 );
64 }
65
66
67 /*
68  * av2ldif:  convert attribute value contained in "av" to ldif format
69  * and write to "outfp".  If "dn" is not NULL, convert it instead of "av".
70  */
71 int
72 av2ldif( FILE *outfp, AV_Sequence av, DN dn, short syntax, char *attrname,
73     PS str_ps )
74 {
75     char                *buf;
76     int                 rc;
77     struct file_syntax  *fsyntax;
78
79     if ( av != NULLAV ) {
80         fsyntax = (struct file_syntax *) av->avseq_av.av_struct;
81     }
82
83     rc = 0;     /* optimistic */
84     str_ps->ps_ptr = str_ps->ps_base;   /* reset string PS */
85
86     if ( dn != NULL || syntax == ldap_dn_syntax ) {     /* DNs */
87         rc = dn2ldif( str_ps, ( dn != NULLDN ) ? dn :
88                 (DN)(av->avseq_av.av_struct));
89
90     } else if ( syntax == ldap_jpeg_syntax || ( syntax > AV_WRITE_FILE &&
91             fsyntax->fs_real_syntax == ldap_jpeg_syntax )) {
92         rc = jpeg2ldif( str_ps, &av->avseq_av );
93
94     } else if ( syntax == ldap_photo_syntax || ( syntax > AV_WRITE_FILE &&
95             fsyntax->fs_real_syntax == ldap_photo_syntax )) {
96         rc = photo2ldif( str_ps, &av->avseq_av );
97
98     } else if ( syntax == ldap_audio_syntax || ( syntax > AV_WRITE_FILE &&
99             fsyntax->fs_real_syntax == ldap_audio_syntax )) {
100         rc = audio2ldif( str_ps, &av->avseq_av );
101
102     } else if ( syntax > AV_WRITE_FILE ) {
103         rc = fileattr2ldif( str_ps, &av->avseq_av );
104
105     } else {
106         AttrV_print( str_ps, &av->avseq_av, EDBOUT );
107         *str_ps->ps_ptr = '\0';
108         de_t61( str_ps->ps_base, 0 );
109
110         if ( syntax == ldap_password_syntax ) {
111             de_crypt( str_ps->ps_base );
112         }
113
114         str_ps->ps_ptr = str_ps->ps_base + strlen( str_ps->ps_base );
115     }
116
117     if ( rc == 0 && str_ps->ps_ptr > str_ps->ps_base ) {
118         *str_ps->ps_ptr = '\0';
119         if (( buf = ldif_type_and_value( attrname, str_ps->ps_base,
120                 str_ps->ps_ptr - str_ps->ps_base )) == NULL ) {
121             rc = -1;
122         } else {
123             if ( fputs( buf, outfp ) == EOF ) {
124                 rc = -1;
125             }
126             ber_memfree( buf );
127         }
128     }
129
130     if ( rc == -2 ) {
131         if ( syntax > AV_WRITE_FILE ) {
132             fprintf( stderr,
133                     "%s: attribute file '%s' not found (skipping value)\n",
134                      progname, fsyntax->fs_name );
135         }
136         rc = 0; /* treat as "soft" error -- keep going */
137     }
138
139     return( rc );
140 }
141
142
143 static int
144 dn2ldif( PS ps, DN dn )
145 {
146     RDN rdn;
147     int firstrdn, rc;
148     char        *value;
149     PS  rps;
150
151     if ( dn == NULLDN ) {
152         return( 0 );
153     }
154
155     if ( dn->dn_parent != NULLDN ) {
156         if (( rc = dn2ldif( ps, dn->dn_parent )) != 0 ) {
157             return( rc );
158         }
159         ps_print( ps, ", " );
160     }
161
162     if ( (rps = ps_alloc( str_open )) == NULLPS ||
163             str_setup( rps, NULLCP, 0, 0 ) == NOTOK ) {
164         return( -1 );
165     }
166
167     firstrdn = 1;
168     for ( rdn = dn->dn_rdn; rdn != NULLRDN; rdn = rdn->rdn_next ) {
169         if ( firstrdn ) {
170             firstrdn = 0;
171         } else {
172             ps_print( ps, " + " );
173         }
174
175         AttrT_print( ps, rdn->rdn_at, EDBOUT );
176         ps_print( ps, "=" );
177
178         if ( rdn->rdn_at->oa_syntax == ldap_dn_syntax ) {
179             if (( rc = dn2ldif( rps, (DN) rdn->rdn_av.av_struct )) != 0 ) {
180                 return( rc );
181             }
182             *rps->ps_ptr = '\0';
183             value = rps->ps_base;
184         } else {
185             AttrV_print( rps, &rdn->rdn_av, EDBOUT );
186             *rps->ps_ptr = '\0';
187             value = rps->ps_base;
188             de_t61( value, 0 );
189         }
190
191         /*
192          * ,+="\\\n all go in quotes.  " and \\ need to
193          * be preceeded by \\.
194          */
195
196         if ( strpbrk( value, ",+=\"\\\n" ) != NULL || SPACE( value[0] )
197                 || SPACE( value[max( strlen(value) - 1, 0 )] ) ) {
198             char        *p, *t, *tmp;
199             int specialcount;
200
201             ps_print( ps, "\"" );
202
203             specialcount = 0;
204             for ( p = value; *p != '\0'; p++ ) {
205                 if ( *p == '"' || *p == '\\' ) {
206                     specialcount++;
207                 }
208             }
209             if ( specialcount > 0 ) {
210                 tmp = smalloc( strlen( value ) + specialcount + 1 );
211                 for ( p = value, t = tmp; *p != '\0'; p++ ) {
212                     switch ( *p ) {
213                     case '"':
214                     case '\\':
215                             *t++ = '\\';
216                             /* FALL THROUGH */
217                     default:
218                             *t++ = *p;
219                     }
220                 }
221                 *t = '\0';
222                 ps_print( ps, tmp );
223                 free( tmp );
224             } else {
225                 ps_print( ps, value );
226             }
227
228             ps_print( ps, "\"" );
229         } else {
230             ps_print( ps, value );
231         }
232
233         rps->ps_ptr = rps->ps_base;
234     }
235
236     ps_free( rps );
237
238     return( 0 );
239 }
240
241 #define T61     "{T.61}"
242 #define T61LEN  6
243
244 static void
245 de_t61( s, t61mark )
246 char    *s;
247 int     t61mark;
248 {
249         char    *next = s;
250         unsigned char   c;
251         unsigned int    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()) == NULL ) {
418             return( -1 );
419         }
420         if ( ber_printf( phber, "t{[tB]{B}}",
421                 (ber_tag_t) 0xA3, (ber_tag_t) 0x81, faxparamset, (ber_len_t) 31,
422                 (char *)pe->pe_prim, (ber_len_t) (len * 8) ) == -1 )
423         {
424             ber_free( phber, 1 );
425             return( -1 );
426         }
427         if ( ps_write( ps, (PElementData)phber->ber_buf,
428                 phber->ber_ptr - phber->ber_buf ) == NOTOK ) {
429             ber_free( phber, 1 );
430             return( -1 );
431         }
432         ber_free( phber, 1 );
433     } else {
434         /*
435          * try just writing this into a PS and sending it along
436          */
437         if ( pe2ps( ps, pe ) == NOTOK ) {
438             return( -1 );
439         }
440     }
441
442     return( 0 );
443 }
444
445
446 static int
447 fileattr2ldif( PS ps, AttributeValue av )
448 {
449     PE          pe;
450
451     if (( pe = grab_pe( av )) == NULLPE || pe->pe_id == PE_PRIM_NULL ) {
452         return( -2 );   /* signal soft error */
453     }
454
455     /*
456      * try just writing this into a PS and sending it along
457      */
458     if ( pe2ps( ps, pe ) == NOTOK ) {
459         return( -1 );
460     }
461
462     return( 0 );
463 }