~ttx/openldap/lucid-gssapi-495418

« back to all changes in this revision

Viewing changes to libraries/liblutil/ldif.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug
  • Date: 2008-07-10 14:45:49 UTC
  • Revision ID: james.westby@ubuntu.com-20080710144549-wck73med0e72gfyo
Tags: upstream-2.4.10
ImportĀ upstreamĀ versionĀ 2.4.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ldif.c - routines for dealing with LDIF files */
 
2
/* $OpenLDAP: pkg/ldap/libraries/liblutil/ldif.c,v 1.15.2.6 2008/02/11 23:26:42 kurt Exp $ */
 
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 
4
 *
 
5
 * Copyright 1998-2008 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->bv_val );
 
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"),
 
194
                                type->bv_val );
 
195
                        if ( !freeval ) ber_memfree( line );
 
196
                        return( -1 );
 
197
                }
 
198
 
 
199
                byte = value->bv_val = s;
 
200
 
 
201
                for ( p = s, value->bv_len = 0; p < d; p += 4, value->bv_len += 3 ) {
 
202
                        int i;
 
203
                        for ( i = 0; i < 4; i++ ) {
 
204
                                if ( p[i] != '=' && (p[i] & 0x80 ||
 
205
                                    b642nib[ p[i] & 0x7f ] > 0x3f) ) {
 
206
                                        ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
 
207
                                                _("ldif_parse_line: %s: invalid base64 encoding"
 
208
                                                " char (%c) 0x%x\n"),
 
209
                                            type->bv_val, p[i], p[i] );
 
210
                                        if ( !freeval ) ber_memfree( line );
 
211
                                        return( -1 );
 
212
                                }
 
213
                        }
 
214
 
 
215
                        /* first digit */
 
216
                        nib = b642nib[ p[0] & 0x7f ];
 
217
                        byte[0] = nib << 2;
 
218
                        /* second digit */
 
219
                        nib = b642nib[ p[1] & 0x7f ];
 
220
                        byte[0] |= nib >> 4;
 
221
                        byte[1] = (nib & RIGHT4) << 4;
 
222
                        /* third digit */
 
223
                        if ( p[2] == '=' ) {
 
224
                                value->bv_len += 1;
 
225
                                break;
 
226
                        }
 
227
                        nib = b642nib[ p[2] & 0x7f ];
 
228
                        byte[1] |= nib >> 2;
 
229
                        byte[2] = (nib & RIGHT2) << 6;
 
230
                        /* fourth digit */
 
231
                        if ( p[3] == '=' ) {
 
232
                                value->bv_len += 2;
 
233
                                break;
 
234
                        }
 
235
                        nib = b642nib[ p[3] & 0x7f ];
 
236
                        byte[2] |= nib;
 
237
 
 
238
                        byte += 3;
 
239
                }
 
240
                s[ value->bv_len ] = '\0';
 
241
 
 
242
        } else if ( url ) {
 
243
                if ( *s == '\0' ) {
 
244
                        /* no value is present, error out */
 
245
                        ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug,
 
246
                                _("ldif_parse_line: %s missing URL value\n"),
 
247
                                type->bv_val );
 
248
                        if ( !freeval ) ber_memfree( line );
 
249
                        return( -1 );
 
250
                }
 
251
 
 
252
                if( ldif_fetch_url( s, &value->bv_val, &value->bv_len ) ) {
 
253
                        ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
 
254
                                _("ldif_parse_line: %s: URL \"%s\" fetch failed\n"),
 
255
                                type->bv_val, s );
 
256
                        if ( !freeval ) ber_memfree( line );
 
257
                        return( -1 );
 
258
                }
 
259
                if ( freeval ) *freeval = 1;
 
260
 
 
261
        } else {
 
262
                value->bv_val = s;
 
263
                value->bv_len = (int) (d - s);
 
264
        }
 
