1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2003 Ximian, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU Lesser General Public
7 * License as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
24 #include "e-account.h"
30 #include <libxml/parser.h>
31 #include <libxml/tree.h>
32 #include <libxml/xmlmemory.h>
34 #include <gconf/gconf-client.h>
43 static guint signals[LAST_SIGNAL];
45 static void finalize (GObject *);
47 G_DEFINE_TYPE (EAccount, e_account, G_TYPE_OBJECT);
50 lock mail accounts Relatively difficult -- involves redesign of the XML blobs which describe accounts
51 disable adding mail accounts Simple -- can be done with just a Gconf key and some UI work to make assoc. widgets unavailable
52 disable editing mail accounts Relatively difficult -- involves redesign of the XML blobs which describe accounts
53 disable removing mail accounts
54 lock default character encoding Simple -- Gconf key + a little UI work to desensitize widgets, etc
55 disable free busy publishing
56 disable specific mime types (from being viewed) 90% done already (Unknown MIME types still pose a problem)
57 lock image loading preference
58 lock junk mail filtering settings
59 ** junk mail per account
61 lock first day of work week
63 disable forward as icalendar
64 lock color options for tasks
65 lock default contact filing format
66 * forbid signatures Simple -- can be done with just a Gconf key and some UI work to make assoc. widgets unavailable
67 * lock user to having 1 specific signature Simple -- can be done with just a Gconf key and some UI work to make assoc. widgets unavailable
68 * forbid adding/removing signatures Simple -- can be done with just a Gconf key and some UI work to make assoc. widgets unavailable
69 * lock each account to a certain signature Relatively difficult -- involved redesign of the XML blobs which describe accounts
71 set trash emptying frequency
72 * lock displayed mail headers Simple -- can be done with just a Gconf key and some UI work to make assoc. widgets unavailable
73 * lock authentication type (for incoming mail) Relatively difficult -- involves redesign of the XML blobs which describe accounts
74 * lock authentication type (for outgoing mail) Relatively difficult -- involves redesign of the XML blobs which describe accounts
75 * lock minimum check mail on server frequency Simple -- can be done with just a Gconf key and some UI work to make assoc. widgets unavailable
77 * require ssl always Relatively difficult -- involves redesign of the XML blobs which describe accounts
78 ** lock imap subscribed folder option
79 ** lock filtering of inbox
80 ** lock source account/options
81 ** lock destination account/options
85 e_account_class_init (EAccountClass *account_class)
87 GObjectClass *object_class = G_OBJECT_CLASS (account_class);
89 /* virtual method override */
90 object_class->finalize = finalize;
93 g_signal_new("changed",
94 G_OBJECT_CLASS_TYPE (object_class),
96 G_STRUCT_OFFSET (EAccountClass, changed),
98 g_cclosure_marshal_VOID__INT,
104 e_account_init (EAccount *account)
106 account->id = g_new0 (EAccountIdentity, 1);
107 account->source = g_new0 (EAccountService, 1);
108 account->transport = g_new0 (EAccountService, 1);
110 account->parent_uid = NULL;
112 account->source->auto_check = FALSE;
113 account->source->auto_check_time = 10;
117 identity_destroy (EAccountIdentity *id)
123 g_free (id->address);
124 g_free (id->reply_to);
125 g_free (id->organization);
126 g_free (id->sig_uid);
132 service_destroy (EAccountService *service)
137 g_free (service->url);
143 finalize (GObject *object)
145 EAccount *account = E_ACCOUNT (object);
147 g_free (account->name);
148 g_free (account->uid);
150 identity_destroy (account->id);
151 service_destroy (account->source);
152 service_destroy (account->transport);
154 g_free (account->drafts_folder_uri);
155 g_free (account->sent_folder_uri);
157 g_free (account->cc_addrs);
158 g_free (account->bcc_addrs);
160 g_free (account->pgp_key);
161 g_free (account->smime_sign_key);
162 g_free (account->smime_encrypt_key);
164 g_free (account->parent_uid);
166 G_OBJECT_CLASS (e_account_parent_class)->finalize (object);
172 * Return value: a blank new account which can be filled in and
173 * added to an #EAccountList.
180 account = g_object_new (E_TYPE_ACCOUNT, NULL);
181 account->uid = e_uid_new ();
187 * e_account_new_from_xml:
188 * @xml: an XML account description
190 * Return value: a new #EAccount based on the data in @xml, or %NULL
191 * if @xml could not be parsed as valid account data.
194 e_account_new_from_xml (const char *xml)
198 account = g_object_new (E_TYPE_ACCOUNT, NULL);
199 if (!e_account_set_from_xml (account, xml)) {
200 g_object_unref (account);
209 xml_set_bool (xmlNodePtr node, const char *name, gboolean *val)
214 if ((buf = xmlGetProp (node, (xmlChar*)name))) {
215 bool = (!strcmp ((char*)buf, "true") || !strcmp ((char*)buf, "yes"));
228 xml_set_int (xmlNodePtr node, const char *name, int *val)
233 if ((buf = xmlGetProp (node, (xmlChar*)name))) {
234 number = strtol ((char*)buf, NULL, 10);
237 if (number != *val) {
247 xml_set_prop (xmlNodePtr node, const char *name, char **val)
252 buf = xmlGetProp (node, (xmlChar*)name);
254 res = (*val != NULL);
260 res = *val == NULL || strcmp(*val, (char*)buf) != 0;
263 *val = g_strdup((char*)buf);
271 static EAccountReceiptPolicy
272 str_to_receipt_policy (const xmlChar *str)
274 if (!strcmp ((char*)str, "ask"))
275 return E_ACCOUNT_RECEIPT_ASK;
276 if (!strcmp ((char*)str, "always"))
277 return E_ACCOUNT_RECEIPT_ALWAYS;
279 return E_ACCOUNT_RECEIPT_NEVER;
283 receipt_policy_to_str (EAccountReceiptPolicy val)
288 case E_ACCOUNT_RECEIPT_NEVER:
291 case E_ACCOUNT_RECEIPT_ASK:
294 case E_ACCOUNT_RECEIPT_ALWAYS:
299 return (xmlChar*)ret;
303 xml_set_receipt_policy (xmlNodePtr node, const char *name, EAccountReceiptPolicy *val)
305 EAccountReceiptPolicy new_val;
308 if ((buf = xmlGetProp (node, (xmlChar*)name))) {
309 new_val = str_to_receipt_policy (buf);
312 if (new_val != *val) {
322 xml_set_content (xmlNodePtr node, char **val)
327 buf = xmlNodeGetContent(node);
329 res = (*val != NULL);
335 res = *val == NULL || strcmp(*val, (char*)buf) != 0;
338 *val = g_strdup((char*)buf);
347 xml_set_identity (xmlNodePtr node, EAccountIdentity *id)
349 gboolean changed = FALSE;
351 for (node = node->children; node; node = node->next) {
352 if (!strcmp ((char*)node->name, "name"))
353 changed |= xml_set_content (node, &id->name);
354 else if (!strcmp ((char*)node->name, "addr-spec"))
355 changed |= xml_set_content (node, &id->address);
356 else if (!strcmp ((char*)node->name, "reply-to"))
357 changed |= xml_set_content (node, &id->reply_to);
358 else if (!strcmp ((char*)node->name, "organization"))
359 changed |= xml_set_content (node, &id->organization);
360 else if (!strcmp ((char*)node->name, "signature")) {
361 changed |= xml_set_prop (node, "uid", &id->sig_uid);
364 /* WTF is this shit doing here? Migrate is supposed to "handle this" */
366 /* set a fake sig uid so the migrate code can handle this */
367 gboolean autogen = FALSE;
370 xml_set_bool (node, "auto", &autogen);
371 xml_set_int (node, "default", &sig_id);
374 id->sig_uid = g_strdup ("::0");
377 id->sig_uid = g_strdup_printf ("::%d", sig_id + 1);
388 xml_set_service (xmlNodePtr node, EAccountService *service)
390 gboolean changed = FALSE;
392 changed |= xml_set_bool (node, "save-passwd", &service->save_passwd);
393 changed |= xml_set_bool (node, "keep-on-server", &service->keep_on_server);
395 changed |= xml_set_bool (node, "auto-check", &service->auto_check);
396 changed |= xml_set_int (node, "auto-check-timeout", &service->auto_check_time);
397 if (service->auto_check && service->auto_check_time <= 0) {
398 service->auto_check = FALSE;
399 service->auto_check_time = 0;
402 for (node = node->children; node; node = node->next) {
403 if (!strcmp ((char*)node->name, "url")) {
404 changed |= xml_set_content (node, &service->url);
413 * e_account_set_from_xml:
414 * @account: an #EAccount
415 * @xml: an XML account description.
417 * Changes @account to match @xml.
419 * Return value: %TRUE if @account was changed, %FALSE if @account
420 * already matched @xml or @xml could not be parsed
423 e_account_set_from_xml (EAccount *account, const char *xml)
425 xmlNodePtr node, cur;
427 gboolean changed = FALSE;
429 if (!(doc = xmlParseDoc ((xmlChar*)xml)))
432 node = doc->children;
433 if (strcmp ((char*)node->name, "account") != 0) {
439 xml_set_prop (node, "uid", &account->uid);
441 changed |= xml_set_prop (node, "name", &account->name);
442 changed |= xml_set_bool (node, "enabled", &account->enabled);
444 for (node = node->children; node; node = node->next) {
445 if (!strcmp ((char*)node->name, "identity")) {
446 changed |= xml_set_identity (node, account->id);
447 } else if (!strcmp ((char*)node->name, "source")) {
448 changed |= xml_set_service (node, account->source);
449 } else if (!strcmp ((char*)node->name, "transport")) {
450 changed |= xml_set_service (node, account->transport);
451 } else if (!strcmp ((char*)node->name, "drafts-folder")) {
452 changed |= xml_set_content (node, &account->drafts_folder_uri);
453 } else if (!strcmp ((char*)node->name, "sent-folder")) {
454 changed |= xml_set_content (node, &account->sent_folder_uri);
455 } else if (!strcmp ((char*)node->name, "auto-cc")) {
456 changed |= xml_set_bool (node, "always", &account->always_cc);
457 changed |= xml_set_content (node, &account->cc_addrs);
458 } else if (!strcmp ((char*)node->name, "auto-bcc")) {
459 changed |= xml_set_bool (node, "always", &account->always_bcc);
460 changed |= xml_set_content (node, &account->bcc_addrs);
461 } else if (!strcmp ((char*)node->name, "receipt-policy")) {
462 changed |= xml_set_receipt_policy (node, "policy", &account->receipt_policy);
463 } else if (!strcmp ((char*)node->name, "pgp")) {
464 changed |= xml_set_bool (node, "encrypt-to-self", &account->pgp_encrypt_to_self);
465 changed |= xml_set_bool (node, "always-trust", &account->pgp_always_trust);
466 changed |= xml_set_bool (node, "always-sign", &account->pgp_always_sign);
467 changed |= xml_set_bool (node, "no-imip-sign", &account->pgp_no_imip_sign);
469 if (node->children) {
470 for (cur = node->children; cur; cur = cur->next) {
471 if (!strcmp ((char*)cur->name, "key-id")) {
472 changed |= xml_set_content (cur, &account->pgp_key);
477 } else if (!strcmp ((char*)node->name, "smime")) {
478 changed |= xml_set_bool (node, "sign-default", &account->smime_sign_default);
479 changed |= xml_set_bool (node, "encrypt-to-self", &account->smime_encrypt_to_self);
480 changed |= xml_set_bool (node, "encrypt-default", &account->smime_encrypt_default);
482 if (node->children) {
483 for (cur = node->children; cur; cur = cur->next) {
484 if (!strcmp ((char*)cur->name, "sign-key-id")) {
485 changed |= xml_set_content (cur, &account->smime_sign_key);
486 } else if (!strcmp ((char*)cur->name, "encrypt-key-id")) {
487 changed |= xml_set_content (cur, &account->smime_encrypt_key);
492 } else if (!strcmp ((char*)node->name, "proxy")) {
493 if (node->children) {
494 for (cur = node->children; cur; cur = cur->next) {
495 if (!strcmp ((char*)cur->name, "parent-uid")) {
496 changed |= xml_set_content (cur, &account->parent_uid);
506 g_signal_emit(account, signals[CHANGED], 0, -1);
514 * @dest: destination account object
515 * @src: source account object
517 * Import the settings from @src to @dest.
520 e_account_import (EAccount *dest, EAccount *src)
523 dest->name = g_strdup (src->name);
525 dest->enabled = src->enabled;
527 g_free (dest->id->name);
528 dest->id->name = g_strdup (src->id->name);
529 g_free (dest->id->address);
530 dest->id->address = g_strdup (src->id->address);
531 g_free (dest->id->reply_to);
532 dest->id->reply_to = g_strdup (src->id->reply_to);
533 g_free (dest->id->organization);
534 dest->id->organization = g_strdup (src->id->organization);
535 dest->id->sig_uid = g_strdup (src->id->sig_uid);
537 g_free (dest->source->url);
538 dest->source->url = g_strdup (src->source->url);
539 dest->source->keep_on_server = src->source->keep_on_server;
540 dest->source->auto_check = src->source->auto_check;
541 dest->source->auto_check_time = src->source->auto_check_time;
542 dest->source->save_passwd = src->source->save_passwd;
544 g_free (dest->transport->url);
545 dest->transport->url = g_strdup (src->transport->url);
546 dest->transport->save_passwd = src->transport->save_passwd;
548 g_free (dest->drafts_folder_uri);
549 dest->drafts_folder_uri = g_strdup (src->drafts_folder_uri);
551 g_free (dest->sent_folder_uri);
552 dest->sent_folder_uri = g_strdup (src->sent_folder_uri);
554 dest->always_cc = src->always_cc;
555 g_free (dest->cc_addrs);
556 dest->cc_addrs = g_strdup (src->cc_addrs);
558 dest->always_bcc = src->always_bcc;
559 g_free (dest->bcc_addrs);
560 dest->bcc_addrs = g_strdup (src->bcc_addrs);
562 dest->receipt_policy = src->receipt_policy;
564 g_free (dest->pgp_key);
565 dest->pgp_key = g_strdup (src->pgp_key);
566 dest->pgp_encrypt_to_self = src->pgp_encrypt_to_self;
567 dest->pgp_always_sign = src->pgp_always_sign;
568 dest->pgp_no_imip_sign = src->pgp_no_imip_sign;
569 dest->pgp_always_trust = src->pgp_always_trust;
571 dest->smime_sign_default = src->smime_sign_default;
572 g_free (dest->smime_sign_key);
573 dest->smime_sign_key = g_strdup (src->smime_sign_key);
575 dest->smime_encrypt_default = src->smime_encrypt_default;
576 dest->smime_encrypt_to_self = src->smime_encrypt_to_self;
577 g_free (dest->smime_encrypt_key);
578 dest->smime_encrypt_key = g_strdup (src->smime_encrypt_key);
580 g_signal_emit(dest, signals[CHANGED], 0, -1);
586 * @account: an #EAccount
588 * Return value: an XML representation of @account, which the caller
592 e_account_to_xml (EAccount *account)
594 xmlNodePtr root, node, id, src, xport;
600 doc = xmlNewDoc ((xmlChar*)"1.0");
602 root = xmlNewDocNode (doc, NULL, (xmlChar*)"account", NULL);
603 xmlDocSetRootElement (doc, root);
605 xmlSetProp (root, (xmlChar*)"name", (xmlChar*)account->name);
606 xmlSetProp (root, (xmlChar*)"uid", (xmlChar*)account->uid);
607 xmlSetProp (root, (xmlChar*)"enabled", (xmlChar*)(account->enabled ? "true" : "false"));
609 id = xmlNewChild (root, NULL, (xmlChar*)"identity", NULL);
610 if (account->id->name)
611 xmlNewTextChild (id, NULL, (xmlChar*)"name", (xmlChar*)account->id->name);
612 if (account->id->address)
613 xmlNewTextChild (id, NULL, (xmlChar*)"addr-spec", (xmlChar*)account->id->address);
614 if (account->id->reply_to)
615 xmlNewTextChild (id, NULL, (xmlChar*)"reply-to", (xmlChar*)account->id->reply_to);
616 if (account->id->organization)
617 xmlNewTextChild (id, NULL, (xmlChar*)"organization", (xmlChar*)account->id->organization);
619 node = xmlNewChild (id, NULL, (xmlChar*)"signature",NULL);
620 xmlSetProp (node, (xmlChar*)"uid", (xmlChar*)account->id->sig_uid);
622 src = xmlNewChild (root, NULL, (xmlChar*)"source", NULL);
623 xmlSetProp (src, (xmlChar*)"save-passwd", (xmlChar*)(account->source->save_passwd ? "true" : "false"));
624 xmlSetProp (src, (xmlChar*)"keep-on-server", (xmlChar*)(account->source->keep_on_server ? "true" : "false"));
625 xmlSetProp (src, (xmlChar*)"auto-check", (xmlChar*)(account->source->auto_check ? "true" : "false"));
626 sprintf (buf, "%d", account->source->auto_check_time);
627 xmlSetProp (src, (xmlChar*)"auto-check-timeout", (xmlChar*)buf);
628 if (account->source->url)
629 xmlNewTextChild (src, NULL, (xmlChar*)"url", (xmlChar*)account->source->url);
631 xport = xmlNewChild (root, NULL, (xmlChar*)"transport", NULL);
632 xmlSetProp (xport, (xmlChar*)"save-passwd", (xmlChar*)(account->transport->save_passwd ? "true" : "false"));
633 if (account->transport->url)
634 xmlNewTextChild (xport, NULL, (xmlChar*)"url", (xmlChar*)account->transport->url);
636 xmlNewTextChild (root, NULL, (xmlChar*)"drafts-folder", (xmlChar*)account->drafts_folder_uri);
637 xmlNewTextChild (root, NULL, (xmlChar*)"sent-folder", (xmlChar*)account->sent_folder_uri);
639 node = xmlNewChild (root, NULL, (xmlChar*)"auto-cc", NULL);
640 xmlSetProp (node, (xmlChar*)"always", (xmlChar*)(account->always_cc ? "true" : "false"));
641 if (account->cc_addrs)
642 xmlNewTextChild (node, NULL, (xmlChar*)"recipients", (xmlChar*)account->cc_addrs);
644 node = xmlNewChild (root, NULL, (xmlChar*)"auto-bcc", NULL);
645 xmlSetProp (node, (xmlChar*)"always", (xmlChar*)(account->always_bcc ? "true" : "false"));
646 if (account->bcc_addrs)
647 xmlNewTextChild (node, NULL, (xmlChar*)"recipients", (xmlChar*)account->bcc_addrs);
649 node = xmlNewChild (root, NULL, (xmlChar*)"receipt-policy", NULL);
650 xmlSetProp (node, (xmlChar*)"policy", receipt_policy_to_str (account->receipt_policy));
652 node = xmlNewChild (root, NULL, (xmlChar*)"pgp", NULL);
653 xmlSetProp (node, (xmlChar*)"encrypt-to-self", (xmlChar*)(account->pgp_encrypt_to_self ? "true" : "false"));
654 xmlSetProp (node, (xmlChar*)"always-trust", (xmlChar*)(account->pgp_always_trust ? "true" : "false"));
655 xmlSetProp (node, (xmlChar*)"always-sign", (xmlChar*)(account->pgp_always_sign ? "true" : "false"));
656 xmlSetProp (node, (xmlChar*)"no-imip-sign", (xmlChar*)(account->pgp_no_imip_sign ? "true" : "false"));
657 if (account->pgp_key)
658 xmlNewTextChild (node, NULL, (xmlChar*)"key-id", (xmlChar*)account->pgp_key);
660 node = xmlNewChild (root, NULL, (xmlChar*)"smime", NULL);
661 xmlSetProp (node, (xmlChar*)"sign-default", (xmlChar*)(account->smime_sign_default ? "true" : "false"));
662 xmlSetProp (node, (xmlChar*)"encrypt-default", (xmlChar*)(account->smime_encrypt_default ? "true" : "false"));
663 xmlSetProp (node, (xmlChar*)"encrypt-to-self", (xmlChar*)(account->smime_encrypt_to_self ? "true" : "false"));
664 if (account->smime_sign_key)
665 xmlNewTextChild (node, NULL, (xmlChar*)"sign-key-id", (xmlChar*)account->smime_sign_key);
666 if (account->smime_encrypt_key)
667 xmlNewTextChild (node, NULL, (xmlChar*)"encrypt-key-id", (xmlChar*)account->smime_encrypt_key);
669 if (account->parent_uid) {
670 node = xmlNewChild (root, NULL, (xmlChar*)"proxy", NULL);
671 xmlNewTextChild (node, NULL, (xmlChar*)"parent-uid", (xmlChar*)account->parent_uid);
674 xmlDocDumpMemory (doc, &xmlbuf, &n);
677 /* remap to glib memory */
678 tmp = g_malloc (n + 1);
679 memcpy (tmp, xmlbuf, n);
688 * e_account_uid_from_xml:
689 * @xml: an XML account description
691 * Return value: the permanent UID of the account described by @xml
692 * (or %NULL if @xml could not be parsed or did not contain a uid).
693 * The caller must free this string.
696 e_account_uid_from_xml (const char *xml)
702 if (!(doc = xmlParseDoc ((xmlChar *)xml)))
705 node = doc->children;
706 if (strcmp ((char*)node->name, "account") != 0) {
711 xml_set_prop (node, "uid", &uid);
718 EAP_IMAP_SUBSCRIBED = 0,
726 EAP_LOCK_DEFAULT_FOLDERS,
727 EAP_LOCK_SAVE_PASSWD,
732 static struct _system_info {
736 { "imap_subscribed", 1<<EAP_IMAP_SUBSCRIBED },
737 { "imap_namespace", 1<<EAP_IMAP_NAMESPACE },
738 { "filter_inbox", 1<<EAP_FILTER_INBOX },
739 { "filter_junk", 1<<EAP_FILTER_JUNK },
740 { "ssl", 1<<EAP_FORCE_SSL },
741 { "signature", 1<<EAP_LOCK_SIGNATURE },
742 { "authtype", 1<<EAP_LOCK_AUTH },
743 { "autocheck", 1<<EAP_LOCK_AUTOCHECK },
744 { "default_folders", 1<<EAP_LOCK_DEFAULT_FOLDERS },
745 { "save_passwd" , 1<<EAP_LOCK_SAVE_PASSWD },
746 { "source", 1<<EAP_LOCK_SOURCE },
747 { "transport", 1<<EAP_LOCK_TRANSPORT },
750 #define TYPE_STRING (1)
752 #define TYPE_BOOL (3)
753 #define TYPE_MASK (0xff)
754 #define TYPE_STRUCT (1<<8)
756 static struct _account_info {
760 unsigned int struct_offset;
761 } account_info[E_ACCOUNT_ITEM_LAST] = {
762 { /* E_ACCOUNT_NAME */ 0, TYPE_STRING, G_STRUCT_OFFSET(EAccount, name) },
764 { /* E_ACCOUNT_ID_NAME, */ 0, TYPE_STRING|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, id), G_STRUCT_OFFSET(EAccountIdentity, name) },
765 { /* E_ACCOUNT_ID_ADDRESS, */ 0, TYPE_STRING|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, id), G_STRUCT_OFFSET(EAccountIdentity, address) },
766 { /* E_ACCOUNT_ID_REPLY_TO, */ 0, TYPE_STRING|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, id), G_STRUCT_OFFSET(EAccountIdentity, reply_to) },
767 { /* E_ACCOUNT_ID_ORGANIZATION */ 0, TYPE_STRING|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, id), G_STRUCT_OFFSET(EAccountIdentity, organization) },
768 { /* E_ACCOUNT_ID_SIGNATURE */ 1<<EAP_LOCK_SIGNATURE, TYPE_STRING|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, id), G_STRUCT_OFFSET(EAccountIdentity, sig_uid) },
770 { /* E_ACCOUNT_SOURCE_URL */ 1<<EAP_LOCK_SOURCE, TYPE_STRING|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, source), G_STRUCT_OFFSET(EAccountService, url) },
771 { /* E_ACCOUNT_SOURCE_KEEP_ON_SERVER */ 0, TYPE_BOOL|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, source), G_STRUCT_OFFSET(EAccountService, keep_on_server) },
772 { /* E_ACCOUNT_SOURCE_AUTO_CHECK */ 1<<EAP_LOCK_AUTOCHECK, TYPE_BOOL|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, source), G_STRUCT_OFFSET(EAccountService, auto_check) },
773 { /* E_ACCOUNT_SOURCE_AUTO_CHECK_TIME */ 1<<EAP_LOCK_AUTOCHECK, TYPE_INT|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, source), G_STRUCT_OFFSET(EAccountService, auto_check_time) },
774 { /* E_ACCOUNT_SOURCE_SAVE_PASSWD */ 1<<EAP_LOCK_SAVE_PASSWD, TYPE_BOOL|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, source), G_STRUCT_OFFSET(EAccountService, save_passwd) },
776 { /* E_ACCOUNT_TRANSPORT_URL */ 1<<EAP_LOCK_TRANSPORT, TYPE_STRING|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, transport), G_STRUCT_OFFSET(EAccountService, url) },
777 { /* E_ACCOUNT_TRANSPORT_SAVE_PASSWD */ 1<<EAP_LOCK_SAVE_PASSWD, TYPE_BOOL|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, transport), G_STRUCT_OFFSET(EAccountService, save_passwd) },
779 { /* E_ACCOUNT_DRAFTS_FOLDER_URI */ 1<<EAP_LOCK_DEFAULT_FOLDERS, TYPE_STRING, G_STRUCT_OFFSET(EAccount, drafts_folder_uri) },
780 { /* E_ACCOUNT_SENT_FOLDER_URI */ 1<<EAP_LOCK_DEFAULT_FOLDERS, TYPE_STRING, G_STRUCT_OFFSET(EAccount, sent_folder_uri) },
782 { /* E_ACCOUNT_CC_ALWAYS */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, always_cc) },
783 { /* E_ACCOUNT_CC_ADDRS */ 0, TYPE_STRING, G_STRUCT_OFFSET(EAccount, cc_addrs) },
785 { /* E_ACCOUNT_BCC_ALWAYS */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, always_bcc) },
786 { /* E_ACCOUNT_BCC_ADDRS */ 0, TYPE_STRING, G_STRUCT_OFFSET(EAccount, bcc_addrs) },
788 { /* E_ACCOUNT_RECEIPT_POLICY */ 0, TYPE_INT, G_STRUCT_OFFSET(EAccount, receipt_policy) },
790 { /* E_ACCOUNT_PGP_KEY */ 0, TYPE_STRING, G_STRUCT_OFFSET(EAccount, pgp_key) },
791 { /* E_ACCOUNT_PGP_ENCRYPT_TO_SELF */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, pgp_encrypt_to_self) },
792 { /* E_ACCOUNT_PGP_ALWAYS_SIGN */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, pgp_always_sign) },
793 { /* E_ACCOUNT_PGP_NO_IMIP_SIGN */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, pgp_no_imip_sign) },
794 { /* E_ACCOUNT_PGP_ALWAYS_TRUST */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, pgp_always_trust) },
796 { /* E_ACCOUNT_SMIME_SIGN_KEY */ 0, TYPE_STRING, G_STRUCT_OFFSET(EAccount, smime_sign_key) },
797 { /* E_ACCOUNT_SMIME_ENCRYPT_KEY */ 0, TYPE_STRING, G_STRUCT_OFFSET(EAccount, smime_encrypt_key) },
798 { /* E_ACCOUNT_SMIME_SIGN_DEFAULT */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, smime_sign_default) },
799 { /* E_ACCOUNT_SMIME_ENCRYPT_TO_SELF */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, smime_encrypt_to_self) },
800 { /* E_ACCOUNT_SMIME_ENCRYPT_DEFAULT */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, smime_encrypt_default) },
802 { /* E_ACCOUNT_PROXY_PARENT_UID, */ 0, TYPE_STRING, G_STRUCT_OFFSET(EAccount, parent_uid) },
805 static GHashTable *ea_option_table;
806 static GHashTable *ea_system_table;
807 static guint32 ea_perms;
809 static struct _option_info {
812 } ea_option_list[] = {
813 { "imap_use_lsub", 1<<EAP_IMAP_SUBSCRIBED },
814 { "imap_override_namespace", 1<<EAP_IMAP_NAMESPACE },
815 { "imap_filter", 1<<EAP_FILTER_INBOX },
816 { "imap_filter_junk", 1<<EAP_FILTER_JUNK },
817 { "imap_filter_junk_inbox", 1<<EAP_FILTER_JUNK },
818 { "*_use_ssl", 1<<EAP_FORCE_SSL },
819 { "*_auth", 1<<EAP_LOCK_AUTH },
822 #define LOCK_BASE "/apps/evolution/lock/mail/accounts"
825 ea_setting_notify(GConfClient *gconf, guint cnxn_id, GConfEntry *entry, void *crap)
829 struct _system_info *info;
831 g_return_if_fail (gconf_entry_get_key (entry) != NULL);
833 if (!(value = gconf_entry_get_value (entry)))
836 tkey = strrchr(entry->key, '/');
837 g_return_if_fail (tkey != NULL);
839 info = g_hash_table_lookup(ea_system_table, tkey+1);
841 if (gconf_value_get_bool(value))
842 ea_perms |= info->perm;
844 ea_perms &= ~info->perm;
849 ea_setting_setup(void)
851 GConfClient *gconf = gconf_client_get_default();
857 if (ea_option_table != NULL)
860 ea_option_table = g_hash_table_new(g_str_hash, g_str_equal);
861 for (i=0;i<sizeof(ea_option_list)/sizeof(ea_option_list[0]);i++)
862 g_hash_table_insert(ea_option_table, ea_option_list[i].key, &ea_option_list[i]);
864 gconf_client_add_dir(gconf, LOCK_BASE, GCONF_CLIENT_PRELOAD_NONE, NULL);
866 ea_system_table = g_hash_table_new(g_str_hash, g_str_equal);
867 for (i=0;i<sizeof(system_perms)/sizeof(system_perms[0]);i++) {
868 g_hash_table_insert(ea_system_table, (char *)system_perms[i].key, &system_perms[i]);
869 sprintf(key, LOCK_BASE "/%s", system_perms[i].key);
870 entry = gconf_client_get_entry(gconf, key, NULL, TRUE, &err);
872 ea_setting_notify(gconf, 0, entry, NULL);
873 gconf_entry_free(entry);
877 g_warning("Could not load account lock settings: %s", err->message);
881 gconf_client_notify_add(gconf, LOCK_BASE, (GConfClientNotifyFunc)ea_setting_notify, NULL, NULL, NULL);
882 g_object_unref(gconf);
885 /* look up the item in the structure or the substructure using our table of reflection data */
886 #define addr(ea, type) \
887 ((account_info[type].type & TYPE_STRUCT)? \
888 (((char **)(((char *)ea)+account_info[type].offset))[0] + account_info[type].struct_offset): \
889 (((char *)ea)+account_info[type].offset))
891 const char *e_account_get_string(EAccount *ea, e_account_item_t type)
893 return *((const char **)addr(ea, type));
896 int e_account_get_int(EAccount *ea, e_account_item_t type)
898 return *((int *)addr(ea, type));
901 gboolean e_account_get_bool(EAccount *ea, e_account_item_t type)
903 return *((gboolean *)addr(ea, type));
908 dump_account(EAccount *ea)
912 printf("Account changed\n");
913 xml = e_account_to_xml(ea);
914 printf(" ->\n%s\n", xml);
919 /* TODO: should it return true if it changed? */
920 void e_account_set_string(EAccount *ea, e_account_item_t type, const char *val)
924 if (!e_account_writable(ea, type)) {
925 g_warning("Trying to set non-writable option account value");
927 p = (char **)addr(ea, type);
928 d(printf("Setting string %d: old '%s' new '%s'\n", type, *p, val));
930 && (*p == NULL || val == NULL || strcmp(*p, val) != 0)) {
934 g_signal_emit(ea, signals[CHANGED], 0, type);
939 void e_account_set_int(EAccount *ea, e_account_item_t type, int val)
941 if (!e_account_writable(ea, type)) {
942 g_warning("Trying to set non-writable option account value");
944 int *p = (int *)addr(ea, type);
949 g_signal_emit(ea, signals[CHANGED], 0, type);
954 void e_account_set_bool(EAccount *ea, e_account_item_t type, gboolean val)
956 if (!e_account_writable(ea, type)) {
957 g_warning("Trying to set non-writable option account value");
959 gboolean *p = (gboolean *)addr(ea, type);
964 g_signal_emit(ea, signals[CHANGED], 0, type);
970 e_account_writable_option(EAccount *ea, const char *protocol, const char *option)
973 struct _option_info *info;
977 key = alloca(strlen(protocol)+strlen(option)+2);
978 sprintf(key, "%s_%s", protocol, option);
980 info = g_hash_table_lookup(ea_option_table, key);
982 sprintf(key, "*_%s", option);
983 info = g_hash_table_lookup(ea_option_table, key);
986 d(printf("checking writable option '%s' perms=%08x\n", option, info?info->perms:0));
989 || (info->perms & ea_perms) == 0;
993 e_account_writable(EAccount *ea, e_account_item_t type)
997 return (account_info[type].perms & ea_perms) == 0;