#include <libxml/tree.h>
#include <libxml/xmlmemory.h>
+#include <gconf/gconf-client.h>
+
+#define d(x)
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
static void finalize (GObject *);
G_DEFINE_TYPE (EAccount, e_account, G_TYPE_OBJECT);
+/*
+lock mail accounts Relatively difficult -- involves redesign of the XML blobs which describe accounts
+disable adding mail accounts Simple -- can be done with just a Gconf key and some UI work to make assoc. widgets unavailable
+disable editing mail accounts Relatively difficult -- involves redesign of the XML blobs which describe accounts
+disable removing mail accounts
+lock default character encoding Simple -- Gconf key + a little UI work to desensitize widgets, etc
+disable free busy publishing
+disable specific mime types (from being viewed) 90% done already (Unknown MIME types still pose a problem)
+lock image loading preference
+lock junk mail filtering settings
+** junk mail per account
+lock work week
+lock first day of work week
+lock working hours
+disable forward as icalendar
+lock color options for tasks
+lock default contact filing format
+* forbid signatures Simple -- can be done with just a Gconf key and some UI work to make assoc. widgets unavailable
+* 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
+* forbid adding/removing signatures Simple -- can be done with just a Gconf key and some UI work to make assoc. widgets unavailable
+* lock each account to a certain signature Relatively difficult -- involved redesign of the XML blobs which describe accounts
+* set default folders
+set trash emptying frequency
+* lock displayed mail headers Simple -- can be done with just a Gconf key and some UI work to make assoc. widgets unavailable
+* lock authentication type (for incoming mail) Relatively difficult -- involves redesign of the XML blobs which describe accounts
+* lock authentication type (for outgoing mail) Relatively difficult -- involves redesign of the XML blobs which describe accounts
+* 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
+** lock save password
+* require ssl always Relatively difficult -- involves redesign of the XML blobs which describe accounts
+** lock imap subscribed folder option
+** lock filtering of inbox
+** lock source account/options
+** lock destination account/options
+*/
+
static void
e_account_class_init (EAccountClass *account_class)
{
/* virtual method override */
object_class->finalize = finalize;
+
+ signals[CHANGED] =
+ g_signal_new("changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EAccountClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE, 1,
+ G_TYPE_INT);
}
static void
account->id = g_new0 (EAccountIdentity, 1);
account->source = g_new0 (EAccountService, 1);
account->transport = g_new0 (EAccountService, 1);
+
+ account->parent_uid = NULL;
+
+ account->source->auto_check = FALSE;
+ account->source->auto_check_time = 10;
}
static void
g_free (id->address);
g_free (id->reply_to);
g_free (id->organization);
+ g_free (id->sig_uid);
g_free (id);
}
g_free (account->smime_sign_key);
g_free (account->smime_encrypt_key);
+ g_free (account->parent_uid);
+
G_OBJECT_CLASS (e_account_parent_class)->finalize (object);
}
static gboolean
xml_set_prop (xmlNodePtr node, const char *name, char **val)
{
- char *buf, *new_val;
+ char *buf;
+ int res;
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;
+ if (buf == NULL) {
+ res = (*val != NULL);
+ if (res) {
+ g_free(*val);
+ *val = NULL;
+ }
} else {
- g_free (new_val);
- return FALSE;
+ res = *val == NULL || strcmp(*val, buf) != 0;
+ if (res) {
+ g_free(*val);
+ *val = g_strdup(buf);
+ }
+ xmlFree(buf);
+ }
+
+ return res;
+}
+
+static EAccountReceiptPolicy
+str_to_receipt_policy (const char *str)
+{
+ if (!strcmp (str, "ask"))
+ return E_ACCOUNT_RECEIPT_ASK;
+ if (!strcmp (str, "always"))
+ return E_ACCOUNT_RECEIPT_ALWAYS;
+
+ return E_ACCOUNT_RECEIPT_NEVER;
+}
+
+static char*
+receipt_policy_to_str (EAccountReceiptPolicy val)
+{
+ char *ret = 0;
+
+ switch (val) {
+ case E_ACCOUNT_RECEIPT_NEVER:
+ ret = "never";
+ break;
+ case E_ACCOUNT_RECEIPT_ASK:
+ ret = "ask";
+ break;
+ case E_ACCOUNT_RECEIPT_ALWAYS:
+ ret = "always";
+ break;
}
+
+ return ret;
+}
+
+static gboolean
+xml_set_receipt_policy (xmlNodePtr node, const char *name, EAccountReceiptPolicy *val)
+{
+ EAccountReceiptPolicy new_val;
+ char *buf;
+
+ if ((buf = xmlGetProp (node, name))) {
+ new_val = str_to_receipt_policy (buf);
+ xmlFree (buf);
+
+ if (new_val != *val) {
+ *val = new_val;
+ return TRUE;
+ }
+ }
+
+ 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;
+ char *buf;
+ int res;
+
+ buf = xmlNodeGetContent(node);
+ if (buf == NULL) {
+ res = (*val != NULL);
+ if (res) {
+ g_free(*val);
+ *val = NULL;
+ }
} else {
- g_free (new_val);
- return FALSE;
+ res = *val == NULL || strcmp(*val, buf) != 0;
+ if (res) {
+ g_free(*val);
+ *val = g_strdup(buf);
+ }
+ xmlFree(buf);
}
+
+ return res;
}
static gboolean
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);
+ changed |= xml_set_prop (node, "uid", &id->sig_uid);
+ if (!id->sig_uid) {
+
+ /* WTF is this shit doing here? Migrate is supposed to "handle this" */
+
+ /* set a fake sig uid so the migrate code can handle this */
+ gboolean autogen = FALSE;
+ int sig_id = 0;
+
+ xml_set_bool (node, "auto", &autogen);
+ xml_set_int (node, "default", &sig_id);
+
+ if (autogen) {
+ id->sig_uid = g_strdup ("::0");
+ changed = TRUE;
+ } else if (sig_id) {
+ id->sig_uid = g_strdup_printf ("::%d", sig_id + 1);
+ changed = TRUE;
+ }
+ }
}
}
} 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, "receipt-policy")) {
+ changed |= xml_set_receipt_policy (node, "policy", &account->receipt_policy);
} 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);
}
}
}
+ } else if (!strcmp (node->name, "proxy")) {
+ if (node->children) {
+ for (cur = node->children; cur; cur = cur->next) {
+ if (!strcmp (cur->name, "parent-uid")) {
+ changed |= xml_set_content (cur, &account->parent_uid);
+ break;
+ }
+ }
+ }
}
}
xmlFreeDoc (doc);
+ g_signal_emit(account, signals[CHANGED], 0, -1);
+
return changed;
}
dest->id->reply_to = g_strdup (src->id->reply_to);
g_free (dest->id->organization);
dest->id->organization = g_strdup (src->id->organization);
- dest->id->def_signature = src->id->def_signature;
- dest->id->auto_signature = src->id->auto_signature;
+ dest->id->sig_uid = g_strdup (src->id->sig_uid);
g_free (dest->source->url);
dest->source->url = g_strdup (src->source->url);
g_free (dest->bcc_addrs);
dest->bcc_addrs = g_strdup (src->bcc_addrs);
+ dest->receipt_policy = src->receipt_policy;
+
g_free (dest->pgp_key);
dest->pgp_key = g_strdup (src->pgp_key);
dest->pgp_encrypt_to_self = src->pgp_encrypt_to_self;
dest->smime_encrypt_to_self = src->smime_encrypt_to_self;
g_free (dest->smime_encrypt_key);
dest->smime_encrypt_key = g_strdup (src->smime_encrypt_key);
+
+ g_signal_emit(dest, signals[CHANGED], 0, -1);
}
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);
+ xmlSetProp (node, "uid", account->id->sig_uid);
src = xmlNewChild (root, NULL, "source", NULL);
xmlSetProp (src, "save-passwd", account->source->save_passwd ? "true" : "false");
if (account->bcc_addrs)
xmlNewTextChild (node, NULL, "recipients", account->bcc_addrs);
+ node = xmlNewChild (root, NULL, "receipt-policy", NULL);
+ xmlSetProp (node, "policy", receipt_policy_to_str (account->receipt_policy));
+
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");
if (account->smime_encrypt_key)
xmlNewTextChild (node, NULL, "encrypt-key-id", account->smime_encrypt_key);
+ if (account->parent_uid) {
+ node = xmlNewChild (root, NULL, "proxy", NULL);
+ xmlNewTextChild (node, NULL, "parent-uid", account->parent_uid);
+ }
+
xmlDocDumpMemory (doc, &xmlbuf, &n);
xmlFreeDoc (doc);
return uid;
}
+
+enum {
+ EAP_IMAP_SUBSCRIBED = 0,
+ EAP_IMAP_NAMESPACE,
+ EAP_FILTER_INBOX,
+ EAP_FILTER_JUNK,
+ EAP_FORCE_SSL,
+ EAP_LOCK_SIGNATURE,
+ EAP_LOCK_AUTH,
+ EAP_LOCK_AUTOCHECK,
+ EAP_LOCK_DEFAULT_FOLDERS,
+ EAP_LOCK_SAVE_PASSWD,
+ EAP_LOCK_SOURCE,
+ EAP_LOCK_TRANSPORT,
+};
+
+static struct _system_info {
+ const char *key;
+ guint32 perm;
+} system_perms[] = {
+ { "imap_subscribed", 1<<EAP_IMAP_SUBSCRIBED },
+ { "imap_namespace", 1<<EAP_IMAP_NAMESPACE },
+ { "filter_inbox", 1<<EAP_FILTER_INBOX },
+ { "filter_junk", 1<<EAP_FILTER_JUNK },
+ { "ssl", 1<<EAP_FORCE_SSL },
+ { "signature", 1<<EAP_LOCK_SIGNATURE },
+ { "authtype", 1<<EAP_LOCK_AUTH },
+ { "autocheck", 1<<EAP_LOCK_AUTOCHECK },
+ { "default_folders", 1<<EAP_LOCK_DEFAULT_FOLDERS },
+ { "save_passwd" , 1<<EAP_LOCK_SAVE_PASSWD },
+ { "source", 1<<EAP_LOCK_SOURCE },
+ { "transport", 1<<EAP_LOCK_TRANSPORT },
+};
+
+#define TYPE_STRING (1)
+#define TYPE_INT (2)
+#define TYPE_BOOL (3)
+#define TYPE_MASK (0xff)
+#define TYPE_STRUCT (1<<8)
+
+static struct _account_info {
+ guint32 perms;
+ guint32 type;
+ unsigned int offset;
+ unsigned int struct_offset;
+} account_info[E_ACCOUNT_ITEM_LAST] = {
+ { /* E_ACCOUNT_NAME */ 0, TYPE_STRING, G_STRUCT_OFFSET(EAccount, name) },
+
+ { /* E_ACCOUNT_ID_NAME, */ 0, TYPE_STRING|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, id), G_STRUCT_OFFSET(EAccountIdentity, name) },
+ { /* E_ACCOUNT_ID_ADDRESS, */ 0, TYPE_STRING|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, id), G_STRUCT_OFFSET(EAccountIdentity, address) },
+ { /* E_ACCOUNT_ID_REPLY_TO, */ 0, TYPE_STRING|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, id), G_STRUCT_OFFSET(EAccountIdentity, reply_to) },
+ { /* E_ACCOUNT_ID_ORGANIZATION */ 0, TYPE_STRING|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, id), G_STRUCT_OFFSET(EAccountIdentity, organization) },
+ { /* E_ACCOUNT_ID_SIGNATURE */ 1<<EAP_LOCK_SIGNATURE, TYPE_STRING|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, id), G_STRUCT_OFFSET(EAccountIdentity, sig_uid) },
+
+ { /* E_ACCOUNT_SOURCE_URL */ 1<<EAP_LOCK_SOURCE, TYPE_STRING|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, source), G_STRUCT_OFFSET(EAccountService, url) },
+ { /* E_ACCOUNT_SOURCE_KEEP_ON_SERVER */ 0, TYPE_BOOL|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, source), G_STRUCT_OFFSET(EAccountService, keep_on_server) },
+ { /* E_ACCOUNT_SOURCE_AUTO_CHECK */ 1<<EAP_LOCK_AUTOCHECK, TYPE_BOOL|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, source), G_STRUCT_OFFSET(EAccountService, auto_check) },
+ { /* 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) },
+ { /* 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) },
+
+ { /* E_ACCOUNT_TRANSPORT_URL */ 1<<EAP_LOCK_TRANSPORT, TYPE_STRING|TYPE_STRUCT, G_STRUCT_OFFSET(EAccount, transport), G_STRUCT_OFFSET(EAccountService, url) },
+ { /* 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) },
+
+ { /* E_ACCOUNT_DRAFTS_FOLDER_URI */ 1<<EAP_LOCK_DEFAULT_FOLDERS, TYPE_STRING, G_STRUCT_OFFSET(EAccount, drafts_folder_uri) },
+ { /* E_ACCOUNT_SENT_FOLDER_URI */ 1<<EAP_LOCK_DEFAULT_FOLDERS, TYPE_STRING, G_STRUCT_OFFSET(EAccount, sent_folder_uri) },
+
+ { /* E_ACCOUNT_CC_ALWAYS */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, always_cc) },
+ { /* E_ACCOUNT_CC_ADDRS */ 0, TYPE_STRING, G_STRUCT_OFFSET(EAccount, cc_addrs) },
+
+ { /* E_ACCOUNT_BCC_ALWAYS */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, always_bcc) },
+ { /* E_ACCOUNT_BCC_ADDRS */ 0, TYPE_STRING, G_STRUCT_OFFSET(EAccount, bcc_addrs) },
+
+ { /* E_ACCOUNT_RECEIPT_POLICY */ 0, TYPE_INT, G_STRUCT_OFFSET(EAccount, receipt_policy) },
+
+ { /* E_ACCOUNT_PGP_KEY */ 0, TYPE_STRING, G_STRUCT_OFFSET(EAccount, pgp_key) },
+ { /* E_ACCOUNT_PGP_ENCRYPT_TO_SELF */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, pgp_encrypt_to_self) },
+ { /* E_ACCOUNT_PGP_ALWAYS_SIGN */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, pgp_always_sign) },
+ { /* E_ACCOUNT_PGP_NO_IMIP_SIGN */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, pgp_no_imip_sign) },
+ { /* E_ACCOUNT_PGP_ALWAYS_TRUST */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, pgp_always_trust) },
+
+ { /* E_ACCOUNT_SMIME_SIGN_KEY */ 0, TYPE_STRING, G_STRUCT_OFFSET(EAccount, smime_sign_key) },
+ { /* E_ACCOUNT_SMIME_ENCRYPT_KEY */ 0, TYPE_STRING, G_STRUCT_OFFSET(EAccount, smime_encrypt_key) },
+ { /* E_ACCOUNT_SMIME_SIGN_DEFAULT */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, smime_sign_default) },
+ { /* E_ACCOUNT_SMIME_ENCRYPT_TO_SELF */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, smime_encrypt_to_self) },
+ { /* E_ACCOUNT_SMIME_ENCRYPT_DEFAULT */ 0, TYPE_BOOL, G_STRUCT_OFFSET(EAccount, smime_encrypt_default) },
+
+ { /* E_ACCOUNT_PROXY_PARENT_UID, */ 0, TYPE_STRING, G_STRUCT_OFFSET(EAccount, parent_uid) },
+};
+
+static GHashTable *ea_option_table;
+static GHashTable *ea_system_table;
+static guint32 ea_perms;
+
+static struct _option_info {
+ char *key;
+ guint32 perms;
+} ea_option_list[] = {
+ { "imap_use_lsub", 1<<EAP_IMAP_SUBSCRIBED },
+ { "imap_override_namespace", 1<<EAP_IMAP_NAMESPACE },
+ { "imap_filter", 1<<EAP_FILTER_INBOX },
+ { "imap_filter_junk", 1<<EAP_FILTER_JUNK },
+ { "imap_filter_junk_inbox", 1<<EAP_FILTER_JUNK },
+ { "*_use_ssl", 1<<EAP_FORCE_SSL },
+ { "*_auth", 1<<EAP_LOCK_AUTH },
+};
+
+#define LOCK_BASE "/apps/evolution/lock/mail/accounts"
+
+static void
+ea_setting_notify(GConfClient *gconf, guint cnxn_id, GConfEntry *entry, void *crap)
+{
+ GConfValue *value;
+ char *tkey;
+ struct _system_info *info;
+
+ g_return_if_fail (gconf_entry_get_key (entry) != NULL);
+
+ if (!(value = gconf_entry_get_value (entry)))
+ return;
+
+ tkey = strrchr(entry->key, '/');
+ g_return_if_fail (tkey != NULL);
+
+ info = g_hash_table_lookup(ea_system_table, tkey+1);
+ if (info) {
+ if (gconf_value_get_bool(value))
+ ea_perms |= info->perm;
+ else
+ ea_perms &= ~info->perm;
+ }
+}
+
+static void
+ea_setting_setup(void)
+{
+ GConfClient *gconf = gconf_client_get_default();
+ GConfEntry *entry;
+ GError *err = NULL;
+ int i;
+ char key[64];
+
+ if (ea_option_table != NULL)
+ return;
+
+ ea_option_table = g_hash_table_new(g_str_hash, g_str_equal);
+ for (i=0;i<sizeof(ea_option_list)/sizeof(ea_option_list[0]);i++)
+ g_hash_table_insert(ea_option_table, ea_option_list[i].key, &ea_option_list[i]);
+
+ gconf_client_add_dir(gconf, LOCK_BASE, GCONF_CLIENT_PRELOAD_NONE, NULL);
+
+ ea_system_table = g_hash_table_new(g_str_hash, g_str_equal);
+ for (i=0;i<sizeof(system_perms)/sizeof(system_perms[0]);i++) {
+ g_hash_table_insert(ea_system_table, (char *)system_perms[i].key, &system_perms[i]);
+ sprintf(key, LOCK_BASE "/%s", system_perms[i].key);
+ entry = gconf_client_get_entry(gconf, key, NULL, TRUE, &err);
+ if (entry)
+ ea_setting_notify(gconf, 0, entry, NULL);
+ gconf_entry_free(entry);
+ }
+
+ if (err) {
+ g_warning("Could not load account lock settings: %s", err->message);
+ g_error_free(err);
+ }
+
+ gconf_client_notify_add(gconf, LOCK_BASE, (GConfClientNotifyFunc)ea_setting_notify, NULL, NULL, NULL);
+ g_object_unref(gconf);
+}
+
+/* look up the item in the structure or the substructure using our table of reflection data */
+#define addr(ea, type) \
+ ((account_info[type].type & TYPE_STRUCT)? \
+ (((char **)(((char *)ea)+account_info[type].offset))[0] + account_info[type].struct_offset): \
+ (((char *)ea)+account_info[type].offset))
+
+const char *e_account_get_string(EAccount *ea, e_account_item_t type)
+{
+ return *((const char **)addr(ea, type));
+}
+
+int e_account_get_int(EAccount *ea, e_account_item_t type)
+{
+ return *((int *)addr(ea, type));
+}
+
+gboolean e_account_get_bool(EAccount *ea, e_account_item_t type)
+{
+ return *((gboolean *)addr(ea, type));
+}
+
+#if d(!)0
+static void
+dump_account(EAccount *ea)
+{
+ char *xml;
+
+ printf("Account changed\n");
+ xml = e_account_to_xml(ea);
+ printf(" ->\n%s\n", xml);
+ g_free(xml);
+}
+#endif
+
+/* TODO: should it return true if it changed? */
+void e_account_set_string(EAccount *ea, e_account_item_t type, const char *val)
+{
+ char **p;
+
+ if (!e_account_writable(ea, type)) {
+ g_warning("Trying to set non-writable option account value");
+ } else {
+ p = (char **)addr(ea, type);
+ d(printf("Setting string %d: old '%s' new '%s'\n", type, *p, val));
+ if (*p != val
+ && (*p == NULL || val == NULL || strcmp(*p, val) != 0)) {
+ g_free(*p);
+ *p = g_strdup(val);
+ d(dump_account(ea));
+ g_signal_emit(ea, signals[CHANGED], 0, type);
+ }
+ }
+}
+
+void e_account_set_int(EAccount *ea, e_account_item_t type, int val)
+{
+ if (!e_account_writable(ea, type)) {
+ g_warning("Trying to set non-writable option account value");
+ } else {
+ int *p = (int *)addr(ea, type);
+
+ if (*p != val) {
+ *p = val;
+ d(dump_account(ea));
+ g_signal_emit(ea, signals[CHANGED], 0, type);
+ }
+ }
+}
+
+void e_account_set_bool(EAccount *ea, e_account_item_t type, gboolean val)
+{
+ if (!e_account_writable(ea, type)) {
+ g_warning("Trying to set non-writable option account value");
+ } else {
+ gboolean *p = (gboolean *)addr(ea, type);
+
+ if (*p != val) {
+ *p = val;
+ d(dump_account(ea));
+ g_signal_emit(ea, signals[CHANGED], 0, type);
+ }
+ }
+}
+
+gboolean
+e_account_writable_option(EAccount *ea, const char *protocol, const char *option)
+{
+ char *key;
+ struct _option_info *info;
+
+ ea_setting_setup();
+
+ key = alloca(strlen(protocol)+strlen(option)+2);
+ sprintf(key, "%s_%s", protocol, option);
+
+ info = g_hash_table_lookup(ea_option_table, key);
+ if (info == NULL) {
+ sprintf(key, "*_%s", option);
+ info = g_hash_table_lookup(ea_option_table, key);
+ }
+
+ d(printf("checking writable option '%s' perms=%08x\n", option, info?info->perms:0));
+
+ return info == NULL
+ || (info->perms & ea_perms) == 0;
+}
+
+gboolean
+e_account_writable(EAccount *ea, e_account_item_t type)
+{
+ ea_setting_setup();
+
+ return (account_info[type].perms & ea_perms) == 0;
+}