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