265
 
 
266
        if ( !freeval ) {
 
267
                struct berval bv = *type;
 
268
 
 
269
                ber_dupbv( type, &bv );
 
270
 
 
271
                if( BER_BVISNULL( type )) {
 
272
                        ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
 
273
                                _("ldif_parse_line: type malloc failed\n"));
 
274
                        if( url ) ber_memfree( value->bv_val );
 
275
                        ber_memfree( line );
 
276
                        return( -1 );
 
277
                }
 
278
 
 
279
                if( !url ) {
 
280
                        bv = *value;
 
281
                        ber_dupbv( value, &bv );
 
282
                        if( BER_BVISNULL( value )) {
 
283
                                ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
 
284
                                        _("ldif_parse_line: value malloc failed\n"));
 
285
                                ber_memfree( type->bv_val );
 
286
                                ber_memfree( line );
 
287
                                return( -1 );
 
288
                        }
 
289
                }
 
290
 
 
291
                ber_memfree( line );
 
292
        }
 
293
 
 
294
        return( 0 );
 
295
}
 
296
 
 
297
/*
 
298
 * ldif_getline - return the next "line" (minus newline) of input from a
 
299
 * string buffer of lines separated by newlines, terminated by \n\n
 
300
 * or \0.  this routine handles continued lines, bundling them into
 
301
 * a single big line before returning.  if a line begins with a white
 
302
 * space character, it is a continuation of the previous line. the white
 
303
 * space character (nb: only one char), and preceeding newline are changed
 
304
 * into CONTINUED_LINE_MARKER chars, to be deleted later by the
 
305
 * ldif_parse_line() routine above.
 
306
 *
 
307
 * ldif_getline will skip over any line which starts '#'.
 
308
 *
 
309
 * ldif_getline takes a pointer to a pointer to the buffer on the first call,
 
310
 * which it updates and must be supplied on subsequent calls.
 
311
 */
 
312
 
 
313
int
 
314
ldif_countlines( LDAP_CONST char *buf )
 
315
{
 
316
        char *nl;
 
317
        int ret = 0;
 
318
 
 
319
        if ( !buf ) return ret;
 
320
 
 
321
        for ( nl = strchr(buf, '\n'); nl; nl = strchr(nl, '\n') ) {
 
322
                nl++;
 
323
                if ( *nl != ' ' ) ret++;
 
324
        }
 
325
        return ret;
 
326
}
 
327
 
 
328
char *
 
329
ldif_getline( char **next )
 
330
{
 
331
        char *line;
 
332
 
 
333
        do {
 
334
                if ( *next == NULL || **next == '\n' || **next == '\0' ) {
 
335
                        return( NULL );
 
336
                }
 
337
 
 
338
                line = *next;
 
339
 
 
340
                while ( (*next = strchr( *next, '\n' )) != NULL ) {
 
341
#if CONTINUED_LINE_MARKER != '\r'
 
342
                        if ( (*next)[-1] == '\r' ) {
 
343
                                (*next)[-1] = CONTINUED_LINE_MARKER;
 
344
                        }
 
345
#endif
 
346
 
 
347
                        if ( (*next)[1] != ' ' ) {
 
348
                                if ( (*next)[1] == '\r' && (*next)[2] == '\n' ) {
 
349
                                        *(*next)++ = '\0';
 
350
                                }
 
351
                                *(*next)++ = '\0';
 
352
                                break;
 
353
                        }
 
354
 
 
355
                        **next = CONTINUED_LINE_MARKER;
 
356
                        (*next)[1] = CONTINUED_LINE_MARKER;
 
357
                        (*next)++;
 
358
                }
 
359
        } while( *line == '#' );
 
360
 
 
361
        return( line );
 
362
}
 
363
 
 
364
/*
 
365
 * name and OID of attributeTypes that must be base64 encoded in any case
 
366
 */
 
367
typedef struct must_b64_encode_s {
 
368
        struct berval   name;
 
369
        struct berval   oid;
 
370
} must_b64_encode_s;
 
