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>
43 #include "modest-account-mgr.h"
44 #include "modest-tny-account-store.h"
46 /* 'private'/'protected' functions */
47 static void modest_tny_account_store_class_init (ModestTnyAccountStoreClass *klass);
48 static void modest_tny_account_store_init (ModestTnyAccountStore *obj);
49 static void modest_tny_account_store_finalize (GObject *obj);
51 /* implementations for tny-account-store-iface */
52 static void modest_tny_account_store_iface_init (gpointer g_iface, gpointer iface_data);
53 static void modest_tny_account_store_add_store_account (TnyAccountStoreIface *self,
54 TnyStoreAccountIface *account);
55 static void modest_tny_account_store_add_transport_account (TnyAccountStoreIface *self,
56 TnyTransportAccountIface *account);
57 static void modest_tny_account_store_get_accounts (TnyAccountStoreIface *iface, TnyListIface *list,
58 TnyGetAccountsRequestType type);
61 PASSWORD_REQUESTED_SIGNAL,
62 UPDATE_ACCOUNTS_SIGNAL,
72 typedef struct _ModestTnyAccountStorePrivate ModestTnyAccountStorePrivate;
73 struct _ModestTnyAccountStorePrivate {
78 TnySessionCamel *tny_session_camel;
79 TnyDeviceIface *device;
81 ModestAccountMgr *account_mgr;
83 ModestTnyGetPassFunc get_pass_func;
85 #define MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
86 MODEST_TYPE_TNY_ACCOUNT_STORE, \
87 ModestTnyAccountStorePrivate))
89 static GObjectClass *parent_class = NULL;
91 static guint signals[LAST_SIGNAL] = {0};
94 modest_tny_account_store_get_type (void)
96 static GType my_type = 0;
98 static const GTypeInfo my_info = {
99 sizeof(ModestTnyAccountStoreClass),
100 NULL, /* base init */
101 NULL, /* base finalize */
102 (GClassInitFunc) modest_tny_account_store_class_init,
103 NULL, /* class finalize */
104 NULL, /* class data */
105 sizeof(ModestTnyAccountStore),
107 (GInstanceInitFunc) modest_tny_account_store_init,
110 static const GInterfaceInfo iface_info = {
111 (GInterfaceInitFunc) modest_tny_account_store_iface_init,
112 NULL, /* interface_finalize */
113 NULL /* interface_data */
116 my_type = g_type_register_static (TNY_TYPE_ACCOUNT_STORE,
117 "ModestTnyAccountStore", &my_info, 0);
119 g_type_add_interface_static (my_type, TNY_TYPE_ACCOUNT_STORE_IFACE,
126 modest_tny_account_store_class_init (ModestTnyAccountStoreClass *klass)
128 GObjectClass *gobject_class;
129 gobject_class = (GObjectClass*) klass;
131 parent_class = g_type_class_peek_parent (klass);
132 gobject_class->finalize = modest_tny_account_store_finalize;
134 g_type_class_add_private (gobject_class,
135 sizeof(ModestTnyAccountStorePrivate));
137 signals[PASSWORD_REQUESTED_SIGNAL] =
138 g_signal_new ("password_requested",
139 G_TYPE_FROM_CLASS (gobject_class),
141 G_STRUCT_OFFSET(ModestTnyAccountStoreClass, password_requested),
143 g_cclosure_marshal_VOID__STRING,
144 G_TYPE_NONE, 1, G_TYPE_STRING);
146 signals[UPDATE_ACCOUNTS_SIGNAL] =
147 g_signal_new ("update_accounts",
148 G_TYPE_FROM_CLASS (gobject_class),
150 G_STRUCT_OFFSET(ModestTnyAccountStoreClass, update_accounts),
152 g_cclosure_marshal_VOID__STRING,
153 G_TYPE_NONE, 1, G_TYPE_STRING);
158 modest_tny_account_store_init (ModestTnyAccountStore *obj)
160 ModestTnyAccountStorePrivate *priv =
161 MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(obj);
163 priv->account_mgr = NULL;
165 priv->cache_dir = NULL;
167 priv->tny_session_camel = NULL;
168 /* Meaning: if not indicated otherwise, we have valid password data */
169 priv->pw_invalid = PW_NOT_INVALID;
170 priv->get_pass_func = NULL;
175 on_account_removed (ModestAccountMgr *acc_mgr, const gchar *account, gboolean server_account,
178 ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(user_data);
180 g_signal_emit (G_OBJECT(self), signals[UPDATE_ACCOUNTS_SIGNAL], 0,
187 on_account_changed (ModestAccountMgr *acc_mgr, const gchar *account, gboolean server_account,
188 const gchar *key, gpointer user_data)
190 ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(user_data);
192 g_signal_emit (G_OBJECT(self), signals[UPDATE_ACCOUNTS_SIGNAL], 0,
199 get_password (TnyAccountIface *account, const gchar *prompt, gboolean *cancel)
203 const TnyAccountStoreIface *account_store;
204 ModestTnyAccountStore *self;
205 ModestTnyAccountStorePrivate *priv;
208 g_return_val_if_fail (account, NULL);
210 key = tny_account_iface_get_id (account);
211 account_store = tny_account_iface_get_account_store(account);
213 self = MODEST_TNY_ACCOUNT_STORE (account_store);
214 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
216 if (priv->pw_invalid==PW_NOT_INVALID) {
217 retval = modest_account_mgr_get_string (priv->account_mgr,
219 MODEST_ACCOUNT_PASSWORD,
223 retval = priv->get_pass_func(account, prompt, cancel);
225 priv->pw_invalid=PW_NOT_INVALID;
226 modest_account_mgr_set_string(priv->account_mgr,
228 MODEST_ACCOUNT_PASSWORD,
238 forget_password (TnyAccountIface *account) {
240 ModestTnyAccountStore *self;
241 ModestTnyAccountStorePrivate *priv;
242 const TnyAccountStoreIface *account_store;
244 account_store = tny_account_iface_get_account_store(account);
245 self = MODEST_TNY_ACCOUNT_STORE (account_store);
246 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
248 priv->pw_invalid=PW_INVALID;
252 /* create a tnyaccount for the server account connected to the account with name 'key'
254 static TnyAccountIface*
255 tny_account_from_name (ModestTnyAccountStore *self, const gchar *account,
256 const gchar *server_account, ModestProtoType modest_type)
258 TnyAccountIface *tny_account;
259 ModestTnyAccountStorePrivate *priv;
262 g_return_val_if_fail (self, NULL);
263 g_return_val_if_fail (account, NULL);
264 g_return_val_if_fail (server_account, NULL);
266 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
268 /* is it a store or a transport? */
269 if (modest_type == MODEST_PROTO_TYPE_STORE)
270 tny_account = TNY_ACCOUNT_IFACE(tny_store_account_new ());
271 else if (modest_type == MODEST_PROTO_TYPE_TRANSPORT)
272 tny_account = TNY_ACCOUNT_IFACE(tny_transport_account_new ());
274 g_assert_not_reached ();
277 g_printerr ("modest: failed to create new tny account for '%s:%s'\n",
278 account, server_account);
282 tny_account_iface_set_account_store (TNY_ACCOUNT_IFACE(tny_account),
283 TNY_ACCOUNT_STORE_IFACE(self));
285 tny_account_iface_set_id (tny_account, server_account);
286 tny_account_iface_set_name (tny_account, account);
289 val = modest_account_mgr_get_string (priv->account_mgr, server_account,
290 MODEST_ACCOUNT_PROTO, TRUE, NULL);
292 tny_account_iface_set_proto (tny_account, val);
295 g_printerr ("modest: protocol not defined for '%s:%s'\n",
296 account, server_account);
297 g_object_unref (G_OBJECT(tny_account));
302 val = modest_account_mgr_get_string (priv->account_mgr, server_account,
303 MODEST_ACCOUNT_HOSTNAME, TRUE,
306 tny_account_iface_set_hostname (tny_account, val);
311 val = modest_account_mgr_get_string (priv->account_mgr, server_account,
312 MODEST_ACCOUNT_USERNAME, TRUE,
315 tny_account_iface_set_user (tny_account, val);
319 tny_account_iface_set_pass_func (tny_account, get_password);
320 tny_account_iface_set_forget_pass_func (tny_account, forget_password);
328 modest_tny_account_store_finalize (GObject *obj)
330 ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(obj);
331 ModestTnyAccountStorePrivate *priv =
332 MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
334 if (priv->account_mgr) {
335 g_object_unref (G_OBJECT(priv->account_mgr));
336 priv->account_mgr = NULL;
340 if (priv->tny_session_camel) {
341 // FIXME: how to kill a camel
342 //g_object_unref (G_OBJECT(priv->tny_session_camel));
343 priv->tny_session_camel = NULL;
347 g_object_unref (G_OBJECT(priv->device));
351 if (priv->store_lock)
352 g_mutex_free (priv->store_lock);
354 g_free (priv->cache_dir);
355 priv->cache_dir = NULL;
359 ModestTnyAccountStore*
360 modest_tny_account_store_new (ModestAccountMgr *account_mgr) {
363 ModestTnyAccountStorePrivate *priv;
365 g_return_val_if_fail (account_mgr, NULL);
367 obj = G_OBJECT(g_object_new(MODEST_TYPE_TNY_ACCOUNT_STORE, NULL));
369 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(obj);
371 g_object_ref(G_OBJECT(account_mgr));
372 priv->account_mgr = account_mgr;
374 g_signal_connect (G_OBJECT(account_mgr), "account_changed",
375 G_CALLBACK (on_account_changed), obj);
376 g_signal_connect (G_OBJECT(account_mgr), "account_removed",
377 G_CALLBACK (on_account_removed), obj);
379 priv->store_lock = g_mutex_new ();
381 priv->device = (TnyDeviceIface*)tny_device_new();
383 g_printerr ("modest: cannot create device instance\n");
384 g_object_unref (obj);
388 priv->tny_session_camel = tny_session_camel_new (TNY_ACCOUNT_STORE_IFACE(obj));
390 if (!priv->tny_session_camel) {
391 g_printerr ("modest: cannot create TnySessionCamel instance\n");
392 g_object_unref (obj);
396 return MODEST_TNY_ACCOUNT_STORE(obj);
401 add_account (TnyAccountStoreIface *self, TnyAccountIface *account) {
403 TnyAccountIface *account_iface;
404 ModestTnyAccountStore *account_store;
405 ModestTnyAccountStorePrivate *priv;
407 const gchar *account_name;
408 const gchar *hostname, *username, *proto;
410 g_return_val_if_fail (self, FALSE);
411 g_return_val_if_fail (account, FALSE);
413 account_iface = TNY_ACCOUNT_IFACE(account);
414 account_store = MODEST_TNY_ACCOUNT_STORE(self);
415 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
417 account_name = tny_account_iface_get_id(account_iface);
419 g_printerr ("modest: failed to retrieve account name\n");
423 hostname = tny_account_iface_get_hostname(account_iface);
424 username = tny_account_iface_get_user(account_iface);
425 proto = tny_account_iface_get_proto(account_iface);
427 return modest_account_mgr_add_server_account (priv->account_mgr,
429 hostname, username, NULL,
435 modest_tny_account_store_add_store_account (TnyAccountStoreIface *self,
436 TnyStoreAccountIface *account)
438 if (!add_account (self, TNY_ACCOUNT_IFACE(account)))
439 g_printerr ("modest: failed to add store account\n");
444 modest_tny_account_store_add_transport_account (TnyAccountStoreIface *self,
445 TnyTransportAccountIface *account)
447 if (!add_account (self, TNY_ACCOUNT_IFACE(account)))
448 g_printerr ("modest: failed to add transport account\n");
453 get_server_account_for_account (ModestTnyAccountStore *self, const gchar *account_name,
454 ModestProtoType modest_type)
456 ModestTnyAccountStorePrivate *priv;
460 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
462 if (modest_type == MODEST_PROTO_TYPE_STORE)
463 key = MODEST_ACCOUNT_STORE_ACCOUNT;
464 else if (modest_type == MODEST_PROTO_TYPE_STORE)
465 key = MODEST_ACCOUNT_TRANSPORT_ACCOUNT;
467 g_assert_not_reached();
469 server = modest_account_mgr_get_string (priv->account_mgr,
474 if (!modest_account_mgr_account_exists (priv->account_mgr,
475 server, TRUE, NULL)) {
486 modest_tny_account_store_get_accounts (TnyAccountStoreIface *iface,
488 TnyGetAccountsRequestType type)
490 ModestTnyAccountStore *self;
491 ModestTnyAccountStorePrivate *priv;
492 GSList *accounts, *cursor;
493 ModestProtoType modest_type;
495 g_return_if_fail (iface);
497 self = MODEST_TNY_ACCOUNT_STORE(iface);
498 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
501 case TNY_ACCOUNT_STORE_IFACE_TRANSPORT_ACCOUNTS:
502 modest_type = MODEST_PROTO_TYPE_TRANSPORT;
504 case TNY_ACCOUNT_STORE_IFACE_STORE_ACCOUNTS:
505 modest_type = MODEST_PROTO_TYPE_STORE;
507 case TNY_ACCOUNT_STORE_IFACE_BOTH:
508 modest_type = MODEST_PROTO_TYPE_ANY;
511 g_assert_not_reached ();
514 cursor = accounts = modest_account_mgr_account_names (priv->account_mgr, NULL);
517 gchar *server_account;
518 TnyAccountIface *account_iface;
520 account_name = (gchar*)cursor->data;
522 if (modest_type == MODEST_PROTO_TYPE_TRANSPORT || MODEST_PROTO_TYPE_ANY) {
523 server_account = get_server_account_for_account (self, account_name,
524 MODEST_PROTO_TYPE_TRANSPORT);
526 account_iface = tny_account_from_name (self, account_name,
528 MODEST_PROTO_TYPE_TRANSPORT);
530 g_printerr ("modest: failed to create account iface for '%s:%s'\n",
531 account_name, server_account);
533 tny_list_iface_prepend (list, account_iface);
534 g_free (server_account);
537 if (modest_type == MODEST_PROTO_TYPE_STORE || MODEST_PROTO_TYPE_ANY) {
538 server_account = get_server_account_for_account (self, account_name,
539 MODEST_PROTO_TYPE_STORE);
541 account_iface = tny_account_from_name (self, account_name,
543 MODEST_PROTO_TYPE_STORE);
545 g_printerr ("modest: failed to create account iface for '%s:%s'\n",
546 account_name, server_account);
548 tny_list_iface_prepend (list, account_iface);
549 g_free (server_account);
552 g_free (account_name);
553 cursor = cursor->next;
556 g_slist_free (accounts);
558 tny_session_camel_set_current_accounts (priv->tny_session_camel,
564 modest_tny_account_store_get_cache_dir (TnyAccountStoreIface *self)
566 ModestTnyAccountStorePrivate *priv;
567 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
569 if (!priv->cache_dir)
570 priv->cache_dir = g_build_filename (g_get_home_dir(),
571 ".modest", "cache", NULL);
572 return priv->cache_dir;
576 static const TnyDeviceIface*
577 modest_tny_account_store_get_device (TnyAccountStoreIface *self)
579 ModestTnyAccountStorePrivate *priv;
581 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE (self);
588 modest_tny_account_store_alert (TnyAccountStoreIface *self, TnyAlertType type,
591 return TRUE; /* FIXME: implement this */
596 modest_tny_account_store_iface_init (gpointer g_iface, gpointer iface_data)
598 TnyAccountStoreIfaceClass *klass;
600 g_return_if_fail (g_iface);
602 klass = (TnyAccountStoreIfaceClass *)g_iface;
604 klass->get_accounts_func =
605 modest_tny_account_store_get_accounts;
606 klass->add_transport_account_func =
607 modest_tny_account_store_add_transport_account;
608 klass->add_store_account_func =
609 modest_tny_account_store_add_store_account;
610 klass->get_cache_dir_func =
611 modest_tny_account_store_get_cache_dir;
612 klass->get_device_func =
613 modest_tny_account_store_get_device;
615 modest_tny_account_store_alert;
619 modest_tny_account_store_set_get_pass_func (ModestTnyAccountStore *self,
620 ModestTnyGetPassFunc func)
622 return; /* not implemented, we use signals */
627 tny_account_store_get_session (TnyAccountStore *self)
629 ModestTnyAccountStorePrivate *priv;
631 priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
633 return priv->tny_session_camel;