Fix CID 1491093: attrib leaked if attvalue is null
[claws.git] / src / ldif.c
blob249634be207ac94c3171da29719631d11cb1cb7a
1 /*
2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
3 * Copyright (C) 2001-2015 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 3 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, see <http://www.gnu.org/licenses/>.
20 * Functions necessary to access LDIF files (LDAP Data Interchange Format
21 * files).
24 #include "config.h"
26 #include <glib.h>
27 #include <glib/gi18n.h>
28 #include <string.h>
29 #include <sys/stat.h>
31 #include "mgutils.h"
32 #include "ldif.h"
33 #include "addritem.h"
34 #include "addrcache.h"
36 #include "utils.h"
37 #include "file-utils.h"
39 #define LDIF_SEP_TAG ':'
40 #define LDIF_LANG_TAG ';'
42 /**
43 * Create new object.
44 * \return Initialized LDIF file object.
46 LdifFile *ldif_create() {
47 LdifFile *ldifFile;
48 ldifFile = g_new0( LdifFile, 1 );
49 ldifFile->path = NULL;
50 ldifFile->file = NULL;
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;
58 return ldifFile;
61 /**
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 cm_return_if_fail( ldifFile != NULL );
69 if( ldifFile->path ) {
70 if( strcmp( ldifFile->path, value ) != 0 )
71 ldifFile->dirtyFlag = TRUE;
73 else {
74 ldifFile->dirtyFlag = TRUE;
76 ldifFile->path = mgu_replace_string( ldifFile->path, value );
77 g_strstrip( ldifFile->path );
78 ldifFile->importCount = 0;
81 /**
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 cm_return_if_fail( ldifFile != NULL );
88 ldifFile->accessFlag = value;
91 /**
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 );
98 rec->userName = NULL;
99 rec->reserved = FALSE;
100 rec->selected = FALSE;
101 return rec;
105 * Free field record object.
106 * \param rec LDIF field object.
108 static void ldif_free_fieldrec( Ldif_FieldRec *rec ) {
109 if( rec ) {
110 g_free( rec->tagName );
111 g_free( rec->userName );
112 rec->tagName = NULL;
113 rec->userName = NULL;
114 rec->reserved = FALSE;
115 rec->selected = FALSE;
116 g_free( rec );
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
124 * named.
126 void ldif_field_set_name( Ldif_FieldRec *rec, const gchar *value ) {
127 cm_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 cm_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
151 * toggled.
152 * \param rec LDIF field object.
154 void ldif_field_toggle( Ldif_FieldRec *rec ) {
155 cm_return_if_fail( rec != NULL );
157 if( ! rec->reserved ) {
158 rec->selected = !rec->selected;
163 * Free hash table entry visitor function.
164 * \param key Key.
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 );
171 return -1;
175 * Free up object by releasing internal memory.
176 * \param ldifFile LDIF import control object.
178 void ldif_free( LdifFile *ldifFile ) {
179 cm_return_if_fail( ldifFile != NULL );
181 /* Close file */
182 if( ldifFile->file ) claws_fclose( ldifFile->file );
184 /* Free internal stuff */
185 g_free( ldifFile->path );
187 /* Free field list */
188 g_hash_table_foreach_remove( ldifFile->hashFields, ldif_hash_free_vis, NULL );
189 g_hash_table_destroy( ldifFile->hashFields );
190 ldifFile->hashFields = NULL;
192 /* Clear pointers */
193 ldifFile->file = NULL;
194 ldifFile->path = NULL;
195 ldifFile->retVal = MGU_SUCCESS;
196 ldifFile->tempList = NULL;
197 ldifFile->dirtyFlag = FALSE;
198 ldifFile->accessFlag = FALSE;
199 ldifFile->cbProgress = NULL;
201 /* Now release file object */
202 g_free( ldifFile );
206 * Open file for read.
207 * \param ldifFile LDIF import control object.
208 * \return <i>TRUE</i> if file opened successfully.
210 static gint ldif_open_file( LdifFile* ldifFile ) {
211 /* g_print( "Opening file\n" ); */
212 if( ldifFile->path ) {
213 ldifFile->file = claws_fopen( ldifFile->path, "rb" );
214 if( ! ldifFile->file ) {
215 /* g_print( "can't open %s\n", ldifFile->path ); */
216 ldifFile->retVal = MGU_OPEN_FILE;
217 return ldifFile->retVal;
220 else {
221 /* g_print( "file not specified\n" ); */
222 ldifFile->retVal = MGU_NO_FILE;
223 return ldifFile->retVal;
226 /* Setup a buffer area */
227 ldifFile->retVal = MGU_SUCCESS;
228 return ldifFile->retVal;
232 * Close file.
233 * \param ldifFile LDIF import control object.
235 static void ldif_close_file( LdifFile *ldifFile ) {
236 cm_return_if_fail( ldifFile != NULL );
237 if( ldifFile->file ) claws_fclose( ldifFile->file );
238 ldifFile->file = NULL;
242 * Read line of text from file.
243 * \param ldifFile LDIF import control object.
244 * \return ptr to buffer where line starts (must be freed by caller).
246 static gchar *ldif_get_line( LdifFile *ldifFile ) {
247 gchar *buf = g_malloc(LDIFBUFSIZE);
248 gint ch;
249 int i = 0;
250 int cur_alloc = LDIFBUFSIZE;
252 if( claws_feof( ldifFile->file ) ) {
253 g_free(buf);
254 return NULL;
257 while( i < cur_alloc-1 ) {
258 ch = fgetc( ldifFile->file );
259 if (claws_ferror( ldifFile->file ))
260 ldifFile->retVal = MGU_ERROR_READ;
261 if( ch == '\0' || ch == EOF ) {
262 if( i == 0 ) {
263 g_free(buf);
264 return NULL;
266 break;
268 #if HAVE_DOSISH_SYSTEM
269 #else
270 if( ch == '\r' )
271 continue;
272 #endif
273 if( ch == '\n' )
274 break;
275 buf[i] = ch;
276 i++;
277 if (i == cur_alloc-1 && cur_alloc < LDIFBUFSIZE * 32) {
278 cur_alloc += LDIFBUFSIZE;
279 buf = g_realloc(buf, cur_alloc);
282 buf[i] = '\0';
284 return buf;
288 * Parse tag name from line buffer.
289 * \param line Buffer.
290 * \param flag64 Base-64 encoder flag.
291 * \return Buffer containing the tag name, or NULL if no delimiter char found.
292 * If a double delimiter (::) is found, flag64 is set.
294 static gchar *ldif_get_tagname( char* line, gboolean *flag64 ) {
295 gint len = 0;
296 gchar *tag = NULL;
297 gchar *lptr = line;
298 gchar *sptr = NULL;
300 while( *lptr++ ) {
301 /* Check for language tag */
302 if( *lptr == LDIF_LANG_TAG ) {
303 if( sptr == NULL ) sptr = lptr;
306 /* Check for delimiter */
307 if( *lptr == LDIF_SEP_TAG ) {
308 if( sptr ) {
309 len = sptr - line;
311 else {
312 len = lptr - line;
315 /* Base-64 encoding? */
316 if( * ++lptr == LDIF_SEP_TAG ) *flag64 = TRUE;
318 tag = g_strndup( line, len+1 );
319 tag[ len ] = '\0';
320 return tag;
323 return tag;
327 * Parse tag value from line buffer.
328 * \param line Buffer.
329 * \return Buffer containing the tag value. Empty string is returned if
330 * no delimiter char found.
332 static gchar *ldif_get_tagvalue( gchar* line ) {
333 gchar *value = NULL;
334 gchar *start = NULL;
335 gchar *lptr;
336 gint len = 0;
338 for( lptr = line; *lptr; lptr++ ) {
339 if( *lptr == LDIF_SEP_TAG ) {
340 if( ! start )
341 start = lptr + 1;
344 if( start ) {
345 if( *start == LDIF_SEP_TAG ) start++;
346 len = lptr - start;
347 value = g_strndup( start, len+1 );
348 g_strstrip( value );
350 else {
351 /* Ensure that we get an empty string */
352 value = g_strndup( "", 1 );
354 value[ len ] = '\0';
355 return value;
359 * Parsed address data record.
361 typedef struct _Ldif_ParsedRec_ Ldif_ParsedRec;
362 struct _Ldif_ParsedRec_ {
363 GSList *listCName;
364 GSList *listFName;
365 GSList *listLName;
366 GSList *listNName;
367 GSList *listAddress;
368 GSList *listID;
369 GSList *userAttr;
373 * User attribute data record.
375 typedef struct _Ldif_UserAttr_ Ldif_UserAttr;
376 struct _Ldif_UserAttr_ {
377 gchar *name;
378 gchar *value;
382 * Build an address list entry and append to list of address items in the
383 * address cache. Name is formatted as "<first-name> <last-name>".
384 * \param ldifFile LDIF import control object.
385 * \param rec LDIF field object.
386 * \param cache Address cache to be populated with data.
388 static void ldif_build_items(
389 LdifFile *ldifFile, Ldif_ParsedRec *rec, AddressCache *cache )
391 GSList *nodeFirst;
392 GSList *nodeAddress;
393 GSList *nodeAttr;
394 gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
395 gchar *nickName = NULL;
396 gint iLen = 0, iLenT = 0;
397 ItemPerson *person;
398 ItemEMail *email;
400 nodeAddress = rec->listAddress;
401 // if( nodeAddress == NULL ) return;
403 /* Find longest first name in list */
404 nodeFirst = rec->listFName;
405 while( nodeFirst ) {
406 if( firstName == NULL ) {
407 firstName = nodeFirst->data;
408 iLen = strlen( firstName );
410 else {
411 if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
412 firstName = nodeFirst->data;
413 iLen = iLenT;
416 nodeFirst = g_slist_next( nodeFirst );
419 /* Format name */
420 if( rec->listLName ) {
421 lastName = rec->listLName->data;
424 if( firstName ) {
425 if( lastName ) {
426 fullName = g_strdup_printf(
427 "%s %s", firstName, lastName );
429 else {
430 fullName = g_strdup_printf( "%s", firstName );
433 else {
434 if( lastName ) {
435 fullName = g_strdup_printf( "%s", lastName );
439 if (!fullName || strlen(fullName) == 0) {
440 g_free(fullName);
441 fullName = NULL;
442 if (rec->listCName)
443 fullName = g_strdup(rec->listCName->data);
446 if( fullName ) {
447 g_strstrip( fullName );
450 if( rec->listNName ) {
451 nickName = rec->listNName->data;
454 person = addritem_create_item_person();
455 addritem_person_set_common_name( person, fullName );
456 addritem_person_set_first_name( person, firstName );
457 addritem_person_set_last_name( person, lastName );
458 addritem_person_set_nick_name( person, nickName );
459 addrcache_id_person( cache, person );
460 addrcache_add_person( cache, person );
461 ++ldifFile->importCount;
463 /* Add address item */
464 while( nodeAddress ) {
465 email = addritem_create_item_email();
466 addritem_email_set_address( email, nodeAddress->data );
467 addrcache_id_email( cache, email );
468 addrcache_person_add_email( cache, person, email );
469 nodeAddress = g_slist_next( nodeAddress );
471 g_free( fullName );
472 fullName = firstName = lastName = NULL;
474 /* Add user attributes */
475 nodeAttr = rec->userAttr;
476 while( nodeAttr ) {
477 Ldif_UserAttr *attr = nodeAttr->data;
478 UserAttribute *attrib = addritem_create_attribute();
479 addritem_attrib_set_name( attrib, attr->name );
480 addritem_attrib_set_value( attrib, attr->value );
481 addritem_person_add_attribute( person, attrib );
482 nodeAttr = g_slist_next( nodeAttr );
484 nodeAttr = NULL;
488 * Add selected field as user attribute.
489 * \param rec LDIF field object.
490 * \param tagName LDIF tag name.
491 * \param tagValue Data value.
492 * \param hashField Hash table to populate.
494 static void ldif_add_user_attr(
495 Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue,
496 GHashTable *hashField )
498 Ldif_FieldRec *fld = NULL;
499 Ldif_UserAttr *attr = NULL;
500 gchar *name;
502 fld = g_hash_table_lookup( hashField, tagName );
503 if( fld ) {
504 if( ! fld->selected ) return;
506 name = fld->tagName;
507 if( fld->userName ) {
508 name = fld->userName;
510 attr = g_new0( Ldif_UserAttr, 1 );
511 attr->name = g_strdup( name );
512 attr->value = g_strdup( tagValue );
513 rec->userAttr = g_slist_append( rec->userAttr, attr );
518 * Add value to parsed data.
519 * \param rec LDIF field object.
520 * \param tagName LDIF tag name.
521 * \param tagValue Data value.
522 * \param hashField Hash table to populate.
524 static void ldif_add_value(
525 Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue,
526 GHashTable *hashField )
528 gchar *nm, *val;
530 nm = g_utf8_strdown( tagName, -1 );
531 if( tagValue ) {
532 val = g_strdup( tagValue );
534 else {
535 val = g_strdup( "" );
537 g_strstrip( val );
539 if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_COMMONNAME, -1 ) ) == 0 ) {
540 rec->listCName = g_slist_append( rec->listCName, val );
542 else if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_FIRSTNAME, -1 ) ) == 0 ) {
543 rec->listFName = g_slist_append( rec->listFName, val );
545 else if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_LASTNAME, -1 ) ) == 0 ) {
546 rec->listLName = g_slist_append( rec->listLName, val );
548 else if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_NICKNAME, -1 ) ) == 0 ) {
549 rec->listNName = g_slist_append( rec->listNName, val );
551 else if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_EMAIL, -1 ) ) == 0 ) {
552 rec->listAddress = g_slist_append( rec->listAddress, val );
554 else {
555 /* Add field as user attribute */
556 ldif_add_user_attr( rec, tagName, tagValue, hashField );
558 g_free( nm );
562 * Clear parsed data record.
563 * \param rec LDIF field object.
565 static void ldif_clear_rec( Ldif_ParsedRec *rec ) {
566 GSList *list;
568 /* Free up user attributes */
569 list = rec->userAttr;
570 while( list ) {
571 Ldif_UserAttr *attr = list->data;
572 g_free( attr->name );
573 g_free( attr->value );
574 g_free( attr );
575 list = g_slist_next( list );
577 g_slist_free( rec->userAttr );
579 g_slist_free( rec->listCName );
580 g_slist_free( rec->listFName );
581 g_slist_free( rec->listLName );
582 g_slist_free( rec->listNName );
583 g_slist_free( rec->listAddress );
584 g_slist_free( rec->listID );
586 rec->userAttr = NULL;
587 rec->listCName = NULL;
588 rec->listFName = NULL;
589 rec->listLName = NULL;
590 rec->listNName = NULL;
591 rec->listAddress = NULL;
592 rec->listID = NULL;
596 * Read file data into address cache.
597 * Note that one LDIF record identifies one entity uniquely with the
598 * distinguished name (dn) tag. Each person can have multiple E-Mail
599 * addresses. Also, each person can have many common name (cn) tags.
601 * \param ldifFile LDIF import control object.
602 * \param cache Address cache to be populated with data.
604 static void ldif_read_file( LdifFile *ldifFile, AddressCache *cache ) {
605 gchar *tagName = NULL, *tagValue = NULL;
606 gchar *lastTag = NULL, *fullValue = NULL;
607 GSList *listValue = NULL;
608 gboolean flagEOF = FALSE, flagEOR = FALSE;
609 gboolean flag64 = FALSE, last64 = FALSE;
610 Ldif_ParsedRec *rec;
611 long posEnd = 0L;
612 long posCur = 0L;
613 GHashTable *hashField;
614 gsize len;
616 hashField = ldifFile->hashFields;
617 rec = g_new0( Ldif_ParsedRec, 1 );
618 ldif_clear_rec( rec );
620 /* Find EOF for progress indicator */
621 fseek( ldifFile->file, 0L, SEEK_END );
622 posEnd = ftell( ldifFile->file );
623 fseek( ldifFile->file, 0L, SEEK_SET );
625 while( ! flagEOF ) {
626 gchar *line = ldif_get_line( ldifFile );
628 posCur = ftell( ldifFile->file );
629 if( ldifFile->cbProgress ) {
630 /* Call progress indicator */
631 ( ldifFile->cbProgress ) ( ldifFile, & posEnd, & posCur );
634 flag64 = FALSE;
635 if( line == NULL ) {
636 flagEOF = flagEOR = TRUE;
638 else if( *line == '\0' ) {
639 flagEOR = TRUE;
642 if( flagEOR ) {
643 /* EOR, Output address data */
644 if( lastTag ) {
645 /* Save record */
646 fullValue = mgu_list_coalesce( listValue );
647 if (fullValue && last64) {
648 gchar *tmp = g_base64_decode_zero(fullValue, &len);
649 g_free(fullValue);
650 fullValue = tmp;
653 ldif_add_value( rec, lastTag, fullValue, hashField );
654 /* ldif_print_record( rec, stdout ); */
655 ldif_build_items( ldifFile, rec, cache );
656 ldif_clear_rec( rec );
657 g_free( lastTag );
658 g_slist_free_full( listValue, g_free );
659 g_free(fullValue);
660 lastTag = NULL;
661 listValue = NULL;
662 last64 = FALSE;
665 if( line ) {
666 flagEOR = FALSE;
667 if( *line == ' ' ) {
668 /* Continuation line */
669 listValue = g_slist_append(
670 listValue, g_strdup( line+1 ) );
672 else if( *line == '=' ) {
673 /* Base-64 encoded continuation field */
674 listValue = g_slist_append(
675 listValue, g_strdup( line ) );
677 else {
678 /* Parse line */
679 tagName = ldif_get_tagname( line, &flag64 );
680 if( tagName ) {
681 tagValue = ldif_get_tagvalue( line );
682 if( tagValue ) {
683 if( lastTag ) {
684 /* Save data */
685 fullValue =
686 mgu_list_coalesce( listValue );
687 if (fullValue && last64) {
688 gchar *tmp = g_base64_decode_zero(fullValue, &len);
689 g_free(fullValue);
690 fullValue = tmp;
692 /* Base-64 encoded data */
694 if( last64 ) {
695 ldif_dump_b64( fullValue );
699 ldif_add_value(
700 rec, lastTag, fullValue,
701 hashField );
702 g_free( lastTag );
703 g_slist_free_full( listValue, g_free );
704 lastTag = NULL;
705 listValue = NULL;
708 lastTag = g_strdup( tagName );
709 listValue = g_slist_append(
710 listValue,
711 g_strdup( tagValue ) );
712 g_free( tagValue );
713 last64 = flag64;
715 g_free( tagName );
718 g_free( line );
722 /* Release data */
723 ldif_clear_rec( rec );
724 g_free( rec );
725 g_free( lastTag );
726 g_slist_free_full( listValue, g_free );
730 * Add list of field names to hash table.
731 * \param table Hashtable.
732 * \param list List of fields.
734 static void ldif_hash_add_list( GHashTable *table, GSList *list ) {
735 GSList *node = list;
737 /* mgu_print_list( list, stdout ); */
738 while( node ) {
739 gchar *tag = node->data;
740 if( ! g_hash_table_lookup( table, tag ) ) {
741 Ldif_FieldRec *rec = NULL;
742 gchar *key = g_utf8_strdown( tag, -1 );
744 rec = ldif_create_fieldrec( tag );
745 if( g_utf8_collate( key, LDIF_TAG_DN ) == 0 ) {
746 rec->reserved = rec->selected = TRUE;
747 rec->userName = g_strdup( "dn" );
749 else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_COMMONNAME, -1 ) ) == 0 ) {
750 rec->reserved = rec->selected = TRUE;
751 rec->userName = g_strdup( _( "Display Name" ) );
753 else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_FIRSTNAME, -1 ) ) == 0 ) {
754 rec->reserved = rec->selected = TRUE;
755 rec->userName = g_strdup( _( "First Name" ) );
757 else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_LASTNAME, -1 ) ) == 0 ) {
758 rec->reserved = rec->selected = TRUE;
759 rec->userName = g_strdup( _( "Last Name" ) );
761 else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_NICKNAME, -1 ) ) == 0 ) {
762 rec->reserved = rec->selected = TRUE;
763 rec->userName = g_strdup( _( "Nick Name" ) );
765 else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_EMAIL, -1 ) ) == 0 ) {
766 rec->reserved = rec->selected = TRUE;
767 rec->userName = g_strdup( _( "Email Address" ) );
769 g_hash_table_insert( table, key, rec );
771 node = g_slist_next( node );
776 * Sorted list comparison function.
777 * \param ptr1 First field.
778 * \param ptr2 Second field.
779 * \return <code>-1, 0, +1</code> if first record less than, equal,
780 * greater than second.
782 static gint ldif_field_compare( gconstpointer ptr1, gconstpointer ptr2 ) {
783 const Ldif_FieldRec *rec1 = ptr1;
784 const Ldif_FieldRec *rec2 = ptr2;
786 if( rec1->reserved ) {
787 if( ! rec2->reserved ) {
788 return +1;
791 else {
792 if( rec2->reserved ) {
793 return -1;
796 return g_utf8_collate( rec1->tagName, rec2->tagName );
800 * Append hash table entry to list - visitor function.
801 * \param key Key.
802 * \param value Data value.
803 * \param data User data (the LDIF import control object).
805 static void ldif_hash2list_vis( gpointer key, gpointer value, gpointer data ) {
806 LdifFile *ldf = data;
807 ldf->tempList =
808 g_list_insert_sorted( ldf->tempList, value, ldif_field_compare );
812 * Read tag names for file data.
813 * \param ldifFile LDIF import control object.
815 static void ldif_read_tag_list( LdifFile *ldifFile ) {
816 gchar *tagName = NULL;
817 GSList *listTags = NULL;
818 gboolean flagEOF = FALSE, flagEOR = FALSE, flagMail = FALSE;
819 gboolean flag64 = FALSE;
820 long posEnd = 0L;
821 long posCur = 0L;
823 /* Clear hash table */
824 g_hash_table_foreach_remove(
825 ldifFile->hashFields, ldif_hash_free_vis, NULL );
827 /* Find EOF for progress indicator */
828 fseek( ldifFile->file, 0L, SEEK_END );
829 posEnd = ftell( ldifFile->file );
830 fseek( ldifFile->file, 0L, SEEK_SET );
832 if (posEnd == 0) {
833 ldifFile->retVal = MGU_EOF;
834 return;
837 /* Process file */
838 while( ! flagEOF ) {
839 gchar *line = ldif_get_line( ldifFile );
840 posCur = ftell( ldifFile->file );
841 if( ldifFile->cbProgress ) {
842 /* Call progress indicator */
843 ( ldifFile->cbProgress ) ( ldifFile, & posEnd, & posCur );
846 flag64 = FALSE;
847 if( line == NULL ) {
848 flagEOF = flagEOR = TRUE;
850 else if( *line == '\0' ) {
851 flagEOR = TRUE;
854 if( flagEOR ) {
855 /* EOR, Output address data */
856 /* Save field list to hash table */
857 if( flagMail ) {
858 ldif_hash_add_list(
859 ldifFile->hashFields, listTags );
861 g_slist_free_full( listTags, g_free );
862 listTags = NULL;
863 flagMail = FALSE;
865 if( line ) {
866 flagEOR = FALSE;
867 if( *line == ' ' ) {
868 /* Continuation line */
870 else if( *line == '=' ) {
871 /* Base-64 encoded continuation field */
873 else {
874 /* Parse line */
875 tagName = ldif_get_tagname( line, &flag64 );
876 if( tagName ) {
877 /* Add tag to list */
878 listTags = g_slist_append( listTags, tagName );
880 if( g_utf8_collate(
881 tagName, LDIF_TAG_EMAIL ) == 0 )
883 flagMail = TRUE;
885 } else {
886 g_strstrip(line);
887 if (*line != '\0') {
888 debug_print("ldif: bad format: '%s'\n", line);
889 ldifFile->retVal = MGU_BAD_FORMAT;
893 g_free( line );
897 /* Release data */
898 g_slist_free_full( listTags, g_free );
899 listTags = NULL;
903 * Read file into list. Main entry point
904 * \param ldifFile LDIF import control object.
905 * \param cache Address cache to load.
906 * \return Status code.
908 gint ldif_import_data( LdifFile *ldifFile, AddressCache *cache ) {
909 cm_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS );
910 ldifFile->retVal = MGU_SUCCESS;
911 addrcache_clear( cache );
912 cache->dataRead = FALSE;
913 ldif_open_file( ldifFile );
914 if( ldifFile->retVal == MGU_SUCCESS ) {
915 /* Read data into the cache */
916 ldif_read_file( ldifFile, cache );
917 ldif_close_file( ldifFile );
919 /* Mark cache */
920 cache->modified = FALSE;
921 cache->dataRead = TRUE;
923 return ldifFile->retVal;
927 * Process entire file reading list of unique fields. List of fields may be
928 * accessed with the <code>ldif_get_fieldlist()</code> function.
929 * \param ldifFile LDIF import control object.
930 * \return Status code.
932 gint ldif_read_tags( LdifFile *ldifFile ) {
933 cm_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS );
934 ldifFile->retVal = MGU_SUCCESS;
935 if( ldifFile->dirtyFlag ) {
936 ldif_open_file( ldifFile );
937 if( ldifFile->retVal == MGU_SUCCESS ) {
938 /* Read data into the cache */
939 ldif_read_tag_list( ldifFile );
940 ldif_close_file( ldifFile );
941 ldifFile->dirtyFlag = FALSE;
942 ldifFile->accessFlag = TRUE;
945 return ldifFile->retVal;
949 * Return list of fields for LDIF file.
950 * \param ldifFile LDIF import control object.
951 * \return Linked list of <code>Ldif_FieldRec</code> objects. This list may be
952 * <code>g_free()</code>. Note that the objects in the list should not
953 * be freed since they refer to objects inside the internal cache.
954 * These objects will be freed when LDIF file object is freed.
956 GList *ldif_get_fieldlist( LdifFile *ldifFile ) {
957 GList *list = NULL;
959 cm_return_val_if_fail( ldifFile != NULL, NULL );
960 if( ldifFile->hashFields ) {
961 ldifFile->tempList = NULL;
962 g_hash_table_foreach( ldifFile->hashFields, ldif_hash2list_vis, ldifFile );
963 list = ldifFile->tempList;
964 ldifFile->tempList = NULL;
966 return list;
970 * Output LDIF name-value pair to stream. Only non-empty names and values will
971 * be output to file.
972 * \param stream File output stream.
973 * \param name Name.
974 * \param value Data value.
975 * \return <i>TRUE</i> if data output.
977 gboolean ldif_write_value( FILE *stream, const gchar *name, const gchar *value ) {
978 if( name == NULL ) return FALSE;
979 if( value == NULL ) return FALSE;
980 if( strlen( name ) < 1 ) return FALSE;
981 if( strlen( value ) < 1 ) return FALSE;
982 fprintf( stream, "%s: ", name );
983 fprintf( stream, "%s\n", value );
984 return TRUE;
988 * Output LDIF End of Record to stream.
989 * \param stream File output stream.
990 * \return <i>TRUE</i> if data output.
992 void ldif_write_eor( FILE *stream ) {
993 /* Simple but caller should not need to know how to end record. */
994 fprintf( stream, "\n" );
998 * ============================================================================
999 * End of Source.
1000 * ============================================================================