claws-mail/src/addrbook.c

2033 lines
55 KiB
C
Raw Normal View History

2001-09-02 01:48:06 +02:00
/*
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
2002-12-21 11:57:35 +01:00
* Copyright (C) 2001-2002 Match Grun and the Sylpheed-Claws team
2001-09-02 01:48:06 +02:00
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
2002-12-21 11:57:35 +01:00
/* General functions for accessing address book files */
2001-09-02 01:48:06 +02:00
#include <glib.h>
2001-09-06 12:24:20 +02:00
#include <stdio.h>
#include <stdlib.h>
2001-09-02 01:48:06 +02:00
#include <dirent.h>
#include <sys/stat.h>
#include <math.h>
#include <setjmp.h>
#include "xml.h"
#include "mgutils.h"
#include "addritem.h"
#include "addrcache.h"
#include "addrbook.h"
#include "adbookbase.h"
2001-09-02 01:48:06 +02:00
#ifndef DEV_STANDALONE
#include "prefs_gtk.h"
2001-09-06 12:24:20 +02:00
#include "codeconv.h"
2001-09-02 01:48:06 +02:00
#endif
#define ADDRBOOK_MAX_SEARCH_COUNT 1000
#define ADDRBOOK_PREFIX "addrbook-"
#define ADDRBOOK_SUFFIX ".xml"
#define FILE_NUMDIGITS 6
#define ID_TIME_OFFSET 998000000
2002-12-21 11:57:35 +01:00
/* Create new address book */
AddressBookFile *addrbook_create_book()
{
2001-09-02 01:48:06 +02:00
AddressBookFile *book;
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
book = g_new0(AddressBookFile, 1);
book->type = ADBOOKTYPE_BOOK;
book->addressCache = addrcache_create();
book->retVal = MGU_SUCCESS;
2001-09-02 01:48:06 +02:00
book->path = NULL;
book->fileName = NULL;
book->maxValue = 0;
2001-09-02 01:48:06 +02:00
book->tempList = NULL;
book->tempHash = NULL;
2002-03-16 07:10:46 +01:00
book->addressCache->modified = TRUE;
2003-03-17 07:49:25 +01:00
/* We want to use an address completion index */
addrcache_use_index( book->addressCache, TRUE );
2001-09-02 01:48:06 +02:00
return book;
}
2002-12-21 11:57:35 +01:00
/* Specify name to be used */
void addrbook_set_name(AddressBookFile *book, const gchar *value)
{
g_return_if_fail(book != NULL);
addrcache_set_name(book->addressCache, value);
}
2002-12-21 11:57:35 +01:00
gchar *addrbook_get_name(AddressBookFile *book)
{
g_return_val_if_fail(book != NULL, NULL);
return addrcache_get_name(book->addressCache);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
void addrbook_set_path(AddressBookFile *book, const gchar *value)
{
g_return_if_fail(book != NULL);
book->path = mgu_replace_string(book->path, value);
addrcache_set_dirty(book->addressCache, TRUE);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
void addrbook_set_file(AddressBookFile *book, const gchar *value)
{
g_return_if_fail(book != NULL);
book->fileName = mgu_replace_string(book->fileName, value);
addrcache_set_dirty(book->addressCache, TRUE);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
gboolean addrbook_get_modified(AddressBookFile *book)
{
g_return_val_if_fail(book != NULL, FALSE);
2002-03-16 07:10:46 +01:00
return book->addressCache->modified;
}
2002-12-21 11:57:35 +01:00
void addrbook_set_modified(AddressBookFile *book, const gboolean value)
{
g_return_if_fail(book != NULL);
2002-03-16 07:10:46 +01:00
book->addressCache->modified = value;
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
gboolean addrbook_get_accessed(AddressBookFile *book)
{
g_return_val_if_fail(book != NULL, FALSE);
2002-03-16 07:10:46 +01:00
return book->addressCache->accessFlag;
}
2002-12-21 11:57:35 +01:00
void addrbook_set_accessed(AddressBookFile *book, const gboolean value)
{
g_return_if_fail(book != NULL);
2002-03-16 07:10:46 +01:00
book->addressCache->accessFlag = value;
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
gboolean addrbook_get_read_flag(AddressBookFile *book)
{
g_return_val_if_fail(book != NULL, FALSE);
2002-03-16 07:10:46 +01:00
return book->addressCache->dataRead;
}
2002-12-21 11:57:35 +01:00
void addrbook_set_read_flag(AddressBookFile *book, const gboolean value)
{
g_return_if_fail(book != NULL);
2002-03-16 07:10:46 +01:00
book->addressCache->dataRead = value;
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
gint addrbook_get_status(AddressBookFile *book)
{
g_return_val_if_fail(book != NULL, -1);
2001-09-02 01:48:06 +02:00
return book->retVal;
}
2002-12-21 11:57:35 +01:00
ItemFolder *addrbook_get_root_folder(AddressBookFile *book)
{
g_return_val_if_fail(book != NULL, NULL);
return addrcache_get_root_folder(book->addressCache);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
GList *addrbook_get_list_folder(AddressBookFile *book)
{
g_return_val_if_fail(book != NULL, NULL);
return addrcache_get_list_folder(book->addressCache);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
GList *addrbook_get_list_person(AddressBookFile *book)
{
g_return_val_if_fail(book != NULL, NULL);
return addrcache_get_list_person(book->addressCache);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
gboolean addrbook_get_dirty(AddressBookFile *book)
{
g_return_val_if_fail(book != NULL, FALSE);
return addrcache_get_dirty(book->addressCache);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
void addrbook_set_dirty(AddressBookFile *book, const gboolean value)
{
g_return_if_fail(book != NULL);
addrcache_set_dirty(book->addressCache, value);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
/* Empty address book */
void addrbook_empty_book(AddressBookFile *book)
{
g_return_if_fail(book != NULL);
2001-09-02 01:48:06 +02:00
/* Free up internal objects */
2002-12-21 11:57:35 +01:00
addrcache_clear(book->addressCache);
addrcache_set_dirty(book->addressCache, FALSE);
g_list_free(book->tempList);
2001-09-02 01:48:06 +02:00
2001-09-27 10:16:30 +02:00
/* Reset to initial state */
book->tempList = NULL;
2001-09-02 01:48:06 +02:00
book->tempHash = NULL;
2002-03-16 07:10:46 +01:00
book->addressCache->dataRead = FALSE;
book->addressCache->modified = FALSE;
book->addressCache->accessFlag = FALSE;
book->retVal = MGU_SUCCESS;
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
/* Free address book */
void addrbook_free_book(AddressBookFile *book)
{
g_return_if_fail(book != NULL);
2001-09-02 01:48:06 +02:00
/* Clear cache */
2002-12-21 11:57:35 +01:00
addrcache_free(book->addressCache);
/* Free up internal objects */
2002-12-21 11:57:35 +01:00
g_free(book->path);
g_free(book->fileName);
g_list_free(book->tempList);
2001-09-02 01:48:06 +02:00
book->path = NULL;
book->fileName = NULL;
book->maxValue = 0;
2001-09-02 01:48:06 +02:00
book->tempList = NULL;
book->tempHash = NULL;
book->type = ADBOOKTYPE_NONE;
book->addressCache = NULL;
book->retVal = MGU_SUCCESS;
2001-09-02 01:48:06 +02:00
2002-12-21 11:57:35 +01:00
g_free(book);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
/* Print list of items */
void addrbook_print_item_list(GList *list, FILE *stream)
{
2001-09-02 01:48:06 +02:00
GList *node = list;
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
while(node) {
2001-09-02 01:48:06 +02:00
AddrItemObject *obj = node->data;
2002-12-21 11:57:35 +01:00
if (ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON)
addritem_print_item_person((ItemPerson *) obj, stream);
else if (ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP)
addritem_print_item_group((ItemGroup *) obj, stream);
else if (ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER)
addritem_print_item_folder((ItemFolder *) obj, stream);
node = g_list_next(node);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
fprintf(stream, "\t---\n");
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
/* Print address book */
void addrbook_print_book(AddressBookFile *book, FILE *stream)
{
g_return_if_fail(book != NULL);
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
fprintf(stream, "AddressBook:\n");
2003-03-17 07:49:25 +01:00
fprintf(stream, "\tpath : '%s'\n", book->path);
fprintf(stream, "\tfile : '%s'\n", book->fileName);
fprintf(stream, "\tstatus : %d\n", book->retVal );
2002-12-21 11:57:35 +01:00
addrcache_print(book->addressCache, stream);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
/* Dump entire address book traversing folders */
void addrbook_dump_book(AddressBookFile *book, FILE *stream)
{
2001-09-02 01:48:06 +02:00
ItemFolder *folder;
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
g_return_if_fail(book != NULL);
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
addrbook_print_book(book, stream);
2001-09-02 01:48:06 +02:00
folder = book->addressCache->rootFolder;
2002-12-21 11:57:35 +01:00
addritem_print_item_folder(folder, stream);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
/* Remove group from address book.
param: group Group to remove.
return: Group, or NULL if not found.
Note that object should still be freed */
ItemGroup *addrbook_remove_group(AddressBookFile *book, ItemGroup *group)
{
g_return_val_if_fail(book != NULL, NULL);
return addrcache_remove_group(book->addressCache, group);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
/* Remove specified person from address book.
param: person Person to remove.
return: Person, or NULL if not found.
Note that object should still be freed */
ItemPerson *addrbook_remove_person(AddressBookFile *book, ItemPerson *person)
{
g_return_val_if_fail(book != NULL, NULL);
return addrcache_remove_person(book->addressCache, person);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
/* Remove email address in address book for specified person.
param: person Person.
email EMail to remove.
return: EMail object, or NULL if not found.
Note that object should still be freed */
ItemEMail *addrbook_person_remove_email(AddressBookFile *book,
ItemPerson *person, ItemEMail *email)
{
g_return_val_if_fail(book != NULL, NULL);
return addrcache_person_remove_email(book->addressCache, person, email);
2001-09-02 01:48:06 +02:00
}
/* **********************************************************************
* Read/Write XML data file...
* ===========================
* Notes:
* 1) The address book is structured as follows:
*
* address-book
* person
* address-list
* address
* attribute-list
* attribute
* group
* member-list
* member
* folder
* item-list
* item
*
* 2) This sequence of elements was chosen so that the most important
* elements (person and their email addresses) appear first.
*
* 3) Groups then appear. When groups are loaded, person's email
* addresses have already been loaded and can be found.
*
* 4) Finally folders are loaded. Any forward and backward references
* to folders, groups and persons in the folders are resolved after
* loading.
*
* ***********************************************************************
*/
2001-09-27 10:16:30 +02:00
/* Element tag names */
2001-09-02 01:48:06 +02:00
#define AB_ELTAG_ADDRESS "address"
#define AB_ELTAG_ATTRIBUTE "attribute"
#define AB_ELTAG_ATTRIBUTE_LIST "attribute-list"
#define AB_ELTAG_ADDRESS_LIST "address-list"
#define AB_ELTAG_MEMBER "member"
#define AB_ELTAG_MEMBER_LIST "member-list"
#define AB_ELTAG_ITEM "item"
#define AB_ELTAG_ITEM_LIST "item-list"
#define AB_ELTAG_ADDRESS_BOOK "address-book"
#define AB_ELTAG_PERSON "person"
#define AB_ELTAG_GROUP "group"
#define AB_ELTAG_FOLDER "folder"
2001-09-30 13:07:34 +02:00
/* Attribute tag names */
2001-09-02 01:48:06 +02:00
#define AB_ATTAG_TYPE "type"
#define AB_ATTAG_UID "uid"
#define AB_ATTAG_NAME "name"
#define AB_ATTAG_REMARKS "remarks"
#define AB_ATTAG_FIRST_NAME "first-name"
#define AB_ATTAG_LAST_NAME "last-name"
#define AB_ATTAG_NICK_NAME "nick-name"
#define AB_ATTAG_COMMON_NAME "cn"
#define AB_ATTAG_ALIAS "alias"
#define AB_ATTAG_EMAIL "email"
#define AB_ATTAG_EID "eid"
#define AB_ATTAG_PID "pid"
2001-09-27 10:16:30 +02:00
/* Attribute values */
2001-09-02 01:48:06 +02:00
#define AB_ATTAG_VAL_PERSON "person"
#define AB_ATTAG_VAL_GROUP "group"
#define AB_ATTAG_VAL_FOLDER "folder"
2002-12-21 11:57:35 +01:00
/* Parse address item for person */
static void addrbook_parse_address(AddressBookFile *book, XMLFile *file,
ItemPerson *person)
{
2001-09-02 01:48:06 +02:00
GList *attr;
gchar *name, *value;
ItemEMail *email = NULL;
attr = xml_get_current_tag_attr(file);
2002-12-21 11:57:35 +01:00
while (attr) {
2001-09-02 01:48:06 +02:00
name = ((XMLAttr *)attr->data)->name;
value = ((XMLAttr *)attr->data)->value;
2002-12-21 11:57:35 +01:00
if (!email)
email = addritem_create_item_email();
if (strcmp(name, AB_ATTAG_UID) == 0)
ADDRITEM_ID(email) = g_strdup(value);
else if (strcmp(name, AB_ATTAG_ALIAS) == 0)
ADDRITEM_NAME(email) = g_strdup(value);
else if (strcmp(name, AB_ATTAG_EMAIL) == 0)
email->address = g_strdup(value);
else if (strcmp(name, AB_ATTAG_REMARKS) == 0)
email->remarks = g_strdup(value);
attr = g_list_next(attr);
}
if (email) {
if (person) {
addrcache_person_add_email(book->addressCache, person,
email);
2001-09-02 01:48:06 +02:00
}
else {
2002-12-21 11:57:35 +01:00
addritem_free_item_email(email);
2001-09-02 01:48:06 +02:00
email = NULL;
}
}
}
2002-12-21 11:57:35 +01:00
/* Parse email address list */
static void addrbook_parse_addr_list(AddressBookFile *book, XMLFile *file,
ItemPerson *person)
{
2001-09-02 01:48:06 +02:00
GList *attr;
guint prev_level;
for (;;) {
prev_level = file->level;
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file)) {
longjmp(book->jumper, 1);
2001-09-02 01:48:06 +02:00
}
if (file->level < prev_level) return;
2002-12-21 11:57:35 +01:00
if (xml_compare_tag(file, AB_ELTAG_ADDRESS)) {
2001-09-02 01:48:06 +02:00
attr = xml_get_current_tag_attr(file);
2002-12-21 11:57:35 +01:00
addrbook_parse_address(book, file, person);
addrbook_parse_addr_list(book, file, person);
2001-09-02 01:48:06 +02:00
}
}
}
2002-12-21 11:57:35 +01:00
/* Parse attibute for person */
static void addrbook_parse_attribute(XMLFile *file, ItemPerson *person)
{
2001-09-02 01:48:06 +02:00
GList *attr;
gchar *name, *value;
gchar *element;
UserAttribute *uAttr = NULL;
attr = xml_get_current_tag_attr(file);
2002-12-21 11:57:35 +01:00
while (attr) {
2001-09-02 01:48:06 +02:00
name = ((XMLAttr *)attr->data)->name;
value = ((XMLAttr *)attr->data)->value;
2002-12-21 11:57:35 +01:00
if (!uAttr) uAttr = addritem_create_attribute();
if (strcmp(name, AB_ATTAG_UID) == 0)
addritem_attrib_set_id(uAttr, value);
else if (strcmp(name, AB_ATTAG_NAME) == 0)
addritem_attrib_set_name(uAttr, value);
attr = g_list_next(attr);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
element = xml_get_element(file);
addritem_attrib_set_value(uAttr, element);
2001-09-02 01:48:06 +02:00
2002-12-21 11:57:35 +01:00
if (uAttr) {
if (person) {
addritem_person_add_attribute(person, uAttr);
2001-09-02 01:48:06 +02:00
}
else {
2002-12-21 11:57:35 +01:00
addritem_free_attribute(uAttr);
2001-09-02 01:48:06 +02:00
uAttr = NULL;
}
}
}
2002-12-21 11:57:35 +01:00
/* Parse attribute list */
static void addrbook_parse_attr_list(AddressBookFile *book, XMLFile *file,
ItemPerson *person)
{
2001-09-02 01:48:06 +02:00
GList *attr;
guint prev_level;
for (;;) {
prev_level = file->level;
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file)) {
2001-09-02 01:48:06 +02:00
longjmp( book->jumper, 1 );
}
if (file->level < prev_level) return;
2002-12-21 11:57:35 +01:00
if (xml_compare_tag(file, AB_ELTAG_ATTRIBUTE)) {
2001-09-02 01:48:06 +02:00
attr = xml_get_current_tag_attr(file);
2002-12-21 11:57:35 +01:00
addrbook_parse_attribute(file, person);
addrbook_parse_attr_list(book, file, person);
2001-09-02 01:48:06 +02:00
}
}
}
2002-12-21 11:57:35 +01:00
/* Parse person */
static void addrbook_parse_person(AddressBookFile *book, XMLFile *file)
{
2001-09-02 01:48:06 +02:00
GList *attr;
gchar *name, *value;
ItemPerson *person = NULL;
attr = xml_get_current_tag_attr(file);
2002-12-21 11:57:35 +01:00
while (attr) {
2001-09-02 01:48:06 +02:00
name = ((XMLAttr *)attr->data)->name;
value = ((XMLAttr *)attr->data)->value;
2002-12-21 11:57:35 +01:00
if (!person)
person = addritem_create_item_person();
if (strcmp(name, AB_ATTAG_UID) == 0)
ADDRITEM_ID(person) = g_strdup(value);
else if (strcmp(name, AB_ATTAG_FIRST_NAME) == 0)
person->firstName = g_strdup(value);
else if (strcmp(name, AB_ATTAG_LAST_NAME) == 0)
person->lastName = g_strdup(value);
else if (strcmp(name, AB_ATTAG_NICK_NAME) == 0)
person->nickName = g_strdup(value);
else if (strcmp(name, AB_ATTAG_COMMON_NAME) == 0)
ADDRITEM_NAME(person) = g_strdup(value);
attr = g_list_next(attr);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file)) { /* Consume closing tag */
longjmp(book->jumper, 1);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
if (xml_compare_tag(file, AB_ELTAG_ADDRESS_LIST)) {
addrbook_parse_addr_list(book, file, person);
if (person) {
addrcache_hash_add_person(book->addressCache, person);
2001-09-02 01:48:06 +02:00
}
}
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file)) { /* Consume closing tag */
longjmp(book->jumper, 1);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
if (xml_compare_tag(file, AB_ELTAG_ATTRIBUTE_LIST)) {
addrbook_parse_attr_list(book, file, person);
2001-09-02 01:48:06 +02:00
}
}
2002-12-21 11:57:35 +01:00
/* Parse group member */
static void addrbook_parse_member(AddressBookFile *book, XMLFile *file,
ItemGroup *group)
{
2001-09-02 01:48:06 +02:00
GList *attr;
gchar *name, *value;
gchar *pid = NULL, *eid = NULL;
ItemEMail *email = NULL;
attr = xml_get_current_tag_attr(file);
2002-12-21 11:57:35 +01:00
while (attr) {
2001-09-02 01:48:06 +02:00
name = ((XMLAttr *)attr->data)->name;
value = ((XMLAttr *)attr->data)->value;
2002-12-21 11:57:35 +01:00
if (strcmp(name, AB_ATTAG_PID) == 0)
pid = g_strdup(value);
else if (strcmp(name, AB_ATTAG_EID) == 0)
eid = g_strdup(value);
attr = g_list_next(attr);
2001-09-02 01:48:06 +02:00
}
/* email = addrcache_get_email( book->addressCache, pid, eid ); */
2002-12-21 11:57:35 +01:00
email = addrcache_get_email(book->addressCache, eid);
if (email) {
if (group) {
addrcache_group_add_email(book->addressCache, group,
email);
2001-09-02 01:48:06 +02:00
}
else {
2002-12-21 11:57:35 +01:00
addritem_free_item_email(email);
2001-09-02 01:48:06 +02:00
email = NULL;
}
}
}
2002-12-21 11:57:35 +01:00
/* Parse group member list */
static void addrbook_parse_member_list(AddressBookFile *book, XMLFile *file,
ItemGroup *group)
{
2001-09-02 01:48:06 +02:00
GList *attr;
guint prev_level;
for (;;) {
prev_level = file->level;
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file)) {
longjmp(book->jumper, 1);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
if (file->level < prev_level)
return;
if (xml_compare_tag(file, AB_ELTAG_MEMBER)) {
2001-09-02 01:48:06 +02:00
attr = xml_get_current_tag_attr(file);
2002-12-21 11:57:35 +01:00
addrbook_parse_member(book, file, group);
addrbook_parse_member_list(book, file, group);
2001-09-02 01:48:06 +02:00
}
else {
2002-12-21 11:57:35 +01:00
attr = xml_get_current_tag_attr(file);
2001-09-02 01:48:06 +02:00
}
}
}
2002-12-21 11:57:35 +01:00
/* Parse group */
static void addrbook_parse_group(AddressBookFile *book, XMLFile *file)
{
2001-09-02 01:48:06 +02:00
GList *attr;
gchar *name, *value;
ItemGroup *group = NULL;
attr = xml_get_current_tag_attr(file);
2002-12-21 11:57:35 +01:00
while (attr) {
2001-09-02 01:48:06 +02:00
name = ((XMLAttr *)attr->data)->name;
value = ((XMLAttr *)attr->data)->value;
2002-12-21 11:57:35 +01:00
if (!group)
group = addritem_create_item_group();
if (strcmp(name, AB_ATTAG_UID) == 0)
ADDRITEM_ID(group) = g_strdup(value);
else if (strcmp(name, AB_ATTAG_NAME) == 0)
ADDRITEM_NAME(group) = g_strdup(value);
else if (strcmp(name, AB_ATTAG_REMARKS) == 0)
group->remarks = g_strdup(value);
attr = g_list_next(attr);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file)) { /* Consume closing tag */
longjmp(book->jumper, 1);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
if (xml_compare_tag(file, AB_ELTAG_MEMBER_LIST)) {
if (group) {
addrcache_hash_add_group(book->addressCache, group);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
addrbook_parse_member_list(book, file, group);
2001-09-02 01:48:06 +02:00
}
}
2002-12-21 11:57:35 +01:00
/* Parse folder item */
static void addrbook_parse_folder_item(AddressBookFile *book, XMLFile *file,
ItemFolder *folder)
{
2001-09-02 01:48:06 +02:00
GList *attr;
gchar *name, *value;
gchar *uid = NULL;
attr = xml_get_current_tag_attr(file);
2002-12-21 11:57:35 +01:00
while (attr) {
2001-09-02 01:48:06 +02:00
name = ((XMLAttr *)attr->data)->name;
value = ((XMLAttr *)attr->data)->value;
2002-12-21 11:57:35 +01:00
if (strcmp(name, AB_ATTAG_UID) == 0) {
uid = g_strdup(value);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
attr = g_list_next(attr);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
if (folder) {
if (uid) {
folder->listItems = g_list_append(folder->listItems, uid);
2001-09-02 01:48:06 +02:00
}
}
}
2002-12-21 11:57:35 +01:00
/* Parse folder item list */
static void addrbook_parse_folder_list(AddressBookFile *book, XMLFile *file,
ItemFolder *folder)
{
2001-09-02 01:48:06 +02:00
GList *attr;
guint prev_level;
for (;;) {
prev_level = file->level;
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file)) {
longjmp(book->jumper, 1);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
if (file->level < prev_level)
return;
if (xml_compare_tag(file, AB_ELTAG_ITEM)) {
2001-09-02 01:48:06 +02:00
attr = xml_get_current_tag_attr(file);
2002-12-21 11:57:35 +01:00
addrbook_parse_folder_item(book, file, folder);
addrbook_parse_folder_list(book, file, folder);
2001-09-02 01:48:06 +02:00
}
else {
2002-12-21 11:57:35 +01:00
attr = xml_get_current_tag_attr(file);
2001-09-02 01:48:06 +02:00
}
}
}
2002-12-21 11:57:35 +01:00
/* Parse folder */
static void addrbook_parse_folder(AddressBookFile *book, XMLFile *file)
{
2001-09-02 01:48:06 +02:00
GList *attr;
gchar *name, *value;
ItemFolder *folder = NULL;
attr = xml_get_current_tag_attr(file);
2002-12-21 11:57:35 +01:00
while (attr) {
2001-09-02 01:48:06 +02:00
name = ((XMLAttr *)attr->data)->name;
value = ((XMLAttr *)attr->data)->value;
2002-12-21 11:57:35 +01:00
if (!folder)
2001-09-02 01:48:06 +02:00
folder = addritem_create_item_folder();
2002-12-21 11:57:35 +01:00
if (strcmp(name, AB_ATTAG_UID) == 0)
ADDRITEM_ID(folder) = g_strdup(value);
else if (strcmp(name, AB_ATTAG_NAME) == 0)
ADDRITEM_NAME(folder) = g_strdup(value);
else if (strcmp(name, AB_ATTAG_REMARKS) == 0)
folder->remarks = g_strdup(value);
attr = g_list_next(attr);
}
if (xml_parse_next_tag(file)) { /* Consume closing tag */
longjmp(book->jumper, 1);
}
if (xml_compare_tag(file, AB_ELTAG_ITEM_LIST)) {
if (folder) {
if (addrcache_hash_add_folder(book->addressCache,
folder)) {
book->tempList = g_list_append(book->tempList,
folder);
/* We will resolve folder later */
ADDRITEM_PARENT(folder) = NULL;
2001-09-02 01:48:06 +02:00
}
}
2002-12-21 11:57:35 +01:00
addrbook_parse_folder_list(book, file, folder);
2001-09-02 01:48:06 +02:00
}
}
2002-12-21 11:57:35 +01:00
/* Parse address book.
Return: TRUE if data read successfully, FALSE if error reading data */
static gboolean addrbook_read_tree(AddressBookFile *book, XMLFile *file)
{
2001-09-02 01:48:06 +02:00
gboolean retVal;
GList *attr;
gchar *name, *value;
book->retVal = MGU_BAD_FORMAT;
2002-12-21 11:57:35 +01:00
if (xml_get_dtd(file))
2001-09-02 01:48:06 +02:00
return FALSE;
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file))
longjmp(book->jumper, 1);
if (!xml_compare_tag(file, AB_ELTAG_ADDRESS_BOOK))
2001-09-02 01:48:06 +02:00
return FALSE;
attr = xml_get_current_tag_attr(file);
2002-12-21 11:57:35 +01:00
while (attr) {
2001-09-02 01:48:06 +02:00
name = ((XMLAttr *)attr->data)->name;
value = ((XMLAttr *)attr->data)->value;
2002-12-21 11:57:35 +01:00
if (strcmp( name, AB_ATTAG_NAME) == 0)
2001-09-02 01:48:06 +02:00
addrbook_set_name( book, value );
attr = g_list_next( attr );
}
retVal = TRUE;
for (;;) {
2002-12-21 11:57:35 +01:00
if (!file->level)
break;
2001-09-27 10:16:30 +02:00
/* Get next item tag (person, group or folder) */
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file))
2001-09-02 01:48:06 +02:00
longjmp( book->jumper, 1 );
2002-12-21 11:57:35 +01:00
if (xml_compare_tag(file, AB_ELTAG_PERSON))
addrbook_parse_person(book, file);
else if (xml_compare_tag(file, AB_ELTAG_GROUP))
addrbook_parse_group(book, file);
else if (xml_compare_tag(file, AB_ELTAG_FOLDER))
addrbook_parse_folder(book, file);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
if (retVal) book->retVal = MGU_SUCCESS;
return retVal;
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
/* Resolve folder items visitor function */
static void addrbook_res_items_vis(gpointer key, gpointer value, gpointer data)
{
2001-09-02 01:48:06 +02:00
AddressBookFile *book = data;
2002-12-21 11:57:35 +01:00
AddrItemObject *obj = (AddrItemObject *) value;
2001-09-02 01:48:06 +02:00
ItemFolder *rootFolder = book->addressCache->rootFolder;
2002-12-21 11:57:35 +01:00
if (obj->parent == NULL) {
if (ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON) {
rootFolder->listPerson = g_list_append(rootFolder->listPerson,
obj);
2001-09-02 01:48:06 +02:00
ADDRITEM_PARENT(obj) = ADDRITEM_OBJECT(rootFolder);
}
2002-12-21 11:57:35 +01:00
else if (ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP) {
rootFolder->listGroup = g_list_append(rootFolder->listGroup,
obj);
2001-09-02 01:48:06 +02:00
ADDRITEM_PARENT(obj) = ADDRITEM_OBJECT(rootFolder);
}
}
}
2002-12-21 11:57:35 +01:00
/* Resolve folder items. Lists of UID's are replaced with pointers to
data items */
static void addrbook_resolve_folder_items(AddressBookFile *book)
{
2001-09-02 01:48:06 +02:00
GList *nodeFolder = NULL;
GList *listRemove = NULL;
GList *node = NULL;
ItemFolder *rootFolder = book->addressCache->rootFolder;
nodeFolder = book->tempList;
2002-12-21 11:57:35 +01:00
while (nodeFolder) {
2001-09-02 01:48:06 +02:00
ItemFolder *folder = nodeFolder->data;
listRemove = NULL;
node = folder->listItems;
2002-12-21 11:57:35 +01:00
while (node) {
2001-09-02 01:48:06 +02:00
gchar *uid = node->data;
2002-12-21 11:57:35 +01:00
AddrItemObject *aio = addrcache_get_object(book->addressCache,
uid);
if (aio) {
if (aio->type == ITEMTYPE_FOLDER) {
ItemFolder *item = (ItemFolder *) aio;
folder->listFolder = g_list_append(folder->listFolder, item);
2001-09-02 01:48:06 +02:00
ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder);
2002-12-21 11:57:35 +01:00
addrcache_hash_add_folder(book->addressCache, folder);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
else if (aio->type == ITEMTYPE_PERSON) {
ItemPerson *item = (ItemPerson *) aio;
folder->listPerson = g_list_append(folder->listPerson, item);
2001-09-02 01:48:06 +02:00
ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder);
}
2002-12-21 11:57:35 +01:00
else if (aio->type == ITEMTYPE_GROUP) {
ItemGroup *item = (ItemGroup *) aio;
folder->listGroup = g_list_append(folder->listGroup, item);
2001-09-02 01:48:06 +02:00
ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder);
}
2001-09-27 10:16:30 +02:00
/* Replace data with pointer to item */
2002-12-21 11:57:35 +01:00
g_free(uid);
2001-09-02 01:48:06 +02:00
node->data = aio;
}
2002-12-21 11:57:35 +01:00
else { /* Not found, append to remove list. */
listRemove = g_list_append(listRemove, uid);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
node = g_list_next(node);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
rootFolder->listFolder = g_list_append(rootFolder->listFolder,
folder);
2001-09-27 10:16:30 +02:00
/* Process remove list */
2001-09-02 01:48:06 +02:00
node = listRemove;
2002-12-21 11:57:35 +01:00
while (node) {
2001-09-02 01:48:06 +02:00
gchar *uid = node->data;
2002-12-21 11:57:35 +01:00
folder->listItems = g_list_remove(folder->listItems,
uid);
g_free(uid);
node = g_list_next(node);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
g_list_free(listRemove);
nodeFolder = g_list_next(nodeFolder);
2001-09-02 01:48:06 +02:00
}
2001-09-27 10:16:30 +02:00
/* Remove folders with parents. */
2001-09-02 01:48:06 +02:00
listRemove = NULL;
node = rootFolder->listFolder;
2002-12-21 11:57:35 +01:00
while (node) {
ItemFolder *folder = (ItemFolder *) node->data;
if (ADDRITEM_PARENT(folder))
2001-09-27 10:16:30 +02:00
/* Remove folders with parents */
2002-12-21 11:57:35 +01:00
listRemove = g_list_append(listRemove, folder);
else /* Add to root folder */
2001-09-02 01:48:06 +02:00
ADDRITEM_PARENT(folder) = ADDRITEM_OBJECT(book->addressCache->rootFolder);
2002-12-21 11:57:35 +01:00
2001-09-02 01:48:06 +02:00
node = g_list_next( node );
}
2001-09-27 10:16:30 +02:00
/* Process remove list */
2001-09-02 01:48:06 +02:00
node = listRemove;
2002-12-21 11:57:35 +01:00
while (node) {
rootFolder->listFolder = g_list_remove(rootFolder->listFolder,
node->data);
node = g_list_next(node);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
g_list_free(listRemove);
2001-09-02 01:48:06 +02:00
2001-09-27 10:16:30 +02:00
/* Move all unparented persons and groups into root folder */
2002-12-21 11:57:35 +01:00
g_hash_table_foreach(book->addressCache->itemHash,
addrbook_res_items_vis, book);
2001-09-02 01:48:06 +02:00
2001-09-27 10:16:30 +02:00
/* Free up some more */
2001-09-02 01:48:06 +02:00
nodeFolder = book->tempList;
2002-12-21 11:57:35 +01:00
while (nodeFolder) {
2001-09-02 01:48:06 +02:00
ItemFolder *folder = nodeFolder->data;
2002-12-21 11:57:35 +01:00
g_list_free(folder->listItems);
2001-09-02 01:48:06 +02:00
folder->listItems = NULL;
2002-12-21 11:57:35 +01:00
nodeFolder = g_list_next(nodeFolder);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
g_list_free(book->tempList);
2001-09-02 01:48:06 +02:00
book->tempList = NULL;
}
2002-12-21 11:57:35 +01:00
/* Read address book file */
gint addrbook_read_data(AddressBookFile *book)
{
2001-09-02 01:48:06 +02:00
XMLFile *file = NULL;
gchar *fileSpec = NULL;
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
g_return_val_if_fail(book != NULL, -1);
2001-09-02 01:48:06 +02:00
2002-03-16 07:10:46 +01:00
/*
printf( "...addrbook_read_data :%s:\t:%s:\n", book->fileName,
addrcache_get_name( book->addressCache ) );
*/
2002-12-21 11:57:35 +01:00
fileSpec = g_strconcat(book->path, G_DIR_SEPARATOR_S,
book->fileName, NULL);
2001-09-02 01:48:06 +02:00
book->retVal = MGU_OPEN_FILE;
2002-12-21 11:57:35 +01:00
addrcache_clear(book->addressCache);
2002-03-16 07:10:46 +01:00
book->addressCache->modified = FALSE;
book->addressCache->accessFlag = FALSE;
2002-12-21 11:57:35 +01:00
file = xml_open_file(fileSpec);
g_free(fileSpec);
if (file) {
2001-09-02 01:48:06 +02:00
book->tempList = NULL;
2001-09-27 10:16:30 +02:00
/* Trap for parsing errors. */
2002-12-21 11:57:35 +01:00
if (setjmp( book->jumper)) {
xml_close_file(file);
2001-09-02 01:48:06 +02:00
return book->retVal;
}
2002-12-21 11:57:35 +01:00
addrbook_read_tree(book, file);
xml_close_file(file);
2001-09-27 10:16:30 +02:00
/* Resolve folder items */
2002-12-21 11:57:35 +01:00
addrbook_resolve_folder_items(book);
2001-09-02 01:48:06 +02:00
book->tempList = NULL;
2002-03-16 07:10:46 +01:00
book->addressCache->modified = FALSE;
book->addressCache->dataRead = TRUE;
2002-12-21 11:57:35 +01:00
addrcache_set_dirty(book->addressCache, FALSE);
2003-03-17 07:49:25 +01:00
/* Build address completion index */
addrcache_build_index( book->addressCache );
2001-09-02 01:48:06 +02:00
}
return book->retVal;
}
2002-12-21 11:57:35 +01:00
static void addrbook_write_elem_s(FILE *fp, gint lvl, gchar *name)
{
2001-09-02 01:48:06 +02:00
gint i;
2002-12-21 11:57:35 +01:00
for (i = 0; i < lvl; i++)
fputs(" ", fp);
fputs("<", fp);
fputs(name, fp);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
static void addrbook_write_elem_e(FILE *fp, gint lvl, gchar *name)
{
2001-09-02 01:48:06 +02:00
gint i;
2002-12-21 11:57:35 +01:00
for(i = 0; i < lvl; i++)
fputs(" ", fp);
fputs("</", fp);
fputs(name, fp);
fputs(">\n", fp);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
static void addrbook_write_attr(FILE *fp, gchar *name, gchar *value)
{
fputs(" ", fp);
fputs(name, fp);
fputs("=\"", fp);
xml_file_put_escape_str(fp, value);
fputs("\"", fp);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
/* Write file hash table visitor function */
static void addrbook_write_item_person_vis(gpointer key, gpointer value,
gpointer data)
{
AddrItemObject *obj = (AddrItemObject *) value;
FILE *fp = (FILE *) data;
2001-09-02 01:48:06 +02:00
GList *node;
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
if (!obj)
return;
if (ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON) {
ItemPerson *person = (ItemPerson *) value;
if (person) {
addrbook_write_elem_s(fp, 1, AB_ELTAG_PERSON);
addrbook_write_attr(fp, AB_ATTAG_UID, ADDRITEM_ID(person));
addrbook_write_attr(fp, AB_ATTAG_FIRST_NAME, person->firstName);
addrbook_write_attr(fp, AB_ATTAG_LAST_NAME, person->lastName);
addrbook_write_attr(fp, AB_ATTAG_NICK_NAME, person->nickName);
addrbook_write_attr(fp, AB_ATTAG_COMMON_NAME, ADDRITEM_NAME(person));
fputs(" >\n", fp);
2001-09-02 01:48:06 +02:00
2001-09-27 10:16:30 +02:00
/* Output email addresses */
2002-12-21 11:57:35 +01:00
addrbook_write_elem_s(fp, 2, AB_ELTAG_ADDRESS_LIST);
fputs(">\n", fp);
2001-09-02 01:48:06 +02:00
node = person->listEMail;
2002-12-21 11:57:35 +01:00
while (node) {
2001-09-02 01:48:06 +02:00
ItemEMail *email = node->data;
2002-12-21 11:57:35 +01:00
addrbook_write_elem_s(fp, 3, AB_ELTAG_ADDRESS);
addrbook_write_attr(fp, AB_ATTAG_UID, ADDRITEM_ID(email));
addrbook_write_attr(fp, AB_ATTAG_ALIAS, ADDRITEM_NAME(email));
addrbook_write_attr(fp, AB_ATTAG_EMAIL, email->address);
addrbook_write_attr(fp, AB_ATTAG_REMARKS, email->remarks);
fputs(" />\n", fp);
node = g_list_next(node);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
addrbook_write_elem_e(fp, 2, AB_ELTAG_ADDRESS_LIST);
2001-09-02 01:48:06 +02:00
2001-09-27 10:16:30 +02:00
/* Output user attributes */
2002-12-21 11:57:35 +01:00
addrbook_write_elem_s(fp, 2, AB_ELTAG_ATTRIBUTE_LIST);
fputs(">\n", fp);
2001-09-02 01:48:06 +02:00
node = person->listAttrib;
2002-12-21 11:57:35 +01:00
while (node) {
2001-09-02 01:48:06 +02:00
UserAttribute *attrib = node->data;
2002-12-21 11:57:35 +01:00
addrbook_write_elem_s(fp, 3, AB_ELTAG_ATTRIBUTE);
addrbook_write_attr(fp, AB_ATTAG_UID, attrib->uid);
addrbook_write_attr(fp, AB_ATTAG_NAME, attrib->name);
fputs(" >", fp);
xml_file_put_escape_str(fp, attrib->value);
addrbook_write_elem_e(fp, 0, AB_ELTAG_ATTRIBUTE);
node = g_list_next(node);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
addrbook_write_elem_e(fp, 2, AB_ELTAG_ATTRIBUTE_LIST);
addrbook_write_elem_e(fp, 1, AB_ELTAG_PERSON);
2001-09-02 01:48:06 +02:00
}
}
}
2002-12-21 11:57:35 +01:00
/* Write file hash table visitor function */
static void addrbook_write_item_group_vis(gpointer key, gpointer value,
gpointer data)
{
AddrItemObject *obj = (AddrItemObject *) value;
FILE *fp = (FILE *) data;
2001-09-02 01:48:06 +02:00
GList *node;
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
if (!obj)
return;
if (ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP) {
ItemGroup *group = (ItemGroup *) value;
if (group) {
addrbook_write_elem_s(fp, 1, AB_ELTAG_GROUP);
addrbook_write_attr(fp, AB_ATTAG_UID, ADDRITEM_ID(group));
addrbook_write_attr(fp, AB_ATTAG_NAME, ADDRITEM_NAME(group));
addrbook_write_attr(fp, AB_ATTAG_REMARKS, group->remarks);
fputs(" >\n", fp);
2001-09-02 01:48:06 +02:00
2001-09-27 10:16:30 +02:00
/* Output email address links */
2002-12-21 11:57:35 +01:00
addrbook_write_elem_s(fp, 2, AB_ELTAG_MEMBER_LIST);
fputs(">\n", fp);
2001-09-02 01:48:06 +02:00
node = group->listEMail;
2002-12-21 11:57:35 +01:00
while (node) {
2001-09-02 01:48:06 +02:00
ItemEMail *email = node->data;
2002-12-21 11:57:35 +01:00
ItemPerson *person = (ItemPerson *) ADDRITEM_PARENT(email);
addrbook_write_elem_s(fp, 3, AB_ELTAG_MEMBER);
addrbook_write_attr(fp, AB_ATTAG_PID, ADDRITEM_ID(person));
addrbook_write_attr(fp, AB_ATTAG_EID, ADDRITEM_ID(email));
fputs(" />\n", fp);
node = g_list_next(node);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
addrbook_write_elem_e(fp, 2, AB_ELTAG_MEMBER_LIST);
addrbook_write_elem_e(fp, 1, AB_ELTAG_GROUP);
2001-09-02 01:48:06 +02:00
}
}
}
2002-12-21 11:57:35 +01:00
/* Write file hash table visitor function */
static void addrbook_write_item_folder_vis(gpointer key, gpointer value,
gpointer data)
{
AddrItemObject *obj = (AddrItemObject *) value;
FILE *fp = (FILE *) data;
2001-09-02 01:48:06 +02:00
GList *node;
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
if (!obj)
return;
if (ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER) {
ItemFolder *folder = (ItemFolder *) value;
if (folder) {
addrbook_write_elem_s(fp, 1, AB_ELTAG_FOLDER);
addrbook_write_attr(fp, AB_ATTAG_UID, ADDRITEM_ID(folder));
addrbook_write_attr(fp, AB_ATTAG_NAME, ADDRITEM_NAME(folder));
addrbook_write_attr(fp, AB_ATTAG_REMARKS, folder->remarks);
fputs(" >\n", fp);
addrbook_write_elem_s(fp, 2, AB_ELTAG_ITEM_LIST);
fputs(">\n", fp);
2001-09-02 01:48:06 +02:00
2001-09-27 10:16:30 +02:00
/* Output persons */
2001-09-02 01:48:06 +02:00
node = folder->listPerson;
2002-12-21 11:57:35 +01:00
while (node) {
2001-09-02 01:48:06 +02:00
ItemPerson *item = node->data;
2002-12-21 11:57:35 +01:00
addrbook_write_elem_s(fp, 3, AB_ELTAG_ITEM);
addrbook_write_attr(fp, AB_ATTAG_TYPE, AB_ATTAG_VAL_PERSON);
addrbook_write_attr(fp, AB_ATTAG_UID, ADDRITEM_ID(item));
fputs(" />\n", fp);
node = g_list_next(node);
2001-09-02 01:48:06 +02:00
}
2001-09-27 10:16:30 +02:00
/* Output groups */
2001-09-02 01:48:06 +02:00
node = folder->listGroup;
2002-12-21 11:57:35 +01:00
while (node) {
2001-09-02 01:48:06 +02:00
ItemGroup *item = node->data;
2002-12-21 11:57:35 +01:00
addrbook_write_elem_s(fp, 3, AB_ELTAG_ITEM);
addrbook_write_attr(fp, AB_ATTAG_TYPE, AB_ATTAG_VAL_GROUP);
addrbook_write_attr(fp, AB_ATTAG_UID, ADDRITEM_ID(item));
fputs(" />\n", fp);
node = g_list_next(node);
2001-09-02 01:48:06 +02:00
}
2001-09-27 10:16:30 +02:00
/* Output folders */
2001-09-02 01:48:06 +02:00
node = folder->listFolder;
2002-12-21 11:57:35 +01:00
while (node) {
2001-09-02 01:48:06 +02:00
ItemFolder *item = node->data;
2002-12-21 11:57:35 +01:00
addrbook_write_elem_s(fp, 3, AB_ELTAG_ITEM);
addrbook_write_attr(fp, AB_ATTAG_TYPE, AB_ATTAG_VAL_FOLDER);
addrbook_write_attr(fp, AB_ATTAG_UID, ADDRITEM_ID(item));
fputs(" />\n", fp);
node = g_list_next(node);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
addrbook_write_elem_e(fp, 2, AB_ELTAG_ITEM_LIST);
addrbook_write_elem_e(fp, 1, AB_ELTAG_FOLDER);
2001-09-02 01:48:06 +02:00
}
}
}
2002-12-21 11:57:35 +01:00
/* Output address book data to specified file.
return: Status code */
gint addrbook_write_to(AddressBookFile *book, gchar *newFile)
{
2001-09-02 01:48:06 +02:00
FILE *fp;
gchar *fileSpec;
#ifndef DEV_STANDALONE
PrefFile *pfile;
#endif
2002-12-21 11:57:35 +01:00
g_return_val_if_fail(book != NULL, -1);
g_return_val_if_fail(newFile != NULL, -1);
2001-09-02 01:48:06 +02:00
2002-12-21 11:57:35 +01:00
fileSpec = g_strconcat(book->path, G_DIR_SEPARATOR_S, newFile, NULL);
2001-09-02 01:48:06 +02:00
book->retVal = MGU_OPEN_FILE;
#ifdef DEV_STANDALONE
2002-12-21 11:57:35 +01:00
fp = fopen(fileSpec, "wb");
g_free(fileSpec);
if (fp) {
fputs("<?xml version=\"1.0\" ?>\n", fp);
2001-09-02 01:48:06 +02:00
#else
2002-12-21 11:57:35 +01:00
pfile = prefs_write_open(fileSpec);
g_free(fileSpec);
if (pfile) {
2001-09-02 01:48:06 +02:00
fp = pfile->fp;
2002-12-21 11:57:35 +01:00
fprintf(fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n",
conv_get_current_charset_str());
2001-09-02 01:48:06 +02:00
#endif
2002-12-21 11:57:35 +01:00
addrbook_write_elem_s(fp, 0, AB_ELTAG_ADDRESS_BOOK);
addrbook_write_attr(fp, AB_ATTAG_NAME,
addrcache_get_name(book->addressCache));
fputs(" >\n", fp);
2001-09-02 01:48:06 +02:00
2001-09-27 10:16:30 +02:00
/* Output all persons */
2002-12-21 11:57:35 +01:00
g_hash_table_foreach(book->addressCache->itemHash,
addrbook_write_item_person_vis, fp);
2001-09-02 01:48:06 +02:00
2001-09-27 10:16:30 +02:00
/* Output all groups */
2002-12-21 11:57:35 +01:00
g_hash_table_foreach(book->addressCache->itemHash,
addrbook_write_item_group_vis, fp);
2001-09-02 01:48:06 +02:00
2001-09-27 10:16:30 +02:00
/* Output all folders */
2002-12-21 11:57:35 +01:00
g_hash_table_foreach(book->addressCache->itemHash,
addrbook_write_item_folder_vis, fp);
2001-09-02 01:48:06 +02:00
2002-12-21 11:57:35 +01:00
addrbook_write_elem_e(fp, 0, AB_ELTAG_ADDRESS_BOOK);
2001-09-02 01:48:06 +02:00
book->retVal = MGU_SUCCESS;
#ifdef DEV_STANDALONE
2002-12-21 11:57:35 +01:00
fclose(fp);
2001-09-02 01:48:06 +02:00
#else
if (prefs_file_close( pfile ) < 0)
2001-09-02 01:48:06 +02:00
book->retVal = MGU_ERROR_WRITE;
#endif
}
fileSpec = NULL;
return book->retVal;
}
2002-12-21 11:57:35 +01:00
/* Output address book data to original file.
return: Status code */
gint addrbook_save_data(AddressBookFile *book)
{
g_return_val_if_fail(book != NULL, -1);
2001-09-02 01:48:06 +02:00
book->retVal = MGU_NO_FILE;
2002-12-21 11:57:35 +01:00
if (book->fileName == NULL || *book->fileName == '\0')
return book->retVal;
if (book->path == NULL || *book->path == '\0')
return book->retVal;
addrbook_write_to(book, book->fileName);
if (book->retVal == MGU_SUCCESS)
addrcache_set_dirty(book->addressCache, FALSE);
2001-09-02 01:48:06 +02:00
return book->retVal;
}
/* **********************************************************************
2002-12-21 11:57:35 +01:00
Address book edit interface functions...
***********************************************************************
Move person's email item.
param: book Address book.
person Person.
itemMove Item to move.
itemTarget Target item before which to move item */
ItemEMail *addrbook_move_email_before(AddressBookFile *book, ItemPerson *person,
ItemEMail *itemMove, ItemEMail *itemTarget)
2001-09-02 01:48:06 +02:00
{
ItemEMail *email = NULL;
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
g_return_val_if_fail(book != NULL, NULL);
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
email = addritem_move_email_before(person, itemMove, itemTarget);
if (email)
addrcache_set_dirty(book->addressCache, TRUE);
2001-09-02 01:48:06 +02:00
return email;
}
2002-12-21 11:57:35 +01:00
/* Move person's email item.
param: book Address book.
person Person.
itemMove Item to move.
itemTarget Target item after which to move item */
ItemEMail *addrbook_move_email_after(AddressBookFile *book, ItemPerson *person,
ItemEMail *itemMove, ItemEMail *itemTarget)
2001-09-02 01:48:06 +02:00
{
ItemEMail *email = NULL;
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
g_return_val_if_fail(book != NULL, NULL);
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
email = addritem_move_email_after(person, itemMove, itemTarget);
if (email)
addrcache_set_dirty(book->addressCache, TRUE);
2001-09-02 01:48:06 +02:00
return email;
}
2002-12-21 11:57:35 +01:00
/* Hash table visitor function for deletion of hashtable entries */
static gboolean addrbook_free_simple_hash_vis(gpointer *key, gpointer *value,
gpointer *data)
2002-08-06 07:52:56 +02:00
{
2002-12-21 11:57:35 +01:00
g_free(key);
2001-09-02 01:48:06 +02:00
key = NULL;
value = NULL;
return TRUE;
}
2002-12-21 11:57:35 +01:00
/* Update address book email list for specified person.
Enter: book Address book.
person Person to update.
listEMail List of new email addresses.
Note: The existing email addresses are replaced with the new addresses. Any references
to old addresses in the groups are re-linked to the new addresses. All old addresses
linked to the person are removed */
void addrbook_update_address_list(AddressBookFile *book, ItemPerson *person,
GList *listEMail)
2002-08-06 07:52:56 +02:00
{
2001-09-02 01:48:06 +02:00
GList *node;
2002-08-06 07:52:56 +02:00
GList *listDelete;
2001-09-02 01:48:06 +02:00
GList *listGroup;
2002-12-21 11:57:35 +01:00
g_return_if_fail(book != NULL);
g_return_if_fail(person != NULL);
2001-09-02 01:48:06 +02:00
2002-08-06 07:52:56 +02:00
/* Get groups where person's existing email addresses are listed */
2002-12-21 11:57:35 +01:00
listGroup = addrcache_get_group_for_person(book->addressCache, person);
if (listGroup) {
2001-09-02 01:48:06 +02:00
GHashTable *hashEMail;
2002-12-21 09:54:24 +01:00
GHashTable *hashEMailAlias;
2001-09-02 01:48:06 +02:00
GList *nodeGrp;
2001-09-27 10:16:30 +02:00
/* Load hash table with new address entries */
2002-12-21 11:57:35 +01:00
hashEMail = g_hash_table_new(g_str_hash, g_str_equal);
hashEMailAlias = g_hash_table_new(g_str_hash, g_str_equal);
2001-09-02 01:48:06 +02:00
node = listEMail;
2002-12-21 11:57:35 +01:00
while (node) {
2001-09-02 01:48:06 +02:00
ItemEMail *email = node->data;
2002-12-21 11:57:35 +01:00
gchar *addr = g_strdup(email->address);
2002-12-21 09:54:24 +01:00
gchar *alias = email->obj.name ;
2002-12-21 11:57:35 +01:00
g_strdown(addr);
if (!g_hash_table_lookup(hashEMail, addr)) {
g_hash_table_insert(hashEMail, addr, email);
2002-12-21 09:54:24 +01:00
}
2002-12-21 11:57:35 +01:00
if (*alias != '\0' && ! g_hash_table_lookup(hashEMailAlias,
alias))
g_hash_table_insert(hashEMailAlias, alias, email);
node = g_list_next(node);
2001-09-02 01:48:06 +02:00
}
2001-09-27 10:16:30 +02:00
/* Re-parent new addresses to existing groups, where email address match. */
2001-09-02 01:48:06 +02:00
nodeGrp = listGroup;
2002-12-21 11:57:35 +01:00
while (nodeGrp) {
ItemGroup *group = (ItemGroup *) nodeGrp->data;
2001-09-02 01:48:06 +02:00
GList *groupEMail = group->listEMail;
GList *nodeGrpEM;
GList *listRemove = NULL;
2001-09-27 10:16:30 +02:00
/* Process each email item linked to group */
2001-09-02 01:48:06 +02:00
nodeGrpEM = groupEMail;
2002-12-21 11:57:35 +01:00
while (nodeGrpEM) {
ItemEMail *emailGrp = (ItemEMail *) nodeGrpEM->data;
2002-08-06 07:52:56 +02:00
2002-12-21 11:57:35 +01:00
if (ADDRITEM_PARENT(emailGrp) == ADDRITEM_OBJECT(person)) {
2001-09-27 10:16:30 +02:00
/* Found an email address for this person */
2001-09-02 01:48:06 +02:00
ItemEMail *emailNew = NULL;
2002-12-21 11:57:35 +01:00
gchar *addr = g_strdup(emailGrp->address);
2002-12-21 09:54:24 +01:00
gchar *alias = emailGrp->obj.name;
2002-12-21 11:57:35 +01:00
g_strdown(addr);
emailNew = (ItemEMail *)
g_hash_table_lookup(hashEMail, addr);
2001-09-02 01:48:06 +02:00
g_free( addr );
2002-12-21 09:54:24 +01:00
/* If no match by e-mail, try to match by e-mail alias */
2002-12-21 11:57:35 +01:00
if (!emailNew && *alias != '\0') {
emailNew = (ItemEMail *)
g_hash_table_lookup(hashEMailAlias, alias);
2002-12-21 09:54:24 +01:00
}
2002-12-21 11:57:35 +01:00
if (emailNew)
2001-09-27 10:16:30 +02:00
/* Point to this entry */
2001-09-02 01:48:06 +02:00
nodeGrpEM->data = emailNew;
2002-12-21 11:57:35 +01:00
else if (g_hash_table_size(hashEMail)==1)
2002-12-21 09:54:24 +01:00
/* If the person has just one e-mail address, then
change e-mail address in group list */
nodeGrpEM->data = listEMail->data;
2002-12-21 11:57:35 +01:00
else
2001-09-27 10:16:30 +02:00
/* Mark for removal */
2002-12-21 11:57:35 +01:00
listRemove = g_list_append(listRemove, emailGrp);
2001-09-02 01:48:06 +02:00
}
2001-09-27 10:16:30 +02:00
/* Move on to next email link */
2002-12-21 11:57:35 +01:00
nodeGrpEM = g_list_next(nodeGrpEM);
2001-09-02 01:48:06 +02:00
}
2001-09-27 10:16:30 +02:00
/* Process all removed links in current group */
2001-09-02 01:48:06 +02:00
nodeGrpEM = listRemove;
2002-12-21 11:57:35 +01:00
while (nodeGrpEM) {
2001-09-02 01:48:06 +02:00
ItemEMail *emailGrp = nodeGrpEM->data;
2002-12-21 11:57:35 +01:00
groupEMail = g_list_remove(groupEMail, emailGrp);
nodeGrpEM = g_list_next(nodeGrpEM);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
g_list_free(listRemove);
2002-08-06 07:52:56 +02:00
2001-09-27 10:16:30 +02:00
/* Move on to next group */
2002-12-21 11:57:35 +01:00
nodeGrp = g_list_next(nodeGrp);
2001-09-02 01:48:06 +02:00
}
2001-09-27 10:16:30 +02:00
/* Clear hash table */
2002-12-21 11:57:35 +01:00
g_hash_table_foreach_remove(hashEMail, (GHRFunc)
addrbook_free_simple_hash_vis, NULL);
g_hash_table_destroy(hashEMail);
2001-09-02 01:48:06 +02:00
hashEMail = NULL;
2002-12-21 11:57:35 +01:00
g_hash_table_destroy(hashEMailAlias);
2002-12-21 09:54:24 +01:00
hashEMailAlias = NULL;
2002-12-21 11:57:35 +01:00
g_list_free(listGroup);
2001-09-02 01:48:06 +02:00
listGroup = NULL;
}
2002-08-06 07:52:56 +02:00
/* Remove old addresses from person and cache */
listDelete = NULL;
node = person->listEMail;
2002-12-21 11:57:35 +01:00
while (node) {
2002-08-06 07:52:56 +02:00
ItemEMail *email = node->data;
2002-12-21 11:57:35 +01:00
if (addrcache_person_remove_email(book->addressCache, person, email))
addrcache_remove_email(book->addressCache, email);
listDelete = g_list_append(listDelete, email);
2002-08-06 07:52:56 +02:00
node = person->listEMail;
}
/* Add new address entries */
node = listEMail;
2002-12-21 11:57:35 +01:00
while (node) {
2002-08-06 07:52:56 +02:00
ItemEMail *email = node->data;
2002-12-21 11:57:35 +01:00
if (ADDRITEM_ID(email) == NULL)
2002-08-06 07:52:56 +02:00
/* Allocate an ID for new address */
2002-12-21 11:57:35 +01:00
addrcache_id_email(book->addressCache, email);
2002-08-06 07:52:56 +02:00
addrcache_person_add_email( book->addressCache, person, email );
node = g_list_next( node );
}
2002-12-21 11:57:35 +01:00
addrcache_set_dirty(book->addressCache, TRUE);
2001-09-02 01:48:06 +02:00
2002-08-06 07:52:56 +02:00
/* Free up memory */
2002-12-21 11:57:35 +01:00
g_list_free(listEMail);
2002-08-06 07:52:56 +02:00
listEMail = NULL;
node = listDelete;
2002-12-21 11:57:35 +01:00
while (node) {
2002-08-06 07:52:56 +02:00
ItemEMail *email = node->data;
2002-12-21 11:57:35 +01:00
addritem_free_item_email(email);
node = g_list_next(node);
2002-08-06 07:52:56 +02:00
}
2002-12-21 11:57:35 +01:00
g_list_free(listDelete);
2002-08-06 07:52:56 +02:00
listDelete = NULL;
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
/* Add person and address data to address book.
Enter: book Address book.
folder Folder where to add person, or NULL for root folder.
listEMail New list of email addresses.
Return: Person added.
Note: A new person is created with specified list of email addresses. All objects inserted
into address book */
ItemPerson *addrbook_add_address_list(AddressBookFile *book, ItemFolder *folder,
GList *listEMail)
{
2001-09-02 01:48:06 +02:00
ItemPerson *person;
ItemFolder *f = folder;
GList *node;
2002-12-21 11:57:35 +01:00
g_return_val_if_fail(book != NULL, NULL);
2001-09-02 01:48:06 +02:00
2002-12-21 11:57:35 +01:00
if (!f)
f = book->addressCache->rootFolder;
2001-09-02 01:48:06 +02:00
person = addritem_create_item_person();
2002-12-21 11:57:35 +01:00
addrcache_id_person(book->addressCache, person);
addrcache_folder_add_person(book->addressCache, f, person);
2001-09-02 01:48:06 +02:00
node = listEMail;
2002-12-21 11:57:35 +01:00
while (node) {
2001-09-02 01:48:06 +02:00
ItemEMail *email = node->data;
2002-12-21 11:57:35 +01:00
if (ADDRITEM_ID(email) == NULL)
addrcache_id_email(book->addressCache, email);
addrcache_person_add_email(book->addressCache, person, email);
node = g_list_next(node);
2001-09-02 01:48:06 +02:00
}
return person;
}
2002-12-21 11:57:35 +01:00
/* Build available email list visitor function */
static void addrbook_build_avail_email_vis(gpointer key, gpointer value,
gpointer data)
{
AddrItemObject *obj = (AddrItemObject *) value;
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
if (ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON) {
2001-09-02 01:48:06 +02:00
AddressBookFile *book = data;
2002-12-21 11:57:35 +01:00
ItemPerson *person = (ItemPerson *) obj;
2001-09-02 01:48:06 +02:00
GList *node = person->listEMail;
2002-12-21 11:57:35 +01:00
while (node) {
2001-09-02 01:48:06 +02:00
ItemEMail *email = node->data;
2001-09-27 10:16:30 +02:00
/* gchar *newKey = g_strdup( ADDRITEM_ID(email) ); */
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
if (!g_hash_table_lookup(book->tempHash,
ADDRITEM_ID(email)))
book->tempList = g_list_append(book->tempList, email);
node = g_list_next(node);
2001-09-02 01:48:06 +02:00
}
}
}
2002-12-21 11:57:35 +01:00
/* Return link list of available email items (which have not already been linked to
groups). Note that the list contains references to items and should be g_free()
when done. Do *NOT* attempt to used the addrbook_free_xxx() functions... this will
destroy the addressbook data!
Return: List of items, or NULL if none */
GList *addrbook_get_available_email_list(AddressBookFile *book, ItemGroup *group)
{
2001-09-02 01:48:06 +02:00
GList *list = NULL;
GHashTable *table;
2002-12-21 11:57:35 +01:00
g_return_val_if_fail(book != NULL, NULL);
2001-09-02 01:48:06 +02:00
2001-09-27 10:16:30 +02:00
/* Load hash table with group email entries */
2002-12-21 11:57:35 +01:00
table = g_hash_table_new(g_str_hash, g_str_equal);
if (group) {
2001-09-02 01:48:06 +02:00
list = group->listEMail;
2002-12-21 11:57:35 +01:00
while (list) {
2001-09-02 01:48:06 +02:00
ItemEMail *email = list->data;
2002-12-21 11:57:35 +01:00
g_hash_table_insert(table, ADDRITEM_ID(email), email);
list = g_list_next(list);
2001-09-02 01:48:06 +02:00
}
}
2001-09-27 10:16:30 +02:00
/* Build list of available email addresses which exclude those already in groups */
2001-09-02 01:48:06 +02:00
book->tempList = NULL;
book->tempHash = table;
2002-12-21 11:57:35 +01:00
g_hash_table_foreach(book->addressCache->itemHash,
addrbook_build_avail_email_vis, book);
2001-09-02 01:48:06 +02:00
list = book->tempList;
book->tempList = NULL;
book->tempHash = NULL;
2001-09-27 10:16:30 +02:00
/* Clear hash table */
2002-12-21 11:57:35 +01:00
g_hash_table_destroy(table);
2001-09-02 01:48:06 +02:00
table = NULL;
return list;
}
2002-12-21 11:57:35 +01:00
/* Update address book email list for specified group.
Enter: book Address book.
group group to update.
listEMail New list of email addresses. This should *NOT* be g_free() when done.
Note: The existing email addresses are replaced with the new addresses. Any references
to old addresses in the groups are re-linked to the new addresses. All old addresses
linked to the person are removed */
void addrbook_update_group_list(AddressBookFile *book, ItemGroup *group,
GList *listEMail)
{
2001-09-02 01:48:06 +02:00
GList *oldData;
2002-12-21 11:57:35 +01:00
g_return_if_fail(book != NULL);
g_return_if_fail(group != NULL);
2001-09-02 01:48:06 +02:00
2002-12-21 11:57:35 +01:00
addrcache_set_dirty(book->addressCache, TRUE);
2001-09-27 10:16:30 +02:00
/* Remember old list */
2001-09-02 01:48:06 +02:00
oldData = group->listEMail;
group->listEMail = listEMail;
2002-12-21 11:57:35 +01:00
mgu_clear_list(oldData);
2001-09-02 01:48:06 +02:00
oldData = NULL;
}
2002-12-21 11:57:35 +01:00
/* Add group and email list to address book.
Enter: book Address book.
folder Parent folder, or NULL for root folder.
listEMail New list of email addresses. This should *NOT* be g_free() when done.
Return: Group object.
Note: The existing email addresses are replaced with the new addresses. Any references
to old addresses in the groups are re-linked to the new addresses. All old addresses
linked to the person are removed */
ItemGroup *addrbook_add_group_list(AddressBookFile *book, ItemFolder *folder,
GList *listEMail)
{
2001-09-02 01:48:06 +02:00
ItemGroup *group = NULL;
ItemFolder *f = folder;
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
g_return_val_if_fail(book != NULL, NULL);
2001-09-02 01:48:06 +02:00
2002-12-21 11:57:35 +01:00
if (!f)
f = book->addressCache->rootFolder;
2001-09-02 01:48:06 +02:00
group = addritem_create_item_group();
2002-12-21 11:57:35 +01:00
addrcache_id_group(book->addressCache, group);
addrcache_folder_add_group(book->addressCache, f, group);
2001-09-02 01:48:06 +02:00
group->listEMail = listEMail;
return group;
}
2002-12-21 11:57:35 +01:00
/* Add new folder to address book.
Enter: book Address book.
parent Parent folder.
Return: Folder that was added. This should *NOT* be g_free() when done */
ItemFolder *addrbook_add_new_folder(AddressBookFile *book, ItemFolder *parent)
{
2001-09-02 01:48:06 +02:00
ItemFolder *folder = NULL;
ItemFolder *p = parent;
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
g_return_val_if_fail(book != NULL, NULL);
2001-09-02 01:48:06 +02:00
2002-12-21 11:57:35 +01:00
if (!p)
p = book->addressCache->rootFolder;
2001-09-02 01:48:06 +02:00
folder = addritem_create_item_folder();
2002-12-21 11:57:35 +01:00
addrcache_id_folder(book->addressCache, folder);
if (addrcache_hash_add_folder(book->addressCache, folder)) {
p->listFolder = g_list_append(p->listFolder, folder);
2001-09-02 01:48:06 +02:00
ADDRITEM_PARENT(folder) = ADDRITEM_OBJECT(p);
2002-12-21 11:57:35 +01:00
addrcache_set_dirty(book->addressCache, TRUE);
2001-09-02 01:48:06 +02:00
}
else {
2002-12-21 11:57:35 +01:00
addritem_free_item_folder(folder);
2001-09-02 01:48:06 +02:00
folder = NULL;
}
return folder;
}
2002-12-21 11:57:35 +01:00
/* Update address book attribute list for specified person.
Enter: book Address book.
person Person to update.
listAttrib New list of attributes.
Note: The existing email addresses are replaced with the new addresses. All old attributes
linked to the person are removed */
void addrbook_update_attrib_list(AddressBookFile *book, ItemPerson *person,
GList *listAttrib)
{
2001-09-02 01:48:06 +02:00
GList *node;
GList *oldData;
2002-12-21 11:57:35 +01:00
g_return_if_fail(book != NULL);
g_return_if_fail(person != NULL);
2001-09-02 01:48:06 +02:00
2001-09-27 10:16:30 +02:00
/* Remember old list */
2001-09-02 01:48:06 +02:00
oldData = person->listAttrib;
2001-09-27 10:16:30 +02:00
/* Attach new address list to person. */
2001-09-02 01:48:06 +02:00
node = listAttrib;
2002-12-21 11:57:35 +01:00
while (node) {
2001-09-02 01:48:06 +02:00
UserAttribute *attrib = node->data;
2002-12-21 11:57:35 +01:00
if (attrib->uid == NULL) {
2001-09-27 10:16:30 +02:00
/* Allocate an ID */
2002-12-21 11:57:35 +01:00
addrcache_id_attribute(book->addressCache, attrib);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
node = g_list_next(node);
2001-09-02 01:48:06 +02:00
}
person->listAttrib = listAttrib;
2002-12-21 11:57:35 +01:00
addrcache_set_dirty(book->addressCache, TRUE);
2001-09-02 01:48:06 +02:00
2001-09-27 10:16:30 +02:00
/* Free up old data */
2002-12-21 11:57:35 +01:00
addritem_free_list_attribute(oldData);
2001-09-02 01:48:06 +02:00
oldData = NULL;
}
/*
* Add attribute data for person to address book.
* Enter: book Address book.
* person New person object.
* listAttrib New list of attributes.
* Note: Only attributes are inserted into address book.
*/
void addrbook_add_attrib_list( AddressBookFile *book, ItemPerson *person, GList *listAttrib ) {
GList *node;
2001-09-06 12:24:20 +02:00
2001-09-02 01:48:06 +02:00
g_return_if_fail( book != NULL );
g_return_if_fail( person != NULL );
node = listAttrib;
while( node ) {
UserAttribute *attrib = node->data;
if( attrib->uid == NULL ) {
addrcache_id_attribute( book->addressCache, attrib );
}
addritem_person_add_attribute( person, attrib );
node = g_list_next( node );
}
addrcache_set_dirty( book->addressCache, TRUE );
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
/* Return address book file for specified object.
Enter: aio Book item object.
Return: Address book, or NULL if not found */
AddressBookFile *addrbook_item_get_bookfile(AddrItemObject *aio)
{
2001-09-02 01:48:06 +02:00
AddressBookFile *book = NULL;
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
if (aio) {
2001-09-02 01:48:06 +02:00
ItemFolder *parent = NULL;
ItemFolder *root = NULL;
2002-12-21 11:57:35 +01:00
if (aio->type == ITEMTYPE_EMAIL) {
ItemPerson *person = (ItemPerson *)ADDRITEM_PARENT(aio);
if( person )
parent = (ItemFolder *)ADDRITEM_PARENT(person);
2001-09-02 01:48:06 +02:00
}
else {
2002-12-21 11:57:35 +01:00
parent = (ItemFolder *)ADDRITEM_PARENT(aio);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
if (parent)
root = addrcache_find_root_folder(parent);
if (root)
book = (AddressBookFile *)ADDRITEM_PARENT(root);
2001-09-02 01:48:06 +02:00
}
return book;
}
2002-12-21 11:57:35 +01:00
/* Remove folder from address book. Children are re-parented to parent folder.
param: folder Folder to remove.
return: Folder, or NULL if not found. Note that object should still be freed */
ItemFolder *addrbook_remove_folder(AddressBookFile *book, ItemFolder *folder)
{
2001-09-02 01:48:06 +02:00
ItemFolder *f;
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
g_return_val_if_fail(book != NULL, NULL);
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
f = addrcache_remove_folder(book->addressCache, folder);
2001-09-02 01:48:06 +02:00
return f;
}
2002-12-21 11:57:35 +01:00
/* Remove folder from address book. Children are deleted.
param: folder Folder to remove.
return: Folder, or NULL if not found. Note that object should still be freed */
ItemFolder *addrbook_remove_folder_delete(AddressBookFile *book,
ItemFolder *folder)
{
2001-09-02 01:48:06 +02:00
ItemFolder *f;
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
g_return_val_if_fail(book != NULL, NULL);
2001-09-06 12:24:20 +02:00
2002-12-21 11:57:35 +01:00
f = addrcache_remove_folder_delete(book->addressCache, folder);
2001-09-02 01:48:06 +02:00
return f;
}
#define WORK_BUFLEN 1024
#define ADDRBOOK_DIGITS "0123456789"
2002-12-21 11:57:35 +01:00
/* Return list of existing address book files.
Enter: book Address book file.
Return: File list */
GList *addrbook_get_bookfile_list(AddressBookFile *book) {
2001-09-02 01:48:06 +02:00
gchar *adbookdir;
DIR *dp;
struct dirent *entry;
struct stat statbuf;
2002-12-21 11:57:35 +01:00
gchar buf[WORK_BUFLEN];
gchar numbuf[WORK_BUFLEN];
2001-09-02 01:48:06 +02:00
gint len, lenpre, lensuf, lennum;
long int val, maxval;
GList *fileList = NULL;
2002-12-21 11:57:35 +01:00
g_return_val_if_fail(book != NULL, NULL);
2001-09-02 01:48:06 +02:00
2002-12-21 11:57:35 +01:00
if (book->path == NULL || *book->path == '\0') {
2001-09-02 01:48:06 +02:00
book->retVal = MGU_NO_PATH;
return NULL;
}
2002-12-21 11:57:35 +01:00
strcpy(buf, book->path);
len = strlen(buf);
if (len > 0) {
if (buf[len-1] != G_DIR_SEPARATOR) {
buf[len] = G_DIR_SEPARATOR;
buf[++len] = '\0';
2001-09-02 01:48:06 +02:00
}
}
2002-12-21 11:57:35 +01:00
adbookdir = g_strdup(buf);
strcat(buf, ADDRBOOK_PREFIX);
2001-09-02 01:48:06 +02:00
2002-12-21 11:57:35 +01:00
if ((dp = opendir(adbookdir)) == NULL) {
2001-09-02 01:48:06 +02:00
book->retVal = MGU_OPEN_DIRECTORY;
2002-12-21 11:57:35 +01:00
g_free(adbookdir);
2001-09-02 01:48:06 +02:00
return NULL;
}
2002-12-21 11:57:35 +01:00
lenpre = strlen(ADDRBOOK_PREFIX);
lensuf = strlen(ADDRBOOK_SUFFIX);
2001-09-02 01:48:06 +02:00
lennum = FILE_NUMDIGITS + lenpre;
maxval = -1;
2002-12-21 11:57:35 +01:00
while ((entry = readdir(dp)) != NULL) {
2001-09-06 12:24:20 +02:00
gchar *endptr = NULL;
2001-09-02 01:48:06 +02:00
gint i;
gboolean flg;
2002-12-21 11:57:35 +01:00
strcpy(buf, adbookdir);
strcat(buf, entry->d_name);
stat(buf, &statbuf);
if (S_IFREG & statbuf.st_mode) {
if (strncmp(entry->d_name, ADDRBOOK_PREFIX, lenpre) == 0) {
if (strncmp((entry->d_name) + lennum, ADDRBOOK_SUFFIX, lensuf) == 0) {
strncpy(numbuf, (entry->d_name) + lenpre, FILE_NUMDIGITS);
numbuf[FILE_NUMDIGITS] = '\0';
2001-09-02 01:48:06 +02:00
flg = TRUE;
2002-12-21 11:57:35 +01:00
for(i = 0; i < FILE_NUMDIGITS; i++) {
if(!strchr(ADDRBOOK_DIGITS, numbuf[i])) {
2001-09-02 01:48:06 +02:00
flg = FALSE;
break;
}
}
2002-12-21 11:57:35 +01:00
if (flg) {
2001-09-27 10:16:30 +02:00
/* Get value */
2002-12-21 11:57:35 +01:00
val = strtol(numbuf, &endptr, 10);
if (endptr && val > -1) {
if (val > maxval) maxval = val;
fileList = g_list_append(fileList, g_strdup(entry->d_name));
2001-09-02 01:48:06 +02:00
}
}
}
}
}
}
2002-12-21 11:57:35 +01:00
closedir(dp);
g_free(adbookdir);
2001-09-02 01:48:06 +02:00
book->maxValue = maxval;
book->retVal = MGU_SUCCESS;
return fileList;
}
2002-12-21 11:57:35 +01:00
/* Return file name for specified file number.
Enter: fileNum File number.
Return: File name, or NULL if file number too large. Should be g_free() when done */
gchar *addrbook_gen_new_file_name(gint fileNum) {
gchar fmt[30];
gchar buf[WORK_BUFLEN];
2001-09-02 01:48:06 +02:00
gint n = fileNum;
long int nmax;
2002-12-21 11:57:35 +01:00
if (n < 1)
n = 1;
nmax = -1 + (long int) pow(10, FILE_NUMDIGITS);
if (fileNum > nmax)
return NULL;
g_snprintf(fmt, sizeof(fmt), "%%s%%0%dd%%s", FILE_NUMDIGITS);
g_snprintf(buf, sizeof(buf), fmt, ADDRBOOK_PREFIX, n, ADDRBOOK_SUFFIX);
return g_strdup(buf);
2001-09-02 01:48:06 +02:00
}
/* **********************************************************************
2002-12-21 11:57:35 +01:00
Address book test functions...
**********************************************************************
2001-09-02 01:48:06 +02:00
*/
/*
* Test email address list.
*/
static void addrbook_chkparse_addr_list( AddressBookFile *book, XMLFile *file ){
guint prev_level;
GList *attr;
for (;;) {
prev_level = file->level;
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file))
longjmp(book->jumper, 1);
if (file->level < prev_level)
return;
2001-09-02 01:48:06 +02:00
attr = xml_get_current_tag_attr(file);
2001-09-27 10:16:30 +02:00
/* addrbook_show_attribs( attr ); */
2002-12-21 11:57:35 +01:00
if (xml_compare_tag(file, AB_ELTAG_ADDRESS))
addrbook_chkparse_addr_list(book, file);
2001-09-02 01:48:06 +02:00
}
}
2002-12-21 11:57:35 +01:00
/* Test user attributes for person */
static void addrbook_chkparse_attribute(AddressBookFile *book, XMLFile *file)
{
2001-09-02 01:48:06 +02:00
GList *attr;
gchar *element;
attr = xml_get_current_tag_attr(file);
2001-09-27 10:16:30 +02:00
/* addrbook_show_attribs( attr ); */
2002-12-21 11:57:35 +01:00
element = xml_get_element(file);
2001-09-27 10:16:30 +02:00
/* printf( "\t\tattrib value : %s\n", element ); */
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
/* Test attribute list */
static void addrbook_chkparse_attr_list(AddressBookFile *book, XMLFile *file)
{
2001-09-02 01:48:06 +02:00
guint prev_level;
for (;;) {
prev_level = file->level;
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file))
longjmp(book->jumper, 1);
if (file->level < prev_level)
return;
if (xml_compare_tag(file, AB_ELTAG_ATTRIBUTE)) {
addrbook_chkparse_attribute(book, file);
addrbook_chkparse_attr_list(book, file);
2001-09-02 01:48:06 +02:00
}
}
}
2002-12-21 11:57:35 +01:00
/* Test person */
static void addrbook_chkparse_person(AddressBookFile *book, XMLFile *file)
{
2001-09-02 01:48:06 +02:00
GList *attr;
attr = xml_get_current_tag_attr(file);
2001-09-27 10:16:30 +02:00
/* addrbook_show_attribs( attr ); */
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file)) /* Consume closing tag */
longjmp(book->jumper, 1);
if (xml_compare_tag(file, AB_ELTAG_ADDRESS_LIST))
addrbook_chkparse_addr_list(book, file);
if (xml_parse_next_tag(file)) /* Consume closing tag */
longjmp(book->jumper, 1);
if (xml_compare_tag(file, AB_ELTAG_ATTRIBUTE_LIST))
addrbook_chkparse_attr_list(book, file);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
/* Test group member list */
static void addrbook_chkparse_member_list(AddressBookFile *book, XMLFile *file)
{
2001-09-02 01:48:06 +02:00
GList *attr;
guint prev_level;
for (;;) {
prev_level = file->level;
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file))
longjmp(book->jumper, 1);
if (file->level < prev_level)
return;
if (xml_compare_tag(file, AB_ELTAG_MEMBER)) {
2001-09-02 01:48:06 +02:00
attr = xml_get_current_tag_attr(file);
2001-09-27 10:16:30 +02:00
/* addrbook_show_attribs( attr ); */
2002-12-21 11:57:35 +01:00
addrbook_chkparse_member_list(book, file);
2001-09-02 01:48:06 +02:00
}
else {
2002-12-21 11:57:35 +01:00
attr = xml_get_current_tag_attr(file);
2001-09-27 10:16:30 +02:00
/* addrbook_show_attribs( attr ); */
2001-09-02 01:48:06 +02:00
}
}
}
2002-12-21 11:57:35 +01:00
/* Test group */
static void addrbook_chkparse_group(AddressBookFile *book, XMLFile *file)
{
2001-09-02 01:48:06 +02:00
GList *attr;
attr = xml_get_current_tag_attr(file);
2001-09-27 10:16:30 +02:00
/* addrbook_show_attribs( attr ); */
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file)) /* Consume closing tag */
longjmp(book->jumper, 1);
if (xml_compare_tag(file, AB_ELTAG_MEMBER_LIST))
addrbook_chkparse_member_list(book, file);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
/* Test folder item list */
static void addrbook_chkparse_folder_list(AddressBookFile *book, XMLFile *file)
{
2001-09-02 01:48:06 +02:00
GList *attr;
guint prev_level;
for (;;) {
prev_level = file->level;
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file))
longjmp(book->jumper, 1);
if (file->level < prev_level)
return;
if (xml_compare_tag(file, AB_ELTAG_ITEM)) {
2001-09-02 01:48:06 +02:00
attr = xml_get_current_tag_attr(file);
2001-09-27 10:16:30 +02:00
/* addrbook_show_attribs( attr ); */
2002-12-21 11:57:35 +01:00
addrbook_chkparse_folder_list(book, file);
2001-09-02 01:48:06 +02:00
}
else {
2002-12-21 11:57:35 +01:00
attr = xml_get_current_tag_attr(file);
2001-09-27 10:16:30 +02:00
/* addrbook_show_attribs( attr ); */
2001-09-02 01:48:06 +02:00
}
}
}
2002-12-21 11:57:35 +01:00
/* Test folder */
static void addrbook_chkparse_folder(AddressBookFile *book, XMLFile *file)
{
2001-09-02 01:48:06 +02:00
GList *attr;
attr = xml_get_current_tag_attr(file);
2001-09-27 10:16:30 +02:00
/* addrbook_show_attribs( attr ); */
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file)) /* Consume closing tag */
longjmp(book->jumper, 1);
if (xml_compare_tag(file, AB_ELTAG_ITEM_LIST))
addrbook_chkparse_folder_list(book, file);
2001-09-02 01:48:06 +02:00
}
2002-12-21 11:57:35 +01:00
/* Test address book */
static gboolean addrbook_chkread_tree(AddressBookFile *book, XMLFile *file)
{
2001-09-02 01:48:06 +02:00
GList *attr;
gboolean retVal;
2002-12-21 11:57:35 +01:00
if (xml_get_dtd(file))
2001-09-02 01:48:06 +02:00
return FALSE;
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file))
2001-09-02 01:48:06 +02:00
return FALSE;
2002-12-21 11:57:35 +01:00
if (!xml_compare_tag(file, AB_ELTAG_ADDRESS_BOOK))
2001-09-02 01:48:06 +02:00
return FALSE;
attr = xml_get_current_tag_attr(file);
2001-09-24 07:44:43 +02:00
/* addrbook_show_attribs( attr ); */
2001-09-02 01:48:06 +02:00
retVal = TRUE;
for (;;) {
2002-12-21 11:57:35 +01:00
if (!file->level)
break;
2001-09-24 07:44:43 +02:00
/* Get item tag */
2002-12-21 11:57:35 +01:00
if (xml_parse_next_tag(file))
longjmp(book->jumper, 1);
2001-09-24 07:44:43 +02:00
/* Get next tag (person, group or folder) */
2002-12-21 11:57:35 +01:00
if (xml_compare_tag(file, AB_ELTAG_PERSON))
2001-09-02 01:48:06 +02:00
addrbook_chkparse_person( book, file );
2002-12-21 11:57:35 +01:00
else if (xml_compare_tag(file, AB_ELTAG_GROUP))
addrbook_chkparse_group(book, file);
else if (xml_compare_tag(file, AB_ELTAG_FOLDER))
addrbook_chkparse_folder(book, file);
2001-09-02 01:48:06 +02:00
}
return retVal;
}
2002-12-21 11:57:35 +01:00
/* Test address book file by parsing contents.
Enter: book Address book file to check.
fileName File name to check.
Return: MGU_SUCCESS if file appears to be valid format */
gint addrbook_test_read_file(AddressBookFile *book, gchar *fileName)
{
2001-09-02 01:48:06 +02:00
XMLFile *file = NULL;
gchar *fileSpec = NULL;
2002-12-21 11:57:35 +01:00
g_return_val_if_fail(book != NULL, -1);
2001-09-02 01:48:06 +02:00
2002-12-21 11:57:35 +01:00
fileSpec = g_strconcat(book->path, G_DIR_SEPARATOR_S, fileName, NULL);
2001-09-02 01:48:06 +02:00
book->retVal = MGU_OPEN_FILE;
2002-12-21 11:57:35 +01:00
file = xml_open_file(fileSpec);
g_free(fileSpec);
if (file) {
2001-09-02 01:48:06 +02:00
book->retVal = MGU_BAD_FORMAT;
2002-12-21 11:57:35 +01:00
if (setjmp(book->jumper)) {
2001-09-24 07:44:43 +02:00
/* printf( "Caught Ya!!!\n" ); */
2002-12-21 11:57:35 +01:00
xml_close_file(file);
2001-09-02 01:48:06 +02:00
return book->retVal;
}
2002-12-21 11:57:35 +01:00
if (addrbook_chkread_tree(book, file))
2001-09-02 01:48:06 +02:00
book->retVal = MGU_SUCCESS;
2002-12-21 11:57:35 +01:00
2001-09-02 01:48:06 +02:00
xml_close_file( file );
}
return book->retVal;
}
2002-12-21 11:57:35 +01:00
/* Return link list of all persons in address book. Note that the list contains
references to items. Do *NOT* attempt to use the addrbook_free_xxx() functions...
this will destroy the addressbook data!
Return: List of items, or NULL if none */
GList *addrbook_get_all_persons(AddressBookFile *book)
{
g_return_val_if_fail(book != NULL, NULL);
return addrcache_get_all_persons(book->addressCache);
}
2003-03-17 07:49:25 +01:00
/**
* Add person and address data to address book.
* \param book Address book.
* \param folder Folder where to add person, or NULL for root folder.
* \param name Common name.
* \param address EMail address.
* \param remarks Remarks.
* \return Person added. Do not <b>*NOT*</b> to use the
* <code>addrbook_free_xxx()</code> functions... this will destroy
* the address book data.
*/
2002-12-21 11:57:35 +01:00
ItemPerson *addrbook_add_contact(AddressBookFile *book, ItemFolder *folder,
const gchar *name,const gchar *address,
const gchar *remarks)
2001-09-02 01:48:06 +02:00
{
2003-03-17 07:49:25 +01:00
ItemPerson *person;
2002-12-21 11:57:35 +01:00
g_return_val_if_fail(book != NULL, NULL);
2003-03-17 07:49:25 +01:00
person = addrcache_add_contact(
book->addressCache, folder, name, address, remarks );
addrcache_invalidate( book->addressCache );
return person;
2001-09-02 01:48:06 +02:00
}
2003-03-17 07:49:25 +01:00
/**
* Return file name for next address book file.
* \param book Address book.
* \return File name, or <i>NULL</i> if could not create. This should be
* <code>g_free()</code> when done.
*/
2002-12-21 11:57:35 +01:00
gchar *addrbook_guess_next_file(AddressBookFile *book)
{
2002-03-16 07:10:46 +01:00
gchar *newFile = NULL;
GList *fileList = NULL;
gint fileNum = 1;
2002-12-21 11:57:35 +01:00
fileList = addrbook_get_bookfile_list(book);
if (fileList)
2002-03-16 07:10:46 +01:00
fileNum = 1 + book->maxValue;
2002-12-21 11:57:35 +01:00
newFile = addrbook_gen_new_file_name(fileNum);
g_list_free(fileList);
2002-03-16 07:10:46 +01:00
fileList = NULL;
return newFile;
}
2003-03-17 07:49:25 +01:00
/**
* Invalidate the address book data. This will cause index to be rebuilt.
* \param book Address book.
*/
void addrbook_invalidate( AddressBookFile *book ) {
g_return_if_fail( book != NULL );
addrcache_invalidate( book->addressCache );
}
/*
* End of Source.
*/