Statistics
| Revision:

root / src / ldif.c @ 901

History | View | Annotate | Download (22.9 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
#include "utils.h"
36
37
/*
38
* Create new object.
39
*/
40
LdifFile *ldif_create() {
41
        LdifFile *ldifFile;
42
        ldifFile = g_new0( LdifFile, 1 );
43
        ldifFile->path = NULL;
44
        ldifFile->file = NULL;
45
        ldifFile->bufptr = ldifFile->buffer;
46
        ldifFile->hashFields = g_hash_table_new( g_str_hash, g_str_equal );
47
        ldifFile->tempList = NULL;
48
        ldifFile->dirtyFlag = TRUE;
49
        ldifFile->accessFlag = FALSE;
50
        ldifFile->retVal = MGU_SUCCESS;
51
        ldifFile->cbProgress = NULL;
52
        ldifFile->importCount = 0;
53
        return ldifFile;
54
}
55
56
/*
57
* Properties...
58
*/
59
void ldif_set_file( LdifFile *ldifFile, const gchar *value ) {
60
        g_return_if_fail( ldifFile != NULL );
61
62
        if( ldifFile->path ) {
63
                if( strcmp( ldifFile->path, value ) != 0 )
64
                        ldifFile->dirtyFlag = TRUE;
65
        }
66
        else {
67
                ldifFile->dirtyFlag = TRUE;
68
        }
69
        ldifFile->path = mgu_replace_string( ldifFile->path, value );
70
        g_strstrip( ldifFile->path );
71
        ldifFile->importCount = 0;
72
}
73
void ldif_set_accessed( LdifFile *ldifFile, const gboolean value ) {
74
        g_return_if_fail( ldifFile != NULL );
75
        ldifFile->accessFlag = value;
76
}
77
78
/*
79
* Register a callback function. When called, the function will be passed
80
* the following arguments:
81
*        LdifFile object,
82
*        File size (long),
83
*        Current position (long)
84
* This can be used for a progress indicator.
85
*/
86
void ldif_set_callback( LdifFile *ldifFile, void *func ) {
87
        ldifFile->cbProgress = func;
88
}
89
90
/*
91
* Create field record object.
92
*/
93
static Ldif_FieldRec *ldif_create_fieldrec( 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;
100
}
101
102
/*
103
* Free field record object.
104
*/
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 );
114
        }
