2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2007 Match Grun and the Claws Mail team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * Functions necessary to access LDIF files (LDAP Data Interchange Format
26 #include <glib/gi18n.h>
33 #include "addrcache.h"
38 #define LDIF_SEP_TAG ':'
39 #define LDIF_LANG_TAG ';'
43 * \return Initialized LDIF file object.
45 LdifFile *ldif_create() {
47 ldifFile = g_new0( LdifFile, 1 );
48 ldifFile->path = NULL;
49 ldifFile->file = NULL;
50 ldifFile->bufptr = ldifFile->buffer;
51 ldifFile->hashFields = g_hash_table_new( g_str_hash, g_str_equal );
52 ldifFile->tempList = NULL;
53 ldifFile->dirtyFlag = TRUE;
54 ldifFile->accessFlag = FALSE;
55 ldifFile->retVal = MGU_SUCCESS;
56 ldifFile->cbProgress = NULL;
57 ldifFile->importCount = 0;
62 * Specify full file specification of LDIF file.
63 * \param ldifFile LDIF import control object.
64 * \param value Value of access flag.
66 void ldif_set_file( LdifFile *ldifFile, const gchar *value ) {
67 g_return_if_fail( ldifFile != NULL );
69 if( ldifFile->path ) {
70 if( strcmp( ldifFile->path, value ) != 0 )
71 ldifFile->dirtyFlag = TRUE;
74 ldifFile->dirtyFlag = TRUE;
76 ldifFile->path = mgu_replace_string( ldifFile->path, value );
77 g_strstrip( ldifFile->path );
78 ldifFile->importCount = 0;
82 * Set the file access indicator.
83 * \param ldifFile LDIF import control object.
84 * \param value File specification.
86 void ldif_set_accessed( LdifFile *ldifFile, const gboolean value ) {
87 g_return_if_fail( ldifFile != NULL );
88 ldifFile->accessFlag = value;
92 * Create field record object.
93 * \return Initialized LDIF field object.
95 static Ldif_FieldRec *ldif_create_fieldrec( const gchar *field ) {
96 Ldif_FieldRec *rec = g_new0( Ldif_FieldRec, 1 );
97 rec->tagName = g_strdup( field );
99 rec->reserved = FALSE;
100 rec->selected = FALSE;
105 * Free field record object.
106 * \param rec LDIF field object.
108 static void ldif_free_fieldrec( Ldif_FieldRec *rec ) {
110 g_free( rec->tagName );
111 g_free( rec->userName );
113 rec->userName = NULL;
114 rec->reserved = FALSE;
115 rec->selected = FALSE;
121 * Set user name for field record.
122 * \param rec LDIF field object.
123 * \param value User name to set. Note that reserved fields cannot be
126 void ldif_field_set_name( Ldif_FieldRec *rec, const gchar *value ) {
127 g_return_if_fail( rec != NULL );
129 if( ! rec->reserved ) {
130 rec->userName = mgu_replace_string( rec->userName, value );
131 g_strstrip( rec->userName );
136 * Specify selection for field record.
137 * \param rec LDIF field object.
138 * \param value Set to <i>TRUE</i> to select field. Note that reserved
139 * fields cannot be unselected.
141 void ldif_field_set_selected( Ldif_FieldRec *rec, const gboolean value ) {
142 g_return_if_fail( rec != NULL );
144 if( ! rec->reserved ) {
145 rec->selected = value;
150 * Toggle selection for field record. Note that reserved fields cannot be
152 * \param rec LDIF field object.
154 void ldif_field_toggle( Ldif_FieldRec *rec ) {
155 g_return_if_fail( rec != NULL );
157 if( ! rec->reserved ) {
158 rec->selected = !rec->selected;
163 * Free hash table entry visitor function.
165 * \param value Value (the LDIF field record).
166 * \param data User data.
167 * \return <code>-1</code>.
169 static gint ldif_hash_free_vis( gpointer key, gpointer value, gpointer data ) {
170 ldif_free_fieldrec( ( Ldif_FieldRec * ) value );
177 * Free up object by releasing internal memory.
178 * \param ldifFile LDIF import control object.
180 void ldif_free( LdifFile *ldifFile ) {
181 g_return_if_fail( ldifFile != NULL );
184 if( ldifFile->file ) fclose( ldifFile->file );
186 /* Free internal stuff */
187 g_free( ldifFile->path );
189 /* Free field list */
190 g_hash_table_foreach_remove( ldifFile->hashFields, ldif_hash_free_vis, NULL );
191 g_hash_table_destroy( ldifFile->hashFields );
192 ldifFile->hashFields = NULL;
195 ldifFile->file = NULL;
196 ldifFile->path = NULL;
197 ldifFile->retVal = MGU_SUCCESS;
198 ldifFile->tempList = NULL;
199 ldifFile->dirtyFlag = FALSE;
200 ldifFile->accessFlag = FALSE;
201 ldifFile->cbProgress = NULL;
203 /* Now release file object */
208 * Open file for read.
209 * \param ldifFile LDIF import control object.
210 * \return <i>TRUE</i> if file opened successfully.
212 static gint ldif_open_file( LdifFile* ldifFile ) {
213 /* printf( "Opening file\n" ); */
214 if( ldifFile->path ) {
215 ldifFile->file = g_fopen( ldifFile->path, "rb" );
216 if( ! ldifFile->file ) {
217 /* printf( "can't open %s\n", ldifFile->path ); */
218 ldifFile->retVal = MGU_OPEN_FILE;
219 return ldifFile->retVal;
223 /* printf( "file not specified\n" ); */
224 ldifFile->retVal = MGU_NO_FILE;
225 return ldifFile->retVal;
228 /* Setup a buffer area */
229 ldifFile->buffer[0] = '\0';
230 ldifFile->bufptr = ldifFile->buffer;
231 ldifFile->retVal = MGU_SUCCESS;
232 return ldifFile->retVal;
237 * \param ldifFile LDIF import control object.
239 static void ldif_close_file( LdifFile *ldifFile ) {
240 g_return_if_fail( ldifFile != NULL );
241 if( ldifFile->file ) fclose( ldifFile->file );
242 ldifFile->file = NULL;
246 * Read line of text from file.
247 * \param ldifFile LDIF import control object.
248 * \return ptr to buffer where line starts.
250 static gchar *ldif_get_line( LdifFile *ldifFile ) {
251 gchar buf[ LDIFBUFSIZE ];
255 if( feof( ldifFile->file ) )
258 while( i < LDIFBUFSIZE-1 ) {
259 ch = fgetc( ldifFile->file );
260 if( ch == '\0' || ch == EOF ) {
261 if( i == 0 ) return NULL;
264 #if HAVE_DOSISH_SYSTEM
276 /* Return a copy of buffer */
277 return g_strdup( buf );
281 * Parse tag name from line buffer.
282 * \param line Buffer.
283 * \param flag64 Base-64 encoder flag.
284 * \return Buffer containing the tag name, or NULL if no delimiter char found.
285 * If a double delimiter (::) is found, flag64 is set.
287 static gchar *ldif_get_tagname( char* line, gboolean *flag64 ) {
294 /* Check for language tag */
295 if( *lptr == LDIF_LANG_TAG ) {
296 if( sptr == NULL ) sptr = lptr;
299 /* Check for delimiter */
300 if( *lptr == LDIF_SEP_TAG ) {
308 /* Base-64 encoding? */
309 if( * ++lptr == LDIF_SEP_TAG ) *flag64 = TRUE;
311 tag = g_strndup( line, len+1 );
321 * Parse tag value from line buffer.
322 * \param line Buffer.
323 * \return Buffer containing the tag value. Empty string is returned if
324 * no delimiter char found.
326 static gchar *ldif_get_tagvalue( gchar* line ) {
332 for( lptr = line; *lptr; lptr++ ) {
333 if( *lptr == LDIF_SEP_TAG ) {
339 if( *start == LDIF_SEP_TAG ) start++;
341 value = g_strndup( start, len+1 );
345 /* Ensure that we get an empty string */
346 value = g_strndup( "", 1 );
353 * Parsed address data record.
355 typedef struct _Ldif_ParsedRec_ Ldif_ParsedRec;
356 struct _Ldif_ParsedRec_ {
367 * User attribute data record.
369 typedef struct _Ldif_UserAttr_ Ldif_UserAttr;
370 struct _Ldif_UserAttr_ {
376 * Build an address list entry and append to list of address items in the
377 * address cache. Name is formatted as "<first-name> <last-name>".
378 * \param ldifFile LDIF import control object.
379 * \param rec LDIF field object.
380 * \param cache Address cache to be populated with data.
382 static void ldif_build_items(
383 LdifFile *ldifFile, Ldif_ParsedRec *rec, AddressCache *cache )
388 gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
389 gchar *nickName = NULL;
390 gint iLen = 0, iLenT = 0;
394 nodeAddress = rec->listAddress;
395 if( nodeAddress == NULL ) return;
397 /* Find longest first name in list */
398 nodeFirst = rec->listFName;
400 if( firstName == NULL ) {
401 firstName = nodeFirst->data;
402 iLen = strlen( firstName );
405 if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
406 firstName = nodeFirst->data;
410 nodeFirst = g_slist_next( nodeFirst );
414 if( rec->listLName ) {
415 lastName = rec->listLName->data;
420 fullName = g_strdup_printf(
421 "%s %s", firstName, lastName );
424 fullName = g_strdup_printf( "%s", firstName );
429 fullName = g_strdup_printf( "%s", lastName );
433 if (!fullName || strlen(fullName) == 0) {
437 fullName = g_strdup(rec->listCName->data);
441 g_strchug( fullName ); g_strchomp( fullName );
444 if( rec->listNName ) {
445 nickName = rec->listNName->data;
448 person = addritem_create_item_person();
449 addritem_person_set_common_name( person, fullName );
450 addritem_person_set_first_name( person, firstName );
451 addritem_person_set_last_name( person, lastName );
452 addritem_person_set_nick_name( person, nickName );
453 addrcache_id_person( cache, person );
454 addrcache_add_person( cache, person );
455 ++ldifFile->importCount;
457 /* Add address item */
458 while( nodeAddress ) {
459 email = addritem_create_item_email();
460 addritem_email_set_address( email, nodeAddress->data );
461 addrcache_id_email( cache, email );
462 addrcache_person_add_email( cache, person, email );
463 nodeAddress = g_slist_next( nodeAddress );
466 fullName = firstName = lastName = NULL;
468 /* Add user attributes */
469 nodeAttr = rec->userAttr;
471 Ldif_UserAttr *attr = nodeAttr->data;
472 UserAttribute *attrib = addritem_create_attribute();
473 addritem_attrib_set_name( attrib, attr->name );
474 addritem_attrib_set_value( attrib, attr->value );
475 addritem_person_add_attribute( person, attrib );
476 nodeAttr = g_slist_next( nodeAttr );
482 * Add selected field as user attribute.
483 * \param rec LDIF field object.
484 * \param tagName LDIF tag name.
485 * \param tagValue Data value.
486 * \param hashField Hash table to populate.
488 static void ldif_add_user_attr(
489 Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue,
490 GHashTable *hashField )
492 Ldif_FieldRec *fld = NULL;
493 Ldif_UserAttr *attr = NULL;
496 fld = g_hash_table_lookup( hashField, tagName );
498 if( ! fld->selected ) return;
501 if( fld->userName ) {
502 name = fld->userName;
504 attr = g_new0( Ldif_UserAttr, 1 );
505 attr->name = g_strdup( name );
506 attr->value = g_strdup( tagValue );
507 rec->userAttr = g_slist_append( rec->userAttr, attr );
512 * Add value to parsed data.
513 * \param rec LDIF field object.
514 * \param tagName LDIF tag name.
515 * \param tagValue Data value.
516 * \param hashField Hash table to populate.
518 static void ldif_add_value(
519 Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue,
520 GHashTable *hashField )
524 nm = g_strdup( tagName );
527 val = g_strdup( tagValue );
530 val = g_strdup( "" );
534 if( g_utf8_collate( nm, LDIF_TAG_COMMONNAME ) == 0 ) {
535 rec->listCName = g_slist_append( rec->listCName, val );
537 else if( g_utf8_collate( nm, LDIF_TAG_FIRSTNAME ) == 0 ) {
538 rec->listFName = g_slist_append( rec->listFName, val );
540 else if( g_utf8_collate( nm, LDIF_TAG_LASTNAME ) == 0 ) {
541 rec->listLName = g_slist_append( rec->listLName, val );
543 else if( g_utf8_collate( nm, LDIF_TAG_NICKNAME ) == 0 ) {
544 rec->listNName = g_slist_append( rec->listNName, val );
546 else if( g_utf8_collate( nm, LDIF_TAG_EMAIL ) == 0 ) {
547 rec->listAddress = g_slist_append( rec->listAddress, val );
550 /* Add field as user attribute */
551 ldif_add_user_attr( rec, tagName, tagValue, hashField );
557 * Clear parsed data record.
558 * \param rec LDIF field object.
560 static void ldif_clear_rec( Ldif_ParsedRec *rec ) {
563 /* Free up user attributes */
564 list = rec->userAttr;
566 Ldif_UserAttr *attr = list->data;
567 g_free( attr->name );
568 g_free( attr->value );
570 list = g_slist_next( list );
572 g_slist_free( rec->userAttr );
574 g_slist_free( rec->listCName );
575 g_slist_free( rec->listFName );
576 g_slist_free( rec->listLName );
577 g_slist_free( rec->listNName );
578 g_slist_free( rec->listAddress );
579 g_slist_free( rec->listID );
581 rec->userAttr = NULL;
582 rec->listCName = NULL;
583 rec->listFName = NULL;
584 rec->listLName = NULL;
585 rec->listNName = NULL;
586 rec->listAddress = NULL;
591 * Read file data into address cache.
592 * Note that one LDIF record identifies one entity uniquely with the
593 * distinguished name (dn) tag. Each person can have multiple E-Mail
594 * addresses. Also, each person can have many common name (cn) tags.
596 * \param ldifFile LDIF import control object.
597 * \param cache Address cache to be populated with data.
599 static void ldif_read_file( LdifFile *ldifFile, AddressCache *cache ) {
600 gchar *tagName = NULL, *tagValue = NULL;
601 gchar *lastTag = NULL, *fullValue = NULL;
602 GSList *listValue = NULL;
603 gboolean flagEOF = FALSE, flagEOR = FALSE;
604 gboolean flag64 = FALSE, last64 = FALSE;
608 GHashTable *hashField;
610 hashField = ldifFile->hashFields;
611 rec = g_new0( Ldif_ParsedRec, 1 );
612 ldif_clear_rec( rec );
614 /* Find EOF for progress indicator */
615 fseek( ldifFile->file, 0L, SEEK_END );
616 posEnd = ftell( ldifFile->file );
617 fseek( ldifFile->file, 0L, SEEK_SET );
620 gchar *line = ldif_get_line( ldifFile );
622 posCur = ftell( ldifFile->file );
623 if( ldifFile->cbProgress ) {
624 /* Call progress indicator */
625 ( ldifFile->cbProgress ) ( ldifFile, & posEnd, & posCur );
630 flagEOF = flagEOR = TRUE;
632 else if( *line == '\0' ) {
637 /* EOR, Output address data */
640 fullValue = mgu_list_coalesce( listValue );
641 if (fullValue && last64) {
642 gchar *out = g_malloc(strlen(fullValue));
644 if ((len = base64_decode(out, fullValue,
645 strlen(fullValue))) >= 0) {
648 fullValue[len] = '\0';
652 /* Base-64 encoded data */
655 ldif_dump_b64( fullValue );
659 ldif_add_value( rec, lastTag, fullValue, hashField );
660 /* ldif_print_record( rec, stdout ); */
661 ldif_build_items( ldifFile, rec, cache );
662 ldif_clear_rec( rec );
664 mgu_free_list( listValue );
673 /* Continuation line */
674 listValue = g_slist_append(
675 listValue, g_strdup( line+1 ) );
677 else if( *line == '=' ) {
678 /* Base-64 encoded continuation field */
679 listValue = g_slist_append(
680 listValue, g_strdup( line ) );
684 tagName = ldif_get_tagname( line, &flag64 );
686 tagValue = ldif_get_tagvalue( line );
691 mgu_list_coalesce( listValue );
692 if (fullValue && last64) {
693 gchar *out = g_malloc(strlen(fullValue));
695 if ((len = base64_decode(out, fullValue,
696 strlen(fullValue))) >= 0) {
699 fullValue[len] = '\0';
703 /* Base-64 encoded data */
706 ldif_dump_b64( fullValue );
711 rec, lastTag, fullValue,
714 mgu_free_list( listValue );
720 lastTag = g_strdup( tagName );
721 listValue = g_slist_append(
723 g_strdup( tagValue ) );
735 ldif_clear_rec( rec );
738 mgu_free_list( listValue );
742 * Add list of field names to hash table.
743 * \param table Hashtable.
744 * \param list List of fields.
746 static void ldif_hash_add_list( GHashTable *table, GSList *list ) {
749 /* mgu_print_list( list, stdout ); */
751 gchar *tag = node->data;
752 if( ! g_hash_table_lookup( table, tag ) ) {
753 Ldif_FieldRec *rec = NULL;
754 gchar *key = g_strdup( tag );
756 rec = ldif_create_fieldrec( tag );
757 if( g_utf8_collate( tag, LDIF_TAG_DN ) == 0 ) {
758 rec->reserved = rec->selected = TRUE;
759 rec->userName = g_strdup( "dn" );
761 else if( g_utf8_collate( tag, LDIF_TAG_COMMONNAME ) == 0 ) {
762 rec->reserved = rec->selected = TRUE;
763 rec->userName = g_strdup( _( "Display Name" ) );
765 else if( g_utf8_collate( tag, LDIF_TAG_FIRSTNAME ) == 0 ) {
766 rec->reserved = rec->selected = TRUE;
767 rec->userName = g_strdup( _( "First Name" ) );
769 else if( g_utf8_collate( tag, LDIF_TAG_LASTNAME ) == 0 ) {
770 rec->reserved = rec->selected = TRUE;
771 rec->userName = g_strdup( _( "Last Name" ) );
773 else if( g_utf8_collate( tag, LDIF_TAG_NICKNAME ) == 0 ) {
774 rec->reserved = rec->selected = TRUE;
775 rec->userName = g_strdup( _( "Nick Name" ) );
777 else if( g_utf8_collate( tag, LDIF_TAG_EMAIL ) == 0 ) {
778 rec->reserved = rec->selected = TRUE;
779 rec->userName = g_strdup( _( "Email Address" ) );
781 g_hash_table_insert( table, key, rec );
783 node = g_slist_next( node );
788 * Sorted list comparison function.
789 * \param ptr1 First field.
790 * \param ptr2 Second field.
791 * \return <code>-1, 0, +1</code> if first record less than, equal,
792 * greater than second.
794 static gint ldif_field_compare( gconstpointer ptr1, gconstpointer ptr2 ) {
795 const Ldif_FieldRec *rec1 = ptr1;
796 const Ldif_FieldRec *rec2 = ptr2;
798 if( rec1->reserved ) {
799 if( ! rec2->reserved ) {
804 if( rec2->reserved ) {
808 return g_utf8_collate( rec1->tagName, rec2->tagName );
812 * Append hash table entry to list - visitor function.
814 * \param value Data value.
815 * \param data User data (the LDIF import control object).
817 static void ldif_hash2list_vis( gpointer key, gpointer value, gpointer data ) {
818 LdifFile *ldf = data;
820 g_list_insert_sorted( ldf->tempList, value, ldif_field_compare );
824 * Read tag names for file data.
825 * \param ldifFile LDIF import control object.
827 static void ldif_read_tag_list( LdifFile *ldifFile ) {
828 gchar *tagName = NULL;
829 GSList *listTags = NULL;
830 gboolean flagEOF = FALSE, flagEOR = FALSE, flagMail = FALSE;
831 gboolean flag64 = FALSE;
835 /* Clear hash table */
836 g_hash_table_foreach_remove(
837 ldifFile->hashFields, ldif_hash_free_vis, NULL );
839 /* Find EOF for progress indicator */
840 fseek( ldifFile->file, 0L, SEEK_END );
841 posEnd = ftell( ldifFile->file );
842 fseek( ldifFile->file, 0L, SEEK_SET );
846 gchar *line = ldif_get_line( ldifFile );
847 posCur = ftell( ldifFile->file );
848 if( ldifFile->cbProgress ) {
849 /* Call progress indicator */
850 ( ldifFile->cbProgress ) ( ldifFile, & posEnd, & posCur );
855 flagEOF = flagEOR = TRUE;
857 else if( *line == '\0' ) {
862 /* EOR, Output address data */
863 /* Save field list to hash table */
866 ldifFile->hashFields, listTags );
868 mgu_free_list( listTags );
875 /* Continuation line */
877 else if( *line == '=' ) {
878 /* Base-64 encoded continuation field */
882 tagName = ldif_get_tagname( line, &flag64 );
884 /* Add tag to list */
885 listTags = g_slist_append( listTags, tagName );
888 tagName, LDIF_TAG_EMAIL ) == 0 )
899 mgu_free_list( listTags );
904 * Read file into list. Main entry point
905 * \param ldifFile LDIF import control object.
906 * \param cache Address cache to load.
907 * \return Status code.
909 gint ldif_import_data( LdifFile *ldifFile, AddressCache *cache ) {
910 g_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS );
911 ldifFile->retVal = MGU_SUCCESS;
912 addrcache_clear( cache );
913 cache->dataRead = FALSE;
914 ldif_open_file( ldifFile );
915 if( ldifFile->retVal == MGU_SUCCESS ) {
916 /* Read data into the cache */
917 ldif_read_file( ldifFile, cache );
918 ldif_close_file( ldifFile );
921 cache->modified = FALSE;
922 cache->dataRead = TRUE;
924 return ldifFile->retVal;
928 * Process entire file reading list of unique fields. List of fields may be
929 * accessed with the <code>ldif_get_fieldlist()</code> function.
930 * \param ldifFile LDIF import control object.
931 * \return Status code.
933 gint ldif_read_tags( LdifFile *ldifFile ) {
934 g_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS );
935 ldifFile->retVal = MGU_SUCCESS;
936 if( ldifFile->dirtyFlag ) {
937 ldif_open_file( ldifFile );
938 if( ldifFile->retVal == MGU_SUCCESS ) {
939 /* Read data into the cache */
940 ldif_read_tag_list( ldifFile );
941 ldif_close_file( ldifFile );
942 ldifFile->dirtyFlag = FALSE;
943 ldifFile->accessFlag = TRUE;
946 return ldifFile->retVal;
950 * Return list of fields for LDIF file.
951 * \param ldifFile LDIF import control object.
952 * \return Linked list of <code>Ldif_FieldRec</code> objects. This list may be
953 * <code>g_free()</code>. Note that the objects in the list should not
954 * be freed since they refer to objects inside the internal cache.
955 * These objects will be freed when LDIF file object is freed.
957 GList *ldif_get_fieldlist( LdifFile *ldifFile ) {
960 g_return_val_if_fail( ldifFile != NULL, NULL );
961 if( ldifFile->hashFields ) {
962 ldifFile->tempList = NULL;
963 g_hash_table_foreach( ldifFile->hashFields, ldif_hash2list_vis, ldifFile );
964 list = ldifFile->tempList;
965 ldifFile->tempList = NULL;
971 * Output LDIF name-value pair to stream. Only non-empty names and values will
973 * \param stream File output stream.
975 * \param value Data value.
976 * \return <i>TRUE</i> if data output.
978 gboolean ldif_write_value( FILE *stream, const gchar *name, const gchar *value ) {
979 if( name == NULL ) return FALSE;
980 if( value == NULL ) return FALSE;
981 if( strlen( name ) < 1 ) return FALSE;
982 if( strlen( value ) < 1 ) return FALSE;
983 fprintf( stream, "%s: ", name );
984 fprintf( stream, "%s\n", value );
989 * Output LDIF End of Record to stream.
990 * \param stream File output stream.
991 * \return <i>TRUE</i> if data output.
993 void ldif_write_eor( FILE *stream ) {
994 /* Simple but caller should not need to know how to end record. */
995 fprintf( stream, "\n" );
999 * ============================================================================
1001 * ============================================================================