371
 
 
372
static must_b64_encode_s        default_must_b64_encode[] = {
 
373
        { BER_BVC( "userPassword" ), BER_BVC( "2.5.4.35" ) },
 
374
        { BER_BVNULL, BER_BVNULL }
 
375
};
 
376
 
 
377
static must_b64_encode_s        *must_b64_encode = default_must_b64_encode;
 
378
 
 
379
/*
 
380
 * register name and OID of attributeTypes that must always be base64 
 
381
 * encoded
 
382
 *
 
383
 * NOTE: this routine mallocs memory in a static struct which must 
 
384
 * be explicitly freed when no longer required
 
385
 */
 
386
int
 
387
ldif_must_b64_encode_register( LDAP_CONST char *name, LDAP_CONST char *oid )
 
388
{
 
389
        int             i;
 
390
        ber_len_t       len;
 
391
 
 
392
        assert( must_b64_encode != NULL );
 
393
        assert( name != NULL );
 
394
        assert( oid != NULL );
 
395
 
 
396
        len = strlen( name );
 
397
 
 
398
        for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
 
399
                if ( len != must_b64_encode[i].name.bv_len ) {
 
400
                        continue;
 
401
                }
 
402
 
 
403
                if ( strcasecmp( name, must_b64_encode[i].name.bv_val ) == 0 ) {
 
404
                        break;
 
405
                }
 
406
        }
 
407
 
 
408
        if ( !BER_BVISNULL( &must_b64_encode[i].name ) ) {
 
409
                return 1;
 
410
        }
 
411
 
 
412
        for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ )
 
413
                /* just count */ ;
 
414
 
 
415
        if ( must_b64_encode == default_must_b64_encode ) {
 
416
                must_b64_encode = ber_memalloc( sizeof( must_b64_encode_s ) * ( i + 2 ) );
 
417
 
 
418
                for ( i = 0; !BER_BVISNULL( &default_must_b64_encode[i].name ); i++ ) {
 
419
                        ber_dupbv( &must_b64_encode[i].name, &default_must_b64_encode[i].name );
 
420
                        ber_dupbv( &must_b64_encode[i].oid, &default_must_b64_encode[i].oid );
 
421
                }
 
422
 
 
423
        } else {
 
424
                must_b64_encode_s       *tmp;
 
425
 
 
426
                tmp = ber_memrealloc( must_b64_encode,
 
427
                        sizeof( must_b64_encode_s ) * ( i + 2 ) );
 
428
                if ( tmp == NULL ) {
 
429
                        return 1;
 
430
                }
 
431
                must_b64_encode = tmp;
 
432
        }
 
433
 
 
434
        ber_str2bv( name, len, 1, &must_b64_encode[i].name );
 
435
        ber_str2bv( oid, 0, 1, &must_b64_encode[i].oid );
 
436
 
 
437
        BER_BVZERO( &must_b64_encode[i + 1].name );
 
438
 
 
439
        return 0;
 
440
}
 
441
 
 
442
void
 
443
ldif_must_b64_encode_release( void )
 
444
{
 
445
        int     i;
 
446
 
 
447
        assert( must_b64_encode != NULL );
 
448
 
 
449
        if ( must_b64_encode == default_must_b64_encode ) {
 
450
                return;
 
451
        }
 
452
 
 
453
        for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
 
454
                ber_memfree( must_b64_encode[i].name.bv_val );
 
455
                ber_memfree( must_b64_encode[i].oid.bv_val );
 
456
        }
 
457
 
 
458
        ber_memfree( must_b64_encode );
 
459
 
 
460
        must_b64_encode = default_must_b64_encode;
 
461
}
 
462
 
 
463
/*
 
464
 * returns 1 iff the string corresponds to the name or the OID of any 
 
465
 * of the attributeTypes listed in must_b64_encode
 
466
 */
 
467
static int
 
468
ldif_must_b64_encode( LDAP_CONST char *s )
 