115
}
116
117
/*
118
* Free hash table entry visitor function.
119
*/
120
static gint ldif_hash_free_vis( gpointer key, gpointer value, gpointer data ) {
121
        ldif_free_fieldrec( ( Ldif_FieldRec * ) value );
122
        value = NULL;
123
        key = NULL;
124
        return -1;
125
}
126
127
/*
128
* Free up object by releasing internal memory.
129
*/
130
void ldif_free( LdifFile *ldifFile ) {
131
        g_return_if_fail( ldifFile != NULL );
132
133
        /* Close file */
134
        if( ldifFile->file ) fclose( ldifFile->file );
135
136
        /* Free internal stuff */
137
        g_free( ldifFile->path );
138
139
        /* Free field list */
140
        g_hash_table_foreach_remove( ldifFile->hashFields, ldif_hash_free_vis, NULL );
141
        g_hash_table_destroy( ldifFile->hashFields );
142
        ldifFile->hashFields = NULL;
143
144
        /* Clear pointers */
145
        ldifFile->file = NULL;
146
        ldifFile->path = NULL;
147
        ldifFile->retVal = MGU_SUCCESS;
148
        ldifFile->tempList = NULL;
149
        ldifFile->dirtyFlag = FALSE;
150
        ldifFile->accessFlag = FALSE;
151
        ldifFile->cbProgress = NULL;
152
153
        /* Now release file object */
154
        g_free( ldifFile );
155
}
156
157
/*
158
* Display field record.
159
*/
160
void ldif_print_fieldrec( Ldif_FieldRec *rec, FILE *stream ) {
161
        fprintf( stream, "\ttag:\t%s", rec->reserved ? "yes" : "no" );
162
        fprintf( stream, "\t%s", rec->selected ? "yes" : "no" );
163
        fprintf( stream, "\t:%s:\t:%s:\n", rec->userName, rec->tagName );
164
}
165
166
/*
167
* Display field record.
168
 * 
169
*/
170
static void ldif_print_file_vis( gpointer key, gpointer value, gpointer data ) {
171
        Ldif_FieldRec *rec = value;
172
        FILE *stream = data;
173
        ldif_print_fieldrec( rec, stream );
174
}
175
176
/*
177
* Display object to specified stream.
178
*/
179
void ldif_print_file( LdifFile *ldifFile, FILE *stream ) {
180
        g_return_if_fail( ldifFile != NULL );
181
        fprintf( stream, "LDIF File:\n" );
182
        fprintf( stream, "file spec: '%s'\n", ldifFile->path );
183
        fprintf( stream, "  ret val: %d\n",   ldifFile->retVal );
184
        fprintf( stream, "   fields: {\n" );
185
        g_hash_table_foreach( ldifFile->hashFields, ldif_print_file_vis, stream );
186
        fprintf( stream, "} ---\n" );
187
}
188
189
/*
190
* Open file for read.
191
* return: TRUE if file opened successfully.
192
*/
193
static gint ldif_open_file( LdifFile* ldifFile ) {
194
        /* printf( "Opening file\n" ); */
195
        if( ldifFile->path ) {
196
                ldifFile->file = g_fopen( ldifFile->path, "rb" );
197
                if( ! ldifFile->file ) {
198
                        /* printf( "can't open %s\n", ldifFile->path ); */
199
                        ldifFile->retVal = MGU_OPEN_FILE;
200
                        return ldifFile->retVal;
201
                }
202
        }
203
        else {
204
                /* printf( "file not specified\n" ); */
205
                ldifFile->retVal = MGU_NO_FILE;
206
                return ldifFile->retVal;
207
        }
208
209
        /* Setup a buffer area */
210
        ldifFile->buffer[0] = '\0';
211
        ldifFile->bufptr = ldifFile->buffer;
212
        ldifFile->retVal = MGU_SUCCESS;
213
        return ldifFile->retVal;
214
}
215
216
/*
217
* Close file.
218
*/
219
static void ldif_close_file( LdifFile *ldifFile ) {
220
        g_return_if_fail( ldifFile != NULL );
221
        if( ldifFile->file ) fclose( ldifFile->file );
222
        ldifFile->file = NULL;
223
}
224
225
/*
226
* Read line of text from file.
227
* Return: ptr to buffer where line starts.
228
*/
229
static gchar *ldif_get_line( LdifFile *ldifFile ) {
230
        gchar buf[ LDIFBUFSIZE ];
231
        gint ch;
232
        gint i = 0;
233
234
        if( feof( ldifFile->file ) )
235
                return NULL;
236
237
        while( i < LDIFBUFSIZE - 1 ) {
238
                ch = fgetc( ldifFile->file );
239
                if( ch == '\0' || ch == EOF ) {
240
                        if( i == 0 )
241
                                return NULL;
242
                        break;
243
                }
244
#if HAVE_DOSISH_SYSTEM
245
#else
246
                if( ch == '\r' )
247
                        continue;
248
#endif
249
                if( ch == '\n' )
250
                        break;
251
                buf[i] = ch;
252
                i++;
253
        }
254
        buf[i] = '\0';
255
256
        /* Return a copy of buffer */
257
        return g_strdup( buf );
258
}
259
260
/*
261
* Parse tag name from line buffer.
262
* Enter: line   Buffer.
263
*        flag64 Base-64 encoder flag.
264
* Return: Buffer containing the tag name, or NULL if no delimiter char found.
265
* If a double delimiter (::) is found, flag64 is set.
266
*/
267
static gchar *ldif_get_tagname( char* line, gboolean *flag64 ) {
268
        gint len = 0;
269
        gchar *tag = NULL;
270
        gchar *lptr = line;
271
        gchar *sptr = NULL;
272
273
        while( *lptr++ ) {
274
                /* Check for language tag */
275
                if( *lptr == LDIF_LANG_TAG ) {
276
                        if( sptr == NULL ) sptr = lptr;
277
                }
278
279
                /* Check for delimiter */
280
                if( *lptr == LDIF_SEP_TAG ) {
281
                        if( sptr ) {
282
                                len = sptr - line;
283
                        }
284
                        else {
285
                                len = lptr - line;
286
                        }
287
288
                        /* Base-64 encoding? */
289
                        if( * ++lptr == LDIF_SEP_TAG ) *flag64 = TRUE;
290
291
                        tag = g_strndup( line, len+1 );
292
                        tag[ len ] = '\0';
293
                        g_strdown( tag );
294
                        return tag;
295
                }
296
        }
297
        return tag;
298
}
299
300
/*
301
* Parse tag value from line buffer.
302
* Enter: line   Buffer.
303
* Return: Buffer containing the tag value. Empty string is returned if
304
* no delimiter char found.
305
*/
306
static gchar *ldif_get_tagvalue( gchar* line ) {
307
        gchar *value = NULL;
308
        gchar *start = NULL;
309
        gchar *lptr;
310
        gint len = 0;
311
312
        for( lptr = line; *lptr; lptr++ ) {
313
                if( *lptr == LDIF_SEP_TAG ) {
314
                        if( ! start )
315
                                start = lptr + 1;
316
                }
317
        }
318
        if( start ) {
319
                if( *start == LDIF_SEP_TAG ) start++;
320
                len = lptr - start;
321
                value = g_strndup( start, len+1 );
322
                g_strstrip( value );
323
        }
324
        else {
325
                /* Ensure that we get an empty string */
326
                value = g_strndup( "", 1 );
327
        }
328
        value[ len ] = '\0';
329
        return value;
330
}
331
332
#if 0
333
/*
334
* Dump linked lists of character strings (for debug).
335
*/
336
static void ldif_dump_lists( GSList *listName, GSList *listAddr, GSList *listRem, GSList *listID, FILE *stream ) {
337
        fprintf( stream, "dump name\n" );
338
        fprintf( stream, "------------\n" );
339
        mgu_print_list( listName, stdout );
340
        fprintf( stream, "dump address\n" );
341
        fprintf( stream, "------------\n" );
342
        mgu_print_list( listAddr, stdout );
343
        fprintf( stream, "dump remarks\n" );
344
        fprintf( stdout, "------------\n" );
345
        mgu_print_list( listRem, stdout );
346
        fprintf( stream, "dump id\n" );
347
        fprintf( stdout, "------------\n" );
348
        mgu_print_list( listID, stdout );
349
}
350
#endif
351
352
/*
353
* Parsed address data.
354
*/
355
typedef struct _Ldif_ParsedRec_ Ldif_ParsedRec;
356
struct _Ldif_ParsedRec_ {
357
        GSList *listCName;
358
        GSList *listFName;
359
        GSList *listLName;
360
        GSList *listNName;
361
        GSList *listAddress;
362
        GSList *listID;
363
        GSList *userAttr;
364
};
365
366
/*
367
* User attribute data.
368
*/
369
typedef struct _Ldif_UserAttr_ Ldif_UserAttr;
370
struct _Ldif_UserAttr_ {
371
        gchar *name;
372
        gchar *value;
373
};
374
375
/*
376
* Build an address list entry and append to list of address items. Name is formatted
377
* as "<first-name> <last-name>".
378
*/
379
static void ldif_build_items( LdifFile *ldifFile, Ldif_ParsedRec *rec, AddressCache *cache ) {
380
        GSList *nodeFirst;
381
        GSList *nodeAddress;
382
        GSList *nodeAttr;
383
        gchar *firstName = NULL, *lastName = NULL, *fullName = NULL, *nickName = NULL;
384
        gint iLen = 0, iLenT = 0;
385
        ItemPerson *person;
386
        ItemEMail *email;
387
388
        nodeAddress = rec->listAddress;
389
        if( nodeAddress == NULL ) return;
390
391
        /* Find longest first name in list */
392
        nodeFirst = rec->listFName;
393
        while( nodeFirst ) {
394
                if( firstName == NULL ) {
395
                        firstName = nodeFirst->data;
396
                        iLen = strlen( firstName );
397
                }
398
                else {
399
                        if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) {
400
                                firstName = nodeFirst->data;
401
                                iLen = iLenT;
402
                        }
403
                }
404
                nodeFirst = g_slist_next( nodeFirst );
405
        }
