Statistics
| Revision:

root / src / addrbook.c @ 2916

History | View | Annotate | Download (54.9 kB)

1 1 hiro
/*
2 1 hiro
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 1 hiro
 * Copyright (C) 2001 Match Grun
4 1 hiro
 *
5 1 hiro
 * This program is free software; you can redistribute it and/or modify
6 1 hiro
 * it under the terms of the GNU General Public License as published by
7 1 hiro
 * the Free Software Foundation; either version 2 of the License, or
8 1 hiro
 * (at your option) any later version.
9 1 hiro
 *
10 1 hiro
 * This program is distributed in the hope that it will be useful,
11 1 hiro
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 1 hiro
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 1 hiro
 * GNU General Public License for more details.
14 1 hiro
 *
15 1 hiro
 * You should have received a copy of the GNU General Public License
16 1 hiro
 * along with this program; if not, write to the Free Software
17 1 hiro
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 1 hiro
 */
19 1 hiro
20 1 hiro
/*
21 1 hiro
 * General functions for accessing external address book files.
22 1 hiro
 */
23 1 hiro
24 1 hiro
#include <glib.h>
25 1 hiro
#include <stdio.h>
26 1 hiro
#include <stdlib.h>
27 1 hiro
#include <sys/stat.h>
28 1 hiro
#include <math.h>
29 1 hiro
#include <setjmp.h>
30 1 hiro
31 1 hiro
#include "xml.h"
32 1 hiro
#include "mgutils.h"
33 1 hiro
#include "addritem.h"
34 1 hiro
#include "addrcache.h"
35 1 hiro
#include "addrbook.h"
36 478 hiro
#include "utils.h"
37 1 hiro
38 1 hiro
#ifndef DEV_STANDALONE
39 1 hiro
#include "prefs.h"
40 1 hiro
#include "codeconv.h"
41 1 hiro
#endif
42 1 hiro
43 1 hiro
#define ADDRBOOK_MAX_SEARCH_COUNT 1000
44 1 hiro
#define ADDRBOOK_PREFIX           "addrbook-"
45 1 hiro
#define ADDRBOOK_SUFFIX           ".xml"
46 1 hiro
#define FILE_NUMDIGITS            6
47 1 hiro
48 1 hiro
#define ID_TIME_OFFSET            998000000
49 1 hiro
/*
50 1 hiro
* Create new address book.
51 1 hiro
*/
52 1 hiro
AddressBookFile *addrbook_create_book() {
53 1 hiro
        AddressBookFile *book;
54 1 hiro
55 1 hiro
        book = g_new0( AddressBookFile, 1 );
56 1 hiro
        book->name = NULL;
57 1 hiro
        book->path = NULL;
58 1 hiro
        book->fileName = NULL;
59 1 hiro
        book->retVal = MGU_SUCCESS;
60 1 hiro
        book->addressCache = addrcache_create();
61 1 hiro
62 1 hiro
        book->tempList = NULL;
63 1 hiro
        book->readFlag = FALSE;
64 1 hiro
        book->dirtyFlag = FALSE;
65 1 hiro
        book->modifyFlag = TRUE;
66 1 hiro
        book->accessFlag = FALSE;
67 1 hiro
        book->tempHash = NULL;
68 1 hiro
        return book;
69 1 hiro
}
70 1 hiro
71 1 hiro
/*
72 1 hiro
* Specify name to be used.
73 1 hiro
*/
74 1 hiro
void addrbook_set_name( AddressBookFile *book, const gchar *value ) {
75 1 hiro
        g_return_if_fail( book != NULL );
76 1 hiro
        book->name = mgu_replace_string( book->name, value );
77 1 hiro
}
78 1 hiro
void addrbook_set_path( AddressBookFile *book, const gchar *value ) {
79 1 hiro
        g_return_if_fail( book != NULL );
80 1 hiro
        book->path = mgu_replace_string( book->path, value );
81 1 hiro
        book->dirtyFlag = TRUE;
82 1 hiro
}
83 1 hiro
void addrbook_set_file( AddressBookFile *book, const gchar *value ) {
84 1 hiro
        g_return_if_fail( book != NULL );
85 1 hiro
        book->fileName = mgu_replace_string( book->fileName, value );
86 1 hiro
        book->dirtyFlag = TRUE;
87 1 hiro
}
88 1 hiro
void addrbook_set_accessed( AddressBookFile *book, const gboolean value ) {
89 1 hiro
        g_return_if_fail( book != NULL );
90 1 hiro
        book->accessFlag = value;
91 1 hiro
}
92 1 hiro
gboolean addrbook_get_modified( AddressBookFile *book ) {
93 1 hiro
        g_return_val_if_fail( book != NULL, FALSE );
94 1 hiro
        return book->modifyFlag;
95 1 hiro
}
96 1 hiro
gboolean addrbook_get_accessed( AddressBookFile *book ) {
97 1 hiro
        g_return_val_if_fail( book != NULL, FALSE );
98 1 hiro
        return book->accessFlag;
99 1 hiro
}
100 1 hiro
gboolean addrbook_get_read_flag( AddressBookFile *book ) {
101 1 hiro
        g_return_val_if_fail( book != NULL, FALSE );
102 1 hiro
        return book->readFlag;
103 1 hiro
}
104 1 hiro
gint addrbook_get_status( AddressBookFile *book ) {
105 1 hiro
        g_return_val_if_fail( book != NULL, -1 );
106 1 hiro
        return book->retVal;
107 1 hiro
}
108 1 hiro
ItemFolder *addrbook_get_root_folder( AddressBookFile *book ) {
109 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
110 1 hiro
        return addrcache_get_root_folder( book->addressCache );
111 1 hiro
}
112 1 hiro
GList *addrbook_get_list_folder( AddressBookFile *book ) {
113 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
114 1 hiro
        return addrcache_get_list_folder( book->addressCache );
115 1 hiro
}
116 1 hiro
GList *addrbook_get_list_person( AddressBookFile *book ) {
117 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
118 1 hiro
        return addrcache_get_list_person( book->addressCache );
119 1 hiro
}
120 1 hiro
gchar *addrbook_get_name( AddressBookFile *book ) {
121 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
122 1 hiro
        return book->name;
123 1 hiro
}
124 1 hiro
125 1 hiro
/*
126 1 hiro
* Empty address book.
127 1 hiro
*/
128 1 hiro
void addrbook_empty_book( AddressBookFile *book ) {
129 1 hiro
        g_return_if_fail( book != NULL );
130 1 hiro
131 1 hiro
        /* Free up folders and hash table */
132 1 hiro
        addrcache_clear( book->addressCache );
133 1 hiro
134 1 hiro
        g_list_free( book->tempList );
135 1 hiro
        book->tempList = NULL;
136 1 hiro
137 1 hiro
        /* Reset to initial state */
138 1 hiro
        book->retVal = MGU_SUCCESS;
139 1 hiro
        book->tempHash = NULL;
140 1 hiro
        book->readFlag = FALSE;
141 1 hiro
        book->dirtyFlag = FALSE;
142 1 hiro
        book->modifyFlag = FALSE;
143 1 hiro
        book->accessFlag = FALSE;
144 1 hiro
}
145 1 hiro
146 1 hiro
/*
147 1 hiro
* Free address book.
148 1 hiro
*/
149 1 hiro
void addrbook_free_book( AddressBookFile *book ) {
150 1 hiro
        g_return_if_fail( book != NULL );
151 1 hiro
152 1 hiro
        g_free( book->name );
153 1 hiro
        g_free( book->path );
154 1 hiro
        g_free( book->fileName );
155 1 hiro
        book->name = NULL;
156 1 hiro
        book->path = NULL;
157 1 hiro
        book->fileName = NULL;
158 1 hiro
159 1 hiro
        /* Free up folders and hash table */
160 1 hiro
        addrcache_free( book->addressCache );
161 1 hiro
        book->addressCache = NULL;
162 1 hiro
163 1 hiro
        g_list_free( book->tempList );
164 1 hiro
        book->tempList = NULL;
165 1 hiro
166 1 hiro
        book->retVal = MGU_SUCCESS;
167 1 hiro
        book->tempHash = NULL;
168 1 hiro
        book->readFlag = FALSE;
169 1 hiro
        book->dirtyFlag = FALSE;
170 1 hiro
        book->modifyFlag = FALSE;
171 1 hiro
        book->accessFlag = FALSE;
172 1 hiro
173 1 hiro
        g_free( book );
174 1 hiro
}
175 1 hiro
176 1 hiro
/*
177 1 hiro
* Print list of items.
178 1 hiro
*/
179 1 hiro
void addrbook_print_item_list( GList *list, FILE *stream ) {
180 1 hiro
        GList *node = list;
181 1 hiro
182 1 hiro
        while( node ) {
183 1 hiro
                AddrItemObject *obj = node->data;
184 1 hiro
                if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
185 1 hiro
                        addritem_print_item_person( ( ItemPerson * ) obj, stream );
186 1 hiro
                }
187 1 hiro
                else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
188 1 hiro
                        addritem_print_item_group( ( ItemGroup * ) obj, stream );
189 1 hiro
                }
190 1 hiro
                else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
191 1 hiro
                        addritem_print_item_folder( ( ItemFolder * ) obj, stream );
192 1 hiro
                }
193 1 hiro
                node = g_list_next( node );
194 1 hiro
        }
195 1 hiro
        fprintf( stream, "\t---\n" );
