aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--e-util/ChangeLog10
-rw-r--r--e-util/Makefile.am4
-rw-r--r--e-util/e-account-list.c286
-rw-r--r--e-util/e-account-list.h59
-rw-r--r--e-util/e-account.c503
-rw-r--r--e-util/e-account.h102
-rw-r--r--e-util/e-list.c23
-rw-r--r--e-util/e-list.h6
-rw-r--r--e-util/e-util-marshal.list1
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