* Create signal on gconf key change and propagate event to account manager.
[modest] / src / modest-account-mgr.c
1 /* modest-account-mgr.c */
2
3 /* insert (c)/licensing information) */
4
5 #include <string.h>
6 #include "modest-account-mgr.h"
7
8 /* 'private'/'protected' functions */
9 static void modest_account_mgr_class_init (ModestAccountMgrClass * klass);
10 static void modest_account_mgr_init (ModestAccountMgr * obj);
11 static void modest_account_mgr_finalize (GObject * obj);
12
13 static gchar *get_account_keyname (const gchar * accname, const gchar * name);
14 static gchar *get_server_account_keyname (const gchar * accname,
15                                           const gchar * name);
16
17 /* list my signals */
18 enum {
19         /* MY_SIGNAL_1, */
20         /* MY_SIGNAL_2, */
21         LAST_SIGNAL
22 };
23
24 typedef struct _ModestAccountMgrPrivate ModestAccountMgrPrivate;
25 struct _ModestAccountMgrPrivate {
26         ModestConf *modest_conf;
27 };
28
29 #define MODEST_ACCOUNT_MGR_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
30                                                 MODEST_TYPE_ACCOUNT_MGR, \
31                                                 ModestAccountMgrPrivate))
32 /* globals */
33 static GObjectClass *parent_class = NULL;
34
35 /* uncomment the following if you have defined any signals */
36 /* static guint signals[LAST_SIGNAL] = {0}; */
37
38 static void
39 modest_account_mgr_check_change (ModestConf *conf, const gchar *key, 
40                                  const gchar *new_value, gpointer user_data)
41 {
42         ModestAccountMgr *amgr = user_data;
43         
44         g_message ("value changed: %s %s\n", key, new_value);
45 }
46
47
48 GType
49 modest_account_mgr_get_type (void)
50 {
51         static GType my_type = 0;
52
53         if (!my_type) {
54                 static const GTypeInfo my_info = {
55                         sizeof (ModestAccountMgrClass),
56                         NULL,   /* base init */
57                         NULL,   /* base finalize */
58                         (GClassInitFunc) modest_account_mgr_class_init,
59                         NULL,   /* class finalize */
60                         NULL,   /* class data */
61                         sizeof (ModestAccountMgr),
62                         1,      /* n_preallocs */
63                         (GInstanceInitFunc) modest_account_mgr_init,
64                 };
65
66                 my_type = g_type_register_static (G_TYPE_OBJECT,
67                                                   "ModestAccountMgr",
68                                                   &my_info, 0);
69         }
70         return my_type;
71 }
72
73 static void
74 modest_account_mgr_class_init (ModestAccountMgrClass * klass)
75 {
76         GObjectClass *gobject_class;
77
78         gobject_class = (GObjectClass *) klass;
79
80         parent_class = g_type_class_peek_parent (klass);
81         gobject_class->finalize = modest_account_mgr_finalize;
82
83         g_type_class_add_private (gobject_class,
84                                   sizeof (ModestAccountMgrPrivate));
85
86         /* signal definitions go here, e.g.: */
87 /*      signals[MY_SIGNAL_1] = */
88 /*              g_signal_new ("my_signal_1",....); */
89 /*      signals[MY_SIGNAL_2] = */
90 /*              g_signal_new ("my_signal_2",....); */
91 /*      etc. */
92 }
93
94
95 static void
96 modest_account_mgr_init (ModestAccountMgr * obj)
97 {
98         ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (obj);
99
100         priv->modest_conf = NULL;
101 }
102
103 static void
104 modest_account_mgr_finalize (GObject * obj)
105 {
106         ModestAccountMgr *self = MODEST_ACCOUNT_MGR (obj);
107         ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
108
109         if (priv->modest_conf) {
110                 g_object_unref (G_OBJECT(priv->modest_conf));
111                 priv->modest_conf = NULL;
112         }
113 }
114
115 GObject *
116 modest_account_mgr_new (ModestConf * conf)
117 {
118         GObject *obj;
119         ModestAccountMgrPrivate *priv;
120
121         g_return_val_if_fail (conf, NULL);
122
123         obj = G_OBJECT (g_object_new (MODEST_TYPE_ACCOUNT_MGR, NULL));
124         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (obj);
125
126         /*
127          * increase the ref count on the modest_conf. Normally, the
128          * ModestConf should outlive the ModestAccountMgr though
129          */
130         g_object_ref (G_OBJECT (priv->modest_conf = conf));
131         
132         g_signal_connect (G_OBJECT (conf), "key-changed", 
133                           G_CALLBACK (modest_account_mgr_check_change), obj);
134         return obj;
135 }
136
137
138 gboolean
139 modest_account_mgr_add_account (ModestAccountMgr * self, const gchar * name,
140                                 const gchar * store_account,
141                                 const gchar * transport_account,
142                                 GError ** err)
143 {
144         ModestAccountMgrPrivate *priv;
145         gchar *key;
146
147         g_return_val_if_fail (self, FALSE);
148         g_return_val_if_fail (name, FALSE);
149
150         if (modest_account_mgr_account_exists (self, name, err)) {
151                 g_warning ("account already exists");
152                 //return FALSE;
153         }
154         /*
155          * we create the account by adding an account 'dir', with the name <name>,
156          * and in that the 'display_name' string key
157          */
158         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
159
160         key = get_account_keyname (name, MODEST_ACCOUNT_DISPLAY_NAME);
161         modest_conf_set_string (priv->modest_conf, key, name, err);
162         g_free (key);
163
164         if (store_account) {
165                 key = get_account_keyname (name,
166                                            MODEST_ACCOUNT_STORE_ACCOUNT);
167                 modest_conf_set_string (priv->modest_conf, key, store_account,
168                                         err);
169                 g_free (key);
170         }
171
172         if (transport_account) {
173                 key = get_account_keyname (name,
174                                            MODEST_ACCOUNT_TRANSPORT_ACCOUNT);
175                 modest_conf_set_string (priv->modest_conf, key,
176                                         transport_account, err);
177                 g_free (key);
178         }
179
180         return TRUE;            /* TODO: error handling */
181 }
182
183
184 gboolean
185 modest_account_mgr_remove_account (ModestAccountMgr * self,
186                                    const gchar * name, GError ** err)
187 {
188         ModestAccountMgrPrivate *priv;
189         gchar *key;
190         gboolean retval;
191
192         g_return_val_if_fail (self, FALSE);
193         g_return_val_if_fail (name, FALSE);
194
195         if (!modest_account_mgr_account_exists (self, name, err)) {
196                 g_warning ("account doest not exist");
197                 return FALSE;
198         }
199
200         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
201         key = get_account_keyname (name, NULL);
202
203         retval = modest_conf_remove_key (priv->modest_conf, key, NULL);
204
205         g_free (key);
206         return retval;
207 }
208
209
210 static const gchar *
211 null_means_empty (const gchar * str)
212 {
213         return str ? str : "";
214 }
215
216
217 gboolean
218 modest_account_mgr_add_server_account (ModestAccountMgr * self,
219                                        const gchar * name,
220                                        const gchar * hostname,
221                                        const gchar * username,
222                                        const gchar * password,
223                                        const gchar * proto)
224 {
225         ModestAccountMgrPrivate *priv;
226         gchar *acckey, *key;
227
228         g_return_val_if_fail (self, FALSE);
229         g_return_val_if_fail (name, FALSE);
230
231         /* TODO: check already exists */
232
233         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
234         acckey = g_strconcat (MODEST_SERVER_ACCOUNT_NAMESPACE, "/",
235                               name, NULL);
236
237         if (modest_conf_key_exists (priv->modest_conf, acckey, NULL)) {
238                 g_warning ("server account %s already exists", name);
239                 //g_free (acckey);
240                 //return FALSE;
241         }
242
243         /* hostname */
244         key = g_strconcat (acckey, "/", MODEST_ACCOUNT_HOSTNAME, NULL);
245         modest_conf_set_string (priv->modest_conf, key,
246                                 null_means_empty (hostname), NULL);
247         g_free (key);
248
249         /* username */
250         key = g_strconcat (acckey, "/", MODEST_ACCOUNT_USERNAME, NULL);
251         modest_conf_set_string (priv->modest_conf, key,
252                                 null_means_empty (username), NULL);
253         g_free (key);
254
255         /* password */
256         if (password) {
257                 key = g_strconcat (acckey, "/", MODEST_ACCOUNT_PASSWORD,
258                                    NULL);
259                 modest_conf_set_string (priv->modest_conf, key,
260                                         null_means_empty (password), NULL);
261                 g_free (key);
262         }
263
264         /* proto */
265         key = g_strconcat (acckey, "/", MODEST_ACCOUNT_PROTO, NULL);
266         modest_conf_set_string (priv->modest_conf, key,
267                                 null_means_empty (proto), NULL);
268         g_free (key);
269         g_free (acckey);
270
271         return TRUE;            /* FIXME: better error checking */
272 }
273
274 gboolean
275 modest_account_mgr_remove_server_account (ModestAccountMgr * self,
276                                           const gchar * name, GError ** err)
277 {
278         ModestAccountMgrPrivate *priv;
279         gchar *acckey;
280         gboolean retval;
281
282         g_return_val_if_fail (self, FALSE);
283         g_return_val_if_fail (name, FALSE);
284
285         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
286
287         acckey = g_strconcat (MODEST_SERVER_ACCOUNT_NAMESPACE, "/",
288                               name, NULL);
289
290         if (!modest_conf_key_exists (priv->modest_conf, acckey, NULL)) {
291                 g_warning ("server account %s does not exist exist", name);
292                 g_free (acckey);
293                 return FALSE;
294         }
295
296         retval = modest_conf_remove_key (priv->modest_conf, acckey, NULL);
297         g_free (acckey);
298
299         return retval;
300 }
301
302
303 /* strip the first /n/ character from each element */
304 /* caller must make sure all elements are strings with
305  * length >= n, and also that data can be freed.
306  */
307 static GSList *
308 strip_prefix_from_elements (GSList * lst, guint n)
309 {
310         GSList *cursor = lst;
311
312         while (cursor) {
313                 gchar *str = (gchar *) cursor->data;
314
315                 cursor->data = g_strdup (str + n);
316                 g_free (str);
317                 cursor = cursor->next;
318         }
319         return lst;
320 }
321
322
323 GSList *
324 modest_account_mgr_server_account_names (ModestAccountMgr * self,
325                                          const gchar * account_name,
326                                          ModestProtoType type,
327                                          const gchar * proto,
328                                          gboolean only_enabled)
329 {
330         GSList *accounts;
331         GSList *cursor;
332         ModestAccountMgrPrivate *priv;
333         const size_t prefix_len =
334                 strlen (MODEST_SERVER_ACCOUNT_NAMESPACE "/");
335
336         g_return_val_if_fail (self, NULL);
337
338         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
339         accounts = modest_conf_list_subkeys (priv->modest_conf,
340                                              MODEST_SERVER_ACCOUNT_NAMESPACE,
341                                              NULL);
342
343         /* no restrictions, return everything */
344         if (type == MODEST_PROTO_TYPE_ANY && !proto)
345                 return strip_prefix_from_elements (accounts, prefix_len);
346
347         /* otherwise, filter out the none-matching ones */
348         cursor = accounts;
349         while (cursor) {
350                 gchar *keyspace, *proto_key, *acc_proto;
351
352                 keyspace = (gchar *) cursor->data;
353                 proto_key =
354                         g_strconcat (keyspace, "/", MODEST_ACCOUNT_PROTO,
355                                      NULL);
356                 acc_proto =
357                         modest_conf_get_string (priv->modest_conf, proto_key,
358                                                 NULL);
359                 g_free (proto_key);
360
361                 if ((!acc_proto) ||     /* proto not defined? */
362                     (type != MODEST_PROTO_TYPE_ANY &&   /* proto type ...     */
363                      modest_proto_type (acc_proto) != type) ||  /* ... matches?       */
364                     (proto && strcmp (proto, acc_proto) != 0)) {        /* proto matches?     */
365                         /* no match: remove from the list */
366                         GSList *nxt = cursor->next;
367
368                         g_free (acc_proto);
369                         accounts = g_slist_delete_link (accounts, cursor);
370                         cursor = nxt;
371                 } else
372                         cursor = cursor->next;
373         }
374
375         return strip_prefix_from_elements (accounts, prefix_len);
376 }
377
378
379 GSList *
380 modest_account_mgr_account_names (ModestAccountMgr * self, GError ** err)
381 {
382         GSList *accounts;
383         ModestAccountMgrPrivate *priv;
384         const size_t prefix_len = strlen (MODEST_ACCOUNT_NAMESPACE "/");
385
386
387         g_return_val_if_fail (self, NULL);
388
389         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
390
391         accounts = modest_conf_list_subkeys (priv->modest_conf,
392                                              MODEST_ACCOUNT_NAMESPACE, err);
393         return strip_prefix_from_elements (accounts, prefix_len);
394 }
395
396
397 static gchar *
398 get_account_string (ModestAccountMgr * self, const gchar * name,
399                     const gchar * key, gboolean server_account, GError ** err)
400 {
401         ModestAccountMgrPrivate *priv;
402
403         gchar *keyname;
404         gchar *retval;
405
406         g_return_val_if_fail (self, NULL);
407         g_return_val_if_fail (name, NULL);
408         g_return_val_if_fail (key, NULL);
409
410         if (server_account)
411                 keyname = get_server_account_keyname (name, key);
412         else
413                 keyname = get_account_keyname (name, key);
414
415         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
416         retval = modest_conf_get_string (priv->modest_conf, keyname, err);
417         g_free (keyname);
418
419         return retval;
420 }
421
422
423 gchar *
424 modest_account_mgr_get_server_account_string (ModestAccountMgr * self,
425                                               const gchar * name,
426                                               const gchar * key,
427                                               GError ** err)
428 {
429         return get_account_string (self, name, key, TRUE, err);
430 }
431
432
433 gchar *
434 modest_account_mgr_get_account_string (ModestAccountMgr * self,
435                                        const gchar * name, const gchar * key,
436                                        GError ** err)
437 {
438         return get_account_string (self, name, key, FALSE, err);
439 }
440
441
442 static gint
443 get_account_int (ModestAccountMgr * self, const gchar * name,
444                  const gchar * key, gboolean server_account, GError ** err)
445 {
446         ModestAccountMgrPrivate *priv;
447
448         gchar *keyname;
449         gint retval;
450
451         g_return_val_if_fail (self, -1);
452         g_return_val_if_fail (name, -1);
453         g_return_val_if_fail (key, -1);
454
455         if (server_account)
456                 keyname = get_server_account_keyname (name, key);
457         else
458                 keyname = get_account_keyname (name, key);
459
460         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
461         retval = modest_conf_get_int (priv->modest_conf, keyname, err);
462         g_free (keyname);
463
464         return retval;
465 }
466
467
468 gint
469 modest_account_mgr_get_server_account_int (ModestAccountMgr * self,
470                                            const gchar * name,
471                                            const gchar * key, GError ** err)
472 {
473         return get_account_int (self, name, key, TRUE, err);
474 }
475
476
477 gint
478 modest_account_mgr_get_account_int (ModestAccountMgr * self,
479                                     const gchar * name, const gchar * key,
480                                     GError ** err)
481 {
482         return get_account_int (self, name, key, FALSE, err);
483 }
484
485
486 static gboolean
487 get_account_bool (ModestAccountMgr * self, const gchar * name,
488                   const gchar * key, gboolean server_account, GError ** err)
489 {
490         ModestAccountMgrPrivate *priv;
491
492         gchar *keyname;
493         gboolean retval;
494
495         g_return_val_if_fail (self, -1);
496         g_return_val_if_fail (name, -1);
497         g_return_val_if_fail (key, -1);
498
499         if (server_account)
500                 keyname = get_server_account_keyname (name, key);
501         else
502                 keyname = get_account_keyname (name, key);
503
504         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
505         retval = modest_conf_get_int (priv->modest_conf, keyname, err);
506         g_free (keyname);
507
508         return retval;
509 }
510
511
512 gint
513 modest_account_mgr_get_server_account_bool (ModestAccountMgr * self,
514                                             const gchar * name,
515                                             const gchar * key, GError ** err)
516 {
517         return get_account_bool (self, name, key, TRUE, err);
518 }
519
520
521 gint
522 modest_account_mgr_get_account_bool (ModestAccountMgr * self,
523                                      const gchar * name, const gchar * key,
524                                      GError ** err)
525 {
526         return get_account_bool (self, name, key, FALSE, err);
527 }
528
529
530 static gboolean
531 set_account_string (ModestAccountMgr * self, const gchar * name,
532                     const gchar * key, const gchar * val,
533                     gboolean server_account, GError ** err)
534 {
535         ModestAccountMgrPrivate *priv;
536
537         gchar *keyname;
538         gboolean retval;
539
540         g_return_val_if_fail (self, FALSE);
541         g_return_val_if_fail (name, FALSE);
542         g_return_val_if_fail (key, FALSE);
543
544         if (server_account)
545                 keyname = get_server_account_keyname (name, key);
546         else
547                 keyname = get_account_keyname (name, key);
548
549         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
550
551         retval = modest_conf_set_string (priv->modest_conf, keyname, val,
552                                          err);
553
554         g_free (keyname);
555         return retval;
556 }
557
558
559 gboolean
560 modest_account_mgr_set_server_account_string (ModestAccountMgr * self,
561                                               const gchar * name,
562                                               const gchar * key,
563                                               const gchar * val,
564                                               GError ** err)
565 {
566         return set_account_string (self, name, key, val, TRUE, err);
567 }
568
569
570 gboolean
571 modest_account_mgr_set_account_string (ModestAccountMgr * self,
572                                        const gchar * name, const gchar * key,
573                                        const gchar * val, GError ** err)
574 {
575         return set_account_string (self, name, key, val, FALSE, err);
576 }
577
578
579 static gboolean
580 set_account_int (ModestAccountMgr * self, const gchar * name,
581                  const gchar * key, gboolean server_account, int val,
582                  GError ** err)
583 {
584         ModestAccountMgrPrivate *priv;
585
586         gchar *keyname;
587         gboolean retval;
588
589         g_return_val_if_fail (self, FALSE);
590         g_return_val_if_fail (name, FALSE);
591         g_return_val_if_fail (key, FALSE);
592
593         if (server_account)
594                 keyname = get_server_account_keyname (name, key);
595         else
596                 keyname = get_account_keyname (name, key);
597
598         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
599
600         retval = modest_conf_set_int (priv->modest_conf, keyname, val, err);
601
602         g_free (keyname);
603         return retval;
604 }
605
606
607 gboolean
608 modest_account_mgr_set_server_account_int (ModestAccountMgr * self,
609                                            const gchar * name,
610                                            const gchar * key, int val,
611                                            GError ** err)
612 {
613         return set_account_int (self, name, key, val, TRUE, err);
614 }
615
616
617 gboolean
618 modest_account_mgr_set_account_int (ModestAccountMgr * self,
619                                     const gchar * name, const gchar * key,
620                                     int val, GError ** err)
621 {
622         return set_account_int (self, name, key, val, FALSE, err);
623 }
624
625
626 static gboolean
627 set_account_bool (ModestAccountMgr * self, const gchar * name,
628                   const gchar * key, gboolean server_account, gboolean val,
629                   GError ** err)
630 {
631         ModestAccountMgrPrivate *priv;
632
633         gchar *keyname;
634         gboolean retval;
635
636         g_return_val_if_fail (self, FALSE);
637         g_return_val_if_fail (name, FALSE);
638         g_return_val_if_fail (key, FALSE);
639
640         if (server_account)
641                 keyname = get_server_account_keyname (name, key);
642         else
643                 keyname = get_account_keyname (name, key);
644
645         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
646
647         retval = modest_conf_set_bool (priv->modest_conf, keyname, val, err);
648
649         g_free (keyname);
650         return retval;
651 }
652
653
654 gboolean
655 modest_account_mgr_set_server_account_bool (ModestAccountMgr * self,
656                                             const gchar * name,
657                                             const gchar * key, gboolean val,
658                                             GError ** err)
659 {
660         return set_account_bool (self, name, key, val, TRUE, err);
661 }
662
663
664 gboolean
665 modest_account_mgr_set_account_bool (ModestAccountMgr * self,
666                                      const gchar * name, const gchar * key,
667                                      gboolean val, GError ** err)
668 {
669         return set_account_bool (self, name, key, val, FALSE, err);
670 }
671
672
673 gboolean
674 account_exists (ModestAccountMgr * self, const gchar * name,
675                 gboolean server_account, GError ** err)
676 {
677         ModestAccountMgrPrivate *priv;
678
679         gchar *keyname;
680         gboolean retval;
681
682         g_return_val_if_fail (self, FALSE);
683         g_return_val_if_fail (name, FALSE);
684
685         if (server_account)
686                 keyname = get_server_account_keyname (name, NULL);
687         else
688                 keyname = get_account_keyname (name, NULL);
689
690         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
691         retval = modest_conf_key_exists (priv->modest_conf, keyname, err);
692
693         g_free (keyname);
694         return retval;
695 }
696
697
698 gboolean
699 modest_account_mgr_server_account_exists (ModestAccountMgr * self,
700                                           const gchar * name, GError ** err)
701 {
702         return account_exists (self, name, TRUE, err);
703 }
704
705
706 gboolean
707 modest_account_mgr_account_exists (ModestAccountMgr * self,
708                                    const gchar * name, GError ** err)
709 {
710         return account_exists (self, name, FALSE, err);
711 }
712
713
714 /* must be freed by caller */
715 static gchar *
716 get_account_keyname (const gchar * accname, const gchar * name)
717 {
718         if (name)
719                 return g_strconcat
720                         (MODEST_ACCOUNT_NAMESPACE, "/",
721                          accname, "/", name, NULL);
722         else
723                 return g_strconcat
724                         (MODEST_ACCOUNT_NAMESPACE, "/", accname, NULL);
725 }
726
727
728 /* must be freed by caller */
729 static gchar *
730 get_server_account_keyname (const gchar * accname, const gchar * name)
731 {
732         if (name)
733                 return g_strconcat
734                         (MODEST_SERVER_ACCOUNT_NAMESPACE, "/",
735                          accname, "/", name, NULL);
736         else
737                 return g_strconcat
738                         (MODEST_SERVER_ACCOUNT_NAMESPACE, "/", accname, NULL);
739 }