* modest_ui_new now returns ModestUI* instead of GObject
[modest] / src / modest-identity-mgr.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30
31 /* modest-identity-mgr.c */
32
33 #include <string.h>
34 #include "modest-marshal.h"
35 #include "modest-identity-mgr.h"
36
37 /* 'private'/'protected' functions */
38 static void modest_identity_mgr_class_init (ModestIdentityMgrClass * klass);
39 static void modest_identity_mgr_init (ModestIdentityMgr * obj);
40 static void modest_identity_mgr_finalize (GObject * obj);
41
42 static gchar *get_identity_keyname (const gchar * accname,
43                                     const gchar * name);
44
45 /* list my signals */
46 enum {
47         IDENTITY_CHANGE_SIGNAL,
48         IDENTITY_REMOVE_SIGNAL,
49         IDENTITY_ADD_SIGNAL,
50         LAST_SIGNAL
51 };
52
53 typedef struct _ModestIdentityMgrPrivate ModestIdentityMgrPrivate;
54 struct _ModestIdentityMgrPrivate {
55         ModestConf *modest_conf;
56         GSList *current_identities;
57 };
58
59 #define MODEST_IDENTITY_MGR_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
60                                                 MODEST_TYPE_IDENTITY_MGR, \
61                                                 ModestIdentityMgrPrivate))
62 /* globals */
63 static GObjectClass *parent_class = NULL;
64
65 /* uncomment the following if you have defined any signals */
66 static guint signals[LAST_SIGNAL] = {0};
67
68
69 static GSList *
70 delete_account_from_list (GSList *list, const gchar *name)
71 {
72         GSList *iter, *result;
73
74         iter = list;
75         result = list;
76         while (iter) {
77                 if (!strcmp (name, iter->data)) {
78                         result = g_slist_delete_link (list, iter);
79                         break;
80                 }
81
82                 iter = g_slist_next (iter);
83         }
84         return result;
85 }
86
87 static GSList *
88 find_account_in_list (GSList *list, const gchar *name)
89 {
90         GSList *iter, *result;
91
92         iter = list;
93         result = list;
94         while (iter) {
95                 if (!strcmp (name, iter->data)) {
96                         return iter;
97                         break;
98                 }
99
100                 iter = g_slist_next (iter);
101         }
102         return NULL;
103 }
104
105
106 static void
107 modest_identity_mgr_check_change (ModestConf *conf,
108                                  const gchar *key,
109                                  const gchar *new_value,
110                                  gpointer userdata)
111 {
112         ModestIdentityMgr *id_mgr = userdata;
113         ModestIdentityMgrPrivate *priv = MODEST_IDENTITY_MGR_GET_PRIVATE(id_mgr);
114         gchar *subkey;
115         gchar *param;
116
117         if ((strlen(key) > strlen(MODEST_IDENTITY_NAMESPACE "/")
118              && g_str_has_prefix(key, MODEST_IDENTITY_NAMESPACE))) {
119                 subkey = g_strdup(key + strlen(MODEST_IDENTITY_NAMESPACE "/"));
120                 if (! strstr(subkey, "/")) { /* no more '/' means an entry was modified */
121                         if (!new_value) {
122                                 priv->current_identities =
123                                         delete_account_from_list (priv->current_identities, subkey);
124                                 g_signal_emit(id_mgr, signals[IDENTITY_REMOVE_SIGNAL], 0, subkey);
125                         }
126                 }
127                 else {
128                         param = strstr(subkey, "/");
129                         param[0] = 0;
130                         param++;
131
132                         if (!find_account_in_list(priv->current_identities, subkey)) {
133                                 priv->current_identities =
134                                         g_slist_prepend(priv->current_identities, g_strdup(subkey));
135                                 g_signal_emit(id_mgr, signals[IDENTITY_ADD_SIGNAL], 0, subkey);
136                         }
137                         g_signal_emit(id_mgr, signals[IDENTITY_CHANGE_SIGNAL], 0, subkey, param, new_value);
138                 }
139                 g_free(subkey);
140         }
141 }
142
143 GType
144 modest_identity_mgr_get_type (void)
145 {
146         static GType my_type = 0;
147
148         if (!my_type) {
149                 static const GTypeInfo my_info = {
150                         sizeof (ModestIdentityMgrClass),
151                         NULL,   /* base init */
152                         NULL,   /* base finalize */
153                         (GClassInitFunc) modest_identity_mgr_class_init,
154                         NULL,   /* class finalize */
155                         NULL,   /* class data */
156                         sizeof (ModestIdentityMgr),
157                         1,      /* n_preallocs */
158                         (GInstanceInitFunc) modest_identity_mgr_init,
159                 };
160
161                 my_type = g_type_register_static (G_TYPE_OBJECT,
162                                                   "ModestIdentityMgr",
163                                                   &my_info, 0);
164         }
165         return my_type;
166 }
167
168 static void
169 modest_identity_mgr_class_init (ModestIdentityMgrClass * klass)
170 {
171         GObjectClass *gobject_class;
172         GType paramtypes[3] = {G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER};
173
174         gobject_class = (GObjectClass *) klass;
175
176         parent_class = g_type_class_peek_parent (klass);
177         gobject_class->finalize = modest_identity_mgr_finalize;
178
179         g_type_class_add_private (gobject_class,
180                                   sizeof (ModestIdentityMgrPrivate));
181
182         /* signal definitions */
183         signals[IDENTITY_ADD_SIGNAL] =
184                 g_signal_newv ("identity-add",
185                                G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
186                                NULL, NULL, NULL,
187                                g_cclosure_marshal_VOID__POINTER,
188                                G_TYPE_NONE, 1, paramtypes);
189
190         signals[IDENTITY_REMOVE_SIGNAL] =
191                 g_signal_newv ("identity-remove",
192                                G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
193                                NULL, NULL, NULL,
194                                g_cclosure_marshal_VOID__POINTER,
195                                G_TYPE_NONE, 1, paramtypes);
196         signals[IDENTITY_CHANGE_SIGNAL] =
197                 g_signal_newv ("identity-change",
198                                G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
199                                NULL, NULL, NULL,
200                                modest_marshal_VOID__POINTER_POINTER_POINTER,
201                                G_TYPE_NONE, 3, paramtypes);
202 }
203
204
205 static void
206 modest_identity_mgr_init (ModestIdentityMgr * obj)
207 {
208         ModestIdentityMgrPrivate *priv =
209                 MODEST_IDENTITY_MGR_GET_PRIVATE (obj);
210         priv->modest_conf = NULL;
211 }
212
213 static void
214 modest_identity_mgr_finalize (GObject * obj)
215 {
216         ModestIdentityMgr *self = MODEST_IDENTITY_MGR (obj);
217         ModestIdentityMgrPrivate *priv =
218                 MODEST_IDENTITY_MGR_GET_PRIVATE (self);
219
220         g_object_unref (G_OBJECT (priv->modest_conf));
221         priv->modest_conf = NULL;
222 }
223
224 GObject *
225 modest_identity_mgr_new (ModestConf * conf)
226 {
227         GObject *obj;
228         ModestIdentityMgrPrivate *priv;
229
230         g_return_val_if_fail (conf, NULL);
231
232         obj = G_OBJECT (g_object_new (MODEST_TYPE_IDENTITY_MGR, NULL));
233         priv = MODEST_IDENTITY_MGR_GET_PRIVATE (obj);
234
235         /*
236          * increase the ref count on the modest_conf. Normally, the
237          * ModestConf should outlive the ModestIdentityMgr though
238          */
239         g_object_ref (G_OBJECT (priv->modest_conf = conf));
240
241         priv->current_identities = modest_identity_mgr_identity_names (MODEST_IDENTITY_MGR(obj), NULL);
242
243         g_signal_connect(G_OBJECT(conf),
244                          "key-changed",
245                          G_CALLBACK (modest_identity_mgr_check_change),
246                          obj);
247         return obj;
248 }
249
250
251 gboolean
252 modest_identity_mgr_remove_identity (ModestIdentityMgr * self,
253                                      const gchar * name, GError ** err)
254 {
255         ModestIdentityMgrPrivate *priv;
256         gchar *key;
257         gboolean retval;
258
259         g_return_val_if_fail (self, FALSE);
260         g_return_val_if_fail (name, FALSE);
261
262         if (!modest_identity_mgr_identity_exists (self, name, err)) {
263                 g_warning ("identity doest not exist");
264                 return FALSE;
265         }
266
267         priv = MODEST_IDENTITY_MGR_GET_PRIVATE (self);
268         key = get_identity_keyname (name, NULL);
269
270         retval = modest_conf_remove_key (priv->modest_conf, key, NULL);
271
272         g_free (key);
273         return retval;
274 }
275
276
277 static const gchar *
278 null_means_empty (const gchar * str)
279 {
280         return str ? str : "";
281 }
282
283
284 gboolean
285 modest_identity_mgr_add_identity (ModestIdentityMgr * self,
286                                   const gchar    * name,
287                                   const gchar    * realname,
288                                   const gchar    * email,
289                                   const gchar    * replyto,
290                                   const gchar    * signature,
291                                   const gboolean use_signature,
292                                   const gchar    * id_via,
293                                   const gboolean use_id_via)
294 {
295         ModestIdentityMgrPrivate *priv;
296         gchar *id_key, *key;
297
298         g_return_val_if_fail (self, FALSE);
299         g_return_val_if_fail (name, FALSE);
300
301         /* TODO: check already exists */
302
303         priv = MODEST_IDENTITY_MGR_GET_PRIVATE (self);
304         id_key = g_strconcat (MODEST_IDENTITY_NAMESPACE, "/", name, NULL);
305
306         if (modest_conf_key_exists (priv->modest_conf, id_key, NULL)) {
307                 g_warning ("identity %s already exists", name);
308                 //g_free (id_key);
309                 //return FALSE;
310         }
311
312         /* realname */
313         key = g_strconcat (id_key, "/", MODEST_IDENTITY_REALNAME, NULL);
314         modest_conf_set_string (priv->modest_conf, key,
315                                 null_means_empty (realname), NULL);
316         g_free (key);
317
318         /* email */
319         key = g_strconcat (id_key, "/", MODEST_IDENTITY_EMAIL, NULL);
320         modest_conf_set_string (priv->modest_conf, key,
321                                 null_means_empty (email), NULL);
322         g_free (key);
323
324         /* replyto */
325         key = g_strconcat (id_key, "/", MODEST_IDENTITY_REPLYTO, NULL);
326         modest_conf_set_string (priv->modest_conf, key,
327                                 null_means_empty (replyto), NULL);
328         g_free (key);
329
330         /* signature */
331         key = g_strconcat (id_key, "/", MODEST_IDENTITY_SIGNATURE, NULL);
332         modest_conf_set_string (priv->modest_conf, key,
333                                 null_means_empty (signature), NULL);
334         g_free (key);
335
336         /* use_signature */
337         key = g_strconcat (id_key, "/", MODEST_IDENTITY_USE_SIGNATURE, NULL);
338         modest_conf_set_bool (priv->modest_conf, key, use_signature, NULL);
339         g_free (key);
340
341         /* id_via */
342         key = g_strconcat (id_key, "/", MODEST_IDENTITY_ID_VIA, NULL);
343         modest_conf_set_string (priv->modest_conf, key,
344                                 null_means_empty (id_via), NULL);
345         g_free (key);
346
347         /* use_id_via */
348         key = g_strconcat (id_key, "/", MODEST_IDENTITY_USE_ID_VIA, NULL);
349         modest_conf_set_bool (priv->modest_conf, key, use_id_via, NULL);
350         g_free (key);
351
352         g_free (id_key);
353
354         return TRUE;            /* FIXME: better error checking */
355 }
356
357 /* strip the first /n/ character from each element */
358 /* caller must make sure all elements are strings with
359  * length >= n, and also that data can be freed.
360  */
361 /* this function is copied from modest-account-mgr. Maybe it should be moved
362  * to modest-list-utils or the like...
363  */
364 static GSList *
365 strip_prefix_from_elements (GSList * lst, guint n)
366 {
367         GSList *cursor = lst;
368
369         while (cursor) {
370                 gchar *str = (gchar *) cursor->data;
371
372                 cursor->data = g_strdup (str + n);
373                 g_free (str);
374                 cursor = cursor->next;
375         }
376         return lst;
377 }
378
379 GSList *
380 modest_identity_mgr_identity_names (ModestIdentityMgr * self, GError ** err)
381 {
382         GSList *identities;
383         ModestIdentityMgrPrivate *priv;
384         const size_t prefix_len = strlen (MODEST_IDENTITY_NAMESPACE "/");
385
386
387         g_return_val_if_fail (self, NULL);
388
389         priv = MODEST_IDENTITY_MGR_GET_PRIVATE (self);
390
391         identities = modest_conf_list_subkeys (priv->modest_conf,
392                                                MODEST_IDENTITY_NAMESPACE,
393                                                err);
394         return strip_prefix_from_elements (identities, prefix_len);
395 }
396
397
398 gchar *
399 modest_identity_mgr_get_identity_string (ModestIdentityMgr * self,
400                                          const gchar * name,
401                                          const gchar * key, GError ** err)
402 {
403         ModestIdentityMgrPrivate *priv;
404
405         gchar *keyname;
406         gchar *retval;
407
408         g_return_val_if_fail (self, NULL);
409         g_return_val_if_fail (name, NULL);
410         g_return_val_if_fail (key, NULL);
411
412         keyname = get_identity_keyname (name, key);
413
414         priv = MODEST_IDENTITY_MGR_GET_PRIVATE (self);
415         retval = modest_conf_get_string (priv->modest_conf, keyname, err);
416         g_free (keyname);
417
418         return retval;
419 }
420
421
422 gint
423 modest_identity_mgr_get_identity_int (ModestIdentityMgr * self,
424                                       const gchar * name, const gchar * key,
425                                       GError ** err)
426 {
427         ModestIdentityMgrPrivate *priv;
428
429         gchar *keyname;
430         gint retval;
431
432         g_return_val_if_fail (self, -1);
433         g_return_val_if_fail (name, -1);
434         g_return_val_if_fail (key, -1);
435
436         keyname = get_identity_keyname (name, key);
437         priv = MODEST_IDENTITY_MGR_GET_PRIVATE (self);
438         retval = modest_conf_get_int (priv->modest_conf, keyname, err);
439         g_free (keyname);
440
441         return retval;
442 }
443
444
445
446 gboolean
447 modest_identity_mgr_get_identity_bool (ModestIdentityMgr * self,
448                                        const gchar * name, const gchar * key,
449                                        GError ** err)
450 {
451         ModestIdentityMgrPrivate *priv;
452
453         gchar *keyname;
454         gboolean retval;
455
456         g_return_val_if_fail (self, FALSE);
457         g_return_val_if_fail (name, FALSE);
458         g_return_val_if_fail (key, FALSE);
459
460         keyname = get_identity_keyname (name, key);
461
462         priv = MODEST_IDENTITY_MGR_GET_PRIVATE (self);
463         retval = modest_conf_get_bool (priv->modest_conf, keyname, err);
464         g_free (keyname);
465
466         return retval;
467 }
468
469
470 gboolean
471 modest_identity_mgr_set_identity_string (ModestIdentityMgr * self,
472                                          const gchar * name,
473                                          const gchar * key, const gchar * val,
474                                          GError ** err)
475 {
476         ModestIdentityMgrPrivate *priv;
477
478         gchar *keyname;
479         gboolean retval;
480
481         g_return_val_if_fail (self, FALSE);
482         g_return_val_if_fail (name, FALSE);
483         g_return_val_if_fail (key, FALSE);
484
485         keyname = get_identity_keyname (name, key);
486
487         priv = MODEST_IDENTITY_MGR_GET_PRIVATE (self);
488
489         retval = modest_conf_set_string (priv->modest_conf, keyname, val,
490                                          err);
491
492         g_free (keyname);
493         return retval;
494 }
495
496
497 gboolean
498 modest_identity_mgr_set_identity_int (ModestIdentityMgr * self,
499                                       const gchar * name, const gchar * key,
500                                       const gint val, GError ** err)
501 {
502         ModestIdentityMgrPrivate *priv;
503
504         gchar *keyname;
505         gboolean retval;
506
507         g_return_val_if_fail (self, FALSE);
508         g_return_val_if_fail (name, FALSE);
509         g_return_val_if_fail (key, FALSE);
510
511         keyname = get_identity_keyname (name, key);
512
513         priv = MODEST_IDENTITY_MGR_GET_PRIVATE (self);
514
515         retval = modest_conf_set_int (priv->modest_conf, keyname, val, err);
516
517         g_free (keyname);
518         return retval;
519 }
520
521
522 gboolean
523 modest_identity_mgr_set_identity_bool (ModestIdentityMgr * self,
524                                        const gchar * name, const gchar * key,
525                                        gboolean val, GError ** err)
526 {
527         ModestIdentityMgrPrivate *priv;
528
529         gchar *keyname;
530         gboolean retval;
531
532         g_return_val_if_fail (self, FALSE);
533         g_return_val_if_fail (name, FALSE);
534         g_return_val_if_fail (key, FALSE);
535
536         keyname = get_identity_keyname (name, key);
537
538         priv = MODEST_IDENTITY_MGR_GET_PRIVATE (self);
539
540         retval = modest_conf_set_bool (priv->modest_conf, keyname, val, err);
541
542         g_free (keyname);
543         return retval;
544 }
545
546
547 gboolean
548 modest_identity_mgr_identity_exists (ModestIdentityMgr * self,
549                                      const gchar * name, GError ** err)
550 {
551         ModestIdentityMgrPrivate *priv;
552
553         gchar *keyname;
554         gboolean retval;
555
556         g_return_val_if_fail (self, FALSE);
557         g_return_val_if_fail (name, FALSE);
558
559         keyname = get_identity_keyname (name, NULL);
560
561         priv = MODEST_IDENTITY_MGR_GET_PRIVATE (self);
562         retval = modest_conf_key_exists (priv->modest_conf, keyname, err);
563
564         g_free (keyname);
565         return retval;
566 }
567
568
569 /* must be freed by caller */
570 static gchar *
571 get_identity_keyname (const gchar * idname, const gchar * name)
572 {
573         if (name)
574                 return g_strconcat
575                         (MODEST_IDENTITY_NAMESPACE, "/",
576                          idname, "/", name, NULL);
577         else
578                 return g_strconcat
579                         (MODEST_IDENTITY_NAMESPACE, "/", idname, NULL);
580 }