196 1 hiro
}
197 1 hiro
198 1 hiro
/*
199 1 hiro
* Print address book.
200 1 hiro
*/
201 1 hiro
void addrbook_print_book( AddressBookFile *book, FILE *stream ) {
202 1 hiro
        g_return_if_fail( book != NULL );
203 1 hiro
204 1 hiro
        fprintf( stream, "AddressBook:\n" );
205 1 hiro
        fprintf( stream, "\tname  : '%s'\n", book->name );
206 1 hiro
        fprintf( stream, "\tpath  : '%s'\n", book->path );
207 1 hiro
        fprintf( stream, "\tfile  : '%s'\n", book->fileName );
208 1 hiro
        fprintf( stream, "\tstatus: %d : '%s'\n", book->retVal, mgu_error2string( book->retVal ) );
209 1 hiro
        addrcache_print( book->addressCache, stream );
210 1 hiro
}
211 1 hiro
212 1 hiro
/*
213 1 hiro
* Dump entire address book traversing folders.
214 1 hiro
*/
215 1 hiro
void addrbook_dump_book( AddressBookFile *book, FILE *stream ) {
216 1 hiro
        ItemFolder *folder;
217 1 hiro
218 1 hiro
        g_return_if_fail( book != NULL );
219 1 hiro
220 1 hiro
        addrbook_print_book( book, stream );
221 1 hiro
        folder = book->addressCache->rootFolder;
222 1 hiro
        addritem_print_item_folder( folder, stream );
223 1 hiro
}
224 1 hiro
225 1 hiro
/*
226 1 hiro
* Remove group from address book.
227 1 hiro
* param: group        Group to remove.
228 1 hiro
* return: Group, or NULL if not found. Note that object should still be freed.
229 1 hiro
*/
230 1 hiro
ItemGroup *addrbook_remove_group( AddressBookFile *book, ItemGroup *group ) {
231 1 hiro
        ItemGroup *item;
232 1 hiro
233 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
234 1 hiro
235 1 hiro
        item = addrcache_remove_group( book->addressCache, group );
236 1 hiro
        if( item ) book->dirtyFlag = TRUE;
237 1 hiro
        return item;
238 1 hiro
}
239 1 hiro
240 1 hiro
/*
241 1 hiro
* Remove specified person from address book.
242 1 hiro
* param: person        Person to remove.
243 1 hiro
* return: Person, or NULL if not found. Note that object should still be freed.
244 1 hiro
*/
245 1 hiro
ItemPerson *addrbook_remove_person( AddressBookFile *book, ItemPerson *person ) {
246 1 hiro
        ItemPerson *item;
247 1 hiro
248 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
249 1 hiro
250 1 hiro
        item = addrcache_remove_person( book->addressCache, person );
251 1 hiro
        if( item ) book->dirtyFlag = TRUE;
252 1 hiro
        return item;
253 1 hiro
}
254 1 hiro
255 1 hiro
/*
256 1 hiro
* Remove email address in address book for specified person.
257 1 hiro
* param: person        Person.
258 1 hiro
*        email        EMail to remove.
259 1 hiro
* return: EMail object, or NULL if not found. Note that object should still be freed.
260 1 hiro
*/
261 1 hiro
ItemEMail *addrbook_person_remove_email( AddressBookFile *book, ItemPerson *person, ItemEMail *email ) {
262 1 hiro
        ItemEMail *item;
263 1 hiro
264 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
265 1 hiro
266 1 hiro
        item = addrcache_person_remove_email( book->addressCache, person, email );
267 1541 hiro
        if( item ) book->dirtyFlag = TRUE;
268 1 hiro
        return item;
269 1 hiro
}
270 1 hiro
271 1541 hiro
ItemEMail *addrbook_group_remove_email( AddressBookFile *book, ItemGroup *group, ItemEMail *email ) {
272 1541 hiro
        ItemEMail *item;
273 1541 hiro
274 1541 hiro
        g_return_val_if_fail( book != NULL, NULL );
275 1541 hiro
276 1541 hiro
        item = addritem_group_remove_email( group, email );
277 1541 hiro
        if( item ) book->dirtyFlag = TRUE;
278 1541 hiro
        return item;
279 1541 hiro
}
280 1541 hiro
281 1 hiro
/* **********************************************************************
282 1 hiro
* Read/Write XML data file...
283 1 hiro
* ===========================
284 1 hiro
* Notes:
285 1 hiro
* 1)        The address book is structured as follows:
286 1 hiro
*
287 1 hiro
*                address-book
288 1 hiro
*                        person
289 1 hiro
*                                address-list
290 1 hiro
*                                        address
291 1 hiro
*                                attribute-list
292 1 hiro
*                                        attribute
293 1 hiro
*                        group
294 1 hiro
*                                member-list
295 1 hiro
*                                        member
296 1 hiro
*                        folder
297 1 hiro
*                                item-list
298 1 hiro
*                                        item
299 1 hiro
*
300 1 hiro
* 2)        This sequence of elements was chosen so that the most important
301 1 hiro
*         elements (person and their email addresses) appear first.
302 1 hiro
*
303 1 hiro
* 3)        Groups then appear. When groups are loaded, person's email
304 1 hiro
*        addresses have already been loaded and can be found.
305 1 hiro
*
306 1 hiro
* 4)        Finally folders are loaded. Any forward and backward references
307 1 hiro
*        to folders, groups and persons in the folders are resolved after
308 1 hiro
*        loading.
309 1 hiro
*
310 1 hiro
* ***********************************************************************
311 1 hiro
*/
312 1 hiro
313 1 hiro
/* Element tag names */
314 1 hiro
#define AB_ELTAG_ADDRESS         "address"
315 1 hiro
#define AB_ELTAG_ATTRIBUTE       "attribute"
316 1 hiro
#define AB_ELTAG_ATTRIBUTE_LIST  "attribute-list"
317 1 hiro
#define AB_ELTAG_ADDRESS_LIST    "address-list"
318 1 hiro
#define AB_ELTAG_MEMBER          "member"
319 1 hiro
#define AB_ELTAG_MEMBER_LIST     "member-list"
320 1 hiro
#define AB_ELTAG_ITEM            "item"
321 1 hiro
#define AB_ELTAG_ITEM_LIST       "item-list"
322 1 hiro
#define AB_ELTAG_ADDRESS_BOOK    "address-book"
323 1 hiro
#define AB_ELTAG_PERSON          "person"
324 1 hiro
#define AB_ELTAG_GROUP           "group"
325 1 hiro
#define AB_ELTAG_FOLDER          "folder"
326 1 hiro
327 1 hiro
/* Attribute tag names */
328 1 hiro
#define AB_ATTAG_TYPE            "type"
329 1 hiro
#define AB_ATTAG_UID             "uid"
330 1 hiro
#define AB_ATTAG_NAME            "name"
331 1 hiro
#define AB_ATTAG_REMARKS         "remarks"
332 1 hiro
#define AB_ATTAG_FIRST_NAME      "first-name"
333 1 hiro
#define AB_ATTAG_LAST_NAME       "last-name"
334 1 hiro
#define AB_ATTAG_NICK_NAME       "nick-name"
335 1 hiro
#define AB_ATTAG_COMMON_NAME     "cn"
336 1 hiro
#define AB_ATTAG_ALIAS           "alias"
337 1 hiro
#define AB_ATTAG_EMAIL           "email"
338 1 hiro
#define AB_ATTAG_EID             "eid"
339 1 hiro
#define AB_ATTAG_PID             "pid"
340 1 hiro
341 1 hiro
/* Attribute values */
342 1 hiro
#define AB_ATTAG_VAL_PERSON      "person"
343 1 hiro
#define AB_ATTAG_VAL_GROUP       "group"
344 1 hiro
#define AB_ATTAG_VAL_FOLDER      "folder"
345 1 hiro
346 1 hiro
/*
347 1 hiro
* Parse address item for person.
348 1 hiro
*/
349 1 hiro
static void addrbook_parse_address( AddressBookFile *book, XMLFile *file, ItemPerson *person ) {
350 1 hiro
        GList *attr;
351 1 hiro
        gchar *name, *value;
352 1 hiro
        ItemEMail *email = NULL;
353 1 hiro
354 1 hiro
        attr = xml_get_current_tag_attr(file);
355 1 hiro
        while( attr ) {
356 1 hiro
                name = ((XMLAttr *)attr->data)->name;
357 1 hiro
                value = ((XMLAttr *)attr->data)->value;
358 1 hiro
                if( ! email ) email = addritem_create_item_email();
359 1 hiro
                if( strcmp( name, AB_ATTAG_UID ) == 0 ) {
360 1 hiro
                        ADDRITEM_ID(email) = g_strdup( value );
361 1 hiro
                }
362 1 hiro
                else if( strcmp( name, AB_ATTAG_ALIAS ) == 0 ) {
363 1 hiro
                        ADDRITEM_NAME(email) = g_strdup( value );
364 1 hiro
                }
365 1 hiro
                else if( strcmp( name, AB_ATTAG_EMAIL ) == 0 ) {
366 1 hiro
                        email->address = g_strdup( value );
367 1 hiro
                }
368 1 hiro
                else if( strcmp( name, AB_ATTAG_REMARKS ) == 0 ) {
369 1 hiro
                        email->remarks = g_strdup( value );
370 1 hiro
                }
371 1 hiro
                attr = g_list_next( attr );
372 1 hiro
        }
373 1 hiro
        if( email ) {
374 1 hiro
                if( person ) {
375 1 hiro
                        addrcache_person_add_email( book->addressCache, person, email );
376 1 hiro
                }
377 1 hiro
                else {
378 1 hiro
                        addritem_free_item_email( email );
379 1 hiro
                        email = NULL;
380 1 hiro
                }
381 1 hiro
        }
382 1 hiro
}
383 1 hiro
384 1 hiro
/*
385 1 hiro
* Parse email address list.
386 1 hiro
*/
387 1 hiro
static void addrbook_parse_addr_list( AddressBookFile *book, XMLFile *file, ItemPerson *person ){
388 1 hiro
        GList *attr;
389 1 hiro
        guint prev_level;
390 1 hiro
391 1 hiro
        for (;;) {
392 1 hiro
                prev_level = file->level;
393 1 hiro
                if( xml_parse_next_tag( file ) ) {
394 1 hiro
                        longjmp( book->jumper, 1 );
395 1 hiro
                }
396 1 hiro
                if (file->level < prev_level) return;
397 1 hiro
                if( xml_compare_tag( file, AB_ELTAG_ADDRESS ) ) {
398 1 hiro
                        attr = xml_get_current_tag_attr(file);
399 1 hiro
                        addrbook_parse_address( book, file, person );
400 1 hiro
                        addrbook_parse_addr_list( book, file, person );
401 1 hiro
                }
402 1 hiro
        }
403 1 hiro
}
404 1 hiro
405 1 hiro
/*
406 1 hiro
* Parse attibute for person.
407 1 hiro
*/
408 1 hiro
static void addrbook_parse_attribute( XMLFile *file, ItemPerson *person ) {
409 1 hiro
        GList *attr;
410 1 hiro
        gchar *name, *value;
411 1 hiro
        gchar *element;
412 1 hiro
        UserAttribute *uAttr = NULL;
413 1 hiro
414 1 hiro
        attr = xml_get_current_tag_attr(file);
415 1 hiro
        while( attr ) {
416 1 hiro
                name = ((XMLAttr *)attr->data)->name;
417 1 hiro
                value = ((XMLAttr *)attr->data)->value;
418 1 hiro
                if( ! uAttr ) uAttr = addritem_create_attribute();
419 1 hiro
                if( strcmp( name, AB_ATTAG_UID ) == 0 ) {
420 1 hiro
                        addritem_attrib_set_id( uAttr, value );
421 1 hiro
                }
422 1 hiro
                else if( strcmp( name, AB_ATTAG_NAME ) == 0 ) {
423 1 hiro
                        addritem_attrib_set_name( uAttr, value );
424 1 hiro
                }
425 1 hiro
                attr = g_list_next( attr );
426 1 hiro
        }
427 1 hiro
428 1 hiro
        element = xml_get_element( file );
429 1 hiro
        addritem_attrib_set_value( uAttr, element );
430 1 hiro
431 1 hiro
        if( uAttr ) {
432 1 hiro
                if( person ) {
433 1 hiro
                        addritem_person_add_attribute( person, uAttr );
434 1 hiro
                }
435 1 hiro
                else {
436 1 hiro
                        addritem_free_attribute( uAttr );
437 1 hiro
                        uAttr = NULL;
438 1 hiro
                }
439 1 hiro
        }
440 1 hiro
}
441 1 hiro
442 1 hiro
/*
443 1 hiro
* Parse attribute list.
444 1 hiro
*/
445 1 hiro
static void addrbook_parse_attr_list( AddressBookFile *book, XMLFile *file, ItemPerson *person ){
446 1 hiro
        GList *attr;
447 1 hiro
        guint prev_level;
448 1 hiro
449 1 hiro
        for (;;) {
450 1 hiro
                prev_level = file->level;
451 1 hiro
                if( xml_parse_next_tag( file ) ) {
452 1 hiro
                        longjmp( book->jumper, 1 );
453 1 hiro
                }
454 1 hiro
                if (file->level < prev_level) return;
455 1 hiro
                if( xml_compare_tag( file, AB_ELTAG_ATTRIBUTE ) ) {
456 1 hiro
                        attr = xml_get_current_tag_attr(file);
457 1 hiro
                        addrbook_parse_attribute( file, person );
458 1 hiro
                        addrbook_parse_attr_list( book, file, person );
459 1 hiro
                }
460 1 hiro
        }
461 1 hiro
}
462 1 hiro
463 1 hiro
/*
464 1 hiro
* Parse person.
465 1 hiro
*/
466 1 hiro
static void addrbook_parse_person( AddressBookFile *book, XMLFile *file ) {
467 1 hiro
        GList *attr;
468 1 hiro
        gchar *name, *value;
469 1 hiro
        ItemPerson *person = NULL;
470 1 hiro
471 1 hiro
        attr = xml_get_current_tag_attr(file);
472 1 hiro
        while( attr ) {
473 1 hiro
                name = ((XMLAttr *)attr->data)->name;
474 1 hiro
                value = ((XMLAttr *)attr->data)->value;
475 1 hiro
                if( ! person ) person = addritem_create_item_person();
476 1 hiro
                if( strcmp( name, AB_ATTAG_UID ) == 0 ) {
477 1 hiro
                        ADDRITEM_ID(person) = g_strdup( value );
478 1 hiro
                }
479 1 hiro
                else if( strcmp( name, AB_ATTAG_FIRST_NAME ) == 0 ) {
480 1 hiro
                        person->firstName = g_strdup( value );
481 1 hiro
                }
482 1 hiro
                else if( strcmp( name, AB_ATTAG_LAST_NAME ) == 0 ) {
483 1 hiro
                        person->lastName = g_strdup( value );
484 1 hiro
                }
485 1 hiro
                else if( strcmp( name, AB_ATTAG_NICK_NAME ) == 0 ) {
486 1 hiro
                        person->nickName = g_strdup( value );
487 1 hiro
                }
488 1 hiro
                else if( strcmp( name, AB_ATTAG_COMMON_NAME ) == 0 ) {
489 1 hiro
                        ADDRITEM_NAME(person) = g_strdup( value );
490 1 hiro
                }
491 1 hiro
                attr = g_list_next( attr );
492 1 hiro
        }
493 1 hiro
        if( xml_parse_next_tag( file ) ) {        /* Consume closing tag */
494 1 hiro
                longjmp( book->jumper, 1 );
495 1 hiro
        }
496 1 hiro
        if( xml_compare_tag( file, AB_ELTAG_ADDRESS_LIST ) ) {
497 1 hiro
                addrbook_parse_addr_list( book, file, person );
498 1 hiro
                if( person ) {
499 1 hiro
                        addrcache_hash_add_person( book->addressCache, person );
500 1 hiro
                }
501 1 hiro
        }
502 1 hiro
        if( xml_parse_next_tag( file ) ) {        /* Consume closing tag */
503 1 hiro
                longjmp( book->jumper, 1 );
504 1 hiro
        }
505 1 hiro
        if( xml_compare_tag( file, AB_ELTAG_ATTRIBUTE_LIST ) ) {
506 1 hiro
                addrbook_parse_attr_list( book, file, person );
507 1 hiro
        }
508 1 hiro
}
509 1 hiro
510 1 hiro
/*
511 1 hiro
* Parse group member.
512 1 hiro
*/
513 1 hiro
static void addrbook_parse_member( AddressBookFile *book, XMLFile *file, ItemGroup *group ) {
514 1 hiro
        GList *attr;
515 1 hiro
        gchar *name, *value;
516 1 hiro
        gchar *pid = NULL, *eid = NULL;
517 1 hiro
        ItemEMail *email = NULL;
518 1 hiro
519 1 hiro
        attr = xml_get_current_tag_attr(file);
520 1 hiro
        while( attr ) {
521 1 hiro
                name = ((XMLAttr *)attr->data)->name;
522 1 hiro
                value = ((XMLAttr *)attr->data)->value;
523 1 hiro
                if( strcmp( name, AB_ATTAG_PID ) == 0 ) {
524 1 hiro
                        pid = g_strdup( value );
525 1 hiro
                }
526 1 hiro
                else if( strcmp( name, AB_ATTAG_EID ) == 0 ) {
527 1 hiro
                        eid = g_strdup( value );
528 1 hiro
                }
529 1 hiro
                attr = g_list_next( attr );
530 1 hiro
        }
531 1 hiro
        email = addrcache_get_email( book->addressCache, pid, eid );
532 1 hiro
        if( email ) {
533 1 hiro
                if( group ) {
534 1 hiro
                        addrcache_group_add_email( book->addressCache, group, email );
535 1 hiro
                }
536 1 hiro
                else {
537 1 hiro
                        addritem_free_item_email( email );
538 1 hiro
                        email = NULL;
539 1 hiro
                }
540 1 hiro
        }
541 1 hiro
}
542 1 hiro
543 1 hiro
/*
544 1 hiro
* Parse group member list.
545 1 hiro
*/
546 1 hiro
static void addrbook_parse_member_list( AddressBookFile *book, XMLFile *file, ItemGroup *group ){
547 1 hiro
        GList *attr;
548 1 hiro
        guint prev_level;
549 1 hiro
550 1 hiro
        for (;;) {
551 1 hiro
                prev_level = file->level;
552 1 hiro
                if( xml_parse_next_tag( file ) ) {
553 1 hiro
                        longjmp( book->jumper, 1 );
554 1 hiro
                }
555 1 hiro
                if (file->level < prev_level) return;
556 1 hiro
                if( xml_compare_tag( file, AB_ELTAG_MEMBER ) ) {
557 1 hiro
                        attr = xml_get_current_tag_attr(file);
558 1 hiro
                        addrbook_parse_member( book, file, group );
559 1 hiro
                        addrbook_parse_member_list( book, file, group );
560 1 hiro
                }
561 1 hiro
                else {
562 1 hiro
                        attr = xml_get_current_tag_attr( file );
563 1 hiro
                }
564 1 hiro
        }
565 1 hiro
}
566 1 hiro
567 1 hiro
/*
568 1 hiro
* Parse group.
569 1 hiro
*/
570 1 hiro
static void addrbook_parse_group( AddressBookFile *book, XMLFile *file ) {
571 1 hiro
        GList *attr;
572 1 hiro
        gchar *name, *value;
573 1 hiro
        ItemGroup *group = NULL;
574 1 hiro
575 1 hiro
        attr = xml_get_current_tag_attr(file);
576 1 hiro
        while( attr ) {
577 1 hiro
                name = ((XMLAttr *)attr->data)->name;
578 1 hiro
                value = ((XMLAttr *)attr->data)->value;
579 1 hiro
                if( ! group ) group = addritem_create_item_group();
580 1 hiro
                if( strcmp( name, AB_ATTAG_UID ) == 0 ) {
581 1 hiro
                        ADDRITEM_ID(group) = g_strdup( value );
582 1 hiro
                }
583 1 hiro
                else if( strcmp( name, AB_ATTAG_NAME ) == 0 ) {
584 1 hiro
                        ADDRITEM_NAME(group) = g_strdup( value );
585 1 hiro
                }
586 1 hiro
                else if( strcmp( name, AB_ATTAG_REMARKS ) == 0 ) {
587 1 hiro
                        group->remarks = g_strdup( value );
588 1 hiro
                }
589 1 hiro
                attr = g_list_next( attr );
590 1 hiro
        }
591 1 hiro
        if( xml_parse_next_tag( file ) ) {        /* Consume closing tag */
592 1 hiro
                longjmp( book->jumper, 1 );
593 1 hiro
        }
594 1 hiro
        if( xml_compare_tag( file, AB_ELTAG_MEMBER_LIST ) ) {
595 1 hiro
                if( group ) {
596 1 hiro
                        addrcache_hash_add_group( book->addressCache, group );
597 1 hiro
                }
598 1 hiro
                addrbook_parse_member_list( book, file, group );
599 1 hiro
        }
600 1 hiro
}
601 1 hiro
602 1 hiro
/*
603 1 hiro
* Parse folder item.
604 1 hiro
*/
605 1 hiro
static void addrbook_parse_folder_item( AddressBookFile *book, XMLFile *file, ItemFolder *folder ) {
606 1 hiro
        GList *attr;
607 1 hiro
        gchar *name, *value;
608 1 hiro
        gchar *uid = NULL;
609 1 hiro
610 1 hiro
        attr = xml_get_current_tag_attr(file);
611 1 hiro
        while( attr ) {
612 1 hiro
                name = ((XMLAttr *)attr->data)->name;
613 1 hiro
                value = ((XMLAttr *)attr->data)->value;
614 1 hiro
                if( strcmp( name, AB_ATTAG_UID ) == 0 ) {
615 1 hiro
                        uid = g_strdup( value );
616 1 hiro
                }
617 1 hiro
                attr = g_list_next( attr );
618 1 hiro
        }
619 1 hiro
        if( folder ) {
620 1 hiro
                if( uid ) {
621 1 hiro
                        folder->listItems = g_list_append( folder->listItems, uid );
622 1 hiro
                }
623 1 hiro
        }
624 1 hiro
}
625 1 hiro
626 1 hiro
/*
627 1 hiro
* Parse folder item list.
628 1 hiro
*/
629 1 hiro
static void addrbook_parse_folder_list( AddressBookFile *book, XMLFile *file, ItemFolder *folder ){
630 1 hiro
        GList *attr;
631 1 hiro
        guint prev_level;
632 1 hiro
633 1 hiro
        for (;;) {
634 1 hiro
                prev_level = file->level;
635 1 hiro
                if( xml_parse_next_tag( file ) ) {
636 1 hiro
                        longjmp( book->jumper, 1 );
637 1 hiro
                }
638 1 hiro
                if (file->level < prev_level) return;
639 1 hiro
                if( xml_compare_tag( file, AB_ELTAG_ITEM ) ) {
640 1 hiro
                        attr = xml_get_current_tag_attr(file);
641 1 hiro
                        addrbook_parse_folder_item( book, file, folder );
642 1 hiro
                        addrbook_parse_folder_list( book, file, folder );
643 1 hiro
                }
644 1 hiro
                else {
645 1 hiro
                        attr = xml_get_current_tag_attr( file );
646 1 hiro
                }
647 1 hiro
        }
648 1 hiro
}
649 1 hiro
650 1 hiro
/*
651 1 hiro
* Parse folder.
652 1 hiro
*/
653 1 hiro
static void addrbook_parse_folder( AddressBookFile *book, XMLFile *file ) {
654 1 hiro
        GList *attr;
655 1 hiro
        gchar *name, *value;
656 1 hiro
        ItemFolder *folder = NULL;
657 1 hiro
658 1 hiro
        attr = xml_get_current_tag_attr(file);
659 1 hiro
        while( attr ) {
660 1 hiro
                name = ((XMLAttr *)attr->data)->name;
661 1 hiro
                value = ((XMLAttr *)attr->data)->value;
662 1 hiro
                if( ! folder ) {
663 1 hiro
                        folder = addritem_create_item_folder();
664 1 hiro
                }
665 1 hiro
                if( strcmp( name, AB_ATTAG_UID ) == 0 ) {
666 1 hiro
                        ADDRITEM_ID(folder) = g_strdup( value );
667 1 hiro
                }
668 1 hiro
                else if( strcmp( name, AB_ATTAG_NAME ) == 0 ) {
669 1 hiro
                        ADDRITEM_NAME(folder) = g_strdup( value );
670 1 hiro
                }
671 1 hiro
                else if( strcmp( name, AB_ATTAG_REMARKS ) == 0 ) {
672 1 hiro
                        folder->remarks = g_strdup( value );
673 1 hiro
                }
674 1 hiro
                attr = g_list_next( attr );
675 1 hiro
        }
676 1 hiro
        if( xml_parse_next_tag( file ) ) {        /* Consume closing tag */
677 1 hiro
                longjmp( book->jumper, 1 );
678 1 hiro
        }
679 1 hiro
        if( xml_compare_tag( file, AB_ELTAG_ITEM_LIST ) ) {
680 1 hiro
                if( folder ) {
681 1 hiro
                        if( addrcache_hash_add_folder( book->addressCache, folder ) ) {
682 1 hiro
                                book->tempList = g_list_append( book->tempList, folder );
683 1 hiro
                                ADDRITEM_PARENT(folder) = NULL;        /* We will resolve folder later */
684 1 hiro
                        }
685 1 hiro
                }
686 1 hiro
                addrbook_parse_folder_list( book, file, folder );
687 1 hiro
        }
688 1 hiro
}
689 1 hiro
690 1 hiro
/*
691 1 hiro
* Parse address book.
692 1 hiro
* Return: TRUE if data read successfully, FALSE if error reading data.
693 1 hiro
*/
694 1 hiro
static gboolean addrbook_read_tree( AddressBookFile *book, XMLFile *file ) {
695 1 hiro
        gboolean retVal;
696 1 hiro
        GList *attr;
697 1 hiro
        gchar *name, *value;
698 1 hiro
699 1 hiro
        book->retVal = MGU_BAD_FORMAT;
700 1 hiro
        if( xml_get_dtd( file ) ) {
701 1 hiro
                return FALSE;
702 1 hiro
        }
703 1 hiro
        if( xml_parse_next_tag( file ) ) {
704 1 hiro
                longjmp( book->jumper, 1 );
705 1 hiro
        }
706 1 hiro
        if( ! xml_compare_tag( file, AB_ELTAG_ADDRESS_BOOK ) ) {
707 1 hiro
                return FALSE;
708 1 hiro
        }
709 1 hiro
710 1 hiro
        attr = xml_get_current_tag_attr(file);
711 1 hiro
        while( attr ) {
712 1 hiro
                name = ((XMLAttr *)attr->data)->name;
713 1 hiro
                value = ((XMLAttr *)attr->data)->value;
714 1 hiro
                if( strcmp( name, AB_ATTAG_NAME ) == 0 ) {
715 1 hiro
                        addrbook_set_name( book, value );
716 1 hiro
                }
717 1 hiro
                attr = g_list_next( attr );
718 1 hiro
        }
719 1 hiro
720 1 hiro
        retVal = TRUE;
721 1 hiro
        for (;;) {
722 1 hiro
                if (! file->level ) break;
723 1 hiro
                /* Get next item tag (person, group or folder) */
724 1 hiro
                if( xml_parse_next_tag( file ) ) {
725 1 hiro
                        longjmp( book->jumper, 1 );
726 1 hiro
                }
727 1 hiro
                if( xml_compare_tag( file, AB_ELTAG_PERSON ) ) {
728 1 hiro
                        addrbook_parse_person( book, file );
729 1 hiro
                }
730 1 hiro
                else if( xml_compare_tag( file, AB_ELTAG_GROUP ) ) {
731 1 hiro
                        addrbook_parse_group( book, file );
732 1 hiro
                }
733 1 hiro
                else if( xml_compare_tag( file, AB_ELTAG_FOLDER ) ) {
734 1 hiro
                        addrbook_parse_folder( book, file );
735 1 hiro
                }
736 1 hiro
        }
737 1 hiro
        if( retVal ) book->retVal = MGU_SUCCESS;
738 1 hiro
        return retVal;
739 1 hiro
}
740 1 hiro
741 1 hiro
/*
742 1 hiro
* Resolve folder items visitor function.
743 1 hiro
*/
744 1 hiro
static void addrbook_res_items_vis( gpointer key, gpointer value, gpointer data ) {
745 1 hiro
        AddressBookFile *book = data;
746 1 hiro
        AddrItemObject *obj = ( AddrItemObject * ) value;
747 1 hiro
        ItemFolder *rootFolder = book->addressCache->rootFolder;
748 1 hiro
        if( obj->parent == NULL ) {
749 1 hiro
                if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
750 1 hiro
                        rootFolder->listPerson = g_list_append( rootFolder->listPerson, obj );
751 1 hiro
                        ADDRITEM_PARENT(obj) = ADDRITEM_OBJECT(rootFolder);
752 1 hiro
                }
753 1 hiro
                else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
754 1 hiro
                        rootFolder->listGroup = g_list_append( rootFolder->listGroup, obj );
755 1 hiro
                        ADDRITEM_PARENT(obj) = ADDRITEM_OBJECT(rootFolder);
756 1 hiro
                }
