ldif.c revision 1.1.1.3
1/* $NetBSD: ldif.c,v 1.1.1.3 2010/12/12 15:22:08 adam Exp $ */ 2 3/* ldif.c - routines for dealing with LDIF files */ 4/* OpenLDAP: pkg/ldap/libraries/liblutil/ldif.c,v 1.15.2.9 2010/04/13 20:23:06 kurt Exp */ 5/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2010 The OpenLDAP Foundation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18/* Portions Copyright (c) 1992-1996 Regents of the University of Michigan. 19 * All rights reserved. 20 * 21 * Redistribution and use in source and binary forms are permitted 22 * provided that this notice is preserved and that due credit is given 23 * to the University of Michigan at Ann Arbor. The name of the 24 * University may not be used to endorse or promote products derived 25 * from this software without specific prior written permission. This 26 * software is provided ``as is'' without express or implied warranty. 27 */ 28/* This work was originally developed by the University of Michigan 29 * and distributed as part of U-MICH LDAP. 30 */ 31 32#include "portable.h" 33 34#include <stdio.h> 35 36#include <ac/stdlib.h> 37#include <ac/ctype.h> 38 39#include <ac/string.h> 40#include <ac/socket.h> 41#include <ac/time.h> 42 43int ldif_debug = 0; 44 45#include "ldap_log.h" 46#include "lber_pvt.h" 47#include "ldif.h" 48 49#define RIGHT2 0x03 50#define RIGHT4 0x0f 51#define CONTINUED_LINE_MARKER '\r' 52 53#ifdef CSRIMALLOC 54#define ber_memalloc malloc 55#define ber_memcalloc calloc 56#define ber_memrealloc realloc 57#define ber_strdup strdup 58#endif 59 60static const char nib2b64[0x40] = 61 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 62 63static const unsigned char b642nib[0x80] = { 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, 0xff, 0xff, 0xff, 0xff, 0xff, 68 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 69 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, 70 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 71 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 72 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 73 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 74 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 75 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 76 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 77 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 78 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 79 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff 80}; 81 82/* 83 * ldif_parse_line - takes a line of the form "type:[:] value" and splits it 84 * into components "type" and "value". if a double colon separates type from 85 * value, then value is encoded in base 64, and parse_line un-decodes it 86 * (in place) before returning. The type and value are stored in malloc'd 87 * memory which must be freed by the caller. 88 * 89 * ldif_parse_line2 - operates in-place on input buffer, returning type 90 * in-place. Will return value in-place if possible, (must malloc for 91 * fetched URLs). If freeval is NULL, all return data will be malloc'd 92 * and the input line will be unmodified. Otherwise freeval is set to 93 * True if the value was malloc'd. 94 */ 95 96int 97ldif_parse_line( 98 LDAP_CONST char *line, 99 char **typep, 100 char **valuep, 101 ber_len_t *vlenp 102) 103{ 104 struct berval type, value; 105 int rc = ldif_parse_line2( (char *)line, &type, &value, NULL ); 106 107 *typep = type.bv_val; 108 *valuep = value.bv_val; 109 *vlenp = value.bv_len; 110 return rc; 111} 112 113int 114ldif_parse_line2( 115 char *line, 116 struct berval *type, 117 struct berval *value, 118 int *freeval 119) 120{ 121 char *s, *p, *d; 122 char nib; 123 int b64, url; 124 125 BER_BVZERO( type ); 126 BER_BVZERO( value ); 127 128 /* skip any leading space */ 129 while ( isspace( (unsigned char) *line ) ) { 130 line++; 131 } 132 133 if ( freeval ) { 134 *freeval = 0; 135 } else { 136 line = ber_strdup( line ); 137 138 if( line == NULL ) { 139 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, 140 _("ldif_parse_line: line malloc failed\n")); 141 return( -1 ); 142 } 143 } 144 145 type->bv_val = line; 146 147 s = strchr( type->bv_val, ':' ); 148 149 if ( s == NULL ) { 150 ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, 151 _("ldif_parse_line: missing ':' after %s\n"), 152 type->bv_val ); 153 if ( !freeval ) ber_memfree( line ); 154 return( -1 ); 155 } 156 157 /* trim any space between type and : */ 158 for ( p = &s[-1]; p > type->bv_val && isspace( * (unsigned char *) p ); p-- ) { 159 *p = '\0'; 160 } 161 *s++ = '\0'; 162 type->bv_len = s - type->bv_val - 1; 163 164 url = 0; 165 b64 = 0; 166 167 if ( *s == '<' ) { 168 s++; 169 url = 1; 170 171 } else if ( *s == ':' ) { 172 /* base 64 encoded value */ 173 s++; 174 b64 = 1; 175 } 176 177 /* skip space between : and value */ 178 while ( isspace( (unsigned char) *s ) ) { 179 s++; 180 } 181 182 /* check for continued line markers that should be deleted */ 183 for ( p = s, d = s; *p; p++ ) { 184 if ( *p != CONTINUED_LINE_MARKER ) 185 *d++ = *p; 186 } 187 *d = '\0'; 188 189 if ( b64 ) { 190 char *byte = s; 191 192 if ( *s == '\0' ) { 193 /* no value is present, error out */ 194 ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, 195 _("ldif_parse_line: %s missing base64 value\n"), 196 type->bv_val ); 197 if ( !freeval ) ber_memfree( line ); 198 return( -1 ); 199 } 200 201 byte = value->bv_val = s; 202 203 for ( p = s, value->bv_len = 0; p < d; p += 4, value->bv_len += 3 ) { 204 int i; 205 for ( i = 0; i < 4; i++ ) { 206 if ( p[i] != '=' && (p[i] & 0x80 || 207 b642nib[ p[i] & 0x7f ] > 0x3f) ) { 208 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, 209 _("ldif_parse_line: %s: invalid base64 encoding" 210 " char (%c) 0x%x\n"), 211 type->bv_val, p[i], p[i] ); 212 if ( !freeval ) ber_memfree( line ); 213 return( -1 ); 214 } 215 } 216 217 /* first digit */ 218 nib = b642nib[ p[0] & 0x7f ]; 219 byte[0] = nib << 2; 220 /* second digit */ 221 nib = b642nib[ p[1] & 0x7f ]; 222 byte[0] |= nib >> 4; 223 byte[1] = (nib & RIGHT4) << 4; 224 /* third digit */ 225 if ( p[2] == '=' ) { 226 value->bv_len += 1; 227 break; 228 } 229 nib = b642nib[ p[2] & 0x7f ]; 230 byte[1] |= nib >> 2; 231 byte[2] = (nib & RIGHT2) << 6; 232 /* fourth digit */ 233 if ( p[3] == '=' ) { 234 value->bv_len += 2; 235 break; 236 } 237 nib = b642nib[ p[3] & 0x7f ]; 238 byte[2] |= nib; 239 240 byte += 3; 241 } 242 s[ value->bv_len ] = '\0'; 243 244 } else if ( url ) { 245 if ( *s == '\0' ) { 246 /* no value is present, error out */ 247 ber_pvt_log_printf( LDAP_DEBUG_PARSE, ldif_debug, 248 _("ldif_parse_line: %s missing URL value\n"), 249 type->bv_val ); 250 if ( !freeval ) ber_memfree( line ); 251 return( -1 ); 252 } 253 254 if( ldif_fetch_url( s, &value->bv_val, &value->bv_len ) ) { 255 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, 256 _("ldif_parse_line: %s: URL \"%s\" fetch failed\n"), 257 type->bv_val, s ); 258 if ( !freeval ) ber_memfree( line ); 259 return( -1 ); 260 } 261 if ( freeval ) *freeval = 1; 262 263 } else { 264 value->bv_val = s; 265 value->bv_len = (int) (d - s); 266 } 267 268 if ( !freeval ) { 269 struct berval bv = *type; 270 271 ber_dupbv( type, &bv ); 272 273 if( BER_BVISNULL( type )) { 274 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, 275 _("ldif_parse_line: type malloc failed\n")); 276 if( url ) ber_memfree( value->bv_val ); 277 ber_memfree( line ); 278 return( -1 ); 279 } 280 281 if( !url ) { 282 bv = *value; 283 ber_dupbv( value, &bv ); 284 if( BER_BVISNULL( value )) { 285 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, 286 _("ldif_parse_line: value malloc failed\n")); 287 ber_memfree( type->bv_val ); 288 ber_memfree( line ); 289 return( -1 ); 290 } 291 } 292 293 ber_memfree( line ); 294 } 295 296 return( 0 ); 297} 298 299/* 300 * ldif_getline - return the next "line" (minus newline) of input from a 301 * string buffer of lines separated by newlines, terminated by \n\n 302 * or \0. this routine handles continued lines, bundling them into 303 * a single big line before returning. if a line begins with a white 304 * space character, it is a continuation of the previous line. the white 305 * space character (nb: only one char), and preceeding newline are changed 306 * into CONTINUED_LINE_MARKER chars, to be deleted later by the 307 * ldif_parse_line() routine above. 308 * 309 * ldif_getline will skip over any line which starts '#'. 310 * 311 * ldif_getline takes a pointer to a pointer to the buffer on the first call, 312 * which it updates and must be supplied on subsequent calls. 313 */ 314 315int 316ldif_countlines( LDAP_CONST char *buf ) 317{ 318 char *nl; 319 int ret = 0; 320 321 if ( !buf ) return ret; 322 323 for ( nl = strchr(buf, '\n'); nl; nl = strchr(nl, '\n') ) { 324 nl++; 325 if ( *nl != ' ' ) ret++; 326 } 327 return ret; 328} 329 330char * 331ldif_getline( char **next ) 332{ 333 char *line; 334 335 do { 336 if ( *next == NULL || **next == '\n' || **next == '\0' ) { 337 return( NULL ); 338 } 339 340 line = *next; 341 342 while ( (*next = strchr( *next, '\n' )) != NULL ) { 343#if CONTINUED_LINE_MARKER != '\r' 344 if ( (*next)[-1] == '\r' ) { 345 (*next)[-1] = CONTINUED_LINE_MARKER; 346 } 347#endif 348 349 if ( (*next)[1] != ' ' ) { 350 if ( (*next)[1] == '\r' && (*next)[2] == '\n' ) { 351 *(*next)++ = '\0'; 352 } 353 *(*next)++ = '\0'; 354 break; 355 } 356 357 **next = CONTINUED_LINE_MARKER; 358 (*next)[1] = CONTINUED_LINE_MARKER; 359 (*next)++; 360 } 361 } while( *line == '#' ); 362 363 return( line ); 364} 365 366/* 367 * name and OID of attributeTypes that must be base64 encoded in any case 368 */ 369typedef struct must_b64_encode_s { 370 struct berval name; 371 struct berval oid; 372} must_b64_encode_s; 373 374static must_b64_encode_s default_must_b64_encode[] = { 375 { BER_BVC( "userPassword" ), BER_BVC( "2.5.4.35" ) }, 376 { BER_BVNULL, BER_BVNULL } 377}; 378 379static must_b64_encode_s *must_b64_encode = default_must_b64_encode; 380 381/* 382 * register name and OID of attributeTypes that must always be base64 383 * encoded 384 * 385 * NOTE: this routine mallocs memory in a static struct which must 386 * be explicitly freed when no longer required 387 */ 388int 389ldif_must_b64_encode_register( LDAP_CONST char *name, LDAP_CONST char *oid ) 390{ 391 int i; 392 ber_len_t len; 393 394 assert( must_b64_encode != NULL ); 395 assert( name != NULL ); 396 assert( oid != NULL ); 397 398 len = strlen( name ); 399 400 for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { 401 if ( len != must_b64_encode[i].name.bv_len ) { 402 continue; 403 } 404 405 if ( strcasecmp( name, must_b64_encode[i].name.bv_val ) == 0 ) { 406 break; 407 } 408 } 409 410 if ( !BER_BVISNULL( &must_b64_encode[i].name ) ) { 411 return 1; 412 } 413 414 for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) 415 /* just count */ ; 416 417 if ( must_b64_encode == default_must_b64_encode ) { 418 must_b64_encode = ber_memalloc( sizeof( must_b64_encode_s ) * ( i + 2 ) ); 419 420 for ( i = 0; !BER_BVISNULL( &default_must_b64_encode[i].name ); i++ ) { 421 ber_dupbv( &must_b64_encode[i].name, &default_must_b64_encode[i].name ); 422 ber_dupbv( &must_b64_encode[i].oid, &default_must_b64_encode[i].oid ); 423 } 424 425 } else { 426 must_b64_encode_s *tmp; 427 428 tmp = ber_memrealloc( must_b64_encode, 429 sizeof( must_b64_encode_s ) * ( i + 2 ) ); 430 if ( tmp == NULL ) { 431 return 1; 432 } 433 must_b64_encode = tmp; 434 } 435 436 ber_str2bv( name, len, 1, &must_b64_encode[i].name ); 437 ber_str2bv( oid, 0, 1, &must_b64_encode[i].oid ); 438 439 BER_BVZERO( &must_b64_encode[i + 1].name ); 440 441 return 0; 442} 443 444void 445ldif_must_b64_encode_release( void ) 446{ 447 int i; 448 449 assert( must_b64_encode != NULL ); 450 451 if ( must_b64_encode == default_must_b64_encode ) { 452 return; 453 } 454 455 for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { 456 ber_memfree( must_b64_encode[i].name.bv_val ); 457 ber_memfree( must_b64_encode[i].oid.bv_val ); 458 } 459 460 ber_memfree( must_b64_encode ); 461 462 must_b64_encode = default_must_b64_encode; 463} 464 465/* 466 * returns 1 iff the string corresponds to the name or the OID of any 467 * of the attributeTypes listed in must_b64_encode 468 */ 469static int 470ldif_must_b64_encode( LDAP_CONST char *s ) 471{ 472 int i; 473 struct berval bv; 474 475 assert( must_b64_encode != NULL ); 476 assert( s != NULL ); 477 478 ber_str2bv( s, 0, 0, &bv ); 479 480 for ( i = 0; !BER_BVISNULL( &must_b64_encode[i].name ); i++ ) { 481 if ( ber_bvstrcasecmp( &must_b64_encode[i].name, &bv ) == 0 482 || ber_bvcmp( &must_b64_encode[i].oid, &bv ) == 0 ) 483 { 484 return 1; 485 } 486 } 487 488 return 0; 489} 490 491/* compatibility with U-Mich off by one bug */ 492#define LDIF_KLUDGE 1 493 494void 495ldif_sput( 496 char **out, 497 int type, 498 LDAP_CONST char *name, 499 LDAP_CONST char *val, 500 ber_len_t vlen ) 501{ 502 const unsigned char *byte, *stop; 503 unsigned char buf[3]; 504 unsigned long bits; 505 char *save; 506 int pad; 507 int namelen = 0; 508 509 ber_len_t savelen; 510 ber_len_t len=0; 511 ber_len_t i; 512 513 /* prefix */ 514 switch( type ) { 515 case LDIF_PUT_COMMENT: 516 *(*out)++ = '#'; 517 len++; 518 519 if( vlen ) { 520 *(*out)++ = ' '; 521 len++; 522 } 523 524 break; 525 526 case LDIF_PUT_SEP: 527 *(*out)++ = '\n'; 528 return; 529 } 530 531 /* name (attribute type) */ 532 if( name != NULL ) { 533 /* put the name + ":" */ 534 namelen = strlen(name); 535 strcpy(*out, name); 536 *out += namelen; 537 len += namelen; 538 539 if( type != LDIF_PUT_COMMENT ) { 540 *(*out)++ = ':'; 541 len++; 542 } 543 544 } 545#ifdef LDAP_DEBUG 546 else { 547 assert( type == LDIF_PUT_COMMENT ); 548 } 549#endif 550 551 if( vlen == 0 ) { 552 *(*out)++ = '\n'; 553 return; 554 } 555 556 switch( type ) { 557 case LDIF_PUT_NOVALUE: 558 *(*out)++ = '\n'; 559 return; 560 561 case LDIF_PUT_URL: /* url value */ 562 *(*out)++ = '<'; 563 len++; 564 break; 565 566 case LDIF_PUT_B64: /* base64 value */ 567 *(*out)++ = ':'; 568 len++; 569 break; 570 } 571 572 switch( type ) { 573 case LDIF_PUT_TEXT: 574 case LDIF_PUT_URL: 575 case LDIF_PUT_B64: 576 *(*out)++ = ' '; 577 len++; 578 /* fall-thru */ 579 580 case LDIF_PUT_COMMENT: 581 /* pre-encoded names */ 582 for ( i=0; i < vlen; i++ ) { 583 if ( len > LDIF_LINE_WIDTH ) { 584 *(*out)++ = '\n'; 585 *(*out)++ = ' '; 586 len = 1; 587 } 588 589 *(*out)++ = val[i]; 590 len++; 591 } 592 *(*out)++ = '\n'; 593 return; 594 } 595 596 save = *out; 597 savelen = len; 598 599 *(*out)++ = ' '; 600 len++; 601 602 stop = (const unsigned char *) (val + vlen); 603 604 if ( type == LDIF_PUT_VALUE 605 && isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' 606 && isgraph( (unsigned char) val[vlen-1] ) 607#ifndef LDAP_BINARY_DEBUG 608 && strstr( name, ";binary" ) == NULL 609#endif 610#ifndef LDAP_PASSWD_DEBUG 611 && !ldif_must_b64_encode( name ) 612#endif 613 ) { 614 int b64 = 0; 615 616 for ( byte = (const unsigned char *) val; byte < stop; 617 byte++, len++ ) 618 { 619 if ( !isascii( *byte ) || !isprint( *byte ) ) { 620 b64 = 1; 621 break; 622 } 623 if ( len > LDIF_LINE_WIDTH+LDIF_KLUDGE ) { 624 *(*out)++ = '\n'; 625 *(*out)++ = ' '; 626 len = 1; 627 } 628 *(*out)++ = *byte; 629 } 630 631 if( !b64 ) { 632 *(*out)++ = '\n'; 633 return; 634 } 635 } 636 637 *out = save; 638 *(*out)++ = ':'; 639 *(*out)++ = ' '; 640 len = savelen + 2; 641 642 /* convert to base 64 (3 bytes => 4 base 64 digits) */ 643 for ( byte = (const unsigned char *) val; 644 byte < stop - 2; 645 byte += 3 ) 646 { 647 bits = (byte[0] & 0xff) << 16; 648 bits |= (byte[1] & 0xff) << 8; 649 bits |= (byte[2] & 0xff); 650 651 for ( i = 0; i < 4; i++, len++, bits <<= 6 ) { 652 if ( len > LDIF_LINE_WIDTH+LDIF_KLUDGE ) { 653 *(*out)++ = '\n'; 654 *(*out)++ = ' '; 655 len = 1; 656 } 657 658 /* get b64 digit from high order 6 bits */ 659 *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ]; 660 } 661 } 662 663 /* add padding if necessary */ 664 if ( byte < stop ) { 665 for ( i = 0; byte + i < stop; i++ ) { 666 buf[i] = byte[i]; 667 } 668 for ( pad = 0; i < 3; i++, pad++ ) { 669 buf[i] = '\0'; 670 } 671 byte = buf; 672 bits = (byte[0] & 0xff) << 16; 673 bits |= (byte[1] & 0xff) << 8; 674 bits |= (byte[2] & 0xff); 675 676 for ( i = 0; i < 4; i++, len++, bits <<= 6 ) { 677 if ( len > LDIF_LINE_WIDTH+LDIF_KLUDGE ) { 678 *(*out)++ = '\n'; 679 *(*out)++ = ' '; 680 len = 1; 681 } 682 683 if( i + pad < 4 ) { 684 /* get b64 digit from low order 6 bits */ 685 *(*out)++ = nib2b64[ (bits & 0xfc0000L) >> 18 ]; 686 } else { 687 *(*out)++ = '='; 688 } 689 } 690 } 691 *(*out)++ = '\n'; 692} 693 694 695/* 696 * ldif_type_and_value return BER malloc'd, zero-terminated LDIF line 697 */ 698char * 699ldif_put( 700 int type, 701 LDAP_CONST char *name, 702 LDAP_CONST char *val, 703 ber_len_t vlen ) 704{ 705 char *buf, *p; 706 ber_len_t nlen; 707 708 nlen = ( name != NULL ) ? strlen( name ) : 0; 709 710 buf = (char *) ber_memalloc( LDIF_SIZE_NEEDED( nlen, vlen ) + 1 ); 711 712 if ( buf == NULL ) { 713 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, 714 _("ldif_type_and_value: malloc failed!")); 715 return NULL; 716 } 717 718 p = buf; 719 ldif_sput( &p, type, name, val, vlen ); 720 *p = '\0'; 721 722 return( buf ); 723} 724 725int ldif_is_not_printable( 726 LDAP_CONST char *val, 727 ber_len_t vlen ) 728{ 729 if( vlen == 0 || val == NULL ) { 730 return -1; 731 } 732 733 if( isgraph( (unsigned char) val[0] ) && val[0] != ':' && val[0] != '<' && 734 isgraph( (unsigned char) val[vlen-1] ) ) 735 { 736 ber_len_t i; 737 738 for ( i = 0; val[i]; i++ ) { 739 if ( !isascii( val[i] ) || !isprint( (unsigned char) val[i] ) ) { 740 return 1; 741 } 742 } 743 744 return 0; 745 } 746 747 return 1; 748} 749 750LDIFFP * 751ldif_open( 752 LDAP_CONST char *file, 753 LDAP_CONST char *mode 754) 755{ 756 FILE *fp = fopen( file, mode ); 757 LDIFFP *lfp = NULL; 758 759 if ( fp ) { 760 lfp = ber_memalloc( sizeof( LDIFFP )); 761 lfp->fp = fp; 762 lfp->prev = NULL; 763 } 764 return lfp; 765} 766 767void 768ldif_close( 769 LDIFFP *lfp 770) 771{ 772 LDIFFP *prev; 773 774 while ( lfp ) { 775 fclose( lfp->fp ); 776 prev = lfp->prev; 777 ber_memfree( lfp ); 778 lfp = prev; 779 } 780} 781 782#define LDIF_MAXLINE 4096 783 784/* 785 * ldif_read_record - read an ldif record. Return 1 for success, 0 for EOF, 786 * -1 for error. 787 */ 788int 789ldif_read_record( 790 LDIFFP *lfp, 791 int *lno, /* ptr to line number counter */ 792 char **bufp, /* ptr to malloced output buffer */ 793 int *buflenp ) /* ptr to length of *bufp */ 794{ 795 char linebuf[LDIF_MAXLINE], *line, *nbufp; 796 ber_len_t lcur = 0, len, linesize; 797 int last_ch = '\n', found_entry = 0, stop, top_comment = 0; 798 799 line = linebuf; 800 linesize = sizeof( linebuf ); 801 802 for ( stop = 0; !stop; last_ch = line[len-1] ) { 803 /* If we're at the end of this file, see if we should pop 804 * back to a previous file. (return from an include) 805 */ 806 while ( feof( lfp->fp )) { 807 if ( lfp->prev ) { 808 LDIFFP *tmp = lfp->prev; 809 fclose( lfp->fp ); 810 *lfp = *tmp; 811 ber_memfree( tmp ); 812 } else { 813 stop = 1; 814 break; 815 } 816 } 817 if ( stop ) 818 break; 819 820 if ( fgets( line, linesize, lfp->fp ) == NULL ) { 821 stop = 1; 822 /* Add \n in case the file does not end with newline */ 823 line = "\n"; 824 } 825 len = strlen( line ); 826 827 if ( last_ch == '\n' ) { 828 (*lno)++; 829 830 if ( line[0] == '\n' || 831 ( line[0] == '\r' && line[1] == '\n' )) { 832 if ( !found_entry ) { 833 lcur = 0; 834 top_comment = 0; 835 continue; 836 } 837 break; 838 } 839 840 if ( !found_entry ) { 841 if ( line[0] == '#' ) { 842 top_comment = 1; 843 } else if ( ! ( top_comment && line[0] == ' ' ) ) { 844 /* Found a new entry */ 845 found_entry = 1; 846 847 if ( isdigit( (unsigned char) line[0] ) ) { 848 /* skip index */ 849 continue; 850 } 851 if ( !strncasecmp( line, "include:", 852 STRLENOF("include:"))) { 853 FILE *fp2; 854 char *ptr; 855 found_entry = 0; 856 857 if ( line[len-1] == '\n' ) { 858 len--; 859 line[len] = '\0'; 860 } 861 if ( line[len-1] == '\r' ) { 862 len--; 863 line[len] = '\0'; 864 } 865 866 ptr = line + STRLENOF("include:"); 867 while (isspace((unsigned char) *ptr)) ptr++; 868 fp2 = ldif_open_url( ptr ); 869 if ( fp2 ) { 870 LDIFFP *lnew = ber_memalloc( sizeof( LDIFFP )); 871 if ( lnew == NULL ) { 872 fclose( fp2 ); 873 return 0; 874 } 875 lnew->prev = lfp->prev; 876 lnew->fp = lfp->fp; 877 lfp->prev = lnew; 878 lfp->fp = fp2; 879 line[len] = '\n'; 880 len++; 881 continue; 882 } else { 883 /* We failed to open the file, this should 884 * be reported as an error somehow. 885 */ 886 ber_pvt_log_printf( LDAP_DEBUG_ANY, ldif_debug, 887 _("ldif_read_record: include %s failed\n"), ptr ); 888 return -1; 889 } 890 } 891 } 892 } 893 } 894 895 if ( *buflenp - lcur <= len ) { 896 *buflenp += len + LDIF_MAXLINE; 897 nbufp = ber_memrealloc( *bufp, *buflenp ); 898 if( nbufp == NULL ) { 899 return 0; 900 } 901 *bufp = nbufp; 902 } 903 strcpy( *bufp + lcur, line ); 904 lcur += len; 905 } 906 907 return( found_entry ); 908} 909