* Fixes NB#65999 note that the translation is still not available
[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-runtime.h>
33 #include <modest-account-mgr.h>
34 #include <modest-account-mgr-priv.h>
35 #include <modest-account-mgr-helpers.h>
36
37 /* 'private'/'protected' functions */
38 static void modest_account_mgr_class_init (ModestAccountMgrClass * klass);
39 static void modest_account_mgr_init       (ModestAccountMgr * obj);
40 static void modest_account_mgr_finalize   (GObject * obj);
41 static void modest_account_mgr_base_init  (gpointer g_class);
42
43 static const gchar *_modest_account_mgr_get_account_keyname_cached (ModestAccountMgrPrivate *priv, 
44                                                                     const gchar* account_name,
45                                                                     const gchar *name, 
46                                                                     gboolean is_server);
47
48 static gboolean modest_account_mgr_unset_default_account (ModestAccountMgr *self);
49
50 /* list my signals */
51 enum {
52         ACCOUNT_INSERTED_SIGNAL,
53         ACCOUNT_CHANGED_SIGNAL,
54         ACCOUNT_REMOVED_SIGNAL,
55         ACCOUNT_BUSY_SIGNAL,
56         DEFAULT_ACCOUNT_CHANGED_SIGNAL,
57         DISPLAY_NAME_CHANGED_SIGNAL,
58         LAST_SIGNAL
59 };
60
61 /* globals */
62 static GObjectClass *parent_class = NULL;
63 static guint signals[LAST_SIGNAL] = {0};
64
65 GType
66 modest_account_mgr_get_type (void)
67 {
68         static GType my_type = 0;
69
70         if (!my_type) {
71                 static const GTypeInfo my_info = {
72                         sizeof (ModestAccountMgrClass),
73                         modest_account_mgr_base_init,   /* base init */
74                         NULL,   /* base finalize */
75                         (GClassInitFunc) modest_account_mgr_class_init,
76                         NULL,   /* class finalize */
77                         NULL,   /* class data */
78                         sizeof (ModestAccountMgr),
79                         1,      /* n_preallocs */
80                         (GInstanceInitFunc) modest_account_mgr_init,
81                         NULL
82                 };
83
84                 my_type = g_type_register_static (G_TYPE_OBJECT,
85                                                   "ModestAccountMgr",
86                                                   &my_info, 0);
87         }
88         return my_type;
89 }
90
91 static void 
92 modest_account_mgr_base_init (gpointer g_class)
93 {
94         static gboolean modest_account_mgr_initialized = FALSE;
95
96         if (!modest_account_mgr_initialized) {
97                 /* signal definitions */
98                 signals[ACCOUNT_INSERTED_SIGNAL] =
99                         g_signal_new ("account_inserted",
100                                       MODEST_TYPE_ACCOUNT_MGR,
101                                       G_SIGNAL_RUN_FIRST,
102                                       G_STRUCT_OFFSET(ModestAccountMgrClass, account_inserted),
103                                       NULL, NULL,
104                                       g_cclosure_marshal_VOID__STRING,
105                                       G_TYPE_NONE, 1, G_TYPE_STRING);
106
107                 signals[ACCOUNT_REMOVED_SIGNAL] =
108                         g_signal_new ("account_removed",
109                                       MODEST_TYPE_ACCOUNT_MGR,
110                                       G_SIGNAL_RUN_FIRST,
111                                       G_STRUCT_OFFSET(ModestAccountMgrClass, account_removed),
112                                       NULL, NULL,
113                                       g_cclosure_marshal_VOID__STRING,
114                                       G_TYPE_NONE, 1, G_TYPE_STRING);
115
116                 signals[ACCOUNT_CHANGED_SIGNAL] =
117                         g_signal_new ("account_changed",
118                                       MODEST_TYPE_ACCOUNT_MGR,
119                                       G_SIGNAL_RUN_FIRST,
120                                       G_STRUCT_OFFSET(ModestAccountMgrClass, account_changed),
121                                       NULL, NULL,
122                                       modest_marshal_VOID__STRING_INT,
123                                       G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
124
125                 signals[ACCOUNT_BUSY_SIGNAL] =
126                         g_signal_new ("account_busy_changed",
127                                       MODEST_TYPE_ACCOUNT_MGR,
128                                       G_SIGNAL_RUN_FIRST,
129                                       G_STRUCT_OFFSET(ModestAccountMgrClass, account_busy_changed),
130                                       NULL, NULL,
131                                       modest_marshal_VOID__STRING_BOOLEAN,
132                                       G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
133
134                 signals[DEFAULT_ACCOUNT_CHANGED_SIGNAL] =
135                         g_signal_new ("default_account_changed",
136                                       MODEST_TYPE_ACCOUNT_MGR,
137                                       G_SIGNAL_RUN_FIRST,
138                                       G_STRUCT_OFFSET(ModestAccountMgrClass, default_account_changed),
139                                       NULL, NULL,
140                                       g_cclosure_marshal_VOID__VOID,
141                                       G_TYPE_NONE, 0);
142
143                 signals[DISPLAY_NAME_CHANGED_SIGNAL] =
144                         g_signal_new ("display_name_changed",
145                                       MODEST_TYPE_ACCOUNT_MGR,
146                                       G_SIGNAL_RUN_FIRST,
147                                       G_STRUCT_OFFSET(ModestAccountMgrClass, display_name_changed),
148                                       NULL, NULL,
149                                       g_cclosure_marshal_VOID__STRING,
150                                       G_TYPE_NONE, 1, G_TYPE_STRING);
151
152                 modest_account_mgr_initialized = TRUE;
153         }
154 }
155
156 static void
157 modest_account_mgr_class_init (ModestAccountMgrClass * klass)
158 {
159         GObjectClass *gobject_class;
160         gobject_class = (GObjectClass *) klass;
161
162         parent_class = g_type_class_peek_parent (klass);
163         gobject_class->finalize = modest_account_mgr_finalize;
164
165         g_type_class_add_private (gobject_class,
166                                   sizeof (ModestAccountMgrPrivate));
167 }
168
169
170 static void
171 modest_account_mgr_init (ModestAccountMgr * obj)
172 {
173         ModestAccountMgrPrivate *priv =
174                 MODEST_ACCOUNT_MGR_GET_PRIVATE (obj);
175
176         priv->modest_conf   = NULL;
177         priv->busy_accounts = NULL;
178         priv->timeout       = 0;
179         
180         priv->notification_id_accounts = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_free);
181
182         /* we maintain hashes for the modest-conf keys we build from account name
183          * + key. many seem to be used often, and generating them showed up high
184          * in oprofile */
185         /* both hashes are hashes to hashes;
186          * account-key => keyname ==> account-key-name
187          */     
188         priv->server_account_key_hash = g_hash_table_new_full (g_str_hash,
189                                                                g_str_equal,
190                                                                g_free,
191                                                                (GDestroyNotify)g_hash_table_destroy);
192         priv->account_key_hash        = g_hash_table_new_full (g_str_hash,
193                                                                g_str_equal,
194                                                                g_free,
195                                                                (GDestroyNotify)g_hash_table_destroy);
196 }
197
198 static void
199 modest_account_mgr_finalize (GObject * obj)
200 {
201         ModestAccountMgrPrivate *priv = 
202                 MODEST_ACCOUNT_MGR_GET_PRIVATE (obj);
203
204         if (priv->notification_id_accounts) {
205                 /* TODO: forget dirs */
206
207                 g_hash_table_destroy (priv->notification_id_accounts);
208         }
209
210         if (priv->modest_conf) {
211                 g_object_unref (G_OBJECT(priv->modest_conf));
212                 priv->modest_conf = NULL;
213         }
214
215         if (priv->timeout)
216                 g_source_remove (priv->timeout);
217         priv->timeout = 0;
218
219         if (priv->server_account_key_hash) {
220                 g_hash_table_destroy (priv->server_account_key_hash);
221                 priv->server_account_key_hash = NULL;
222         }
223         
224         if (priv->account_key_hash) {
225                 g_hash_table_destroy (priv->account_key_hash);
226                 priv->account_key_hash = NULL;
227         }
228
229         G_OBJECT_CLASS(parent_class)->finalize (obj);
230 }
231
232
233 ModestAccountMgr *
234 modest_account_mgr_new (ModestConf *conf)
235 {
236         GObject *obj;
237         ModestAccountMgrPrivate *priv;
238
239         g_return_val_if_fail (conf, NULL);
240
241         obj = G_OBJECT (g_object_new (MODEST_TYPE_ACCOUNT_MGR, NULL));
242         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (obj);
243
244         g_object_ref (G_OBJECT(conf));
245         priv->modest_conf = conf;
246
247         return MODEST_ACCOUNT_MGR (obj);
248 }
249
250
251 static const gchar *
252 null_means_empty (const gchar * str)
253 {
254         return str ? str : "";
255 }
256
257
258 gboolean
259 modest_account_mgr_add_account (ModestAccountMgr *self,
260                                 const gchar *name,
261                                 const gchar *display_name,
262                                 const gchar *user_fullname,
263                                 const gchar *user_email,
264                                 const gchar *retrieve_type,
265                                 const gchar *store_account,
266                                 const gchar *transport_account,
267                                 gboolean enabled)
268 {
269         ModestAccountMgrPrivate *priv;
270         const gchar *key;
271         gboolean ok;
272         gchar *default_account;
273         GError *err = NULL;
274         
275         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
276         g_return_val_if_fail (name, FALSE);
277         g_return_val_if_fail (strchr(name, '/') == NULL, FALSE);
278         
279         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
280
281         /*
282          * we create the account by adding an account 'dir', with the name <name>,
283          * and in that the 'display_name' string key
284          */
285         key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_DISPLAY_NAME,
286                                                               FALSE);
287         if (modest_account_mgr_account_exists (self, key, FALSE)) {
288                 g_printerr ("modest: account already exists\n");
289                 return FALSE;
290         }
291         
292         ok = modest_conf_set_string (priv->modest_conf, key, name, &err);
293         if (!ok) {
294                 g_printerr ("modest: cannot set display name\n");
295                 if (err) {
296                         g_printerr ("modest: Error adding account conf: %s\n", err->message);
297                         g_error_free (err);
298                 }
299                 return FALSE;
300         }
301         
302         if (store_account) {
303                 key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_STORE_ACCOUNT,
304                                                                       FALSE);
305                 ok = modest_conf_set_string (priv->modest_conf, key, store_account, &err);
306                 if (!ok) {
307                         g_printerr ("modest: failed to set store account '%s'\n",
308                                     store_account);
309                         if (err) {
310                                 g_printerr ("modest: Error adding store account conf: %s\n", err->message);
311                                 g_error_free (err);
312                         }
313                         return FALSE;
314                 }
315         }
316         
317         if (transport_account) {
318                 key = _modest_account_mgr_get_account_keyname_cached (priv, name,
319                                                                       MODEST_ACCOUNT_TRANSPORT_ACCOUNT,
320                                                                       FALSE);
321                 ok = modest_conf_set_string (priv->modest_conf, key, transport_account, &err);
322                 if (!ok) {
323                         g_printerr ("modest: failed to set transport account '%s'\n",
324                                     transport_account);
325                         if (err) {
326                                 g_printerr ("modest: Error adding transport account conf: %s\n", err->message);
327                                 g_error_free (err);
328                         }       
329                         return FALSE;
330                 }
331         }
332
333         /* Make sure that leave-messages-on-server is enabled by default, 
334          * as per the UI spec, though it is only meaningful for accounts using POP.
335          * (possibly this gconf key should be under the server account): */
336         modest_account_mgr_set_bool (self, name, MODEST_ACCOUNT_LEAVE_ON_SERVER, TRUE, FALSE);
337         modest_account_mgr_set_bool (self, name, MODEST_ACCOUNT_ENABLED, enabled,FALSE);
338
339         /* Fill other data */
340         modest_account_mgr_set_string (self, name,
341                                        MODEST_ACCOUNT_DISPLAY_NAME, 
342                                        display_name, FALSE);
343         modest_account_mgr_set_string (self, name,
344                                        MODEST_ACCOUNT_FULLNAME, 
345                                        user_fullname, FALSE);
346         modest_account_mgr_set_string (self, name,
347                                        MODEST_ACCOUNT_EMAIL, 
348                                        user_email, FALSE);
349         modest_account_mgr_set_string (self, name,
350                                        MODEST_ACCOUNT_RETRIEVE, 
351                                        retrieve_type, FALSE);
352
353         /* Notify the observers */
354         g_signal_emit (self, signals[ACCOUNT_INSERTED_SIGNAL], 0, name);
355
356         /* if no default account has been defined yet, do so now */
357         default_account = modest_account_mgr_get_default_account (self);
358         if (!default_account)
359                 modest_account_mgr_set_default_account (self, name);
360         g_free (default_account);
361
362         return TRUE;
363 }
364
365
366 gboolean
367 modest_account_mgr_add_server_account (ModestAccountMgr * self,
368                                        const gchar *name, 
369                                        const gchar *hostname,
370                                        guint portnumber,
371                                        const gchar *username, 
372                                        const gchar *password,
373                                        ModestTransportStoreProtocol proto,
374                                        ModestConnectionProtocol security,
375                                        ModestAuthProtocol auth)
376 {
377         ModestAccountMgrPrivate *priv;
378         const gchar *key;
379         gboolean ok = TRUE;
380         GError *err = NULL;
381
382         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
383         g_return_val_if_fail (name, FALSE);
384         g_return_val_if_fail (strchr(name, '/') == NULL, FALSE);
385                               
386         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
387
388         /* hostname */
389         key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_HOSTNAME, TRUE);
390         if (modest_conf_key_exists (priv->modest_conf, key, &err)) {
391                 g_printerr ("modest: server account '%s' already exists\n", name);
392                 ok =  FALSE;
393         }
394         if (!ok)
395                 goto cleanup;
396         
397         modest_conf_set_string (priv->modest_conf, key, null_means_empty(hostname), &err);
398         if (err) {
399                 g_printerr ("modest: failed to set %s: %s\n", key, err->message);
400                 g_error_free (err);
401                 ok = FALSE;
402         }
403         if (!ok)
404                 goto cleanup;
405         
406         /* username */
407         key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_USERNAME, TRUE);
408         ok = modest_conf_set_string (priv->modest_conf, key, null_means_empty (username), &err);
409         if (err) {
410                 g_printerr ("modest: failed to set %s: %s\n", key, err->message);
411                 g_error_free (err);
412                 ok = FALSE;
413         }
414         if (!ok)
415                 goto cleanup;
416         
417         
418         /* password */
419         key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_PASSWORD, TRUE);
420         ok = modest_conf_set_string (priv->modest_conf, key, null_means_empty (password), &err);
421         if (err) {
422                 g_printerr ("modest: failed to set %s: %s\n", key, err->message);
423                 g_error_free (err);
424                 ok = FALSE;
425         }
426         if (!ok)
427                 goto cleanup;
428
429         /* proto */
430         key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_PROTO, TRUE);
431         ok = modest_conf_set_string (priv->modest_conf, key,
432                                      modest_protocol_info_get_transport_store_protocol_name(proto),
433                                      &err);
434         if (err) {
435                 g_printerr ("modest: failed to set %s: %s\n", key, err->message);
436                 g_error_free (err);
437                 ok = FALSE;
438         }
439         if (!ok)
440                 goto cleanup;
441
442
443         /* portnumber */
444         key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_PORT, TRUE);
445         ok = modest_conf_set_int (priv->modest_conf, key, portnumber, &err);
446         if (err) {
447                 g_printerr ("modest: failed to set %s: %s\n", key, err->message);
448                 g_error_free (err);
449                 ok = FALSE;
450         }
451         if (!ok)
452                 goto cleanup;
453
454         
455         /* auth mechanism */
456         key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_AUTH_MECH, TRUE);
457         ok = modest_conf_set_string (priv->modest_conf, key,
458                                      modest_protocol_info_get_auth_protocol_name (auth),
459                                      &err);
460         if (err) {
461                 g_printerr ("modest: failed to set %s: %s\n", key, err->message);
462                 g_error_free (err);
463                 ok = FALSE;
464         }
465         if (!ok)
466                 goto cleanup;
467         
468         /* Add the security settings: */
469         modest_account_mgr_set_server_account_security (self, name, security);
470         
471 cleanup:
472         if (!ok) {
473                 g_printerr ("modest: failed to add server account\n");
474                 return FALSE;
475         }
476
477         return TRUE;
478 }
479
480 /** modest_account_mgr_add_server_account_uri:
481  * Only used for mbox and maildir accounts.
482  */
483 gboolean
484 modest_account_mgr_add_server_account_uri (ModestAccountMgr * self,
485                                            const gchar *name, 
486                                            ModestTransportStoreProtocol proto,
487                                            const gchar *uri)
488 {
489         ModestAccountMgrPrivate *priv;
490         const gchar *key;
491         gboolean ok;
492         
493         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
494         g_return_val_if_fail (name, FALSE);
495         g_return_val_if_fail (strchr(name, '/') == NULL, FALSE);
496         g_return_val_if_fail (uri, FALSE);
497         
498         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
499         
500         /* proto */
501         key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_PROTO, TRUE);
502         ok = modest_conf_set_string (priv->modest_conf, key,
503                                      modest_protocol_info_get_transport_store_protocol_name(proto),
504                                      NULL);
505
506         if (!ok) {
507                 g_printerr ("modest: failed to set proto\n");
508                 return FALSE;
509         }
510         
511         /* uri */
512         key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_URI, TRUE);
513         ok = modest_conf_set_string (priv->modest_conf, key, uri, NULL);
514
515         if (!ok) {
516                 g_printerr ("modest: failed to set uri\n");
517                 return FALSE;
518         }
519         return TRUE;
520 }
521
522 /* 
523  * Utility function used by modest_account_mgr_remove_account
524  */
525 static void
526 real_remove_account (ModestConf *conf,
527                      const gchar *acc_name,
528                      gboolean server_account)
529 {
530         GError *err = NULL;
531         gchar *key;
532         
533         key = _modest_account_mgr_get_account_keyname (acc_name, NULL, server_account);
534         modest_conf_remove_key (conf, key, &err);
535
536         if (err) {
537                 g_printerr ("modest: error removing key: %s\n", err->message);
538                 g_error_free (err);
539         }
540         g_free (key);
541 }
542
543 gboolean
544 modest_account_mgr_remove_account (ModestAccountMgr * self,
545                                    const gchar* name)
546 {
547         ModestAccountMgrPrivate *priv;
548         gchar *default_account_name, *store_acc_name, *transport_acc_name;
549         gboolean default_account_deleted;
550
551         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
552         g_return_val_if_fail (name, FALSE);
553
554         if (!modest_account_mgr_account_exists (self, name, FALSE)) {
555                 g_printerr ("modest: %s: account '%s' does not exist\n", __FUNCTION__, name);
556                 return FALSE;
557         }
558
559         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
560         default_account_deleted = FALSE;
561
562         /* If this was the default, then remove that setting: */
563         default_account_name = modest_account_mgr_get_default_account (self);
564         if (default_account_name && (strcmp (default_account_name, name) == 0)) {
565                 modest_account_mgr_unset_default_account (self);
566                 default_account_deleted = TRUE;
567         }
568         g_free (default_account_name);
569
570         /* Delete transport and store accounts */
571         store_acc_name = modest_account_mgr_get_string (self, name, 
572                                                         MODEST_ACCOUNT_STORE_ACCOUNT, FALSE);
573         if (store_acc_name)
574                 real_remove_account (priv->modest_conf, store_acc_name, TRUE);
575
576         transport_acc_name = modest_account_mgr_get_string (self, name, 
577                                                             MODEST_ACCOUNT_TRANSPORT_ACCOUNT, FALSE);
578         if (transport_acc_name)
579                 real_remove_account (priv->modest_conf, transport_acc_name, TRUE);
580                         
581         /* Remove the modest account */
582         real_remove_account (priv->modest_conf, name, FALSE);
583
584         if (default_account_deleted) {  
585                 /* pick another one as the new default account. We do
586                    this *after* deleting the keys, because otherwise a
587                    call to account_names will retrieve also the
588                    deleted account */
589                 modest_account_mgr_set_first_account_as_default (self);
590         }
591         
592         /* Notify the observers. We do this *after* deleting
593            the keys, because otherwise a call to account_names
594            will retrieve also the deleted account */
595         g_signal_emit (G_OBJECT(self), signals[ACCOUNT_REMOVED_SIGNAL], 0, name);
596
597         return TRUE;
598 }
599
600
601
602 /* strip the first /n/ character from each element
603  * caller must make sure all elements are strings with
604  * length >= n, and also that data can be freed.
605  * change is in-place
606  */
607 static void
608 strip_prefix_from_elements (GSList * lst, guint n)
609 {
610         while (lst) {
611                 memmove (lst->data, lst->data + n,
612                          strlen(lst->data) - n + 1);
613                 lst = lst->next;
614         }
615 }
616
617
618 GSList*
619 modest_account_mgr_account_names (ModestAccountMgr * self, gboolean only_enabled)
620 {
621         GSList *accounts;
622         ModestAccountMgrPrivate *priv;
623         GError *err = NULL;
624         
625         const size_t prefix_len = strlen (MODEST_ACCOUNT_NAMESPACE "/");
626
627         g_return_val_if_fail (self, NULL);
628
629         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
630         accounts = modest_conf_list_subkeys (priv->modest_conf,
631                                              MODEST_ACCOUNT_NAMESPACE, &err);
632
633         if (err) {
634                 g_printerr ("modest: failed to get subkeys (%s): %s\n",
635                             MODEST_ACCOUNT_NAMESPACE, err->message);
636                 g_error_free (err);
637                 return NULL; /* assume accounts did not get value when err is set...*/
638         }
639         
640         strip_prefix_from_elements (accounts, prefix_len);
641                 
642         GSList *result = NULL;
643         
644         /* Unescape the keys to get the account names: */
645         GSList *iter = accounts;
646         while (iter) {
647                 if (!(iter->data))
648                         continue;
649                         
650                 const gchar* account_name_key = (const gchar*)iter->data;
651                 gchar* unescaped_name = account_name_key ? 
652                         modest_conf_key_unescape (account_name_key) 
653                         : NULL;
654                 
655                 gboolean add = TRUE;
656                 if (only_enabled) {
657                         if (unescaped_name && 
658                             !modest_account_mgr_get_bool (self, unescaped_name, 
659                                                           MODEST_ACCOUNT_ENABLED, FALSE))
660                                 add = FALSE;
661                 }
662                 
663                 /* Ignore modest accounts whose server accounts don't exist: 
664                  * (We could be getting this list while the account is being deleted, 
665                  * while the child server accounts have already been deleted, but the 
666                  * parent modest account already exists.
667                  */
668                 if (add) {
669                         gchar* server_account_name = modest_account_mgr_get_string
670                                 (self, account_name_key, MODEST_ACCOUNT_STORE_ACCOUNT,
671                                  FALSE);
672                         if (server_account_name) {
673                                 if (!modest_account_mgr_account_exists (self, server_account_name, TRUE))
674                                         add = FALSE;
675                                 g_free (server_account_name);
676                         }
677                 }
678                 
679                 if (add) {
680                         gchar* server_account_name = modest_account_mgr_get_string
681                                 (self, account_name_key, MODEST_ACCOUNT_TRANSPORT_ACCOUNT,
682                                  FALSE);
683                         if (server_account_name) {
684                                 if (!modest_account_mgr_account_exists (self, server_account_name, TRUE))
685                                         add = FALSE;
686                                 g_free (server_account_name);
687                         }
688                 }
689                 
690                 if (add)
691                         result = g_slist_append (result, unescaped_name);
692                 else 
693                         g_free (unescaped_name);
694
695                 g_free (iter->data);
696                 iter->data = NULL;
697                 
698                 iter = g_slist_next (iter);     
699         }
700         
701
702         /* we already freed the strings in the loop */
703         g_slist_free (accounts);
704         
705         accounts = NULL;
706         return result;
707 }
708
709
710 void
711 modest_account_mgr_free_account_names (GSList *account_names)
712 {
713         g_slist_foreach (account_names, (GFunc)g_free, NULL);
714         g_slist_free (account_names);
715 }
716
717
718
719 gchar *
720 modest_account_mgr_get_string (ModestAccountMgr *self, const gchar *name,
721                                const gchar *key, gboolean server_account) {
722
723         ModestAccountMgrPrivate *priv;
724
725         const gchar *keyname;
726         gchar *retval;
727         GError *err = NULL;
728
729         g_return_val_if_fail (self, NULL);
730         g_return_val_if_fail (name, NULL);
731         g_return_val_if_fail (key, NULL);
732
733         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
734         
735         keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, key, server_account);
736         
737         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
738         retval = modest_conf_get_string (priv->modest_conf, keyname, &err);     
739         if (err) {
740                 g_printerr ("modest: error getting string '%s': %s\n", keyname, err->message);
741                 g_error_free (err);
742                 retval = NULL;
743         }
744
745         return retval;
746 }
747
748
749 gint
750 modest_account_mgr_get_int (ModestAccountMgr *self, const gchar *name, const gchar *key,
751                             gboolean server_account)
752 {
753         ModestAccountMgrPrivate *priv;
754
755         const gchar *keyname;
756         gint retval;
757         GError *err = NULL;
758         
759         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), -1);
760         g_return_val_if_fail (name, -1);
761         g_return_val_if_fail (key, -1);
762
763         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
764
765         keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, key, server_account);
766         
767         retval = modest_conf_get_int (priv->modest_conf, keyname, &err);
768         if (err) {
769                 g_printerr ("modest: error getting int '%s': %s\n", keyname, err->message);
770                 g_error_free (err);
771                 retval = -1;
772         }
773
774         return retval;
775 }
776
777
778
779 gboolean
780 modest_account_mgr_get_bool (ModestAccountMgr * self, const gchar *account,
781                              const gchar * key, gboolean server_account)
782 {
783         ModestAccountMgrPrivate *priv;
784
785         const gchar *keyname;
786         gboolean retval;
787         GError *err = NULL;
788
789         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
790         g_return_val_if_fail (account, FALSE);
791         g_return_val_if_fail (key, FALSE);
792
793         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
794         ///keyname = _modest_account_mgr_get_account_keyname (account, key, server_account);
795
796         keyname = _modest_account_mgr_get_account_keyname_cached (priv, account, key, server_account);
797                 
798         retval = modest_conf_get_bool (priv->modest_conf, keyname, &err);               
799         if (err) {
800                 g_printerr ("modest: error getting bool '%s': %s\n", keyname, err->message);
801                 g_error_free (err);
802                 retval = FALSE;
803         }
804
805         return retval;
806 }
807
808
809
810 GSList * 
811 modest_account_mgr_get_list (ModestAccountMgr *self, const gchar *name,
812                              const gchar *key, ModestConfValueType list_type,
813                              gboolean server_account)
814 {
815         ModestAccountMgrPrivate *priv;
816
817         const gchar *keyname;
818         GSList *retval;
819         GError *err = NULL;
820         
821         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), NULL);
822         g_return_val_if_fail (name, NULL);
823         g_return_val_if_fail (key, NULL);
824         
825         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
826
827         keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, key,
828                                                                   server_account);
829         
830         retval = modest_conf_get_list (priv->modest_conf, keyname, list_type, &err);
831         if (err) {
832                 g_printerr ("modest: error getting list '%s': %s\n", keyname,
833                             err->message);
834                 g_error_free (err);
835                 retval = FALSE;
836         }
837         return retval;
838 }
839
840
841 gboolean
842 modest_account_mgr_set_string (ModestAccountMgr * self, 
843                                const gchar * name,
844                                const gchar * key, 
845                                const gchar * val, 
846                                gboolean server_account)
847 {
848         ModestAccountMgrPrivate *priv;
849
850         const gchar *keyname;
851         gboolean retval;
852         GError *err = NULL;
853
854         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
855         g_return_val_if_fail (name, FALSE);
856         g_return_val_if_fail (key, FALSE);
857
858         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
859
860         keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, key, server_account);
861         
862         retval = modest_conf_set_string (priv->modest_conf, keyname, val, &err);
863         if (err) {
864                 g_printerr ("modest: error setting string '%s': %s\n", keyname, err->message);
865                 g_error_free (err);
866                 retval = FALSE;
867         }
868         return retval;
869 }
870
871 gboolean
872 modest_account_mgr_set_int (ModestAccountMgr * self, const gchar * name,
873                             const gchar * key, int val, gboolean server_account)
874 {
875         ModestAccountMgrPrivate *priv;
876
877         const gchar *keyname;
878         gboolean retval;
879         GError *err = NULL;
880         
881         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
882         g_return_val_if_fail (name, FALSE);
883         g_return_val_if_fail (key, FALSE);
884
885         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
886
887         keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, key, server_account);
888         
889         retval = modest_conf_set_int (priv->modest_conf, keyname, val, &err);
890         if (err) {
891                 g_printerr ("modest: error setting int '%s': %s\n", keyname, err->message);
892                 g_error_free (err);
893                 retval = FALSE;
894         }
895         return retval;
896 }
897
898
899
900 gboolean
901 modest_account_mgr_set_bool (ModestAccountMgr * self, const gchar * name,
902                              const gchar * key, gboolean val, gboolean server_account)
903 {
904         ModestAccountMgrPrivate *priv;
905
906         const gchar *keyname;
907         gboolean retval;
908         GError *err = NULL;
909
910         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
911         g_return_val_if_fail (name, FALSE);
912         g_return_val_if_fail (key, FALSE);
913
914         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
915         keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, key, server_account);
916         
917         retval = modest_conf_set_bool (priv->modest_conf, keyname, val, &err);
918         if (err) {
919                 g_printerr ("modest: error setting bool '%s': %s\n", keyname, err->message);
920                 g_error_free (err);
921                 retval = FALSE;
922         }
923
924         return retval;
925 }
926
927
928 gboolean
929 modest_account_mgr_set_list (ModestAccountMgr *self,
930                              const gchar *name,
931                              const gchar *key,
932                              GSList *val,
933                              ModestConfValueType list_type,
934                              gboolean server_account)
935 {
936         ModestAccountMgrPrivate *priv;
937         const gchar *keyname;
938         GError *err = NULL;
939         gboolean retval;
940         
941         g_return_val_if_fail (self, FALSE);
942         g_return_val_if_fail (name, FALSE);
943         g_return_val_if_fail (key,  FALSE);
944         g_return_val_if_fail (val,  FALSE);
945
946         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
947
948         keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, key, server_account);
949         
950         retval = modest_conf_set_list (priv->modest_conf, keyname, val, list_type, &err);
951         if (err) {
952                 g_printerr ("modest: error setting list '%s': %s\n", keyname, err->message);
953                 g_error_free (err);
954                 retval = FALSE;
955         }
956
957         return retval;
958 }
959
960 gboolean
961 modest_account_mgr_account_exists (ModestAccountMgr * self, const gchar* name,
962                                    gboolean server_account)
963 {
964         ModestAccountMgrPrivate *priv;
965
966         const gchar *keyname;
967         gboolean retval;
968         GError *err = NULL;
969
970         g_return_val_if_fail (self, FALSE);
971         g_return_val_if_fail (name, FALSE);
972
973         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
974         keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, NULL, server_account);
975         retval = modest_conf_key_exists (priv->modest_conf, keyname, &err);
976         if (err) {
977                 g_printerr ("modest: error determining existance of '%s': %s\n", keyname,
978                             err->message);
979                 g_error_free (err);
980                 retval = FALSE;
981         }
982         return retval;
983 }
984
985 gboolean
986 modest_account_mgr_account_with_display_name_exists  (ModestAccountMgr *self, 
987                                                       const gchar *display_name)
988 {
989         GSList *account_names = NULL;
990         GSList *cursor = NULL;
991         
992         cursor = account_names = modest_account_mgr_account_names (self, 
993                                                                    TRUE /* enabled accounts, because disabled accounts are not user visible. */);
994
995         gboolean found = FALSE;
996         
997         /* Look at each non-server account to check their display names; */
998         while (cursor) {
999                 const gchar * account_name = (gchar*)cursor->data;
1000                 
1001                 ModestAccountData *account_data = modest_account_mgr_get_account_data (self, account_name);
1002                 if (!account_data) {
1003                         g_printerr ("modest: failed to get account data for %s\n", account_name);
1004                         continue;
1005                 }
1006
1007                 if(account_data->display_name && (strcmp (account_data->display_name, display_name) == 0)) {
1008                         found = TRUE;
1009                         break;
1010                 }
1011
1012                 modest_account_mgr_free_account_data (self, account_data);
1013                 cursor = cursor->next;
1014         }
1015         modest_account_mgr_free_account_names (account_names);
1016         account_names = NULL;
1017         
1018         return found;
1019 }
1020
1021
1022
1023
1024 gboolean 
1025 modest_account_mgr_unset (ModestAccountMgr *self, const gchar *name,
1026                           const gchar *key, gboolean server_account)
1027 {
1028         ModestAccountMgrPrivate *priv;
1029         
1030         const gchar *keyname;
1031         gboolean retval;
1032         GError *err = NULL;
1033         
1034         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
1035         g_return_val_if_fail (name, FALSE);
1036         g_return_val_if_fail (key, FALSE);
1037
1038         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
1039         keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, key, server_account);
1040
1041         retval = modest_conf_remove_key (priv->modest_conf, keyname, &err);
1042         if (err) {
1043                 g_printerr ("modest: error unsetting'%s': %s\n", keyname,
1044                             err->message);
1045                 g_error_free (err);
1046                 retval = FALSE;
1047         }
1048         return retval;
1049 }
1050
1051 gchar*
1052 _modest_account_mgr_account_from_key (const gchar *key, gboolean *is_account_key, gboolean *is_server_account)
1053 {
1054         /* Initialize input parameters: */
1055         if (is_account_key)
1056                 *is_account_key = FALSE;
1057
1058         if (is_server_account)
1059                 *is_server_account = FALSE;
1060
1061         const gchar* account_ns        = MODEST_ACCOUNT_NAMESPACE "/";
1062         const gchar* server_account_ns = MODEST_SERVER_ACCOUNT_NAMESPACE "/";
1063         gchar *cursor;
1064         gchar *account = NULL;
1065
1066         /* determine whether it's an account or a server account,
1067          * based on the prefix */
1068         if (g_str_has_prefix (key, account_ns)) {
1069
1070                 if (is_server_account)
1071                         *is_server_account = FALSE;
1072                 
1073                 account = g_strdup (key + strlen (account_ns));
1074
1075         } else if (g_str_has_prefix (key, server_account_ns)) {
1076
1077                 if (is_server_account)
1078                         *is_server_account = TRUE;
1079                 
1080                 account = g_strdup (key + strlen (server_account_ns));  
1081         } else
1082                 return NULL;
1083
1084         /* if there are any slashes left in the key, it's not
1085          * the toplevel entry for an account
1086          */
1087         cursor = strstr(account, "/");
1088         
1089         if (is_account_key && cursor)
1090                 *is_account_key = TRUE;
1091
1092         /* put a NULL where the first slash was */
1093         if (cursor)
1094                 *cursor = '\0';
1095
1096         if (account) {
1097                 /* The key is an escaped string, so unescape it to get the actual account name: */
1098                 gchar *unescaped_name = modest_conf_key_unescape (account);
1099                 g_free (account);
1100                 return unescaped_name;
1101         } else
1102                 return NULL;
1103 }
1104
1105
1106
1107
1108
1109 /* optimization: only with non-alphanum chars, escaping is needed */
1110 inline static gboolean
1111 is_alphanum (const gchar* str)
1112 {
1113         const gchar *cursor;
1114         for (cursor = str; cursor && *cursor; ++cursor) {
1115                 const char c = *cursor;
1116                 /* we cannot trust isalnum(3), because it might consider locales */
1117                 /*       numbers            ALPHA            alpha       */
1118                 if (!((c>=48 && c<=57)||(c>=65 && c<=90)||(c>=97 && c<=122)))
1119                         return FALSE;
1120         }
1121         return TRUE;
1122 }
1123                 
1124
1125
1126
1127 /* must be freed by caller */
1128 gchar *
1129 _modest_account_mgr_get_account_keyname (const gchar *account_name, const gchar* name,
1130                                          gboolean server_account)
1131 {
1132         gchar *retval = NULL;   
1133         gchar *namespace = server_account ? MODEST_SERVER_ACCOUNT_NAMESPACE : MODEST_ACCOUNT_NAMESPACE;
1134         gchar *escaped_account_name, *escaped_name;
1135         
1136         if (!account_name)
1137                 return g_strdup (namespace);
1138
1139         /* optimization: only escape names when need to be escaped */
1140         if (is_alphanum (account_name))
1141                 escaped_account_name = (gchar*)account_name;
1142         else
1143                 escaped_account_name = modest_conf_key_escape (account_name);
1144         
1145         if (is_alphanum (name))
1146                 escaped_name = (gchar*)name;
1147         else
1148                 escaped_name = modest_conf_key_escape (name);
1149         //////////////////////////////////////////////////////////////
1150
1151         if (escaped_account_name && escaped_name)
1152                 retval = g_strconcat (namespace, "/", escaped_account_name, "/", escaped_name, NULL);
1153         else if (escaped_account_name)
1154                 retval = g_strconcat (namespace, "/", escaped_account_name, NULL);
1155
1156         /* Sanity check: */
1157         if (!modest_conf_key_is_valid (retval)) {
1158                 g_warning ("%s: Generated conf key was invalid: %s", __FUNCTION__, retval);
1159                 g_free (retval);
1160                 retval = NULL;
1161         }
1162         
1163         /* g_free is only needed if we actually allocated anything */
1164         if (name != escaped_name)
1165                 g_free (escaped_name);
1166         if (account_name != escaped_account_name)
1167                 g_free (escaped_account_name);
1168
1169         return retval;
1170 }
1171
1172 static const gchar *
1173 _modest_account_mgr_get_account_keyname_cached (ModestAccountMgrPrivate *priv, 
1174                                                 const gchar* account_name,
1175                                                 const gchar *name, 
1176                                                 gboolean is_server)
1177 {
1178         GHashTable *hash = is_server ? priv->server_account_key_hash : priv->account_key_hash;
1179         GHashTable *account_hash;
1180         gchar *key = NULL;
1181         const gchar *search_name;
1182
1183         if (!account_name)
1184                 return is_server ? MODEST_SERVER_ACCOUNT_NAMESPACE : MODEST_ACCOUNT_NAMESPACE;
1185
1186         search_name = name ? name : "<dummy>";
1187         
1188         account_hash = g_hash_table_lookup (hash, account_name);        
1189         if (!account_hash) { /* no hash for this account yet? create it */
1190                 account_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);         
1191                 key = _modest_account_mgr_get_account_keyname (account_name, name, is_server);
1192                 g_hash_table_insert (account_hash, g_strdup(search_name), key);
1193                 g_hash_table_insert (hash, g_strdup(account_name), account_hash);
1194                 return key;
1195         }
1196         
1197         /* we have a hash for this account, but do we have the key? */  
1198         key = g_hash_table_lookup (account_hash, search_name);
1199         if (!key) {
1200                 key = _modest_account_mgr_get_account_keyname (account_name, name, is_server);
1201                 g_hash_table_insert (account_hash, g_strdup(search_name), key);
1202         }
1203         
1204         return key;
1205 }
1206
1207
1208 gboolean
1209 modest_account_mgr_has_accounts (ModestAccountMgr* self, gboolean enabled)
1210 {
1211         /* Check that at least one account exists: */
1212         GSList *account_names = modest_account_mgr_account_names (self,
1213                                                                   enabled);
1214         gboolean accounts_exist = account_names != NULL;
1215         
1216         modest_account_mgr_free_account_names (account_names);
1217         account_names = NULL;
1218         
1219         return accounts_exist;
1220 }
1221
1222 static int
1223 compare_account_name(gconstpointer a, gconstpointer b)
1224 {
1225         const gchar* account_name = (const gchar*) a;
1226         const gchar* account_name2 = (const gchar*) b;
1227         return strcmp(account_name, account_name2);
1228 }
1229
1230 void 
1231 modest_account_mgr_set_account_busy(ModestAccountMgr* self, 
1232                                     const gchar* account_name, 
1233                                     gboolean busy)
1234 {
1235         ModestAccountMgrPrivate* priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
1236         if (busy)
1237         {
1238                 GSList *account_names = modest_account_mgr_account_names (self, TRUE);
1239                 GSList* account = g_slist_find_custom(account_names, account_name, 
1240                                                       (GCompareFunc) compare_account_name);
1241
1242                 if (account && !modest_account_mgr_account_is_busy(self, account_name)) {
1243                         priv->busy_accounts = g_slist_append(priv->busy_accounts, g_strdup(account_name));
1244                         g_signal_emit (G_OBJECT(self), signals[ACCOUNT_BUSY_SIGNAL], 
1245                                        0, account_name, TRUE);
1246                 }
1247                 modest_account_mgr_free_account_names (account_names);
1248                 account_names = NULL;
1249         } else {
1250                 GSList* account = 
1251                         g_slist_find_custom(priv->busy_accounts, account_name, (GCompareFunc) compare_account_name);
1252
1253                 if (account) {
1254                         g_free(account->data);
1255                         priv->busy_accounts = g_slist_delete_link(priv->busy_accounts, account);
1256                         g_signal_emit (G_OBJECT(self), signals[ACCOUNT_BUSY_SIGNAL], 
1257                                        0, account_name, FALSE);
1258                 }
1259         }
1260 }
1261
1262 gboolean
1263 modest_account_mgr_account_is_busy(ModestAccountMgr* self, const gchar* account_name)
1264 {
1265         ModestAccountMgrPrivate* priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
1266         return (g_slist_find_custom(priv->busy_accounts, account_name, (GCompareFunc) compare_account_name)
1267                                         != NULL);
1268 }
1269
1270 void
1271 modest_account_mgr_notify_account_update (ModestAccountMgr* self, 
1272                                           const gchar *server_account_name)
1273 {
1274         ModestTransportStoreProtocol proto;
1275         gchar *proto_name = NULL;
1276
1277         /* Get protocol */
1278         proto_name = modest_account_mgr_get_string (self, server_account_name, 
1279                                                     MODEST_ACCOUNT_PROTO, TRUE);
1280         if (!proto_name) {
1281                 g_free (proto_name);
1282                 g_return_if_reached ();
1283         }
1284         proto = modest_protocol_info_get_transport_store_protocol (proto_name);
1285         g_free (proto_name);
1286
1287         /* Emit "update-account" */
1288         g_signal_emit (G_OBJECT(self), 
1289                        signals[ACCOUNT_CHANGED_SIGNAL], 0, 
1290                        server_account_name, 
1291                        (modest_protocol_info_protocol_is_store (proto)) ? 
1292                        TNY_ACCOUNT_TYPE_STORE : 
1293                        TNY_ACCOUNT_TYPE_TRANSPORT);
1294 }
1295
1296
1297 gboolean
1298 modest_account_mgr_set_default_account  (ModestAccountMgr *self, const gchar* account)
1299 {
1300         ModestConf *conf;
1301         gboolean retval;
1302         
1303         g_return_val_if_fail (self,    FALSE);
1304         g_return_val_if_fail (account, FALSE);
1305         g_return_val_if_fail (modest_account_mgr_account_exists (self, account, FALSE),
1306                               FALSE);
1307         
1308         conf = MODEST_ACCOUNT_MGR_GET_PRIVATE (self)->modest_conf;
1309
1310         /* Change the default account and notify */
1311         retval = modest_conf_set_string (conf, MODEST_CONF_DEFAULT_ACCOUNT, account, NULL);
1312         if (retval)
1313                 g_signal_emit (G_OBJECT(self), signals[DEFAULT_ACCOUNT_CHANGED_SIGNAL], 0);
1314
1315         return retval;
1316 }
1317
1318
1319 gchar*
1320 modest_account_mgr_get_default_account  (ModestAccountMgr *self)
1321 {
1322         gchar *account; 
1323         ModestConf *conf;
1324         GError *err = NULL;
1325         
1326         g_return_val_if_fail (self, NULL);
1327
1328         conf = MODEST_ACCOUNT_MGR_GET_PRIVATE (self)->modest_conf;
1329         account = modest_conf_get_string (conf, MODEST_CONF_DEFAULT_ACCOUNT, &err);
1330         
1331         if (err) {
1332                 g_printerr ("modest: failed to get '%s': %s\n",
1333                             MODEST_CONF_DEFAULT_ACCOUNT, err->message);
1334                 g_error_free (err);
1335                 g_free (account);
1336                 return  NULL;
1337         }
1338         
1339         /* sanity check */
1340         if (account && !modest_account_mgr_account_exists (self, account, FALSE)) {
1341                 g_printerr ("modest: default account does not exist\n");
1342                 g_free (account);
1343                 return NULL;
1344         }
1345
1346         return account;
1347 }
1348
1349 static gboolean
1350 modest_account_mgr_unset_default_account (ModestAccountMgr *self)
1351 {
1352         ModestConf *conf;
1353         gboolean retval;
1354         
1355         g_return_val_if_fail (self,    FALSE);
1356
1357         conf = MODEST_ACCOUNT_MGR_GET_PRIVATE (self)->modest_conf;
1358                 
1359         retval = modest_conf_remove_key (conf, MODEST_CONF_DEFAULT_ACCOUNT, NULL /* err */);
1360
1361         if (retval)
1362                 g_signal_emit (G_OBJECT(self), signals[DEFAULT_ACCOUNT_CHANGED_SIGNAL], 0);
1363
1364         return retval;
1365 }
1366
1367
1368 gchar* 
1369 modest_account_mgr_get_display_name (ModestAccountMgr *self, 
1370                                      const gchar* name)
1371 {
1372         return modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_DISPLAY_NAME, FALSE);
1373 }
1374
1375 void 
1376 modest_account_mgr_set_display_name (ModestAccountMgr *self, 
1377                                      const gchar *account_name,
1378                                      const gchar *display_name)
1379 {
1380         modest_account_mgr_set_string (self, 
1381                                        account_name,
1382                                        MODEST_ACCOUNT_DISPLAY_NAME, 
1383                                        display_name, 
1384                                        FALSE /* not server account */);
1385
1386         /* Notify about the change in the display name */
1387         g_signal_emit (self, signals[DISPLAY_NAME_CHANGED_SIGNAL], 0, account_name);
1388 }