757 1 hiro
        }
758 1 hiro
}
759 1 hiro
760 1 hiro
/*
761 1 hiro
* Resolve folder items. Lists of UID's are replaced with pointers to data items.
762 1 hiro
*/
763 1 hiro
static void addrbook_resolve_folder_items( AddressBookFile *book ) {
764 1 hiro
        GList *nodeFolder = NULL;
765 1 hiro
        GList *listRemove = NULL;
766 1 hiro
        GList *node = NULL;
767 1 hiro
        ItemFolder *rootFolder = book->addressCache->rootFolder;
768 1 hiro
        nodeFolder = book->tempList;
769 1 hiro
        while( nodeFolder ) {
770 1 hiro
                ItemFolder *folder = nodeFolder->data;
771 1 hiro
                listRemove = NULL;
772 1 hiro
                node = folder->listItems;
773 1 hiro
                while( node ) {
774 1 hiro
                        gchar *uid = node->data;
775 1 hiro
                        AddrItemObject *aio = addrcache_get_object( book->addressCache, uid );
776 1 hiro
                        if( aio ) {
777 1 hiro
                                if( aio->type == ITEMTYPE_FOLDER ) {
778 1 hiro
                                        ItemFolder *item = ( ItemFolder * ) aio;
779 1 hiro
                                        folder->listFolder = g_list_append( folder->listFolder, item );
780 1 hiro
                                        ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder);
781 1 hiro
                                        addrcache_hash_add_folder( book->addressCache, folder );
782 1 hiro
                                }
783 1 hiro
                                else if( aio->type == ITEMTYPE_PERSON ) {
784 1 hiro
                                        ItemPerson *item = ( ItemPerson * ) aio;
785 1 hiro
                                        folder->listPerson = g_list_append( folder->listPerson, item );
786 1 hiro
                                        ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder);
787 1 hiro
                                }
788 1 hiro
                                else if( aio->type == ITEMTYPE_GROUP ) {
789 1 hiro
                                        ItemGroup *item = ( ItemGroup * ) aio;
790 1 hiro
                                        folder->listGroup = g_list_append( folder->listGroup, item );
791 1 hiro
                                        ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder);
792 1 hiro
                                }
793 1 hiro
                                /* Replace data with pointer to item */
794 1 hiro
                                g_free( uid );
795 1 hiro
                                node->data = aio;
796 1 hiro
                        }
