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 = key + strlen (MODEST_SERVER_ACCOUNT_NAMESPACE "/");
92 if (! strstr (subkey, "/")) {/* no more '/' means an account was modified */
94 /* covers only one case of two */
95 priv->current_accounts =
96 g_slist_prepend (priv->current_accounts, g_strdup (subkey));
97 g_signal_emit (amgr, signals[ACCOUNT_ADD_SIGNAL], 0, subkey);
99 priv->current_accounts =
100 delete_account_from_list (priv->current_accounts, subkey);
102 g_signal_emit (amgr, signals[ACCOUNT_REMOVE_SIGNAL], 0, subkey);
107 param = strstr (subkey, "/");
111 /* that's the second case for a new account */
112 if (!find_account_in_list (priv->current_accounts, subkey)) {
113 priv->current_accounts =
114 g_slist_prepend (priv->current_accounts, g_strdup (subkey));
115 g_signal_emit (amgr, signals[ACCOUNT_ADD_SIGNAL], 0, subkey);
118 g_signal_emit (amgr, signals[ACCOUNT_CHANGE_SIGNAL], 0, subkey, param, new_value);
122 g_message ("value changed: %s %s\n", key, new_value);
127 modest_account_mgr_get_type (void)
129 static GType my_type = 0;
132 static const GTypeInfo my_info = {
133 sizeof (ModestAccountMgrClass),
134 NULL, /* base init */
135 NULL, /* base finalize */
136 (GClassInitFunc) modest_account_mgr_class_init,
137 NULL, /* class finalize */
138 NULL, /* class data */
139 sizeof (ModestAccountMgr),
141 (GInstanceInitFunc) modest_account_mgr_init,
144 my_type = g_type_register_static (G_TYPE_OBJECT,
152 modest_account_mgr_class_init (ModestAccountMgrClass * klass)
154 GObjectClass *gobject_class;
155 GType paramtypes[3] = {G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER};
157 gobject_class = (GObjectClass *) klass;
159 parent_class = g_type_class_peek_parent (klass);
160 gobject_class->finalize = modest_account_mgr_finalize;
162 g_type_class_add_private (gobject_class,
163 sizeof (ModestAccountMgrPrivate));
165 /* signal definitions */
166 signals[ACCOUNT_ADD_SIGNAL] =
167 g_signal_newv ("account-add",
168 G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
170 g_cclosure_marshal_VOID__POINTER,
171 G_TYPE_NONE, 1, paramtypes);
173 signals[ACCOUNT_REMOVE_SIGNAL] =
174 g_signal_newv ("account-remove",
175 G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
177 g_cclosure_marshal_VOID__POINTER,
178 G_TYPE_NONE, 1, paramtypes);
179 signals[ACCOUNT_CHANGE_SIGNAL] =
180 g_signal_newv ("account-change",
181 G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
183 modest_marshal_VOID__POINTER_POINTER_POINTER,
184 G_TYPE_NONE, 3, paramtypes);
189 modest_account_mgr_init (ModestAccountMgr * obj)
191 ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (obj);
193 priv->modest_conf = NULL;
197 modest_account_mgr_finalize (GObject * obj)
199 ModestAccountMgr *self = MODEST_ACCOUNT_MGR (obj);
200 ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
202 if (priv->modest_conf) {
203 g_object_unref (G_OBJECT(priv->modest_conf));
204 priv->modest_conf = NULL;
209 modest_account_mgr_new (ModestConf * conf)
212 ModestAccountMgrPrivate *priv;
214 g_return_val_if_fail (conf, NULL);
216 obj = G_OBJECT (g_object_new (MODEST_TYPE_ACCOUNT_MGR, NULL));
217 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (obj);
220 * increase the ref count on the modest_conf. Normally, the
221 * ModestConf should outlive the ModestAccountMgr though
223 g_object_ref (G_OBJECT (priv->modest_conf = conf));
225 priv->current_accounts = modest_account_mgr_account_names (MODEST_ACCOUNT_MGR(obj), NULL);
227 g_signal_connect (G_OBJECT (conf), "key-changed",
228 G_CALLBACK (modest_account_mgr_check_change), obj);
234 modest_account_mgr_add_account (ModestAccountMgr * self, const gchar * name,
235 const gchar * store_account,
236 const gchar * transport_account,
239 ModestAccountMgrPrivate *priv;
242 g_return_val_if_fail (self, FALSE);
243 g_return_val_if_fail (name, FALSE);
245 if (modest_account_mgr_account_exists (self, name, err)) {
246 g_warning ("account already exists");
250 * we create the account by adding an account 'dir', with the name <name>,
251 * and in that the 'display_name' string key
253 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
255 key = get_account_keyname (name, MODEST_ACCOUNT_DISPLAY_NAME);
256 modest_conf_set_string (priv->modest_conf, key, name, err);
260 key = get_account_keyname (name,
261 MODEST_ACCOUNT_STORE_ACCOUNT);
262 modest_conf_set_string (priv->modest_conf, key, store_account,
267 if (transport_account) {
268 key = get_account_keyname (name,
269 MODEST_ACCOUNT_TRANSPORT_ACCOUNT);
270 modest_conf_set_string (priv->modest_conf, key,
271 transport_account, err);
275 return TRUE; /* TODO: error handling */
280 modest_account_mgr_remove_account (ModestAccountMgr * self,
281 const gchar * name, GError ** err)
283 ModestAccountMgrPrivate *priv;
287 g_return_val_if_fail (self, FALSE);
288 g_return_val_if_fail (name, FALSE);
290 if (!modest_account_mgr_account_exists (self, name, err)) {
291 g_warning ("account doest not exist");
295 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
296 key = get_account_keyname (name, NULL);
298 retval = modest_conf_remove_key (priv->modest_conf, key, NULL);
306 null_means_empty (const gchar * str)
308 return str ? str : "";
313 modest_account_mgr_add_server_account (ModestAccountMgr * self,
315 const gchar * hostname,
316 const gchar * username,
317 const gchar * password,
320 ModestAccountMgrPrivate *priv;
323 g_return_val_if_fail (self, FALSE);
324 g_return_val_if_fail (name, FALSE);
326 /* TODO: check already exists */
328 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
329 acckey = g_strconcat (MODEST_SERVER_ACCOUNT_NAMESPACE, "/",
332 if (modest_conf_key_exists (priv->modest_conf, acckey, NULL)) {
333 g_warning ("server account %s already exists", name);
339 key = g_strconcat (acckey, "/", MODEST_ACCOUNT_HOSTNAME, NULL);
340 modest_conf_set_string (priv->modest_conf, key,
341 null_means_empty (hostname), NULL);
345 key = g_strconcat (acckey, "/", MODEST_ACCOUNT_USERNAME, NULL);
346 modest_conf_set_string (priv->modest_conf, key,
347 null_means_empty (username), NULL);
352 key = g_strconcat (acckey, "/", MODEST_ACCOUNT_PASSWORD,
354 modest_conf_set_string (priv->modest_conf, key,
355 null_means_empty (password), NULL);
360 key = g_strconcat (acckey, "/", MODEST_ACCOUNT_PROTO, NULL);
361 modest_conf_set_string (priv->modest_conf, key,
362 null_means_empty (proto), NULL);
366 return TRUE; /* FIXME: better error checking */
370 modest_account_mgr_remove_server_account (ModestAccountMgr * self,
371 const gchar * name, GError ** err)
373 ModestAccountMgrPrivate *priv;
377 g_return_val_if_fail (self, FALSE);
378 g_return_val_if_fail (name, FALSE);
380 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
382 acckey = g_strconcat (MODEST_SERVER_ACCOUNT_NAMESPACE, "/",
385 if (!modest_conf_key_exists (priv->modest_conf, acckey, NULL)) {
386 g_warning ("server account %s does not exist exist", name);
391 retval = modest_conf_remove_key (priv->modest_conf, acckey, NULL);
398 /* strip the first /n/ character from each element */
399 /* caller must make sure all elements are strings with
400 * length >= n, and also that data can be freed.
403 strip_prefix_from_elements (GSList * lst, guint n)
405 GSList *cursor = lst;
408 gchar *str = (gchar *) cursor->data;
410 cursor->data = g_strdup (str + n);
412 cursor = cursor->next;
419 modest_account_mgr_server_account_names (ModestAccountMgr * self,
420 const gchar * account_name,
421 ModestProtoType type,
423 gboolean only_enabled)
427 ModestAccountMgrPrivate *priv;
428 const size_t prefix_len =
429 strlen (MODEST_SERVER_ACCOUNT_NAMESPACE "/");
431 g_return_val_if_fail (self, NULL);
433 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
434 accounts = modest_conf_list_subkeys (priv->modest_conf,
435 MODEST_SERVER_ACCOUNT_NAMESPACE,
438 /* no restrictions, return everything */
439 if (type == MODEST_PROTO_TYPE_ANY && !proto)
440 return strip_prefix_from_elements (accounts, prefix_len);
442 /* otherwise, filter out the none-matching ones */
445 gchar *keyspace, *proto_key, *acc_proto;
447 keyspace = (gchar *) cursor->data;
449 g_strconcat (keyspace, "/", MODEST_ACCOUNT_PROTO,
452 modest_conf_get_string (priv->modest_conf, proto_key,
456 if ((!acc_proto) || /* proto not defined? */
457 (type != MODEST_PROTO_TYPE_ANY && /* proto type ... */
458 modest_proto_type (acc_proto) != type) || /* ... matches? */
459 (proto && strcmp (proto, acc_proto) != 0)) { /* proto matches? */
460 /* no match: remove from the list */
461 GSList *nxt = cursor->next;
464 accounts = g_slist_delete_link (accounts, cursor);
467 cursor = cursor->next;
470 return strip_prefix_from_elements (accounts, prefix_len);
475 modest_account_mgr_account_names (ModestAccountMgr * self, GError ** err)
478 ModestAccountMgrPrivate *priv;
479 const size_t prefix_len = strlen (MODEST_ACCOUNT_NAMESPACE "/");
482 g_return_val_if_fail (self, NULL);
484 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
486 accounts = modest_conf_list_subkeys (priv->modest_conf,
487 MODEST_ACCOUNT_NAMESPACE, err);
488 return strip_prefix_from_elements (accounts, prefix_len);
493 get_account_string (ModestAccountMgr * self, const gchar * name,
494 const gchar * key, gboolean server_account, GError ** err)
496 ModestAccountMgrPrivate *priv;
501 g_return_val_if_fail (self, NULL);
502 g_return_val_if_fail (name, NULL);
503 g_return_val_if_fail (key, NULL);
506 keyname = get_server_account_keyname (name, key);
508 keyname = get_account_keyname (name, key);
510 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
511 retval = modest_conf_get_string (priv->modest_conf, keyname, err);
519 modest_account_mgr_get_server_account_string (ModestAccountMgr * self,
524 return get_account_string (self, name, key, TRUE, err);
529 modest_account_mgr_get_account_string (ModestAccountMgr * self,
530 const gchar * name, const gchar * key,
533 return get_account_string (self, name, key, FALSE, err);
538 get_account_int (ModestAccountMgr * self, const gchar * name,
539 const gchar * key, gboolean server_account, GError ** err)
541 ModestAccountMgrPrivate *priv;
546 g_return_val_if_fail (self, -1);
547 g_return_val_if_fail (name, -1);
548 g_return_val_if_fail (key, -1);
551 keyname = get_server_account_keyname (name, key);
553 keyname = get_account_keyname (name, key);
555 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
556 retval = modest_conf_get_int (priv->modest_conf, keyname, err);
564 modest_account_mgr_get_server_account_int (ModestAccountMgr * self,
566 const gchar * key, GError ** err)
568 return get_account_int (self, name, key, TRUE, err);
573 modest_account_mgr_get_account_int (ModestAccountMgr * self,
574 const gchar * name, const gchar * key,
577 return get_account_int (self, name, key, FALSE, err);
582 get_account_bool (ModestAccountMgr * self, const gchar * name,
583 const gchar * key, gboolean server_account, GError ** err)
585 ModestAccountMgrPrivate *priv;
590 g_return_val_if_fail (self, FALSE);
591 g_return_val_if_fail (name, FALSE);
592 g_return_val_if_fail (key, FALSE);
595 keyname = get_server_account_keyname (name, key);
597 keyname = get_account_keyname (name, key);
599 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
600 retval = modest_conf_get_bool (priv->modest_conf, keyname, err);
608 modest_account_mgr_get_server_account_bool (ModestAccountMgr * self,
610 const gchar * key, GError ** err)
612 return get_account_bool (self, name, key, TRUE, err);
617 modest_account_mgr_get_account_bool (ModestAccountMgr * self,
618 const gchar * name, const gchar * key,
621 return get_account_bool (self, name, key, FALSE, err);
626 set_account_string (ModestAccountMgr * self, const gchar * name,
627 const gchar * key, const gchar * val,
628 gboolean server_account, GError ** err)
630 ModestAccountMgrPrivate *priv;
635 g_return_val_if_fail (self, FALSE);
636 g_return_val_if_fail (name, FALSE);
637 g_return_val_if_fail (key, FALSE);
640 keyname = get_server_account_keyname (name, key);
642 keyname = get_account_keyname (name, key);
644 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
646 retval = modest_conf_set_string (priv->modest_conf, keyname, val,
655 modest_account_mgr_set_server_account_string (ModestAccountMgr * self,
661 return set_account_string (self, name, key, val, TRUE, err);
666 modest_account_mgr_set_account_string (ModestAccountMgr * self,
667 const gchar * name, const gchar * key,
668 const gchar * val, GError ** err)
670 return set_account_string (self, name, key, val, FALSE, err);
675 set_account_int (ModestAccountMgr * self, const gchar * name,
676 const gchar * key, gboolean server_account, int val,
679 ModestAccountMgrPrivate *priv;
684 g_return_val_if_fail (self, FALSE);
685 g_return_val_if_fail (name, FALSE);
686 g_return_val_if_fail (key, FALSE);
689 keyname = get_server_account_keyname (name, key);
691 keyname = get_account_keyname (name, key);
693 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
695 retval = modest_conf_set_int (priv->modest_conf, keyname, val, err);
703 modest_account_mgr_set_server_account_int (ModestAccountMgr * self,
705 const gchar * key, int val,
708 return set_account_int (self, name, key, val, TRUE, err);
713 modest_account_mgr_set_account_int (ModestAccountMgr * self,
714 const gchar * name, const gchar * key,
715 int val, GError ** err)
717 return set_account_int (self, name, key, val, FALSE, err);
722 set_account_bool (ModestAccountMgr * self, const gchar * name,
723 const gchar * key, gboolean server_account, gboolean val,
726 ModestAccountMgrPrivate *priv;
731 g_return_val_if_fail (self, FALSE);
732 g_return_val_if_fail (name, FALSE);
733 g_return_val_if_fail (key, FALSE);
736 keyname = get_server_account_keyname (name, key);
738 keyname = get_account_keyname (name, key);
740 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
742 retval = modest_conf_set_bool (priv->modest_conf, keyname, val, err);
750 modest_account_mgr_set_server_account_bool (ModestAccountMgr * self,
752 const gchar * key, gboolean val,
755 return set_account_bool (self, name, key, val, TRUE, err);
760 modest_account_mgr_set_account_bool (ModestAccountMgr * self,
761 const gchar * name, const gchar * key,
762 gboolean val, GError ** err)
764 return set_account_bool (self, name, key, val, FALSE, err);
769 account_exists (ModestAccountMgr * self, const gchar * name,
770 gboolean server_account, GError ** err)
772 ModestAccountMgrPrivate *priv;
777 g_return_val_if_fail (self, FALSE);
778 g_return_val_if_fail (name, FALSE);
781 keyname = get_server_account_keyname (name, NULL);
783 keyname = get_account_keyname (name, NULL);
785 priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
786 retval = modest_conf_key_exists (priv->modest_conf, keyname, err);
794 modest_account_mgr_server_account_exists (ModestAccountMgr * self,
795 const gchar * name, GError ** err)
797 return account_exists (self, name, TRUE, err);
802 modest_account_mgr_account_exists (ModestAccountMgr * self,
803 const gchar * name, GError ** err)
805 return account_exists (self, name, FALSE, err);
809 /* must be freed by caller */
811 get_account_keyname (const gchar * accname, const gchar * name)
815 (MODEST_ACCOUNT_NAMESPACE, "/",
816 accname, "/", name, NULL);
819 (MODEST_ACCOUNT_NAMESPACE, "/", accname, NULL);
823 /* must be freed by caller */
825 get_server_account_keyname (const gchar * accname, const gchar * name)
829 (MODEST_SERVER_ACCOUNT_NAMESPACE, "/",
830 accname, "/", name, NULL);
833 (MODEST_SERVER_ACCOUNT_NAMESPACE, "/", accname, NULL);