Statistics
| Revision:

root / src / addrcache.c @ 1

History | View | Annotate | Download (34.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 to maintain address cache.
22
 */
23

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

    
29
/* #include "mgutils.h" */
30
#include "addritem.h"
31
#include "addrcache.h"
32

    
33
#define ID_TIME_OFFSET             998000000
34
#define ADDRCACHE_MAX_SEARCH_COUNT 1000
35

    
36
/*
37
* Create new address cache.
38
*/
39
AddressCache *addrcache_create() {
40
        AddressCache *cache;
41
        gint t;
42

    
43
        cache = g_new0( AddressCache, 1 );
44
        cache->itemHash = g_hash_table_new( g_str_hash, g_str_equal );
45

    
46
        cache->dataRead = FALSE;
47
        cache->modified = FALSE;
48
        cache->modifyTime = 0;
49

    
50
        /* Generate the next ID using system time */
51
        cache->nextID = 1;
52
        t = time( NULL );
53
        if( t > 0 ) {
54
                cache->nextID = t - ID_TIME_OFFSET;
55
        }
56

    
57
        cache->tempList = NULL;
58
        cache->rootFolder = addritem_create_item_folder();
59
        cache->rootFolder->isRoot = TRUE;
60
        ADDRITEM_PARENT(cache->rootFolder) = NULL;
61
        return cache;
62
}
63

    
64
/*
65
* Properties.
66
*/
67
ItemFolder *addrcache_get_root_folder( AddressCache *cache ) {
68
        g_return_val_if_fail( cache != NULL, NULL );
69
        return cache->rootFolder;
70
}
71
GList *addrcache_get_list_folder( AddressCache *cache ) {
72
        g_return_val_if_fail( cache != NULL, NULL );
73
        return cache->rootFolder->listFolder;
74
}
75
GList *addrcache_get_list_person( AddressCache *cache ) {
76
        g_return_val_if_fail( cache != NULL, NULL );
77
        return cache->rootFolder->listPerson;
78
}
79

    
80
/*
81
* Generate next ID.
82
*/
83
void addrcache_next_id( AddressCache *cache ) {
84
        g_return_if_fail( cache != NULL );
85
        cache->nextID++;
86
}
87

    
88
/*
89
* Refresh internal variables. This can be used force a reload.
90
*/
91
void addrcache_refresh( AddressCache *cache ) {
92
        cache->dataRead = FALSE;
93
        cache->modified = TRUE;
94
        cache->modifyTime = 0;
95
}
96

    
97
/*
98
* Free hash table visitor function.
99
*/
100
static gint addrcache_free_item_vis( gpointer key, gpointer value, gpointer data ) {
101
        AddrItemObject *obj = ( AddrItemObject * ) value;
102
        if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
103
                addritem_free_item_person( ( ItemPerson * ) obj );
104
        }
105
        else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
106
                addritem_free_item_group( ( ItemGroup * ) obj );
107
        }
108
        else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
109
                addritem_free_item_folder( ( ItemFolder * ) obj );
110
        }
111
        key = NULL;
112
        value = NULL;
113
        return 0;
114
}
115

    
116
/*
117
* Free hash table of address cache items.
118
*/
119
static void addrcache_free_item_hash( GHashTable *table ) {
120
        g_return_if_fail( table != NULL );
121
        g_hash_table_freeze( table );
122
        g_hash_table_foreach_remove( table, addrcache_free_item_vis, NULL );
123
        g_hash_table_thaw( table );
124
        g_hash_table_destroy( table );
125
}
126

    
127
/*
128
* Free up folders and groups.
129
*/
130
static void addrcache_free_all_folders( ItemFolder *parent ) {
131
        GList *node = parent->listFolder;
132
        while( node ) {
133
                ItemFolder *folder = node->data;
134
                addrcache_free_all_folders( folder );
135
                node = g_list_next( node );
136
        }
137
        g_list_free( parent->listPerson );
138
        g_list_free( parent->listGroup );
139
        g_list_free( parent->listFolder );
140
        parent->listPerson = NULL;
141
        parent->listGroup = NULL;
142
        parent->listFolder = NULL;
143
}
144

    
145
/*
146
* Clear the address cache.
147
*/
148
void addrcache_clear( AddressCache *cache ) {
149
        g_return_if_fail( cache != NULL );
150

    
151
        /* Free up folders and hash table */
152
        addrcache_free_all_folders( cache->rootFolder );
153
        addrcache_free_item_hash( cache->itemHash );
154
        cache->itemHash = NULL;
155
        ADDRITEM_PARENT(cache->rootFolder) = NULL;
156
        addritem_free_item_folder( cache->rootFolder );
157
        cache->rootFolder = NULL;
158
        g_list_free( cache->tempList );
159
        cache->tempList = NULL;
160

    
161
        /* Reset to initial state */
162
        cache->itemHash = g_hash_table_new( g_str_hash, g_str_equal );
163
        cache->rootFolder = addritem_create_item_folder();
164
        cache->rootFolder->isRoot = TRUE;
165
        ADDRITEM_PARENT(cache->rootFolder) = NULL;
166

    
167
        addrcache_refresh( cache );
168

    
169
}
170

    
171
/*
172
* Free address cache.
173
*/
174
void addrcache_free( AddressCache *cache ) {
175
        g_return_if_fail( cache != NULL );
176

    
177
        addrcache_free_all_folders( cache->rootFolder );
178
        addrcache_free_item_hash( cache->itemHash );
179
        cache->itemHash = NULL;
180
        ADDRITEM_PARENT(cache->rootFolder) = NULL;
181
        addritem_free_item_folder( cache->rootFolder );
182
        cache->rootFolder = NULL;
183
        g_list_free( cache->tempList );
184
        cache->tempList = NULL;
185
        g_free( cache );
186
}
187

    
188
/*
189
* Check whether file has changed by comparing with cache.
190
* return: TRUE if file has changed.
191
*/
192
gboolean addrcache_check_file( AddressCache *cache, gchar *path ) {
193
        gboolean retVal;
194
        struct stat filestat;
195
        retVal = TRUE;
196
        if( path ) {
197
                if( 0 == lstat( path, &filestat ) ) {
198
                        if( filestat.st_mtime == cache->modifyTime ) retVal = FALSE;
199
                }
200
        }
201
        return retVal;
202
}
203

    
204
/*
205
* Save file time to cache.
206
* return: TRUE if time marked.
207
*/
208
gboolean addrcache_mark_file( AddressCache *cache, gchar *path ) {
209
        gboolean retVal = FALSE;
210
        struct stat filestat;
211
        if( path ) {
212
                if( 0 == lstat( path, &filestat ) ) {
213
                        cache->modifyTime = filestat.st_mtime;
214
                        retVal = TRUE;
215
                }
216
        }
217
        return retVal;
218
}
219

    
220
/*
221
* Print list of items.
222
*/
223
void addrcache_print_item_list( GList *list, FILE *stream ) {
224
        GList *node = list;
225
        while( node ) {
226
                AddrItemObject *obj = node->data;
227
                if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
228
                        addritem_print_item_person( ( ItemPerson * ) obj, stream );
229
                }
230
                else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
231
                        addritem_print_item_group( ( ItemGroup * ) obj, stream );
232
                }