797 1 hiro
                        else {
798 1 hiro
                                /* Not found, append to remove list. */
799 1 hiro
                                listRemove = g_list_append( listRemove, uid );
800 1 hiro
                        }
801 1 hiro
                        node = g_list_next( node );
802 1 hiro
                }
803 1 hiro
                rootFolder->listFolder = g_list_append( rootFolder->listFolder, folder );
804 1 hiro
805 1 hiro
                /* Process remove list */
806 1 hiro
                node = listRemove;
807 1 hiro
                while( node ) {
808 1 hiro
                        gchar *uid = node->data;
809 1 hiro
                        folder->listItems = g_list_remove( folder->listItems, uid );
810 1 hiro
                        g_free( uid );
811 1 hiro
                        node = g_list_next( node );
812 1 hiro
                }
813 1 hiro
                g_list_free( listRemove );
814 1 hiro
                nodeFolder = g_list_next( nodeFolder );
815 1 hiro
        }
816 1 hiro
817 1 hiro
        /* Remove folders with parents. */
818 1 hiro
        listRemove = NULL;
819 1 hiro
        node = rootFolder->listFolder;
820 1 hiro
        while( node ) {
821 1 hiro
                ItemFolder *folder = ( ItemFolder * ) node->data;
822 1 hiro
                if( ADDRITEM_PARENT(folder) ) {
823 1 hiro
                        /* Remove folders with parents */
824 1 hiro
                        listRemove = g_list_append( listRemove, folder );
825 1 hiro
                }
826 1 hiro
                else {
827 1 hiro
                        /* Add to root folder */
828 1 hiro
                        ADDRITEM_PARENT(folder) = ADDRITEM_OBJECT(book->addressCache->rootFolder);
829 1 hiro
                }
830 1 hiro
                node = g_list_next( node );
831 1 hiro
        }
832 1 hiro
833 1 hiro
        /* Process remove list */
834 1 hiro
        node = listRemove;
835 1 hiro
        while( node ) {
836 1 hiro
                rootFolder->listFolder = g_list_remove( rootFolder->listFolder, node->data );
837 1 hiro
                node = g_list_next( node );
838 1 hiro
        }
839 1 hiro
        g_list_free( listRemove );
840 1 hiro
841 1 hiro
        /* Move all unparented persons and groups into root folder */
842 1 hiro
        g_hash_table_foreach( book->addressCache->itemHash, addrbook_res_items_vis, book );
843 1 hiro
844 1 hiro
        /* Free up some more */
845 1 hiro
        nodeFolder = book->tempList;
846 1 hiro
        while( nodeFolder ) {
847 1 hiro
                ItemFolder *folder = nodeFolder->data;
848 1 hiro
                g_list_free( folder->listItems );
849 1 hiro
                folder->listItems = NULL;
850 1 hiro
                nodeFolder = g_list_next( nodeFolder );
851 1 hiro
        }
852 1 hiro
        g_list_free( book->tempList );
853 1 hiro
        book->tempList = NULL;
854 1 hiro
855 1 hiro
}
856 1 hiro
857 1 hiro
/*
858 1 hiro
* Read address book file.
859 1 hiro
*/
860 1 hiro
gint addrbook_read_data( AddressBookFile *book ) {
861 1 hiro
        XMLFile *file = NULL;
862 1 hiro
        gchar *fileSpec = NULL;
863 1 hiro
864 1 hiro
        g_return_val_if_fail( book != NULL, -1 );
865 1 hiro
866 1 hiro
        fileSpec = g_strconcat( book->path, G_DIR_SEPARATOR_S, book->fileName, NULL );
867 1 hiro
        book->retVal = MGU_OPEN_FILE;
868 1 hiro
        book->accessFlag = FALSE;
869 1 hiro
        book->modifyFlag = FALSE;
870 1 hiro
        file = xml_open_file( fileSpec );
871 1 hiro
        g_free( fileSpec );
872 1 hiro
        if( file ) {
873 1 hiro
                book->tempList = NULL;
874 1 hiro
875 1 hiro
                /* Trap for parsing errors. */
876 1 hiro
                if( setjmp( book->jumper ) ) {
877 1 hiro
                        xml_close_file( file );
878 1 hiro
                        return book->retVal;
879 1 hiro
                }
880 1 hiro
                addrbook_read_tree( book, file );
881 1 hiro
                xml_close_file( file );
882 1 hiro
883 1 hiro
                /* Resolve folder items */
884 1 hiro
                addrbook_resolve_folder_items( book );
885 1 hiro
                book->tempList = NULL;
886 1 hiro
                book->readFlag = TRUE;
887 1 hiro
                book->dirtyFlag = FALSE;
888 1 hiro
        }
889 1 hiro
        return book->retVal;
890 1 hiro
}
891 1 hiro
892 1 hiro
static void addrbook_write_elem_s( FILE *fp, gint lvl, gchar *name ) {
893 1 hiro
        gint i;
894 1 hiro
        for( i = 0; i < lvl; i++ ) fputs( "  ", fp );
895 1 hiro
        fputs( "<", fp );
896 1 hiro
        fputs( name, fp );
897 1 hiro
}
898 1 hiro
899 1 hiro
static void addrbook_write_elem_e( FILE *fp, gint lvl, gchar *name ) {
900 1 hiro
        gint i;
901 1 hiro
        for( i = 0; i < lvl; i++ ) fputs( "  ", fp );
902 1 hiro
        fputs( "</", fp );
903 1 hiro
        fputs( name, fp );
904 1 hiro
        fputs( ">\n", fp );
905 1 hiro
}
906 1 hiro
907 1 hiro
static void addrbook_write_attr( FILE *fp, gchar *name, gchar *value ) {
908 1 hiro
        fputs( " ", fp );
909 1 hiro
        fputs( name, fp );
910 1 hiro
        fputs( "=\"", fp );
911 1 hiro
        xml_file_put_escape_str( fp, value );
912 1 hiro
        fputs( "\"", fp );
913 1 hiro
}
914 1 hiro
915 1 hiro
/*
916 1 hiro
* Write file hash table visitor function.
917 1 hiro
*/
918 1 hiro
static void addrbook_write_item_person_vis( gpointer key, gpointer value, gpointer data ) {
919 1 hiro
        AddrItemObject *obj = ( AddrItemObject * ) value;
920 1 hiro
        FILE *fp = ( FILE * ) data;
921 1 hiro
        GList *node;
922 1 hiro
923 1 hiro
        if( ! obj ) return;
924 1 hiro
        if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
925 1 hiro
                ItemPerson *person = ( ItemPerson * ) value;
926 1 hiro
                if( person ) {
927 1 hiro
                        addrbook_write_elem_s( fp, 1, AB_ELTAG_PERSON );
928 1 hiro
                        addrbook_write_attr( fp, AB_ATTAG_UID, ADDRITEM_ID(person) );
929 1 hiro
                        addrbook_write_attr( fp, AB_ATTAG_FIRST_NAME, person->firstName );
930 1 hiro
                        addrbook_write_attr( fp, AB_ATTAG_LAST_NAME, person->lastName );
931 1 hiro
                        addrbook_write_attr( fp, AB_ATTAG_NICK_NAME, person->nickName );
932 1 hiro
                        addrbook_write_attr( fp, AB_ATTAG_COMMON_NAME, ADDRITEM_NAME(person) );
933 1 hiro
                        fputs( " >\n", fp);
934 1 hiro
935 1 hiro
                        /* Output email addresses */
936 1 hiro
                        addrbook_write_elem_s( fp, 2, AB_ELTAG_ADDRESS_LIST );
937 1 hiro
                        fputs( ">\n", fp );
938 1 hiro
                        node = person->listEMail;
939 1 hiro
                        while ( node ) {
940 1 hiro
                                ItemEMail *email = node->data;
941 1 hiro
                                addrbook_write_elem_s( fp, 3, AB_ELTAG_ADDRESS );
942 1 hiro
                                addrbook_write_attr( fp, AB_ATTAG_UID, ADDRITEM_ID(email) );
943 1 hiro
                                addrbook_write_attr( fp, AB_ATTAG_ALIAS, ADDRITEM_NAME(email) );
944 1 hiro
                                addrbook_write_attr( fp, AB_ATTAG_EMAIL, email->address );
945 1 hiro
                                addrbook_write_attr( fp, AB_ATTAG_REMARKS, email->remarks );
946 1 hiro
                                fputs( " />\n", fp);
947 1 hiro
                                node = g_list_next( node );
948 1 hiro
                        }
949 1 hiro
                        addrbook_write_elem_e( fp, 2, AB_ELTAG_ADDRESS_LIST );
950 1 hiro
951 1 hiro
                        /* Output user attributes */
952 1 hiro
                        addrbook_write_elem_s( fp, 2, AB_ELTAG_ATTRIBUTE_LIST );
953 1 hiro
                        fputs( ">\n", fp );
954 1 hiro
                        node = person->listAttrib;
955 1 hiro
                        while ( node ) {
956 1 hiro
                                UserAttribute *attrib = node->data;
957 1 hiro
                                addrbook_write_elem_s( fp, 3, AB_ELTAG_ATTRIBUTE );
958 1 hiro
                                addrbook_write_attr( fp, AB_ATTAG_UID, attrib->uid );
959 1 hiro
                                addrbook_write_attr( fp, AB_ATTAG_NAME, attrib->name );
960 1 hiro
                                fputs( " >", fp);
961 1 hiro
                                xml_file_put_escape_str( fp, attrib->value );
962 1 hiro
                                addrbook_write_elem_e( fp, 0, AB_ELTAG_ATTRIBUTE );
963 1 hiro
                                node = g_list_next( node );
964 1 hiro
                        }
965 1 hiro
                        addrbook_write_elem_e( fp, 2, AB_ELTAG_ATTRIBUTE_LIST );
966 1 hiro
                        addrbook_write_elem_e( fp, 1, AB_ELTAG_PERSON );
967 1 hiro
                }
968 1 hiro
        }
969 1 hiro
}
970 1 hiro
971 1 hiro
/*
972 1 hiro
* Write file hash table visitor function.
973 1 hiro
*/
974 1 hiro
static void addrbook_write_item_group_vis( gpointer key, gpointer value, gpointer data ) {
975 1 hiro
        AddrItemObject *obj = ( AddrItemObject * ) value;
976 1 hiro
        FILE *fp = ( FILE * ) data;
977 1 hiro
        GList *node;
978 1 hiro
979 1 hiro
        if( ! obj ) return;
980 1 hiro
        if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
981 1 hiro
                ItemGroup *group = ( ItemGroup * ) value;
982 1 hiro
                if( group ) {
983 1 hiro
                        addrbook_write_elem_s( fp, 1, AB_ELTAG_GROUP );
984 1 hiro
                        addrbook_write_attr( fp, AB_ATTAG_UID, ADDRITEM_ID(group) );
985 1 hiro
                        addrbook_write_attr( fp, AB_ATTAG_NAME, ADDRITEM_NAME(group) );
986 1 hiro
                        addrbook_write_attr( fp, AB_ATTAG_REMARKS, group->remarks );
987 1 hiro
                        fputs( " >\n", fp );
988 1 hiro
989 1 hiro
                        /* Output email address links */
990 1 hiro
                        addrbook_write_elem_s( fp, 2, AB_ELTAG_MEMBER_LIST );
991 1 hiro
                        fputs( ">\n", fp );
992 1 hiro
                        node = group->listEMail;
993 1 hiro
                        while ( node ) {
994 1 hiro
                                ItemEMail *email = node->data;
995 1 hiro
                                ItemPerson *person = ( ItemPerson * ) ADDRITEM_PARENT(email);
996 1 hiro
                                addrbook_write_elem_s( fp, 3, AB_ELTAG_MEMBER );
997 1 hiro
                                addrbook_write_attr( fp, AB_ATTAG_PID, ADDRITEM_ID(person) );
998 1 hiro
                                addrbook_write_attr( fp, AB_ATTAG_EID, ADDRITEM_ID(email) );
999 1 hiro
                                fputs( " />\n", fp );
1000 1 hiro
                                node = g_list_next( node );
1001 1 hiro
                        }
1002 1 hiro
                        addrbook_write_elem_e( fp, 2, AB_ELTAG_MEMBER_LIST );
1003 1 hiro
                        addrbook_write_elem_e( fp, 1, AB_ELTAG_GROUP );
1004 1 hiro
                }
1005 1 hiro
        }
