1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <tny-account-iface.h>
33 #include <tny-account-store-iface.h>
34 #include <tny-store-account-iface.h>
35 #include <tny-transport-account-iface.h>
36 #include <tny-device-iface.h>
37 #include <tny-device.h>
38 #include <tny-account-store.h>
40 #include <tny-store-account.h>
41 #include <tny-transport-account.h>
42 #include <modest-marshal.h>
44 #include "modest-account-mgr.h"
45 #include "modest-tny-account-store.h"
47 /* 'private'/'protected' functions */
48 static void modest_tny_account_store_class_init (ModestTnyAccountStoreClass *klass);
49 static void modest_tny_account_store_init (ModestTnyAccountStore *obj);
50 static void modest_tny_account_store_finalize (GObject *obj);
52 /* implementations for tny-account-store-iface */
53 static void modest_tny_account_store_iface_init (gpointer g_iface, gpointer iface_data);
54 static void modest_tny_account_store_add_store_account (TnyAccountStoreIface *self,
55 TnyStoreAccountIface *account);
56 static void modest_tny_account_store_add_transport_account (TnyAccountStoreIface *self,
57 TnyTransportAccountIface *account);
58 static void modest_tny_account_store_get_accounts (TnyAccountStoreIface *iface, TnyListIface *list,
59 TnyGetAccountsRequestType type);
62 PASSWORD_REQUESTED_SIGNAL,
63 ACCOUNT_UPDATE_SIGNAL,
67 typedef struct _ModestTnyAccountStorePrivate ModestTnyAccountStorePrivate;
68 struct _ModestTnyAccountStorePrivate {
74 TnySessionCamel *tny_session_camel;
75 TnyDeviceIface *device;
77 ModestAccountMgr *account_mgr;
80 #define MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
81 MODEST_TYPE_TNY_ACCOUNT_STORE, \
82 ModestTnyAccountStorePrivate))
84 static GObjectClass *parent_class = NULL;
86 static guint signals[LAST_SIGNAL] = {0};
89 modest_tny_account_store_get_type (void)
91 static GType my_type = 0;
93 static const GTypeInfo my_info = {
94 sizeof(ModestTnyAccountStoreClass),
96 NULL, /* base finalize */
97 (GClassInitFunc) modest_tny_account_store_class_init,
98 NULL, /* class finalize */
99 NULL, /* class data */
100 sizeof(ModestTnyAccountStore),
102 (GInstanceInitFunc) modest_tny_account_store_init,
106 static const GInterfaceInfo iface_info = {
107 (GInterfaceInitFunc) modest_tny_account_store_iface_init,
108 NULL, /* interface_finalize */
109 NULL /* interface_data */
112 my_type = g_type_register_static (TNY_TYPE_ACCOUNT_STORE,
113 "ModestTnyAccountStore", &my_info, 0);
115 g_type_add_interface_static (my_type, TNY_TYPE_ACCOUNT_STORE_IFACE,
122 modest_tny_account_store_class_init (ModestTnyAccountStoreClass *klass)
124 GObjectClass *gobject_class;
125 gobject_class = (GObjectClass*) klass;
127 parent_class = g_type_class_peek_parent (klass);
128 gobject_class->finalize = modest_tny_account_store_finalize;
130 g_type_class_add_private (gobject_class,
131 sizeof(ModestTnyAccountStorePrivate));
133 signals[PASSWORD_REQUESTED_SIGNAL] =
134 g_signal_new ("password_requested",
135 G_TYPE_FROM_CLASS (gobject_class),
137 G_STRUCT_OFFSET(ModestTnyAccountStoreClass, password_requested),
139 modest_marshal_VOID__STRING_POINTER_POINTER,
140 G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER);
142 signals[ACCOUNT_UPDATE_SIGNAL] =
143 g_signal_new ("account_update",
144 G_TYPE_FROM_CLASS (gobject_class),
146 G_STRUCT_OFFSET(ModestTnyAccountStoreClass, account_update),
148 g_cclosure_marshal_VOID__STRING,
149 G_TYPE_NONE, 1, G_TYPE_STRING);
154 modest_tny_account_store_init (ModestTnyAccountStore *obj)
156 ModestTnyAccountStorePrivate *priv =
157 MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(obj);
159 priv->account_mgr = NULL;
161 priv->cache_dir = NULL;
162 priv->tny_session_camel = NULL;
167 on_account_removed (ModestAccountMgr *acc_mgr, const gchar *account, gboolean server_account,
170 ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(user_data);
172 g_signal_emit (G_OBJECT(self), signals[ACCOUNT_UPDATE_SIGNAL], 0,
179 on_account_changed (ModestAccountMgr *acc_mgr, const gchar *account, gboolean server_account,
180 const gchar *key, gpointer user_data)
182 ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(user_data);
184 g_signal_emit (G_OBJECT(self), signals[ACCOUNT_UPDATE_SIGNAL], 0,
191 get_password (TnyAccountIface *account, const gchar *prompt, gboolean *cancel)
194 const TnyAccountStoreIface *account_store;
195 ModestTnyAccountStore *self;
196 ModestTnyAccountStorePrivate *priv;
198 gboolean remember_pwd;
200 g_return_val_if_fail (account, NULL);
202 key = tny_account_iface_get_id (account);
203 account_store = tny_account_iface_get_account_store(account);
205 self = MODEST_TNY_ACCOUNT_STORE (account_store);
206 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
208 /* is it in the conf? */
209 pwd = modest_account_mgr_get_string (priv->account_mgr,
210 key, MODEST_ACCOUNT_PASSWORD,
212 if (!pwd || strlen(pwd) == 0) {
213 /* we don't have it yet. we emit a signal to get the password somewhere */
214 const gchar* name = tny_account_iface_get_name (account);
217 g_signal_emit (G_OBJECT(self), signals[PASSWORD_REQUESTED_SIGNAL], 0,
219 if (!*cancel) /* remember the password */
220 modest_account_mgr_set_string (priv->account_mgr,
221 key, MODEST_ACCOUNT_PASSWORD,
231 forget_password (TnyAccountIface *account) {
233 ModestTnyAccountStore *self;
234 ModestTnyAccountStorePrivate *priv;
235 const TnyAccountStoreIface *account_store;
237 account_store = tny_account_iface_get_account_store(account);
238 self = MODEST_TNY_ACCOUNT_STORE (account_store);
239 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
243 /* create a tnyaccount for the server account connected to the account with name 'key'
245 static TnyAccountIface*
246 tny_account_from_name (ModestTnyAccountStore *self, const gchar *account,
247 const gchar *server_account, ModestProtoType modest_type)
249 TnyAccountIface *tny_account;
250 ModestTnyAccountStorePrivate *priv;
253 g_return_val_if_fail (self, NULL);
254 g_return_val_if_fail (account, NULL);
255 g_return_val_if_fail (server_account, NULL);
257 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
259 /* is it a store or a transport? */
260 if (modest_type == MODEST_PROTO_TYPE_STORE)
261 tny_account = TNY_ACCOUNT_IFACE(tny_store_account_new ());
262 else if (modest_type == MODEST_PROTO_TYPE_TRANSPORT)
263 tny_account = TNY_ACCOUNT_IFACE(tny_transport_account_new ());
265 g_assert_not_reached ();
268 g_printerr ("modest: failed to create new tny account for '%s:%s'\n",
269 account, server_account);
273 tny_account_iface_set_account_store (TNY_ACCOUNT_IFACE(tny_account),
274 TNY_ACCOUNT_STORE_IFACE(self));
276 tny_account_iface_set_id (tny_account, server_account);
277 tny_account_iface_set_name (tny_account, account);
280 val = modest_account_mgr_get_string (priv->account_mgr, server_account,
281 MODEST_ACCOUNT_PROTO, TRUE, NULL);
283 tny_account_iface_set_proto (tny_account, val);
286 g_printerr ("modest: protocol not defined for '%s:%s'\n",
287 account, server_account);
288 g_object_unref (G_OBJECT(tny_account));
293 val = modest_account_mgr_get_string (priv->account_mgr, server_account,
294 MODEST_ACCOUNT_HOSTNAME, TRUE,
297 tny_account_iface_set_hostname (tny_account, val);
302 val = modest_account_mgr_get_string (priv->account_mgr, server_account,
303 MODEST_ACCOUNT_USERNAME, TRUE,
306 tny_account_iface_set_user (tny_account, val);
310 tny_account_iface_set_pass_func (tny_account, get_password);
311 tny_account_iface_set_forget_pass_func (tny_account, forget_password);
319 modest_tny_account_store_finalize (GObject *obj)
321 ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(obj);
322 ModestTnyAccountStorePrivate *priv =
323 MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
327 if (priv->account_mgr) {
328 g_signal_handler_disconnect (G_OBJECT(priv->account_mgr),
330 g_signal_handler_disconnect (G_OBJECT(priv->account_mgr),
332 g_object_unref (G_OBJECT(priv->account_mgr));
333 priv->account_mgr = NULL;
336 if (priv->tny_session_camel) {
337 // FIXME: how to kill a camel
338 priv->tny_session_camel = NULL;
342 g_object_unref (G_OBJECT(priv->device));
346 if (priv->store_lock)
347 g_mutex_free (priv->store_lock);
349 g_free (priv->cache_dir);
350 priv->cache_dir = NULL;
352 G_OBJECT_CLASS(parent_class)->finalize (obj);
356 ModestTnyAccountStore*
357 modest_tny_account_store_new (ModestAccountMgr *account_mgr) {
360 ModestTnyAccountStorePrivate *priv;
362 g_return_val_if_fail (account_mgr, NULL);
364 obj = G_OBJECT(g_object_new(MODEST_TYPE_TNY_ACCOUNT_STORE, NULL));
366 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(obj);
368 g_object_ref(G_OBJECT(account_mgr));
369 priv->account_mgr = account_mgr;
371 priv->sig1 = g_signal_connect (G_OBJECT(account_mgr), "account_changed",
372 G_CALLBACK (on_account_changed), obj);
373 priv->sig2 = g_signal_connect (G_OBJECT(account_mgr), "account_removed",
374 G_CALLBACK (on_account_removed), obj);
376 priv->store_lock = g_mutex_new ();
378 priv->device = (TnyDeviceIface*)tny_device_new();
380 g_printerr ("modest: cannot create device instance\n");
381 g_object_unref (obj);
385 priv->tny_session_camel = tny_session_camel_new (TNY_ACCOUNT_STORE_IFACE(obj));
387 if (!priv->tny_session_camel) {
388 g_printerr ("modest: cannot create TnySessionCamel instance\n");
389 g_object_unref (obj);
393 return MODEST_TNY_ACCOUNT_STORE(obj);
398 add_account (TnyAccountStoreIface *self, TnyAccountIface *account) {
400 TnyAccountIface *account_iface;
401 ModestTnyAccountStore *account_store;
402 ModestTnyAccountStorePrivate *priv;
404 const gchar *account_name;
405 const gchar *hostname, *username, *proto;
407 g_return_val_if_fail (self, FALSE);
408 g_return_val_if_fail (account, FALSE);
410 account_iface = TNY_ACCOUNT_IFACE(account);
411 account_store = MODEST_TNY_ACCOUNT_STORE(self);
412 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
414 account_name = tny_account_iface_get_id(account_iface);
416 g_printerr ("modest: failed to retrieve account name\n");
420 hostname = tny_account_iface_get_hostname(account_iface);
421 username = tny_account_iface_get_user(account_iface);
422 proto = tny_account_iface_get_proto(account_iface);
424 return modest_account_mgr_add_server_account (priv->account_mgr,
426 hostname, username, NULL,
432 modest_tny_account_store_add_store_account (TnyAccountStoreIface *self,
433 TnyStoreAccountIface *account)
435 if (!add_account (self, TNY_ACCOUNT_IFACE(account)))
436 g_printerr ("modest: failed to add store account\n");
441 modest_tny_account_store_add_transport_account (TnyAccountStoreIface *self,
442 TnyTransportAccountIface *account)
444 if (!add_account (self, TNY_ACCOUNT_IFACE(account)))
445 g_printerr ("modest: failed to add transport account\n");
450 get_server_account_for_account (ModestTnyAccountStore *self, const gchar *account_name,
451 ModestProtoType modest_type)
453 ModestTnyAccountStorePrivate *priv;
457 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
459 if (modest_type == MODEST_PROTO_TYPE_STORE)
460 key = MODEST_ACCOUNT_STORE_ACCOUNT;
461 else if (modest_type == MODEST_PROTO_TYPE_STORE)
462 key = MODEST_ACCOUNT_TRANSPORT_ACCOUNT;
464 g_assert_not_reached();
466 server = modest_account_mgr_get_string (priv->account_mgr,
471 if (!modest_account_mgr_account_exists (priv->account_mgr,
472 server, TRUE, NULL)) {
483 modest_tny_account_store_get_accounts (TnyAccountStoreIface *iface,
485 TnyGetAccountsRequestType type)
487 ModestTnyAccountStore *self;
488 ModestTnyAccountStorePrivate *priv;
489 GSList *accounts, *cursor;
490 ModestProtoType modest_type;
492 g_return_if_fail (iface);
494 self = MODEST_TNY_ACCOUNT_STORE(iface);
495 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
498 case TNY_ACCOUNT_STORE_IFACE_TRANSPORT_ACCOUNTS:
499 modest_type = MODEST_PROTO_TYPE_TRANSPORT;
501 case TNY_ACCOUNT_STORE_IFACE_STORE_ACCOUNTS:
502 modest_type = MODEST_PROTO_TYPE_STORE;
504 case TNY_ACCOUNT_STORE_IFACE_BOTH:
505 modest_type = MODEST_PROTO_TYPE_ANY;
508 g_assert_not_reached ();
511 cursor = accounts = modest_account_mgr_account_names (priv->account_mgr, NULL);
514 gchar *server_account;
515 TnyAccountIface *account_iface;
517 account_name = (gchar*)cursor->data;
519 if (!modest_account_mgr_account_get_enabled (priv->account_mgr, account_name)) {
520 g_free (account_name);
521 cursor = cursor->next;
525 if (modest_type == MODEST_PROTO_TYPE_TRANSPORT || MODEST_PROTO_TYPE_ANY) {
526 server_account = get_server_account_for_account (self, account_name,
527 MODEST_PROTO_TYPE_TRANSPORT);
529 account_iface = tny_account_from_name (self, account_name,
531 MODEST_PROTO_TYPE_TRANSPORT);
533 g_printerr ("modest: failed to create account iface for '%s:%s'\n",
534 account_name, server_account);
536 tny_list_iface_prepend (list, G_OBJECT(account_iface));
537 g_free (server_account);
540 if (modest_type == MODEST_PROTO_TYPE_STORE || MODEST_PROTO_TYPE_ANY) {
541 server_account = get_server_account_for_account (self, account_name,
542 MODEST_PROTO_TYPE_STORE);
544 account_iface = tny_account_from_name (self, account_name,
546 MODEST_PROTO_TYPE_STORE);
548 g_printerr ("modest: failed to create account iface for '%s:%s'\n",
549 account_name, server_account);
551 tny_list_iface_prepend (list, G_OBJECT(account_iface));
552 g_free (server_account);
555 g_free (account_name);
556 cursor = cursor->next;
559 g_slist_free (accounts);
561 tny_session_camel_set_current_accounts (priv->tny_session_camel,
567 modest_tny_account_store_get_cache_dir (TnyAccountStoreIface *self)
569 ModestTnyAccountStorePrivate *priv;
570 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
572 if (!priv->cache_dir)
573 priv->cache_dir = g_build_filename (g_get_home_dir(),
574 ".modest", "cache", NULL);
575 return priv->cache_dir;
579 static TnyDeviceIface*
580 modest_tny_account_store_get_device (TnyAccountStoreIface *self)
582 ModestTnyAccountStorePrivate *priv;
584 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE (self);
591 modest_tny_account_store_alert (TnyAccountStoreIface *self, TnyAlertType type,
594 g_printerr ("modest: alert [%d]: %s", type, prompt);
595 return TRUE; /* FIXME: implement this */
600 modest_tny_account_store_iface_init (gpointer g_iface, gpointer iface_data)
602 TnyAccountStoreIfaceClass *klass;
604 g_return_if_fail (g_iface);
606 klass = (TnyAccountStoreIfaceClass *)g_iface;
608 klass->get_accounts_func =
609 modest_tny_account_store_get_accounts;
610 klass->add_transport_account_func =
611 modest_tny_account_store_add_transport_account;
612 klass->add_store_account_func =
613 modest_tny_account_store_add_store_account;
614 klass->get_cache_dir_func =
615 modest_tny_account_store_get_cache_dir;
616 klass->get_device_func =
617 modest_tny_account_store_get_device;
619 modest_tny_account_store_alert;
623 modest_tny_account_store_set_get_pass_func (ModestTnyAccountStore *self,
624 ModestTnyGetPassFunc func)
626 g_warning (__FUNCTION__);
627 return; /* not implemented, we use signals */
632 tny_account_store_get_session (TnyAccountStore *self)
634 g_return_val_if_fail (self, NULL);
636 return MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self)->tny_session_camel;