233
                else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
234
                        addritem_print_item_folder( ( ItemFolder * ) obj, stream );
235
                }
236
                node = g_list_next( node );
237
        }
238
        fprintf( stream, "\t---\n" );
239
}
240

    
241
/*
242
* Print item hash table visitor function.
243
*/
244
static void addrcache_print_item_vis( gpointer key, gpointer value, gpointer data ) {
245
        AddrItemObject *obj = ( AddrItemObject * ) value;
246
        FILE *stream = ( FILE * ) data;
247
        if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
248
                addritem_print_item_person( ( ItemPerson * ) obj, stream );
249
        }
250
        else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
251
                addritem_print_item_group( ( ItemGroup * ) obj, stream );
252
        }
253
        else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
254
                addritem_print_item_folder( ( ItemFolder * ) obj, stream );
255
        }
256
}
257

    
258
/*
259
* Dump entire address cache hash table contents.
260
*/
261
void addrcache_print( AddressCache *cache, FILE *stream ) {
262
        g_return_if_fail( cache != NULL );
263
        fprintf( stream, "AddressCache:\n" );
264
        fprintf( stream, "next id  : %d\n",  cache->nextID );
265
        fprintf( stream, "mod time : %ld\n", cache->modifyTime );
266
        fprintf( stream, "modified : %s\n",  cache->modified ? "yes" : "no" );
267
        fprintf( stream, "data read: %s\n",  cache->dataRead ? "yes" : "no" );
268
}
269

    
270
/*
271
* Dump entire address cache hash table contents.
272
*/
273
void addrcache_dump_hash( AddressCache *cache, FILE *stream ) {
274
        g_return_if_fail( cache != NULL );
275
        addrcache_print( cache, stream );
276
        g_hash_table_foreach( cache->itemHash, addrcache_print_item_vis, stream );
277
}
278

    
279
/*
280
 * Allocate ID for person.
281
 */
282
void addrcache_id_person( AddressCache *cache, ItemPerson *person ) {
283
        g_return_if_fail( cache != NULL );
284
        g_return_if_fail( person != NULL );
285
        if( ADDRITEM_ID(person) ) return;
286
        addrcache_next_id( cache );
287
        ADDRITEM_ID(person) = g_strdup_printf( "%d", cache->nextID );
288
}
289

    
290
/*
291
 * Allocate ID for group.
292
 */
293
void addrcache_id_group( AddressCache *cache, ItemGroup *group ) {
294
        g_return_if_fail( cache != NULL );
295
        g_return_if_fail( group != NULL );
296
        if( ADDRITEM_ID(group) ) return;
297
        addrcache_next_id( cache );
298
        ADDRITEM_ID(group) = g_strdup_printf( "%d", cache->nextID );
299
}
300

    
301
/*
302
 * Allocate ID for folder.
303
 */
304
void addrcache_id_folder( AddressCache *cache, ItemFolder *folder ) {
305
        g_return_if_fail( cache != NULL );
306
        g_return_if_fail( folder != NULL );
307
        if( ADDRITEM_ID(folder) ) return;
308
        addrcache_next_id( cache );
309
        ADDRITEM_ID(folder) = g_strdup_printf( "%d", cache->nextID );
310
}
311

    
312
/*
313
 * Allocate ID for email address.
314
 */
315
void addrcache_id_email( AddressCache *cache, ItemEMail *email ) {
316
        g_return_if_fail( cache != NULL );
317
        g_return_if_fail( email != NULL );
318
        if( ADDRITEM_ID(email) ) return;
319
        addrcache_next_id( cache );
320
        ADDRITEM_ID(email) = g_strdup_printf( "%d", cache->nextID );
321
}
322

    
323
/*
324
 * Allocate ID for user attribute.
325
 */
326
void addrcache_id_attribute( AddressCache *cache, UserAttribute *attrib ) {
327
        g_return_if_fail( cache != NULL );
328
        g_return_if_fail( attrib != NULL );
329
        if( attrib->uid ) return;
330
        addrcache_next_id( cache );
331
        attrib->uid = g_strdup_printf( "%d", cache->nextID );
332
}
333

    
334
/*
335
* Add person to hash table.
336
* return: TRUE if item added.
337
*/
338
gboolean addrcache_hash_add_person( AddressCache *cache, ItemPerson *person ) {
339
        if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(person) ) ) {
340
                return FALSE;
341
        }