1006 1 hiro
}
1007 1 hiro
1008 1 hiro
/*
1009 1 hiro
* Write file hash table visitor function.
1010 1 hiro
*/
1011 1 hiro
static void addrbook_write_item_folder_vis( gpointer key, gpointer value, gpointer data ) {
1012 1 hiro
        AddrItemObject *obj = ( AddrItemObject * ) value;
1013 1 hiro
        FILE *fp = ( FILE * ) data;
1014 1 hiro
        GList *node;
1015 1 hiro
1016 1 hiro
        if( ! obj ) return;
1017 1 hiro
        if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
1018 1 hiro
                ItemFolder *folder = ( ItemFolder * ) value;
1019 1 hiro
                if( folder ) {
1020 1 hiro
                        addrbook_write_elem_s( fp, 1, AB_ELTAG_FOLDER );
1021 1 hiro
                        addrbook_write_attr( fp, AB_ATTAG_UID, ADDRITEM_ID(folder) );
1022 1 hiro
                        addrbook_write_attr( fp, AB_ATTAG_NAME, ADDRITEM_NAME(folder) );
1023 1 hiro
                        addrbook_write_attr( fp, AB_ATTAG_REMARKS, folder->remarks );
1024 1 hiro
                        fputs( " >\n", fp );
1025 1 hiro
                        addrbook_write_elem_s( fp, 2, AB_ELTAG_ITEM_LIST );
1026 1 hiro
                        fputs( ">\n", fp );
1027 1 hiro
1028 1 hiro
                        /* Output persons */
1029 1 hiro
                        node = folder->listPerson;
1030 1 hiro
                        while ( node ) {
1031 1 hiro
                                ItemPerson *item = node->data;
1032 1 hiro
                                addrbook_write_elem_s( fp, 3, AB_ELTAG_ITEM );
1033 1 hiro
                                addrbook_write_attr( fp, AB_ATTAG_TYPE,  AB_ATTAG_VAL_PERSON );
1034 1 hiro
                                addrbook_write_attr( fp, AB_ATTAG_UID, ADDRITEM_ID(item ) );
1035 1 hiro
                                fputs( " />\n", fp );
1036 1 hiro
                                node = g_list_next( node );
1037 1 hiro
                        }
1038 1 hiro
1039 1 hiro
                        /* Output groups */
1040 1 hiro
                        node = folder->listGroup;
1041 1 hiro
                        while ( node ) {
1042 1 hiro
                                ItemGroup *item = node->data;
1043 1 hiro
                                addrbook_write_elem_s( fp, 3, AB_ELTAG_ITEM );
1044 1 hiro
                                addrbook_write_attr( fp, AB_ATTAG_TYPE, AB_ATTAG_VAL_GROUP );
1045 1 hiro
                                addrbook_write_attr( fp, AB_ATTAG_UID, ADDRITEM_ID(item ) );
1046 1 hiro
                                fputs( " />\n", fp );
1047 1 hiro
                                node = g_list_next( node );
1048 1 hiro
                        }
1049 1 hiro
1050 1 hiro
                        /* Output folders */
1051 1 hiro
                        node = folder->listFolder;
1052 1 hiro
                        while ( node ) {
1053 1 hiro
                                ItemFolder *item = node->data;
1054 1 hiro
                                addrbook_write_elem_s( fp, 3, AB_ELTAG_ITEM );
1055 1 hiro
                                addrbook_write_attr( fp, AB_ATTAG_TYPE, AB_ATTAG_VAL_FOLDER );
1056 1 hiro
                                addrbook_write_attr( fp, AB_ATTAG_UID, ADDRITEM_ID(item ) );
1057 1 hiro
                                fputs( " />\n", fp );
1058 1 hiro
                                node = g_list_next( node );
1059 1 hiro
                        }
1060 1 hiro
                        addrbook_write_elem_e( fp, 2, AB_ELTAG_ITEM_LIST );
1061 1 hiro
                        addrbook_write_elem_e( fp, 1, AB_ELTAG_FOLDER );
1062 1 hiro
                }
1063 1 hiro
        }
1064 1 hiro
}
1065 1 hiro
1066 1 hiro
/*
1067 1 hiro
* Output address book data to specified file.
1068 1 hiro
* return: Status code.
1069 1 hiro
*/
1070 1 hiro
gint addrbook_write_to( AddressBookFile *book, gchar *newFile ) {
1071 1 hiro
        FILE *fp;
1072 1 hiro
        gchar *fileSpec;
1073 1 hiro
#ifndef DEV_STANDALONE
1074 1 hiro
        PrefFile *pfile;
1075 1 hiro
#endif
1076 1 hiro
1077 1 hiro
        g_return_val_if_fail( book != NULL, -1 );
1078 1 hiro
        g_return_val_if_fail( newFile != NULL, -1 );
1079 1 hiro
1080 1 hiro
        fileSpec = g_strconcat( book->path, G_DIR_SEPARATOR_S, newFile, NULL );
1081 1 hiro
1082 1 hiro
        book->retVal = MGU_OPEN_FILE;
1083 1 hiro
#ifdef DEV_STANDALONE
1084 478 hiro
        fp = g_fopen( fileSpec, "wb" );
1085 1 hiro
        g_free( fileSpec );
1086 1 hiro
        if( fp ) {
1087 1 hiro
                fputs( "<?xml version=\"1.0\" ?>\n", fp );
1088 1 hiro
#else
1089 1 hiro
        pfile = prefs_file_open( fileSpec );
1090 1 hiro
        g_free( fileSpec );
1091 1 hiro
        if( pfile ) {
1092 1 hiro
                fp = pfile->fp;
1093 41 hiro
                fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n", CS_INTERNAL );
1094 1 hiro
#endif
1095 1 hiro
                addrbook_write_elem_s( fp, 0, AB_ELTAG_ADDRESS_BOOK );
1096 1 hiro
                addrbook_write_attr( fp, AB_ATTAG_NAME, book->name );
1097 1 hiro
                fputs( " >\n", fp );
1098 1 hiro
1099 1 hiro
                /* Output all persons */
1100 1 hiro
                g_hash_table_foreach( book->addressCache->itemHash, addrbook_write_item_person_vis, fp );
1101 1 hiro
1102 1 hiro
                /* Output all groups */
1103 1 hiro
                g_hash_table_foreach( book->addressCache->itemHash, addrbook_write_item_group_vis, fp );
1104 1 hiro
1105 1 hiro
                /* Output all folders */
1106 1 hiro
                g_hash_table_foreach( book->addressCache->itemHash, addrbook_write_item_folder_vis, fp );
1107 1 hiro
1108 1 hiro
                addrbook_write_elem_e( fp, 0, AB_ELTAG_ADDRESS_BOOK );
1109 1 hiro
                book->retVal = MGU_SUCCESS;
1110 1 hiro
#ifdef DEV_STANDALONE
1111 1 hiro
                fclose( fp );
1112 1 hiro
#else
1113 1 hiro
                if( prefs_file_close( pfile ) < 0 ) {
1114 1 hiro
                        book->retVal = MGU_ERROR_WRITE;
1115 1 hiro
                }
1116 1 hiro
#endif
1117 1 hiro
        }
1118 1 hiro
1119 1 hiro
        fileSpec = NULL;
1120 1 hiro
        return book->retVal;
1121 1 hiro
}
1122 1 hiro
1123 1 hiro
/*
1124 1 hiro
* Output address book data to original file.
1125 1 hiro
* return: Status code.
1126 1 hiro
*/
1127 1 hiro
gint addrbook_save_data( AddressBookFile *book ) {
1128 1 hiro
        g_return_val_if_fail( book != NULL, -1 );
1129 1 hiro
1130 1 hiro
        book->retVal = MGU_NO_FILE;
1131 1 hiro
        if( book->fileName == NULL || *book->fileName == '\0' ) return book->retVal;
1132 1 hiro
        if( book->path == NULL || *book->path == '\0' ) return book->retVal;
1133 1 hiro
1134 1 hiro
        addrbook_write_to( book, book->fileName );
1135 1 hiro
        if( book->retVal == MGU_SUCCESS ) {
1136 1 hiro
                book->dirtyFlag = FALSE;
1137 1 hiro
        }
1138 1 hiro
        return book->retVal;
1139 1 hiro
}
1140 1 hiro
1141 1 hiro
/* **********************************************************************
1142 1 hiro
* Address book edit interface functions...
1143 1 hiro
* ***********************************************************************
1144 1 hiro
*/
1145 1 hiro
1146 1 hiro
/*
1147 1 hiro
* Move person's email item.
1148 1 hiro
* param: book       Address book.
1149 1 hiro
*        person     Person.
1150 1 hiro
*        itemMove   Item to move.
1151 1 hiro
*        itemTarget Target item before which to move item.
1152 1 hiro
*/
1153 1 hiro
ItemEMail *addrbook_move_email_before( AddressBookFile *book, ItemPerson *person,
1154 1 hiro
                        ItemEMail *itemMove, ItemEMail *itemTarget )
1155 1 hiro
{
1156 1 hiro
        ItemEMail *email = NULL;
1157 1 hiro
1158 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
1159 1 hiro
1160 1 hiro
        email = addritem_move_email_before( person, itemMove, itemTarget );
1161 1 hiro
        if( email ) {
1162 1 hiro
                book->dirtyFlag = TRUE;
1163 1 hiro
        }
1164 1 hiro
        return email;
1165 1 hiro
}
1166 1 hiro
1167 1 hiro
/*
1168 1 hiro
* Move person's email item.
1169 1 hiro
* param: book       Address book.
1170 1 hiro
*        person     Person.
1171 1 hiro
*        itemMove   Item to move.
1172 1 hiro
*        itemTarget Target item after which to move item.
1173 1 hiro
*/
1174 1 hiro
ItemEMail *addrbook_move_email_after( AddressBookFile *book, ItemPerson *person,
1175 1 hiro
                        ItemEMail *itemMove, ItemEMail *itemTarget )
1176 1 hiro
{
1177 1 hiro
        ItemEMail *email = NULL;
1178 1 hiro
1179 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
1180 1 hiro
1181 1 hiro
        email = addritem_move_email_after( person, itemMove, itemTarget );
1182 1 hiro
        if( email ) {
1183 1 hiro
                book->dirtyFlag = TRUE;
1184 1 hiro
        }
1185 1 hiro
        return email;
1186 1 hiro
}
1187 1 hiro
1188 1 hiro
/*
1189 1 hiro
* Hash table visitor function.
1190 1 hiro
*/
1191 1 hiro
static gboolean addrbook_free_simple_hash_vis( gpointer *key, gpointer *value, gpointer *data ) {
1192 1 hiro
        g_free( key );
1193 1 hiro
        key = NULL;
1194 1 hiro
        value = NULL;
1195 1 hiro
        return TRUE;
1196 1 hiro
}
1197 1 hiro
1198 1 hiro
/*
1199 1 hiro
* Update address book email list for specified person.
1200 1 hiro
* Enter: book      Address book.
1201 1 hiro
*        person    Person to update.
1202 1 hiro
*        listEMail New list of email addresses.
1203 1 hiro
* Note: The existing email addresses are replaced with the new addresses. Any references
1204 1 hiro
* to old addresses in the groups are re-linked to the new addresses. All old addresses
1205 1 hiro
* linked to the person are removed.
1206 1 hiro
*/
1207 1 hiro
void addrbook_update_address_list( AddressBookFile *book, ItemPerson *person, GList *listEMail ) {
1208 1 hiro
        GList *node;
1209 1 hiro
        GList *oldData;
1210 1 hiro
        GList *listGroup;
1211 1 hiro
1212 1 hiro
        g_return_if_fail( book != NULL );
1213 1 hiro
        g_return_if_fail( person != NULL );
1214 1 hiro
1215 1 hiro
        /* Remember old list */
1216 1 hiro
        oldData = person->listEMail;
1217 1 hiro
1218 1 hiro
        /* Attach new address list to person. */
1219 1 hiro
           node = listEMail;
1220 1 hiro
        while( node ) {
1221 1 hiro
                ItemEMail *email = node->data;
1222 1 hiro
                if( ADDRITEM_ID(email) == NULL ) {
1223 1 hiro
                        /* Allocate an ID */
1224 1 hiro
                        addrcache_id_email( book->addressCache, email );
1225 1 hiro
                }
1226 1 hiro
                ADDRITEM_PARENT(email) = ADDRITEM_OBJECT(person);
1227 1 hiro
                node = g_list_next( node );
1228 1 hiro
        }
1229 1 hiro
        person->listEMail = listEMail;
1230 1 hiro
1231 1 hiro
        /* Get groups where person's email is listed */
1232 1 hiro
        listGroup = addrcache_get_group_for_person( book->addressCache, person );
1233 1 hiro
        if( listGroup ) {
1234 1 hiro
                GHashTable *hashEMail;
1235 1 hiro
                GList *nodeGrp;
1236 1 hiro
1237 1 hiro
                /* Load hash table with new address entries */
1238 1 hiro
                hashEMail = g_hash_table_new( g_str_hash, g_str_equal );
1239 1 hiro
                   node = listEMail;
1240 1 hiro
                while( node ) {
1241 1 hiro
                        ItemEMail *email = node->data;
1242 1 hiro
                        gchar *addr = g_strdup( email->address );
1243 1 hiro
                        g_strdown( addr );
1244 1 hiro
                        if( ! g_hash_table_lookup( hashEMail, addr ) ) {
1245 1 hiro
                                g_hash_table_insert( hashEMail, addr, email );
1246 1 hiro
                        }
1247 1 hiro
                        node = g_list_next( node );
1248 1 hiro
                }
1249 1 hiro
1250 1 hiro
                /* Re-parent new addresses to existing groups, where email address match. */
1251 1 hiro
                nodeGrp = listGroup;
1252 1 hiro
                while( nodeGrp ) {
1253 1 hiro
                        ItemGroup *group = ( ItemGroup * ) nodeGrp->data;
1254 1 hiro
                        GList *groupEMail = group->listEMail;
1255 1 hiro
                        GList *nodeGrpEM;
1256 1 hiro
                        GList *listRemove = NULL;
1257 1 hiro
1258 1 hiro
                        /* Process each email item linked to group */
1259 1 hiro
                        nodeGrpEM = groupEMail;
1260 1 hiro
                        while( nodeGrpEM ) {
1261 1 hiro
                                ItemEMail *emailGrp = ( ItemEMail * ) nodeGrpEM->data;
1262 1 hiro
                                if( ADDRITEM_PARENT(emailGrp) == ADDRITEM_OBJECT(person) ) {
1263 1 hiro
                                        /* Found an email address for this person */
1264 1 hiro
                                        ItemEMail *emailNew = NULL;
1265 1 hiro
                                        gchar *addr = g_strdup( emailGrp->address );
1266 1 hiro
                                        g_strdown( addr );
1267 1 hiro
                                        emailNew = ( ItemEMail * ) g_hash_table_lookup( hashEMail, addr );
1268 1 hiro
                                        g_free( addr );
1269 1 hiro
                                        if( emailNew ) {
1270 1 hiro
                                                /* Point to this entry */
1271 1 hiro
                                                nodeGrpEM->data = emailNew;
1272 1 hiro
                                        }
1273 1 hiro
                                        else {
1274 1 hiro
                                                /* Mark for removal */
1275 1 hiro
                                                listRemove = g_list_append( listRemove, emailGrp );
1276 1 hiro
                                        }
1277 1 hiro
                                }
1278 1 hiro
                                /* Move on to next email link */
1279 1 hiro
                                nodeGrpEM = g_list_next( nodeGrpEM );
1280 1 hiro
                        }
1281 1 hiro
1282 1 hiro
                        /* Process all removed links in current group */
1283 1 hiro
                        nodeGrpEM = listRemove;
1284 1 hiro
                        while( nodeGrpEM ) {
1285 1 hiro
                                ItemEMail *emailGrp = nodeGrpEM->data;
1286 1 hiro
                                groupEMail = g_list_remove( groupEMail, emailGrp );
1287 1 hiro
                                nodeGrpEM = g_list_next( nodeGrpEM );
1288 1 hiro
                        }
1289 798 hiro
                        group->listEMail = groupEMail;
1290 1 hiro
1291 1 hiro
                        /* Move on to next group */
1292 1 hiro
                        nodeGrp = g_list_next( nodeGrp );
1293 1 hiro
1294 1 hiro
                }
1295 1 hiro
1296 1 hiro
                /* Clear hash table */
1297 1 hiro
                g_hash_table_foreach_remove( hashEMail, ( GHRFunc ) addrbook_free_simple_hash_vis, NULL );
1298 1 hiro
                g_hash_table_destroy( hashEMail );
1299 1 hiro
                hashEMail = NULL;
1300 1 hiro
                g_list_free( listGroup );
1301 1 hiro
                listGroup = NULL;
1302 1 hiro
        }
1303 1 hiro
1304 1 hiro
        /* Free up old data */
1305 1 hiro
        addritem_free_list_email( oldData );
1306 1 hiro
        oldData = NULL;
1307 1 hiro
        book->dirtyFlag = TRUE;
1308 1 hiro
1309 1 hiro
}
1310 1 hiro
1311 1 hiro
/*
1312 1 hiro
* Add person and address data to address book.
1313 1 hiro
* Enter: book      Address book.
1314 1 hiro
*        folder    Folder where to add person, or NULL for root folder.
1315 1 hiro
*        listEMail New list of email addresses.
1316 1 hiro
* Return: Person added.
1317 1 hiro
* Note: A new person is created with specified list of email addresses. All objects inserted
1318 1 hiro
* into address book.
1319 1 hiro
*/
1320 1 hiro
ItemPerson *addrbook_add_address_list( AddressBookFile *book, ItemFolder *folder, GList *listEMail ) {
1321 1 hiro
        ItemPerson *person;
1322 1 hiro
        ItemFolder *f = folder;
1323 1 hiro
        GList *node;
1324 1 hiro
1325 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
1326 1 hiro
1327 1 hiro
        if( ! f ) f = book->addressCache->rootFolder;
1328 1 hiro
        person = addritem_create_item_person();
1329 1 hiro
        addrcache_id_person( book->addressCache, person );
1330 1 hiro
        addrcache_folder_add_person( book->addressCache, f, person );
1331 1 hiro
1332 1 hiro
           node = listEMail;
1333 1 hiro
        while( node ) {
1334 1 hiro
                ItemEMail *email = node->data;
1335 1 hiro
                if( ADDRITEM_ID(email) == NULL ) {
1336 1 hiro
                        addrcache_id_email( book->addressCache, email );
1337 1 hiro
                }
1338 1 hiro
                addrcache_person_add_email( book->addressCache, person, email );
1339 1 hiro
                node = g_list_next( node );
1340 1 hiro
        }
1341 1 hiro
        book->dirtyFlag = TRUE;
1342 1 hiro
        return person;
1343 1 hiro
}
1344 1 hiro
1345 1 hiro
#if 0
1346 1 hiro
/*
1347 1 hiro
* Load hash table visitor function.
1348 1 hiro
*/
1349 1 hiro
static void addrbook_load_hash_table_email_vis( gpointer key, gpointer value, gpointer data ) {
1350 1 hiro
        AddrItemObject *obj = ( AddrItemObject * ) value;
1351 1 hiro
1352 1 hiro
        if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
1353 1 hiro
                GHashTable *table = ( GHashTable * ) data;
1354 1 hiro
                gchar *newKey = g_strdup( key );
1355 1 hiro
                ItemEMail *email = ( ItemEMail * ) obj;
1356 1 hiro
                if( ! g_hash_table_lookup( table, newKey ) ) {
1357 1 hiro
                        g_hash_table_insert( table, newKey, email );
1358 1 hiro
                }
1359 1 hiro
        }
1360 1 hiro
}
1361 1 hiro
1362 1 hiro
/*
1363 1 hiro
* Load hash table with links to email addresses.
1364 1 hiro
*/
1365 1 hiro
static void addrbook_load_hash_table_email( AddressBookFile *book, GHashTable *table ) {
1366 1 hiro
        g_return_if_fail( book != NULL );
1367 1 hiro
        g_return_if_fail( table != NULL );
1368 1 hiro
        g_hash_table_foreach( book->addressCache->itemHash, addrbook_load_hash_table_email_vis, table );
1369 1 hiro
}
1370 1 hiro
#endif
1371 1 hiro
1372 1 hiro
/*
1373 1 hiro
* Build available email list visitor function.
1374 1 hiro
*/
1375 1 hiro
static void addrbook_build_avail_email_vis( gpointer key, gpointer value, gpointer data ) {
1376 1 hiro
        AddrItemObject *obj = ( AddrItemObject * ) value;
1377 1 hiro
1378 1 hiro
        if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
1379 1 hiro
                AddressBookFile *book = data;
1380 1 hiro
                ItemPerson *person = ( ItemPerson * ) obj;
1381 1 hiro
                GList *node = person->listEMail;
1382 1 hiro
                while( node ) {
1383 1 hiro
                        ItemEMail *email = node->data;
1384 1 hiro
                        /* gchar *newKey = g_strdup( ADDRITEM_ID(email) ); */
1385 1 hiro
1386 1 hiro
                        if( ! g_hash_table_lookup( book->tempHash, ADDRITEM_ID(email) ) ) {
1387 1 hiro
                                book->tempList = g_list_append( book->tempList, email );
1388 1 hiro
                        }
1389 1 hiro
                        node = g_list_next( node );
1390 1 hiro
                }
1391 1 hiro
        }