469
{
 
470
        int             i;
 
471
        struct berval   bv;
 
472
 
 
473
        assert( must_b64_encode != NULL );
 
474
        assert( s != NULL );
 
475
 
 
476
        ber_str2bv( s, 0, 0, &bv );
 
477
 
 
478
        for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) {
 
479
                if ( ber_bvstrcasecmp( &must_b64_encode[i].name, &bv ) == 0
 
480
                        || ber_bvcmp( &must_b64_encode[i].oid, &bv ) == 0 )
 
481
                {
 
482
                        return 1;
 
483
                }
 
484
        }
 
485
 
 
486
        return 0;
 
487
}
 
488
 
 
489
/* compatibility with U-Mich off by one bug */
 
490
#define LDIF_KLUDGE 1
 
491
 
 
492
void
 
493
ldif_sput(
 
494
        char **out,
 
495
        int type,
 
496
        LDAP_CONST char *name,
 
497
        LDAP_CONST char *val,
 
498
        ber_len_t vlen )
 
499
{
 
500
        const unsigned char *byte, *stop;
 
501
        unsigned char   buf[3];
 
502
        unsigned long   bits;
 
503
        char            *save;
 
504
        int             pad;
 
505
        int             namelen = 0;
 
506
 
 
507
        ber_len_t savelen;
 
508
        ber_len_t len=0;
 
509
        ber_len_t i;
 
510
 
 
511
        /* prefix */
 
512
        switch( type ) {
 
513
        case LDIF_PUT_COMMENT:
 
514
                *(*out)++ = '#';
 
515
                len++;
 
516
 
 
517
                if( vlen ) {
 
518
                        *(*out)++ = ' ';
 
519
                        len++;
 
520
                }
 
521
 
 
522
                break;
 
523
 
 
524
        case LDIF_PUT_SEP:
 
525
                *(*out)++ = '\n';
 
526
                return;
 
527
        }
 
528
 
 
529
        /* name (attribute type) */
 
530
        if( name != NULL ) {
 
531
                /* put the name + ":" */
 
532
                namelen = strlen(name);
 
533
                strcpy(*out, name);
 
534
                *out += namelen;
 
535
                len += namelen;
 
536
 
 
537
                if( type != LDIF_PUT_COMMENT ) {
 
538
                        *(*out)++ = ':';
 
539
                        len++;
 
540
                }
 
541
 
 
542
        }
 
543
#ifdef LDAP_DEBUG
 
544
        else {
 
545
                assert( type == LDIF_PUT_COMMENT );
 
546
        }
 
547
#endif
 
548
 
 
549
        if( vlen == 0 ) {
 
550
                *(*out)++ = '\n';
 
551
                return;
 
552
        }
 
553
 
 
554
        switch( type ) {
 
555
        case LDIF_PUT_NOVALUE:
 
556
                *(*out)++ = '\n';
 
557
                return;
 
558
 
 
559
        case LDIF_PUT_URL: /* url value */
 
560
                *(*out)++ = '<';
 
561
                len++;
 
562
                break;
 
563
 
 
564
        case LDIF_PUT_B64: /* base64 value */
 
565
                *(*out)++ = ':';
 
566
                len++;
 
567
                break;
 
568
        }
 
569
 
 
570
        switch( type ) {
 
571
        case LDIF_PUT_TEXT:
 
572
        case LDIF_PUT_URL:
 
573
        case LDIF_PUT_B64:
 
574
                *(*out)++ = ' ';
 
575
                len++;
 
576
                /* fall-thru */
 
577
 
 
578
        case LDIF_PUT_COMMENT:
 
579
                /* pre-encoded names */
 
580
                for ( i=0; i < vlen; i++ ) {
 
581
                        if ( len > LDIF_LINE_WIDTH ) {
 
582
                                *(*out)++ = '\n';
 
583
                                *(*out)++ = ' ';
 
584
                                len = 1;
 
585
                        }
 
586
 
 
587
                        *(*out)++ = val[i];
 
588
                        len++;
 
589
                }
 
590
                *(*out)++ = '\n';
 
591
                return;
 
592
        }
 
593
 
 
594
        save = *out;
 
595
        savelen = len;
 
596
 
 
597
        *(*out)++ = ' ';
 
598
        len++;
 
599
 
 
600
        stop = (const unsigned char *) (val + vlen);
 
601
 
 
602
        if ( type == LDIF_PUT_VALUE
 
603
                && isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<'
 
604
                && isgraph( (unsigned char) val[vlen-1] )
 
605
#ifndef LDAP_BINARY_DEBUG
 
606
                && strstr( name, ";binary" ) == NULL
 
607
#endif
 
608
#ifndef LDAP_PASSWD_DEBUG
 
609
                && !ldif_must_b64_encode( name )
 
610
#endif
 
611
        ) {
 
612
                int b64 = 0;
 
613
 
 
614
                for ( byte = (const unsigned char *) val; byte < stop;
 
615
                    byte++, len++ )
 
616
                {
 
617
                        if ( !isascii( *byte ) || !isprint( *byte ) ) {
 
618
                                b64 = 1;
 
619
                                break;
 
620
                        }
 
621
                        if ( len > LDIF_LINE_WIDTH+LDIF_KLUDGE ) {
 
622
                                *(*out)++ = '\n';
 
623
                                *(*out)++ = ' ';
 
624
                                len = 1;
 
625
                        }
 
626
                        *(*out)++ = *byte;
 
627
                }
 
628
 
 
629
                if( !b64 ) {
 
630
                        *(*out)++ = '\n';
 
631
                        return;
 
632
                }
 
633
        }
 
634
 
 
635
        *out = save;
 
636
        *(*out)++ = ':';
 
637
        *(*out)++ = ' ';
 
638
        len = savelen + 2;
 
639
 
 
640
        /* convert to base 64 (3 bytes => 4 base 64 digits) */
 
641
        for ( byte = (const unsigned char *) val;
 
642
                byte < stop - 2;
 
643
            byte += 3 )
 
644
        {
 
645
                bits = (byte[0] & 0xff) << 16;
 
646
                bits |= (byte[1] & 0xff) << 8;
 
647
                bits |= (byte[2] & 0xff);
 
648
 
 
649
                for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
 
650
                        if ( len > LDIF_LINE_WIDTH+LDIF_KLUDGE ) {
 
651
                                *(*out)++ = '\n';
 
652
                                *(*out)++ = ' ';
 
653
                                len = 1;
 
654
                        }
 
655
 
 
656
                        /* get b64 digit from high order 6 bits */
 
657
                        *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
 
658
                }
 
659
        }
 
