1/* ldif.c - routines for dealing with LDIF files */ 2/* $OpenLDAP: pkg/ldap/libraries/liblutil/ldif.c,v 1.15.2.9 2010/04/13 20:23:06 kurt Exp $ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2010 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 492void 493ldif_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 */ 696char * 697ldif_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 723int 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 748LDIFFP * 749ldif_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 765void 766ldif_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 * -1 for error. 785 */ 786int 787ldif_read_record( 788 LDIFFP *lfp, 789 int *lno, /* ptr to line number counter */ 790 char **bufp, /* ptr to malloced output buffer */ 791 int *buflenp ) /* ptr to length of *bufp */ 792{ 793 char linebuf[LDIF_MAXLINE], *line, *nbufp; 794 ber_len_t lcur = 0, len, linesize; 795 int last_ch = '\n', found_entry = 0, stop, top_comment = 0; 796 797 line = linebuf; 798 linesize = sizeof( linebuf ); 799 800 for ( stop = 0; !stop; last_ch = line[len-1] ) { 801 /* If we're at the end of this file, see if we should pop 802 * back to a previous file. (return from an include) 803 */ 804 while ( feof( lfp->fp )) { 805 if ( lfp->prev ) { 806 LDIFFP *tmp = lfp->prev; 807 fclose( lfp->fp ); 808 *lfp = *tmp; 809 ber_memfree( tmp ); 810 } else { 811 stop = 1; 812 break; 813 } 814 } 815 if ( stop ) 816 break; 817 818 if ( fgets( line, linesize, lfp->fp ) == NULL ) { 819 stop = 1; 820 /* Add \n in case the file does not end with newline */ 821 line = "\n"; 822 } 823 len = strlen( line ); 824 825 if ( last_ch == '\n' ) { 826 (*lno)++; 827 828 if ( line[0] == '\n' || 829 ( line[0] == '\r' && line[1] == '\n' )) { 830 if ( !found_entry ) { 831 lcur = 0; 832 top_comment = 0; 833 continue; 834 } 835 break; 836 } 837 838 if ( !found_entry ) { 839 if ( line[0] == '#' ) { 840 top_comment = 1; 841 } else if ( ! ( top_comment && line[0] == ' ' ) ) { 842 /* Found a new entry */ 843 found_entry = 1; 844 845 if ( isdigit( (unsigned char) line[0] ) ) { 846 /* skip index */ 847 continue; 848 } 849 if ( !strncasecmp( line, "include:", 850 STRLENOF("include:"))) { 851 FILE *fp2; 852 char *ptr; 853 found_entry = 0; 854 855 if ( line[len-1] == '\n' ) { 856 len--; 857 line[len] = '\0'; 858 } 859 if ( line[len-1] == '\r' ) { 860 len--; 861 line[len] = '\0'; 862 } 863 864 ptr = line + STRLENOF("include:"); 865 while (isspace((unsigned char) *ptr)) ptr++; 866 fp2 = ldif_open_url( ptr ); 867 if ( fp2 ) { 868 LDIFFP *lnew = ber_memalloc( sizeof( LDIFFP )); 869 if ( lnew == NULL ) { 870 fclose( fp2 ); 871 return 0; 872 } 873 lnew->prev = lfp->prev; 874 lnew->fp = lfp->fp; 875 lfp->prev = lnew; 876 lfp->fp = fp2; 877 line[len] = '\n'; 878 len++; 879 continue; 880 } else { 881 /* We failed to open the file, this should 882 * be reported as an error somehow. 883 */ 884 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, 885 _("ldif_read_record: include %s failed\n"), ptr ); 886 return -1; 887 } 888 } 889 } 890 } 891 } 892 893 if ( *buflenp - lcur <= len ) { 894 *buflenp += len + LDIF_MAXLINE; 895 nbufp = ber_memrealloc( *bufp, *buflenp ); 896 if( nbufp == NULL ) { 897 return 0; 898 } 899 *bufp = nbufp; 900 } 901 strcpy( *bufp + lcur, line ); 902 lcur += len; 903 } 904 905 return( found_entry ); 906} 907