Statistics
| Revision:

root / src / ldif.c @ 1

History | View | Annotate | Download (22.8 KB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 2001 Match Grun
4
 *
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.
9
 *
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.
14
 *
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 */
19

    
20
/*
21
 * Functions necessary to access LDIF files (LDAP Data Interchange Format
22
 * files).
23
 */
24

    
25
#include <glib.h>
26
#include <string.h>
27
#include <sys/stat.h>
28

    
29
#include "mgutils.h"
30
#include "ldif.h"
31
#include "addritem.h"
32
#include "addrcache.h"
33

    
34
#include "base64.h"
35

    
36
/*
37
* Create new object.
38
*/
39
LdifFile *ldif_create() {
40
        LdifFile *ldifFile;
41
        ldifFile = g_new0( LdifFile, 1 );
42
        ldifFile->path = NULL;
43
        ldifFile->file = NULL;
44
        ldifFile->bufptr = ldifFile->buffer;
45
        ldifFile->hashFields = g_hash_table_new( g_str_hash, g_str_equal );
46
        ldifFile->tempList = NULL;
47
        ldifFile->dirtyFlag = TRUE;
48
        ldifFile->accessFlag = FALSE;
49
        ldifFile->retVal = MGU_SUCCESS;
50
        ldifFile->cbProgress = NULL;
51
        ldifFile->importCount = 0;
52
        return ldifFile;
53
}
54

    
55
/*
56
* Properties...
57
*/
58
void ldif_set_file( LdifFile *ldifFile, const gchar *value ) {
59
        g_return_if_fail( ldifFile != NULL );
60

    
61
        if( ldifFile->path ) {
62
                if( strcmp( ldifFile->path, value ) != 0 )
63
                        ldifFile->dirtyFlag = TRUE;
64
        }
65
        else {
66
                ldifFile->dirtyFlag = TRUE;
67
        }
68
        ldifFile->path = mgu_replace_string( ldifFile->path, value );
69
        g_strstrip( ldifFile->path );
70
        ldifFile->importCount = 0;
71
}
72
void ldif_set_accessed( LdifFile *ldifFile, const gboolean value ) {
73
        g_return_if_fail( ldifFile != NULL );
74
        ldifFile->accessFlag = value;
75
}
76

    
77
/*
78
* Register a callback function. When called, the function will be passed
79
* the following arguments:
80
*        LdifFile object,
81
*        File size (long),
82
*        Current position (long)
83
* This can be used for a progress indicator.
84
*/
85
void ldif_set_callback( LdifFile *ldifFile, void *func ) {
86
        ldifFile->cbProgress = func;
87
}
88

    
89
/*
90
* Create field record object.
91
*/
92
static Ldif_FieldRec *ldif_create_fieldrec( 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;
99
}
100

    
101
/*
102
* Free field record object.
103
*/
104
static void ldif_free_fieldrec( Ldif_FieldRec *rec ) {
105
        if( rec ) {
106
                g_free( rec->tagName );
107
                g_free( rec->userName );
108
                rec->tagName = NULL;
109
                rec->userName = NULL;
110
                rec->reserved = FALSE;
111
                rec->selected = FALSE;
112
                g_free( rec );
113
        }
114
}
115

    
116
/*
117
* Free hash table entry visitor function.
118
*/
119
static gint ldif_hash_free_vis( gpointer key, gpointer value, gpointer data ) {
120
        ldif_free_fieldrec( ( Ldif_FieldRec * ) value );
121
        value = NULL;
122
        key = NULL;
123
        return -1;
124
}
125

    
126
/*
127
* Free up object by releasing internal memory.
128
*/
129
void ldif_free( LdifFile *ldifFile ) {
130
        g_return_if_fail( ldifFile != NULL );
131

    
132
        /* Close file */
133
        if( ldifFile->file ) fclose( ldifFile->file );
134

    
135
        /* Free internal stuff */
136
        g_free( ldifFile->path );
137

    
138
        /* Free field list */
139
        g_hash_table_foreach_remove( ldifFile->hashFields, ldif_hash_free_vis, NULL );
140
        g_hash_table_destroy( ldifFile->hashFields );
141
        ldifFile->hashFields = NULL;
142

    
143
        /* Clear pointers */
144
        ldifFile->file = NULL;
145
        ldifFile->path = NULL;
146
        ldifFile->retVal = MGU_SUCCESS;
147
        ldifFile->tempList = NULL;
148
        ldifFile->dirtyFlag = FALSE;
149
        ldifFile->accessFlag = FALSE;
150
        ldifFile->cbProgress = NULL;
151

    
152
        /* Now release file object */
153
        g_free( ldifFile );
154
}
155

    
156
/*
157
* Display field record.
158
*/
159
void ldif_print_fieldrec( Ldif_FieldRec *rec, FILE *stream ) {
160
        fprintf( stream, "\ttag:\t%s", rec->reserved ? "yes" : "no" );
161
        fprintf( stream, "\t%s", rec->selected ? "yes" : "no" );
162
        fprintf( stream, "\t:%s:\t:%s:\n", rec->userName, rec->tagName );
163
}
164

    
165
/*
166
* Display field record.
167
 * 
168
*/
169
static void ldif_print_file_vis( gpointer key, gpointer value, gpointer data ) {
170
        Ldif_FieldRec *rec = value;
171
        FILE *stream = data;
172
        ldif_print_fieldrec( rec, stream );
173
}
174

    
175
/*
176
* Display object to specified stream.
177
*/
178
void ldif_print_file( LdifFile *ldifFile, FILE *stream ) {
179
        g_return_if_fail( ldifFile != NULL );
180
        fprintf( stream, "LDIF File:\n" );
181
        fprintf( stream, "file spec: '%s'\n", ldifFile->path );
182
        fprintf( stream, "  ret val: %d\n",   ldifFile->retVal );
183
        fprintf( stream, "   fields: {\n" );
184
        g_hash_table_foreach( ldifFile->hashFields, ldif_print_file_vis, stream );
185
        fprintf( stream, "} ---\n" );
186
}
187

    
188
/*
189
* Open file for read.
190
* return: TRUE if file opened successfully.
191
*/
192
static gint ldif_open_file( LdifFile* ldifFile ) {
193
        /* printf( "Opening file\n" ); */
194
        if( ldifFile->path ) {
195
                ldifFile->file = fopen( ldifFile->path, "rb" );
196
                if( ! ldifFile->file ) {
197
                        /* printf( "can't open %s\n", ldifFile->path ); */
198
                        ldifFile->retVal = MGU_OPEN_FILE;
199
                        return ldifFile->retVal;
200
                }
201
        }
202
        else {
203
                /* printf( "file not specified\n" ); */
204
                ldifFile->retVal = MGU_NO_FILE;
205
                return ldifFile->retVal;
206
        }
207

    
208
        /* Setup a buffer area */
209
        ldifFile->buffer[0] = '\0';
210
        ldifFile->bufptr = ldifFile->buffer;
211
        ldifFile->retVal = MGU_SUCCESS;
212
        return ldifFile->retVal;
213
}
214

    
215
/*
216
* Close file.
217
*/
218
static void ldif_close_file( LdifFile *ldifFile ) {
219
        g_return_if_fail( ldifFile != NULL );
220
        if( ldifFile->file ) fclose( ldifFile->file );
221
        ldifFile->file = NULL;
222
}
223

    
224
/*
225
* Read line of text from file.
226
* Return: ptr to buffer where line starts.
227
*/
228
static gchar *ldif_get_line( LdifFile *ldifFile ) {
229
        gchar buf[ LDIFBUFSIZE ];
230
        gint ch;
231
        gchar *ptr;
232

    
233
        if( feof( ldifFile->file ) ) return NULL;
234

    
235
        ptr = buf;
236
        while( TRUE ) {
237
                *ptr = '\0';
238
                ch = fgetc( ldifFile->file );
239
                if( ch == '\0' || ch == EOF ) {
240
                        if( *buf == '\0' ) return NULL;
241
                        break;
242
                }
243
#if HAVE_DOSISH_SYSTEM
244
#else
245
                if( ch == '\r' ) continue;
246
#endif
247
                if( ch == '\n' ) break;
248
                *ptr = ch;
249
                ptr++;
250
        }
251

    
252
        /* Return a copy of buffer */
253
        return g_strdup( buf );
254
}
255

    
256
/*
257
* Parse tag name from line buffer.
258
* Enter: line   Buffer.
259
*        flag64 Base-64 encoder flag.
260
* Return: Buffer containing the tag name, or NULL if no delimiter char found.
261
* If a double delimiter (::) is found, flag64 is set.
262
*/
263
static gchar *ldif_get_tagname( char* line, gboolean *flag64 ) {
264
        gint len = 0;
265
        gchar *tag = NULL;
266
        gchar *lptr = line;
267
        gchar *sptr = NULL;
268

    
269
        while( *lptr++ ) {
270
                /* Check for language tag */
271
                if( *lptr == LDIF_LANG_TAG ) {
272
                        if( sptr == NULL ) sptr = lptr;
273
                }
274

    
275
                /* Check for delimiter */
276
                if( *lptr == LDIF_SEP_TAG ) {
277
                        if( sptr ) {
278
                                len = sptr - line;
279
                        }
280
                        else {
281
                                len = lptr - line;
282
                        }
283

    
284
                        /* Base-64 encoding? */
285
                        if( * ++lptr == LDIF_SEP_TAG ) *flag64 = TRUE;
286

    
287
                        tag = g_strndup( line, len+1 );
288
                        tag[ len ] = '\0';
289
                        g_strdown( tag );
290
                        return tag;
291
                }
292
        }
293
        return tag;
294
}
295

    
296
/*
297
* Parse tag value from line buffer.
298
* Enter: line   Buffer.
299
* Return: Buffer containing the tag value. Empty string is returned if
300
* no delimiter char found.
301
*/
302
static gchar *ldif_get_tagvalue( gchar* line ) {
303
        gchar *value = NULL;
304
        gchar *start = NULL;
305
        gchar *lptr;
306
        gint len = 0;
307

    
308
        for( lptr = line; *lptr; lptr++ ) {
309
                if( *lptr == LDIF_SEP_TAG ) {
310
                        if( ! start )
311
                                start = lptr + 1;
312
                }
313
        }
314
        if( start ) {
315
                if( *start == LDIF_SEP_TAG ) start++;
316
                len = lptr - start;
317
                value = g_strndup( start, len+1 );
318
                g_strstrip( value );
319
        }
320
        else {
321
                /* Ensure that we get an empty string */
322
                value = g_strndup( "", 1 );
323
        }
324
        value[ len ] = '\0';
325
        return value;
326
}
327

    
328
#if 0
329
/*
330
* Dump linked lists of character strings (for debug).
331
*/
332
static void ldif_dump_lists( GSList *listName, GSList *listAddr, GSList *listRem, GSList *listID, FILE *stream ) {
333
        fprintf( stream, "dump name\n" );
334
        fprintf( stream, "------------\n" );
335
        mgu_print_list( listName, stdout );
336
        fprintf( stream, "dump address\n" );
337
        fprintf( stream, "------------\n" );
338
        mgu_print_list( listAddr, stdout );
339
        fprintf( stream, "dump remarks\n" );
340
        fprintf( stdout, "------------\n" );
341
        mgu_print_list( listRem, stdout );
342
        fprintf( stream, "dump id\n" );
343
        fprintf( stdout, "------------\n" );
344
        mgu_print_list( listID, stdout );
345
}
346
#endif
347

    
348
/*
349
* Parsed address data.
350
*/
351
typedef struct _Ldif_ParsedRec_ Ldif_ParsedRec;
352
struct _Ldif_ParsedRec_ {
353
        GSList *listCName;
354
        GSList *listFName;
355
        GSList *listLName;
356
        GSList *listNName;
357
        GSList *listAddress;
358
        GSList *listID;
359
        GSList *userAttr;
360
};
361

    
362
/*
363
* User attribute data.
364
*/
365
typedef struct _Ldif_UserAttr_ Ldif_UserAttr;
366
struct _Ldif_UserAttr_ {
367
        gchar *name;
368
        gchar *value;
369
};
370

    
371
/*
372
* Build an address list entry and append to list of address items. Name is formatted
373
* as "<first-name> <last-name>".
374
*/
375
static void ldif_build_items( LdifFile *ldifFile, Ldif_ParsedRec *rec, AddressCache *cache ) {
376
        GSList *nodeFirst;
377
        GSList *nodeAddress;
378
        GSList *nodeAttr;
379
        gchar *firstName = NULL, *lastName = NULL, *fullName = NULL, *nickName = NULL;
380
        gint iLen = 0, iLenT = 0;
381
        ItemPerson *person;
382
        ItemEMail *email;
383

    
384
        nodeAddress = rec->listAddress;
385
        if( nodeAddress == NULL ) return;
386

    
387
        /* Find longest first name in list */
388
        nodeFirst = rec->listFName;
389
        while( nodeFirst ) {
390
                if( firstName == NULL ) {
391
                        firstName = nodeFirst->data;
392
                        iLen = strlen( firstName );
393
                }
394
                else {
395
                        if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
396
                                firstName = nodeFirst->data;
397
                                iLen = iLenT;
398
                        }
399
                }
400
                nodeFirst = g_slist_next( nodeFirst );
401
        }
402

    
403
        /* Format name */
404
        if( rec->listLName ) {
405
                lastName = rec->listLName->data;
406
        }
407

    
408
        if( firstName ) {
409
                if( lastName ) {
410
                        fullName = g_strdup_printf( "%s %s", firstName, lastName );
411
                }
412
                else {
413
                        fullName = g_strdup_printf( "%s", firstName );
414
                }
415
        }
416
        else {
417
                if( lastName ) {
418
                        fullName = g_strdup_printf( "%s", lastName );
419
                }
420
        }
421
        if( fullName ) {
422
                g_strchug( fullName ); g_strchomp( fullName );
423
        }
424

    
425
        if( rec->listNName ) {
426
                nickName = rec->listNName->data;
427
        }
428

    
429
        person = addritem_create_item_person();
430
        addritem_person_set_common_name( person, fullName );
431
        addritem_person_set_first_name( person, firstName );
432
        addritem_person_set_last_name( person, lastName );
433
        addritem_person_set_nick_name( person, nickName );
434
        addrcache_id_person( cache, person );
435
        addrcache_add_person( cache, person );
436
        ++ldifFile->importCount;
437

    
438
        /* Add address item */
439
        while( nodeAddress ) {
440
                email = addritem_create_item_email();
441
                addritem_email_set_address( email, nodeAddress->data );
442
                addrcache_id_email( cache, email );
443
                addrcache_person_add_email( cache, person, email );
444
                nodeAddress = g_slist_next( nodeAddress );
445
        }
446
        g_free( fullName );
447
        fullName = firstName = lastName = NULL;
448

    
449
        /* Add user attributes */
450
        nodeAttr = rec->userAttr;
451
        while( nodeAttr ) {
452
                Ldif_UserAttr *attr = nodeAttr->data;
453
                UserAttribute *attrib = addritem_create_attribute();
454
                addritem_attrib_set_name( attrib, attr->name );
455
                addritem_attrib_set_value( attrib, attr->value );
456
                addritem_person_add_attribute( person, attrib );
457
                nodeAttr = g_slist_next( nodeAttr );
458
        }
459
        nodeAttr = NULL;
460
}
461

    
462
/*
463
* Add selected field as user attribute.
464
*/
465
static void ldif_add_user_attr( Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue, GHashTable *hashField ) {
466
        Ldif_FieldRec *fld = NULL;
467
        Ldif_UserAttr *attr = NULL;
468
        gchar *name;
469

    
470
        fld = g_hash_table_lookup( hashField, tagName );
471
        if( fld ) {
472
                if( fld->reserved ) return;
473
                if( ! fld->selected ) return;
474

    
475
                name = fld->tagName;
476
                if( fld->userName ) {
477
                        name = fld->userName;
478
                }
479
                attr = g_new0( Ldif_UserAttr, 1 );
480
                attr->name = g_strdup( name );
481
                attr->value = g_strdup( tagValue );
482
                rec->userAttr = g_slist_append( rec->userAttr, attr );
483
        }
484
}
485

    
486
/*
487
* Add value to parsed data.
488
*/
489
static void ldif_add_value( Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue, GHashTable *hashField ) {
490
        gchar *nm, *val;
491

    
492
        nm = g_strdup( tagName );
493
        g_strdown( nm );
494
        if( tagValue ) {
495
                val = g_strdup( tagValue );
496
        }
497
        else {
498
                val = g_strdup( "" );
499
        }
500
        g_strstrip( val );
501
        if( g_strcasecmp( nm, LDIF_TAG_COMMONNAME ) == 0 ) {
502
                rec->listCName = g_slist_append( rec->listCName, val );
503
        }
504
        else if( g_strcasecmp( nm, LDIF_TAG_FIRSTNAME ) == 0 ) {
505
                rec->listFName = g_slist_append( rec->listFName, val );
506
        }
507
        else if( g_strcasecmp( nm, LDIF_TAG_LASTNAME ) == 0 ) {
508
                rec->listLName = g_slist_append( rec->listLName, val );
509
        }
510
        else if( g_strcasecmp( nm, LDIF_TAG_NICKNAME ) == 0 ) {
511
                rec->listNName = g_slist_append( rec->listNName, val );
512
        }
513
        else if( g_strcasecmp( nm, LDIF_TAG_EMAIL ) == 0 ) {
514
                rec->listAddress = g_slist_append( rec->listAddress, val );
515
        }
516
        else {
517
                /* Add field as user attribute */
518
                ldif_add_user_attr( rec, tagName, tagValue, hashField );
519
        }
520
        g_free( nm );
521
}
522

    
523
/*
524
* Clear parsed data.
525
*/
526
static void ldif_clear_rec( Ldif_ParsedRec *rec ) {
527
        GSList *list;
528

    
529
        /* Free up user attributes */
530
        list = rec->userAttr;
531
        while( list ) {
532
                Ldif_UserAttr *attr = list->data;
533
                g_free( attr->name );
534
                g_free( attr->value );
535
                g_free( attr );
536
                list = g_slist_next( list );
537
        }
538
        g_slist_free( rec->userAttr );
539

    
540
        g_slist_free( rec->listCName );
541
        g_slist_free( rec->listFName );
542
        g_slist_free( rec->listLName );
543
        g_slist_free( rec->listNName );
544
        g_slist_free( rec->listAddress );
545
        g_slist_free( rec->listID );
546

    
547
        rec->userAttr = NULL;
548
        rec->listCName = NULL;
549
        rec->listFName = NULL;
550
        rec->listLName = NULL;
551
        rec->listNName = NULL;
552
        rec->listAddress = NULL;
553
        rec->listID = NULL;
554
}
555

    
556
#if 0
557
/*
558
* Print parsed data.
559
*/
560
static void ldif_print_record( Ldif_ParsedRec *rec, FILE *stream ) {
561
        GSList *list;
562

563
        fprintf( stream, "LDIF Parsed Record:\n" );
564
        fprintf( stream, "common name:" );
565
        mgu_print_list( rec->listCName, stream );
566
        if( ! rec->listCName ) fprintf( stream, "\n" );
567
        fprintf( stream, "first name:" );
568
        mgu_print_list( rec->listFName, stream );
569
        if( ! rec->listFName ) fprintf( stream, "\n" );
570
        fprintf( stream, "last name:" );
571
        mgu_print_list( rec->listLName, stream );
572
        if( ! rec->listLName ) fprintf( stream, "\n" );
573
        fprintf( stream, "nick name:" );
574
        mgu_print_list( rec->listNName, stream );
575
        if( ! rec->listNName ) fprintf( stream, "\n" );
576
        fprintf( stream, "address:" );
577
        mgu_print_list( rec->listAddress, stream );
578
        if( ! rec->listAddress ) fprintf( stream, "\n" );
579
        fprintf( stream, "id:" );
580
        mgu_print_list( rec->listID, stream );
581
        if( ! rec->listID ) fprintf( stream, "\n" );
582

583
        list = rec->userAttr;
584
        while( list ) {
585
                Ldif_UserAttr *attr = list->data;
586
                fprintf( stream, "n/v:\t%s:\t:%s:\n", attr->name, attr->value );
587
                list = g_slist_next( list );
588
        }
589
        list = NULL;
590
}
591

