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