1392 1 hiro
}
1393 1 hiro
1394 1 hiro
/*
1395 1 hiro
* Return link list of available email items (which have not already been linked to
1396 1 hiro
* groups). Note that the list contains references to items and should be g_free()
1397 1 hiro
* when done. Do *NOT* attempt to used the addrbook_free_xxx() functions... this will
1398 1 hiro
* destroy the addressbook data!
1399 1 hiro
* Return: List of items, or NULL if none.
1400 1 hiro
*/
1401 1 hiro
GList *addrbook_get_available_email_list( AddressBookFile *book, ItemGroup *group ) {
1402 1 hiro
        GList *list = NULL;
1403 1 hiro
        GHashTable *table;
1404 1 hiro
1405 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
1406 1 hiro
1407 1 hiro
        /* Load hash table with group email entries */
1408 1 hiro
        table = g_hash_table_new( g_str_hash, g_str_equal );
1409 1 hiro
        if( group ) {
1410 1 hiro
                list = group->listEMail;
1411 1 hiro
                while( list ) {
1412 1 hiro
                        ItemEMail *email = list->data;
1413 1 hiro
                        g_hash_table_insert( table, ADDRITEM_ID(email), email );
1414 1 hiro
                        list = g_list_next( list );
1415 1 hiro
                }
1416 1 hiro
        }
1417 1 hiro
1418 1 hiro
        /* Build list of available email addresses which exclude those already in groups */
1419 1 hiro
        book->tempList = NULL;
1420 1 hiro
        book->tempHash = table;
1421 1 hiro
        g_hash_table_foreach( book->addressCache->itemHash, addrbook_build_avail_email_vis, book );
1422 1 hiro
        list = book->tempList;
1423 1 hiro
        book->tempList = NULL;
1424 1 hiro
        book->tempHash = NULL;
1425 1 hiro
1426 1 hiro
        /* Clear hash table */
1427 1 hiro
        g_hash_table_destroy( table );
1428 1 hiro
        table = NULL;
1429 1 hiro
1430 1 hiro
        return list;
1431 1 hiro
}
1432 1 hiro
1433 1 hiro
/*
1434 1 hiro
* Update address book email list for specified group.
1435 1 hiro
* Enter: book      Address book.
1436 1 hiro
*        group     group to update.
1437 1 hiro
*        listEMail New list of email addresses. This should *NOT* be g_free() when done.
1438 1 hiro
* Note: The existing email addresses are replaced with the new addresses. Any references
1439 1 hiro
* to old addresses in the groups are re-linked to the new addresses. All old addresses
1440 1 hiro
* linked to the person are removed.
1441 1 hiro
*/
1442 1 hiro
void addrbook_update_group_list( AddressBookFile *book, ItemGroup *group, GList *listEMail ) {
1443 1 hiro
        GList *oldData;
1444 1 hiro
1445 1 hiro
        g_return_if_fail( book != NULL );
1446 1 hiro
        g_return_if_fail( group != NULL );
1447 1 hiro
1448 1 hiro
        /* Remember old list */
1449 1 hiro
        oldData = group->listEMail;
1450 1 hiro
        group->listEMail = listEMail;
1451 1 hiro
        mgu_clear_list( oldData );
1452 798 hiro
        g_list_free ( oldData );
1453 1 hiro
        book->dirtyFlag = TRUE;
1454 1 hiro
}
1455 1 hiro
1456 1 hiro
/*
1457 1 hiro
* Add group and email list to address book.
1458 1 hiro
* Enter: book      Address book.
1459 1 hiro
*        folder    Parent folder, or NULL for root folder.
1460 1 hiro
*        listEMail New list of email addresses. This should *NOT* be g_free() when done.
1461 1 hiro
* Return: Group object.
1462 1 hiro
* Note: The existing email addresses are replaced with the new addresses. Any references
1463 1 hiro
* to old addresses in the groups are re-linked to the new addresses. All old addresses
1464 1 hiro
* linked to the person are removed.
1465 1 hiro
*/
1466 1 hiro
ItemGroup *addrbook_add_group_list( AddressBookFile *book, ItemFolder *folder, GList *listEMail ) {
1467 1 hiro
        ItemGroup *group = NULL;
1468 1 hiro
        ItemFolder *f = folder;
1469 1 hiro
1470 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
1471 1 hiro
1472 1 hiro
        if( ! f ) f = book->addressCache->rootFolder;
1473 1 hiro
        group = addritem_create_item_group();
1474 1 hiro
        addrcache_id_group( book->addressCache, group );
1475 1 hiro
        addrcache_folder_add_group( book->addressCache, f, group );
1476 1 hiro
        group->listEMail = listEMail;
1477 1 hiro
        book->dirtyFlag = TRUE;
1478 1 hiro
        return group;
1479 1 hiro
}
1480 1 hiro
1481 1 hiro
/*
1482 1 hiro
* Add new folder to address book.
1483 1 hiro
* Enter: book   Address book.
1484 1 hiro
*        parent        Parent folder.
1485 1 hiro
* Return: Folder that was added. This should *NOT* be g_free() when done.
1486 1 hiro
*/
1487 1 hiro
ItemFolder *addrbook_add_new_folder( AddressBookFile *book, ItemFolder *parent ) {
1488 1 hiro
        ItemFolder *folder = NULL;
1489 1 hiro
        ItemFolder *p = parent;
1490 1 hiro
1491 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
1492 1 hiro
1493 1 hiro
        if( ! p ) p = book->addressCache->rootFolder;
1494 1 hiro
        folder = addritem_create_item_folder();
1495 1 hiro
        addrcache_id_folder( book->addressCache, folder );
1496 1 hiro
        if( addrcache_hash_add_folder( book->addressCache, folder ) ) {
1497 1 hiro
                p->listFolder = g_list_append( p->listFolder, folder );
1498 1 hiro
                ADDRITEM_PARENT(folder) = ADDRITEM_OBJECT(p);
1499 1 hiro
                book->dirtyFlag = TRUE;
1500 1 hiro
        }
1501 1 hiro
        else {
1502 1 hiro
                addritem_free_item_folder( folder );
1503 1 hiro
                folder = NULL;
1504 1 hiro
        }
1505 1 hiro
        return folder;
1506 1 hiro
}
1507 1 hiro
1508 1 hiro
/*
1509 1 hiro
* Update address book attribute list for specified person.
1510 1 hiro
* Enter: book       Address book.
1511 1 hiro
*        person     Person to update.
1512 1 hiro
*        listAttrib New list of attributes.
1513 1 hiro
* Note: The existing email addresses are replaced with the new addresses. All old attributes
1514 1 hiro
* linked to the person are removed.
1515 1 hiro
*/
1516 1 hiro
void addrbook_update_attrib_list( AddressBookFile *book, ItemPerson *person, GList *listAttrib ) {
1517 1 hiro
        GList *node;
1518 1 hiro
        GList *oldData;
1519 1 hiro
1520 1 hiro
        g_return_if_fail( book != NULL );
1521 1 hiro
        g_return_if_fail( person != NULL );
1522 1 hiro
1523 1 hiro
        /* Remember old list */
1524 1 hiro
        oldData = person->listAttrib;
1525 1 hiro
1526 1 hiro
        /* Attach new address list to person. */
1527 1 hiro
           node = listAttrib;
1528 1 hiro
        while( node ) {
1529 1 hiro
                UserAttribute *attrib = node->data;
1530 1 hiro
                if( attrib->uid == NULL ) {
1531 1 hiro
                        /* Allocate an ID */
1532 1 hiro
                        addrcache_id_attribute( book->addressCache, attrib );
1533 1 hiro
                }
1534 1 hiro
                node = g_list_next( node );
1535 1 hiro
        }
1536 1 hiro
        person->listAttrib = listAttrib;
1537 1 hiro
1538 1 hiro
        /* Free up old data */
1539 1 hiro
        addritem_free_list_attribute( oldData );
1540 1 hiro
        oldData = NULL;
1541 1 hiro
        book->dirtyFlag = TRUE;
1542 1 hiro
1543 1 hiro
}
1544 1 hiro
1545 1 hiro
/*
1546 1 hiro
* Add attribute data for person to address book.
1547 1 hiro
* Enter: book       Address book.
1548 1 hiro
*        person     New person object.
1549 1 hiro
*        listAttrib New list of attributes.
1550 1 hiro
* Note: Only attributes are inserted into address book.
1551 1 hiro
*/
1552 1 hiro
void addrbook_add_attrib_list( AddressBookFile *book, ItemPerson *person, GList *listAttrib ) {
1553 1 hiro
        GList *node;
1554 1 hiro
1555 1 hiro
        g_return_if_fail( book != NULL );
1556 1 hiro
        g_return_if_fail( person != NULL );
1557 1 hiro
1558 1 hiro
           node = listAttrib;
1559 1 hiro
        while( node ) {
1560 1 hiro
                UserAttribute *attrib = node->data;
1561 1 hiro
                if( attrib->uid == NULL ) {
1562 1 hiro
                        addrcache_id_attribute( book->addressCache, attrib );
1563 1 hiro
                }
1564 1 hiro
                addritem_person_add_attribute( person, attrib );
1565 1 hiro
                node = g_list_next( node );
1566 1 hiro
        }
1567 1 hiro
        book->dirtyFlag = TRUE;
1568 1 hiro
}
1569 1 hiro
1570 1 hiro
/*
1571 1 hiro
* Return address book file for specified object.
1572 1 hiro
* Enter: aio Book item object.
1573 1 hiro
* Return: Address book, or NULL if not found.
1574 1 hiro
*/
1575 1 hiro
AddressBookFile *addrbook_item_get_bookfile( AddrItemObject *aio ) {
1576 1 hiro
        AddressBookFile *book = NULL;
1577 1 hiro
1578 1 hiro
        if( aio ) {
1579 1 hiro
                ItemFolder *parent = NULL;
1580 1 hiro
                ItemFolder *root = NULL;
1581 1 hiro
                if( aio->type == ITEMTYPE_EMAIL ) {
1582 1 hiro
                        ItemPerson *person = ( ItemPerson * ) ADDRITEM_PARENT(aio);
1583 1 hiro
                        if( person ) {
1584 1 hiro
                                parent = ( ItemFolder * ) ADDRITEM_PARENT(person);
1585 1 hiro
                        }
1586 1 hiro
                }
1587 1 hiro
                else {
1588 1 hiro
                        parent = ( ItemFolder * ) ADDRITEM_PARENT(aio);
1589 1 hiro
                }
1590 1 hiro
                if( parent ) {
1591 1 hiro
                        root = addrcache_find_root_folder( parent );
1592 1 hiro
                }
1593 1 hiro
                if( root ) {
1594 1 hiro
                        book = ( AddressBookFile * ) ADDRITEM_PARENT(root);
1595 1 hiro
                }
1596 1 hiro
        }
1597 1 hiro
        return book;
1598 1 hiro
}
1599 1 hiro
1600 1 hiro
/*
1601 1 hiro
* Remove folder from address book. Children are re-parented to parent folder.
1602 1 hiro
* param: folder Folder to remove.
1603 1 hiro
* return: Folder, or NULL if not found. Note that object should still be freed.
1604 1 hiro
*/
1605 1 hiro
ItemFolder *addrbook_remove_folder( AddressBookFile *book, ItemFolder *folder ) {
1606 1 hiro
        ItemFolder *f;
1607 1 hiro
1608 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
1609 1 hiro
1610 1 hiro
        f = addrcache_remove_folder( book->addressCache, folder );
1611 1 hiro
        if( f ) book->dirtyFlag = TRUE;
1612 1 hiro
        return f;
1613 1 hiro
}
1614 1 hiro
1615 1 hiro
/*
1616 1 hiro
* Remove folder from address book. Children are deleted.
1617 1 hiro
* param: folder Folder to remove.
1618 1 hiro
* return: Folder, or NULL if not found. Note that object should still be freed.
1619 1 hiro
*/
1620 1 hiro
ItemFolder *addrbook_remove_folder_delete( AddressBookFile *book, ItemFolder *folder ) {
1621 1 hiro
        ItemFolder *f;
1622 1 hiro
1623 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
1624 1 hiro
1625 1 hiro
        f = addrcache_remove_folder_delete( book->addressCache, folder );
1626 1 hiro
        if( f ) book->dirtyFlag = TRUE;
1627 1 hiro
        return f;
1628 1 hiro
}
1629 1 hiro
1630 1 hiro
#define WORK_BUFLEN     1024
1631 1 hiro
#define ADDRBOOK_DIGITS "0123456789"
1632 1 hiro
1633 1 hiro
/*
1634 1 hiro
* Return list of existing address book files.
1635 1 hiro
* Enter: book Address book file.
1636 1 hiro
* Return: File list.
1637 1 hiro
*/
1638 1 hiro
GList *addrbook_get_bookfile_list( AddressBookFile *book ) {
1639 1 hiro
        gchar *adbookdir;
1640 479 hiro
        GDir *dir;
1641 479 hiro
        const gchar *dir_name;
1642 1 hiro
        struct stat statbuf;
1643 1 hiro
        gchar buf[ WORK_BUFLEN ];
1644 1 hiro
        gchar numbuf[ WORK_BUFLEN ];
1645 1 hiro
        gint len, lenpre, lensuf, lennum;
1646 1 hiro
        long int val, maxval;
1647 1 hiro
        GList *fileList = NULL;
1648 1 hiro
1649 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
1650 1 hiro
1651 1 hiro
        if( book->path == NULL || *book->path == '\0' ) {
1652 1 hiro
                book->retVal = MGU_NO_PATH;
1653 1 hiro
                return NULL;
1654 1 hiro
        }
1655 1 hiro
1656 1 hiro
        strcpy( buf, book->path );
1657 1 hiro
        len = strlen( buf );
1658 1 hiro
        if( len > 0 ) {
1659 1 hiro
                if( buf[ len-1 ] != G_DIR_SEPARATOR ) {
1660 1 hiro
                        buf[ len ] = G_DIR_SEPARATOR;
1661 1 hiro
                        buf[ ++len ] = '\0';
1662 1 hiro
                }
1663 1 hiro
        }
1664 1 hiro
1665 1 hiro
        adbookdir = g_strdup( buf );
1666 1 hiro
        strcat( buf, ADDRBOOK_PREFIX );
1667 1 hiro
1668 479 hiro
        if( ( dir = g_dir_open( adbookdir, 0, NULL ) ) == NULL ) {
1669 1 hiro
                book->retVal = MGU_OPEN_DIRECTORY;
1670 1 hiro
                g_free( adbookdir );
1671 1 hiro
                return NULL;
1672 1 hiro
        }
1673 1 hiro
1674 1 hiro
        lenpre = strlen( ADDRBOOK_PREFIX );
1675 1 hiro
        lensuf = strlen( ADDRBOOK_SUFFIX );
1676 1 hiro
        lennum = FILE_NUMDIGITS + lenpre;
1677 1 hiro
        maxval = -1;
1678 1 hiro
1679 479 hiro
        while( ( dir_name = g_dir_read_name( dir ) ) != NULL ) {
1680 1 hiro
                gchar *endptr = NULL;
1681 1 hiro
                gint i;
1682 1 hiro
                gboolean flg;
1683 1 hiro
1684 1 hiro
                strcpy( buf, adbookdir );
1685 479 hiro
                strcat( buf, dir_name );
1686 478 hiro
                g_stat( buf, &statbuf );
1687 1 hiro
                if( S_IFREG & statbuf.st_mode ) {
1688 479 hiro
                        if( strncmp( dir_name, ADDRBOOK_PREFIX, lenpre ) == 0 ) {
1689 479 hiro
                                if( strncmp( (dir_name) + lennum, ADDRBOOK_SUFFIX, lensuf ) == 0 ) {
1690 479 hiro
                                        strncpy( numbuf, (dir_name) + lenpre, FILE_NUMDIGITS );
1691 1 hiro
                                        numbuf[ FILE_NUMDIGITS ] = '\0';
1692 1 hiro
                                        flg = TRUE;
1693 1 hiro
                                        for( i = 0; i < FILE_NUMDIGITS; i++ ) {
1694 1 hiro
                                                if( ! strchr( ADDRBOOK_DIGITS, numbuf[i] ) ) {
1695 1 hiro
                                                        flg = FALSE;
1696 1 hiro
                                                        break;
1697 1 hiro
                                                }
1698 1 hiro
                                        }
1699 1 hiro
                                        if( flg ) {
1700 1 hiro
                                                /* Get value */
1701 1 hiro
                                                val = strtol( numbuf, &endptr, 10 );
1702 1 hiro
                                                if( endptr  && val > -1 ) {
1703 1 hiro
                                                        if( val > maxval ) maxval = val;
1704 479 hiro
                                                        fileList = g_list_append( fileList, g_strdup( dir_name ) );
1705 1 hiro
                                                }
1706 1 hiro
                                        }
1707 1 hiro
                                }
1708 1 hiro
                        }
1709 1 hiro
                }
1710 1 hiro
        }
1711 479 hiro
        g_dir_close( dir );
1712 1 hiro
        g_free( adbookdir );
1713 1 hiro
1714 1 hiro
        book->maxValue = maxval;
1715 1 hiro
        book->retVal = MGU_SUCCESS;
1716 1 hiro
        return fileList;
1717 1 hiro
}
1718 1 hiro
1719 1 hiro
/*
1720 1 hiro
* Return file name for specified file number.
1721 1 hiro
* Enter:  fileNum File number.
1722 1 hiro
* Return: File name, or NULL if file number too large. Should be g_free() when done.
1723 1 hiro
*/
1724 1 hiro
gchar *addrbook_gen_new_file_name( gint fileNum ) {
1725 1 hiro
        gchar fmt[ 30 ];
1726 1 hiro
        gchar buf[ WORK_BUFLEN ];
1727 1 hiro
        gint n = fileNum;
1728 1 hiro
        long int nmax;
1729 1 hiro
1730 1 hiro
        if( n < 1 ) n = 1;
1731 1 hiro
        nmax = -1 + (long int) pow( 10, FILE_NUMDIGITS );
1732 1 hiro
        if( fileNum > nmax ) return NULL;
1733 1 hiro
        sprintf( fmt, "%%s%%0%dd%%s", FILE_NUMDIGITS );
1734 1 hiro
        sprintf( buf, fmt, ADDRBOOK_PREFIX, n, ADDRBOOK_SUFFIX );
1735 1 hiro
        return g_strdup( buf );
1736 1 hiro
}
1737 1 hiro
1738 1 hiro
/* **********************************************************************
1739 1 hiro
* Address book test functions...
1740 1 hiro
* ***********************************************************************
1741 1 hiro
*/
1742 1 hiro
1743 1 hiro
#if 0
1744 1 hiro
static void addrbook_show_attribs( GList *attr ) {
1745 1 hiro
        while( attr ) {
1746 1 hiro
                gchar *name = ((XMLAttr *)attr->data)->name;
1747 1 hiro
                gchar *value = ((XMLAttr *)attr->data)->value;
1748 1 hiro
                printf( "\tn/v = %s : %s\n", name, value );
1749 1 hiro
                attr = g_list_next( attr );
1750 1 hiro
        }
1751 1 hiro
        printf( "\t---\n" );
1752 1 hiro
}
1753 1 hiro
#endif
1754 1 hiro
1755 1 hiro
/*
1756 1 hiro
* Test email address list.
1757 1 hiro
*/
1758 1 hiro
static void addrbook_chkparse_addr_list( AddressBookFile *book, XMLFile *file ){
1759 1 hiro
        guint prev_level;
1760 1 hiro
        GList *attr;
1761 1 hiro
1762 1 hiro
        for (;;) {
1763 1 hiro
                prev_level = file->level;
1764 1 hiro
                if( xml_parse_next_tag( file ) ) {
1765 1 hiro
                        longjmp( book->jumper, 1 );
1766 1 hiro
                }
1767 1 hiro
                if (file->level < prev_level) return;
1768 1 hiro
                attr = xml_get_current_tag_attr(file);
1769 1 hiro
                /* addrbook_show_attribs( attr ); */
1770 1 hiro
                if( xml_compare_tag( file, AB_ELTAG_ADDRESS ) ) {
1771 1 hiro
                        addrbook_chkparse_addr_list( book, file );
1772 1 hiro
                }
1773 1 hiro
        }
1774 1 hiro
}
1775 1 hiro
1776 1 hiro
/*
1777 1 hiro
* Test user attributes for person.
1778 1 hiro
*/
1779 1 hiro
static void addrbook_chkparse_attribute( AddressBookFile *book, XMLFile *file ) {
1780 1 hiro
        GList *attr;
1781 1 hiro
        gchar *element;
1782 1 hiro
1783 1 hiro
        attr = xml_get_current_tag_attr(file);
1784 1 hiro
        /* addrbook_show_attribs( attr ); */
1785 1 hiro
        element = xml_get_element( file );
1786 1 hiro
        /* printf( "\t\tattrib value : %s\n", element ); */
1787 1 hiro
}
1788 1 hiro
1789 1 hiro
/*
1790 1 hiro
* Test attribute list.
1791 1 hiro
*/
1792 1 hiro
static void addrbook_chkparse_attr_list( AddressBookFile *book, XMLFile *file ){
1793 1 hiro
        guint prev_level;
1794 1 hiro
1795 1 hiro
        for (;;) {
1796 1 hiro
                prev_level = file->level;
1797 1 hiro
                if( xml_parse_next_tag( file ) ) {
1798 1 hiro
                        longjmp( book->jumper, 1 );
1799 1 hiro
                }
1800 1 hiro
                if (file->level < prev_level) return;
1801 1 hiro
                if( xml_compare_tag( file, AB_ELTAG_ATTRIBUTE ) ) {
1802 1 hiro
                        addrbook_chkparse_attribute( book, file );
1803 1 hiro
                        addrbook_chkparse_attr_list( book, file );
1804 1 hiro
                }
1805 1 hiro
        }
1806 1 hiro
}
1807 1 hiro
1808 1 hiro
/*
1809 1 hiro
* Test person.
1810 1 hiro
*/
1811 1 hiro
static void addrbook_chkparse_person( AddressBookFile *book, XMLFile *file ) {
1812 1 hiro
        GList *attr;
1813 1 hiro
1814 1 hiro
        attr = xml_get_current_tag_attr(file);
1815 1 hiro
        /* addrbook_show_attribs( attr ); */
1816 1 hiro
        if( xml_parse_next_tag( file ) ) {        /* Consume closing tag */
1817 1 hiro
                longjmp( book->jumper, 1 );
1818 1 hiro
        }
1819 1 hiro
        if( xml_compare_tag( file, AB_ELTAG_ADDRESS_LIST ) ) {
1820 1 hiro
                addrbook_chkparse_addr_list( book, file );
1821 1 hiro
        }
1822 1 hiro
        if( xml_parse_next_tag( file ) ) {        /* Consume closing tag */
1823 1 hiro
                longjmp( book->jumper, 1 );
1824 1 hiro
        }
1825 1 hiro
        if( xml_compare_tag( file, AB_ELTAG_ATTRIBUTE_LIST ) ) {
1826 1 hiro
                addrbook_chkparse_attr_list( book, file );
1827 1 hiro
        }
1828 1 hiro
}
1829 1 hiro
1830 1 hiro
/*
1831 1 hiro
* Test group member list.
1832 1 hiro
*/
1833 1 hiro
static void addrbook_chkparse_member_list( AddressBookFile *book, XMLFile *file ){
1834 1 hiro
        GList *attr;
1835 1 hiro
        guint prev_level;
1836 1 hiro
1837 1 hiro
        for (;;) {
1838 1 hiro
                prev_level = file->level;
1839 1 hiro
                if( xml_parse_next_tag( file ) ) {
1840 1 hiro
                        longjmp( book->jumper, 1 );
1841 1 hiro
                }
1842 1 hiro
                if (file->level < prev_level) return;
1843 1 hiro
                if( xml_compare_tag( file, AB_ELTAG_MEMBER ) ) {
1844 1 hiro
                        attr = xml_get_current_tag_attr(file);
1845 1 hiro
                        /* addrbook_show_attribs( attr ); */
1846 1 hiro
                        addrbook_chkparse_member_list( book, file );
1847 1 hiro
                }
1848 1 hiro
                else {
1849 1 hiro
                        attr = xml_get_current_tag_attr( file );
1850 1 hiro
                        /* addrbook_show_attribs( attr ); */
1851 1 hiro
                }
1852 1 hiro
        }
1853 1 hiro
}
1854 1 hiro
1855 1 hiro
/*
1856 1 hiro
* Test group.
1857 1 hiro
*/
1858 1 hiro
static void addrbook_chkparse_group( AddressBookFile *book, XMLFile *file ) {
1859 1 hiro
        GList *attr;
1860 1 hiro
1861 1 hiro
        attr = xml_get_current_tag_attr(file);
1862 1 hiro
        /* addrbook_show_attribs( attr ); */
1863 1 hiro
        if( xml_parse_next_tag( file ) ) {        /* Consume closing tag */
1864 1 hiro
                longjmp( book->jumper, 1 );
1865 1 hiro
        }
1866 1 hiro
        if( xml_compare_tag( file, AB_ELTAG_MEMBER_LIST ) ) {
1867 1 hiro
                addrbook_chkparse_member_list( book, file );
1868 1 hiro
        }
1869 1 hiro
}
1870 1 hiro
1871 1 hiro
/*
1872 1 hiro
* Test folder item list.
1873 1 hiro
*/
1874 1 hiro
static void addrbook_chkparse_folder_list( AddressBookFile *book, XMLFile *file ){
1875 1 hiro
        GList *attr;
1876 1 hiro
        guint prev_level;
1877 1 hiro
1878 1 hiro
        for (;;) {
1879 1 hiro
                prev_level = file->level;
1880 1 hiro
                if( xml_parse_next_tag( file ) ) {
1881 1 hiro
                        longjmp( book->jumper, 1 );
1882 1 hiro
                }
1883 1 hiro
                if (file->level < prev_level) return;
1884 1 hiro
                if( xml_compare_tag( file, AB_ELTAG_ITEM ) ) {
1885 1 hiro
                        attr = xml_get_current_tag_attr(file);
1886 1 hiro
                        /* addrbook_show_attribs( attr ); */
1887 1 hiro
                        addrbook_chkparse_folder_list( book, file );
1888 1 hiro
                }
1889 1 hiro
                else {
1890 1 hiro
                        attr = xml_get_current_tag_attr( file );
1891 1 hiro
                        /* addrbook_show_attribs( attr ); */
1892 1 hiro
                }
1893 1 hiro
        }
1894 1 hiro
}
1895 1 hiro
1896 1 hiro
/*
1897 1 hiro
* Test folder.
1898 1 hiro
*/
1899 1 hiro
static void addrbook_chkparse_folder( AddressBookFile *book, XMLFile *file ) {
1900 1 hiro
        GList *attr;
1901 1 hiro
1902 1 hiro
        attr = xml_get_current_tag_attr(file);
1903 1 hiro
        /* addrbook_show_attribs( attr ); */
1904 1 hiro
        if( xml_parse_next_tag( file ) ) {        /* Consume closing tag */
1905 1 hiro
                longjmp( book->jumper, 1 );
1906 1 hiro
        }
1907 1 hiro
        if( xml_compare_tag( file, AB_ELTAG_ITEM_LIST ) ) {
1908 1 hiro
                addrbook_chkparse_folder_list( book, file );
1909 1 hiro
        }
1910 1 hiro
}
1911 1 hiro
1912 1 hiro
/*
1913 1 hiro
* Test address book.
1914 1 hiro
*/
1915 1 hiro
static gboolean addrbook_chkread_tree( AddressBookFile *book, XMLFile *file ) {
1916 1 hiro
        GList *attr;
1917 1 hiro
        gboolean retVal;
1918 1 hiro
1919 1 hiro
        if( xml_get_dtd( file ) ) {
1920 1 hiro
                return FALSE;
1921 1 hiro
        }
1922 1 hiro
        if( xml_parse_next_tag( file ) ) {
1923 1 hiro
                return FALSE;
1924 1 hiro
        }
1925 1 hiro
1926 1 hiro
        if( ! xml_compare_tag( file, AB_ELTAG_ADDRESS_BOOK ) ) {
1927 1 hiro
                return FALSE;
1928 1 hiro
        }
1929 1 hiro
1930 1 hiro
        attr = xml_get_current_tag_attr(file);
1931 1 hiro
        /* addrbook_show_attribs( attr ); */
1932 1 hiro
1933 1 hiro
        retVal = TRUE;
1934 1 hiro
        for (;;) {
1935 1 hiro
                if (! file->level ) break;
1936 1 hiro
                /* Get item tag */
1937 1 hiro
                if( xml_parse_next_tag( file ) ) {
1938 1 hiro
                        longjmp( book->jumper, 1 );
1939 1 hiro
                }
1940 1 hiro
                /* Get next tag (person, group or folder) */
1941 1 hiro
                if( xml_compare_tag( file, AB_ELTAG_PERSON ) ) {
1942 1 hiro
                        addrbook_chkparse_person( book, file );
1943 1 hiro
                }
1944 1 hiro
                else if( xml_compare_tag( file, AB_ELTAG_GROUP ) ) {
1945 1 hiro
                        addrbook_chkparse_group( book, file );
1946 1 hiro
                }
1947 1 hiro
                else if( xml_compare_tag( file, AB_ELTAG_FOLDER ) ) {
1948 1 hiro
                        addrbook_chkparse_folder( book, file );
1949 1 hiro
                }
1950 1 hiro
        }
1951 1 hiro
        return retVal;
1952 1 hiro
}
1953 1 hiro
1954 1 hiro
/*
1955 1 hiro
* Test address book file by parsing contents.
1956 1 hiro
* Enter: book     Address book file to check.
1957 1 hiro
*        fileName File name to check.
1958 1 hiro
* Return: MGU_SUCCESS if file appears to be valid format.
1959 1 hiro
*/
1960 1 hiro
gint addrbook_test_read_file( AddressBookFile *book, gchar *fileName ) {
1961 1 hiro
        XMLFile *file = NULL;
1962 1 hiro
        gchar *fileSpec = NULL;
1963 1 hiro
1964 1 hiro
        g_return_val_if_fail( book != NULL, -1 );
1965 1 hiro
1966 1 hiro
        fileSpec = g_strconcat( book->path, G_DIR_SEPARATOR_S, fileName, NULL );
1967 1 hiro
        book->retVal = MGU_OPEN_FILE;
1968 1 hiro
        file = xml_open_file( fileSpec );
1969 1 hiro
        g_free( fileSpec );
1970 1 hiro
        if( file ) {
1971 1 hiro
                book->retVal = MGU_BAD_FORMAT;
1972 1 hiro
                if( setjmp( book->jumper ) ) {
1973 1 hiro
                        /* printf( "Caught Ya!!!\n" ); */
1974 1 hiro
                        xml_close_file( file );
1975 1 hiro
                        return book->retVal;
1976 1 hiro
                }
1977 1 hiro
                if( addrbook_chkread_tree( book, file ) ) {
1978 1 hiro
                        book->retVal = MGU_SUCCESS;
1979 1 hiro
                }
1980 1 hiro
                xml_close_file( file );
1981 1 hiro
        }
1982 1 hiro
        return book->retVal;
1983 1 hiro
}
1984 1 hiro
1985 1 hiro
/*
1986 1 hiro
* Return link list of all persons in address book.  Note that the list contains
1987 1 hiro
* references to items. Do *NOT* attempt to use the addrbook_free_xxx() functions...
1988 1 hiro
* this will destroy the addressbook data!
1989 1 hiro
* Return: List of items, or NULL if none.
1990 1 hiro
*/
1991 1 hiro
GList *addrbook_get_all_persons( AddressBookFile *book ) {
1992 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
1993 1 hiro
        return addrcache_get_all_persons( book->addressCache );
1994 1 hiro
}
1995 1 hiro
1996 1 hiro
/*
1997 1 hiro
* Add person and address data to address book.
1998 1 hiro
* Enter: book      Address book.
1999 1 hiro
*        folder    Folder where to add person, or NULL for root folder.
2000 1 hiro
*        name      Common name.
2001 1 hiro
*        address   EMail address.
2002 1 hiro
*        remarks   Remarks.
2003 1 hiro
* Return: Person added. Do not *NOT* to use the addrbook_free_xxx() functions...
2004 1 hiro
* this will destroy the address book data.
2005 1 hiro
*/
2006 1 hiro
ItemPerson *addrbook_add_contact( AddressBookFile *book, ItemFolder *folder, const gchar *name,
2007 1 hiro
                const gchar *address, const gchar *remarks )
2008 1 hiro
{
2009 1 hiro
        ItemPerson *person = NULL;
2010 1 hiro
2011 1 hiro
        g_return_val_if_fail( book != NULL, NULL );
2012 1 hiro
2013 1 hiro
        person = addrcache_add_contact( book->addressCache, folder, name, address, remarks );
2014 1 hiro
        if( person ) book->dirtyFlag = TRUE;
2015 1 hiro
        return person;
2016 1 hiro
}
2017 1 hiro
2018 1 hiro
/*
2019 1 hiro
* End of Source.
2020 1 hiro
*/