342
        g_hash_table_insert( cache->itemHash, ADDRITEM_ID(person), person );
343
        return TRUE;
344
}
345

    
346
/*
347
* Add group to hash table.
348
* return: TRUE if item added.
349
*/
350
gboolean addrcache_hash_add_group( AddressCache *cache, ItemGroup *group ) {
351
        g_return_val_if_fail( cache != NULL, FALSE );
352
        g_return_val_if_fail( group != NULL, FALSE );
353

    
354
        if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(group) ) ) {
355
                return FALSE;
356
        }
357
        g_hash_table_insert( cache->itemHash, ADDRITEM_ID(group), group );
358
        return TRUE;
359
}
360

    
361
/*
362
* Add folder to hash table.
363
* return: TRUE if item added.
364
*/
365
gboolean addrcache_hash_add_folder( AddressCache *cache, ItemFolder *folder ) {
366
        g_return_val_if_fail( cache != NULL, FALSE );
367
        g_return_val_if_fail( folder != NULL, FALSE );
368

    
369
        if( g_hash_table_lookup( cache->itemHash, ADDRITEM_ID(folder) ) ) {
370
                return FALSE;
371
        }
372
        g_hash_table_insert( cache->itemHash, ADDRITEM_ID(folder), folder );
373
        return TRUE;
374
}
375

    
376
/*
377
* Add person to specified folder in cache.
378
*/
379
gboolean addrcache_folder_add_person( AddressCache *cache, ItemFolder *folder, ItemPerson *item ) {
380
        gboolean retVal = FALSE;
381

    
382
        g_return_val_if_fail( cache != NULL, FALSE );
383
        g_return_val_if_fail( folder != NULL, FALSE );
384
        g_return_val_if_fail( item != NULL, FALSE );
385

    
386
        retVal = addrcache_hash_add_person( cache, item );
387
        if( retVal ) {
388
                addritem_folder_add_person( folder, item );
389
        }
390
        return retVal;
391
}
392

    
393
/*
394
* Add folder to specified folder in cache.
395
*/
396
gboolean addrcache_folder_add_folder( AddressCache *cache, ItemFolder *folder, ItemFolder *item ) {
397
        gboolean retVal = FALSE;
398

    
399
        g_return_val_if_fail( cache != NULL, FALSE );
400
        g_return_val_if_fail( folder != NULL, FALSE );
401
        g_return_val_if_fail( item != NULL, FALSE );
402

    
403
        retVal = addrcache_hash_add_folder( cache, item );
404
        if( retVal ) {
405
                addritem_folder_add_folder( folder, item );
406
        }
407
        return TRUE;
408
}
409

    
410
/*
411
* Add folder to specified folder in cache.
412
*/
413
gboolean addrcache_folder_add_group( AddressCache *cache, ItemFolder *folder, ItemGroup *item ) {
414
        gboolean retVal = FALSE;
415

    
416
        g_return_val_if_fail( cache != NULL, FALSE );
417
        g_return_val_if_fail( folder != NULL, FALSE );
418
        g_return_val_if_fail( item != NULL, FALSE );
419

    
420
        retVal = addrcache_hash_add_group( cache, item );
421
        if( retVal ) {
422
                addritem_folder_add_group( folder, item );
423
        }
424
        return retVal;
425
}
426

    
427
/*
428
* Add person to address cache.
429
* return: TRUE if item added.
430
*/
431
gboolean addrcache_add_person( AddressCache *cache, ItemPerson *person ) {
432
        gboolean retVal = FALSE;
433

    
434
        g_return_val_if_fail( cache != NULL, FALSE );
435
        g_return_val_if_fail( person != NULL, FALSE );
436

    
437
        retVal = addrcache_hash_add_person( cache, person );
438
        if( retVal ) {
439
                addritem_folder_add_person( cache->rootFolder, person );
440
        }
441
        return retVal;
442
}
443

    
444
/*
445
* Add EMail address to person.
446
* return: TRUE if item added.
447
*/
448
gboolean addrcache_person_add_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
449
        g_return_val_if_fail( cache != NULL, FALSE );
450
        g_return_val_if_fail( person != NULL, FALSE );
451
        g_return_val_if_fail( email != NULL, FALSE );
452

    
453
        addritem_person_add_email( person, email );
454
        return TRUE;