406
407
        /* Format name */
408
        if( rec->listLName ) {
409
                lastName = rec->listLName->data;
410
        }
411
412
        if( firstName ) {
413
                if( lastName ) {
414
                        fullName = g_strdup_printf( "%s %s", firstName, lastName );
415
                }
416
                else {
417
                        fullName = g_strdup_printf( "%s", firstName );
418
                }
419
        }
420
        else {
421
                if( lastName ) {
422
                        fullName = g_strdup_printf( "%s", lastName );
423
                }
424
        }
425
        if( fullName ) {
426
                g_strchug( fullName ); g_strchomp( fullName );
427
        }
428
429
        if( rec->listNName ) {
430
                nickName = rec->listNName->data;
431
        }
432
433
        person = addritem_create_item_person();
434
        addritem_person_set_common_name( person, fullName );
435
        addritem_person_set_first_name( person, firstName );
436
        addritem_person_set_last_name( person, lastName );
437
        addritem_person_set_nick_name( person, nickName );
438
        addrcache_id_person( cache, person );
439
        addrcache_add_person( cache, person );
440
        ++ldifFile->importCount;
441
442
        /* Add address item */
443
        while( nodeAddress ) {
444
                email = addritem_create_item_email();
445
                addritem_email_set_address( email, nodeAddress->data );
446
                addrcache_id_email( cache, email );
447
                addrcache_person_add_email( cache, person, email );
448
                nodeAddress = g_slist_next( nodeAddress );
449
        }
