change labels, remove empty lines, show phishing warning on copy
[claws.git] / src / ldif.c
blob086ab0b2cd987824b2a1437dc1b6cad2b43093d9
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 <glib.h>
25 #include <glib/gi18n.h>
26 #include <string.h>
27 #include <sys/stat.h>
29 #include "mgutils.h"
30 #include "ldif.h"
31 #include "addritem.h"
32 #include "addrcache.h"
34 #include "utils.h"
35 #include "file-utils.h"
37 #define LDIF_SEP_TAG ':'
38 #define LDIF_LANG_TAG ';'
40 /**
41 * Create new object.
42 * \return Initialized LDIF file object.
44 LdifFile *ldif_create() {
45 LdifFile *ldifFile;
46 ldifFile = g_new0( LdifFile, 1 );
47 ldifFile->path = NULL;
48 ldifFile->file = NULL;
49 ldifFile->hashFields = g_hash_table_new( g_str_hash, g_str_equal );
50 ldifFile->tempList = NULL;
51 ldifFile->dirtyFlag = TRUE;
52 ldifFile->accessFlag = FALSE;
53 ldifFile->retVal = MGU_SUCCESS;
54 ldifFile->cbProgress = NULL;
55 ldifFile->importCount = 0;
56 return ldifFile;
59 /**
60 * Specify full file specification of LDIF file.
61 * \param ldifFile LDIF import control object.
62 * \param value Value of access flag.
64 void ldif_set_file( LdifFile *ldifFile, const gchar *value ) {
65 cm_return_if_fail( ldifFile != NULL );
67 if( ldifFile->path ) {
68 if( strcmp( ldifFile->path, value ) != 0 )
69 ldifFile->dirtyFlag = TRUE;
71 else {
72 ldifFile->dirtyFlag = TRUE;
74 ldifFile->path = mgu_replace_string( ldifFile->path, value );
75 g_strstrip( ldifFile->path );
76 ldifFile->importCount = 0;
79 /**
80 * Set the file access indicator.
81 * \param ldifFile LDIF import control object.
82 * \param value File specification.
84 void ldif_set_accessed( LdifFile *ldifFile, const gboolean value ) {
85 cm_return_if_fail( ldifFile != NULL );
86 ldifFile->accessFlag = value;
89 /**
90 * Create field record object.
91 * \return Initialized LDIF field object.
93 static Ldif_FieldRec *ldif_create_fieldrec( const gchar *field ) {
94 Ldif_FieldRec *rec = g_new0( Ldif_FieldRec, 1 );
95 rec->tagName = g_strdup( field );
96 rec->userName = NULL;
97 rec->reserved = FALSE;
98 rec->selected = FALSE;
99 return rec;
103 * Free field record object.
104 * \param rec LDIF field object.
106 static void ldif_free_fieldrec( Ldif_FieldRec *rec ) {
107 if( rec ) {
108 g_free( rec->tagName );
109 g_free( rec->userName );
110 rec->tagName = NULL;
111 rec->userName = NULL;
112 rec->reserved = FALSE;
113 rec->selected = FALSE;
114 g_free( rec );
119 * Set user name for field record.
120 * \param rec LDIF field object.
121 * \param value User name to set. Note that reserved fields cannot be
122 * named.
124 void ldif_field_set_name( Ldif_FieldRec *rec, const gchar *value ) {
125 cm_return_if_fail( rec != NULL );
127 if( ! rec->reserved ) {
128 rec->userName = mgu_replace_string( rec->userName, value );
129 g_strstrip( rec->userName );
134 * Specify selection for field record.
135 * \param rec LDIF field object.
136 * \param value Set to <i>TRUE</i> to select field. Note that reserved
137 * fields cannot be unselected.
139 void ldif_field_set_selected( Ldif_FieldRec *rec, const gboolean value ) {
140 cm_return_if_fail( rec != NULL );
142 if( ! rec->reserved ) {
143 rec->selected = value;
148 * Toggle selection for field record. Note that reserved fields cannot be
149 * toggled.
150 * \param rec LDIF field object.
152 void ldif_field_toggle( Ldif_FieldRec *rec ) {
153 cm_return_if_fail( rec != NULL );
155 if( ! rec->reserved ) {
156 rec->selected = !rec->selected;
161 * Free hash table entry visitor function.
162 * \param key Key.
163 * \param value Value (the LDIF field record).
164 * \param data User data.
165 * \return <code>-1</code>.
167 static gint ldif_hash_free_vis( gpointer key, gpointer value, gpointer data ) {
168 ldif_free_fieldrec( ( Ldif_FieldRec * ) value );
169 return -1;
173 * Free up object by releasing internal memory.
174 * \param ldifFile LDIF import control object.
176 void ldif_free( LdifFile *ldifFile ) {
177 cm_return_if_fail( ldifFile != NULL );
179 /* Close file */
180 if( ldifFile->file ) claws_fclose( ldifFile->file );
182 /* Free internal stuff */
183 g_free( ldifFile->path );
185 /* Free field list */
186 g_hash_table_foreach_remove( ldifFile->hashFields, ldif_hash_free_vis, NULL );
187 g_hash_table_destroy( ldifFile->hashFields );
188 ldifFile->hashFields = NULL;
190 /* Clear pointers */
191 ldifFile->file = NULL;
192 ldifFile->path = NULL;
193 ldifFile->retVal = MGU_SUCCESS;
194 ldifFile->tempList = NULL;
195 ldifFile->dirtyFlag = FALSE;
196 ldifFile->accessFlag = FALSE;
197 ldifFile->cbProgress = NULL;
199 /* Now release file object */
200 g_free( ldifFile );
204 * Open file for read.
205 * \param ldifFile LDIF import control object.
206 * \return <i>TRUE</i> if file opened successfully.
208 static gint ldif_open_file( LdifFile* ldifFile ) {
209 /* g_print( "Opening file\n" ); */
210 if( ldifFile->path ) {
211 ldifFile->file = claws_fopen( ldifFile->path, "rb" );
212 if( ! ldifFile->file ) {
213 /* g_print( "can't open %s\n", ldifFile->path ); */
214 ldifFile->retVal = MGU_OPEN_FILE;
215 return ldifFile->retVal;
218 else {
219 /* g_print( "file not specified\n" ); */
220 ldifFile->retVal = MGU_NO_FILE;
221 return ldifFile->retVal;
224 /* Setup a buffer area */
225 ldifFile->retVal = MGU_SUCCESS;
226 return ldifFile->retVal;
230 * Close file.
231 * \param ldifFile LDIF import control object.
233 static void ldif_close_file( LdifFile *ldifFile ) {
234 cm_return_if_fail( ldifFile != NULL );
235 if( ldifFile->file ) claws_fclose( ldifFile->file );
236 ldifFile->file = NULL;
240 * Read line of text from file.
241 * \param ldifFile LDIF import control object.
242 * \return ptr to buffer where line starts.
244 static gchar *ldif_get_line( LdifFile *ldifFile ) {
245 gchar *buf = g_malloc(LDIFBUFSIZE);
246 gint ch;
247 int i = 0;
248 int cur_alloc = LDIFBUFSIZE;
250 if( claws_feof( ldifFile->file ) ) {
251 g_free(buf);
252 return NULL;
255 while( i < cur_alloc-1 ) {
256 ch = fgetc( ldifFile->file );
257 if (claws_ferror( ldifFile->file ))
258 ldifFile->retVal = MGU_ERROR_READ;
259 if( ch == '\0' || ch == EOF ) {
260 if( i == 0 ) return NULL;
261 break;
263 #if HAVE_DOSISH_SYSTEM
264 #else
265 if( ch == '\r' )
266 continue;
267 #endif
268 if( ch == '\n' )
269 break;
270 buf[i] = ch;
271 i++;
272 if (i == cur_alloc-1 && cur_alloc < LDIFBUFSIZE * 32) {
273 cur_alloc += LDIFBUFSIZE;
274 buf = g_realloc(buf, cur_alloc);
277 buf[i] = '\0';
279 /* Return a copy of buffer */
280 return g_strdup( buf );
284 * Parse tag name from line buffer.
285 * \param line Buffer.
286 * \param flag64 Base-64 encoder flag.
287 * \return Buffer containing the tag name, or NULL if no delimiter char found.
288 * If a double delimiter (::) is found, flag64 is set.
290 static gchar *ldif_get_tagname( char* line, gboolean *flag64 ) {
291 gint len = 0;
292 gchar *tag = NULL;
293 gchar *lptr = line;
294 gchar *sptr = NULL;
296 while( *lptr++ ) {
297 /* Check for language tag */
298 if( *lptr == LDIF_LANG_TAG ) {
299 if( sptr == NULL ) sptr = lptr;
302 /* Check for delimiter */
303 if( *lptr == LDIF_SEP_TAG ) {
304 if( sptr ) {
305 len = sptr - line;
307 else {
308 len = lptr - line;
311 /* Base-64 encoding? */
312 if( * ++lptr == LDIF_SEP_TAG ) *flag64 = TRUE;
314 tag = g_strndup( line, len+1 );
315 tag[ len ] = '\0';
316 return tag;
319 return tag;
323 * Parse tag value from line buffer.
324 * \param line Buffer.
325 * \return Buffer containing the tag value. Empty string is returned if
326 * no delimiter char found.
328 static gchar *ldif_get_tagvalue( gchar* line ) {
329 gchar *value = NULL;
330 gchar *start = NULL;
331 gchar *lptr;
332 gint len = 0;
334 for( lptr = line; *lptr; lptr++ ) {
335 if( *lptr == LDIF_SEP_TAG ) {
336 if( ! start )
337 start = lptr + 1;
340 if( start ) {
341 if( *start == LDIF_SEP_TAG ) start++;
342 len = lptr - start;
343 value = g_strndup( start, len+1 );
344 g_strstrip( value );
346 else {
347 /* Ensure that we get an empty string */
348 value = g_strndup( "", 1 );
350 value[ len ] = '\0';
351 return value;
355 * Parsed address data record.
357 typedef struct _Ldif_ParsedRec_ Ldif_ParsedRec;
358 struct _Ldif_ParsedRec_ {
359 GSList *listCName;
360 GSList *listFName;
361 GSList *listLName;
362 GSList *listNName;
363 GSList *listAddress;
364 GSList *listID;
365 GSList *userAttr;
369 * User attribute data record.
371 typedef struct _Ldif_UserAttr_ Ldif_UserAttr;
372 struct _Ldif_UserAttr_ {
373 gchar *name;
374 gchar *value;
378 * Build an address list entry and append to list of address items in the
379 * address cache. Name is formatted as "<first-name> <last-name>".
380 * \param ldifFile LDIF import control object.
381 * \param rec LDIF field object.
382 * \param cache Address cache to be populated with data.
384 static void ldif_build_items(
385 LdifFile *ldifFile, Ldif_ParsedRec *rec, AddressCache *cache )
387 GSList *nodeFirst;
388 GSList *nodeAddress;
389 GSList *nodeAttr;
390 gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
391 gchar *nickName = NULL;
392 gint iLen = 0, iLenT = 0;
393 ItemPerson *person;
394 ItemEMail *email;
396 nodeAddress = rec->listAddress;
397 // if( nodeAddress == NULL ) return;
399 /* Find longest first name in list */
400 nodeFirst = rec->listFName;
401 while( nodeFirst ) {
402 if( firstName == NULL ) {
403 firstName = nodeFirst->data;
404 iLen = strlen( firstName );
406 else {
407 if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
408 firstName = nodeFirst->data;
409 iLen = iLenT;
412 nodeFirst = g_slist_next( nodeFirst );
415 /* Format name */
416 if( rec->listLName ) {
417 lastName = rec->listLName->data;
420 if( firstName ) {
421 if( lastName ) {
422 fullName = g_strdup_printf(
423 "%s %s", firstName, lastName );
425 else {
426 fullName = g_strdup_printf( "%s", firstName );
429 else {
430 if( lastName ) {
431 fullName = g_strdup_printf( "%s", lastName );
435 if (!fullName || strlen(fullName) == 0) {
436 g_free(fullName);
437 fullName = NULL;
438 if (rec->listCName)
439 fullName = g_strdup(rec->listCName->data);
442 if( fullName ) {
443 g_strstrip( fullName );
446 if( rec->listNName ) {
447 nickName = rec->listNName->data;
450 person = addritem_create_item_person();
451 addritem_person_set_common_name( person, fullName );
452 addritem_person_set_first_name( person, firstName );
453 addritem_person_set_last_name( person, lastName );
454 addritem_person_set_nick_name( person, nickName );
455 addrcache_id_person( cache, person );
456 addrcache_add_person( cache, person );
457 ++ldifFile->importCount;
459 /* Add address item */
460 while( nodeAddress ) {
461 email = addritem_create_item_email();
462 addritem_email_set_address( email, nodeAddress->data );
463 addrcache_id_email( cache, email );
464 addrcache_person_add_email( cache, person, email );
465 nodeAddress = g_slist_next( nodeAddress );
467 g_free( fullName );
468 fullName = firstName = lastName = NULL;
470 /* Add user attributes */
471 nodeAttr = rec->userAttr;
472 while( nodeAttr ) {
473 Ldif_UserAttr *attr = nodeAttr->data;
474 UserAttribute *attrib = addritem_create_attribute();
475 addritem_attrib_set_name( attrib, attr->name );
476 addritem_attrib_set_value( attrib, attr->value );
477 addritem_person_add_attribute( person, attrib );
478 nodeAttr = g_slist_next( nodeAttr );
480 nodeAttr = NULL;
484 * Add selected field as user attribute.
485 * \param rec LDIF field object.
486 * \param tagName LDIF tag name.
487 * \param tagValue Data value.
488 * \param hashField Hash table to populate.
490 static void ldif_add_user_attr(
491 Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue,
492 GHashTable *hashField )
494 Ldif_FieldRec *fld = NULL;
495 Ldif_UserAttr *attr = NULL;
496 gchar *name;
498 fld = g_hash_table_lookup( hashField, tagName );
499 if( fld ) {
500 if( ! fld->selected ) return;
502 name = fld->tagName;
503 if( fld->userName ) {
504 name = fld->userName;
506 attr = g_new0( Ldif_UserAttr, 1 );
507 attr->name = g_strdup( name );
508 attr->value = g_strdup( tagValue );
509 rec->userAttr = g_slist_append( rec->userAttr, attr );
514 * Add value to parsed data.
515 * \param rec LDIF field object.
516 * \param tagName LDIF tag name.
517 * \param tagValue Data value.
518 * \param hashField Hash table to populate.
520 static void ldif_add_value(
521 Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue,
522 GHashTable *hashField )
524 gchar *nm, *val;
526 nm = g_utf8_strdown( tagName, -1 );
527 if( tagValue ) {
528 val = g_strdup( tagValue );
530 else {
531 val = g_strdup( "" );
533 g_strstrip( val );
535 if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_COMMONNAME, -1 ) ) == 0 ) {
536 rec->listCName = g_slist_append( rec->listCName, val );
538 else if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_FIRSTNAME, -1 ) ) == 0 ) {
539 rec->listFName = g_slist_append( rec->listFName, val );
541 else if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_LASTNAME, -1 ) ) == 0 ) {
542 rec->listLName = g_slist_append( rec->listLName, val );
544 else if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_NICKNAME, -1 ) ) == 0 ) {
545 rec->listNName = g_slist_append( rec->listNName, val );
547 else if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_EMAIL, -1 ) ) == 0 ) {
548 rec->listAddress = g_slist_append( rec->listAddress, val );
550 else {
551 /* Add field as user attribute */
552 ldif_add_user_attr( rec, tagName, tagValue, hashField );
554 g_free( nm );
558 * Clear parsed data record.
559 * \param rec LDIF field object.
561 static void ldif_clear_rec( Ldif_ParsedRec *rec ) {
562 GSList *list;
564 /* Free up user attributes */
565 list = rec->userAttr;
566 while( list ) {
567 Ldif_UserAttr *attr = list->data;
568 g_free( attr->name );
569 g_free( attr->value );
570 g_free( attr );
571 list = g_slist_next( list );
573 g_slist_free( rec->userAttr );
575 g_slist_free( rec->listCName );
576 g_slist_free( rec->listFName );
577 g_slist_free( rec->listLName );
578 g_slist_free( rec->listNName );
579 g_slist_free( rec->listAddress );
580 g_slist_free( rec->listID );
582 rec->userAttr = NULL;
583 rec->listCName = NULL;
584 rec->listFName = NULL;
585 rec->listLName = NULL;
586 rec->listNName = NULL;
587 rec->listAddress = NULL;
588 rec->listID = NULL;
592 * Read file data into address cache.
593 * Note that one LDIF record identifies one entity uniquely with the
594 * distinguished name (dn) tag. Each person can have multiple E-Mail
595 * addresses. Also, each person can have many common name (cn) tags.
597 * \param ldifFile LDIF import control object.
598 * \param cache Address cache to be populated with data.
600 static void ldif_read_file( LdifFile *ldifFile, AddressCache *cache ) {
601 gchar *tagName = NULL, *tagValue = NULL;
602 gchar *lastTag = NULL, *fullValue = NULL;
603 GSList *listValue = NULL;
604 gboolean flagEOF = FALSE, flagEOR = FALSE;
605 gboolean flag64 = FALSE, last64 = FALSE;
606 Ldif_ParsedRec *rec;
607 long posEnd = 0L;
608 long posCur = 0L;
609 GHashTable *hashField;
610 gsize len;
612 hashField = ldifFile->hashFields;
613 rec = g_new0( Ldif_ParsedRec, 1 );
614 ldif_clear_rec( rec );
616 /* Find EOF for progress indicator */
617 fseek( ldifFile->file, 0L, SEEK_END );
618 posEnd = ftell( ldifFile->file );
619 fseek( ldifFile->file, 0L, SEEK_SET );
621 while( ! flagEOF ) {
622 gchar *line = ldif_get_line( ldifFile );
624 posCur = ftell( ldifFile->file );
625 if( ldifFile->cbProgress ) {
626 /* Call progress indicator */
627 ( ldifFile->cbProgress ) ( ldifFile, & posEnd, & posCur );
630 flag64 = FALSE;
631 if( line == NULL ) {
632 flagEOF = flagEOR = TRUE;
634 else if( *line == '\0' ) {
635 flagEOR = TRUE;
638 if( flagEOR ) {
639 /* EOR, Output address data */
640 if( lastTag ) {
641 /* Save record */
642 fullValue = mgu_list_coalesce( listValue );
643 if (fullValue && last64) {
644 gchar *tmp = g_base64_decode_zero(fullValue, &len);
645 g_free(fullValue);
646 fullValue = tmp;
649 ldif_add_value( rec, lastTag, fullValue, hashField );
650 /* ldif_print_record( rec, stdout ); */
651 ldif_build_items( ldifFile, rec, cache );
652 ldif_clear_rec( rec );
653 g_free( lastTag );
654 g_slist_free_full( listValue, g_free );
655 g_free(fullValue);
656 lastTag = NULL;
657 listValue = NULL;
658 last64 = FALSE;
661 if( line ) {
662 flagEOR = FALSE;
663 if( *line == ' ' ) {
664 /* Continuation line */
665 listValue = g_slist_append(
666 listValue, g_strdup( line+1 ) );
668 else if( *line == '=' ) {
669 /* Base-64 encoded continuation field */
670 listValue = g_slist_append(
671 listValue, g_strdup( line ) );
673 else {
674 /* Parse line */
675 tagName = ldif_get_tagname( line, &flag64 );
676 if( tagName ) {
677 tagValue = ldif_get_tagvalue( line );
678 if( tagValue ) {
679 if( lastTag ) {
680 /* Save data */
681 fullValue =
682 mgu_list_coalesce( listValue );
683 if (fullValue && last64) {
684 gchar *tmp = g_base64_decode_zero(fullValue, &len);
685 g_free(fullValue);
686 fullValue = tmp;
688 /* Base-64 encoded data */
690 if( last64 ) {
691 ldif_dump_b64( fullValue );
695 ldif_add_value(
696 rec, lastTag, fullValue,
697 hashField );
698 g_free( lastTag );
699 g_slist_free_full( listValue, g_free );
700 lastTag = NULL;
701 listValue = NULL;
704 lastTag = g_strdup( tagName );
705 listValue = g_slist_append(
706 listValue,
707 g_strdup( tagValue ) );
708 g_free( tagValue );
709 last64 = flag64;
711 g_free( tagName );
715 g_free( line );
718 /* Release data */
719 ldif_clear_rec( rec );
720 g_free( rec );
721 g_free( lastTag );
722 g_slist_free_full( listValue, g_free );
726 * Add list of field names to hash table.
727 * \param table Hashtable.
728 * \param list List of fields.
730 static void ldif_hash_add_list( GHashTable *table, GSList *list ) {
731 GSList *node = list;
733 /* mgu_print_list( list, stdout ); */
734 while( node ) {
735 gchar *tag = node->data;
736 if( ! g_hash_table_lookup( table, tag ) ) {
737 Ldif_FieldRec *rec = NULL;
738 gchar *key = g_utf8_strdown( tag, -1 );
740 rec = ldif_create_fieldrec( tag );
741 if( g_utf8_collate( key, LDIF_TAG_DN ) == 0 ) {
742 rec->reserved = rec->selected = TRUE;
743 rec->userName = g_strdup( "dn" );
745 else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_COMMONNAME, -1 ) ) == 0 ) {
746 rec->reserved = rec->selected = TRUE;
747 rec->userName = g_strdup( _( "Display Name" ) );
749 else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_FIRSTNAME, -1 ) ) == 0 ) {
750 rec->reserved = rec->selected = TRUE;
751 rec->userName = g_strdup( _( "First Name" ) );
753 else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_LASTNAME, -1 ) ) == 0 ) {
754 rec->reserved = rec->selected = TRUE;
755 rec->userName = g_strdup( _( "Last Name" ) );
757 else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_NICKNAME, -1 ) ) == 0 ) {
758 rec->reserved = rec->selected = TRUE;
759 rec->userName = g_strdup( _( "Nick Name" ) );
761 else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_EMAIL, -1 ) ) == 0 ) {
762 rec->reserved = rec->selected = TRUE;
763 rec->userName = g_strdup( _( "Email Address" ) );
765 g_hash_table_insert( table, key, rec );
767 node = g_slist_next( node );
772 * Sorted list comparison function.
773 * \param ptr1 First field.
774 * \param ptr2 Second field.
775 * \return <code>-1, 0, +1</code> if first record less than, equal,
776 * greater than second.
778 static gint ldif_field_compare( gconstpointer ptr1, gconstpointer ptr2 ) {
779 const Ldif_FieldRec *rec1 = ptr1;
780 const Ldif_FieldRec *rec2 = ptr2;
782 if( rec1->reserved ) {
783 if( ! rec2->reserved ) {
784 return +1;
787 else {
788 if( rec2->reserved ) {
789 return -1;
792 return g_utf8_collate( rec1->tagName, rec2->tagName );
796 * Append hash table entry to list - visitor function.
797 * \param key Key.
798 * \param value Data value.
799 * \param data User data (the LDIF import control object).
801 static void ldif_hash2list_vis( gpointer key, gpointer value, gpointer data ) {
802 LdifFile *ldf = data;
803 ldf->tempList =
804 g_list_insert_sorted( ldf->tempList, value, ldif_field_compare );
808 * Read tag names for file data.
809 * \param ldifFile LDIF import control object.
811 static void ldif_read_tag_list( LdifFile *ldifFile ) {
812 gchar *tagName = NULL;
813 GSList *listTags = NULL;
814 gboolean flagEOF = FALSE, flagEOR = FALSE, flagMail = FALSE;
815 gboolean flag64 = FALSE;
816 long posEnd = 0L;
817 long posCur = 0L;
819 /* Clear hash table */
820 g_hash_table_foreach_remove(
821 ldifFile->hashFields, ldif_hash_free_vis, NULL );
823 /* Find EOF for progress indicator */
824 fseek( ldifFile->file, 0L, SEEK_END );
825 posEnd = ftell( ldifFile->file );
826 fseek( ldifFile->file, 0L, SEEK_SET );
828 if (posEnd == 0) {
829 ldifFile->retVal = MGU_EOF;
830 return;
833 /* Process file */
834 while( ! flagEOF ) {
835 gchar *line = ldif_get_line( ldifFile );
836 posCur = ftell( ldifFile->file );
837 if( ldifFile->cbProgress ) {
838 /* Call progress indicator */
839 ( ldifFile->cbProgress ) ( ldifFile, & posEnd, & posCur );
842 flag64 = FALSE;
843 if( line == NULL ) {
844 flagEOF = flagEOR = TRUE;
846 else if( *line == '\0' ) {
847 flagEOR = TRUE;
850 if( flagEOR ) {
851 /* EOR, Output address data */
852 /* Save field list to hash table */
853 if( flagMail ) {
854 ldif_hash_add_list(
855 ldifFile->hashFields, listTags );
857 g_slist_free_full( listTags, g_free );
858 listTags = NULL;
859 flagMail = FALSE;
861 if( line ) {
862 flagEOR = FALSE;
863 if( *line == ' ' ) {
864 /* Continuation line */
866 else if( *line == '=' ) {
867 /* Base-64 encoded continuation field */
869 else {
870 /* Parse line */
871 tagName = ldif_get_tagname( line, &flag64 );
872 if( tagName ) {
873 /* Add tag to list */
874 listTags = g_slist_append( listTags, tagName );
876 if( g_utf8_collate(
877 tagName, LDIF_TAG_EMAIL ) == 0 )
879 flagMail = TRUE;
881 } else {
882 g_strstrip(line);
883 if (*line != '\0') {
884 debug_print("ldif: bad format: '%s'\n", line);
885 ldifFile->retVal = MGU_BAD_FORMAT;
890 g_free( line );
893 /* Release data */
894 g_slist_free_full( listTags, g_free );
895 listTags = NULL;
899 * Read file into list. Main entry point
900 * \param ldifFile LDIF import control object.
901 * \param cache Address cache to load.
902 * \return Status code.
904 gint ldif_import_data( LdifFile *ldifFile, AddressCache *cache ) {
905 cm_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS );
906 ldifFile->retVal = MGU_SUCCESS;
907 addrcache_clear( cache );
908 cache->dataRead = FALSE;
909 ldif_open_file( ldifFile );
910 if( ldifFile->retVal == MGU_SUCCESS ) {
911 /* Read data into the cache */
912 ldif_read_file( ldifFile, cache );
913 ldif_close_file( ldifFile );
915 /* Mark cache */
916 cache->modified = FALSE;
917 cache->dataRead = TRUE;
919 return ldifFile->retVal;
923 * Process entire file reading list of unique fields. List of fields may be
924 * accessed with the <code>ldif_get_fieldlist()</code> function.
925 * \param ldifFile LDIF import control object.
926 * \return Status code.
928 gint ldif_read_tags( LdifFile *ldifFile ) {
929 cm_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS );
930 ldifFile->retVal = MGU_SUCCESS;
931 if( ldifFile->dirtyFlag ) {
932 ldif_open_file( ldifFile );
933 if( ldifFile->retVal == MGU_SUCCESS ) {
934 /* Read data into the cache */
935 ldif_read_tag_list( ldifFile );
936 ldif_close_file( ldifFile );
937 ldifFile->dirtyFlag = FALSE;
938 ldifFile->accessFlag = TRUE;
941 return ldifFile->retVal;
945 * Return list of fields for LDIF file.
946 * \param ldifFile LDIF import control object.
947 * \return Linked list of <code>Ldif_FieldRec</code> objects. This list may be
948 * <code>g_free()</code>. Note that the objects in the list should not
949 * be freed since they refer to objects inside the internal cache.
950 * These objects will be freed when LDIF file object is freed.
952 GList *ldif_get_fieldlist( LdifFile *ldifFile ) {
953 GList *list = NULL;
955 cm_return_val_if_fail( ldifFile != NULL, NULL );
956 if( ldifFile->hashFields ) {
957 ldifFile->tempList = NULL;
958 g_hash_table_foreach( ldifFile->hashFields, ldif_hash2list_vis, ldifFile );
959 list = ldifFile->tempList;
960 ldifFile->tempList = NULL;
962 return list;
966 * Output LDIF name-value pair to stream. Only non-empty names and values will
967 * be output to file.
968 * \param stream File output stream.
969 * \param name Name.
970 * \param value Data value.
971 * \return <i>TRUE</i> if data output.
973 gboolean ldif_write_value( FILE *stream, const gchar *name, const gchar *value ) {
974 if( name == NULL ) return FALSE;
975 if( value == NULL ) return FALSE;
976 if( strlen( name ) < 1 ) return FALSE;
977 if( strlen( value ) < 1 ) return FALSE;
978 fprintf( stream, "%s: ", name );
979 fprintf( stream, "%s\n", value );
980 return TRUE;
984 * Output LDIF End of Record to stream.
985 * \param stream File output stream.
986 * \return <i>TRUE</i> if data output.
988 void ldif_write_eor( FILE *stream ) {
989 /* Simple but caller should not need to know how to end record. */
990 fprintf( stream, "\n" );
994 * ============================================================================
995 * End of Source.
996 * ============================================================================