592
static void ldif_dump_b64( gchar *buf ) {
593
        Base64Decoder *decoder = NULL;
594
        gchar outBuf[8192];
595
        gint len;
596

597
        printf( "base-64 : inbuf : %s\n", buf );
598
        decoder = base64_decoder_new();
599
        len = base64_decoder_decode( decoder, buf, outBuf );
600
        if (len < 0) {
601
                printf( "base-64 : Bad BASE64 content\n" );
602
        }
603
        else {
604
                outBuf[len] = '\0';
605
                printf( "base-64 : %d : %s\n\n", len, outBuf );
606
        }
607
        base64_decoder_free( decoder );
608
        decoder = NULL;
609
}
610
#endif
611

    
612
/*
613
* Read file data into address cache.
614
* Note that one LDIF record identifies one entity uniquely with the
615
* distinguished name (dn) tag. Each person can have multiple E-Mail
616
* addresses. Also, each person can have many common name (cn) tags.
617
*/
618
static void ldif_read_file( LdifFile *ldifFile, AddressCache *cache ) {
619
        gchar *tagName = NULL, *tagValue = NULL;
620
        gchar *lastTag = NULL, *fullValue = NULL;
621
        GSList *listValue = NULL;
622
        gboolean flagEOF = FALSE, flagEOR = FALSE;
623
        gboolean flag64 = FALSE, last64 = FALSE;
624
        Ldif_ParsedRec *rec;
625
        long posEnd = 0L;
626
        long posCur = 0L;
627
        GHashTable *hashField;
628

    
629
        hashField = ldifFile->hashFields;
630
        rec = g_new0( Ldif_ParsedRec, 1 );
631
        ldif_clear_rec( rec );
632

    
633
        /* Find EOF for progress indicator */
634
        fseek( ldifFile->file, 0L, SEEK_END );
635
        posEnd = ftell( ldifFile->file );
636
        fseek( ldifFile->file, 0L, SEEK_SET );
637

    
638
        while( ! flagEOF ) {
639
                gchar *line =  ldif_get_line( ldifFile );
640

    
641
                posCur = ftell( ldifFile->file );
642
                if( ldifFile->cbProgress ) {
643
                        /* Call progress indicator */
644
                        ( ldifFile->cbProgress ) ( ldifFile, & posEnd, & posCur );
645
                }
646

    
647
                flag64 = FALSE;
648
                if( line == NULL ) {
649
                        flagEOF = flagEOR = TRUE;
650
                }
651
                else if( *line == '\0' ) {
652
                        flagEOR = TRUE;
653
                }
654

    
655
                if( flagEOR ) {
656
                        /* EOR, Output address data */
657
                        if( lastTag ) {
658
                                /* Save record */
659
                                fullValue = mgu_list_coalesce( listValue );
660

    
661
                                /* Base-64 encoded data */
662
                                /*
663
                                if( last64 ) {
664
                                        ldif_dump_b64( fullValue );
665
                                }
666
                                */
667

    
668
                                ldif_add_value( rec, lastTag, fullValue, hashField );
669
                                /* ldif_print_record( rec, stdout ); */
670
                                ldif_build_items( ldifFile, rec, cache );
671
                                ldif_clear_rec( rec );
672
                                g_free( lastTag );
673
                                mgu_free_list( listValue );
674
                                lastTag = NULL;
675
                                listValue = NULL;
676
                                last64 = FALSE;
677
                        }
678
                }
679
                if( line ) {
680
                        flagEOR = FALSE;
681
                        if( *line == ' ' ) {
682
                                /* Continuation line */
683
                                listValue = g_slist_append( listValue, g_strdup( line+1 ) );
684
                        }
685
                        else if( *line == '=' ) {
686
                                /* Base-64 encoded continuation field */
687
                                listValue = g_slist_append( listValue, g_strdup( line ) );
688
                        }
689
                        else {
690
                                /* Parse line */
691
                                tagName = ldif_get_tagname( line, &flag64 );
692
                                if( tagName ) {
693
                                        tagValue = ldif_get_tagvalue( line );
694
                                        if( tagValue ) {
695
                                                if( lastTag ) {
696
                                                        /* Save data */
697
                                                        fullValue = mgu_list_coalesce( listValue );
698
                                                        /* Base-64 encoded data */
699
                                                        /*
700
                                                        if( last64 ) {
701
                                                                ldif_dump_b64( fullValue );
702
                                                        }
703
                                                        */
704

    
705
                                                        ldif_add_value( rec, lastTag, fullValue, hashField );
706
                                                        g_free( lastTag );
707
                                                        mgu_free_list( listValue );
708
                                                        lastTag = NULL;
709
                                                        listValue = NULL;
710
                                                        last64 = FALSE;
711
                                                }
712

    
713
                                                lastTag = g_strdup( tagName );
714
                                                listValue = g_slist_append( listValue, g_strdup( tagValue ) );
715
                                                g_free( tagValue );
716
                                                last64 = flag64;
717
                                        }
718
                                        g_free( tagName );
719
                                }
720
                        }
721
                }
722
                g_free( line );
723
        }
724

    
725
        /* Release data */
726
        ldif_clear_rec( rec );
727
        g_free( rec );
728
        g_free( lastTag );
729
        mgu_free_list( listValue );
730
}
731

    
732
/*
733
* Add list of field names to hash table.
734
*/
735
static void ldif_hash_add_list( GHashTable *table, GSList *list ) {
736
        GSList *node = list;
737

    
738
        /* mgu_print_list( list, stdout ); */
739
        while( node ) {
740
                gchar *tag = node->data;
741
                if( ! g_hash_table_lookup( table, tag ) ) {
742
                        Ldif_FieldRec *rec = NULL;
743
                        gchar *key = g_strdup( tag );
744

    
745
                        rec = ldif_create_fieldrec( tag );
746
                        if( g_strcasecmp( tag, LDIF_TAG_COMMONNAME ) == 0 ) {
747
                                rec->reserved = TRUE;
748
                        }
749
                        else if( g_strcasecmp( tag, LDIF_TAG_FIRSTNAME ) == 0 ) {
750
                                rec->reserved = TRUE;
751
                        }
752
                        else if( g_strcasecmp( tag, LDIF_TAG_LASTNAME ) == 0 ) {
753
                                rec->reserved = TRUE;
754
                        }
755
                        else if( g_strcasecmp( tag, LDIF_TAG_NICKNAME ) == 0 ) {
756
                                rec->reserved = TRUE;
757
                        }
758
                        else if( g_strcasecmp( tag, LDIF_TAG_EMAIL ) == 0 ) {
759
                                rec->reserved = TRUE;
760
                        }
761
                        g_hash_table_insert( table, key, rec );
762
                }
763
                node = g_slist_next( node );
764
        }
765
}
766

    
767
/*
768
* Sorted list comparison function.
769
*/
770
static int ldif_field_compare( gconstpointer ptr1, gconstpointer ptr2 ) {
771
        const Ldif_FieldRec *rec1 = ptr1;
772
        const Ldif_FieldRec *rec2 = ptr2;
773
        return g_strcasecmp( rec1->tagName, rec2->tagName );
774
}
775

    
776
/*
777
* Append hash table entry to list - visitor function.
778
*/
779
static void ldif_hash2list_vis( gpointer key, gpointer value, gpointer data ) {
780
        LdifFile *ldf = data;
781
        ldf->tempList = g_list_insert_sorted( ldf->tempList, value, ldif_field_compare );
782
}
783

    
784
/*
785
* Read tag names for file data.
786
*/
787
static void ldif_read_tag_list( LdifFile *ldifFile ) {
788
        gchar *tagName = NULL;
789
        GSList *listTags = NULL;
790
        gboolean flagEOF = FALSE, flagEOR = FALSE, flagMail = FALSE;
791
        gboolean flag64 = FALSE;
792
        long posEnd = 0L;
793
        long posCur = 0L;
794

    
795
        /* Clear hash table */
796
        g_hash_table_foreach_remove( ldifFile->hashFields, ldif_hash_free_vis, NULL );
797

    
798
        /* Find EOF for progress indicator */
799
        fseek( ldifFile->file, 0L, SEEK_END );
800
        posEnd = ftell( ldifFile->file );
801
        fseek( ldifFile->file, 0L, SEEK_SET );
802

    
803
        /* Process file */
804
        while( ! flagEOF ) {
805
                gchar *line = ldif_get_line( ldifFile );
806

    
807
                posCur = ftell( ldifFile->file );
808
                if( ldifFile->cbProgress ) {
809
                        /* Call progress indicator */
810
                        ( ldifFile->cbProgress ) ( ldifFile, & posEnd, & posCur );
811
                }
812

    
813
                flag64 = FALSE;
814
                if( line == NULL ) {
815
                        flagEOF = flagEOR = TRUE;
816
                }
817
                else if( *line == '\0' ) {
818
                        flagEOR = TRUE;
819
                }
820

    
821
                if( flagEOR ) {
822
                        /* EOR, Output address data */
823
                        /* Save field list to hash table */
824
                        if( flagMail ) {
825
                                ldif_hash_add_list( ldifFile->hashFields, listTags );
826
                        }
827
                        mgu_free_list( listTags );
828
                        listTags = NULL;
829
                        flagMail = FALSE;
830
                }
831
                if( line ) {
832
                        flagEOR = FALSE;
833
                        if( *line == ' ' ) {
834
                                /* Continuation line */
835
                        }
836
                        else if( *line == '=' ) {
837
                                /* Base-64 encoded continuation field */
838
                        }
839
                        else {
840
                                /* Parse line */
841
                                tagName = ldif_get_tagname( line, &flag64 );
842
                                if( tagName ) {
843
                                        /* Add tag to list */
844
                                        listTags = g_slist_append( listTags, tagName );
845
                                        if( g_strcasecmp( tagName, LDIF_TAG_EMAIL ) == 0 ) {
846
                                                flagMail = TRUE;
847
                                        }
848
                                }
849
                        }
850
                }
851
                g_free( line );
852
        }
853

    
854
        /* Release data */
855
        mgu_free_list( listTags );
856
        listTags = NULL;
857
}
858

    
859
/*
860
* ============================================================================
861
* Read file into list. Main entry point
862
* Enter:  ldifFile LDIF control data.
863
*         cache    Address cache to load.
864
* Return: Status code.
865
* ============================================================================
866
*/
867
gint ldif_import_data( LdifFile *ldifFile, AddressCache *cache ) {
868
        g_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS );
