diff options
-rw-r--r-- | e-util/ChangeLog | 10 | ||||
-rw-r--r-- | e-util/Makefile.am | 4 | ||||
-rw-r--r-- | e-util/e-account-list.c | 286 | ||||
-rw-r--r-- | e-util/e-account-list.h | 59 | ||||
-rw-r--r-- | e-util/e-account.c | 503 | ||||
-rw-r--r-- | e-util/e-account.h | 102 | ||||
-rw-r--r-- | e-util/e-list.c | 23 | ||||
-rw-r--r-- | e-util/e-list.h | 6 | ||||
-rw-r--r-- | e-util/e-util-marshal.list | 1 |
9 files changed, 990 insertions, 4 deletions
diff --git a/e-util/ChangeLog b/e-util/ChangeLog index 58dcd79912..3700f7b5dd 100644 --- a/e-util/ChangeLog +++ b/e-util/ChangeLog @@ -1,3 +1,13 @@ +2003-01-16 Dan Winship <danw@ximian.com> + + * e-account.c: New class, based on MailConfigAccount, for + describing an evolution (mail) account. + + * e-account-list.c: New class for tracking the list of configured + accounts. (Also uses some code from mail-config.) + + * e-list.c (e_list_construct, e_list_remove): New + 2003-01-14 Ettore Perazzoli <ettore@ximian.com> * e-dialog-utils.c: Do not #include <e-bonobo-widget.h>. diff --git a/e-util/Makefile.am b/e-util/Makefile.am index 93da8b15e3..559165a22b 100644 --- a/e-util/Makefile.am +++ b/e-util/Makefile.am @@ -21,6 +21,8 @@ privlib_LTLIBRARIES = libeutil.la libedb3util.la libeconduit.la noinst_LTLIBRARIES = libeutil-static.la libeconduit-static.la eutilinclude_HEADERS = \ + e-account-list.h \ + e-account.h \ e-categories-config.h \ e-categories-master-list-wombat.h \ e-component-listener.h \ @@ -51,6 +53,8 @@ eutilinclude_HEADERS = \ libeutil_la_SOURCES = \ $(eutilinclude_HEADERS) \ + e-account-list.c \ + e-account.c \ e-categories-config.c \ e-categories-master-list-wombat.c \ e-component-listener.c \ diff --git a/e-util/e-account-list.c b/e-util/e-account-list.c new file mode 100644 index 0000000000..4e7b86a85f --- /dev/null +++ b/e-util/e-account-list.c @@ -0,0 +1,286 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2003 Ximian, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "e-account-list.h" +#include "e-account.h" +#include "e-util-marshal.h" + +#include <gal/util/e-util.h> + +struct EAccountListPrivate { + GConfClient *gconf; + guint notify_id; +}; + +enum { + ACCOUNT_ADDED, + ACCOUNT_CHANGED, + ACCOUNT_REMOVED, + LAST_SIGNAL +}; + +static guint signals [LAST_SIGNAL] = { 0 }; + +#define PARENT_TYPE E_TYPE_LIST +static EListClass *parent_class = NULL; + +static void dispose (GObject *); +static void finalize (GObject *); + +static void +class_init (GObjectClass *object_class) +{ + parent_class = g_type_class_ref (PARENT_TYPE); + + /* virtual method override */ + object_class->dispose = dispose; + object_class->finalize = finalize; + + /* signals */ + signals[ACCOUNT_ADDED] = + g_signal_new ("account_added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAccountListClass, account_added), + NULL, NULL, + e_util_marshal_NONE__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_ACCOUNT); + signals[ACCOUNT_CHANGED] = + g_signal_new ("account_changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAccountListClass, account_changed), + NULL, NULL, + e_util_marshal_NONE__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_ACCOUNT); + signals[ACCOUNT_REMOVED] = + g_signal_new ("account_removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAccountListClass, account_removed), + NULL, NULL, + e_util_marshal_NONE__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_ACCOUNT); +} + +static void +init (GObject *object) +{ + EAccountList *account_list = E_ACCOUNT_LIST (object); + + account_list->priv = g_new0 (EAccountListPrivate, 1); +} + +static void +dispose (GObject *object) +{ + EAccountList *account_list = E_ACCOUNT_LIST (object); + + if (account_list->priv->gconf) { + if (account_list->priv->notify_id) { + gconf_client_notify_remove (account_list->priv->gconf, + account_list->priv->notify_id); + } + g_object_unref (account_list->priv->gconf); + account_list->priv->gconf = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + EAccountList *account_list = E_ACCOUNT_LIST (object); + + g_free (account_list->priv); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +E_MAKE_TYPE (e_account_list, "EAccountList", EAccountList, class_init, init, PARENT_TYPE) + + +static void +gconf_accounts_changed (GConfClient *client, guint cnxn_id, + GConfEntry *entry, gpointer user_data) +{ + EAccountList *account_list = user_data; + GSList *list, *l; + EAccount *account; + EList *old_accounts; + EIterator *iter; + const char *uid; + + old_accounts = e_list_duplicate (E_LIST (account_list)); + + list = gconf_client_get_list (client, "/apps/evolution/mail/accounts", + GCONF_VALUE_STRING, NULL); + for (l = list; l; l = l->next) { + uid = e_account_uid_from_xml (l->data); + if (!uid) + continue; + + /* See if this is an existing account */ + for (iter = e_list_get_iterator (old_accounts); + e_iterator_is_valid (iter); + e_iterator_next (iter)) { + account = (EAccount *)e_iterator_get (iter); + if (!strcmp (account->uid, uid)) { + /* The account still exists, so remove + * it from "old_accounts" and update it. + */ + e_iterator_delete (iter); + if (e_account_set_from_xml (account, l->data)) + g_signal_emit (account_list, signals[ACCOUNT_CHANGED], 0, account); + goto next; + } + } + + /* Must be a new account */ + account = e_account_new_from_xml (l->data); + e_list_append (E_LIST (account_list), account); + g_signal_emit (account_list, signals[ACCOUNT_ADDED], 0, account); + g_object_unref (account); + + next: + g_object_unref (iter); + } + + /* Anything left in old_accounts must have been deleted */ + for (iter = e_list_get_iterator (old_accounts); + e_iterator_is_valid (iter); + e_iterator_next (iter)) { + account = (EAccount *)e_iterator_get (iter); + e_list_remove (E_LIST (account_list), account); + g_signal_emit (account_list, signals[ACCOUNT_REMOVED], 0, account); + } + g_object_unref (iter); + g_object_unref (old_accounts); +} + +static void * +copy_func (const void *data, void *closure) +{ + GObject *object = (GObject *)data; + + g_object_ref (object); + return object; +} + +static void +free_func (void *data, void *closure) +{ + g_object_unref (data); +} + +/** + * e_account_list_new: + * @gconf: a #GConfClient + * + * Reads the list of accounts from @gconf and listens for changes. + * Will emit %account_added, %account_changed, and %account_removed + * signals according to notifications from GConf. + * + * You can modify the list using e_list_append(), e_list_remove(), and + * e_iterator_delete(). After adding, removing, or changing accounts, + * you must call e_account_list_save() to push the changes back to + * GConf. + * + * Return value: the list of accounts + **/ +EAccountList * +e_account_list_new (GConfClient *gconf) +{ + EAccountList *account_list; + + g_return_val_if_fail (GCONF_IS_CLIENT (gconf), NULL); + + account_list = g_object_new (E_TYPE_ACCOUNT_LIST, NULL); + e_account_list_construct (account_list, gconf); + + return account_list; +} + +void +e_account_list_construct (EAccountList *account_list, GConfClient *gconf) +{ + g_return_if_fail (GCONF_IS_CLIENT (gconf)); + + e_list_construct (E_LIST (account_list), copy_func, free_func, NULL); + account_list->priv->gconf = gconf; + g_object_ref (gconf); + + gconf_client_add_dir (account_list->priv->gconf, + "/apps/evolution/mail/accounts", + GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); + account_list->priv->notify_id = + gconf_client_notify_add (account_list->priv->gconf, + "/apps/evolution/mail/accounts", + gconf_accounts_changed, account_list, + NULL, NULL); + + gconf_accounts_changed (account_list->priv->gconf, + account_list->priv->notify_id, + NULL, account_list); +} + +/** + * e_account_list_save: + * @account_list: an #EAccountList + * + * Saves @account_list to GConf. Signals will be emitted for changes. + **/ +void +e_account_list_save (EAccountList *account_list) +{ + GSList *list = NULL; + EAccount *account; + EIterator *iter; + char *xmlbuf; + + for (iter = e_list_get_iterator (E_LIST (account_list)); + e_iterator_is_valid (iter); + e_iterator_next (iter)) { + account = (EAccount *)e_iterator_get (iter); + + xmlbuf = e_account_to_xml (account); + if (xmlbuf) + list = g_slist_append (list, xmlbuf); + } + g_object_unref (iter); + + gconf_client_set_list (account_list->priv->gconf, + "/apps/evolution/mail/accounts", + GCONF_VALUE_STRING, list, NULL); + + while (list) { + g_free (list->data); + list = g_slist_remove (list, list->data); + } + + gconf_client_suggest_sync (account_list->priv->gconf, NULL); +} diff --git a/e-util/e-account-list.h b/e-util/e-account-list.h new file mode 100644 index 0000000000..6a8a1c7505 --- /dev/null +++ b/e-util/e-account-list.h @@ -0,0 +1,59 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2003 Ximian, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __E_ACCOUNT_LIST__ +#define __E_ACCOUNT_LIST__ + +#include "e-list.h" +#include "e-account.h" +#include <gconf/gconf-client.h> + +#define E_TYPE_ACCOUNT_LIST (e_account_list_get_type ()) +#define E_ACCOUNT_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_ACCOUNT_LIST, EAccountList)) +#define E_ACCOUNT_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_ACCOUNT_LIST, EAccountListClass)) +#define E_IS_ACCOUNT_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_ACCOUNT_LIST)) +#define E_IS_ACCOUNT_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_ACCOUNT_LIST)) + +typedef struct EAccountListPrivate EAccountListPrivate; + +typedef struct { + EList parent_object; + + EAccountListPrivate *priv; +} EAccountList; + +typedef struct { + EListClass parent_class; + + /* signals */ + void (*account_added) (EAccountList *, EAccount *); + void (*account_changed) (EAccountList *, EAccount *); + void (*account_removed) (EAccountList *, EAccount *); +} EAccountListClass; + + +GType e_account_list_get_type (void); + +EAccountList *e_account_list_new (GConfClient *gconf); +void e_account_list_construct (EAccountList *account_list, + GConfClient *gconf); + +void e_account_list_save (EAccountList *account_list); + +#endif /* __E_ACCOUNT_LIST__ */ diff --git a/e-util/e-account.c b/e-util/e-account.c new file mode 100644 index 0000000000..ac58575d51 --- /dev/null +++ b/e-util/e-account.c @@ -0,0 +1,503 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2003 Ximian, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "e-account.h" + +#include <gal/util/e-util.h> +#include <libxml/parser.h> +#include <libxml/tree.h> +#include <libxml/xmlmemory.h> + +#define PARENT_TYPE G_TYPE_OBJECT +static GObjectClass *parent_class = NULL; + +static void finalize (GObject *); + +static void +class_init (GObjectClass *object_class) +{ + parent_class = g_type_class_ref (PARENT_TYPE); + + /* virtual method override */ + object_class->finalize = finalize; +} + +static void +init (EAccount *account) +{ + account->id = g_new0 (EAccountIdentity, 1); + account->source = g_new0 (EAccountService, 1); + account->transport = g_new0 (EAccountService, 1); +} + +static void +identity_destroy (EAccountIdentity *id) +{ + if (!id) + return; + + g_free (id->name); + g_free (id->address); + g_free (id->reply_to); + g_free (id->organization); + + g_free (id); +} + +static void +service_destroy (EAccountService *service) +{ + if (!service) + return; + + g_free (service->url); + + g_free (service); +} + +static void +finalize (GObject *object) +{ + EAccount *account = E_ACCOUNT (object); + + g_free (account->name); + g_free (account->uid); + + identity_destroy (account->id); + service_destroy (account->source); + service_destroy (account->transport); + + g_free (account->drafts_folder_uri); + g_free (account->sent_folder_uri); + + g_free (account->cc_addrs); + g_free (account->bcc_addrs); + + g_free (account->pgp_key); + g_free (account->smime_key); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +E_MAKE_TYPE (e_account, "EAccount", EAccount, class_init, init, PARENT_TYPE) + + +char * +e_account_gen_uid (void) +{ + static char *hostname; + static int serial; + + if (!hostname) { + static char buffer [512]; + + if ((gethostname (buffer, sizeof (buffer) - 1) == 0) && + (buffer [0] != 0)) + hostname = buffer; + else + hostname = "localhost"; + } + + return g_strdup_printf ("%lu.%lu.%d@%s", + (unsigned long) time (NULL), + (unsigned long) getpid (), + serial++, + hostname); +} + +/** + * e_account_new: + * + * Return value: a blank new account which can be filled in and + * added to an #EAccountList. + **/ +EAccount * +e_account_new (void) +{ + EAccount *account; + + account = g_object_new (E_TYPE_ACCOUNT, NULL); + account->uid = e_account_gen_uid (); + + return account; +} + +/** + * e_account_new_from_xml: + * @xml: an XML account description + * + * Return value: a new #EAccount based on the data in @xml, or %NULL + * if @xml could not be parsed as valid account data. + **/ +EAccount * +e_account_new_from_xml (const char *xml) +{ + EAccount *account; + + account = g_object_new (E_TYPE_ACCOUNT, NULL); + if (!e_account_set_from_xml (account, xml)) { + g_object_unref (account); + return NULL; + } + + return account; +} + + +static gboolean +xml_set_bool (xmlNodePtr node, const char *name, gboolean *val) +{ + gboolean bool; + char *buf; + + if ((buf = xmlGetProp (node, name))) { + bool = (!strcmp (buf, "true") || !strcmp (buf, "yes")); + xmlFree (buf); + + if (bool != *val) { + *val = bool; + return TRUE; + } + } + + return FALSE; +} + +static gboolean +xml_set_int (xmlNodePtr node, const char *name, int *val) +{ + int number; + char *buf; + + if ((buf = xmlGetProp (node, name))) { + number = strtol (buf, NULL, 10); + xmlFree (buf); + + if (number != *val) { + *val = number; + return TRUE; + } + } + + return FALSE; +} + +static gboolean +xml_set_prop (xmlNodePtr node, const char *name, char **val) +{ + char *buf, *new_val; + + buf = xmlGetProp (node, name); + new_val = g_strdup (buf); + xmlFree (buf); + + /* We can use strcmp here whether the value is UTF8 or + * not, since we only care if the bytes changed. + */ + if (!*val || strcmp (*val, new_val)) { + g_free (*val); + *val = new_val; + return TRUE; + } else { + g_free (new_val); + return FALSE; + } +} + +static gboolean +xml_set_content (xmlNodePtr node, char **val) +{ + char *buf, *new_val; + + buf = xmlNodeGetContent (node); + new_val = g_strdup (buf); + xmlFree (buf); + + /* We can use strcmp here whether the value is UTF8 or + * not, since we only care if the bytes changed. + */ + if (!*val || strcmp (*val, new_val)) { + g_free (*val); + *val = new_val; + return TRUE; + } else { + g_free (new_val); + return FALSE; + } +} + +static gboolean +xml_set_identity (xmlNodePtr node, EAccountIdentity *id) +{ + gboolean changed = FALSE; + + for (node = node->children; node; node = node->next) { + if (!strcmp (node->name, "name")) + changed |= xml_set_content (node, &id->name); + else if (!strcmp (node->name, "addr-spec")) + changed |= xml_set_content (node, &id->address); + else if (!strcmp (node->name, "reply-to")) + changed |= xml_set_content (node, &id->reply_to); + else if (!strcmp (node->name, "organization")) + changed |= xml_set_content (node, &id->organization); + else if (!strcmp (node->name, "signature")) { + changed |= xml_set_bool (node, "auto", &id->auto_signature); + changed |= xml_set_int (node, "default", &id->def_signature); + } + } + + return changed; +} + +static gboolean +xml_set_service (xmlNodePtr node, EAccountService *service) +{ + gboolean changed = FALSE; + int timeout; + + changed |= xml_set_bool (node, "save-passwd", &service->save_passwd); + changed |= xml_set_bool (node, "keep-on-server", &service->keep_on_server); + + changed |= xml_set_bool (node, "auto-check", &service->auto_check); + changed |= xml_set_int (node, "auto-check-timeout", &service->auto_check_time); + if (service->auto_check && service->auto_check_time <= 0) { + service->auto_check = FALSE; + service->auto_check_time = 0; + } + + for (node = node->children; node; node = node->next) { + if (!strcmp (node->name, "url")) { + changed |= xml_set_content (node, &service->url); + break; + } + } + + return changed; +} + +/** + * e_account_set_from_xml: + * @account: an #EAccount + * @xml: an XML account description. + * + * Changes @account to match @xml. + * + * Return value: %TRUE if @account was changed, %FALSE if @account + * already matched @xml or @xml could not be parsed + **/ +gboolean +e_account_set_from_xml (EAccount *account, const char *xml) +{ + xmlNodePtr node, cur; + xmlDocPtr doc; + gboolean changed = FALSE; + + if (!(doc = xmlParseDoc ((char *)xml))) + return FALSE; + + node = doc->children; + if (strcmp (node->name, "account") != 0) { + xmlFreeDoc (doc); + return FALSE; + } + + if (!account->uid) + xml_set_prop (node, "uid", &account->uid); + + changed |= xml_set_prop (node, "name", &account->name); + changed |= xml_set_bool (node, "enabled", &account->enabled); + + for (node = node->children; node; node = node->next) { + if (!strcmp (node->name, "identity")) { + changed |= xml_set_identity (node, account->id); + } else if (!strcmp (node->name, "source")) { + changed |= xml_set_service (node, account->source); + } else if (!strcmp (node->name, "transport")) { + changed |= xml_set_service (node, account->transport); + } else if (!strcmp (node->name, "drafts-folder")) { + changed |= xml_set_content (node, &account->drafts_folder_uri); + } else if (!strcmp (node->name, "sent-folder")) { + changed |= xml_set_content (node, &account->sent_folder_uri); + } else if (!strcmp (node->name, "auto-cc")) { + changed |= xml_set_bool (node, "always", &account->always_cc); + changed |= xml_set_content (node, &account->cc_addrs); + } else if (!strcmp (node->name, "auto-bcc")) { + changed |= xml_set_bool (node, "always", &account->always_bcc); + changed |= xml_set_content (node, &account->bcc_addrs); + } else if (!strcmp (node->name, "pgp")) { + changed |= xml_set_bool (node, "encrypt-to-self", &account->pgp_encrypt_to_self); + changed |= xml_set_bool (node, "always-trust", &account->pgp_always_trust); + changed |= xml_set_bool (node, "always-sign", &account->pgp_always_sign); + changed |= xml_set_bool (node, "no-imip-sign", &account->pgp_no_imip_sign); + + if (node->children) { + for (cur = node->children; cur; cur = cur->next) { + if (!strcmp (cur->name, "key-id")) { + changed |= xml_set_content (cur, &account->pgp_key); + break; + } + } + } + } else if (!strcmp (node->name, "smime")) { + changed |= xml_set_bool (node, "encrypt-to-self", &account->smime_encrypt_to_self); + changed |= xml_set_bool (node, "always-sign", &account->smime_always_sign); + + if (node->children) { + for (cur = node->children; cur; cur = cur->next) { + if (!strcmp (cur->name, "key-id")) { + changed |= xml_set_content (cur, &account->smime_key); + break; + } + } + } + } + } + + xmlFreeDoc (doc); + + return changed; +} + +/** + * e_account_to_xml: + * @account: an #EAccount + * + * Return value: an XML representation of @account, which the caller + * must free. + **/ +char * +e_account_to_xml (EAccount *account) +{ + xmlNodePtr root, node, id, src, xport; + char *tmp, buf[20]; + xmlChar *xmlbuf; + xmlDocPtr doc; + int n; + + doc = xmlNewDoc ("1.0"); + + root = xmlNewDocNode (doc, NULL, "account", NULL); + xmlDocSetRootElement (doc, root); + + xmlSetProp (root, "name", account->name); + xmlSetProp (root, "uid", account->uid); + xmlSetProp (root, "enabled", account->enabled ? "true" : "false"); + + id = xmlNewChild (root, NULL, "identity", NULL); + if (account->id->name) + xmlNewTextChild (id, NULL, "name", account->id->name); + if (account->id->address) + xmlNewTextChild (id, NULL, "addr-spec", account->id->address); + if (account->id->reply_to) + xmlNewTextChild (id, NULL, "reply-to", account->id->reply_to); + if (account->id->organization) + xmlNewTextChild (id, NULL, "organization", account->id->organization); + + node = xmlNewChild (id, NULL, "signature",NULL); + xmlSetProp (node, "auto", account->id->auto_signature ? "true" : "false"); + sprintf (buf, "%d", account->id->def_signature); + xmlSetProp (node, "default", buf); + + src = xmlNewChild (root, NULL, "source", NULL); + xmlSetProp (src, "save-passwd", account->source->save_passwd ? "true" : "false"); + xmlSetProp (src, "keep-on-server", account->source->keep_on_server ? "true" : "false"); + xmlSetProp (src, "auto-check", account->source->auto_check ? "true" : "false"); + sprintf (buf, "%d", account->source->auto_check_time); + xmlSetProp (src, "auto-check-timeout", buf); + if (account->source->url) + xmlNewTextChild (src, NULL, "url", account->source->url); + + xport = xmlNewChild (root, NULL, "transport", NULL); + xmlSetProp (xport, "save-passwd", account->transport->save_passwd ? "true" : "false"); + if (account->transport->url) + xmlNewTextChild (xport, NULL, "url", account->transport->url); + + xmlNewTextChild (root, NULL, "drafts-folder", account->drafts_folder_uri); + xmlNewTextChild (root, NULL, "sent-folder", account->sent_folder_uri); + + node = xmlNewChild (root, NULL, "auto-cc", NULL); + xmlSetProp (node, "always", account->always_cc ? "true" : "false"); + if (account->cc_addrs) + xmlNewTextChild (node, NULL, "recipients", account->cc_addrs); + + node = xmlNewChild (root, NULL, "auto-bcc", NULL); + xmlSetProp (node, "always", account->always_bcc ? "true" : "false"); + if (account->bcc_addrs) + xmlNewTextChild (node, NULL, "recipients", account->bcc_addrs); + + node = xmlNewChild (root, NULL, "pgp", NULL); + xmlSetProp (node, "encrypt-to-self", account->pgp_encrypt_to_self ? "true" : "false"); + xmlSetProp (node, "always-trust", account->pgp_always_trust ? "true" : "false"); + xmlSetProp (node, "always-sign", account->pgp_always_sign ? "true" : "false"); + xmlSetProp (node, "no-imip-sign", account->pgp_no_imip_sign ? "true" : "false"); + if (account->pgp_key) + xmlNewTextChild (node, NULL, "key-id", account->pgp_key); + + node = xmlNewChild (root, NULL, "smime", NULL); + xmlSetProp (node, "encrypt-to-self", account->smime_encrypt_to_self ? "true" : "false"); + xmlSetProp (node, "always-sign", account->smime_always_sign ? "true" : "false"); + if (account->smime_key) + xmlNewTextChild (node, NULL, "key-id", account->smime_key); + + xmlDocDumpMemory (doc, &xmlbuf, &n); + xmlFreeDoc (doc); + + /* remap to glib memory */ + tmp = g_malloc (n + 1); + memcpy (tmp, xmlbuf, n); + tmp[n] = '\0'; + xmlFree (xmlbuf); + + return tmp; +} + + +/** + * e_account_uid_from_xml: + * @xml: an XML account description + * + * Return value: the permanent UID of the account described by @xml + * (or %NULL if @xml could not be parsed or did not contain a uid). + * The caller must free this string. + **/ +char * +e_account_uid_from_xml (const char *xml) +{ + xmlNodePtr node; + xmlDocPtr doc; + char *uid = NULL; + + if (!(doc = xmlParseDoc ((char *)xml))) + return NULL; + + node = doc->children; + if (strcmp (node->name, "account") != 0) { + xmlFreeDoc (doc); + return NULL; + } + + xml_set_prop (node, "uid", &uid); + xmlFreeDoc (doc); + + return uid; +} diff --git a/e-util/e-account.h b/e-util/e-account.h new file mode 100644 index 0000000000..f20588a0ea --- /dev/null +++ b/e-util/e-account.h @@ -0,0 +1,102 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2003 Ximian, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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 library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __E_ACCOUNT__ +#define __E_ACCOUNT__ + +#include <glib-object.h> + +#define E_TYPE_ACCOUNT (e_account_get_type ()) +#define E_ACCOUNT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_ACCOUNT, EAccount)) +#define E_ACCOUNT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_ACCOUNT, EAccountClass)) +#define E_IS_ACCOUNT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_ACCOUNT)) +#define E_IS_ACCOUNT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_ACCOUNT)) + +typedef struct { + char *name; + char *address; + char *reply_to; + char *organization; + + int def_signature; + gboolean auto_signature; +} EAccountIdentity; + +typedef struct { + char *url; + gboolean keep_on_server; + gboolean auto_check; + int auto_check_time; + gboolean save_passwd; +} EAccountService; + + +typedef struct { + GObject parent_object; + + char *name; + char *uid; + + gboolean enabled; + + EAccountIdentity *id; + EAccountService *source; + EAccountService *transport; + + char *drafts_folder_uri, *sent_folder_uri; + + gboolean always_cc; + char *cc_addrs; + gboolean always_bcc; + char *bcc_addrs; + + char *pgp_key; + gboolean pgp_encrypt_to_self; + gboolean pgp_always_sign; + gboolean pgp_no_imip_sign; + gboolean pgp_always_trust; + + char *smime_key; + gboolean smime_encrypt_to_self; + gboolean smime_always_sign; +} EAccount; + +typedef struct { + GObjectClass parent_class; + +} EAccountClass; + + +GType e_account_get_type (void); + +EAccount *e_account_new (void); + +EAccount *e_account_new_from_xml (const char *xml); + +gboolean e_account_set_from_xml (EAccount *account, + const char *xml); + +char *e_account_to_xml (EAccount *account); + + +char *e_account_uid_from_xml (const char *xml); + +char *e_account_gen_uid (void); + +#endif /* __E_ACCOUNT__ */ diff --git a/e-util/e-list.c b/e-util/e-list.c index 7ef7ce2351..f1b190b16a 100644 --- a/e-util/e-list.c +++ b/e-util/e-list.c @@ -74,17 +74,23 @@ e_list_init (EList *list) } EList * -e_list_new (EListCopyFunc copy, EListFreeFunc free, void *closure) +e_list_new (EListCopyFunc copy, EListFreeFunc free, void *closure) { EList *list = g_object_new (E_TYPE_LIST, NULL); + e_list_construct (list, copy, free, closure); + return list; +} + +void +e_list_construct (EList *list, EListCopyFunc copy, EListFreeFunc free, void *closure) +{ list->copy = copy; list->free = free; list->closure = closure; - return list; } EList * -e_list_duplicate (EList *old) +e_list_duplicate (EList *old) { EList *list = g_object_new (E_TYPE_LIST, NULL); @@ -116,7 +122,7 @@ e_list_length (EList *list) } void -e_list_append (EList *list, const void *data) +e_list_append (EList *list, const void *data) { e_list_invalidate_iterators(list, NULL); if (list->copy) @@ -126,6 +132,15 @@ e_list_append (EList *list, const void *data) } void +e_list_remove (EList *list, const void *data) +{ + GList *link; + link = g_list_find (list->list, data); + if (link) + e_list_remove_link(list, link); +} + +void e_list_invalidate_iterators (EList *list, EIterator *skip) { GList *iterators = list->iterators; diff --git a/e-util/e-list.h b/e-util/e-list.h index 4c9357aebd..d249fcfa4a 100644 --- a/e-util/e-list.h +++ b/e-util/e-list.h @@ -45,10 +45,16 @@ struct _EListClass { EList *e_list_new (EListCopyFunc copy, EListFreeFunc free, void *closure); +void e_list_construct (EList *list, + EListCopyFunc copy, + EListFreeFunc free, + void *closure); EList *e_list_duplicate (EList *list); EIterator *e_list_get_iterator (EList *list); void e_list_append (EList *list, const void *data); +void e_list_remove (EList *list, + const void *data); int e_list_length (EList *list); /* For iterators to call. */ diff --git a/e-util/e-util-marshal.list b/e-util/e-util-marshal.list index fa33740eaa..463afd8129 100644 --- a/e-util/e-util-marshal.list +++ b/e-util/e-util-marshal.list @@ -1 +1,2 @@ NONE:NONE +NONE:OBJECT |