]> git.sur5r.net Git - openldap/blob - libraries/liblutil/ldif.c
Sync with HEAD
[openldap] / libraries / liblutil / ldif.c
1 /* ldif.c - routines for dealing with LDIF files */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2005 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16 /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
17  * All rights reserved.
18  *
19  * Redistribution and use in source and binary forms are permitted
20  * provided that this notice is preserved and that due credit is given
21  * to the University of Michigan at Ann Arbor.  The name of the
22  * University may not be used to endorse or promote products derived
23  * from this software without specific prior written permission.  This
24  * software is provided ``as is'' without express or implied warranty.
25  */
26 /* This work was originally developed by the University of Michigan
27  * and distributed as part of U-MICH LDAP.
28  */
29
30 #include "portable.h"
31
32 #include <stdio.h>
33
34 #include <ac/stdlib.h>
35 #include <ac/ctype.h>
36
37 #include <ac/string.h>
38 #include <ac/socket.h>
39 #include <ac/time.h>
40
41 int ldif_debug = 0;
42
43 #include "ldap_log.h"
44 #include "lber_pvt.h"
45 #include "ldif.h"
46
47 #define RIGHT2                  0x03
48 #define RIGHT4                  0x0f
49 #define CONTINUED_LINE_MARKER   '\r'
50
51 #ifdef CSRIMALLOC
52 #define ber_memalloc malloc
53 #define ber_memcalloc calloc
54 #define ber_memrealloc realloc
55 #define ber_strdup strdup
56 #endif
57
58 static const char nib2b64[0x40] =
59         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
60
61 static const unsigned char b642nib[0x80] = {
62         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
63         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
64         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
65         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
66         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
67         0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
68         0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
69         0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
70         0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
71         0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
72         0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
73         0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
74         0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
75         0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
76         0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
77         0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
78 };
79
80 /*
81  * ldif_parse_line - takes a line of the form "type:[:] value" and splits it
82  * into components "type" and "value".  if a double colon separates type from
83  * value, then value is encoded in base 64, and parse_line un-decodes it
84  * (in place) before returning. The type and value are stored in malloc'd
85  * memory which must be freed by the caller.
86  *
87  * ldif_parse_line2 - operates in-place on input buffer, returning type
88  * in-place. Will return value in-place if possible, (must malloc for
89  * fetched URLs). If freeval is NULL, all return data will be malloc'd
90  * and the input line will be unmodified. Otherwise freeval is set to
91  * True if the value was malloc'd.
92  */
93
94 int
95 ldif_parse_line(
96     LDAP_CONST char     *line,
97     char        **typep,
98     char        **valuep,
99     ber_len_t *vlenp
100 )
101 {
102         struct berval type, value;
103         int rc = ldif_parse_line2( (char *)line, &type, &value, NULL );
104
105         *typep = type.bv_val;
106         *valuep = value.bv_val;
107         *vlenp = value.bv_len;
108         return rc;
109 }
110
111 int
112 ldif_parse_line2(
113     char        *line,
114         struct berval *type,
115         struct berval *value,
116         int             *freeval
117 )
118 {
119         char    *s, *p, *d; 
120         char    nib;
121         int     b64, url;
122
123         BER_BVZERO( type );
124         BER_BVZERO( value );
125
126         /* skip any leading space */
127         while ( isspace( (unsigned char) *line ) ) {
128                 line++;
129         }
130
131         if ( freeval ) {
132                 *freeval = 0;
133         } else {
134                 line = ber_strdup( line );
135
136                 if( line == NULL ) {
137                         ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
138                                 _("ldif_parse_line: line malloc failed\n"));
139                         return( -1 );
140                 }
141         }
142
143         type->bv_val = line;
144
145         s = strchr( type->bv_val, ':' );
146
147         if ( s == NULL ) {
148                 ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
149                         _("ldif_parse_line: missing ':' after %s\n"),
150                         type );
151                 if ( !freeval ) ber_memfree( line );
152                 return( -1 );
153         }
154
155         /* trim any space between type and : */
156         for ( p = &s[-1]; p > type->bv_val && isspace( * (unsigned char *) p ); p-- ) {
157                 *p = '\0';
158         }
159         *s++ = '\0';
160         type->bv_len = s - type->bv_val - 1;
161
162         url = 0;
163         b64 = 0;
164
165         if ( *s == '<' ) {
166                 s++;
167                 url = 1;
168
169         } else if ( *s == ':' ) {
170                 /* base 64 encoded value */
171                 s++;
172                 b64 = 1;
173         }
174
175         /* skip space between : and value */
176         while ( isspace( (unsigned char) *s ) ) {
177                 s++;
178         }
179
180         /* check for continued line markers that should be deleted */
181         for ( p = s, d = s; *p; p++ ) {
182                 if ( *p != CONTINUED_LINE_MARKER )
183                         *d++ = *p;
184         }
185         *d = '\0';
186
187         if ( b64 ) {
188                 char *byte = s;
189
190                 if ( *s == '\0' ) {
191                         /* no value is present, error out */
192                         ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
193                                 _("ldif_parse_line: %s missing base64 value\n"), type );
194                         if ( !freeval ) ber_memfree( line );
195                         return( -1 );
196                 }
197
198                 byte = value->bv_val = s;
199
200                 for ( p = s, value->bv_len = 0; p < d; p += 4, value->bv_len += 3 ) {
201                         int i;
202                         for ( i = 0; i < 4; i++ ) {
203                                 if ( p[i] != '=' && (p[i] & 0x80 ||
204                                     b642nib[ p[i] & 0x7f ] > 0x3f) ) {
205                                         ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
206                                                 _("ldif_parse_line: %s: invalid base64 encoding"
207                                                 " char (%c) 0x%x\n"),
208                                             type, p[i], p[i] );
209                                         if ( !freeval ) ber_memfree( line );
210                                         return( -1 );
211                                 }
212                         }
213
214                         /* first digit */
215                         nib = b642nib[ p[0] & 0x7f ];
216                         byte[0] = nib << 2;
217                         /* second digit */
218                         nib = b642nib[ p[1] & 0x7f ];
219                         byte[0] |= nib >> 4;
220                         byte[1] = (nib & RIGHT4) << 4;
221                         /* third digit */
222                         if ( p[2] == '=' ) {
223                                 value->bv_len += 1;
224                                 break;
225                         }
226                         nib = b642nib[ p[2] & 0x7f ];
227                         byte[1] |= nib >> 2;
228                         byte[2] = (nib & RIGHT2) << 6;
229                         /* fourth digit */
230                         if ( p[3] == '=' ) {
231                                 value->bv_len += 2;
232                                 break;
233                         }
234                         nib = b642nib[ p[3] & 0x7f ];
235                         byte[2] |= nib;
236
237                         byte += 3;
238                 }
239                 s[ value->bv_len ] = '\0';
240
241         } else if ( url ) {
242                 if ( *s == '\0' ) {
243                         /* no value is present, error out */
244                         ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
245                                 _("ldif_parse_line: %s missing URL value\n"), type );
246                         if ( !freeval ) ber_memfree( line );
247                         return( -1 );
248                 }
249
250                 if( ldif_fetch_url( s, &value->bv_val, &value->bv_len ) ) {
251                         ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
252                                 _("ldif_parse_line: %s: URL \"%s\" fetch failed\n"),
253                                 type, s );
254                         if ( !freeval ) ber_memfree( line );
255                         return( -1 );
256                 }
257                 if ( freeval ) *freeval = 1;
258
259         } else {
260                 value->bv_val = s;
261                 value->bv_len = (int) (d - s);
262         }
263
264         if ( !freeval ) {
265                 struct berval bv = *type;
266
267                 ber_dupbv( type, &bv );
268
269                 if( BER_BVISNULL( type )) {
270                         ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
271                                 _("ldif_parse_line: type malloc failed\n"));
272                         if( url ) ber_memfree( value->bv_val );
273                         ber_memfree( line );
274                         return( -1 );
275                 }
276
277                 if( !url ) {
278                         bv = *value;
279                         ber_dupbv( value, &bv );
280                         if( BER_BVISNULL( value )) {
281                                 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
282                                         _("ldif_parse_line: value malloc failed\n"));
283                                 ber_memfree( type->bv_val );
284                                 ber_memfree( line );
285                                 return( -1 );
286                         }
287                 }
288
289                 ber_memfree( line );
290         }
291
292         return( 0 );
293 }
294
295 /*
296  * ldif_getline - return the next "line" (minus newline) of input from a
297  * string buffer of lines separated by newlines, terminated by \n\n
298  * or \0.  this routine handles continued lines, bundling them into
299  * a single big line before returning.  if a line begins with a white
300  * space character, it is a continuation of the previous line. the white
301  * space character (nb: only one char), and preceeding newline are changed
302  * into CONTINUED_LINE_MARKER chars, to be deleted later by the
303  * ldif_parse_line() routine above.
304  *
305  * ldif_getline will skip over any line which starts '#'.
306  *
307  * ldif_getline takes a pointer to a pointer to the buffer on the first call,
308  * which it updates and must be supplied on subsequent calls.
309  */
310
311 int
312 ldif_countlines( LDAP_CONST char *buf )
313 {
314         char *nl;
315         int ret = 0;
316
317         if ( !buf ) return ret;
318
319         for ( nl = strchr(buf, '\n'); nl; nl = strchr(nl, '\n') ) {
320                 nl++;
321                 if ( *nl != ' ' ) ret++;
322         }
323         return ret;
324 }
325
326 char *
327 ldif_getline( char **next )
328 {
329         char *line;
330
331         do {
332                 if ( *next == NULL || **next == '\n' || **next == '\0' ) {
333                         return( NULL );
334                 }
335
336                 line = *next;
337
338                 while ( (*next = strchr( *next, '\n' )) != NULL ) {
339 #if CONTINUED_LINE_MARKER != '\r'
340                         if ( (*next)[-1] == '\r' ) {
341                                 (*next)[-1] = CONTINUED_LINE_MARKER;
342                         }
343 #endif
344
345                         if ( (*next)[1] != ' ' ) {
346                                 if ( (*next)[1] == '\r' && (*next)[2] == '\n' ) {
347                                         *(*next)++ = '\0';
348                                 }
349                                 *(*next)++ = '\0';
350                                 break;
351                         }
352
353                         **next = CONTINUED_LINE_MARKER;
354                         (*next)[1] = CONTINUED_LINE_MARKER;
355                         (*next)++;
356                 }
357         } while( *line == '#' );
358
359         return( line );
360 }
361
362 /* compatibility with U-Mich off by one bug */
363 #define LDIF_KLUDGE 1
364
365 void
366 ldif_sput(
367         char **out,
368         int type,
369         LDAP_CONST char *name,
370         LDAP_CONST char *val,
371         ber_len_t vlen )
372 {
373         const unsigned char *byte, *stop;
374         unsigned char   buf[3];
375         unsigned long   bits;
376         char            *save;
377         int             pad;
378         int             namelen = 0;
379
380         ber_len_t savelen;
381         ber_len_t len=0;
382         ber_len_t i;
383
384         /* prefix */
385         switch( type ) {
386         case LDIF_PUT_COMMENT:
387                 *(*out)++ = '#';
388                 len++;
389
390                 if( vlen ) {
391                         *(*out)++ = ' ';
392                         len++;
393                 }
394
395                 break;
396
397         case LDIF_PUT_SEP:
398                 *(*out)++ = '\n';
399                 return;
400         }
401
402         /* name (attribute type) */
403         if( name != NULL ) {
404                 /* put the name + ":" */
405                 namelen = strlen(name);
406                 strcpy(*out, name);
407                 *out += namelen;
408                 len += namelen;
409
410                 if( type != LDIF_PUT_COMMENT ) {
411                         *(*out)++ = ':';
412                         len++;
413                 }
414
415         }
416 #ifdef LDAP_DEBUG
417         else {
418                 assert( type == LDIF_PUT_COMMENT );
419         }
420 #endif
421
422         if( vlen == 0 ) {
423                 *(*out)++ = '\n';
424                 return;
425         }
426
427         switch( type ) {
428         case LDIF_PUT_NOVALUE:
429                 *(*out)++ = '\n';
430                 return;
431
432         case LDIF_PUT_URL: /* url value */
433                 *(*out)++ = '<';
434                 len++;
435                 break;
436
437         case LDIF_PUT_B64: /* base64 value */
438                 *(*out)++ = ':';
439                 len++;
440                 break;
441         }
442
443         switch( type ) {
444         case LDIF_PUT_TEXT:
445         case LDIF_PUT_URL:
446         case LDIF_PUT_B64:
447                 *(*out)++ = ' ';
448                 len++;
449                 /* fall-thru */
450
451         case LDIF_PUT_COMMENT:
452                 /* pre-encoded names */
453                 for ( i=0; i < vlen; i++ ) {
454                         if ( len > LDIF_LINE_WIDTH ) {
455                                 *(*out)++ = '\n';
456                                 *(*out)++ = ' ';
457                                 len = 1;
458                         }
459
460                         *(*out)++ = val[i];
461                         len++;
462                 }
463                 *(*out)++ = '\n';
464                 return;
465         }
466
467         save = *out;
468         savelen = len;
469
470         *(*out)++ = ' ';
471         len++;
472
473         stop = (const unsigned char *) (val + vlen);
474
475         if ( type == LDIF_PUT_VALUE
476                 && isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<'
477                 && isgraph( (unsigned char) val[vlen-1] )
478 #ifndef LDAP_BINARY_DEBUG
479                 && strstr( name, ";binary" ) == NULL
480 #endif
481 #ifndef LDAP_PASSWD_DEBUG
482                 && (namelen != (sizeof("userPassword")-1)
483                 || strcasecmp( name, "userPassword" ) != 0)     /* encode userPassword */
484                 && (namelen != (sizeof("2.5.4.35")-1) 
485                 || strcasecmp( name, "2.5.4.35" ) != 0)         /* encode userPassword */
486 #endif
487         ) {
488                 int b64 = 0;
489
490                 for ( byte = (const unsigned char *) val; byte < stop;
491                     byte++, len++ )
492                 {
493                         if ( !isascii( *byte ) || !isprint( *byte ) ) {
494                                 b64 = 1;
495                                 break;
496                         }
497                         if ( len > LDIF_LINE_WIDTH+LDIF_KLUDGE ) {
498                                 *(*out)++ = '\n';
499                                 *(*out)++ = ' ';
500                                 len = 1;
501                         }
502                         *(*out)++ = *byte;
503                 }
504
505                 if( !b64 ) {
506                         *(*out)++ = '\n';
507                         return;
508                 }
509         }
510
511         *out = save;
512         *(*out)++ = ':';
513         *(*out)++ = ' ';
514         len = savelen + 2;
515
516         /* convert to base 64 (3 bytes => 4 base 64 digits) */
517         for ( byte = (const unsigned char *) val;
518                 byte < stop - 2;
519             byte += 3 )
520         {
521                 bits = (byte[0] & 0xff) << 16;
522                 bits |= (byte[1] & 0xff) << 8;
523                 bits |= (byte[2] & 0xff);
524
525                 for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
526                         if ( len > LDIF_LINE_WIDTH+LDIF_KLUDGE ) {
527                                 *(*out)++ = '\n';
528                                 *(*out)++ = ' ';
529                                 len = 1;
530                         }
531
532                         /* get b64 digit from high order 6 bits */
533                         *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
534                 }
535         }
536
537         /* add padding if necessary */
538         if ( byte < stop ) {
539                 for ( i = 0; byte + i < stop; i++ ) {
540                         buf[i] = byte[i];
541                 }
542                 for ( pad = 0; i < 3; i++, pad++ ) {
543                         buf[i] = '\0';
544                 }
545                 byte = buf;
546                 bits = (byte[0] & 0xff) << 16;
547                 bits |= (byte[1] & 0xff) << 8;
548                 bits |= (byte[2] & 0xff);
549
550                 for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
551                         if ( len > LDIF_LINE_WIDTH+LDIF_KLUDGE ) {
552                                 *(*out)++ = '\n';
553                                 *(*out)++ = ' ';
554                                 len = 1;
555                         }
556
557                         if( i + pad < 4 ) {
558                                 /* get b64 digit from low order 6 bits */
559                                 *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
560                         } else {
561                                 *(*out)++ = '=';
562                         }
563                 }
564         }
565         *(*out)++ = '\n';
566 }
567
568
569 /*
570  * ldif_type_and_value return BER malloc'd, zero-terminated LDIF line
571  */
572 char *
573 ldif_put(
574         int type,
575         LDAP_CONST char *name,
576         LDAP_CONST char *val,
577         ber_len_t vlen )
578 {
579     char        *buf, *p;
580     ber_len_t nlen;
581
582     nlen = ( name != NULL ) ? strlen( name ) : 0;
583
584         buf = (char *) ber_memalloc( LDIF_SIZE_NEEDED( nlen, vlen ) + 1 );
585
586     if ( buf == NULL ) {
587                 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
588                         _("ldif_type_and_value: malloc failed!"));
589                 return NULL;
590     }
591
592     p = buf;
593     ldif_sput( &p, type, name, val, vlen );
594     *p = '\0';
595
596     return( buf );
597 }
598
599 int ldif_is_not_printable(
600         LDAP_CONST char *val,
601         ber_len_t vlen )
602 {
603         if( vlen == 0 || val == NULL  ) {
604                 return -1;
605         }
606
607         if( isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' &&
608                 isgraph( (unsigned char) val[vlen-1] ) )
609         {
610                 ber_len_t i;
611
612                 for ( i = 0; val[i]; i++ ) {
613                         if ( !isascii( val[i] ) || !isprint( val[i] ) ) {
614                                 return 1;
615                         }
616                 }
617
618                 return 0;
619         }
620
621         return 1;
622 }
623
624 /*
625  * slap_read_ldif - read an ldif record.  Return 1 for success, 0 for EOF.
626  */
627 int
628 ldif_read_record(
629         FILE        *fp,
630         int         *lno,               /* ptr to line number counter              */
631         char        **bufp,     /* ptr to malloced output buffer           */
632         int         *buflenp )  /* ptr to length of *bufp                  */
633 {
634         char        linebuf[BUFSIZ], *line, *nbufp;
635         ber_len_t   lcur = 0, len, linesize;
636         int         last_ch = '\n', found_entry = 0, stop, top_comment = 0;
637
638         line     = linebuf;
639         linesize = sizeof( linebuf );
640
641         for ( stop = feof( fp );  !stop;  last_ch = line[len-1] ) {
642                 if ( fgets( line, linesize, fp ) == NULL ) {
643                         stop = 1;
644                         /* Add \n in case the file does not end with newline */
645                         line = "\n";
646                 }
647                 len = strlen( line );
648
649                 if ( last_ch == '\n' ) {
650                         (*lno)++;
651
652                         if ( line[0] == '\n' ) {
653                                 if ( !found_entry ) {
654                                         lcur = 0;
655                                         top_comment = 0;
656                                         continue;
657                                 }
658                                 break;
659                         }
660
661                         if ( !found_entry ) {
662                                 if ( line[0] == '#' ) {
663                                         top_comment = 1;
664                                 } else if ( ! ( top_comment && line[0] == ' ' ) ) {
665                                         /* Found a new entry */
666                                         found_entry = 1;
667
668                                         if ( isdigit( (unsigned char) line[0] ) ) {
669                                                 /* skip index */
670                                                 continue;
671                                         }
672                                 }
673                         }                       
674                 }
675
676                 if ( *buflenp - lcur <= len ) {
677                         *buflenp += len + BUFSIZ;
678                         nbufp = ber_memrealloc( *bufp, *buflenp );
679                         if( nbufp == NULL ) {
680                                 return 0;
681                         }
682                         *bufp = nbufp;
683                 }
684                 strcpy( *bufp + lcur, line );
685                 lcur += len;
686         }
687
688         return( found_entry );
689 }