660
 
 
661
        /* add padding if necessary */
 
662
        if ( byte < stop ) {
 
663
                for ( i = 0; byte + i < stop; i++ ) {
 
664
                        buf[i] = byte[i];
 
665
                }
 
666
                for ( pad = 0; i < 3; i++, pad++ ) {
 
667
                        buf[i] = '\0';
 
668
                }
 
669
                byte = buf;
 
670
                bits = (byte[0] & 0xff) << 16;
 
671
                bits |= (byte[1] & 0xff) << 8;
 
672
                bits |= (byte[2] & 0xff);
 
673
 
 
674
                for ( i = 0; i < 4; i++, len++, bits <<= 6 ) {
 
675
                        if ( len > LDIF_LINE_WIDTH+LDIF_KLUDGE ) {
 
676
                                *(*out)++ = '\n';
 
677
                                *(*out)++ = ' ';
 
678
                                len = 1;
 
679
                        }
 
680
 
 
681
                        if( i + pad < 4 ) {
 
682
                                /* get b64 digit from low order 6 bits */
 
683
                                *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ];
 
684
                        } else {
 
685
                                *(*out)++ = '=';
 
686
                        }
 
687
                }
 
688
        }
 
689
        *(*out)++ = '\n';
 
690
}
 
691
 
 
692
 
 
693
/*
 
694
 * ldif_type_and_value return BER malloc'd, zero-terminated LDIF line
 
695
 */
 