455
}
456

    
457
/*
458
* Add group to address cache.
459
* return: TRUE if item added.
460
*/
461
gboolean addrcache_add_group( AddressCache *cache, ItemGroup *group ) {
462
        gboolean retVal = FALSE;
463

    
464
        g_return_val_if_fail( cache != NULL, FALSE );
465
        g_return_val_if_fail( group != NULL, FALSE );
466

    
467
        retVal = addrcache_hash_add_group( cache, group );
468
        if( retVal ) {
469
                addritem_folder_add_group( cache->rootFolder, group );
470
        }
471
        return retVal;
472
}
473

    
474
/*
475
* Add EMail address to person.
476
* return: TRUE if item added.
477
*/
478
gboolean addrcache_group_add_email( AddressCache *cache, ItemGroup *group, ItemEMail *email ) {
479
        g_return_val_if_fail( cache != NULL, FALSE );
480
        g_return_val_if_fail( group != NULL, FALSE );
481
        g_return_val_if_fail( email != NULL, FALSE );
482

    
483
        addritem_group_add_email( group, email );
484
        return TRUE;
485
}
486

    
487
/*
488
* Add folder to address cache.
489
* return: TRUE if item added.
490
*/
491
gboolean addrcache_add_folder( AddressCache *cache, ItemFolder *folder ) {
492
        gboolean retVal = FALSE;
493

    
494
        g_return_val_if_fail( cache != NULL, FALSE );
495
        g_return_val_if_fail( folder != NULL, FALSE );
496

    
497
        retVal = addrcache_hash_add_folder( cache, folder );
498
        if( retVal ) {
499
                addritem_folder_add_folder( cache->rootFolder, folder );
500
        }
501
        return retVal;
502
}
503

    
504
/*
505
* Return pointer to object (either person or group) for specified ID.
506
* param: uid Object ID.
507
* return: Object, or NULL if not found.
508
*/
509
AddrItemObject *addrcache_get_object( AddressCache *cache, const gchar *uid ) {
510
        AddrItemObject *obj = NULL;
511
        gchar *uidH;
512

    
513
        g_return_val_if_fail( cache != NULL, NULL );
514

    
515
        if( uid == NULL || *uid == '\0' ) return NULL;
516
        obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
517
        if( obj ) {
518
                /* Check for matching UID */
519
                uidH = ADDRITEM_ID(obj);
520
                if( uidH ) {
521
                        if( strcmp( uidH, uid ) == 0 ) return obj;
522
                }
523
        }
524
        return NULL;
525
}
526

    
527
/*
528
* Return pointer for specified object ID.
529
* param: uid Object ID.
530
* return: Person object, or NULL if not found.
531
*/
532
ItemPerson *addrcache_get_person( AddressCache *cache, const gchar *uid ) {
533
        ItemPerson *person = NULL;
534
        AddrItemObject *obj = addrcache_get_object( cache, uid );
535

    
536
        if( obj ) {
537
                if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
538
                        person = ( ItemPerson * ) obj;
539
                }
540
        }
541
        return person;
542
}
543

    
544
/*
545
* Return pointer for specified object ID.
546
* param: uid group ID.
547
* return: Group object, or NULL if not found.
548
*/
549
ItemGroup *addrcache_get_group( AddressCache *cache, const gchar *uid ) {
550
        ItemGroup *group = NULL;
551
        AddrItemObject *obj = addrcache_get_object( cache, uid );
552

    
553
        if( obj ) {
554
                if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
555
                        group = ( ItemGroup * ) obj;
556
                }
557
        }
558
        return group;
559
}
560

    
561
/*
562
* Find email address in address cache.
563
* param: uid        Object ID for person.
564
*        eid        EMail ID.
565
* return: email object for specified object ID and email ID, or NULL if not found.
566
*/
567
ItemEMail *addrcache_get_email( AddressCache *cache, const gchar *uid, const gchar *eid ) {
568
        AddrItemObject *objP;
569

    
570
        if( eid == NULL || *eid == '\0' ) return NULL;
571

    
572
        objP = addrcache_get_object( cache, uid );
573
        if( objP ) {
574
                if( ADDRITEM_TYPE(objP) == ITEMTYPE_PERSON ) {
575
                        /* Sequential search through email addresses */
576
                        ItemPerson *person = ( ItemPerson * ) objP;
577
                        GList *nodeMail = person->listEMail;
578
                        while( nodeMail ) {
579
                                AddrItemObject *objE = nodeMail->data;
580
                                gchar *ide = ADDRITEM_ID(objE);
581
                                if( ide ) {
582
                                        if( strcmp( ide, eid ) == 0 ) {
583
                                                return ( ItemEMail * ) objE;
584
                                        }
585
                                }
586
                                nodeMail = g_list_next( nodeMail );
587
                        }
588
                }
589
        }
590
        return NULL;
591
}
592

    
593
/*
594
* Remove attribute from person.
595
* param: uid        Object ID for person.
596
*        aid        Attribute ID.
597
* return: UserAttribute object, or NULL if not found. Note that object should still be freed.
598
*/
599
UserAttribute *addrcache_person_remove_attrib_id( AddressCache *cache, const gchar *uid, const gchar *aid ) {
600
        UserAttribute *attrib = NULL;
601
        ItemPerson *person;
602

    
603
        if( aid == NULL || *aid == '\0' ) return NULL;
604

    
605
        person = addrcache_get_person( cache, uid );
606
        if( person ) {
607
                attrib = addritem_person_remove_attrib_id( person, aid );
608
        }
609
        return attrib;
610
}
611

    
612
/*
613
* Remove attribute from person.
614
* param: person        Person.
615
*        attrib        Attribute to remove.
616
* return: UserAttribute object. Note that object should still be freed.
617
*/
618
UserAttribute *addrcache_person_remove_attribute( AddressCache *cache, ItemPerson *person, UserAttribute *attrib ) {
619
        UserAttribute *found = NULL;
620

    
621
        g_return_val_if_fail( cache != NULL, NULL );
622

    
623
        if( person && attrib ) {
624
                found = addritem_person_remove_attribute( person, attrib );
625
        }
626
        return found;
627
}
628

    
629
/*
630
* Remove group from address cache for specified ID.
631
* param: uid Object ID.
632
* return: Group, or NULL if not found. Note that object should still be freed.
633
*/
634
ItemGroup *addrcache_remove_group_id( AddressCache *cache, const gchar *uid ) {
635
        AddrItemObject *obj = NULL;
636

    
637
        g_return_val_if_fail( cache != NULL, NULL );
638

    
639
        if( uid == NULL || *uid == '\0' ) return NULL;
640
        obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
641
        if( obj ) {
642
                if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
643
                        ItemGroup *group = ( ItemGroup * ) obj;
644
                        ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
645
                        if( ! parent ) parent = cache->rootFolder;
646
                        /* Remove group from parent's list and hash table */
647
                        parent->listGroup = g_list_remove( parent->listGroup, group );
648
                        g_hash_table_remove( cache->itemHash, uid );
649
                        return ( ItemGroup * ) obj;
650
                }
651
        }