450
        g_free( fullName );
451
        fullName = firstName = lastName = NULL;
452
453
        /* Add user attributes */
454
        nodeAttr = rec->userAttr;
455
        while( nodeAttr ) {
456
                Ldif_UserAttr *attr = nodeAttr->data;
457
                UserAttribute *attrib = addritem_create_attribute();
458
                addritem_attrib_set_name( attrib, attr->name );
459
                addritem_attrib_set_value( attrib, attr->value );
460
                addritem_person_add_attribute( person, attrib );
461
                nodeAttr = g_slist_next( nodeAttr );
462
        }
463
        nodeAttr = NULL;
464
}
465
466
/*
467
* Add selected field as user attribute.
468
*/
469
static void ldif_add_user_attr( Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue, GHashTable *hashField ) {
470
        Ldif_FieldRec *fld = NULL;
471
        Ldif_UserAttr *attr = NULL;
472
        gchar *name;
473
474
        fld = g_hash_table_lookup( hashField, tagName );
475
        if( fld ) {
476
                if( fld->reserved ) return;
477
                if( ! fld->selected ) return;
478
479
                name = fld->tagName;
480
                if( fld->userName ) {
481
                        name = fld->userName;
482
                }
483
                attr = g_new0( Ldif_UserAttr, 1 );
484
                attr->name = g_strdup( name );
485
                attr->value = g_strdup( tagValue );
486
                rec->userAttr = g_slist_append( rec->userAttr, attr );
487
        }
488
}
489
490
/*
491
* Add value to parsed data.
492
*/
493
static void ldif_add_value( Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue, GHashTable *hashField ) {
494
        gchar *nm, *val;
495
496
        nm = g_strdup( tagName );
497
        g_strdown( nm );
498
        if( tagValue ) {
499
                val = g_strdup( tagValue );
500
        }
501
        else {
502
                val = g_strdup( "" );
503
        }
504
        g_strstrip( val );
505
        if( g_ascii_strcasecmp( nm, LDIF_TAG_COMMONNAME ) == 0 ) {
506
                rec->listCName = g_slist_append( rec->listCName, val );
507
        }
508
        else if( g_ascii_strcasecmp( nm, LDIF_TAG_FIRSTNAME ) == 0 ) {
509
                rec->listFName = g_slist_append( rec->listFName, val );
510
        }
511
        else if( g_ascii_strcasecmp( nm, LDIF_TAG_LASTNAME ) == 0 ) {
512
                rec->listLName = g_slist_append( rec->listLName, val );
513
        }
514
        else if( g_ascii_strcasecmp( nm, LDIF_TAG_NICKNAME ) == 0 ) {
515
                rec->listNName = g_slist_append( rec->listNName, val );
516
        }
517
        else if( g_ascii_strcasecmp( nm, LDIF_TAG_EMAIL ) == 0 ) {
518
                rec->listAddress = g_slist_append( rec->listAddress, val );
519
        }
520
        else {
521
                /* Add field as user attribute */
522
                ldif_add_user_attr( rec, tagName, tagValue, hashField );
523
        }
524
        g_free( nm );
525
}
526
527
/*
528
* Clear parsed data.
529
*/
530
static void ldif_clear_rec( Ldif_ParsedRec *rec ) {
531
        GSList *list;
532
533
        /* Free up user attributes */
534
        list = rec->userAttr;
535
        while( list ) {
536
                Ldif_UserAttr *attr = list->data;
537
                g_free( attr->name );
538
                g_free( attr->value );
539
                g_free( attr );
540
                list = g_slist_next( list );
541
        }
542
        g_slist_free( rec->userAttr );
543
544
        g_slist_free( rec->listCName );
545
        g_slist_free( rec->listFName );
546
        g_slist_free( rec->listLName );
547
        g_slist_free( rec->listNName );
548
        g_slist_free( rec->listAddress );
549
        g_slist_free( rec->listID );
550
551
        rec->userAttr = NULL;
552
        rec->listCName = NULL;
553
        rec->listFName = NULL;
554
        rec->listLName = NULL;
555
        rec->listNName = NULL;
556
        rec->listAddress = NULL;
557
        rec->listID = NULL;
558
}
559
560
#if 0
561
/*
562
* Print parsed data.
563
*/
564
static void ldif_print_record( Ldif_ParsedRec *rec, FILE *stream ) {
565
        GSList *list;
566
567
        fprintf( stream, "LDIF Parsed Record:\n" );
568
        fprintf( stream, "common name:" );
569
        mgu_print_list( rec->listCName, stream );
570
        if( ! rec->listCName ) fprintf( stream, "\n" );
571
        fprintf( stream, "first name:" );
572
        mgu_print_list( rec->listFName, stream );
573
        if( ! rec->listFName ) fprintf( stream, "\n" );
574
        fprintf( stream, "last name:" );
575
        mgu_print_list( rec->listLName, stream );
576
        if( ! rec->listLName ) fprintf( stream, "\n" );
577
        fprintf( stream, "nick name:" );
578
        mgu_print_list( rec->listNName, stream );
579
        if( ! rec->listNName ) fprintf( stream, "\n" );
580
        fprintf( stream, "address:" );
581
        mgu_print_list( rec->listAddress, stream );
582
        if( ! rec->listAddress ) fprintf( stream, "\n" );
583
        fprintf( stream, "id:" );
584
        mgu_print_list( rec->listID, stream );
585
        if( ! rec->listID ) fprintf( stream, "\n" );
586
587
        list = rec->userAttr;
588
        while( list ) {
589
                Ldif_UserAttr *attr = list->data;
590
                fprintf( stream, "n/v:\t%s:\t:%s:\n", attr->name, attr->value );
591
                list = g_slist_next( list );
592
        }
593
        list = NULL;
594
}
595
596
static void ldif_dump_b64( gchar *buf ) {
597
        Base64Decoder *decoder = NULL;
598
        gchar outBuf[8192];
599
        gint len;
600
601
        printf( "base-64 : inbuf : %s\n", buf );
602
        decoder = base64_decoder_new();
603
        len = base64_decoder_decode( decoder, buf, outBuf );
604
        if (len < 0) {
605
                printf( "base-64 : Bad BASE64 content\n" );
606
        }
607
        else {
608
                outBuf[len] = '\0';
609
                printf( "base-64 : %d : %s\n\n", len, outBuf );
610
        }
611
        base64_decoder_free( decoder );
612
        decoder = NULL;
613
}
614
#endif
615
616
/*
617
* Read file data into address cache.
618
* Note that one LDIF record identifies one entity uniquely with the
619
* distinguished name (dn) tag. Each person can have multiple E-Mail
620
* addresses. Also, each person can have many common name (cn) tags.
621
*/
622
static void ldif_read_file( LdifFile *ldifFile, AddressCache *cache ) {
623
        gchar *tagName = NULL, *tagValue = NULL;
624
        gchar *lastTag = NULL, *fullValue = NULL;
625
        GSList *listValue = NULL;
626
        gboolean flagEOF = FALSE, flagEOR = FALSE;
627
        gboolean flag64 = FALSE, last64 = FALSE;
628
        Ldif_ParsedRec *rec;
629
        long posEnd = 0L;
630
        long posCur = 0L;
631
        GHashTable *hashField;
632
633
        hashField = ldifFile->hashFields;
634
        rec = g_new0( Ldif_ParsedRec, 1 );
635
        ldif_clear_rec( rec );
636
637
        /* Find EOF for progress indicator */
638
        fseek( ldifFile->file, 0L, SEEK_END );
639
        posEnd = ftell( ldifFile->file );
640
        fseek( ldifFile->file, 0L, SEEK_SET );
641
642
        while( ! flagEOF ) {
643
                gchar *line =  ldif_get_line( ldifFile );
644
645
                posCur = ftell( ldifFile->file );
646
                if( ldifFile->cbProgress ) {
647
                        /* Call progress indicator */
648
                        ( ldifFile->cbProgress ) ( ldifFile, & posEnd, & posCur );
649
                }
650
651
                flag64 = FALSE;
652
                if( line == NULL ) {
653
                        flagEOF = flagEOR = TRUE;
654
                }
655
                else if( *line == '\0' ) {
656
                        flagEOR = TRUE;
657
                }
658
659
                if( flagEOR ) {
660
                        /* EOR, Output address data */
661
                        if( lastTag ) {
662
                                /* Save record */
663
                                fullValue = mgu_list_coalesce( listValue );
664
665
                                /* Base-64 encoded data */
666
                                /*
667
                                if( last64 ) {
668
                                        ldif_dump_b64( fullValue );
669
                                }
670
                                */
671
672
                                ldif_add_value( rec, lastTag, fullValue, hashField );
673
                                /* ldif_print_record( rec, stdout ); */
674
                                ldif_build_items( ldifFile, rec, cache );
675
                                ldif_clear_rec( rec );
676
                                g_free( lastTag );
677
                                mgu_free_list( listValue );
678
                                lastTag = NULL;
679
                                listValue = NULL;
680
                                last64 = FALSE;
681
                        }
682
                }
683
                if( line ) {
684
                        flagEOR = FALSE;
685
                        if( *line == ' ' ) {
686
                                /* Continuation line */
687
                                listValue = g_slist_append( listValue, g_strdup( line+1 ) );
688
                        }
689
                        else if( *line == '=' ) {
690
                                /* Base-64 encoded continuation field */
691
                                listValue = g_slist_append( listValue, g_strdup( line ) );
692
                        }
693
                        else {
694
                                /* Parse line */
695
                                tagName = ldif_get_tagname( line, &flag64 );
696
                                if( tagName ) {
697
                                        tagValue = ldif_get_tagvalue( line );
698
                                        if( tagValue ) {
699
                                                if( lastTag ) {
700
                                                        /* Save data */
701
                                                        fullValue = mgu_list_coalesce( listValue );
702
                                                        /* Base-64 encoded data */
703
                                                        /*
704
                                                        if( last64 ) {
705
                                                                ldif_dump_b64( fullValue );
706
                                                        }
707
                                                        */
708
709
                                                        ldif_add_value( rec, lastTag, fullValue, hashField );
710
                                                        g_free( lastTag );
711
                                                        mgu_free_list( listValue );
712
                                                        lastTag = NULL;
713
                                                        listValue = NULL;
714
                                                        last64 = FALSE;
715
                                                }
716
717
                                                lastTag = g_strdup( tagName );
718
                                                listValue = g_slist_append( listValue, g_strdup( tagValue ) );
719
                                                g_free( tagValue );
720
                                                last64 = flag64;
721
                                        }
722
                                        g_free( tagName );
723
                                }
724
                        }
725
                }
726
                g_free( line );
727
        }
728
729
        /* Release data */
730
        ldif_clear_rec( rec );
731
        g_free( rec );
732
        g_free( lastTag );
733
        mgu_free_list( listValue );
734
}
735
736
/*
737
* Add list of field names to hash table.
738
*/
739
static void ldif_hash_add_list( GHashTable *table, GSList *list ) {
740
        GSList *node = list;
741
742
        /* mgu_print_list( list, stdout ); */
743
        while( node ) {
744
                gchar *tag = node->data;
745
                if( ! g_hash_table_lookup( table, tag ) ) {
746
                        Ldif_FieldRec *rec = NULL;
747
                        gchar *key = g_strdup( tag );
748
749
                        rec = ldif_create_fieldrec( tag );
750
                        if( g_ascii_strcasecmp( tag, LDIF_TAG_COMMONNAME ) == 0 ) {
751
                                rec->reserved = TRUE;
752
                        }
753
                        else if( g_ascii_strcasecmp( tag, LDIF_TAG_FIRSTNAME ) == 0 ) {
754
                                rec->reserved = TRUE;
755
                        }
756
                        else if( g_ascii_strcasecmp( tag, LDIF_TAG_LASTNAME ) == 0 ) {
757
                                rec->reserved = TRUE;
758
                        }
759
                        else if( g_ascii_strcasecmp( tag, LDIF_TAG_NICKNAME ) == 0 ) {
760
                                rec->reserved = TRUE;
761
                        }
762
                        else if( g_ascii_strcasecmp( tag, LDIF_TAG_EMAIL ) == 0 ) {
763
                                rec->reserved = TRUE;
764
                        }
765
                        g_hash_table_insert( table, key, rec );
766
                }
767
                node = g_slist_next( node );
768
        }
769
}
770
771
/*
772
* Sorted list comparison function.
773
*/
774
static int ldif_field_compare( gconstpointer ptr1, gconstpointer ptr2 ) {
775
        const Ldif_FieldRec *rec1 = ptr1;
776
        const Ldif_FieldRec *rec2 = ptr2;
777
        return g_ascii_strcasecmp( rec1->tagName, rec2->tagName );
778
}
779
780
/*
781
* Append hash table entry to list - visitor function.
782
*/
783
static void ldif_hash2list_vis( gpointer key, gpointer value, gpointer data ) {
784
        LdifFile *ldf = data;
785
        ldf->tempList = g_list_insert_sorted( ldf->tempList, value, ldif_field_compare );
786
}
787
788
/*
789
* Read tag names for file data.
790
*/
791
static void ldif_read_tag_list( LdifFile *ldifFile ) {
792
        gchar *tagName = NULL;
793
        GSList *listTags = NULL;
794
        gboolean flagEOF = FALSE, flagEOR = FALSE, flagMail = FALSE;
795
        gboolean flag64 = FALSE;
796
        long posEnd = 0L;
797
        long posCur = 0L;
798
799
        /* Clear hash table */
800
        g_hash_table_foreach_remove( ldifFile->hashFields, ldif_hash_free_vis, NULL );
801
802
        /* Find EOF for progress indicator */
803
        fseek( ldifFile->file, 0L, SEEK_END );
804
        posEnd = ftell( ldifFile->file );
805
        fseek( ldifFile->file, 0L, SEEK_SET );
806
807
        /* Process file */
808
        while( ! flagEOF ) {
809
                gchar *line = ldif_get_line( ldifFile );
810
811
                posCur = ftell( ldifFile->file );
812
                if( ldifFile->cbProgress ) {
813
                        /* Call progress indicator */
814
                        ( ldifFile->cbProgress ) ( ldifFile, & posEnd, & posCur );
815
                }
816
817
                flag64 = FALSE;
818
                if( line == NULL ) {
819
                        flagEOF = flagEOR = TRUE;
820
                }
821
                else if( *line == '\0' ) {
822
                        flagEOR = TRUE;
823
                }
824
825
                if( flagEOR ) {
826
                        /* EOR, Output address data */
827
                        /* Save field list to hash table */
828
                        if( flagMail ) {
829
                                ldif_hash_add_list( ldifFile->hashFields, listTags );
830
                        }
831
                        mgu_free_list( listTags );
832
                        listTags = NULL;
833
                        flagMail = FALSE;
834
                }
835
                if( line ) {
836
                        flagEOR = FALSE;
837
                        if( *line == ' ' ) {
838
                                /* Continuation line */
839
                        }
840
                        else if( *line == '=' ) {
841
                                /* Base-64 encoded continuation field */
842
                        }
843
                        else {
844
                                /* Parse line */
845
                                tagName = ldif_get_tagname( line, &flag64 );
846
                                if( tagName ) {
847
                                        /* Add tag to list */
848
                                        listTags = g_slist_append( listTags, tagName );
849
                                        if( g_ascii_strcasecmp( tagName, LDIF_TAG_EMAIL ) == 0 ) {
850
                                                flagMail = TRUE;
851
                                        }
852
                                }
853
                        }
854
                }
855
                g_free( line );
856
        }
857
858
        /* Release data */
859
        mgu_free_list( listTags );
860
        listTags = NULL;
861
}
862
863
/*
864
* ============================================================================
865
* Read file into list. Main entry point
866
* Enter:  ldifFile LDIF control data.
867
*         cache    Address cache to load.
868
* Return: Status code.
869
* ============================================================================
870
*/
871
gint ldif_import_data( LdifFile *ldifFile, AddressCache *cache ) {
872
        g_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS );
