From 2596671b8712915820d2590c86a429257ee2d8f7 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 16 Jan 2003 19:38:44 +0000 Subject: New class, based on MailConfigAccount, for describing an evolution (mail) * 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 svn path=/trunk/; revision=19495 --- e-util/e-account.c | 503 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 503 insertions(+) create mode 100644 e-util/e-account.c (limited to 'e-util/e-account.c') 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 +#include +#include +#include + +#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; +} -- cgit