652
        return NULL;
653
}
654

    
655
/*
656
* Remove group from address cache.
657
* param: group        Group to remove.
658
* return: Group, or NULL if not found. Note that object should still be freed.
659
*/
660
ItemGroup *addrcache_remove_group( AddressCache *cache, ItemGroup *group ) {
661
        AddrItemObject *obj = NULL;
662

    
663
        g_return_val_if_fail( cache != NULL, NULL );
664

    
665
        if( group ) {
666
                gchar *uid = ADDRITEM_ID(group);
667
                if( uid == NULL || *uid == '\0' ) return NULL;
668
                obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
669
                if( obj ) {
670
                        ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(group);
671
                        if( ! parent ) parent = cache->rootFolder;
672

    
673
                        /* Remove group from parent's list and hash table */
674
                        parent->listGroup = g_list_remove( parent->listGroup, obj );
675
                        g_hash_table_remove( cache->itemHash, uid );
676
                        return group;
677
                }
678
        }
679
        return NULL;
680
}
681

    
682
/*
683
* Remove person's email address from all groups in folder.
684
*/
685
static void addrcache_foldergrp_rem_person( ItemFolder *folder, ItemPerson *person ) {
686
        GList *nodeGrp = folder->listGroup;
687

    
688
        while( nodeGrp ) {
689
                ItemGroup *group = nodeGrp->data;
690
                if( group ) {
691
                        /* Remove each email address that belongs to the person from the list */
692
                        GList *node = person->listEMail;
693
                        while( node ) {
694
                                group->listEMail = g_list_remove( group->listEMail, node->data );
695
                                node = g_list_next( node );
696
                        }
697
                }
698
                nodeGrp = g_list_next( nodeGrp );
699
        }
700
}
701

    
702
/*
703
* Remove person from address cache for specified ID. Note that person still retains
704
* their EMail addresses. Also, links to these email addresses will be severed from
705
* the group.
706
* param: uid Object ID.
707
* return: Person, or NULL if not found. Note that object should still be freed.
708
*/
709
ItemPerson *addrcache_remove_person_id( AddressCache *cache, const gchar *uid ) {
710
        AddrItemObject *obj = NULL;
711

    
712
        g_return_val_if_fail( cache != NULL, NULL );
713

    
714
        if( uid == NULL || *uid == '\0' ) return NULL;
715
        obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
716
        if( obj ) {
717
                if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
718
                        /* Remove person's email addresses from all groups where */
719
                        /* referenced and from hash table. */
720
                        ItemPerson *person = ( ItemPerson * ) obj;
721
                        ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
722
                        if( ! parent ) parent = cache->rootFolder;
723
                        /* Remove emails from groups, remove from parent's list */
724
                        /* and hash table */
725
                        addrcache_foldergrp_rem_person( parent, person );
726
                        parent->listPerson = g_list_remove( parent->listPerson, person );
727
                        g_hash_table_remove( cache->itemHash, uid );
728
                        return person;
729
                }
730
        }
731
        return NULL;
732
}
733

    
734
/*
735
* Remove specified person from address cache.
736
* param: person        Person to remove.
737
* return: Person, or NULL if not found. Note that object should still be freed.
738
*/
739
ItemPerson *addrcache_remove_person( AddressCache *cache, ItemPerson *person ) {
740
        AddrItemObject *obj = NULL;
741

    
742
        g_return_val_if_fail( cache != NULL, NULL );
743

    
744
        if( person ) {
745
                gchar *uid = ADDRITEM_ID(person);
746
                if( uid == NULL || *uid == '\0' ) return NULL;
747
                obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
748
                if( obj ) {
749
                        if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
750
                                /* Remove person's email addresses from all groups where */
751
                                /* referenced and from hash table. */
752
                                ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
753
                                if( ! parent ) parent = cache->rootFolder;
754
                                addrcache_foldergrp_rem_person( parent, person );
755
                                parent->listPerson = g_list_remove( parent->listPerson, person );
756
                                g_hash_table_remove( cache->itemHash, uid );
757
                                return person;
758
                        }
759
                }
760
        }
761
        return NULL;
762
}
763

    
764
/*
765
* Remove email from group item hash table visitor function.
766
*/
767
static void addrcache_allgrp_rem_email_vis( gpointer key, gpointer value, gpointer data ) {
768
        AddrItemObject *obj = ( AddrItemObject * ) value;
769
        ItemEMail *email = ( ItemEMail * ) data;
770

    
771
        if( !email ) return;
772
        if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
773
                ItemGroup *group = ( ItemGroup * ) value;
774
                if( group ) {
775
                        /* Remove each email address that belongs to the person from the list */
776
                        group->listEMail = g_list_remove( group->listEMail, email );
777
                }
778
        }