696
char *
 
697
ldif_put(
 
698
        int type,
 
699
        LDAP_CONST char *name,
 
700
        LDAP_CONST char *val,
 
701
        ber_len_t vlen )
 
702
{
 
703
    char        *buf, *p;
 
704
    ber_len_t nlen;
 
705
 
 
706
    nlen = ( name != NULL ) ? strlen( name ) : 0;
 
707
 
 
708
        buf = (char *) ber_memalloc( LDIF_SIZE_NEEDED( nlen, vlen ) + 1 );
 
709
 
 
710
    if ( buf == NULL ) {
 
711
                ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
 
712
                        _("ldif_type_and_value: malloc failed!"));
 
713
                return NULL;
 
714
    }
 
715
 
 
716
    p = buf;
 
717
    ldif_sput( &p, type, name, val, vlen );
 
718
    *p = '\0';
 
719
 
 
720
    return( buf );
 
721
}
 
722
 
 
723
int ldif_is_not_printable(
 
724
        LDAP_CONST char *val,
 
725
        ber_len_t vlen )
 
726
{
 
727
        if( vlen == 0 || val == NULL  ) {
 
728
                return -1;
 
729
        }
 
730
 
 
731
        if( isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' &&
 
732
                isgraph( (unsigned char) val[vlen-1] ) )
 
733
        {
 
734
                ber_len_t i;
 
735
 
 
736
                for ( i = 0; val[i]; i++ ) {
 
737
                        if ( !isascii( val[i] ) || !isprint( (unsigned char) val[i] ) ) {
 
738
                                return 1;
 
739
                        }
 
740
                }
 
741
 
 
742
                return 0;
 
743
        }
 
744
 
 
745
        return 1;
 
746
}
 
747
 
 
748
LDIFFP *
 
749
ldif_open(
 
750
        LDAP_CONST char *file,
 
751
        LDAP_CONST char *mode
 
752
)
 
753
{
 
754
        FILE *fp = fopen( file, mode );
 
755
        LDIFFP *lfp = NULL;
 
756
 
 
757
        if ( fp ) {
 
758
                lfp = ber_memalloc( sizeof( LDIFFP ));
 
759
                lfp->fp = fp;
 
760
                lfp->prev = NULL;
 
761
        }
 
762
        return lfp;
 
763
}
 
764
 
 
765
void
 
766
ldif_close(
 
767
        LDIFFP *lfp
 
768
)
 
769
{
 
770
        LDIFFP *prev;
 
771
 
 
772
        while ( lfp ) {
 
773
                fclose( lfp->fp );
 
774
                prev = lfp->prev;
 
775
                ber_memfree( lfp );
 
776
                lfp = prev;
 
777
        }
 
778
}
 
779
 
 
780
#define LDIF_MAXLINE    4096
 
781
 
 
782
/*
 
783
 * ldif_read_record - read an ldif record.  Return 1 for success, 0 for EOF.
 
784
 */
 
785
int
 
786
ldif_read_record(
 
787
        LDIFFP      *lfp,
 
788
        int         *lno,               /* ptr to line number counter              */
 
789
        char        **bufp,     /* ptr to malloced output buffer           */
 
790
        int         *buflenp )  /* ptr to length of *bufp                  */
 
