1 /* modest-account-mgr.c */
3 /* insert (c)/licensing information) */
6 #include "modest-marshal.h"
7 #include "modest-account-keys.h"
8 #include "modest-account-mgr.h"
10 /* 'private'/'protected' functions */
11 static void modest_account_mgr_class_init (ModestAccountMgrClass * klass);
12 static void modest_account_mgr_init (ModestAccountMgr * obj);
13 static void modest_account_mgr_finalize (GObject * obj);
15 static gchar *get_account_keyname (const gchar * accname, const gchar * name);
16 static gchar *get_server_account_keyname (const gchar * accname,
21 ACCOUNT_CHANGE_SIGNAL,
22 ACCOUNT_REMOVE_SIGNAL,
27 typedef struct _ModestAccountMgrPrivate ModestAccountMgrPrivate;
28 struct _ModestAccountMgrPrivate {
29 ModestConf *modest_conf;
30 GSList *current_accounts;
33 #define MODEST_ACCOUNT_MGR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
34 MODEST_TYPE_ACCOUNT_MGR, \
35 ModestAccountMgrPrivate))
37 static GObjectClass *parent_class = NULL;
39 static guint signals[LAST_SIGNAL] = {0};
43 delete_account_from_list (GSList *list, const gchar *name)
45 GSList *iter, *result;
50 if (!strcmp (name, iter->data)) {
51 result = g_slist_delete_link (list, iter);
55 iter = g_slist_next (iter);
61 find_account_in_list (GSList *list, const gchar *name)
63 GSList *iter, *result;
68 if (!strcmp (name, iter->data)) {
73 iter = g_slist_next (iter);
78 /* Map configuration changes to account changes.
79 * Doing this here makes sure all changes are available and external changes
80 * are covered as well. */
83 modest_account_mgr_check_change (ModestConf *conf, const gchar *key,
84 const gchar *new_value, gpointer user_data)
86 ModestAccountMgr *amgr = user_data;
87 ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (amgr);
89 if ((strlen (key) > strlen (MODEST_SERVER_ACCOUNT_NAMESPACE "/")
90 && g_str_has_prefix (key, MODEST_SERVER_ACCOUNT_NAMESPACE))) {
91 gchar *subkey = g_strdup(key + strlen (MODEST_SERVER_ACCOUNT_NAMESPACE "/"));
93 if (! strstr (subkey, "/")) {/* no more '/' means an account was modified */
95 /* covers only one case of two */
97 priv->current_accounts =
98 g_slist_prepend (priv->current_accounts, g_strdup (subkey));
99 g_signal_emit (amgr, signals[ACCOUNT_ADD_SIGNAL], 0, subkey);
102 priv->current_accounts =
103 delete_account_from_list (priv->current_accounts, subkey);
105 g_signal_emit (amgr, signals[ACCOUNT_REMOVE_SIGNAL], 0, subkey);
110 param = strstr (subkey, "/");
114 /* that's the second case for a new account */
115 if (!find_account_in_list (priv->current_accounts, subkey) && strstr (param, MODEST_ACCOUNT_PROTO)) {
116 priv->current_accounts =
117 g_slist_prepend (priv->current_accounts, g_strdup (subkey));
118 g_signal_emit (amgr, signals[ACCOUNT_ADD_SIGNAL], 0, subkey);
121 g_signal_emit (amgr, signals[ACCOUNT_CHANGE_SIGNAL], 0, subkey, param, new_value);
130 modest_account_mgr_get_type (void)
132 static GType my_type = 0;
135 static const GTypeInfo my_info = {
136 sizeof (ModestAccountMgrClass),
137 NULL, /* base init */
138 NULL, /* base finalize */
139 (GClassInitFunc) modest_account_mgr_class_init,
140 NULL, /* class finalize */
141 NULL, /* class data */
142 sizeof (ModestAccountMgr),
144 (GInstanceInitFunc) modest_account_mgr_init,
147 my_type = g_type_register_static (G_TYPE_OBJECT,
155 modest_account_mgr_class_init (ModestAccountMgrClass * klass)
157 GObjectClass *gobject_class;
158 GType paramtypes[3] = {G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER};
160 gobject_class = (GObjectClass *) klass;
162 parent_class = g_type_class_peek_parent (klass);
163 gobject_class->finalize = modest_account_mgr_finalize;
165 g_type_class_add_private (gobject_class,
166 sizeof (ModestAccountMgrPrivate));
168 /* signal definitions */
169 signals[ACCOUNT_ADD_SIGNAL] =
170 g_signal_newv ("account-add",
171 G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
173 g_cclosure_marshal_VOID__POINTER,
174 G_TYPE_NONE, 1, paramtypes);
176 signals[ACCOUNT_REMOVE_SIGNAL] =
177 g_signal_newv ("account-remove",
178 G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
180 g_cclosure_marshal_VOID__POINTER,
181 G_TYPE_NONE, 1, paramtypes);
182 signals[ACCOUNT_CHANGE_SIGNAL] =
183 g_signal_newv ("account-change",
184 G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
186 modest_marshal_VOID__POINTER_POINTER_POINTER,
187 G_TYPE_NONE, 3, paramtypes);
192 modest_account_mgr_init (ModestAccountMgr * obj)
194 ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (obj);
196 priv->modest_conf = NULL;
200 modest_account_mgr_finalize (GObject * obj)
202 ModestAccountMgr *self = MODEST_ACCOUNT_MGR (obj);
203 ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
205 if (priv->modest_conf) {
206 g_object_unref (G_OBJECT(priv->modest_conf));
207 priv->modest_conf = NULL;
212 modest_account_mgr_new (ModestConf * conf)
215 ModestAccountMgrPrivate *priv;
217 g_return_val_if_fail (conf, NULL);
219 obj = G_OBJECT (g_object_new (MODEST_TYPE_ACCOUNT_MGR, NULL));
220 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (obj);
223 * increase the ref count on the modest_conf. Normally, the
224 * ModestConf should outlive the ModestAccountMgr though
226 g_object_ref (G_OBJECT (priv->modest_conf = conf));
228 priv->current_accounts = modest_account_mgr_account_names (MODEST_ACCOUNT_MGR(obj), NULL);
230 g_signal_connect (G_OBJECT (conf), "key-changed",
231 G_CALLBACK (modest_account_mgr_check_change), obj);
237 modest_account_mgr_add_account (ModestAccountMgr * self, const gchar * name,
238 const gchar * store_account,
239 const gchar * transport_account,
242 ModestAccountMgrPrivate *priv;
245 g_return_val_if_fail (self, FALSE);
246 g_return_val_if_fail (name, FALSE);
248 if (modest_account_mgr_account_exists (self, name, err)) {
249 g_warning ("account already exists");
253 * we create the account by adding an account 'dir', with the name <name>,
254 * and in that the 'display_name' string key
256 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
258 key = get_account_keyname (name, MODEST_ACCOUNT_DISPLAY_NAME);
259 modest_conf_set_string (priv->modest_conf, key, name, err);
263 key = get_account_keyname (name,
264 MODEST_ACCOUNT_STORE_ACCOUNT);
265 modest_conf_set_string (priv->modest_conf, key, store_account,
270 if (transport_account) {
271 key = get_account_keyname (name,
272 MODEST_ACCOUNT_TRANSPORT_ACCOUNT);
273 modest_conf_set_string (priv->modest_conf, key,
274 transport_account, err);
278 return TRUE; /* TODO: error handling */
283 modest_account_mgr_remove_account (ModestAccountMgr * self,
284 const gchar * name, GError ** err)
286 ModestAccountMgrPrivate *priv;
290 g_return_val_if_fail (self, FALSE);
291 g_return_val_if_fail (name, FALSE);
293 if (!modest_account_mgr_account_exists (self, name, err)) {
294 g_warning ("account doest not exist");
298 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
299 key = get_account_keyname (name, NULL);
301 retval = modest_conf_remove_key (priv->modest_conf, key, NULL);
309 null_means_empty (const gchar * str)
311 return str ? str : "";
316 modest_account_mgr_add_server_account (ModestAccountMgr * self,
318 const gchar * hostname,
319 const gchar * username,
320 const gchar * password,
323 ModestAccountMgrPrivate *priv;
326 g_return_val_if_fail (self, FALSE);
327 g_return_val_if_fail (name, FALSE);
329 /* TODO: check already exists */
331 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
332 acckey = g_strconcat (MODEST_SERVER_ACCOUNT_NAMESPACE, "/",
335 if (modest_conf_key_exists (priv->modest_conf, acckey, NULL)) {
336 g_warning ("server account %s already exists", name);
342 key = g_strconcat (acckey, "/", MODEST_ACCOUNT_HOSTNAME, NULL);
343 modest_conf_set_string (priv->modest_conf, key,
344 null_means_empty (hostname), NULL);
348 key = g_strconcat (acckey, "/", MODEST_ACCOUNT_USERNAME, NULL);
349 modest_conf_set_string (priv->modest_conf, key,
350 null_means_empty (username), NULL);
355 key = g_strconcat (acckey, "/", MODEST_ACCOUNT_PASSWORD,
357 modest_conf_set_string (priv->modest_conf, key,
358 null_means_empty (password), NULL);
363 key = g_strconcat (acckey, "/", MODEST_ACCOUNT_PROTO, NULL);
364 modest_conf_set_string (priv->modest_conf, key,
365 null_means_empty (proto), NULL);
369 return TRUE; /* FIXME: better error checking */
373 modest_account_mgr_remove_server_account (ModestAccountMgr * self,
374 const gchar * name, GError ** err)
376 ModestAccountMgrPrivate *priv;
380 g_return_val_if_fail (self, FALSE);
381 g_return_val_if_fail (name, FALSE);
383 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
385 acckey = g_strconcat (MODEST_SERVER_ACCOUNT_NAMESPACE, "/",
388 if (!modest_conf_key_exists (priv->modest_conf, acckey, NULL)) {
389 g_warning ("server account %s does not exist exist", name);
394 retval = modest_conf_remove_key (priv->modest_conf, acckey, NULL);
401 /* strip the first /n/ character from each element */
402 /* caller must make sure all elements are strings with
403 * length >= n, and also that data can be freed.
406 strip_prefix_from_elements (GSList * lst, guint n)
408 GSList *cursor = lst;
411 gchar *str = (gchar *) cursor->data;
413 cursor->data = g_strdup (str + n);
415 cursor = cursor->next;
422 modest_account_mgr_server_account_names (ModestAccountMgr * self,
423 const gchar * account_name,
424 ModestProtoType type,
426 gboolean only_enabled)
430 ModestAccountMgrPrivate *priv;
431 const size_t prefix_len =
432 strlen (MODEST_SERVER_ACCOUNT_NAMESPACE "/");
434 g_return_val_if_fail (self, NULL);
436 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
437 accounts = modest_conf_list_subkeys (priv->modest_conf,
438 MODEST_SERVER_ACCOUNT_NAMESPACE,
441 /* no restrictions, return everything */
442 if (type == MODEST_PROTO_TYPE_ANY && !proto)
443 return strip_prefix_from_elements (accounts, prefix_len);
445 /* otherwise, filter out the none-matching ones */
448 gchar *keyspace, *proto_key, *acc_proto;
450 keyspace = (gchar *) cursor->data;
452 g_strconcat (keyspace, "/", MODEST_ACCOUNT_PROTO,
455 modest_conf_get_string (priv->modest_conf, proto_key,
459 if ((!acc_proto) || /* proto not defined? */
460 (type != MODEST_PROTO_TYPE_ANY && /* proto type ... */
461 modest_proto_type (acc_proto) != type) || /* ... matches? */
462 (proto && strcmp (proto, acc_proto) != 0)) { /* proto matches? */
463 /* no match: remove from the list */
464 GSList *nxt = cursor->next;
467 accounts = g_slist_delete_link (accounts, cursor);
470 cursor = cursor->next;
473 return strip_prefix_from_elements (accounts, prefix_len);
478 modest_account_mgr_account_names (ModestAccountMgr * self, GError ** err)
481 ModestAccountMgrPrivate *priv;
482 const size_t prefix_len = strlen (MODEST_ACCOUNT_NAMESPACE "/");
485 g_return_val_if_fail (self, NULL);
487 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
489 accounts = modest_conf_list_subkeys (priv->modest_conf,
490 MODEST_ACCOUNT_NAMESPACE, err);
491 return strip_prefix_from_elements (accounts, prefix_len);
496 get_account_string (ModestAccountMgr * self, const gchar * name,
497 const gchar * key, gboolean server_account, GError ** err)
499 ModestAccountMgrPrivate *priv;
504 g_return_val_if_fail (self, NULL);
505 g_return_val_if_fail (name, NULL);
506 g_return_val_if_fail (key, NULL);
509 keyname = get_server_account_keyname (name, key);
511 keyname = get_account_keyname (name, key);
513 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
514 retval = modest_conf_get_string (priv->modest_conf, keyname, err);
522 modest_account_mgr_get_server_account_string (ModestAccountMgr * self,
527 return get_account_string (self, name, key, TRUE, err);
532 modest_account_mgr_get_account_string (ModestAccountMgr * self,
533 const gchar * name, const gchar * key,
536 return get_account_string (self, name, key, FALSE, err);
541 get_account_int (ModestAccountMgr * self, const gchar * name,
542 const gchar * key, gboolean server_account, GError ** err)
544 ModestAccountMgrPrivate *priv;
549 g_return_val_if_fail (self, -1);
550 g_return_val_if_fail (name, -1);
551 g_return_val_if_fail (key, -1);
554 keyname = get_server_account_keyname (name, key);
556 keyname = get_account_keyname (name, key);
558 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
559 retval = modest_conf_get_int (priv->modest_conf, keyname, err);
567 modest_account_mgr_get_server_account_int (ModestAccountMgr * self,
569 const gchar * key, GError ** err)
571 return get_account_int (self, name, key, TRUE, err);
576 modest_account_mgr_get_account_int (ModestAccountMgr * self,
577 const gchar * name, const gchar * key,
580 return get_account_int (self, name, key, FALSE, err);
585 get_account_bool (ModestAccountMgr * self, const gchar * name,
586 const gchar * key, gboolean server_account, GError ** err)
588 ModestAccountMgrPrivate *priv;
593 g_return_val_if_fail (self, FALSE);
594 g_return_val_if_fail (name, FALSE);
595 g_return_val_if_fail (key, FALSE);
598 keyname = get_server_account_keyname (name, key);
600 keyname = get_account_keyname (name, key);
602 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
603 retval = modest_conf_get_bool (priv->modest_conf, keyname, err);
611 modest_account_mgr_get_server_account_bool (ModestAccountMgr * self,
613 const gchar * key, GError ** err)
615 return get_account_bool (self, name, key, TRUE, err);
620 modest_account_mgr_get_account_bool (ModestAccountMgr * self,
621 const gchar * name, const gchar * key,
624 return get_account_bool (self, name, key, FALSE, err);
629 set_account_string (ModestAccountMgr * self, const gchar * name,
630 const gchar * key, const gchar * val,
631 gboolean server_account, GError ** err)
633 ModestAccountMgrPrivate *priv;
638 g_return_val_if_fail (self, FALSE);
639 g_return_val_if_fail (name, FALSE);
640 g_return_val_if_fail (key, FALSE);
643 keyname = get_server_account_keyname (name, key);
645 keyname = get_account_keyname (name, key);
647 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
649 retval = modest_conf_set_string (priv->modest_conf, keyname, val,
658 modest_account_mgr_set_server_account_string (ModestAccountMgr * self,
664 return set_account_string (self, name, key, val, TRUE, err);
669 modest_account_mgr_set_account_string (ModestAccountMgr * self,
670 const gchar * name, const gchar * key,
671 const gchar * val, GError ** err)
673 return set_account_string (self, name, key, val, FALSE, err);
678 set_account_int (ModestAccountMgr * self, const gchar * name,
679 const gchar * key, gboolean server_account, int val,
682 ModestAccountMgrPrivate *priv;
687 g_return_val_if_fail (self, FALSE);
688 g_return_val_if_fail (name, FALSE);
689 g_return_val_if_fail (key, FALSE);
692 keyname = get_server_account_keyname (name, key);
694 keyname = get_account_keyname (name, key);
696 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
698 retval = modest_conf_set_int (priv->modest_conf, keyname, val, err);
706 modest_account_mgr_set_server_account_int (ModestAccountMgr * self,
708 const gchar * key, int val,
711 return set_account_int (self, name, key, val, TRUE, err);
716 modest_account_mgr_set_account_int (ModestAccountMgr * self,
717 const gchar * name, const gchar * key,
718 int val, GError ** err)
720 return set_account_int (self, name, key, val, FALSE, err);
725 set_account_bool (ModestAccountMgr * self, const gchar * name,
726 const gchar * key, gboolean server_account, gboolean val,
729 ModestAccountMgrPrivate *priv;
734 g_return_val_if_fail (self, FALSE);
735 g_return_val_if_fail (name, FALSE);
736 g_return_val_if_fail (key, FALSE);
739 keyname = get_server_account_keyname (name, key);
741 keyname = get_account_keyname (name, key);
743 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
745 retval = modest_conf_set_bool (priv->modest_conf, keyname, val, err);
753 modest_account_mgr_set_server_account_bool (ModestAccountMgr * self,
755 const gchar * key, gboolean val,
758 return set_account_bool (self, name, key, val, TRUE, err);
763 modest_account_mgr_set_account_bool (ModestAccountMgr * self,
764 const gchar * name, const gchar * key,
765 gboolean val, GError ** err)
767 return set_account_bool (self, name, key, val, FALSE, err);
772 account_exists (ModestAccountMgr * self, const gchar * name,
773 gboolean server_account, GError ** err)
775 ModestAccountMgrPrivate *priv;
780 g_return_val_if_fail (self, FALSE);
781 g_return_val_if_fail (name, FALSE);
784 keyname = get_server_account_keyname (name, NULL);
786 keyname = get_account_keyname (name, NULL);
788 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
789 retval = modest_conf_key_exists (priv->modest_conf, keyname, err);
797 modest_account_mgr_server_account_exists (ModestAccountMgr * self,
798 const gchar * name, GError ** err)
800 return account_exists (self, name, TRUE, err);
805 modest_account_mgr_account_exists (ModestAccountMgr * self,
806 const gchar * name, GError ** err)
808 return account_exists (self, name, FALSE, err);
812 /* must be freed by caller */
814 get_account_keyname (const gchar * accname, const gchar * name)
818 (MODEST_ACCOUNT_NAMESPACE, "/",
819 accname, "/", name, NULL);
822 (MODEST_ACCOUNT_NAMESPACE, "/", accname, NULL);
826 /* must be freed by caller */
828 get_server_account_keyname (const gchar * accname, const gchar * name)
832 (MODEST_SERVER_ACCOUNT_NAMESPACE, "/",
833 accname, "/", name, NULL);
836 (MODEST_SERVER_ACCOUNT_NAMESPACE, "/", accname, NULL);