* modest-tny-account-store.c:
[modest] / src / modest-tny-account-store.c
1 /* modest-tny-account-store.c */
2
3 /* insert (c)/licensing information) */
4
5 #include <string.h>
6
7 #include <tny-account-iface.h>
8 #include <tny-account-store-iface.h>
9 #include <tny-store-account-iface.h>
10 #include <tny-transport-account-iface.h>
11 //#include <tny-device-iface.h>
12
13 #include <tny-store-account.h>
14 #include <tny-transport-account.h>
15
16 #include "modest-account-mgr.h"
17 #include "modest-tny-account-store.h"
18
19 /* 'private'/'protected' functions */
20 static void modest_tny_account_store_class_init   (ModestTnyAccountStoreClass *klass);
21 static void modest_tny_account_store_init         (ModestTnyAccountStore *obj);
22 static void modest_tny_account_store_finalize     (GObject *obj);
23
24 /* implementations for tny-account-store-iface */
25 static void    modest_tny_account_store_iface_init              (gpointer g_iface, gpointer iface_data);
26
27 static void    modest_tny_account_store_add_store_account       (TnyAccountStoreIface *self,
28                                                                TnyStoreAccountIface *account);
29 static void    modest_tny_account_store_add_transport_account   (TnyAccountStoreIface *self,
30                                                                        TnyTransportAccountIface *account);
31 static const GList*  modest_tny_account_store_get_store_accounts      (TnyAccountStoreIface *iface);
32 static const GList*  modest_tny_account_store_get_transport_accounts  (TnyAccountStoreIface *iface);
33
34 /* list my signals */
35 enum {
36         /* MY_SIGNAL_1, */
37         /* MY_SIGNAL_2, */
38         LAST_SIGNAL
39 };
40
41 typedef struct _ModestTnyAccountStorePrivate ModestTnyAccountStorePrivate;
42 struct _ModestTnyAccountStorePrivate {
43
44         GList *store_accounts;
45         GList *transport_accounts;
46         gchar *cache_dir;
47
48         ModestAccountMgr *modest_acc_mgr;       
49 };
50 #define MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
51                                                       MODEST_TYPE_TNY_ACCOUNT_STORE, \
52                                                       ModestTnyAccountStorePrivate))
53 /* globals */
54 static GObjectClass *parent_class = NULL;
55
56 /* uncomment the following if you have defined any signals */
57 /* static guint signals[LAST_SIGNAL] = {0}; */
58
59 GType
60 modest_tny_account_store_get_type (void)
61 {
62         static GType my_type = 0;
63         if (!my_type) {
64                 static const GTypeInfo my_info = {
65                         sizeof(ModestTnyAccountStoreClass),
66                         NULL,           /* base init */
67                         NULL,           /* base finalize */
68                         (GClassInitFunc) modest_tny_account_store_class_init,
69                         NULL,           /* class finalize */
70                         NULL,           /* class data */
71                         sizeof(ModestTnyAccountStore),
72                         1,              /* n_preallocs */
73                         (GInstanceInitFunc) modest_tny_account_store_init,
74                 };
75
76                 static const GInterfaceInfo iface_info = {
77                         (GInterfaceInitFunc) modest_tny_account_store_iface_init,
78                         NULL,         /* interface_finalize */
79                         NULL          /* interface_data */
80                 };
81
82                 my_type = g_type_register_static (G_TYPE_OBJECT,
83                                                   "ModestTnyAccountStore", &my_info, 0);
84
85                 g_type_add_interface_static (my_type, TNY_TYPE_ACCOUNT_STORE_IFACE,
86                                              &iface_info);
87         }
88         return my_type;
89 }
90
91 static void
92 modest_tny_account_store_class_init (ModestTnyAccountStoreClass *klass)
93 {
94         GObjectClass *gobject_class;
95         gobject_class = (GObjectClass*) klass;
96
97         parent_class            = g_type_class_peek_parent (klass);
98         gobject_class->finalize = modest_tny_account_store_finalize;
99
100         g_type_class_add_private (gobject_class,
101                                   sizeof(ModestTnyAccountStorePrivate));
102
103         /* signal definitions go here, e.g.: */
104 /*      signals[MY_SIGNAL_1] = */
105 /*              g_signal_new ("my_signal_1",....); */
106 /*      signals[MY_SIGNAL_2] = */
107 /*              g_signal_new ("my_signal_2",....); */
108 /*      etc. */
109 }
110
111 static void
112 modest_tny_account_store_init (ModestTnyAccountStore *obj)
113 {
114         ModestTnyAccountStorePrivate *priv =
115                 MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(obj);
116
117         priv->modest_acc_mgr         = NULL;
118
119         priv->store_accounts         = NULL;
120         priv->transport_accounts     = NULL;
121         priv->cache_dir              = NULL;
122 }
123
124
125 static void
126 free_gobject (GObject *obj, gpointer user_data)
127 {
128         if (obj)
129                 g_object_unref (obj);
130 }
131
132
133 static GList*
134 free_gobject_list (GList *list)
135 {
136         if (list) {
137                 g_list_foreach (list, (GFunc)free_gobject, NULL);
138                 g_list_free (list);
139         }
140         return NULL;
141 }
142
143
144 static void
145 modest_tny_account_store_finalize (GObject *obj)
146 {
147         ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(obj);
148         ModestTnyAccountStorePrivate *priv =
149                 MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
150
151         if (priv->modest_acc_mgr) {
152                 g_object_unref (G_OBJECT(priv->modest_acc_mgr));
153                 priv->modest_acc_mgr = NULL;
154         }
155
156         priv->store_accounts     = free_gobject_list (priv->store_accounts);
157         priv->transport_accounts = free_gobject_list (priv->store_accounts);
158         
159         g_free (priv->cache_dir);
160         priv->cache_dir = NULL;
161 }
162
163 GObject*
164 modest_tny_account_store_new (ModestAccountMgr *modest_acc_mgr)
165 {
166         GObject *obj;
167         ModestTnyAccountStorePrivate *priv;
168
169         g_return_val_if_fail (modest_acc_mgr, NULL);
170
171         obj  = G_OBJECT(g_object_new(MODEST_TYPE_TNY_ACCOUNT_STORE, NULL));
172
173         priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(obj);
174         g_object_ref(G_OBJECT(priv->modest_acc_mgr = modest_acc_mgr));
175
176         return obj;
177 }
178
179
180
181 /* FIXME: tinymail needs to change here */
182 /* a gpointer arg to get_password should be enough */
183 static gchar*
184 get_password (TnyAccountIface *account, const gchar *prompt)
185 {
186         const gchar *key = tny_account_iface_get_id (account);
187         const TnyAccountStoreIface *AccountStore = tny_account_iface_get_account_store(account);
188         ModestTnyAccountStorePrivate *priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(AccountStore);
189         gchar *val;
190
191         /* hostname */
192         val = modest_account_mgr_get_account_string (priv->modest_acc_mgr, key,
193                                                      MODEST_ACCOUNT_PASSWORD, NULL);
194         /* SMF:
195          * FIXME: if no password avail. in modest-conf, then we need to get the pw from
196          * somewhere else.
197          *
198          * DJCB: good point: we should probably emit a signal for that..
199          */
200
201         /* g_warning (val); */
202
203         return val;
204 }
205
206
207 static void
208 forget_password (TnyAccountIface *account)
209 {
210         g_warning (__FUNCTION__);
211 }
212
213
214
215 static gboolean
216 add_account  (TnyAccountStoreIface *self, TnyAccountIface *account)
217 {
218         TnyAccountIface       *account_iface;
219         ModestTnyAccountStore *account_store;
220         ModestTnyAccountStorePrivate *priv;
221
222         const gchar* account_name;
223         const gchar *hostname, *username, *proto;
224
225         g_warning (__FUNCTION__);
226
227         g_return_val_if_fail (self, FALSE);
228         g_return_val_if_fail (account, FALSE);
229
230         account_iface  = TNY_ACCOUNT_IFACE(account);
231         account_store  = MODEST_TNY_ACCOUNT_STORE(self);
232         priv           = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
233
234         account_name   = tny_account_iface_get_id(account_iface);
235         if (!account_name) {
236                 g_warning ("failed to retrieve account name");
237                 return FALSE;
238         }
239
240         hostname =  tny_account_iface_get_hostname(account_iface);
241         username =  tny_account_iface_get_user(account_iface);
242         proto    =  tny_account_iface_get_proto(account_iface);
243
244         return modest_account_mgr_add_server_account (priv->modest_acc_mgr,
245                                                       account_name,
246                                                       hostname, username, NULL,
247                                                       proto);
248 }
249
250
251
252 static void
253 modest_tny_account_store_add_store_account  (TnyAccountStoreIface *self,
254                                              TnyStoreAccountIface *account)
255 {
256         if (!add_account (self, TNY_ACCOUNT_IFACE(account)))
257                 g_warning ("failed to add store account");
258 }
259
260
261
262 static void
263 modest_tny_account_store_add_transport_account  (TnyAccountStoreIface *self,
264                                                  TnyTransportAccountIface *account)
265 {
266         if (!add_account (self, TNY_ACCOUNT_IFACE(account)))
267                 g_warning ("failed to add transport account");
268 }
269
270
271
272
273 static TnyAccountIface*
274 tny_account_from_key (ModestTnyAccountStore *self, const gchar *key,
275                       gboolean is_store)
276 {
277         TnyAccountIface *tny_account;
278         ModestTnyAccountStorePrivate *priv;
279         gchar *val;
280
281         g_return_val_if_fail (self, NULL);
282         g_return_val_if_fail (key, NULL);
283         
284         priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
285         
286         /* is it a store or a transport? */
287         if (is_store)
288                 tny_account = TNY_ACCOUNT_IFACE(tny_store_account_new ());
289         else
290                 tny_account = TNY_ACCOUNT_IFACE(tny_transport_account_new ());
291
292         if (!tny_account) {
293                 g_warning ("failed to create new tny %s account",
294                            is_store ? "store" : "transport");
295                 return NULL;
296         }
297         
298         tny_account_iface_set_account_store (TNY_ACCOUNT_IFACE(tny_account),
299                                              TNY_ACCOUNT_STORE_IFACE(self));
300         /* id */
301         tny_account_iface_set_id (tny_account, key);
302
303         /* proto */
304         val = modest_account_mgr_get_server_account_string (priv->modest_acc_mgr, key,
305                                                      MODEST_ACCOUNT_PROTO, NULL);
306         if (val) {
307                 tny_account_iface_set_proto (tny_account, val);
308                 g_free (val);
309         } else {
310                 g_warning ("protocol not defined for %s", key);
311                 g_object_unref (G_OBJECT(tny_account));
312                 return NULL;    
313         }
314
315         
316         /* hostname */
317         val = modest_account_mgr_get_server_account_string (priv->modest_acc_mgr, key,
318                                                      MODEST_ACCOUNT_HOSTNAME, NULL);
319         if (val) {
320                 g_warning ("hostname: %s", val);
321                 tny_account_iface_set_hostname (tny_account, val);
322                 g_free (val);
323         }
324                 
325
326         /* username */
327         val = modest_account_mgr_get_account_string (priv->modest_acc_mgr, key,
328                                                      MODEST_ACCOUNT_USERNAME, NULL);
329         if (val) {
330                 tny_account_iface_set_user (tny_account, val);
331                 g_free (val);
332         }
333
334         tny_account_iface_set_pass_func (tny_account, get_password);
335         tny_account_iface_set_forget_pass_func (tny_account, forget_password);
336
337         return tny_account;
338 }
339
340
341 static GList*
342 tny_accounts_from_server_accounts (ModestTnyAccountStore *self, GSList *accounts,
343                                    gboolean is_store)
344 {
345         GSList *cursor = accounts;
346         GList *tny_accounts = NULL;
347         
348         g_return_val_if_fail (self, NULL);
349         
350         while (cursor) {
351                 TnyAccountIface *tny_account;
352                 tny_account = tny_account_from_key (self, (gchar*)cursor->data, is_store);
353                 if (!tny_account) {
354                         g_warning ("could not create tnyaccount for %s",
355                                    (gchar*)cursor->data);
356                 } else {
357                         g_warning ("added %s",(gchar*)cursor->data);
358                         tny_accounts =
359                                 g_list_append (tny_accounts, tny_account);
360                 }
361                 cursor = cursor->next;
362         }
363
364         g_warning ("got %d %s account(s)", g_list_length(tny_accounts),
365                    is_store ? "store" : "transport");
366
367         
368         return tny_accounts;
369 }
370
371
372
373 static const GList*
374 modest_tny_account_store_get_store_accounts  (TnyAccountStoreIface *iface)
375 {
376         ModestTnyAccountStore        *self;
377         ModestTnyAccountStorePrivate *priv;
378         GSList                       *accounts, *cursor;
379         GList                        *tny_accounts;
380         
381         g_return_val_if_fail (iface, NULL);
382         
383         self = MODEST_TNY_ACCOUNT_STORE(iface);
384         priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
385         
386         accounts =
387                 modest_account_mgr_server_account_names (priv->modest_acc_mgr,
388                                                          NULL,
389                                                          MODEST_PROTO_TYPE_STORE,
390                                                          NULL, FALSE);
391
392         g_message ("accounts: %d", g_slist_length (accounts));
393         tny_accounts = tny_accounts_from_server_accounts (self, accounts, TRUE);
394         g_slist_free (accounts);
395         g_message ("store accounts: %d", g_list_length (tny_accounts)); 
396
397
398         /*
399          * FIXME: after gconf notification support is added,
400          * we can simply return priv->store_account
401          */
402         priv->store_accounts = free_gobject_list (priv->store_accounts);
403         priv->store_accounts = tny_accounts;
404         
405         return tny_accounts; 
406 }
407
408
409
410 static const GList*
411 modest_tny_account_store_get_transport_accounts (TnyAccountStoreIface *iface)
412 {
413         ModestTnyAccountStore        *self;
414         ModestTnyAccountStorePrivate *priv;
415         GSList                       *accounts, *cursor;
416         GList                        *tny_accounts;
417
418         g_return_val_if_fail (iface, NULL);
419
420         self = MODEST_TNY_ACCOUNT_STORE(iface);
421         priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
422
423         accounts =
424                 modest_account_mgr_server_account_names (priv->modest_acc_mgr,
425                                                          NULL,
426                                                          MODEST_PROTO_TYPE_TRANSPORT,
427                                                          NULL, FALSE);
428         tny_accounts = tny_accounts_from_server_accounts (self, accounts, FALSE);
429         g_warning ("transport accounts: %d", g_list_length (tny_accounts));
430
431         g_slist_free (accounts);
432         
433         /*
434          * FIXME: after gconf notification support is added,
435          * we can simply return priv->store_account
436          */
437         priv->transport_accounts = free_gobject_list (priv->transport_accounts);
438         priv->transport_accounts = tny_accounts;
439         
440         return tny_accounts; /* FIXME: who will free this? */
441 }
442
443
444 /**
445  * modest_tny_account_store_get_cache_dir:
446  * @self: self a TnyAccountStoreIface instance
447  *
448  * returns the pathname of the cache directory
449  *
450  * Returns: a string with the value of the pathname
451  * to the cache directory or NULL if the environment variable $HOME is
452  * not set. string should _not_ be freed by caller
453  */
454 static const gchar*
455 modest_tny_account_store_get_cache_dir (TnyAccountStoreIface *self)
456 {
457         ModestTnyAccountStorePrivate *priv;
458         priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
459
460         gchar *cache_dir;
461         
462         if (!priv->cache_dir) {
463                 if (g_getenv("HOME") != NULL)
464                         priv->cache_dir = g_strconcat(g_getenv("HOME"),
465                                                       "/.modest/cache/", NULL);
466         }
467         return priv->cache_dir;
468 }
469
470
471
472 /* FIXME */
473 static const TnyDeviceIface*
474 modest_tny_account_store_get_device (TnyAccountStoreIface *self)
475 {
476         return NULL;
477 }
478
479
480
481 static void
482 modest_tny_account_store_iface_init (gpointer g_iface, gpointer iface_data)
483 {
484         TnyAccountStoreIfaceClass *klass;
485
486         g_return_if_fail (g_iface);
487
488         klass = (TnyAccountStoreIfaceClass *)g_iface;
489
490         klass->add_store_account_func      =
491                 modest_tny_account_store_add_store_account;
492         klass->get_store_accounts_func     =
493                 modest_tny_account_store_get_store_accounts;
494         klass->add_transport_account_func  =
495                 modest_tny_account_store_add_transport_account;
496         klass->get_transport_accounts_func =
497                 modest_tny_account_store_get_transport_accounts;
498         klass->get_cache_dir_func =
499                 modest_tny_account_store_get_cache_dir;
500         klass->get_device_func =
501                 modest_tny_account_store_get_device;    
502
503 }
504