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-2011 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 41int 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 58static const char nib2b64[0x40] = 59 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 60 61static 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 94int 95ldif_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 111int 112ldif_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 313int 314ldif_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 328char * 329ldif_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 */ 367typedef struct must_b64_encode_s { 368 struct berval name; 369 struct berval oid; 370} must_b64_encode_s; 371 372static 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 377static 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 */ 386int 387ldif_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 442void 443ldif_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 */ 467static int 468ldif_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/* NOTE: only preserved for binary compatibility */ 493void 494ldif_sput( 495 char **out, 496 int type, 497 LDAP_CONST char *name, 498 LDAP_CONST char *val, 499 ber_len_t vlen ) 500{ 501 ldif_sput_wrap( out, type, name, val, vlen, LDIF_LINE_WIDTH ); 502} 503 504void 505ldif_sput_wrap( 506 char **out, 507 int type, 508 LDAP_CONST char *name, 509 LDAP_CONST char *val, 510 ber_len_t vlen, 511 ber_len_t wrap ) 512{ 513 const unsigned char *byte, *stop; 514 unsigned char buf[3]; 515 unsigned long bits; 516 char *save; 517 int pad; 518 int namelen = 0; 519 520 ber_len_t savelen; 521 ber_len_t len=0; 522 ber_len_t i; 523 524 wrap = LDIF_LINE_WIDTH_WRAP( wrap ); 525 526 /* prefix */ 527 switch( type ) { 528 case LDIF_PUT_COMMENT: 529 *(*out)++ = '#'; 530 len++; 531 532 if( vlen ) { 533 *(*out)++ = ' '; 534 len++; 535 } 536 537 break; 538 539 case LDIF_PUT_SEP: 540 *(*out)++ = '\n'; 541 return; 542 } 543 544 /* name (attribute type) */ 545 if( name != NULL ) { 546 /* put the name + ":" */ 547 namelen = strlen(name); 548 strcpy(*out, name); 549 *out += namelen; 550 len += namelen; 551 552 if( type != LDIF_PUT_COMMENT ) { 553 *(*out)++ = ':'; 554 len++; 555 } 556 557 } 558#ifdef LDAP_DEBUG 559 else { 560 assert( type == LDIF_PUT_COMMENT ); 561 } 562#endif 563 564 if( vlen == 0 ) { 565 *(*out)++ = '\n'; 566 return; 567 } 568 569 switch( type ) { 570 case LDIF_PUT_NOVALUE: 571 *(*out)++ = '\n'; 572 return; 573 574 case LDIF_PUT_URL: /* url value */ 575 *(*out)++ = '<'; 576 len++; 577 break; 578 579 case LDIF_PUT_B64: /* base64 value */ 580 *(*out)++ = ':'; 581 len++; 582 break; 583 } 584 585 switch( type ) { 586 case LDIF_PUT_TEXT: 587 case LDIF_PUT_URL: 588 case LDIF_PUT_B64: 589 *(*out)++ = ' '; 590 len++; 591 /* fall-thru */ 592 593 case LDIF_PUT_COMMENT: 594 /* pre-encoded names */ 595 for ( i=0; i < vlen; i++ ) { 596 if ( len > wrap ) { 597 *(*out)++ = '\n'; 598 *(*out)++ = ' '; 599 len = 1; 600 } 601 602 *(*out)++ = val[i]; 603 len++; 604 } 605 *(*out)++ = '\n'; 606 return; 607 } 608 609 save = *out; 610 savelen = len; 611 612 *(*out)++ = ' '; 613 len++; 614 615 stop = (const unsigned char *) (val + vlen); 616 617 if ( type == LDIF_PUT_VALUE 618 && isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' 619 && isgraph( (unsigned char) val[vlen-1] ) 620#ifndef LDAP_BINARY_DEBUG 621 && strstr( name, ";binary" ) == NULL 622#endif 623#ifndef LDAP_PASSWD_DEBUG 624 && !ldif_must_b64_encode( name ) 625#endif 626 ) { 627 int b64 = 0; 628 629 for ( byte = (const unsigned char *) val; byte < stop; 630 byte++, len++ ) 631 { 632 if ( !isascii( *byte ) || !isprint( *byte ) ) { 633 b64 = 1; 634 break; 635 } 636 if ( len - LDIF_KLUDGE > wrap ) { 637 *(*out)++ = '\n'; 638 *(*out)++ = ' '; 639 len = 1; 640 } 641 *(*out)++ = *byte; 642 } 643 644 if( !b64 ) { 645 *(*out)++ = '\n'; 646 return; 647 } 648 } 649 650 *out = save; 651 *(*out)++ = ':'; 652 *(*out)++ = ' '; 653 len = savelen + 2; 654 655 /* convert to base 64 (3 bytes => 4 base 64 digits) */ 656 for ( byte = (const unsigned char *) val; 657 byte < stop - 2; 658 byte += 3 ) 659 { 660 bits = (byte[0] & 0xff) << 16; 661 bits |= (byte[1] & 0xff) << 8; 662 bits |= (byte[2] & 0xff); 663 664 for ( i = 0; i < 4; i++, len++, bits <<= 6 ) { 665 if ( len - LDIF_KLUDGE > wrap ) { 666 *(*out)++ = '\n'; 667 *(*out)++ = ' '; 668 len = 1; 669 } 670 671 /* get b64 digit from high order 6 bits */ 672 *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ]; 673 } 674 } 675 676 /* add padding if necessary */ 677 if ( byte < stop ) { 678 for ( i = 0; byte + i < stop; i++ ) { 679 buf[i] = byte[i]; 680 } 681 for ( pad = 0; i < 3; i++, pad++ ) { 682 buf[i] = '\0'; 683 } 684 byte = buf; 685 bits = (byte[0] & 0xff) << 16; 686 bits |= (byte[1] & 0xff) << 8; 687 bits |= (byte[2] & 0xff); 688 689 for ( i = 0; i < 4; i++, len++, bits <<= 6 ) { 690 if ( len - LDIF_KLUDGE > wrap ) { 691 *(*out)++ = '\n'; 692 *(*out)++ = ' '; 693 len = 1; 694 } 695 696 if( i + pad < 4 ) { 697 /* get b64 digit from low order 6 bits */ 698 *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ]; 699 } else { 700 *(*out)++ = '='; 701 } 702 } 703 } 704 *(*out)++ = '\n'; 705} 706 707 708/* 709 * ldif_type_and_value return BER malloc'd, zero-terminated LDIF line 710 */ 711 712/* NOTE: only preserved for binary compatibility */ 713char * 714ldif_put( 715 int type, 716 LDAP_CONST char *name, 717 LDAP_CONST char *val, 718 ber_len_t vlen ) 719{ 720 return ldif_put_wrap( type, name, val, vlen, LDIF_LINE_WIDTH ); 721} 722 723char * 724ldif_put_wrap( 725 int type, 726 LDAP_CONST char *name, 727 LDAP_CONST char *val, 728 ber_len_t vlen, 729 ber_len_t wrap ) 730{ 731 char *buf, *p; 732 ber_len_t nlen; 733 734 nlen = ( name != NULL ) ? strlen( name ) : 0; 735 736 buf = (char *) ber_memalloc( LDIF_SIZE_NEEDED_WRAP( nlen, vlen, wrap ) + 1 ); 737 738 if ( buf == NULL ) { 739 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, 740 _("ldif_type_and_value: malloc failed!")); 741 return NULL; 742 } 743 744 p = buf; 745 ldif_sput_wrap( &p, type, name, val, vlen, wrap ); 746 *p = '\0'; 747 748 return( buf ); 749} 750 751int ldif_is_not_printable( 752 LDAP_CONST char *val, 753 ber_len_t vlen ) 754{ 755 if( vlen == 0 || val == NULL ) { 756 return -1; 757 } 758 759 if( isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' && 760 isgraph( (unsigned char) val[vlen-1] ) ) 761 { 762 ber_len_t i; 763 764 for ( i = 0; val[i]; i++ ) { 765 if ( !isascii( val[i] ) || !isprint( (unsigned char) val[i] ) ) { 766 return 1; 767 } 768 } 769 770 return 0; 771 } 772 773 return 1; 774} 775 776LDIFFP * 777ldif_open( 778 LDAP_CONST char *file, 779 LDAP_CONST char *mode 780) 781{ 782 FILE *fp = fopen( file, mode ); 783 LDIFFP *lfp = NULL; 784 785 if ( fp ) { 786 lfp = ber_memalloc( sizeof( LDIFFP )); 787 lfp->fp = fp; 788 lfp->prev = NULL; 789 } 790 return lfp; 791} 792 793void 794ldif_close( 795 LDIFFP *lfp 796) 797{ 798 LDIFFP *prev; 799 800 while ( lfp ) { 801 fclose( lfp->fp ); 802 prev = lfp->prev; 803 ber_memfree( lfp ); 804 lfp = prev; 805 } 806} 807 808#define LDIF_MAXLINE 4096 809 810/* 811 * ldif_read_record - read an ldif record. Return 1 for success, 0 for EOF, 812 * -1 for error. 813 */ 814int 815ldif_read_record( 816 LDIFFP *lfp, 817 int *lno, /* ptr to line number counter */ 818 char **bufp, /* ptr to malloced output buffer */ 819 int *buflenp ) /* ptr to length of *bufp */ 820{ 821 char linebuf[LDIF_MAXLINE], *line, *nbufp; 822 ber_len_t lcur = 0, len, linesize; 823 int last_ch = '\n', found_entry = 0, stop, top_comment = 0; 824 825 line = linebuf; 826 linesize = sizeof( linebuf ); 827 828 for ( stop = 0; !stop; last_ch = line[len-1] ) { 829 /* If we're at the end of this file, see if we should pop 830 * back to a previous file. (return from an include) 831 */ 832 while ( feof( lfp->fp )) { 833 if ( lfp->prev ) { 834 LDIFFP *tmp = lfp->prev; 835 fclose( lfp->fp ); 836 *lfp = *tmp; 837 ber_memfree( tmp ); 838 } else { 839 stop = 1; 840 break; 841 } 842 } 843 if ( stop ) 844 break; 845 846 if ( fgets( line, linesize, lfp->fp ) == NULL ) { 847 stop = 1; 848 /* Add \n in case the file does not end with newline */ 849 line = "\n"; 850 } 851 len = strlen( line ); 852 853 if ( last_ch == '\n' ) { 854 (*lno)++; 855 856 if ( line[0] == '\n' || 857 ( line[0] == '\r' && line[1] == '\n' )) { 858 if ( !found_entry ) { 859 lcur = 0; 860 top_comment = 0; 861 continue; 862 } 863 break; 864 } 865 866 if ( !found_entry ) { 867 if ( line[0] == '#' ) { 868 top_comment = 1; 869 } else if ( ! ( top_comment && line[0] == ' ' ) ) { 870 /* Found a new entry */ 871 found_entry = 1; 872 873 if ( isdigit( (unsigned char) line[0] ) ) { 874 /* skip index */ 875 continue; 876 } 877 if ( !strncasecmp( line, "include:", 878 STRLENOF("include:"))) { 879 FILE *fp2; 880 char *ptr; 881 found_entry = 0; 882 883 if ( line[len-1] == '\n' ) { 884 len--; 885 line[len] = '\0'; 886 } 887 if ( line[len-1] == '\r' ) { 888 len--; 889 line[len] = '\0'; 890 } 891 892 ptr = line + STRLENOF("include:"); 893 while (isspace((unsigned char) *ptr)) ptr++; 894 fp2 = ldif_open_url( ptr ); 895 if ( fp2 ) { 896 LDIFFP *lnew = ber_memalloc( sizeof( LDIFFP )); 897 if ( lnew == NULL ) { 898 fclose( fp2 ); 899 return 0; 900 } 901 lnew->prev = lfp->prev; 902 lnew->fp = lfp->fp; 903 lfp->prev = lnew; 904 lfp->fp = fp2; 905 line[len] = '\n'; 906 len++; 907 continue; 908 } else { 909 /* We failed to open the file, this should 910 * be reported as an error somehow. 911 */ 912 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, 913 _("ldif_read_record: include %s failed\n"), ptr ); 914 return -1; 915 } 916 } 917 } 918 } 919 } 920 921 if ( *buflenp - lcur <= len ) { 922 *buflenp += len + LDIF_MAXLINE; 923 nbufp = ber_memrealloc( *bufp, *buflenp ); 924 if( nbufp == NULL ) { 925 return 0; 926 } 927 *bufp = nbufp; 928 } 929 strcpy( *bufp + lcur, line ); 930 lcur += len; 931 } 932 933 return( found_entry ); 934} 935