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