873
        ldifFile->retVal = MGU_SUCCESS;
874
        addrcache_clear( cache );
875
        cache->dataRead = FALSE;
876
        ldif_open_file( ldifFile );
877
        if( ldifFile->retVal == MGU_SUCCESS ) {
878
                /* Read data into the cache */
879
                ldif_read_file( ldifFile, cache );
880
                ldif_close_file( ldifFile );
881
882
                /* Mark cache */
883
                cache->modified = FALSE;
884
                cache->dataRead = TRUE;
885
        }
886
        return ldifFile->retVal;
887
}
888
889
/*
890
* ============================================================================
891
* Process entire file reading list of unique fields. List of fields may be
892
* accessed with the ldif_get_fieldlist() function.
893
* Enter:  ldifFile LDIF control data.
894
* Return: Status code.
895
* ============================================================================
896
*/
897
gint ldif_read_tags( LdifFile *ldifFile ) {
898
        g_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS );
899
        ldifFile->retVal = MGU_SUCCESS;
900
        if( ldifFile->dirtyFlag ) {
901
                ldif_open_file( ldifFile );
902
                if( ldifFile->retVal == MGU_SUCCESS ) {
903
                        /* Read data into the cache */
904
                        ldif_read_tag_list( ldifFile );
905
                        ldif_close_file( ldifFile );
906
                        ldifFile->dirtyFlag = FALSE;
907
                        ldifFile->accessFlag = TRUE;
908
                }
909
        }
910
        return ldifFile->retVal;
911
}
912
913
/*
914
* Return list of fields for LDIF file.
915
* Enter: ldifFile LdifFile object.
916
* Return: Linked list of Ldif_FieldRec objects. This list may be g_free'd.
917
* Note that the objects in the list should not be freed since they refer to
918
* objects inside the internal cache. These objects will be freed when
919
* LDIF file object is freed.
920
*/
921
GList *ldif_get_fieldlist( LdifFile *ldifFile ) {
922
        GList *list = NULL;
923
924
        g_return_val_if_fail( ldifFile != NULL, NULL );
925
        if( ldifFile->hashFields ) {
926
                ldifFile->tempList = NULL;
927
                g_hash_table_foreach( ldifFile->hashFields, ldif_hash2list_vis, ldifFile );
928
                list = ldifFile->tempList;
929
                ldifFile->tempList = NULL;
930
        }
931
        return list;
932
}
933
934
/*
935
* End of Source.
936
*/
937