791
{
 
792
        char        linebuf[LDIF_MAXLINE], *line, *nbufp;
 
793
        ber_len_t   lcur = 0, len, linesize;
 
794
        int         last_ch = '\n', found_entry = 0, stop, top_comment = 0;
 
795
 
 
796
        line     = linebuf;
 
797
        linesize = sizeof( linebuf );
 
798
 
 
799
        for ( stop = 0;  !stop;  last_ch = line[len-1] ) {
 
800
                /* If we're at the end of this file, see if we should pop
 
801
                 * back to a previous file. (return from an include)
 
802
                 */
 
803
                while ( feof( lfp->fp )) {
 
804
                        if ( lfp->prev ) {
 
805
                                LDIFFP *tmp = lfp->prev;
 
806
                                fclose( lfp->fp );
 
807
                                *lfp = *tmp;
 
808
                                ber_memfree( tmp );
 
809
                        } else {
 
810
                                stop = 1;
 
811
                                break;
 
812
                        }
 
813
                }
 
814
                if ( stop )
 
815
                        break;
 
816
 
 
817
                if ( fgets( line, linesize, lfp->fp ) == NULL ) {
 
818
                        stop = 1;
 
819
                        /* Add \n in case the file does not end with newline */
 
820
                        line = "\n";
 
821
                }
 
822
                len = strlen( line );
 
823
 
 
824
                if ( last_ch == '\n' ) {
 
825
                        (*lno)++;
 
826
 
 
827
                        if ( line[0] == '\n' ||
 
828
                                ( line[0] == '\r' && line[1] == '\n' )) {
 
829
                                if ( !found_entry ) {
 
830
                                        lcur = 0;
 
831
                                        top_comment = 0;
 
832
                                        continue;
 
833
                                }
 
834
                                break;
 
835
                        }
 
836
 
 
837
                        if ( !found_entry ) {
 
838
                                if ( line[0] == '#' ) {
 
839
                                        top_comment = 1;
 
840
                                } else if ( ! ( top_comment && line[0] == ' ' ) ) {
 
841
                                        /* Found a new entry */
 
842
                                        found_entry = 1;
 
843
 
 
844
                                        if ( isdigit( (unsigned char) line[0] ) ) {
 
845
                                                /* skip index */
 
846
                                                continue;
 
847
                                        }
 
848
                                        if ( !strncasecmp( line, "include:",
 
849
                                                STRLENOF("include:"))) {
 
850
                                                FILE *fp2;
 
851
                                                char *ptr;
 
852
                                                found_entry = 0;
 
853
 
 
854
                                                if ( line[len-1] == '\n' ) {
 
855
                                                        len--;
 
856
                                                        line[len] = '\0';
 
857
                                                }
 
858
                                                if ( line[len-1] == '\r' ) {
 
859
                                                        len--;
 
860
                                                        line[len] = '\0';
 
861
                                                }
 
862
 
 
863
                                                ptr = line + STRLENOF("include:");
 
864
                                                while (isspace((unsigned char) *ptr)) ptr++;
 
865
                                                fp2 = ldif_open_url( ptr );
 
866
                                                if ( fp2 ) {
 
867
                                                        LDIFFP *lnew = ber_memalloc( sizeof( LDIFFP ));
 
868
                                                        if ( lnew == NULL ) {
 
869
                                                                fclose( fp2 );
 
870
                                                                return 0;
 
871
                                                        }
 
872
                                                        lnew->prev = lfp->prev;
 
873
                                                        lnew->fp = lfp->fp;
 
874
                                                        lfp->prev = lnew;
 
875
                                                        lfp->fp = fp2;
 
876
                                                        line[len] = '\n';
 
877
                                                        len++;
 
878
                                                        continue;
 
879
                                                } else {
 
880
                                                        /* We failed to open the file, this should
 
881
                                                         * be reported as an error somehow.
 
882
                                                         */
 
883
                                                        ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug,
 
884
                                                                _("ldif_read_record: include %s failed\n"), ptr );
 
885
                                                        return 0;
 
886
                                                }
 
887
                                        }
 
888
                                }
 
889
                        }                       
 
890
                }
 
891
 
 
892
                if ( *buflenp - lcur <= len ) {
 
893
                        *buflenp += len + LDIF_MAXLINE;
 
894
                        nbufp = ber_memrealloc( *bufp, *buflenp );
 
895
                        if( nbufp == NULL ) {
 
896
                                return 0;
 
897
                        }
 
898
                        *bufp = nbufp;
 
899
                }
 
900
                strcpy( *bufp + lcur, line );
 
901
                lcur += len;
 
902
        }
 
903
 
 
904
        return( found_entry );
 
905
}