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