779
}
780

    
781
/*
782
* Remove email address in address cache for specified ID.
783
* param: uid        Object ID for person.
784
*        eid        EMail ID.
785
* return: EMail object, or NULL if not found. Note that object should still be freed.
786
*/
787
ItemEMail *addrcache_person_remove_email_id( AddressCache *cache, const gchar *uid, const gchar *eid ) {
788
        ItemEMail *email = NULL;
789
        ItemPerson *person;
790

    
791
        if( eid == NULL || *eid == '\0' ) return NULL;
792

    
793
        person = addrcache_get_person( cache, uid );
794
        if( person ) {
795
                email = addritem_person_remove_email_id( person, eid );
796
                if( email ) {
797
                        /* Remove email from all groups. */
798
                        g_hash_table_foreach( cache->itemHash, addrcache_allgrp_rem_email_vis, email );
799

    
800
                        /* Remove email from person's address list */
801
                        if( person->listEMail ) {
802
                                person->listEMail = g_list_remove( person->listEMail, email );
803
                        }
804
                        /* Unlink reference to person. */
805
                        ADDRITEM_PARENT(email) = NULL;
806
                }
807
        }
808
        return email;
809
}
810

    
811
/*
812
* Remove email address in address cache for specified person.
813
* param: person        Person.
814
*        email        EMail to remove.
815
* return: EMail object, or NULL if not found. Note that object should still be freed.
816
*/
817
ItemEMail *addrcache_person_remove_email( AddressCache *cache, ItemPerson *person, ItemEMail *email ) {
818
        ItemEMail *found = NULL;
819

    
820
        g_return_val_if_fail( cache != NULL, NULL );
821

    
822
        if( person && email ) {
823
                found = addritem_person_remove_email( person, email );
824
                if( found ) {
825
                        /* Remove email from all groups. */
826
                        g_hash_table_foreach( cache->itemHash, addrcache_allgrp_rem_email_vis, email );
827

    
828
                        /* Remove email from person's address list */
829
                        if( person->listEMail ) {
830
                                person->listEMail = g_list_remove( person->listEMail, email );
831
                        }
832
                        /* Unlink reference to person. */
833
                        ADDRITEM_PARENT(email) = NULL;
834
                }
835
        }
836
        return found;
837
}
838

    
839
/*
840
* Return link list of address items for root level folder. Note that the list contains
841
* references to items and should be g_free() when done. Do *NOT* attempt to use the
842
* addrcache_free_xxx() functions... this will destroy the address cache data!
843
* Return: List of items, or NULL if none.
844
*/
845
GList *addrcache_folder_get_address_list( AddressCache *cache, ItemFolder *folder ) {
846
        GList *list = NULL;
847
        GList *node = NULL;
848
        ItemFolder *f = folder;
849

    
850
        g_return_val_if_fail( cache != NULL, NULL );
851

    
852
        if( ! f ) f = cache->rootFolder;
853
        node = f->listPerson;
854
        while( node ) {
855
                list = g_list_append( list, node->data );
856
                node = g_list_next( node );
857
        }
858
        node = f->listGroup;
859
        while( node ) {
860
                list = g_list_append( list, node->data );
861
                node = g_list_next( node );
862
        }
863
        return list;
864
}
865

    
866
/*
867
* Return link list of persons for specified folder. Note that the list contains
868
* references to items and should be g_free() when done. Do *NOT* attempt to use the
869
* addrcache_free_xxx() functions... this will destroy the address cache data!
870
* Return: List of items, or NULL if none.
871
*/
872
GList *addrcache_folder_get_person_list( AddressCache *cache, ItemFolder *folder ) {
873
        ItemFolder *f = folder;
874

    
875
        g_return_val_if_fail( cache != NULL, NULL );
876

    
877
        if( ! f ) f = cache->rootFolder;
878
        return addritem_folder_get_person_list( f );
879
}
880

    
881
/*
882
* Return link list of group items for specified folder. Note that the list contains
883
* references to items and should be g_free() when done. Do *NOT* attempt to use the
884
* addrcache_free_xxx() functions... this will destroy the address cache data!
885
* Return: List of items, or NULL if none.
886
*/
887
GList *addrcache_folder_get_group_list( AddressCache *cache, ItemFolder *folder ) {
888
        ItemFolder *f = folder;
889

    
890
        g_return_val_if_fail( cache != NULL, NULL );
891

    
892
        if( ! f ) f = cache->rootFolder;
893
        return addritem_folder_get_group_list( f );
894
}
895

    
896
/*
897
* Return link list of folder items for specified folder. Note that the list contains
898
* references to items and should be g_free() when done. Do *NOT* attempt to used the
899
* addrcache_free_xxx() functions... this will destroy the address cache data!
900
* Return: List of items, or NULL if none.
901
*/
902
GList *addrcache_folder_get_folder_list( AddressCache *cache, ItemFolder *folder ) {
903
        GList *node = NULL;
904
        GList *list = NULL;
905
        ItemFolder *f = folder;
906

    
907
        g_return_val_if_fail( cache != NULL, NULL );
908

    
909
        if( ! f ) f = cache->rootFolder;
910
        node = f->listFolder;
911
        while( node ) {
912
                list = g_list_append( list, node->data );
913
                node = g_list_next( node );
914
        }
915
        return list;
916
}
917

    
918
/*
919
* Return link list of address items for root level folder. Note that the list contains
920
* references to items and should be g_free() when done. Do *NOT* attempt to used the
921
* addrcache_free_xxx() functions... this will destroy the address cache data!
922
* Return: List of items, or NULL if none.
923
*/
924
GList *addrcache_get_address_list( AddressCache *cache ) {
925
        g_return_val_if_fail( cache != NULL, NULL );
926
        return addrcache_folder_get_address_list( cache, cache->rootFolder );
927
}
928

    
929
/*
930
* Return link list of persons for root level folder. Note that the list contains
931
* references to items and should be g_free() when done. Do *NOT* attempt to used the
932
* addrcache_free_xxx() functions... this will destroy the address cache data!
933
* Return: List of items, or NULL if none.
934
*/
935
GList *addrcache_get_person_list( AddressCache *cache ) {
936
        g_return_val_if_fail( cache != NULL, NULL );
937
        return addritem_folder_get_person_list( cache->rootFolder );
938
}
939

    
940
/*
941
* Return link list of group items in root level folder. Note that the list contains
942
* references to items and should be g_free() when done. Do *NOT* attempt to used the
943
* addrcache_free_xxx() functions... this will destroy the address cache data!
944
* Return: List of items, or NULL if none.
945
*/
946
GList *addrcache_get_group_list( AddressCache *cache ) {
947
        g_return_val_if_fail( cache != NULL, NULL );
948
        return cache->rootFolder->listGroup;
949
}
950

    
951
/*
952
* Return link list of folder items in root level folder. Note that the list contains
953
* references to items and should be g_free() when done. Do *NOT* attempt to used the
954
* addrcache_free_xxx() functions... this will destroy the address cache data!
955
* Return: List of items, or NULL if none.
956
*/
957
GList *addrcache_get_folder_list( AddressCache *cache ) {
958
        g_return_val_if_fail( cache != NULL, NULL );
959
        return cache->rootFolder->listFolder;
960
}
961

    
962
/*
963
* Group visitor function.
964
*/
965
static void addrcache_get_grp_person_vis( gpointer key, gpointer value, gpointer data ) {
966
        AddrItemObject *obj = ( AddrItemObject * ) value;
967

    
968
        if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
969
                AddressCache *cache = data;
970
                ItemGroup *group = ( ItemGroup * ) obj;
971
                ItemPerson *person = ( ItemPerson * ) cache->tempList->data;
972
                GList *node = group->listEMail;
973
                while( node ) {
974
                        ItemEMail *email = ( ItemEMail * ) node->data;
975
                        if( ADDRITEM_PARENT(email) == ADDRITEM_OBJECT(person) ) {
976
                                if( ! g_list_find( cache->tempList, group ) ) {
977
                                        cache->tempList = g_list_append( cache->tempList, group );
978
                                }
979
                        }
980
                        node = g_list_next( node );
981
                }
982
        }
