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