root/trunk/libtinymail-maemo/tny-maemo-account-store.c

Revision 3666 (checked in by jdapena, 7 months ago)

* Use GOnce registering all types in tinymail to make

registering thread-safe.

Line 
1 /* tinymail - Tiny Mail
2  * Copyright (C) 2006-2007 Philip Van Hoof <pvanhoof@gnome.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with self library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include <sys/mman.h>
21
22 #include <config.h>
23 #include <glib/gi18n-lib.h>
24
25 #include <string.h>
26 #include <glib.h>
27 #include <gtk/gtk.h>
28 #include <gconf/gconf-client.h>
29
30
31 #include <tny-platform-factory.h>
32 #include <tny-password-getter.h>
33 #include <tny-maemo-platform-factory.h>
34
35 #include <tny-account-store.h>
36 #include <tny-error.h>
37 #include <tny-maemo-account-store.h>
38 #include <tny-account.h>
39 #include <tny-store-account.h>
40 #include <tny-transport-account.h>
41 #include <tny-device.h>
42
43 #include <tny-camel-account.h>
44 #include <tny-camel-store-account.h>
45 #include <tny-camel-transport-account.h>
46 #include <tny-camel-imap-store-account.h>
47 #include <tny-camel-nntp-store-account.h>
48 #include <tny-camel-pop-store-account.h>
49 #include <tny-session-camel.h>
50 #include <tny-maemo-device.h>
51
52 #include <tny-gtk-lockable.h>
53
54 /* "GConf vs. Camel" account implementation */
55
56 static GObjectClass *parent_class = NULL;
57
58 typedef struct _TnyMaemoAccountStorePriv TnyMaemoAccountStorePriv;
59
60 struct _TnyMaemoAccountStorePriv
61 {
62         GConfClient *client;
63         gchar *cache_dir;
64         TnySessionCamel *session;
65         TnyDevice *device;
66         guint notify;
67         GList *accounts;
68 };
69
70 #define TNY_MAEMO_ACCOUNT_STORE_GET_PRIVATE(o)  \
71         (G_TYPE_INSTANCE_GET_PRIVATE ((o), TNY_TYPE_MAEMO_ACCOUNT_STORE, TnyMaemoAccountStorePriv))
72
73
74 static gchar*
75 per_account_get_pass(TnyAccount *account, const gchar *prompt, gboolean *cancel)
76 {
77         TnyPlatformFactory *platfact = tny_maemo_platform_factory_get_instance ();
78         TnyPasswordGetter *pwdgetter;
79         gchar *retval;
80
81         pwdgetter = tny_platform_factory_new_password_getter (platfact);
82         retval = (gchar*) tny_password_getter_get_password (pwdgetter,
83                 tny_account_get_id (account), prompt, cancel);
84         g_object_unref (G_OBJECT (pwdgetter));
85
86         return retval;
87 }
88
89
90 static void
91 per_account_forget_pass(TnyAccount *account)
92 {
93         TnyPlatformFactory *platfact = tny_maemo_platform_factory_get_instance ();
94         TnyPasswordGetter *pwdgetter;
95
96         pwdgetter = tny_platform_factory_new_password_getter (platfact);
97         tny_password_getter_forget_password (pwdgetter, tny_account_get_id (account));
98         g_object_unref (G_OBJECT (pwdgetter));
99
100         return;
101 }
102
103 static gboolean
104 tny_maemo_account_store_alert (TnyAccountStore *self, TnyAccount *account, TnyAlertType type, gboolean question, GError *error)
105 {
106         GtkMessageType gtktype;
107         gboolean retval = FALSE;
108         GtkWidget *dialog;
109
110         switch (type)
111         {
112                 case TNY_ALERT_TYPE_INFO:
113                 gtktype = GTK_MESSAGE_INFO;
114                 break;
115                 case TNY_ALERT_TYPE_WARNING:
116                 gtktype = GTK_MESSAGE_WARNING;
117                 break;
118                 case TNY_ALERT_TYPE_ERROR:
119                 default:
120                 gtktype = GTK_MESSAGE_ERROR;
121                 break;
122         }
123
124         dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL,
125                 gtktype, GTK_BUTTONS_YES_NO, error->message);
126
127         if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_YES)
128                 retval = TRUE;
129
130         gtk_widget_destroy (dialog);
131
132         return retval;
133 }
134
135
136 static void
137 kill_stored_accounts (TnyMaemoAccountStorePriv *priv)
138 {
139         if (priv->accounts)
140         {
141                 g_list_foreach (priv->accounts, (GFunc) g_object_unref, NULL);
142                 g_list_free (priv->accounts);
143                 priv->accounts = NULL;
144         }
145
146         return;
147 }
148
149 static void
150 gconf_listener_account_changed (GConfClient *client, guint cnxn_id,
151                         GConfEntry *entry, gpointer user_data)
152 {
153         TnyAccountStore *self = user_data;
154         TnyMaemoAccountStorePriv *priv = TNY_MAEMO_ACCOUNT_STORE_GET_PRIVATE (self);
155
156         gchar *key = entry->key ? g_strdup (entry->key) : g_strdup ("");
157         gchar *ptr = strrchr (key, '/');
158
159         if (ptr) {
160                 ptr++;
161                 if (!strcmp (ptr, "count"))
162                         kill_stored_accounts (priv);
163         }
164
165         g_free (key);
166
167         return;
168 }
169
170 static void
171 load_accounts (TnyAccountStore *self)
172 {
173         TnyMaemoAccountStorePriv *priv = TNY_MAEMO_ACCOUNT_STORE_GET_PRIVATE (self);
174
175         gint i=0, count, port;
176
177         count = gconf_client_get_int (priv->client,
178                         "/apps/tinymail/accounts/count", NULL);
179
180         for (i=0; i < count; i++)
181         {
182
183                 gchar *proto, *type, *key, *name, *mech;
184                 TnyAccount *account = NULL;
185                 GSList *options;
186
187                 key = g_strdup_printf ("/apps/tinymail/accounts/%d", i);
188                
189                 if (!gconf_client_dir_exists (priv->client, (const gchar*)key, NULL))
190                 {
191                         g_free (key);
192                         continue;
193                 }
194                 g_free (key);
195
196                 key = g_strdup_printf ("/apps/tinymail/accounts/%d/disabled", i);
197                 if (gconf_client_get_bool (priv->client, (const gchar*) key, NULL))
198                 {
199                         g_free (key);
200                         continue;
201                 }
202                 g_free (key);
203
204                 key = g_strdup_printf ("/apps/tinymail/accounts/%d/type", i);
205                 type = gconf_client_get_string (priv->client,
206                         (const gchar*) key, NULL);
207                 g_free (key);
208
209                 key = g_strdup_printf ("/apps/tinymail/accounts/%d/proto", i);
210                 proto = gconf_client_get_string (priv->client,
211                         (const gchar*) key, NULL);
212                 g_free (key);
213
214                 key = g_strdup_printf ("/apps/tinymail/accounts/%d/mech", i);
215                 mech = gconf_client_get_string (priv->client,
216                         (const gchar*) key, NULL);
217                 g_free (key);
218
219                 if (!g_ascii_strncasecmp (proto, "smtp", 4))
220                         account = TNY_ACCOUNT (tny_camel_transport_account_new ());
221                 else if (!g_ascii_strncasecmp (proto, "imap", 4))
222                         account = TNY_ACCOUNT (tny_camel_imap_store_account_new ());
223                 else if (!g_ascii_strncasecmp (proto, "nntp", 4))
224                         account = TNY_ACCOUNT (tny_camel_nntp_store_account_new ());
225                 else if (!g_ascii_strncasecmp (proto, "pop", 3))
226                         account = TNY_ACCOUNT (tny_camel_pop_store_account_new ());
227                 else    /* Unknown, create a generic one? */
228                         account = TNY_ACCOUNT (tny_camel_store_account_new ());
229
230                 if (type)
231                         g_free (type);
232
233                 if (account)
234                 {
235                         tny_camel_account_set_session (TNY_CAMEL_ACCOUNT (account), priv->session);
236                         tny_account_set_proto (TNY_ACCOUNT (account), proto);
237
238                         key = g_strdup_printf ("/apps/tinymail/accounts/%d/name", i);
239                         name = gconf_client_get_string (priv->client,
240                                 (const gchar*) key, NULL);
241                         g_free (key);
242                         tny_account_set_name (TNY_ACCOUNT (account), name);
243                         if (name)
244                         {
245                                 tny_account_set_name (TNY_ACCOUNT (account), name);
246                                 g_free (name);
247                         }
248
249                         if (mech)
250                                 tny_account_set_secure_auth_mech (TNY_ACCOUNT (account), mech);
251
252                         key = g_strdup_printf ("/apps/tinymail/accounts/%d/options", i);
253                         options = gconf_client_get_list (priv->client,
254                                 (const gchar*) key, GCONF_VALUE_STRING, NULL);
255                         g_free (key);
256
257                         if (options) {
258                                 while (options) {
259                                         gchar *key = options->data;
260                                         gchar *value = strchr (options->data, '=');
261
262                                         if (value) {
263                                                 *value = '\0';
264                                                 value++;
265                                         } else
266                                                 value = "";
267
268                                         tny_camel_account_add_option (TNY_CAMEL_ACCOUNT (account),
269                                                 tny_pair_new (key, value));
270                                         g_free (options->data);
271                                         options = g_slist_next (options);
272                                 }
273                                 g_slist_free (options);
274                         }
275
276                         if (!g_ascii_strncasecmp (proto, "pop", 3) ||
277                                 !g_ascii_strncasecmp (proto, "imap", 4))
278                         {
279                                 gchar *user, *hostname;
280
281                                 key = g_strdup_printf ("/apps/tinymail/accounts/%d/user", i);
282                                 user = gconf_client_get_string (priv->client,
283                                         (const gchar*) key, NULL);
284
285                                 g_free (key);
286                                 tny_account_set_user (TNY_ACCOUNT (account), user);
287
288                                 key = g_strdup_printf ("/apps/tinymail/accounts/%d/hostname", i);
289                                 hostname = gconf_client_get_string (priv->client,
290                                         (const gchar*) key, NULL);
291                                 g_free (key);
292                                 tny_account_set_hostname (TNY_ACCOUNT (account),
293                                         hostname);
294
295                                 key = g_strdup_printf ("/apps/tinymail/accounts/%d/port", i);
296                                 port = gconf_client_get_int (priv->client,
297                                         (const gchar*) key, NULL);
298                                 g_free (key);
299                                 if (port != 0) tny_account_set_port (TNY_ACCOUNT (account),
300                                         port);
301
302                                 g_free (hostname); g_free (user);
303                         } else {
304                                 gchar *url_string;
305
306                                 /* Un officially supported provider */
307                                 /* Assuming there's a url_string in this case */
308
309                                 key = g_strdup_printf ("/apps/tinymail/accounts/%d/url_string", i);
310                                 url_string = gconf_client_get_string (priv->client,
311                                         (const gchar*) key, NULL);
312
313                                 g_free (key);
314                                 tny_account_set_url_string (TNY_ACCOUNT (account), url_string);
315                                 g_free (url_string);
316                         }
317
318                         key = g_strdup_printf ("/apps/tinymail/accounts/%d", i);
319                         tny_account_set_id (TNY_ACCOUNT (account), key);
320                         g_free (key);
321
322                         tny_account_set_forget_pass_func (TNY_ACCOUNT (account),
323                                 per_account_forget_pass);
324
325                         tny_account_set_pass_func (TNY_ACCOUNT (account),
326                                 per_account_get_pass);
327
328                         priv->accounts = g_list_prepend (priv->accounts, account);
329
330                 }
331
332                 if (proto)
333                         g_free (proto);
334
335                 if (mech)
336                         g_free (mech);
337         }
338
339         tny_session_camel_set_initialized (priv->session);
340 }
341
342 static TnyAccount*
343 tny_maemo_account_store_find_account (TnyAccountStore *self, const gchar *url_string)
344 {
345         TnyMaemoAccountStorePriv *priv = TNY_MAEMO_ACCOUNT_STORE_GET_PRIVATE (self);
346         TnyAccount *found = NULL;
347
348         if (!priv->accounts)
349                 load_accounts (self);
350
351         if (priv->accounts) {
352                 GList *copy = priv->accounts;
353                 while (copy) {
354                         TnyAccount *account = copy->data;
355                         if (tny_account_matches_url_string (account, url_string)) {
356                                 found = TNY_ACCOUNT (g_object_ref (G_OBJECT (account)));
357                                 break;
358                         }
359                         copy = g_list_next (copy);
360                 }
361         }
362
363         return found;
364 }
365
366
367 static const gchar*
368 tny_maemo_account_store_get_cache_dir (TnyAccountStore *self)
369 {
370         TnyMaemoAccountStorePriv *priv = TNY_MAEMO_ACCOUNT_STORE_GET_PRIVATE (self);
371
372         if (!priv->cache_dir) {
373                 gchar *cache_dir = gconf_client_get_string (priv->client,
374                         "/apps/tinymail/cache_dir", NULL);
375                 priv->cache_dir = g_build_filename (g_get_home_dir (),
376                         cache_dir, NULL);
377                 g_free (cache_dir);
378         }
379
380         return priv->cache_dir;
381 }
382
383
384 static void
385 tny_maemo_account_store_get_accounts (TnyAccountStore *self, TnyList *list, TnyGetAccountsRequestType types)
386 {
387         TnyMaemoAccountStorePriv *priv = TNY_MAEMO_ACCOUNT_STORE_GET_PRIVATE (self);
388
389         g_assert (TNY_IS_LIST (list));
390
391         if (!priv->accounts)
392                 load_accounts (self);
393
394         if (priv->accounts)
395         {
396                 GList *copy = priv->accounts;
397                 while (copy) {
398                         TnyAccount *account = copy->data;
399                         if (types == TNY_ACCOUNT_STORE_BOTH || types == TNY_ACCOUNT_STORE_STORE_ACCOUNTS) {
400                                 if (TNY_IS_STORE_ACCOUNT (account))
401                                         tny_list_prepend (list, (GObject*)account);
402                         }
403                         if (types == TNY_ACCOUNT_STORE_BOTH || types == TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS) {
404                                 if (TNY_IS_TRANSPORT_ACCOUNT (account))
405                                         tny_list_prepend (list, (GObject*)account);
406                         }
407                         copy = g_list_next (copy);
408                 }
409         }
410
411         return;
412 }
413
414
415 static void
416 tny_maemo_account_store_notify_add (TnyAccountStore *self)
417 {
418         TnyMaemoAccountStorePriv *priv = TNY_MAEMO_ACCOUNT_STORE_GET_PRIVATE (self);
419         priv->notify = gconf_client_notify_add (priv->client,
420                 "/apps/tinymail/accounts", gconf_listener_account_changed,
421                 self, NULL, NULL);
422         return;
423 }
424
425 static void
426 tny_maemo_account_store_notify_remove (TnyAccountStore *self)
427 {
428         TnyMaemoAccountStorePriv *priv = TNY_MAEMO_ACCOUNT_STORE_GET_PRIVATE (self);
429         gconf_client_notify_remove (priv->client, priv->notify);
430         return;
431 }
432
433 /*
434         gconftool-2 -s /apps/tinymail/cache_dir -t string .tinymail
435
436         gconftool-2 -s /apps/tinymail/accounts/count -t int COUNT
437         gconftool-2 -s /apps/tinymail/accounts/0/proto -t string [smtp|imap|pop]
438         gconftool-2 -s /apps/tinymail/accounts/0/type -t string [transport|store]
439
440         gconftool-2 -s /apps/tinymail/accounts/0/user -t string username
441         gconftool-2 -s /apps/tinymail/accounts/0/hostname -t string mailserver
442 or
443         gconftool-2 -s /apps/tinymail/accounts/0/url_string -t string url_string
444
445 */
446
447
448 static TnyDevice*
449 tny_maemo_account_store_get_device (TnyAccountStore *self)
450 {
451         TnyMaemoAccountStorePriv *priv = TNY_MAEMO_ACCOUNT_STORE_GET_PRIVATE (self);
452         return g_object_ref (priv->device);
453 }
454
455 /**
456  * tny_maemo_account_store_new:
457  *
458  *
459  * Return value: A new #TnyAccountStore instance implemented for Maemo
460  **/
461 TnyAccountStore*
462 tny_maemo_account_store_new (void)
463 {
464         TnyMaemoAccountStore *self = g_object_new (TNY_TYPE_MAEMO_ACCOUNT_STORE, NULL);
465         TnyMaemoAccountStorePriv *priv = TNY_MAEMO_ACCOUNT_STORE_GET_PRIVATE (self);
466         priv->session = tny_session_camel_new (TNY_ACCOUNT_STORE (self));
467
468         tny_session_camel_set_ui_locker (priv->session, tny_gtk_lockable_new ());
469
470         return TNY_ACCOUNT_STORE (self);
471 }
472
473
474 static void
475 tny_maemo_account_store_instance_init (GTypeInstance *instance, gpointer g_class)
476 {
477         TnyMaemoAccountStore *self = (TnyMaemoAccountStore *)instance;
478         TnyMaemoAccountStorePriv *priv = TNY_MAEMO_ACCOUNT_STORE_GET_PRIVATE (self);
479         TnyPlatformFactory *platfact;
480
481         priv->cache_dir = NULL;
482         priv->accounts = NULL;
483         priv->client = gconf_client_get_default ();
484
485         gconf_client_add_dir (priv->client, "/apps/tinymail",
486                 GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
487
488         tny_maemo_account_store_notify_add (TNY_ACCOUNT_STORE (self));
489
490         platfact = TNY_PLATFORM_FACTORY (
491                 tny_maemo_platform_factory_get_instance ());
492
493         priv->device = tny_platform_factory_new_device (platfact);
494
495         return;
496 }
497
498
499 static void
500 tny_maemo_account_store_finalize (GObject *object)
501 {
502         TnyMaemoAccountStore *self = (TnyMaemoAccountStore *)object;   
503         TnyMaemoAccountStorePriv *priv = TNY_MAEMO_ACCOUNT_STORE_GET_PRIVATE (self);
504
505         tny_maemo_account_store_notify_remove (TNY_ACCOUNT_STORE (self));
506         g_object_unref (G_OBJECT (priv->client));
507
508         kill_stored_accounts (priv);
509
510         if (priv->cache_dir)
511                 g_free (priv->cache_dir);
512
513         (*parent_class->finalize) (object);
514
515         return;
516 }
517
518
519 /**
520  * tny_maemo_account_store_get_session:
521  * @self: The #TnyMaemoAccountStore instance
522  *
523  * Return value: A #TnySessionCamel instance
524  **/
525 TnySessionCamel*
526 tny_maemo_account_store_get_session (TnyMaemoAccountStore *self)
527 {
528         TnyMaemoAccountStorePriv *priv = TNY_MAEMO_ACCOUNT_STORE_GET_PRIVATE (self);
529
530         return priv->session;
531 }
532
533 static void
534 tny_maemo_account_store_class_init (TnyMaemoAccountStoreClass *class)
535 {
536         GObjectClass *object_class;
537
538         parent_class = g_type_class_peek_parent (class);
539         object_class = (GObjectClass*) class;
540
541         object_class->finalize = tny_maemo_account_store_finalize;
542
543         g_type_class_add_private (object_class, sizeof (TnyMaemoAccountStorePriv));
544
545         return;
546 }
547
548 static void
549 tny_account_store_init (gpointer g, gpointer iface_data)
550 {
551         TnyAccountStoreIface *klass = (TnyAccountStoreIface *)g;
552
553         klass->get_accounts= tny_maemo_account_store_get_accounts;
554         klass->get_cache_dir= tny_maemo_account_store_get_cache_dir;
555         klass->get_device= tny_maemo_account_store_get_device;
556         klass->alert= tny_maemo_account_store_alert;
557         klass->find_account= tny_maemo_account_store_find_account;
558
559         return;
560 }
561
562
563 static gpointer
564 tny_maemo_account_store_register_type (gpointer notused)
565 {
566         GType type = 0;
567
568         static const GTypeInfo info =
569                 {
570                         sizeof (TnyMaemoAccountStoreClass),
571                         NULL,   /* base_init */
572                         NULL,   /* base_finalize */
573                         (GClassInitFunc) tny_maemo_account_store_class_init,   /* class_init */
574                         NULL,   /* class_finalize */
575                         NULL,   /* class_data */
576                         sizeof (TnyMaemoAccountStore),
577                         0,      /* n_preallocs */
578                         tny_maemo_account_store_instance_init    /* instance_init */
579                 };
580        
581         static const GInterfaceInfo tny_account_store_info =
582                 {
583                         (GInterfaceInitFunc) tny_account_store_init, /* interface_init */
584                         NULL,         /* interface_finalize */
585                         NULL          /* interface_data */
586                 };
587        
588         type = g_type_register_static (G_TYPE_OBJECT,
589                                        "TnyMaemoAccountStore",
590                                        &info, 0);
591        
592         g_type_add_interface_static (type, TNY_TYPE_ACCOUNT_STORE,
593                                      &tny_account_store_info);
594
595         return GUINT_TO_POINTER (type);
596 }
597
598 GType
599 tny_maemo_account_store_get_type (void)
600 {
601         static GOnce once = G_ONCE_INIT;
602         g_once (&once, tny_maemo_account_store_register_type, NULL);
603         return GPOINTER_TO_UINT (once.retval);
604 }
Note: See TracBrowser for help on using the browser.