869
        ldifFile->retVal = MGU_SUCCESS;
870
        addrcache_clear( cache );
871
        cache->dataRead = FALSE;
872
        ldif_open_file( ldifFile );
873
        if( ldifFile->retVal == MGU_SUCCESS ) {
874
                /* Read data into the cache */
875
                ldif_read_file( ldifFile, cache );
876
                ldif_close_file( ldifFile );
877

    
878
                /* Mark cache */
879
                cache->modified = FALSE;
880
                cache->dataRead = TRUE;
881
        }
882
        return ldifFile->retVal;
883
}
884

    
885
/*
886
* ============================================================================
887
* Process entire file reading list of unique fields. List of fields may be
888
* accessed with the ldif_get_fieldlist() function.
889
* Enter:  ldifFile LDIF control data.
890
* Return: Status code.
891
* ============================================================================
892
*/
893
gint ldif_read_tags( LdifFile *ldifFile ) {
894
        g_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS );
895
        ldifFile->retVal = MGU_SUCCESS;
896
        if( ldifFile->dirtyFlag ) {
897
                ldif_open_file( ldifFile );
898
                if( ldifFile->retVal == MGU_SUCCESS ) {
899
                        /* Read data into the cache */
900
                        ldif_read_tag_list( ldifFile );
901
                        ldif_close_file( ldifFile );
902
                        ldifFile->dirtyFlag = FALSE;
903
                        ldifFile->accessFlag = TRUE;
904
                }
905
        }
906
        return ldifFile->retVal;
907
}
908

    
909
/*
910
* Return list of fields for LDIF file.
911
* Enter: ldifFile LdifFile object.
912
* Return: Linked list of Ldif_FieldRec objects. This list may be g_free'd.
913
* Note that the objects in the list should not be freed since they refer to
914
* objects inside the internal cache. These objects will be freed when
915
* LDIF file object is freed.
916
*/
917
GList *ldif_get_fieldlist( LdifFile *ldifFile ) {
918
        GList *list = NULL;
919

    
920
        g_return_val_if_fail( ldifFile != NULL, NULL );
921
        if( ldifFile->hashFields ) {
922
                ldifFile->tempList = NULL;
923
                g_hash_table_foreach( ldifFile->hashFields, ldif_hash2list_vis, ldifFile );
924
                list = ldifFile->tempList;
925
                ldifFile->tempList = NULL;
926
        }
927
        return list;
928
}
929

    
930
/*
931
* End of Source.
932
*/
933