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