983
}
984

    
985
/*
986
* Return link list of groups which contain a reference to specified person's email
987
* address.
988
*/
989
GList *addrcache_get_group_for_person( AddressCache *cache, ItemPerson *person ) {
990
        GList *list = NULL;
991

    
992
        g_return_val_if_fail( cache != NULL, NULL );
993

    
994
        cache->tempList = NULL;
995
        cache->tempList = g_list_append( cache->tempList, person );
996
        g_hash_table_foreach( cache->itemHash, addrcache_get_grp_person_vis, cache );
997
        cache->tempList = g_list_remove( cache->tempList, person );
998
        list = cache->tempList;
999
        cache->tempList = NULL;
1000
        return list;
1001
}
1002

    
1003
/*
1004
* Find root folder for specified folder.
1005
* Enter: folder Folder to search.
1006
* Return: root folder, or NULL if not found.
1007
*/
1008
ItemFolder *addrcache_find_root_folder( ItemFolder *folder ) {
1009
        ItemFolder *item = folder;
1010
        gint count = 0;
1011

    
1012
        while( item ) {
1013
                if( item->isRoot ) break;
1014
                if( ++count > ADDRCACHE_MAX_SEARCH_COUNT ) {
1015
                        item = NULL;
1016
                        break;
1017
                }
1018
                item = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1019
        }
1020
        return item;
1021
}
1022

    
1023
/*
1024
* Get all person visitor function.
1025
*/
1026
static void addrcache_get_all_persons_vis( gpointer key, gpointer value, gpointer data ) {
1027
        AddrItemObject *obj = ( AddrItemObject * ) value;
1028

    
1029
        if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
1030
                AddressCache *cache = data;
1031
                cache->tempList = g_list_append( cache->tempList, obj );
1032
        }
1033
}
1034

    
1035
/*
1036
* Return link list of all persons in address cache.  Note that the list contains
1037
* references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
1038
* this will destroy the address cache data!
1039
* Return: List of items, or NULL if none.
1040
*/
1041
GList *addrcache_get_all_persons( AddressCache *cache ) {
1042
        GList *list = NULL;
1043

    
1044
        g_return_val_if_fail( cache != NULL, NULL );
1045

    
1046
        cache->tempList = NULL;
1047
        g_hash_table_foreach( cache->itemHash, addrcache_get_all_persons_vis, cache );
1048
        list = cache->tempList;
1049
        cache->tempList = NULL;
1050
        return list;
1051
}
1052

    
1053
/*
1054
* Get all groups visitor function.
1055
*/
1056
static void addrcache_get_all_groups_vis( gpointer key, gpointer value, gpointer data ) {
1057
        AddrItemObject *obj = ( AddrItemObject * ) value;
1058

    
1059
        if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
1060
                AddressCache *cache = data;
1061
                cache->tempList = g_list_append( cache->tempList, obj );
1062
        }
