283412fa01
* README * README.jp * configure.ac * config/config.rpath * doc/manual/en/sylpheed-20.html * doc/manual/es/sylpheed-20.html * po/bg.po * po/ca.po * po/de.po * po/es.po * po/fr.po * po/it.po * po/pt_BR.po * po/sk.po * po/zh_TW.po * src/account.c * src/account.h * src/action.c * src/action.h * src/adbookbase.h * src/addr_compl.c * src/addr_compl.h * src/addrbook.c * src/addrbook.h * src/addrcache.c * src/addrcache.h * src/addrcindex.c * src/addrcindex.h * src/addrclip.c * src/addrclip.h * src/addrdefs.h * src/addressadd.c * src/addressadd.h * src/addressbook.c * src/addressbook.h * src/addressitem.h * src/addrgather.c * src/addrgather.h * src/addrharvest.c * src/addrharvest.h * src/addrindex.c * src/addrindex.h * src/addritem.c * src/addritem.h * src/addrquery.c * src/addrquery.h * src/addrselect.c * src/addrselect.h * src/alertpanel.c * src/alertpanel.h * src/browseldap.c * src/browseldap.h * src/codeconv.c * src/codeconv.h * src/compose.c * src/compose.h * src/crash.c * src/crash.h * src/customheader.c * src/customheader.h * src/displayheader.c * src/displayheader.h * src/editaddress.c * src/editaddress.h * src/editbook.c * src/editbook.h * src/editgroup.c * src/editgroup.h * src/editjpilot.c * src/editjpilot.h * src/editldap.c * src/editldap.h * src/editldap_basedn.c * src/editldap_basedn.h * src/editvcard.c * src/editvcard.h * src/enriched.c * src/enriched.h * src/exphtmldlg.c * src/exphtmldlg.h * src/expldifdlg.c * src/expldifdlg.h * src/export.c * src/export.h * src/exporthtml.c * src/exporthtml.h * src/exportldif.c * src/exportldif.h * src/filtering.c * src/filtering.h * src/folder.c * src/folder.h * src/folder_item_prefs.c * src/folder_item_prefs.h * src/foldersel.c * src/foldersel.h * src/folderutils.c * src/folderutils.h * src/folderview.c * src/folderview.h * src/grouplistdialog.c * src/grouplistdialog.h * src/headerview.c * src/headerview.h * src/html.c * src/html.h * src/image_viewer.c * src/image_viewer.h * src/imap.c * src/imap.h * src/imap_gtk.c * src/imap_gtk.h * src/import.c * src/import.h * src/importldif.c * src/importldif.h * src/importmutt.c * src/importmutt.h * src/importpine.c * src/importpine.h * src/inc.c * src/inc.h * src/jpilot.c * src/jpilot.h * src/ldapctrl.c * src/ldapctrl.h * src/ldaplocate.c * src/ldaplocate.h * src/ldapquery.c * src/ldapquery.h * src/ldapserver.c * src/ldapserver.h * src/ldaputil.c * src/ldaputil.h * src/ldif.c * src/ldif.h * src/localfolder.c * src/localfolder.h * src/main.c * src/main.h * src/mainwindow.c * src/mainwindow.h * src/manual.c * src/manual.h * src/matcher.c * src/matcher.h * src/matcher_parser.h * src/matcher_parser_lex.l * src/matcher_parser_parse.y * src/mbox.c * src/mbox.h * src/message_search.c * src/message_search.h * src/messageview.c * src/messageview.h * src/mh.c * src/mh.h * src/mh_gtk.c * src/mh_gtk.h * src/mimeview.c * src/mimeview.h * src/msgcache.c * src/msgcache.h * src/mutt.c * src/mutt.h * src/news.c * src/news.h * src/news_gtk.c * src/news_gtk.h * src/noticeview.c * src/noticeview.h * src/partial_download.c * src/partial_download.h * src/pine.c * src/pine.h * src/pop.c * src/pop.h * src/prefs_account.c * src/prefs_account.h * src/prefs_actions.c * src/prefs_actions.h * src/prefs_common.c * src/prefs_common.h * src/prefs_compose_writing.c * src/prefs_compose_writing.h * src/prefs_customheader.c * src/prefs_customheader.h * src/prefs_display_header.c * src/prefs_display_header.h * src/prefs_ext_prog.c * src/prefs_ext_prog.h * src/prefs_filtering.c * src/prefs_filtering.h * src/prefs_filtering_action.c * src/prefs_filtering_action.h * src/prefs_folder_column.c * src/prefs_folder_column.h * src/prefs_folder_item.c * src/prefs_folder_item.h * src/prefs_fonts.c * src/prefs_fonts.h * src/prefs_gtk.c * src/prefs_gtk.h * src/prefs_image_viewer.c * src/prefs_image_viewer.h * src/prefs_matcher.c * src/prefs_matcher.h * src/prefs_message.c * src/prefs_message.h * src/prefs_msg_colors.c * src/prefs_msg_colors.h * src/prefs_other.c * src/prefs_other.h * src/prefs_quote.c * src/prefs_quote.h * src/prefs_receive.c * src/prefs_receive.h * src/prefs_send.c * src/prefs_send.h * src/prefs_spelling.c * src/prefs_spelling.h * src/prefs_summaries.c * src/prefs_summaries.h * src/prefs_summary_column.c * src/prefs_summary_column.h * src/prefs_template.c * src/prefs_template.h * src/prefs_themes.c * src/prefs_themes.h * src/prefs_toolbar.c * src/prefs_toolbar.h * src/prefs_wrapping.c * src/prefs_wrapping.h * src/privacy.c * src/privacy.h * src/procheader.c * src/procheader.h * src/procmime.c * src/procmime.h * src/procmsg.c * src/procmsg.h * src/quote_fmt.c * src/quote_fmt_parse.y * src/recv.c * src/recv.h * src/remotefolder.c * src/remotefolder.h * src/send_message.c * src/send_message.h * src/setup.c * src/setup.h * src/simple-gettext.c * src/sourcewindow.c * src/sourcewindow.h * src/ssl_manager.c * src/ssl_manager.h * src/statusbar.c * src/statusbar.h * src/stock_pixmap.c * src/stock_pixmap.h * src/summary_search.c * src/summary_search.h * src/summaryview.c * src/summaryview.h * src/syldap.c * src/syldap.h * src/textview.c * src/textview.h * src/toolbar.c * src/toolbar.h * src/undo.c * src/undo.h * src/unmime.c * src/unmime.h * src/vcard.c * src/vcard.h * src/wizard.c * src/wizard.h * src/common/base64.c * src/common/base64.h * src/common/defs.h * src/common/hooks.c * src/common/hooks.h * src/common/log.c * src/common/log.h * src/common/md5.c * src/common/md5.h * src/common/mgutils.c * src/common/mgutils.h * src/common/nntp.c * src/common/nntp.h * src/common/passcrypt.c * src/common/passcrypt.h.in * src/common/plugin.c * src/common/plugin.h * src/common/prefs.c * src/common/prefs.h * src/common/progressindicator.c * src/common/progressindicator.h * src/common/quoted-printable.c * src/common/quoted-printable.h * src/common/session.c * src/common/session.h * src/common/smtp.c * src/common/smtp.h * src/common/socket.c * src/common/socket.h * src/common/ssl.c * src/common/ssl.h * src/common/ssl_certificate.c * src/common/ssl_certificate.h * src/common/string_match.c * src/common/string_match.h * src/common/stringtable.c * src/common/sylpheed.c * src/common/sylpheed.h * src/common/template.c * src/common/template.h * src/common/timing.h * src/common/utils.c * src/common/utils.h * src/common/uuencode.c * src/common/uuencode.h * src/common/version.h.in * src/common/xml.c * src/common/xml.h * src/common/xmlprops.c * src/common/xmlprops.h * src/gtk/about.c * src/gtk/about.h * src/gtk/colorlabel.c * src/gtk/colorlabel.h * src/gtk/colorsel.c * src/gtk/colorsel.h * src/gtk/description_window.c * src/gtk/description_window.h * src/gtk/filesel.c * src/gtk/filesel.h * src/gtk/foldersort.c * src/gtk/foldersort.h * src/gtk/gtkutils.c * src/gtk/gtkutils.h * src/gtk/inputdialog.c * src/gtk/inputdialog.h * src/gtk/logwindow.c * src/gtk/logwindow.h * src/gtk/manage_window.c * src/gtk/manage_window.h * src/gtk/menu.c * src/gtk/menu.h * src/gtk/pluginwindow.c * src/gtk/pluginwindow.h * src/gtk/prefswindow.c * src/gtk/prefswindow.h * src/gtk/progressdialog.c * src/gtk/progressdialog.h * src/gtk/quicksearch.c * src/gtk/quicksearch.h * src/gtk/sslcertwindow.c * src/gtk/sslcertwindow.h * src/plugins/clamav/clamav_plugin.c * src/plugins/clamav/clamav_plugin.h * src/plugins/clamav/clamav_plugin_gtk.c * src/plugins/demo/demo.c * src/plugins/dillo_viewer/dillo_prefs.c * src/plugins/dillo_viewer/dillo_prefs.h * src/plugins/dillo_viewer/dillo_viewer.c * src/plugins/mathml_viewer/mathml_viewer.c * src/plugins/pgpcore/passphrase.c * src/plugins/pgpcore/passphrase.h * src/plugins/pgpcore/plugin.c * src/plugins/pgpcore/prefs_gpg.c * src/plugins/pgpcore/prefs_gpg.h * src/plugins/pgpcore/select-keys.c * src/plugins/pgpcore/select-keys.h * src/plugins/pgpcore/sgpgme.c * src/plugins/pgpcore/sgpgme.h * src/plugins/pgpinline/pgpinline.c * src/plugins/pgpinline/pgpinline.h * src/plugins/pgpinline/plugin.c * src/plugins/pgpmime/pgpmime.c * src/plugins/pgpmime/pgpmime.h * src/plugins/pgpmime/plugin.c * src/plugins/spamassassin/spamassassin.c * src/plugins/spamassassin/spamassassin.h * src/plugins/spamassassin/spamassassin_gtk.c * src/plugins/trayicon/trayicon.c * tools/OOo2sylpheed.pl * tools/acroread2sylpheed.pl * tools/asus_mailled.sh * tools/filter_conv.pl * tools/freshmeat_search.pl * tools/google_search.pl * tools/kmail2sylpheed.pl * tools/kmail2sylpheed_v2.pl * tools/maildir2sylpheed.pl * tools/multiwebsearch.pl * tools/newscache_clean.pl * tools/outlook2sylpheed.pl * tools/sylpheed-switcher * tools/update-po * tools/vcard2xml.py * tools/kdeservicemenu/sylpheed-kdeservicemenu.pl update FSF address
2321 lines
61 KiB
C
2321 lines
61 KiB
C
/*
|
|
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
|
|
* Copyright (C) 2001-2002 Match Grun and the Sylpheed-Claws team
|
|
*
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
/* General functions for accessing address book files */
|
|
|
|
#include <glib.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.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"
|
|
|
|
#ifndef DEV_STANDALONE
|
|
#include "prefs_gtk.h"
|
|
#include "codeconv.h"
|
|
#endif
|
|
|
|
#define ADDRBOOK_MAX_SEARCH_COUNT 1000
|
|
#define ADDRBOOK_PREFIX "addrbook-"
|
|
#define ADDRBOOK_SUFFIX ".xml"
|
|
#define FILE_NUMDIGITS 6
|
|
|
|
#define ID_TIME_OFFSET 998000000
|
|
|
|
/**
|
|
* Create new address book
|
|
* \return Address book.
|
|
*/
|
|
AddressBookFile *addrbook_create_book()
|
|
{
|
|
AddressBookFile *book;
|
|
|
|
book = g_new0(AddressBookFile, 1);
|
|
book->type = ADBOOKTYPE_BOOK;
|
|
book->addressCache = addrcache_create();
|
|
book->retVal = MGU_SUCCESS;
|
|
book->path = NULL;
|
|
book->fileName = NULL;
|
|
book->maxValue = 0;
|
|
book->tempList = NULL;
|
|
book->tempHash = NULL;
|
|
book->addressCache->modified = TRUE;
|
|
|
|
return book;
|
|
}
|
|
|
|
/**
|
|
* Specify name to be used
|
|
* \param book Address book.
|
|
* \param value Name.
|
|
*/
|
|
void addrbook_set_name(AddressBookFile *book, const gchar *value)
|
|
{
|
|
g_return_if_fail(book != NULL);
|
|
addrcache_set_name(book->addressCache, value);
|
|
}
|
|
|
|
gchar *addrbook_get_name(AddressBookFile *book)
|
|
{
|
|
g_return_val_if_fail(book != NULL, NULL);
|
|
return addrcache_get_name(book->addressCache);
|
|
}
|
|
|
|
/**
|
|
* Specify path to address book file.
|
|
* \param book Address book.
|
|
* \param value Path.
|
|
*/
|
|
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);
|
|
}
|
|
|
|
/**
|
|
* Specify filename to be used
|
|
* \param book Address book.
|
|
* \param value Filename.
|
|
*/
|
|
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);
|
|
}
|
|
|
|
gboolean addrbook_get_modified(AddressBookFile *book)
|
|
{
|
|
g_return_val_if_fail(book != NULL, FALSE);
|
|
return book->addressCache->modified;
|
|
}
|
|
|
|
/**
|
|
* Specify book as modified.
|
|
* \param book Address book.
|
|
* \param value Indicator.
|
|
*/
|
|
void addrbook_set_modified(AddressBookFile *book, const gboolean value)
|
|
{
|
|
g_return_if_fail(book != NULL);
|
|
book->addressCache->modified = value;
|
|
}
|
|
|
|
gboolean addrbook_get_accessed(AddressBookFile *book)
|
|
{
|
|
g_return_val_if_fail(book != NULL, FALSE);
|
|
return book->addressCache->accessFlag;
|
|
}
|
|
|
|
/**
|
|
* Specify address book as accessed.
|
|
* \param book Address book.
|
|
* \param value Value.
|
|
*/
|
|
void addrbook_set_accessed(AddressBookFile *book, const gboolean value)
|
|
{
|
|
g_return_if_fail(book != NULL);
|
|
book->addressCache->accessFlag = value;
|
|
}
|
|
|
|
gboolean addrbook_get_read_flag(AddressBookFile *book)
|
|
{
|
|
g_return_val_if_fail(book != NULL, FALSE);
|
|
return book->addressCache->dataRead;
|
|
}
|
|
|
|
/**
|
|
* Specify address book as read.
|
|
* \param book Address book.
|
|
* \param value Value.
|
|
*/
|
|
void addrbook_set_read_flag(AddressBookFile *book, const gboolean value)
|
|
{
|
|
g_return_if_fail(book != NULL);
|
|
book->addressCache->dataRead = value;
|
|
}
|
|
|
|
gint addrbook_get_status(AddressBookFile *book)
|
|
{
|
|
g_return_val_if_fail(book != NULL, -1);
|
|
return book->retVal;
|
|
}
|
|
|
|
ItemFolder *addrbook_get_root_folder(AddressBookFile *book)
|
|
{
|
|
g_return_val_if_fail(book != NULL, NULL);
|
|
return addrcache_get_root_folder(book->addressCache);
|
|
}
|
|
|
|
GList *addrbook_get_list_folder(AddressBookFile *book)
|
|
{
|
|
g_return_val_if_fail(book != NULL, NULL);
|
|
return addrcache_get_list_folder(book->addressCache);
|
|
}
|
|
|
|
GList *addrbook_get_list_person(AddressBookFile *book)
|
|
{
|
|
g_return_val_if_fail(book != NULL, NULL);
|
|
return addrcache_get_list_person(book->addressCache);
|
|
}
|
|
|
|
gboolean addrbook_get_dirty(AddressBookFile *book)
|
|
{
|
|
g_return_val_if_fail(book != NULL, FALSE);
|
|
return addrcache_get_dirty(book->addressCache);
|
|
}
|
|
|
|
/**
|
|
* Set address book as dirty (needs to be written to file).
|
|
* \param book Address book.
|
|
* \param value Dirty flag.
|
|
*/
|
|
void addrbook_set_dirty(AddressBookFile *book, const gboolean value)
|
|
{
|
|
g_return_if_fail(book != NULL);
|
|
addrcache_set_dirty(book->addressCache, value);
|
|
}
|
|
|
|
/**
|
|
* Empty address book contents.
|
|
* \param book Address book.
|
|
*/
|
|
void addrbook_empty_book(AddressBookFile *book)
|
|
{
|
|
g_return_if_fail(book != NULL);
|
|
|
|
/* Free up internal objects */
|
|
addrcache_clear(book->addressCache);
|
|
addrcache_set_dirty(book->addressCache, FALSE);
|
|
g_list_free(book->tempList);
|
|
|
|
/* Reset to initial state */
|
|
book->tempList = NULL;
|
|
book->tempHash = NULL;
|
|
book->addressCache->dataRead = FALSE;
|
|
book->addressCache->modified = FALSE;
|
|
book->addressCache->accessFlag = FALSE;
|
|
book->retVal = MGU_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* Free address book.
|
|
* \param book Address book.
|
|
*/
|
|
void addrbook_free_book(AddressBookFile *book)
|
|
{
|
|
g_return_if_fail(book != NULL);
|
|
|
|
/* Clear cache */
|
|
addrcache_free(book->addressCache);
|
|
|
|
/* Free up internal objects */
|
|
g_free(book->path);
|
|
g_free(book->fileName);
|
|
g_list_free(book->tempList);
|
|
|
|
book->path = NULL;
|
|
book->fileName = NULL;
|
|
book->maxValue = 0;
|
|
book->tempList = NULL;
|
|
book->tempHash = NULL;
|
|
|
|
book->type = ADBOOKTYPE_NONE;
|
|
book->addressCache = NULL;
|
|
book->retVal = MGU_SUCCESS;
|
|
|
|
g_free(book);
|
|
}
|
|
|
|
/**
|
|
* Print list of items.
|
|
* \param book Address book.
|
|
* \param stream Output stream.
|
|
*/
|
|
void addrbook_print_item_list(GList *list, FILE *stream)
|
|
{
|
|
GList *node = list;
|
|
|
|
while(node) {
|
|
AddrItemObject *obj = node->data;
|
|
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);
|
|
}
|
|
fprintf(stream, "\t---\n");
|
|
}
|
|
|
|
/**
|
|
* Print address book header.
|
|
* \param book Address book.
|
|
* \param stream Output stream.
|
|
*/
|
|
void addrbook_print_book(AddressBookFile *book, FILE *stream)
|
|
{
|
|
g_return_if_fail(book != NULL);
|
|
|
|
fprintf(stream, "AddressBook:\n");
|
|
fprintf(stream, "\tpath : '%s'\n", book->path);
|
|
fprintf(stream, "\tfile : '%s'\n", book->fileName);
|
|
fprintf(stream, "\tstatus : %d\n", book->retVal );
|
|
addrcache_print(book->addressCache, stream);
|
|
}
|
|
|
|
/**
|
|
* Dump entire address book traversing folders.
|
|
* \param book Address book.
|
|
* \param stream Output stream.
|
|
*/
|
|
void addrbook_dump_book(AddressBookFile *book, FILE *stream)
|
|
{
|
|
ItemFolder *folder;
|
|
|
|
g_return_if_fail(book != NULL);
|
|
|
|
addrbook_print_book(book, stream);
|
|
folder = book->addressCache->rootFolder;
|
|
addritem_print_item_folder(folder, stream);
|
|
}
|
|
|
|
/**
|
|
* Remove specified group from address book. Note that object should still
|
|
* be freed.
|
|
* Specify name to be used
|
|
* \param book Address book.
|
|
* \param group Group to remove.
|
|
* \param value Name.
|
|
* \return Group, or NULL if not found.
|
|
*/
|
|
ItemGroup *addrbook_remove_group(AddressBookFile *book, ItemGroup *group)
|
|
{
|
|
g_return_val_if_fail(book != NULL, NULL);
|
|
return addrcache_remove_group(book->addressCache, group);
|
|
}
|
|
|
|
/**
|
|
* Remove specified person from address book. Note that object should still
|
|
* be freed.
|
|
* \param book Address book.
|
|
* \param person Person to remove.
|
|
* \return Person, or NULL if not found.
|
|
*/
|
|
ItemPerson *addrbook_remove_person(AddressBookFile *book, ItemPerson *person)
|
|
{
|
|
g_return_val_if_fail(book != NULL, NULL);
|
|
return addrcache_remove_person(book->addressCache, person);
|
|
}
|
|
|
|
/**
|
|
* Remove specified email address in address book for specified person.
|
|
* Note that object should still be freed.
|
|
* \param book Address book.
|
|
* \param person Person.
|
|
* \param email EMail to remove.
|
|
* \return EMail object, or NULL if not found.
|
|
*/
|
|
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);
|
|
}
|
|
|
|
/*
|
|
* ***********************************************************************
|
|
* 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.
|
|
*
|
|
* ***********************************************************************
|
|
*/
|
|
|
|
/* Element tag names */
|
|
#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"
|
|
|
|
/* Attribute tag names */
|
|
#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"
|
|
|
|
/* Attribute values */
|
|
#define AB_ATTAG_VAL_PERSON "person"
|
|
#define AB_ATTAG_VAL_GROUP "group"
|
|
#define AB_ATTAG_VAL_FOLDER "folder"
|
|
|
|
/**
|
|
* Parse address item for person from XML file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
* \param person Person.
|
|
*/
|
|
static void addrbook_parse_address(AddressBookFile *book, XMLFile *file,
|
|
ItemPerson *person)
|
|
{
|
|
GList *attr;
|
|
gchar *name, *value;
|
|
ItemEMail *email = NULL;
|
|
|
|
attr = xml_get_current_tag_attr(file);
|
|
while (attr) {
|
|
name = ((XMLAttr *)attr->data)->name;
|
|
value = ((XMLAttr *)attr->data)->value;
|
|
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);
|
|
}
|
|
else {
|
|
addritem_free_item_email(email);
|
|
email = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parse list of email address for person from XML file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
* \param person Person.
|
|
*/
|
|
static void addrbook_parse_addr_list(AddressBookFile *book, XMLFile *file,
|
|
ItemPerson *person)
|
|
{
|
|
GList *attr;
|
|
guint prev_level;
|
|
|
|
for (;;) {
|
|
prev_level = file->level;
|
|
if (xml_parse_next_tag(file)) {
|
|
longjmp(book->jumper, 1);
|
|
}
|
|
if (file->level < prev_level) return;
|
|
if (xml_compare_tag(file, AB_ELTAG_ADDRESS)) {
|
|
attr = xml_get_current_tag_attr(file);
|
|
addrbook_parse_address(book, file, person);
|
|
addrbook_parse_addr_list(book, file, person);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parse attribute for person from XML file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
* \param person Person.
|
|
*/
|
|
static void addrbook_parse_attribute(XMLFile *file, ItemPerson *person)
|
|
{
|
|
GList *attr;
|
|
gchar *name, *value;
|
|
gchar *element;
|
|
UserAttribute *uAttr = NULL;
|
|
|
|
attr = xml_get_current_tag_attr(file);
|
|
while (attr) {
|
|
name = ((XMLAttr *)attr->data)->name;
|
|
value = ((XMLAttr *)attr->data)->value;
|
|
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);
|
|
}
|
|
|
|
element = xml_get_element(file);
|
|
addritem_attrib_set_value(uAttr, element);
|
|
|
|
if (uAttr) {
|
|
if (person) {
|
|
addritem_person_add_attribute(person, uAttr);
|
|
}
|
|
else {
|
|
addritem_free_attribute(uAttr);
|
|
uAttr = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parse list of attributes for person from XML file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
* \param person Person.
|
|
*/
|
|
static void addrbook_parse_attr_list(AddressBookFile *book, XMLFile *file,
|
|
ItemPerson *person)
|
|
{
|
|
GList *attr;
|
|
guint prev_level;
|
|
|
|
for (;;) {
|
|
prev_level = file->level;
|
|
if (xml_parse_next_tag(file)) {
|
|
longjmp( book->jumper, 1 );
|
|
}
|
|
if (file->level < prev_level) return;
|
|
if (xml_compare_tag(file, AB_ELTAG_ATTRIBUTE)) {
|
|
attr = xml_get_current_tag_attr(file);
|
|
addrbook_parse_attribute(file, person);
|
|
addrbook_parse_attr_list(book, file, person);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parse person from XML file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
*/
|
|
static void addrbook_parse_person(AddressBookFile *book, XMLFile *file)
|
|
{
|
|
GList *attr;
|
|
gchar *name, *value;
|
|
ItemPerson *person = NULL;
|
|
|
|
attr = xml_get_current_tag_attr(file);
|
|
while (attr) {
|
|
name = ((XMLAttr *)attr->data)->name;
|
|
value = ((XMLAttr *)attr->data)->value;
|
|
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);
|
|
}
|
|
if (xml_parse_next_tag(file)) { /* Consume closing tag */
|
|
longjmp(book->jumper, 1);
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
if (xml_parse_next_tag(file)) { /* Consume closing tag */
|
|
longjmp(book->jumper, 1);
|
|
}
|
|
if (xml_compare_tag(file, AB_ELTAG_ATTRIBUTE_LIST)) {
|
|
addrbook_parse_attr_list(book, file, person);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parse group member from XML file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
* \param group Group.
|
|
*/
|
|
static void addrbook_parse_member(AddressBookFile *book, XMLFile *file,
|
|
ItemGroup *group)
|
|
{
|
|
GList *attr;
|
|
gchar *name, *value;
|
|
gchar *eid = NULL;
|
|
/* gchar *pid = NULL; */
|
|
ItemEMail *email = NULL;
|
|
|
|
attr = xml_get_current_tag_attr(file);
|
|
while (attr) {
|
|
name = ((XMLAttr *)attr->data)->name;
|
|
value = ((XMLAttr *)attr->data)->value;
|
|
/*
|
|
if (strcmp(name, AB_ATTAG_PID) == 0)
|
|
pid = g_strdup(value);
|
|
else if (strcmp(name, AB_ATTAG_EID) == 0)
|
|
eid = g_strdup(value);
|
|
*/
|
|
if( strcmp( name, AB_ATTAG_EID ) == 0 )
|
|
eid = g_strdup( value );
|
|
attr = g_list_next(attr);
|
|
}
|
|
/* email = addrcache_get_email( book->addressCache, pid, eid ); */
|
|
email = addrcache_get_email(book->addressCache, eid);
|
|
if (email) {
|
|
if (group) {
|
|
addrcache_group_add_email(book->addressCache, group,
|
|
email);
|
|
}
|
|
else {
|
|
addritem_free_item_email(email);
|
|
email = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parse list of group members from XML file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
* \param group Group.
|
|
*/
|
|
static void addrbook_parse_member_list(AddressBookFile *book, XMLFile *file,
|
|
ItemGroup *group)
|
|
{
|
|
GList *attr;
|
|
guint prev_level;
|
|
|
|
for (;;) {
|
|
prev_level = file->level;
|
|
if (xml_parse_next_tag(file)) {
|
|
longjmp(book->jumper, 1);
|
|
}
|
|
if (file->level < prev_level)
|
|
return;
|
|
if (xml_compare_tag(file, AB_ELTAG_MEMBER)) {
|
|
attr = xml_get_current_tag_attr(file);
|
|
addrbook_parse_member(book, file, group);
|
|
addrbook_parse_member_list(book, file, group);
|
|
}
|
|
else {
|
|
attr = xml_get_current_tag_attr(file);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parse group object from XML file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
*/
|
|
static void addrbook_parse_group(AddressBookFile *book, XMLFile *file)
|
|
{
|
|
GList *attr;
|
|
gchar *name, *value;
|
|
ItemGroup *group = NULL;
|
|
|
|
attr = xml_get_current_tag_attr(file);
|
|
while (attr) {
|
|
name = ((XMLAttr *)attr->data)->name;
|
|
value = ((XMLAttr *)attr->data)->value;
|
|
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);
|
|
}
|
|
if (xml_parse_next_tag(file)) { /* Consume closing tag */
|
|
longjmp(book->jumper, 1);
|
|
}
|
|
if (xml_compare_tag(file, AB_ELTAG_MEMBER_LIST)) {
|
|
if (group) {
|
|
addrcache_hash_add_group(book->addressCache, group);
|
|
}
|
|
addrbook_parse_member_list(book, file, group);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parse folder item from XML file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
* \param folder Folder.
|
|
*/
|
|
static void addrbook_parse_folder_item(AddressBookFile *book, XMLFile *file,
|
|
ItemFolder *folder)
|
|
{
|
|
GList *attr;
|
|
gchar *name, *value;
|
|
gchar *uid = NULL;
|
|
|
|
attr = xml_get_current_tag_attr(file);
|
|
while (attr) {
|
|
name = ((XMLAttr *)attr->data)->name;
|
|
value = ((XMLAttr *)attr->data)->value;
|
|
if (strcmp(name, AB_ATTAG_UID) == 0) {
|
|
uid = g_strdup(value);
|
|
}
|
|
attr = g_list_next(attr);
|
|
}
|
|
if (folder) {
|
|
if (uid) {
|
|
folder->listItems = g_list_append(folder->listItems, uid);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parse list of folder items from XML file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
* \param folder Folder.
|
|
*/
|
|
static void addrbook_parse_folder_list(AddressBookFile *book, XMLFile *file,
|
|
ItemFolder *folder)
|
|
{
|
|
GList *attr;
|
|
guint prev_level;
|
|
|
|
for (;;) {
|
|
prev_level = file->level;
|
|
if (xml_parse_next_tag(file)) {
|
|
longjmp(book->jumper, 1);
|
|
}
|
|
if (file->level < prev_level)
|
|
return;
|
|
if (xml_compare_tag(file, AB_ELTAG_ITEM)) {
|
|
attr = xml_get_current_tag_attr(file);
|
|
addrbook_parse_folder_item(book, file, folder);
|
|
addrbook_parse_folder_list(book, file, folder);
|
|
}
|
|
else {
|
|
attr = xml_get_current_tag_attr(file);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parse folder from XML file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
*/
|
|
static void addrbook_parse_folder(AddressBookFile *book, XMLFile *file)
|
|
{
|
|
GList *attr;
|
|
gchar *name, *value;
|
|
ItemFolder *folder = NULL;
|
|
|
|
attr = xml_get_current_tag_attr(file);
|
|
while (attr) {
|
|
name = ((XMLAttr *)attr->data)->name;
|
|
value = ((XMLAttr *)attr->data)->value;
|
|
if (!folder)
|
|
folder = addritem_create_item_folder();
|
|
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;
|
|
}
|
|
}
|
|
addrbook_parse_folder_list(book, file, folder);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Read address book (DOM) tree from file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
* \return <i>TRUE</i> if data read successfully, <i>FALSE</i> if error
|
|
* reading data.
|
|
*/
|
|
static gboolean addrbook_read_tree(AddressBookFile *book, XMLFile *file)
|
|
{
|
|
gboolean retVal;
|
|
GList *attr;
|
|
gchar *name, *value;
|
|
|
|
book->retVal = MGU_BAD_FORMAT;
|
|
if (xml_get_dtd(file))
|
|
return FALSE;
|
|
if (xml_parse_next_tag(file))
|
|
longjmp(book->jumper, 1);
|
|
if (!xml_compare_tag(file, AB_ELTAG_ADDRESS_BOOK))
|
|
return FALSE;
|
|
|
|
attr = xml_get_current_tag_attr(file);
|
|
while (attr) {
|
|
name = ((XMLAttr *)attr->data)->name;
|
|
value = ((XMLAttr *)attr->data)->value;
|
|
if (strcmp( name, AB_ATTAG_NAME) == 0)
|
|
addrbook_set_name( book, value );
|
|
attr = g_list_next( attr );
|
|
}
|
|
|
|
retVal = TRUE;
|
|
for (;;) {
|
|
if (!file->level)
|
|
break;
|
|
/* Get next item tag (person, group or folder) */
|
|
if (xml_parse_next_tag(file))
|
|
longjmp( book->jumper, 1 );
|
|
|
|
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);
|
|
}
|
|
if (retVal) book->retVal = MGU_SUCCESS;
|
|
return retVal;
|
|
}
|
|
|
|
/**
|
|
* Resolve folder items callback function.
|
|
* \param key Table key.
|
|
* \param value Reference to object contained in folder.
|
|
* \param data Reference to address book.
|
|
*/
|
|
static void addrbook_res_items_vis(gpointer key, gpointer value, gpointer data)
|
|
{
|
|
AddressBookFile *book = data;
|
|
AddrItemObject *obj = (AddrItemObject *) value;
|
|
ItemFolder *rootFolder = book->addressCache->rootFolder;
|
|
if (obj->parent == NULL) {
|
|
if (ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON) {
|
|
rootFolder->listPerson = g_list_append(rootFolder->listPerson,
|
|
obj);
|
|
ADDRITEM_PARENT(obj) = ADDRITEM_OBJECT(rootFolder);
|
|
}
|
|
else if (ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP) {
|
|
rootFolder->listGroup = g_list_append(rootFolder->listGroup,
|
|
obj);
|
|
ADDRITEM_PARENT(obj) = ADDRITEM_OBJECT(rootFolder);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resolve folder items. Lists of UID's are replaced with pointers to
|
|
* data items.
|
|
* \param book Address book.
|
|
*/
|
|
static void addrbook_resolve_folder_items(AddressBookFile *book)
|
|
{
|
|
GList *nodeFolder = NULL;
|
|
GList *listRemove = NULL;
|
|
GList *node = NULL;
|
|
ItemFolder *rootFolder = book->addressCache->rootFolder;
|
|
nodeFolder = book->tempList;
|
|
|
|
while (nodeFolder) {
|
|
ItemFolder *folder = nodeFolder->data;
|
|
listRemove = NULL;
|
|
node = folder->listItems;
|
|
while (node) {
|
|
gchar *uid = node->data;
|
|
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);
|
|
ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder);
|
|
addrcache_hash_add_folder(book->addressCache, folder);
|
|
}
|
|
else if (aio->type == ITEMTYPE_PERSON) {
|
|
ItemPerson *item = (ItemPerson *) aio;
|
|
folder->listPerson = g_list_append(folder->listPerson, item);
|
|
ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder);
|
|
}
|
|
else if (aio->type == ITEMTYPE_GROUP) {
|
|
ItemGroup *item = (ItemGroup *) aio;
|
|
folder->listGroup = g_list_append(folder->listGroup, item);
|
|
ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder);
|
|
}
|
|
/* Replace data with pointer to item */
|
|
g_free(uid);
|
|
node->data = aio;
|
|
}
|
|
else { /* Not found, append to remove list. */
|
|
listRemove = g_list_append(listRemove, uid);
|
|
}
|
|
node = g_list_next(node);
|
|
}
|
|
rootFolder->listFolder = g_list_append(rootFolder->listFolder,
|
|
folder);
|
|
/* Process remove list */
|
|
node = listRemove;
|
|
while (node) {
|
|
gchar *uid = node->data;
|
|
folder->listItems = g_list_remove(folder->listItems,
|
|
uid);
|
|
g_free(uid);
|
|
node = g_list_next(node);
|
|
}
|
|
g_list_free(listRemove);
|
|
nodeFolder = g_list_next(nodeFolder);
|
|
}
|
|
/* Remove folders with parents. */
|
|
listRemove = NULL;
|
|
node = rootFolder->listFolder;
|
|
while (node) {
|
|
ItemFolder *folder = (ItemFolder *) node->data;
|
|
if (ADDRITEM_PARENT(folder))
|
|
/* Remove folders with parents */
|
|
listRemove = g_list_append(listRemove, folder);
|
|
else /* Add to root folder */
|
|
ADDRITEM_PARENT(folder) = ADDRITEM_OBJECT(book->addressCache->rootFolder);
|
|
|
|
node = g_list_next( node );
|
|
}
|
|
/* Process remove list */
|
|
node = listRemove;
|
|
while (node) {
|
|
rootFolder->listFolder = g_list_remove(rootFolder->listFolder,
|
|
node->data);
|
|
node = g_list_next(node);
|
|
}
|
|
g_list_free(listRemove);
|
|
|
|
/* Move all unparented persons and groups into root folder */
|
|
g_hash_table_foreach(book->addressCache->itemHash,
|
|
addrbook_res_items_vis, book);
|
|
|
|
/* Free up some more */
|
|
nodeFolder = book->tempList;
|
|
while (nodeFolder) {
|
|
ItemFolder *folder = nodeFolder->data;
|
|
g_list_free(folder->listItems);
|
|
folder->listItems = NULL;
|
|
nodeFolder = g_list_next(nodeFolder);
|
|
}
|
|
g_list_free(book->tempList);
|
|
book->tempList = NULL;
|
|
}
|
|
|
|
/**
|
|
* Read address book.
|
|
* \param book Address book.
|
|
* \return Status code.
|
|
*/
|
|
gint addrbook_read_data(AddressBookFile *book)
|
|
{
|
|
XMLFile *file = NULL;
|
|
gchar *fileSpec = NULL;
|
|
|
|
g_return_val_if_fail(book != NULL, -1);
|
|
|
|
/*
|
|
printf( "...addrbook_read_data :%s:\t:%s:\n", book->fileName,
|
|
addrcache_get_name( book->addressCache ) );
|
|
*/
|
|
|
|
fileSpec = g_strconcat(book->path, G_DIR_SEPARATOR_S,
|
|
book->fileName, NULL);
|
|
book->retVal = MGU_OPEN_FILE;
|
|
addrcache_clear(book->addressCache);
|
|
book->addressCache->modified = FALSE;
|
|
book->addressCache->accessFlag = FALSE;
|
|
file = xml_open_file(fileSpec);
|
|
g_free(fileSpec);
|
|
if (file) {
|
|
book->tempList = NULL;
|
|
/* Trap for parsing errors. */
|
|
if (setjmp( book->jumper)) {
|
|
xml_close_file(file);
|
|
return book->retVal;
|
|
}
|
|
addrbook_read_tree(book, file);
|
|
xml_close_file(file);
|
|
/* Resolve folder items */
|
|
addrbook_resolve_folder_items(book);
|
|
book->tempList = NULL;
|
|
book->addressCache->modified = FALSE;
|
|
book->addressCache->dataRead = TRUE;
|
|
addrcache_set_dirty(book->addressCache, FALSE);
|
|
}
|
|
return book->retVal;
|
|
}
|
|
|
|
/**
|
|
* Write start element to file.
|
|
* \param fp File handle.
|
|
* \param lvl Indent level.
|
|
* \param name Element name.
|
|
*/
|
|
static void addrbook_write_elem_s(FILE *fp, gint lvl, gchar *name)
|
|
{
|
|
gint i;
|
|
for (i = 0; i < lvl; i++)
|
|
fputs(" ", fp);
|
|
fputs("<", fp);
|
|
fputs(name, fp);
|
|
}
|
|
|
|
/**
|
|
* Write end element to file.
|
|
* \param fp File handle.
|
|
* \param lvl Indent level.
|
|
* \param name Element name.
|
|
*/
|
|
static void addrbook_write_elem_e(FILE *fp, gint lvl, gchar *name)
|
|
{
|
|
gint i;
|
|
for(i = 0; i < lvl; i++)
|
|
fputs(" ", fp);
|
|
fputs("</", fp);
|
|
fputs(name, fp);
|
|
fputs(">\n", fp);
|
|
}
|
|
|
|
/**
|
|
* Write attribute name/value pair to file.
|
|
* \param fp File handle.
|
|
* \param name Attribute name.
|
|
* \param value Attribute value.
|
|
*/
|
|
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);
|
|
}
|
|
|
|
/**
|
|
* Write person and associated addresses and attributes to file.
|
|
* file hash table visitor function.
|
|
* \param key Table key.
|
|
* \param value Reference to person.
|
|
* \param data File pointer.
|
|
*/
|
|
static void addrbook_write_item_person_vis(gpointer key, gpointer value,
|
|
gpointer data)
|
|
{
|
|
AddrItemObject *obj = (AddrItemObject *) value;
|
|
FILE *fp = (FILE *) data;
|
|
GList *node;
|
|
|
|
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);
|
|
|
|
/* Output email addresses */
|
|
addrbook_write_elem_s(fp, 2, AB_ELTAG_ADDRESS_LIST);
|
|
fputs(">\n", fp);
|
|
node = person->listEMail;
|
|
while (node) {
|
|
ItemEMail *email = node->data;
|
|
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);
|
|
}
|
|
addrbook_write_elem_e(fp, 2, AB_ELTAG_ADDRESS_LIST);
|
|
|
|
/* Output user attributes */
|
|
addrbook_write_elem_s(fp, 2, AB_ELTAG_ATTRIBUTE_LIST);
|
|
fputs(">\n", fp);
|
|
node = person->listAttrib;
|
|
while (node) {
|
|
UserAttribute *attrib = node->data;
|
|
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);
|
|
}
|
|
addrbook_write_elem_e(fp, 2, AB_ELTAG_ATTRIBUTE_LIST);
|
|
addrbook_write_elem_e(fp, 1, AB_ELTAG_PERSON);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Write group and associated references to addresses to file.
|
|
* file hash table visitor function.
|
|
* \param key Table key.
|
|
* \param value Reference to group.
|
|
* \param data File pointer.
|
|
*/
|
|
static void addrbook_write_item_group_vis(gpointer key, gpointer value,
|
|
gpointer data)
|
|
{
|
|
AddrItemObject *obj = (AddrItemObject *) value;
|
|
FILE *fp = (FILE *) data;
|
|
GList *node;
|
|
|
|
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);
|
|
|
|
/* Output email address links */
|
|
addrbook_write_elem_s(fp, 2, AB_ELTAG_MEMBER_LIST);
|
|
fputs(">\n", fp);
|
|
node = group->listEMail;
|
|
while (node) {
|
|
ItemEMail *email = node->data;
|
|
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);
|
|
}
|
|
addrbook_write_elem_e(fp, 2, AB_ELTAG_MEMBER_LIST);
|
|
addrbook_write_elem_e(fp, 1, AB_ELTAG_GROUP);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Write folder and associated references to addresses to file.
|
|
* file hash table visitor function.
|
|
* \param key Table key.
|
|
* \param value Reference to folder.
|
|
* \param data File pointer.
|
|
*/
|
|
static void addrbook_write_item_folder_vis(gpointer key, gpointer value,
|
|
gpointer data)
|
|
{
|
|
AddrItemObject *obj = (AddrItemObject *) value;
|
|
FILE *fp = (FILE *) data;
|
|
GList *node;
|
|
|
|
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);
|
|
|
|
/* Output persons */
|
|
node = folder->listPerson;
|
|
while (node) {
|
|
ItemPerson *item = node->data;
|
|
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);
|
|
}
|
|
|
|
/* Output groups */
|
|
node = folder->listGroup;
|
|
while (node) {
|
|
ItemGroup *item = node->data;
|
|
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);
|
|
}
|
|
|
|
/* Output folders */
|
|
node = folder->listFolder;
|
|
while (node) {
|
|
ItemFolder *item = node->data;
|
|
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);
|
|
}
|
|
addrbook_write_elem_e(fp, 2, AB_ELTAG_ITEM_LIST);
|
|
addrbook_write_elem_e(fp, 1, AB_ELTAG_FOLDER);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Output address book data to specified file.
|
|
* \param book Address book.
|
|
* \param newFile Filename of new file (in book's filepath).
|
|
* \return Status code.
|
|
*/
|
|
gint addrbook_write_to(AddressBookFile *book, gchar *newFile)
|
|
{
|
|
FILE *fp;
|
|
gchar *fileSpec;
|
|
#ifndef DEV_STANDALONE
|
|
PrefFile *pfile;
|
|
#endif
|
|
|
|
g_return_val_if_fail(book != NULL, -1);
|
|
g_return_val_if_fail(newFile != NULL, -1);
|
|
|
|
fileSpec = g_strconcat(book->path, G_DIR_SEPARATOR_S, newFile, NULL);
|
|
|
|
book->retVal = MGU_OPEN_FILE;
|
|
#ifdef DEV_STANDALONE
|
|
fp = g_fopen(fileSpec, "wb");
|
|
g_free(fileSpec);
|
|
if (fp) {
|
|
fputs("<?xml version=\"1.0\" ?>\n", fp);
|
|
#else
|
|
pfile = prefs_write_open(fileSpec);
|
|
g_free(fileSpec);
|
|
if (pfile) {
|
|
fp = pfile->fp;
|
|
fprintf( fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n", CS_INTERNAL );
|
|
#endif
|
|
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);
|
|
|
|
/* Output all persons */
|
|
g_hash_table_foreach(book->addressCache->itemHash,
|
|
addrbook_write_item_person_vis, fp);
|
|
|
|
/* Output all groups */
|
|
g_hash_table_foreach(book->addressCache->itemHash,
|
|
addrbook_write_item_group_vis, fp);
|
|
|
|
/* Output all folders */
|
|
g_hash_table_foreach(book->addressCache->itemHash,
|
|
addrbook_write_item_folder_vis, fp);
|
|
|
|
addrbook_write_elem_e(fp, 0, AB_ELTAG_ADDRESS_BOOK);
|
|
book->retVal = MGU_SUCCESS;
|
|
#ifdef DEV_STANDALONE
|
|
fclose(fp);
|
|
#else
|
|
if (prefs_file_close( pfile ) < 0)
|
|
book->retVal = MGU_ERROR_WRITE;
|
|
#endif
|
|
}
|
|
|
|
fileSpec = NULL;
|
|
return book->retVal;
|
|
}
|
|
|
|
/**
|
|
* Output address book data to original file.
|
|
* \param book Address book.
|
|
* \return Status code.
|
|
*/
|
|
gint addrbook_save_data(AddressBookFile *book)
|
|
{
|
|
g_return_val_if_fail(book != NULL, -1);
|
|
|
|
book->retVal = MGU_NO_FILE;
|
|
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);
|
|
return book->retVal;
|
|
}
|
|
|
|
/*
|
|
* **********************************************************************
|
|
* Address book edit interface functions.
|
|
* **********************************************************************
|
|
*/
|
|
|
|
/**
|
|
* Move email item within list of person's email items.
|
|
* \param book Address book.
|
|
* \param person Person.
|
|
* \param itemMove EMail item to move.
|
|
* \param itemTarget EMail item to move before.
|
|
* \return Moved item.
|
|
*/
|
|
ItemEMail *addrbook_move_email_before(AddressBookFile *book, ItemPerson *person,
|
|
ItemEMail *itemMove, ItemEMail *itemTarget)
|
|
{
|
|
ItemEMail *email = NULL;
|
|
|
|
g_return_val_if_fail(book != NULL, NULL);
|
|
|
|
email = addritem_move_email_before(person, itemMove, itemTarget);
|
|
if (email)
|
|
addrcache_set_dirty(book->addressCache, TRUE);
|
|
return email;
|
|
}
|
|
|
|
/**
|
|
* Move email item within list of person's email items.
|
|
* \param book Address book.
|
|
* \param person Person.
|
|
* \param itemMove EMail item to move.
|
|
* \param itemTarget EMail item after which to move.
|
|
* \return Moved item.
|
|
*/
|
|
ItemEMail *addrbook_move_email_after(AddressBookFile *book, ItemPerson *person,
|
|
ItemEMail *itemMove, ItemEMail *itemTarget)
|
|
{
|
|
ItemEMail *email = NULL;
|
|
|
|
g_return_val_if_fail(book != NULL, NULL);
|
|
|
|
email = addritem_move_email_after(person, itemMove, itemTarget);
|
|
if (email)
|
|
addrcache_set_dirty(book->addressCache, TRUE);
|
|
return email;
|
|
}
|
|
|
|
/**
|
|
* Hash table callback function for simple deletion of hashtable entries.
|
|
* \param key Table key (will be freed).
|
|
* \param value Value stored in table.
|
|
* \param data User data.
|
|
* \return <i>TRUE</i> to indicate that entry freed.
|
|
*/
|
|
static gboolean addrbook_free_simple_hash_vis(gpointer *key, gpointer *value,
|
|
gpointer *data)
|
|
{
|
|
g_free(key);
|
|
key = NULL;
|
|
value = NULL;
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* Update address book email list for specified person. 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.
|
|
* \param book Address book.
|
|
* \param person Person to update.
|
|
* \param listEMail List of new email addresses.
|
|
*/
|
|
void addrbook_update_address_list(AddressBookFile *book, ItemPerson *person,
|
|
GList *listEMail)
|
|
{
|
|
GList *node;
|
|
GList *listDelete;
|
|
GList *listGroup;
|
|
|
|
g_return_if_fail(book != NULL);
|
|
g_return_if_fail(person != NULL);
|
|
|
|
/* Get groups where person's existing email addresses are listed */
|
|
listGroup = addrcache_get_group_for_person(book->addressCache, person);
|
|
if (listGroup) {
|
|
GHashTable *hashEMail;
|
|
GHashTable *hashEMailAlias;
|
|
GList *nodeGrp;
|
|
|
|
/* Load hash table with new address entries */
|
|
hashEMail = g_hash_table_new(g_str_hash, g_str_equal);
|
|
hashEMailAlias = g_hash_table_new(g_str_hash, g_str_equal);
|
|
node = listEMail;
|
|
while (node) {
|
|
ItemEMail *email = node->data;
|
|
gchar *addr = g_strdup(email->address);
|
|
gchar *alias = email->obj.name ;
|
|
g_strdown(addr);
|
|
if (!g_hash_table_lookup(hashEMail, addr)) {
|
|
g_hash_table_insert(hashEMail, addr, email);
|
|
}
|
|
if (*alias != '\0' && ! g_hash_table_lookup(hashEMailAlias,
|
|
alias))
|
|
g_hash_table_insert(hashEMailAlias, alias, email);
|
|
|
|
node = g_list_next(node);
|
|
}
|
|
|
|
/* Re-parent new addresses to existing groups, where email address match. */
|
|
nodeGrp = listGroup;
|
|
while (nodeGrp) {
|
|
ItemGroup *group = (ItemGroup *) nodeGrp->data;
|
|
GList *groupEMail = group->listEMail;
|
|
GList *nodeGrpEM;
|
|
GList *listRemove = NULL;
|
|
|
|
/* Process each email item linked to group */
|
|
nodeGrpEM = groupEMail;
|
|
while (nodeGrpEM) {
|
|
ItemEMail *emailGrp = (ItemEMail *) nodeGrpEM->data;
|
|
|
|
if (ADDRITEM_PARENT(emailGrp) == ADDRITEM_OBJECT(person)) {
|
|
/* Found an email address for this person */
|
|
ItemEMail *emailNew = NULL;
|
|
gchar *addr = g_strdup(emailGrp->address);
|
|
gchar *alias = emailGrp->obj.name;
|
|
g_strdown(addr);
|
|
emailNew = (ItemEMail *)
|
|
g_hash_table_lookup(hashEMail, addr);
|
|
g_free( addr );
|
|
/* If no match by e-mail, try to match by e-mail alias */
|
|
if (!emailNew && *alias != '\0') {
|
|
emailNew = (ItemEMail *)
|
|
g_hash_table_lookup(hashEMailAlias, alias);
|
|
}
|
|
|
|
if (emailNew)
|
|
/* Point to this entry */
|
|
nodeGrpEM->data = emailNew;
|
|
else if (g_hash_table_size(hashEMail)==1)
|
|
/* If the person has just one e-mail address, then
|
|
change e-mail address in group list */
|
|
nodeGrpEM->data = listEMail->data;
|
|
else
|
|
/* Mark for removal */
|
|
listRemove = g_list_append(listRemove, emailGrp);
|
|
}
|
|
/* Move on to next email link */
|
|
nodeGrpEM = g_list_next(nodeGrpEM);
|
|
}
|
|
|
|
/* Process all removed links in current group */
|
|
nodeGrpEM = listRemove;
|
|
while (nodeGrpEM) {
|
|
ItemEMail *emailGrp = nodeGrpEM->data;
|
|
groupEMail = g_list_remove(groupEMail, emailGrp);
|
|
nodeGrpEM = g_list_next(nodeGrpEM);
|
|
}
|
|
|
|
g_list_free(listRemove);
|
|
|
|
/* Move on to next group */
|
|
nodeGrp = g_list_next(nodeGrp);
|
|
|
|
}
|
|
/* Clear hash table */
|
|
g_hash_table_foreach_remove(hashEMail, (GHRFunc)
|
|
addrbook_free_simple_hash_vis, NULL);
|
|
g_hash_table_destroy(hashEMail);
|
|
hashEMail = NULL;
|
|
g_hash_table_destroy(hashEMailAlias);
|
|
hashEMailAlias = NULL;
|
|
g_list_free(listGroup);
|
|
listGroup = NULL;
|
|
}
|
|
/* Remove old addresses from person and cache */
|
|
listDelete = NULL;
|
|
node = person->listEMail;
|
|
while (node) {
|
|
ItemEMail *email = node->data;
|
|
|
|
if (addrcache_person_remove_email(book->addressCache, person, email))
|
|
addrcache_remove_email(book->addressCache, email);
|
|
|
|
listDelete = g_list_append(listDelete, email);
|
|
node = person->listEMail;
|
|
}
|
|
/* Add new address entries */
|
|
node = listEMail;
|
|
while (node) {
|
|
ItemEMail *email = node->data;
|
|
|
|
if (ADDRITEM_ID(email) == NULL)
|
|
/* Allocate an ID for new address */
|
|
addrcache_id_email(book->addressCache, email);
|
|
|
|
addrcache_person_add_email( book->addressCache, person, email );
|
|
node = g_list_next( node );
|
|
}
|
|
|
|
addrcache_set_dirty(book->addressCache, TRUE);
|
|
|
|
/* Free up memory */
|
|
g_list_free(listEMail);
|
|
listEMail = NULL;
|
|
|
|
node = listDelete;
|
|
while (node) {
|
|
ItemEMail *email = node->data;
|
|
|
|
addritem_free_item_email(email);
|
|
node = g_list_next(node);
|
|
}
|
|
g_list_free(listDelete);
|
|
listDelete = NULL;
|
|
|
|
}
|
|
|
|
/**
|
|
* Create person object and add person with specified address data to address
|
|
* book. Note: A new person is created with specified list of email addresses.
|
|
* All objects inserted into address book.
|
|
*
|
|
* \param book Address book.
|
|
* \param folder Parent folder where to add person, or <i>NULL</i> for
|
|
* root folder.
|
|
* \param listEMail List of new email addresses to associate with person.
|
|
* \return Person object created.
|
|
*/
|
|
ItemPerson *addrbook_add_address_list(AddressBookFile *book, ItemFolder *folder,
|
|
GList *listEMail)
|
|
{
|
|
ItemPerson *person;
|
|
ItemFolder *f = folder;
|
|
GList *node;
|
|
|
|
g_return_val_if_fail(book != NULL, NULL);
|
|
|
|
if (!f)
|
|
f = book->addressCache->rootFolder;
|
|
person = addritem_create_item_person();
|
|
addrcache_id_person(book->addressCache, person);
|
|
addrcache_folder_add_person(book->addressCache, f, person);
|
|
|
|
node = listEMail;
|
|
while (node) {
|
|
ItemEMail *email = node->data;
|
|
if (ADDRITEM_ID(email) == NULL)
|
|
addrcache_id_email(book->addressCache, email);
|
|
|
|
addrcache_person_add_email(book->addressCache, person, email);
|
|
node = g_list_next(node);
|
|
}
|
|
return person;
|
|
}
|
|
|
|
/**
|
|
* Build available email list visitor function.
|
|
* \param key Table key.
|
|
* \param value Value stored in table.
|
|
* \param data Reference to address book.
|
|
*/
|
|
static void addrbook_build_avail_email_vis(gpointer key, gpointer value,
|
|
gpointer data)
|
|
{
|
|
AddrItemObject *obj = (AddrItemObject *) value;
|
|
|
|
if (ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON) {
|
|
AddressBookFile *book = data;
|
|
ItemPerson *person = (ItemPerson *) obj;
|
|
GList *node = person->listEMail;
|
|
while (node) {
|
|
ItemEMail *email = node->data;
|
|
/* gchar *newKey = g_strdup( ADDRITEM_ID(email) ); */
|
|
|
|
if (!g_hash_table_lookup(book->tempHash,
|
|
ADDRITEM_ID(email)))
|
|
book->tempList = g_list_append(book->tempList, email);
|
|
|
|
node = g_list_next(node);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return link list of available email items that have not already been linked
|
|
* to groups. Note that the list contains references to items and should be
|
|
* <code>g_free()</code> when done. Do <b>*NOT*</b> attempt to used the
|
|
* <code>addrbook_free_xxx()<code> functions... this will destroy the
|
|
* addressbook data!
|
|
*
|
|
* \param book Address book.
|
|
* \param group Group to process.
|
|
* \return List of items, or <i>NULL</i> if none.
|
|
*/
|
|
GList *addrbook_get_available_email_list(AddressBookFile *book, ItemGroup *group)
|
|
{
|
|
GList *list = NULL;
|
|
GHashTable *table;
|
|
|
|
g_return_val_if_fail(book != NULL, NULL);
|
|
|
|
/* Load hash table with group email entries */
|
|
table = g_hash_table_new(g_str_hash, g_str_equal);
|
|
if (group) {
|
|
list = group->listEMail;
|
|
while (list) {
|
|
ItemEMail *email = list->data;
|
|
g_hash_table_insert(table, ADDRITEM_ID(email), email);
|
|
list = g_list_next(list);
|
|
}
|
|
}
|
|
|
|
/* Build list of available email addresses which exclude those already in groups */
|
|
book->tempList = NULL;
|
|
book->tempHash = table;
|
|
g_hash_table_foreach(book->addressCache->itemHash,
|
|
addrbook_build_avail_email_vis, book);
|
|
list = book->tempList;
|
|
book->tempList = NULL;
|
|
book->tempHash = NULL;
|
|
|
|
/* Clear hash table */
|
|
g_hash_table_destroy(table);
|
|
table = NULL;
|
|
|
|
return list;
|
|
}
|
|
|
|
/**
|
|
* Update address book email list for specified group. 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.
|
|
*
|
|
* \param book Address book.
|
|
* \param group Group to process.
|
|
* \param listEMail List of email items. This should <b>*NOT*</b> be
|
|
* <code>g_free()</code> when done.
|
|
*/
|
|
void addrbook_update_group_list(AddressBookFile *book, ItemGroup *group,
|
|
GList *listEMail)
|
|
{
|
|
GList *oldData;
|
|
|
|
g_return_if_fail(book != NULL);
|
|
g_return_if_fail(group != NULL);
|
|
|
|
addrcache_set_dirty(book->addressCache, TRUE);
|
|
|
|
/* Remember old list */
|
|
oldData = group->listEMail;
|
|
group->listEMail = listEMail;
|
|
mgu_clear_list(oldData);
|
|
oldData = NULL;
|
|
}
|
|
|
|
/**
|
|
* Create group object and add with specifed list of email addresses to
|
|
* address book. 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.
|
|
*
|
|
* \param book Address book.
|
|
* \param folder Parent folder where to add group, or <i>NULL</i> for
|
|
* root folder.
|
|
* \param listEMail List of email items. This should <b>*NOT*</b> be
|
|
* <code>g_free()</code> when done.
|
|
* \return Group object created.
|
|
*/
|
|
ItemGroup *addrbook_add_group_list(AddressBookFile *book, ItemFolder *folder,
|
|
GList *listEMail)
|
|
{
|
|
ItemGroup *group = NULL;
|
|
ItemFolder *f = folder;
|
|
|
|
g_return_val_if_fail(book != NULL, NULL);
|
|
|
|
if (!f)
|
|
f = book->addressCache->rootFolder;
|
|
group = addritem_create_item_group();
|
|
addrcache_id_group(book->addressCache, group);
|
|
addrcache_folder_add_group(book->addressCache, f, group);
|
|
group->listEMail = listEMail;
|
|
return group;
|
|
}
|
|
|
|
/**
|
|
* Create a new folder and add to address book.
|
|
* \param book Address book.
|
|
* \param folder Parent folder where to add folder, or <i>NULL</i> for
|
|
* root folder.
|
|
* \return Folder that was created. This should <b>*NOT*</b> be
|
|
* <code>g_free()</code> when done.
|
|
*/
|
|
ItemFolder *addrbook_add_new_folder(AddressBookFile *book, ItemFolder *parent)
|
|
{
|
|
g_return_val_if_fail(book != NULL, NULL);
|
|
return addrcache_add_new_folder( book->addressCache, parent );
|
|
}
|
|
#if 0
|
|
{
|
|
ItemFolder *folder = NULL;
|
|
ItemFolder *p = parent;
|
|
|
|
g_return_val_if_fail(book != NULL, NULL);
|
|
|
|
if (!p)
|
|
p = book->addressCache->rootFolder;
|
|
folder = addritem_create_item_folder();
|
|
addrcache_id_folder(book->addressCache, folder);
|
|
if (addrcache_hash_add_folder(book->addressCache, folder)) {
|
|
p->listFolder = g_list_append(p->listFolder, folder);
|
|
ADDRITEM_PARENT(folder) = ADDRITEM_OBJECT(p);
|
|
addrcache_set_dirty(book->addressCache, TRUE);
|
|
}
|
|
else {
|
|
addritem_free_item_folder(folder);
|
|
folder = NULL;
|
|
}
|
|
return folder;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* Update address book attribute list for specified person. Note: The existing
|
|
* attributes are replaced with the new addresses. All old attributes linked
|
|
* to the person are removed.
|
|
*
|
|
* \param book Address book.
|
|
* \param person Person to receive attributes.
|
|
* \param listAttrib New list of attributes.
|
|
*/
|
|
void addrbook_update_attrib_list(AddressBookFile *book, ItemPerson *person,
|
|
GList *listAttrib)
|
|
{
|
|
GList *node;
|
|
GList *oldData;
|
|
|
|
g_return_if_fail(book != NULL);
|
|
g_return_if_fail(person != NULL);
|
|
|
|
/* Remember old list */
|
|
oldData = person->listAttrib;
|
|
|
|
/* Attach new address list to person. */
|
|
node = listAttrib;
|
|
while (node) {
|
|
UserAttribute *attrib = node->data;
|
|
if (attrib->uid == NULL) {
|
|
/* Allocate an ID */
|
|
addrcache_id_attribute(book->addressCache, attrib);
|
|
}
|
|
node = g_list_next(node);
|
|
}
|
|
person->listAttrib = listAttrib;
|
|
addrcache_set_dirty(book->addressCache, TRUE);
|
|
|
|
/* Free up old data */
|
|
addritem_free_list_attribute(oldData);
|
|
oldData = NULL;
|
|
}
|
|
|
|
/**
|
|
* Add attribute data for specified person to address book. Note: Only
|
|
* attributes are inserted into address book.
|
|
* \param book Address book.
|
|
* \param person Person to receive attributes.
|
|
* \param listAttrib List of attributes.
|
|
*/
|
|
void addrbook_add_attrib_list( AddressBookFile *book, ItemPerson *person, GList *listAttrib ) {
|
|
GList *node;
|
|
|
|
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 );
|
|
}
|
|
|
|
/*
|
|
* Return reference to address book file for specified object by traversing up
|
|
* address book heirarchy.
|
|
*
|
|
* \param aio Book item object.
|
|
* \return Address book, or <i>NULL</i> if not found.
|
|
*/
|
|
AddressBookFile *addrbook_item_get_bookfile(AddrItemObject *aio)
|
|
{
|
|
AddressBookFile *book = NULL;
|
|
|
|
if (aio) {
|
|
ItemFolder *parent = NULL;
|
|
ItemFolder *root = NULL;
|
|
if (aio->type == ITEMTYPE_EMAIL) {
|
|
ItemPerson *person = (ItemPerson *)ADDRITEM_PARENT(aio);
|
|
if( person )
|
|
parent = (ItemFolder *)ADDRITEM_PARENT(person);
|
|
}
|
|
else {
|
|
parent = (ItemFolder *)ADDRITEM_PARENT(aio);
|
|
}
|
|
if (parent)
|
|
root = addrcache_find_root_folder(parent);
|
|
if (root)
|
|
book = (AddressBookFile *)ADDRITEM_PARENT(root);
|
|
}
|
|
return book;
|
|
}
|
|
|
|
/**
|
|
* Remove folder from address book. Children are re-parented to the parent
|
|
* folder.
|
|
* \param book Address book.
|
|
* \param folder Folder to remove.
|
|
* \return Folder, or <i>NULL</i> if not found. Note that object should still
|
|
* be freed.
|
|
*/
|
|
ItemFolder *addrbook_remove_folder(AddressBookFile *book, ItemFolder *folder)
|
|
{
|
|
ItemFolder *f;
|
|
|
|
g_return_val_if_fail(book != NULL, NULL);
|
|
|
|
f = addrcache_remove_folder(book->addressCache, folder);
|
|
return f;
|
|
}
|
|
|
|
/**
|
|
* Remove folder from address book. Children are deleted.
|
|
* \param book Address book.
|
|
* \param folder Folder to remove.
|
|
* \return Folder, or <i>NULL</i> if not found. Note that object should still
|
|
* be freed.
|
|
*/
|
|
ItemFolder *addrbook_remove_folder_delete(AddressBookFile *book,
|
|
ItemFolder *folder)
|
|
{
|
|
ItemFolder *f;
|
|
|
|
g_return_val_if_fail(book != NULL, NULL);
|
|
|
|
f = addrcache_remove_folder_delete(book->addressCache, folder);
|
|
return f;
|
|
}
|
|
|
|
#define WORK_BUFLEN 1024
|
|
#define ADDRBOOK_DIGITS "0123456789"
|
|
|
|
/**
|
|
* Return list of existing address book files.
|
|
* \param book Address book.
|
|
* \return List of files (as strings).
|
|
*/
|
|
GList *addrbook_get_bookfile_list(AddressBookFile *book) {
|
|
gchar *adbookdir;
|
|
GDir *dir;
|
|
const gchar *dir_name;
|
|
struct stat statbuf;
|
|
gchar buf[WORK_BUFLEN];
|
|
gchar numbuf[WORK_BUFLEN];
|
|
gint len, lenpre, lensuf, lennum;
|
|
long int val, maxval;
|
|
GList *fileList = NULL;
|
|
|
|
g_return_val_if_fail(book != NULL, NULL);
|
|
|
|
if (book->path == NULL || *book->path == '\0') {
|
|
book->retVal = MGU_NO_PATH;
|
|
return NULL;
|
|
}
|
|
|
|
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';
|
|
}
|
|
}
|
|
|
|
adbookdir = g_strdup(buf);
|
|
strcat(buf, ADDRBOOK_PREFIX);
|
|
|
|
if( ( dir = g_dir_open( adbookdir, 0, NULL ) ) == NULL ) {
|
|
book->retVal = MGU_OPEN_DIRECTORY;
|
|
g_free(adbookdir);
|
|
return NULL;
|
|
}
|
|
|
|
lenpre = strlen(ADDRBOOK_PREFIX);
|
|
lensuf = strlen(ADDRBOOK_SUFFIX);
|
|
lennum = FILE_NUMDIGITS + lenpre;
|
|
maxval = -1;
|
|
|
|
while( ( dir_name = g_dir_read_name( dir ) ) != NULL ) {
|
|
gchar *endptr = NULL;
|
|
gint i;
|
|
gboolean flg;
|
|
|
|
strcpy(buf, adbookdir);
|
|
strcat( buf, dir_name );
|
|
stat(buf, &statbuf);
|
|
if (S_ISREG(statbuf.st_mode)) {
|
|
if (strncmp(
|
|
dir_name,
|
|
ADDRBOOK_PREFIX, lenpre) == 0)
|
|
{
|
|
if (strncmp(
|
|
(dir_name) + lennum,
|
|
ADDRBOOK_SUFFIX, lensuf) == 0)
|
|
{
|
|
strncpy(numbuf,
|
|
(dir_name) + lenpre,
|
|
FILE_NUMDIGITS);
|
|
numbuf[FILE_NUMDIGITS] = '\0';
|
|
flg = TRUE;
|
|
for(i = 0; i < FILE_NUMDIGITS; i++) {
|
|
if(!strchr(ADDRBOOK_DIGITS, numbuf[i])) {
|
|
flg = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
if (flg) {
|
|
/* Get value */
|
|
val = strtol(numbuf, &endptr, 10);
|
|
if (endptr && val > -1) {
|
|
if (val > maxval) maxval = val;
|
|
fileList = g_list_append(
|
|
fileList,
|
|
g_strdup(dir_name));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
g_dir_close( dir );
|
|
g_free(adbookdir);
|
|
|
|
book->maxValue = maxval;
|
|
book->retVal = MGU_SUCCESS;
|
|
return fileList;
|
|
}
|
|
|
|
/**
|
|
* Return file name for specified file number.
|
|
* \param fileNum File number.
|
|
* \return File name, or <i>NULL</i> if file number too large. Should be
|
|
* <code>g_free()</code> when done.
|
|
*/
|
|
gchar *addrbook_gen_new_file_name(gint fileNum) {
|
|
gchar fmt[30];
|
|
gchar buf[WORK_BUFLEN];
|
|
gint n = fileNum;
|
|
long int nmax;
|
|
|
|
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);
|
|
}
|
|
|
|
/*
|
|
* **********************************************************************
|
|
* Address book test functions...
|
|
* **********************************************************************
|
|
*/
|
|
|
|
/**
|
|
* Attempt to parse list of email address from file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
*/
|
|
static void addrbook_chkparse_addr_list( AddressBookFile *book, XMLFile *file ){
|
|
guint prev_level;
|
|
GList *attr;
|
|
|
|
for (;;) {
|
|
prev_level = file->level;
|
|
if (xml_parse_next_tag(file))
|
|
longjmp(book->jumper, 1);
|
|
if (file->level < prev_level)
|
|
return;
|
|
attr = xml_get_current_tag_attr(file);
|
|
/* addrbook_show_attribs( attr ); */
|
|
if (xml_compare_tag(file, AB_ELTAG_ADDRESS))
|
|
addrbook_chkparse_addr_list(book, file);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Attempt to parse attributes for person address from file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
*/
|
|
static void addrbook_chkparse_attribute(AddressBookFile *book, XMLFile *file)
|
|
{
|
|
GList *attr;
|
|
gchar *element;
|
|
|
|
attr = xml_get_current_tag_attr(file);
|
|
/* addrbook_show_attribs( attr ); */
|
|
element = xml_get_element(file);
|
|
/* printf( "\t\tattrib value : %s\n", element ); */
|
|
}
|
|
|
|
/**
|
|
* Attempt to parse list of attributes for person address from file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
*/
|
|
static void addrbook_chkparse_attr_list(AddressBookFile *book, XMLFile *file)
|
|
{
|
|
guint prev_level;
|
|
|
|
for (;;) {
|
|
prev_level = file->level;
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Attempt to parse person from file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
*/
|
|
static void addrbook_chkparse_person(AddressBookFile *book, XMLFile *file)
|
|
{
|
|
GList *attr;
|
|
|
|
attr = xml_get_current_tag_attr(file);
|
|
/* addrbook_show_attribs( attr ); */
|
|
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);
|
|
}
|
|
|
|
/**
|
|
* Attempt to parse list of members from file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
*/
|
|
static void addrbook_chkparse_member_list(AddressBookFile *book, XMLFile *file)
|
|
{
|
|
GList *attr;
|
|
guint prev_level;
|
|
|
|
for (;;) {
|
|
prev_level = file->level;
|
|
if (xml_parse_next_tag(file))
|
|
longjmp(book->jumper, 1);
|
|
|
|
if (file->level < prev_level)
|
|
return;
|
|
|
|
if (xml_compare_tag(file, AB_ELTAG_MEMBER)) {
|
|
attr = xml_get_current_tag_attr(file);
|
|
/* addrbook_show_attribs( attr ); */
|
|
addrbook_chkparse_member_list(book, file);
|
|
}
|
|
else {
|
|
attr = xml_get_current_tag_attr(file);
|
|
/* addrbook_show_attribs( attr ); */
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Attempt to parse group from file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
*/
|
|
static void addrbook_chkparse_group(AddressBookFile *book, XMLFile *file)
|
|
{
|
|
GList *attr;
|
|
|
|
attr = xml_get_current_tag_attr(file);
|
|
/* addrbook_show_attribs( attr ); */
|
|
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);
|
|
}
|
|
|
|
/**
|
|
* Attempt to parse list of folders from file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
*/
|
|
static void addrbook_chkparse_folder_list(AddressBookFile *book, XMLFile *file)
|
|
{
|
|
GList *attr;
|
|
guint prev_level;
|
|
|
|
for (;;) {
|
|
prev_level = file->level;
|
|
if (xml_parse_next_tag(file))
|
|
longjmp(book->jumper, 1);
|
|
|
|
if (file->level < prev_level)
|
|
return;
|
|
|
|
if (xml_compare_tag(file, AB_ELTAG_ITEM)) {
|
|
attr = xml_get_current_tag_attr(file);
|
|
/* addrbook_show_attribs( attr ); */
|
|
addrbook_chkparse_folder_list(book, file);
|
|
}
|
|
else {
|
|
attr = xml_get_current_tag_attr(file);
|
|
/* addrbook_show_attribs( attr ); */
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Attempt to parse a folder from file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
*/
|
|
static void addrbook_chkparse_folder(AddressBookFile *book, XMLFile *file)
|
|
{
|
|
GList *attr;
|
|
|
|
attr = xml_get_current_tag_attr(file);
|
|
/* addrbook_show_attribs( attr ); */
|
|
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);
|
|
}
|
|
|
|
/**
|
|
* Attempt to parse (DOM) tree from file.
|
|
* \param book Address book.
|
|
* \param file XML file handle.
|
|
*/
|
|
static gboolean addrbook_chkread_tree(AddressBookFile *book, XMLFile *file)
|
|
{
|
|
GList *attr;
|
|
gboolean retVal;
|
|
|
|
if (xml_get_dtd(file))
|
|
return FALSE;
|
|
|
|
if (xml_parse_next_tag(file))
|
|
return FALSE;
|
|
|
|
if (!xml_compare_tag(file, AB_ELTAG_ADDRESS_BOOK))
|
|
return FALSE;
|
|
|
|
attr = xml_get_current_tag_attr(file);
|
|
/* addrbook_show_attribs( attr ); */
|
|
|
|
retVal = TRUE;
|
|
for (;;) {
|
|
if (!file->level)
|
|
break;
|
|
/* Get item tag */
|
|
if (xml_parse_next_tag(file))
|
|
longjmp(book->jumper, 1);
|
|
|
|
/* Get next tag (person, group or folder) */
|
|
if (xml_compare_tag(file, AB_ELTAG_PERSON))
|
|
addrbook_chkparse_person( book, file );
|
|
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);
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
/**
|
|
* Test address book file by parsing contents.
|
|
* \param book Address book.
|
|
* \param fileName Filename of XML file.
|
|
* \return Status code <i>MGU_SUCCESS</i> if file appears to be valid format.
|
|
*/
|
|
gint addrbook_test_read_file(AddressBookFile *book, gchar *fileName)
|
|
{
|
|
XMLFile *file = NULL;
|
|
gchar *fileSpec = NULL;
|
|
|
|
g_return_val_if_fail(book != NULL, -1);
|
|
|
|
fileSpec = g_strconcat(book->path, G_DIR_SEPARATOR_S, fileName, NULL);
|
|
book->retVal = MGU_OPEN_FILE;
|
|
file = xml_open_file(fileSpec);
|
|
g_free(fileSpec);
|
|
if (file) {
|
|
book->retVal = MGU_BAD_FORMAT;
|
|
if (setjmp(book->jumper)) {
|
|
/* printf( "Caught Ya!!!\n" ); */
|
|
xml_close_file(file);
|
|
return book->retVal;
|
|
}
|
|
if (addrbook_chkread_tree(book, file))
|
|
book->retVal = MGU_SUCCESS;
|
|
|
|
xml_close_file( file );
|
|
}
|
|
return book->retVal;
|
|
}
|
|
|
|
/**
|
|
* Return link list of all persons in address book. Note that the list
|
|
* contains references to items. Do <b>*NOT*</b> attempt to use the
|
|
* <code>addrbook_free_xxx()</code> functions... this will destroy the
|
|
* addressbook data!
|
|
* \param book Address book.
|
|
* \return List of persons, 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);
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
ItemPerson *addrbook_add_contact(AddressBookFile *book, ItemFolder *folder,
|
|
const gchar *name,const gchar *address,
|
|
const gchar *remarks)
|
|
{
|
|
ItemPerson *person;
|
|
|
|
g_return_val_if_fail(book != NULL, NULL);
|
|
person = addrcache_add_contact(
|
|
book->addressCache, folder, name, address, remarks );
|
|
return person;
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
gchar *addrbook_guess_next_file(AddressBookFile *book)
|
|
{
|
|
gchar *newFile = NULL;
|
|
GList *fileList = NULL;
|
|
gint fileNum = 1;
|
|
fileList = addrbook_get_bookfile_list(book);
|
|
if (fileList)
|
|
fileNum = 1 + book->maxValue;
|
|
|
|
newFile = addrbook_gen_new_file_name(fileNum);
|
|
g_list_free(fileList);
|
|
fileList = NULL;
|
|
return newFile;
|
|
}
|
|
|
|
/*
|
|
* End of Source.
|
|
*/
|
|
|
|
|