Forgot to adjust default window size
[claws.git] / src / ldif.c
blob93ce80000297fb1b1c67a85419d17f67cbbe3720
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"
36 #define LDIF_SEP_TAG ':'
37 #define LDIF_LANG_TAG ';'
39 /**
40 * Create new object.
41 * \return Initialized LDIF file object.
43 LdifFile *ldif_create() {
44 LdifFile *ldifFile;
45 ldifFile = g_new0( LdifFile, 1 );
46 ldifFile->path = NULL;
47 ldifFile->file = NULL;
48 ldifFile->hashFields = g_hash_table_new( g_str_hash, g_str_equal );
49 ldifFile->tempList = NULL;
50 ldifFile->dirtyFlag = TRUE;
51 ldifFile->accessFlag = FALSE;
52 ldifFile->retVal = MGU_SUCCESS;
53 ldifFile->cbProgress = NULL;
54 ldifFile->importCount = 0;
55 return ldifFile;
58 /**
59 * Specify full file specification of LDIF file.
60 * \param ldifFile LDIF import control object.
61 * \param value Value of access flag.
63 void ldif_set_file( LdifFile *ldifFile, const gchar *value ) {
64 cm_return_if_fail( ldifFile != NULL );
66 if( ldifFile->path ) {
67 if( strcmp( ldifFile->path, value ) != 0 )
68 ldifFile->dirtyFlag = TRUE;
70 else {
71 ldifFile->dirtyFlag = TRUE;
73 ldifFile->path = mgu_replace_string( ldifFile->path, value );
74 g_strstrip( ldifFile->path );
75 ldifFile->importCount = 0;
78 /**
79 * Set the file access indicator.
80 * \param ldifFile LDIF import control object.
81 * \param value File specification.
83 void ldif_set_accessed( LdifFile *ldifFile, const gboolean value ) {
84 cm_return_if_fail( ldifFile != NULL );
85 ldifFile->accessFlag = value;
88 /**
89 * Create field record object.
90 * \return Initialized LDIF field object.
92 static Ldif_FieldRec *ldif_create_fieldrec( const gchar *field ) {
93 Ldif_FieldRec *rec = g_new0( Ldif_FieldRec, 1 );
94 rec->tagName = g_strdup( field );
95 rec->userName = NULL;
96 rec->reserved = FALSE;
97 rec->selected = FALSE;
98 return rec;
102 * Free field record object.
103 * \param rec LDIF field object.
105 static void ldif_free_fieldrec( Ldif_FieldRec *rec ) {
106 if( rec ) {
107 g_free( rec->tagName );
108 g_free( rec->userName );
109 rec->tagName = NULL;
110 rec->userName = NULL;
111 rec->reserved = FALSE;
112 rec->selected = FALSE;
113 g_free( rec );
118 * Set user name for field record.
119 * \param rec LDIF field object.
120 * \param value User name to set. Note that reserved fields cannot be
121 * named.
123 void ldif_field_set_name( Ldif_FieldRec *rec, const gchar *value ) {
124 cm_return_if_fail( rec != NULL );
126 if( ! rec->reserved ) {
127 rec->userName = mgu_replace_string( rec->userName, value );
128 g_strstrip( rec->userName );
133 * Specify selection for field record.
134 * \param rec LDIF field object.
135 * \param value Set to <i>TRUE</i> to select field. Note that reserved
136 * fields cannot be unselected.
138 void ldif_field_set_selected( Ldif_FieldRec *rec, const gboolean value ) {
139 cm_return_if_fail( rec != NULL );
141 if( ! rec->reserved ) {
142 rec->selected = value;
147 * Toggle selection for field record. Note that reserved fields cannot be
148 * toggled.
149 * \param rec LDIF field object.
151 void ldif_field_toggle( Ldif_FieldRec *rec ) {
152 cm_return_if_fail( rec != NULL );
154 if( ! rec->reserved ) {
155 rec->selected = !rec->selected;
160 * Free hash table entry visitor function.
161 * \param key Key.
162 * \param value Value (the LDIF field record).
163 * \param data User data.
164 * \return <code>-1</code>.
166 static gint ldif_hash_free_vis( gpointer key, gpointer value, gpointer data ) {
167 ldif_free_fieldrec( ( Ldif_FieldRec * ) value );
168 return -1;
172 * Free up object by releasing internal memory.
173 * \param ldifFile LDIF import control object.
175 void ldif_free( LdifFile *ldifFile ) {
176 cm_return_if_fail( ldifFile != NULL );
178 /* Close file */
179 if( ldifFile->file ) fclose( ldifFile->file );
181 /* Free internal stuff */
182 g_free( ldifFile->path );
184 /* Free field list */
185 g_hash_table_foreach_remove( ldifFile->hashFields, ldif_hash_free_vis, NULL );
186 g_hash_table_destroy( ldifFile->hashFields );
187 ldifFile->hashFields = NULL;
189 /* Clear pointers */
190 ldifFile->file = NULL;
191 ldifFile->path = NULL;
192 ldifFile->retVal = MGU_SUCCESS;
193 ldifFile->tempList = NULL;
194 ldifFile->dirtyFlag = FALSE;
195 ldifFile->accessFlag = FALSE;
196 ldifFile->cbProgress = NULL;
198 /* Now release file object */
199 g_free( ldifFile );
203 * Open file for read.
204 * \param ldifFile LDIF import control object.
205 * \return <i>TRUE</i> if file opened successfully.
207 static gint ldif_open_file( LdifFile* ldifFile ) {
208 /* g_print( "Opening file\n" ); */
209 if( ldifFile->path ) {
210 ldifFile->file = g_fopen( ldifFile->path, "rb" );
211 if( ! ldifFile->file ) {
212 /* g_print( "can't open %s\n", ldifFile->path ); */
213 ldifFile->retVal = MGU_OPEN_FILE;
214 return ldifFile->retVal;
217 else {
218 /* g_print( "file not specified\n" ); */
219 ldifFile->retVal = MGU_NO_FILE;
220 return ldifFile->retVal;
223 /* Setup a buffer area */
224 ldifFile->retVal = MGU_SUCCESS;
225 return ldifFile->retVal;
229 * Close file.
230 * \param ldifFile LDIF import control object.
232 static void ldif_close_file( LdifFile *ldifFile ) {
233 cm_return_if_fail( ldifFile != NULL );
234 if( ldifFile->file ) fclose( ldifFile->file );
235 ldifFile->file = NULL;
239 * Read line of text from file.
240 * \param ldifFile LDIF import control object.
241 * \return ptr to buffer where line starts.
243 static gchar *ldif_get_line( LdifFile *ldifFile ) {
244 gchar *buf = g_malloc(LDIFBUFSIZE);
245 gint ch;
246 int i = 0;
247 int cur_alloc = LDIFBUFSIZE;
249 if( feof( ldifFile->file ) ) {
250 g_free(buf);
251 return NULL;
254 while( i < cur_alloc-1 ) {
255 ch = fgetc( ldifFile->file );
256 if (ferror( ldifFile->file ))
257 ldifFile->retVal = MGU_ERROR_READ;
258 if( ch == '\0' || ch == EOF ) {
259 if( i == 0 ) return NULL;
260 break;
262 #if HAVE_DOSISH_SYSTEM
263 #else
264 if( ch == '\r' )
265 continue;
266 #endif
267 if( ch == '\n' )
268 break;
269 buf[i] = ch;
270 i++;
271 if (i == cur_alloc-1 && cur_alloc < LDIFBUFSIZE * 32) {
272 cur_alloc += LDIFBUFSIZE;
273 buf = g_realloc(buf, cur_alloc);
276 buf[i] = '\0';
278 /* Return a copy of buffer */
279 return g_strdup( buf );
283 * Parse tag name from line buffer.
284 * \param line Buffer.
285 * \param flag64 Base-64 encoder flag.
286 * \return Buffer containing the tag name, or NULL if no delimiter char found.
287 * If a double delimiter (::) is found, flag64 is set.
289 static gchar *ldif_get_tagname( char* line, gboolean *flag64 ) {
290 gint len = 0;
291 gchar *tag = NULL;
292 gchar *lptr = line;
293 gchar *sptr = NULL;
295 while( *lptr++ ) {
296 /* Check for language tag */
297 if( *lptr == LDIF_LANG_TAG ) {
298 if( sptr == NULL ) sptr = lptr;
301 /* Check for delimiter */
302 if( *lptr == LDIF_SEP_TAG ) {
303 if( sptr ) {
304 len = sptr - line;
306 else {
307 len = lptr - line;
310 /* Base-64 encoding? */
311 if( * ++lptr == LDIF_SEP_TAG ) *flag64 = TRUE;
313 tag = g_strndup( line, len+1 );
314 tag[ len ] = '\0';
315 return tag;
318 return tag;
322 * Parse tag value from line buffer.
323 * \param line Buffer.
324 * \return Buffer containing the tag value. Empty string is returned if
325 * no delimiter char found.
327 static gchar *ldif_get_tagvalue( gchar* line ) {
328 gchar *value = NULL;
329 gchar *start = NULL;
330 gchar *lptr;
331 gint len = 0;
333 for( lptr = line; *lptr; lptr++ ) {
334 if( *lptr == LDIF_SEP_TAG ) {
335 if( ! start )
336 start = lptr + 1;
339 if( start ) {
340 if( *start == LDIF_SEP_TAG ) start++;
341 len = lptr - start;
342 value = g_strndup( start, len+1 );
343 g_strstrip( value );
345 else {
346 /* Ensure that we get an empty string */
347 value = g_strndup( "", 1 );
349 value[ len ] = '\0';
350 return value;
354 * Parsed address data record.
356 typedef struct _Ldif_ParsedRec_ Ldif_ParsedRec;
357 struct _Ldif_ParsedRec_ {
358 GSList *listCName;
359 GSList *listFName;
360 GSList *listLName;
361 GSList *listNName;
362 GSList *listAddress;
363 GSList *listID;
364 GSList *userAttr;
368 * User attribute data record.
370 typedef struct _Ldif_UserAttr_ Ldif_UserAttr;
371 struct _Ldif_UserAttr_ {
372 gchar *name;
373 gchar *value;
377 * Build an address list entry and append to list of address items in the
378 * address cache. Name is formatted as "<first-name> <last-name>".
379 * \param ldifFile LDIF import control object.
380 * \param rec LDIF field object.
381 * \param cache Address cache to be populated with data.
383 static void ldif_build_items(
384 LdifFile *ldifFile, Ldif_ParsedRec *rec, AddressCache *cache )
386 GSList *nodeFirst;
387 GSList *nodeAddress;
388 GSList *nodeAttr;
389 gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
390 gchar *nickName = NULL;
391 gint iLen = 0, iLenT = 0;
392 ItemPerson *person;
393 ItemEMail *email;
395 nodeAddress = rec->listAddress;
396 // if( nodeAddress == NULL ) return;
398 /* Find longest first name in list */
399 nodeFirst = rec->listFName;
400 while( nodeFirst ) {
401 if( firstName == NULL ) {
402 firstName = nodeFirst->data;
403 iLen = strlen( firstName );
405 else {
406 if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
407 firstName = nodeFirst->data;
408 iLen = iLenT;
411 nodeFirst = g_slist_next( nodeFirst );
414 /* Format name */
415 if( rec->listLName ) {
416 lastName = rec->listLName->data;
419 if( firstName ) {
420 if( lastName ) {
421 fullName = g_strdup_printf(
422 "%s %s", firstName, lastName );
424 else {
425 fullName = g_strdup_printf( "%s", firstName );
428 else {
429 if( lastName ) {
430 fullName = g_strdup_printf( "%s", lastName );
434 if (!fullName || strlen(fullName) == 0) {
435 g_free(fullName);
436 fullName = NULL;
437 if (rec->listCName)
438 fullName = g_strdup(rec->listCName->data);
441 if( fullName ) {
442 g_strstrip( fullName );
445 if( rec->listNName ) {
446 nickName = rec->listNName->data;
449 person = addritem_create_item_person();
450 addritem_person_set_common_name( person, fullName );
451 addritem_person_set_first_name( person, firstName );
452 addritem_person_set_last_name( person, lastName );
453 addritem_person_set_nick_name( person, nickName );
454 addrcache_id_person( cache, person );
455 addrcache_add_person( cache, person );
456 ++ldifFile->importCount;
458 /* Add address item */
459 while( nodeAddress ) {
460 email = addritem_create_item_email();
461 addritem_email_set_address( email, nodeAddress->data );
462 addrcache_id_email( cache, email );
463 addrcache_person_add_email( cache, person, email );
464 nodeAddress = g_slist_next( nodeAddress );
466 g_free( fullName );
467 fullName = firstName = lastName = NULL;
469 /* Add user attributes */
470 nodeAttr = rec->userAttr;
471 while( nodeAttr ) {
472 Ldif_UserAttr *attr = nodeAttr->data;
473 UserAttribute *attrib = addritem_create_attribute();
474 addritem_attrib_set_name( attrib, attr->name );
475 addritem_attrib_set_value( attrib, attr->value );
476 addritem_person_add_attribute( person, attrib );
477 nodeAttr = g_slist_next( nodeAttr );
479 nodeAttr = NULL;
483 * Add selected field as user attribute.
484 * \param rec LDIF field object.
485 * \param tagName LDIF tag name.
486 * \param tagValue Data value.
487 * \param hashField Hash table to populate.
489 static void ldif_add_user_attr(
490 Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue,
491 GHashTable *hashField )
493 Ldif_FieldRec *fld = NULL;
494 Ldif_UserAttr *attr = NULL;
495 gchar *name;
497 fld = g_hash_table_lookup( hashField, tagName );
498 if( fld ) {
499 if( ! fld->selected ) return;
501 name = fld->tagName;
502 if( fld->userName ) {
503 name = fld->userName;
505 attr = g_new0( Ldif_UserAttr, 1 );
506 attr->name = g_strdup( name );
507 attr->value = g_strdup( tagValue );
508 rec->userAttr = g_slist_append( rec->userAttr, attr );
513 * Add value to parsed data.
514 * \param rec LDIF field object.
515 * \param tagName LDIF tag name.
516 * \param tagValue Data value.
517 * \param hashField Hash table to populate.
519 static void ldif_add_value(
520 Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue,
521 GHashTable *hashField )
523 gchar *nm, *val;
525 nm = g_utf8_strdown( tagName, -1 );
526 if( tagValue ) {
527 val = g_strdup( tagValue );
529 else {
530 val = g_strdup( "" );
532 g_strstrip( val );
534 if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_COMMONNAME, -1 ) ) == 0 ) {
535 rec->listCName = g_slist_append( rec->listCName, val );
537 else if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_FIRSTNAME, -1 ) ) == 0 ) {
538 rec->listFName = g_slist_append( rec->listFName, val );
540 else if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_LASTNAME, -1 ) ) == 0 ) {
541 rec->listLName = g_slist_append( rec->listLName, val );
543 else if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_NICKNAME, -1 ) ) == 0 ) {
544 rec->listNName = g_slist_append( rec->listNName, val );
546 else if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_EMAIL, -1 ) ) == 0 ) {
547 rec->listAddress = g_slist_append( rec->listAddress, val );
549 else {
550 /* Add field as user attribute */
551 ldif_add_user_attr( rec, tagName, tagValue, hashField );
553 g_free( nm );
557 * Clear parsed data record.
558 * \param rec LDIF field object.
560 static void ldif_clear_rec( Ldif_ParsedRec *rec ) {
561 GSList *list;
563 /* Free up user attributes */
564 list = rec->userAttr;
565 while( list ) {
566 Ldif_UserAttr *attr = list->data;
567 g_free( attr->name );
568 g_free( attr->value );
569 g_free( attr );
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;
587 rec->listID = 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;
605 Ldif_ParsedRec *rec;
606 long posEnd = 0L;
607 long posCur = 0L;
608 GHashTable *hashField;
609 gsize len;
611 hashField = ldifFile->hashFields;
612 rec = g_new0( Ldif_ParsedRec, 1 );
613 ldif_clear_rec( rec );
615 /* Find EOF for progress indicator */
616 fseek( ldifFile->file, 0L, SEEK_END );
617 posEnd = ftell( ldifFile->file );
618 fseek( ldifFile->file, 0L, SEEK_SET );
620 while( ! flagEOF ) {
621 gchar *line = ldif_get_line( ldifFile );
623 posCur = ftell( ldifFile->file );
624 if( ldifFile->cbProgress ) {
625 /* Call progress indicator */
626 ( ldifFile->cbProgress ) ( ldifFile, & posEnd, & posCur );
629 flag64 = FALSE;
630 if( line == NULL ) {
631 flagEOF = flagEOR = TRUE;
633 else if( *line == '\0' ) {
634 flagEOR = TRUE;
637 if( flagEOR ) {
638 /* EOR, Output address data */
639 if( lastTag ) {
640 /* Save record */
641 fullValue = mgu_list_coalesce( listValue );
642 if (fullValue && last64) {
643 gchar *tmp = g_base64_decode_zero(fullValue, &len);
644 g_free(fullValue);
645 fullValue = tmp;
648 ldif_add_value( rec, lastTag, fullValue, hashField );
649 /* ldif_print_record( rec, stdout ); */
650 ldif_build_items( ldifFile, rec, cache );
651 ldif_clear_rec( rec );
652 g_free( lastTag );
653 mgu_free_list( listValue );
654 g_free(fullValue);
655 lastTag = NULL;
656 listValue = NULL;
657 last64 = FALSE;
660 if( line ) {
661 flagEOR = FALSE;
662 if( *line == ' ' ) {
663 /* Continuation line */
664 listValue = g_slist_append(
665 listValue, g_strdup( line+1 ) );
667 else if( *line == '=' ) {
668 /* Base-64 encoded continuation field */
669 listValue = g_slist_append(
670 listValue, g_strdup( line ) );
672 else {
673 /* Parse line */
674 tagName = ldif_get_tagname( line, &flag64 );
675 if( tagName ) {
676 tagValue = ldif_get_tagvalue( line );
677 if( tagValue ) {
678 if( lastTag ) {
679 /* Save data */
680 fullValue =
681 mgu_list_coalesce( listValue );
682 if (fullValue && last64) {
683 gchar *tmp = g_base64_decode_zero(fullValue, &len);
684 g_free(fullValue);
685 fullValue = tmp;
687 /* Base-64 encoded data */
689 if( last64 ) {
690 ldif_dump_b64( fullValue );
694 ldif_add_value(
695 rec, lastTag, fullValue,
696 hashField );
697 g_free( lastTag );
698 mgu_free_list( listValue );
699 lastTag = NULL;
700 listValue = NULL;
703 lastTag = g_strdup( tagName );
704 listValue = g_slist_append(
705 listValue,
706 g_strdup( tagValue ) );
707 g_free( tagValue );
708 last64 = flag64;
710 g_free( tagName );
714 g_free( line );
717 /* Release data */
718 ldif_clear_rec( rec );
719 g_free( rec );
720 g_free( lastTag );
721 mgu_free_list( listValue );
725 * Add list of field names to hash table.
726 * \param table Hashtable.
727 * \param list List of fields.
729 static void ldif_hash_add_list( GHashTable *table, GSList *list ) {
730 GSList *node = list;
732 /* mgu_print_list( list, stdout ); */
733 while( node ) {
734 gchar *tag = node->data;
735 if( ! g_hash_table_lookup( table, tag ) ) {
736 Ldif_FieldRec *rec = NULL;
737 gchar *key = g_utf8_strdown( tag, -1 );
739 rec = ldif_create_fieldrec( tag );
740 if( g_utf8_collate( key, LDIF_TAG_DN ) == 0 ) {
741 rec->reserved = rec->selected = TRUE;
742 rec->userName = g_strdup( "dn" );
744 else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_COMMONNAME, -1 ) ) == 0 ) {
745 rec->reserved = rec->selected = TRUE;
746 rec->userName = g_strdup( _( "Display Name" ) );
748 else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_FIRSTNAME, -1 ) ) == 0 ) {
749 rec->reserved = rec->selected = TRUE;
750 rec->userName = g_strdup( _( "First Name" ) );
752 else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_LASTNAME, -1 ) ) == 0 ) {
753 rec->reserved = rec->selected = TRUE;
754 rec->userName = g_strdup( _( "Last Name" ) );
756 else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_NICKNAME, -1 ) ) == 0 ) {
757 rec->reserved = rec->selected = TRUE;
758 rec->userName = g_strdup( _( "Nick Name" ) );
760 else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_EMAIL, -1 ) ) == 0 ) {
761 rec->reserved = rec->selected = TRUE;
762 rec->userName = g_strdup( _( "Email Address" ) );
764 g_hash_table_insert( table, key, rec );
766 node = g_slist_next( node );
771 * Sorted list comparison function.
772 * \param ptr1 First field.
773 * \param ptr2 Second field.
774 * \return <code>-1, 0, +1</code> if first record less than, equal,
775 * greater than second.
777 static gint ldif_field_compare( gconstpointer ptr1, gconstpointer ptr2 ) {
778 const Ldif_FieldRec *rec1 = ptr1;
779 const Ldif_FieldRec *rec2 = ptr2;
781 if( rec1->reserved ) {
782 if( ! rec2->reserved ) {
783 return +1;
786 else {
787 if( rec2->reserved ) {
788 return -1;
791 return g_utf8_collate( rec1->tagName, rec2->tagName );
795 * Append hash table entry to list - visitor function.
796 * \param key Key.
797 * \param value Data value.
798 * \param data User data (the LDIF import control object).
800 static void ldif_hash2list_vis( gpointer key, gpointer value, gpointer data ) {
801 LdifFile *ldf = data;
802 ldf->tempList =
803 g_list_insert_sorted( ldf->tempList, value, ldif_field_compare );
807 * Read tag names for file data.
808 * \param ldifFile LDIF import control object.
810 static void ldif_read_tag_list( LdifFile *ldifFile ) {
811 gchar *tagName = NULL;
812 GSList *listTags = NULL;
813 gboolean flagEOF = FALSE, flagEOR = FALSE, flagMail = FALSE;
814 gboolean flag64 = FALSE;
815 long posEnd = 0L;
816 long posCur = 0L;
818 /* Clear hash table */
819 g_hash_table_foreach_remove(
820 ldifFile->hashFields, ldif_hash_free_vis, NULL );
822 /* Find EOF for progress indicator */
823 fseek( ldifFile->file, 0L, SEEK_END );
824 posEnd = ftell( ldifFile->file );
825 fseek( ldifFile->file, 0L, SEEK_SET );
827 if (posEnd == 0) {
828 ldifFile->retVal = MGU_EOF;
829 return;
832 /* Process file */
833 while( ! flagEOF ) {
834 gchar *line = ldif_get_line( ldifFile );
835 posCur = ftell( ldifFile->file );
836 if( ldifFile->cbProgress ) {
837 /* Call progress indicator */
838 ( ldifFile->cbProgress ) ( ldifFile, & posEnd, & posCur );
841 flag64 = FALSE;
842 if( line == NULL ) {
843 flagEOF = flagEOR = TRUE;
845 else if( *line == '\0' ) {
846 flagEOR = TRUE;
849 if( flagEOR ) {
850 /* EOR, Output address data */
851 /* Save field list to hash table */
852 if( flagMail ) {
853 ldif_hash_add_list(
854 ldifFile->hashFields, listTags );
856 mgu_free_list( listTags );
857 listTags = NULL;
858 flagMail = FALSE;
860 if( line ) {
861 flagEOR = FALSE;
862 if( *line == ' ' ) {
863 /* Continuation line */
865 else if( *line == '=' ) {
866 /* Base-64 encoded continuation field */
868 else {
869 /* Parse line */
870 tagName = ldif_get_tagname( line, &flag64 );
871 if( tagName ) {
872 /* Add tag to list */
873 listTags = g_slist_append( listTags, tagName );
875 if( g_utf8_collate(
876 tagName, LDIF_TAG_EMAIL ) == 0 )
878 flagMail = TRUE;
880 } else {
881 g_strstrip(line);
882 if (*line != '\0') {
883 debug_print("ldif: bad format: '%s'\n", line);
884 ldifFile->retVal = MGU_BAD_FORMAT;
889 g_free( line );
892 /* Release data */
893 mgu_free_list( listTags );
894 listTags = NULL;
898 * Read file into list. Main entry point
899 * \param ldifFile LDIF import control object.
900 * \param cache Address cache to load.
901 * \return Status code.
903 gint ldif_import_data( LdifFile *ldifFile, AddressCache *cache ) {
904 cm_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS );
905 ldifFile->retVal = MGU_SUCCESS;
906 addrcache_clear( cache );
907 cache->dataRead = FALSE;
908 ldif_open_file( ldifFile );
909 if( ldifFile->retVal == MGU_SUCCESS ) {
910 /* Read data into the cache */
911 ldif_read_file( ldifFile, cache );
912 ldif_close_file( ldifFile );
914 /* Mark cache */
915 cache->modified = FALSE;
916 cache->dataRead = TRUE;
918 return ldifFile->retVal;
922 * Process entire file reading list of unique fields. List of fields may be
923 * accessed with the <code>ldif_get_fieldlist()</code> function.
924 * \param ldifFile LDIF import control object.
925 * \return Status code.
927 gint ldif_read_tags( LdifFile *ldifFile ) {
928 cm_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS );
929 ldifFile->retVal = MGU_SUCCESS;
930 if( ldifFile->dirtyFlag ) {
931 ldif_open_file( ldifFile );
932 if( ldifFile->retVal == MGU_SUCCESS ) {
933 /* Read data into the cache */
934 ldif_read_tag_list( ldifFile );
935 ldif_close_file( ldifFile );
936 ldifFile->dirtyFlag = FALSE;
937 ldifFile->accessFlag = TRUE;
940 return ldifFile->retVal;
944 * Return list of fields for LDIF file.
945 * \param ldifFile LDIF import control object.
946 * \return Linked list of <code>Ldif_FieldRec</code> objects. This list may be
947 * <code>g_free()</code>. Note that the objects in the list should not
948 * be freed since they refer to objects inside the internal cache.
949 * These objects will be freed when LDIF file object is freed.
951 GList *ldif_get_fieldlist( LdifFile *ldifFile ) {
952 GList *list = NULL;
954 cm_return_val_if_fail( ldifFile != NULL, NULL );
955 if( ldifFile->hashFields ) {
956 ldifFile->tempList = NULL;
957 g_hash_table_foreach( ldifFile->hashFields, ldif_hash2list_vis, ldifFile );
958 list = ldifFile->tempList;
959 ldifFile->tempList = NULL;
961 return list;
965 * Output LDIF name-value pair to stream. Only non-empty names and values will
966 * be output to file.
967 * \param stream File output stream.
968 * \param name Name.
969 * \param value Data value.
970 * \return <i>TRUE</i> if data output.
972 gboolean ldif_write_value( FILE *stream, const gchar *name, const gchar *value ) {
973 if( name == NULL ) return FALSE;
974 if( value == NULL ) return FALSE;
975 if( strlen( name ) < 1 ) return FALSE;
976 if( strlen( value ) < 1 ) return FALSE;
977 fprintf( stream, "%s: ", name );
978 fprintf( stream, "%s\n", value );
979 return TRUE;
983 * Output LDIF End of Record to stream.
984 * \param stream File output stream.
985 * \return <i>TRUE</i> if data output.
987 void ldif_write_eor( FILE *stream ) {
988 /* Simple but caller should not need to know how to end record. */
989 fprintf( stream, "\n" );
993 * ============================================================================
994 * End of Source.
995 * ============================================================================