1063
}
1064

    
1065
/*
1066
* Return link list of all groups in address cache.  Note that the list contains
1067
* references to items. Do *NOT* attempt to use the addrcache_free_xxx() functions...
1068
* this will destroy the address cache data!
1069
* Return: List of items, or NULL if none.
1070
*/
1071
GList *addrcache_get_all_groups( AddressCache *cache ) {
1072
        GList *list = NULL;
1073

    
1074
        g_return_val_if_fail( cache != NULL, NULL );
1075

    
1076
        cache->tempList = NULL;
1077
        g_hash_table_foreach( cache->itemHash, addrcache_get_all_groups_vis, cache );
1078
        list = cache->tempList;
1079
        cache->tempList = NULL;
1080
        return list;
1081
}
1082

    
1083
/*
1084
* Remove folder from cache. Children are re-parented to parent folder.
1085
* param: folder Folder to remove.
1086
* return: Folder, or NULL if not found. Note that object should still be freed.
1087
*/
1088
ItemFolder *addrcache_remove_folder( AddressCache *cache, ItemFolder *folder ) {
1089
        AddrItemObject *obj = NULL;
1090

    
1091
        g_return_val_if_fail( cache != NULL, NULL );
1092

    
1093
        if( folder ) {
1094
                gchar *uid = ADDRITEM_ID(folder);
1095
                if( uid == NULL || *uid == '\0' ) return NULL;
1096
                obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
1097
                if( obj ) {
1098
                        ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1099
                        GList *node;
1100
                        AddrItemObject *aio;
1101
                        if( ! parent ) parent = cache->rootFolder;
1102

    
1103
                        /* Re-parent children in folder */
1104
                        node = folder->listFolder;
1105
                        while( node ) {
1106
                                aio = ( AddrItemObject * ) node->data;
1107
                                parent->listFolder = g_list_append( parent->listFolder, aio );
1108
                                aio->parent = ADDRITEM_OBJECT(parent);
1109
                                node = g_list_next( node );
1110
                        }
1111
                        node = folder->listPerson;
1112
                        while( node ) {
1113
                                aio = ( AddrItemObject * ) node->data;
1114
                                parent->listPerson = g_list_append( parent->listPerson, aio );
1115
                                aio->parent = ADDRITEM_OBJECT(parent);
1116
                                node = g_list_next( node );
1117
                        }
1118
                        node = folder->listGroup;
1119
                        while( node ) {
1120
                                aio = ( AddrItemObject * ) node->data;
1121
                                parent->listGroup = g_list_append( parent->listGroup, aio );
1122
                                aio->parent = ADDRITEM_OBJECT(parent);
1123
                                node = g_list_next( node );
1124
                        }
1125

    
1126
                        /* Remove folder from parent's list and hash table */
1127
                        parent->listFolder = g_list_remove( parent->listFolder, folder );
1128
                        ADDRITEM_PARENT(folder) = NULL;
1129
                        g_hash_table_remove( cache->itemHash, uid );
1130
                        return folder;
1131
                }
1132
        }
1133
        return NULL;
1134
}
1135

    
1136
/*
1137
* Remove folder from cache. Children are deleted.
1138
* param: folder Folder to remove.
1139
* return: Folder, or NULL if not found. Note that object should still be freed.
1140
*/
1141
ItemFolder *addrcache_remove_folder_delete( AddressCache *cache, ItemFolder *folder ) {
1142
        AddrItemObject *obj = NULL;
1143

    
1144
        g_return_val_if_fail( cache != NULL, NULL );
1145

    
1146
        if( folder ) {
1147
                gchar *uid = ADDRITEM_ID(folder);
1148
                if( uid == NULL || *uid == '\0' ) return NULL;
1149
                obj = ( AddrItemObject * ) g_hash_table_lookup( cache->itemHash, uid );
1150
                if( obj ) {
1151
                        ItemFolder *parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
1152
                        if( ! parent ) parent = cache->rootFolder;
1153

    
1154
                        /* Remove groups */
1155
                        while( folder->listGroup ) {
1156
                                ItemGroup *item = ( ItemGroup * ) folder->listGroup->data;
1157
                                item = addrcache_remove_group( cache, item );
1158
                                if( item ) {
1159
                                        addritem_free_item_group( item );
1160
                                        item = NULL;
1161
                                }
1162
                        }
1163

    
1164
                        while( folder->listPerson ) {
1165
                                ItemPerson *item = ( ItemPerson * ) folder->listPerson->data;
1166
                                item = addrcache_remove_person( cache, item );
1167
                                if( item ) {
1168
                                        addritem_free_item_person( item );
1169
                                        item = NULL;
1170
                                }
1171
                        }
1172

    
1173
                        /* Recursive deletion of folder */
1174
                        while( folder->listFolder ) {
1175
                                ItemFolder *item = ( ItemFolder * ) folder->listFolder->data;
1176
                                item = addrcache_remove_folder_delete( cache, item );
1177
                                if( item ) {
1178
                                        addritem_free_item_folder( item );
1179
                                        item = NULL;
1180
                                }
1181
                        }
1182

    
1183
                        /* Remove folder from parent's list and hash table */
1184
                        parent->listFolder = g_list_remove( parent->listFolder, folder );
1185
                        ADDRITEM_PARENT(folder) = NULL;
1186
                        g_hash_table_remove( cache->itemHash, uid );
1187
                        return folder;
1188
                }
1189
        }
1190
        return NULL;
1191
}
1192

    
1193
/*
1194
* Add person and address data to cache.
1195
* Enter: cache     Cache.
1196
*        folder    Folder where to add person, or NULL for root folder.
1197
*        name      Common name.
1198
*        address   EMail address.
1199
*        remarks   Remarks.
1200
* Return: Person added. Do not *NOT* to use the addrbook_free_xxx() functions...
1201
* this will destroy the address book data.
1202
*/
1203
ItemPerson *addrcache_add_contact( AddressCache *cache, ItemFolder *folder, const gchar *name,
1204
                const gchar *address, const gchar *remarks )
1205
{
1206
        ItemPerson *person = NULL;
1207
        ItemEMail *email = NULL;
1208
        ItemFolder *f = folder;
1209

    
1210
        g_return_val_if_fail( cache != NULL, NULL );
1211

    
1212
        if( ! f ) f = cache->rootFolder;
1213

    
1214
        /* Create person object */
1215
        person = addritem_create_item_person();
1216
        addritem_person_set_common_name( person, name );
1217
        addrcache_id_person( cache, person );
1218
        addrcache_folder_add_person( cache, f, person );
1219

    
1220
        /* Create email object */
1221
        email = addritem_create_item_email();
1222
        addritem_email_set_address( email, address );
1223
        addritem_email_set_remarks( email, remarks );
1224
        addrcache_id_email( cache, email );
1225
        addritem_person_add_email( person, email );
1226

    
1227
        return person;
1228
}
1229

    
1230
/*
1231
* End of Source.
1232
*/