2007-05-14 Murray Cumming <murrayc@murrayc.com>
[modest] / src / modest-account-mgr.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <string.h>
31 #include <modest-marshal.h>
32 #include <modest-account-mgr.h>
33 #include <modest-account-mgr-priv.h>
34 #include <modest-account-mgr-helpers.h>
35
36 /* 'private'/'protected' functions */
37 static void modest_account_mgr_class_init (ModestAccountMgrClass * klass);
38 static void modest_account_mgr_init       (ModestAccountMgr * obj);
39 static void modest_account_mgr_finalize   (GObject * obj);
40
41 /* list my signals */
42 enum {
43         ACCOUNT_CHANGED_SIGNAL,
44         ACCOUNT_REMOVED_SIGNAL,
45         LAST_SIGNAL
46 };
47
48
49 /* globals */
50 static GObjectClass *parent_class = NULL;
51 static guint signals[LAST_SIGNAL] = {0};
52
53 static void
54 on_key_change (ModestConf *conf, const gchar *key, ModestConfEvent event, gpointer user_data)
55 {
56         /* printf("DEBUG: %s: key=%s\n", __FUNCTION__, key); */
57         
58         ModestAccountMgr *self = MODEST_ACCOUNT_MGR (user_data);
59         /* ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self); */
60
61         /* there is only one not-really-account key which will still emit
62          * a signal: a change in MODEST_CONF_DEFAULT_ACCOUNT */
63         if (key && strcmp (key, MODEST_CONF_DEFAULT_ACCOUNT) == 0) {
64                 gchar *default_account =
65                         modest_account_mgr_get_default_account (self);
66                 g_signal_emit (G_OBJECT(self), signals[ACCOUNT_CHANGED_SIGNAL], 0,
67                                default_account, key, FALSE);
68                 g_free (default_account);
69                 return;
70         }
71         
72         gboolean is_account_key = FALSE;
73         gboolean is_server_account = FALSE;
74         gchar* account = _modest_account_mgr_account_from_key (key, &is_account_key, &is_server_account);
75         
76         /* if this is not an account-related key change, ignore */
77         if (!account)
78                 return;
79
80         /* account was removed -- emit this, even if the account was disabled */
81         if (is_account_key && event == MODEST_CONF_EVENT_KEY_UNSET) {
82                 g_signal_emit (G_OBJECT(self), signals[ACCOUNT_REMOVED_SIGNAL], 0,
83                                account, is_server_account);
84                 g_free (account);
85                 return;
86         }
87
88         /* is this account enabled? */
89         gboolean enabled = FALSE;
90         if (is_server_account)
91                 enabled = TRUE;
92         else 
93                 enabled = modest_account_mgr_get_enabled (self, account);
94
95         /* Notify is server account was changed, default account was changed
96          * or when enabled/disabled changes:
97          */
98         if (enabled ||
99             g_str_has_suffix (key, MODEST_ACCOUNT_ENABLED) ||
100             strcmp (key, MODEST_CONF_DEFAULT_ACCOUNT) == 0)
101                 g_signal_emit (G_OBJECT(self), signals[ACCOUNT_CHANGED_SIGNAL], 0,
102                                account, key, is_server_account);
103
104         g_free (account);
105 }
106
107
108 GType
109 modest_account_mgr_get_type (void)
110 {
111         static GType my_type = 0;
112
113         if (!my_type) {
114                 static const GTypeInfo my_info = {
115                         sizeof (ModestAccountMgrClass),
116                         NULL,   /* base init */
117                         NULL,   /* base finalize */
118                         (GClassInitFunc) modest_account_mgr_class_init,
119                         NULL,   /* class finalize */
120                         NULL,   /* class data */
121                         sizeof (ModestAccountMgr),
122                         1,      /* n_preallocs */
123                         (GInstanceInitFunc) modest_account_mgr_init,
124                         NULL
125                 };
126
127                 my_type = g_type_register_static (G_TYPE_OBJECT,
128                                                   "ModestAccountMgr",
129                                                   &my_info, 0);
130         }
131         return my_type;
132 }
133
134 static void
135 modest_account_mgr_class_init (ModestAccountMgrClass * klass)
136 {
137         GObjectClass *gobject_class;
138         gobject_class = (GObjectClass *) klass;
139
140         parent_class = g_type_class_peek_parent (klass);
141         gobject_class->finalize = modest_account_mgr_finalize;
142
143         g_type_class_add_private (gobject_class,
144                                   sizeof (ModestAccountMgrPrivate));
145
146         /* signal definitions */
147         signals[ACCOUNT_REMOVED_SIGNAL] =
148                 g_signal_new ("account_removed",
149                               G_TYPE_FROM_CLASS (klass),
150                               G_SIGNAL_RUN_FIRST,
151                               G_STRUCT_OFFSET(ModestAccountMgrClass,account_removed),
152                               NULL, NULL,
153                               modest_marshal_VOID__STRING_BOOLEAN,
154                               G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
155         signals[ACCOUNT_CHANGED_SIGNAL] =
156                 g_signal_new ("account_changed",
157                                G_TYPE_FROM_CLASS (klass),
158                               G_SIGNAL_RUN_FIRST,
159                               G_STRUCT_OFFSET(ModestAccountMgrClass,account_changed),
160                               NULL, NULL,
161                               modest_marshal_VOID__STRING_STRING_BOOLEAN,
162                               G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
163 }
164
165
166 static void
167 modest_account_mgr_init (ModestAccountMgr * obj)
168 {
169         ModestAccountMgrPrivate *priv =
170                 MODEST_ACCOUNT_MGR_GET_PRIVATE (obj);
171
172         priv->modest_conf = NULL;
173 }
174
175 static void
176 modest_account_mgr_finalize (GObject * obj)
177 {
178         ModestAccountMgrPrivate *priv =
179                 MODEST_ACCOUNT_MGR_GET_PRIVATE (obj);
180
181         if (priv->modest_conf) {
182                 g_object_unref (G_OBJECT(priv->modest_conf));
183                 priv->modest_conf = NULL;
184         }
185
186         G_OBJECT_CLASS(parent_class)->finalize (obj);
187 }
188
189
190 ModestAccountMgr *
191 modest_account_mgr_new (ModestConf *conf)
192 {
193         GObject *obj;
194         ModestAccountMgrPrivate *priv;
195
196         g_return_val_if_fail (conf, NULL);
197
198         obj = G_OBJECT (g_object_new (MODEST_TYPE_ACCOUNT_MGR, NULL));
199         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (obj);
200
201         g_object_ref (G_OBJECT(conf));
202         priv->modest_conf = conf;
203
204         g_signal_connect (G_OBJECT (conf), "key_changed",
205                           G_CALLBACK (on_key_change),
206                           obj);
207         
208         return MODEST_ACCOUNT_MGR (obj);
209 }
210
211
212 static const gchar *
213 null_means_empty (const gchar * str)
214 {
215         return str ? str : "";
216 }
217
218
219 gboolean
220 modest_account_mgr_add_account (ModestAccountMgr *self,
221                                 const gchar *name,
222                                 const gchar *store_account,
223                                 const gchar *transport_account,
224                                 gboolean enabled)
225 {
226         ModestAccountMgrPrivate *priv;
227         gchar *key;
228         gboolean ok;
229         gchar *default_account;
230         GError *err = NULL;
231         
232         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
233         g_return_val_if_fail (name, FALSE);
234         g_return_val_if_fail (strchr(name, '/') == NULL, FALSE);
235         
236         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
237         
238         /*
239          * we create the account by adding an account 'dir', with the name <name>,
240          * and in that the 'display_name' string key
241          */
242         key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_DISPLAY_NAME, FALSE);
243         if (modest_account_mgr_account_exists (self, key, FALSE)) {
244                 g_printerr ("modest: account already exists\n");
245                 g_free (key);
246                 return FALSE;
247         }
248         
249         ok = modest_conf_set_string (priv->modest_conf, key, name, &err);
250         g_free (key);
251         if (!ok) {
252                 g_printerr ("modest: cannot set display name\n");
253                 if (err) {
254                         g_printerr ("modest: %s\n", err->message);
255                         g_error_free (err);
256                 }
257                 return FALSE;
258         }
259         
260         if (store_account) {
261                 key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_STORE_ACCOUNT, FALSE);
262                 ok = modest_conf_set_string (priv->modest_conf, key, store_account, &err);
263                 g_free (key);
264                 if (!ok) {
265                         g_printerr ("modest: failed to set store account '%s'\n",
266                                 store_account);
267                         if (err) {
268                                 g_printerr ("modest: %s\n", err->message);
269                                 g_error_free (err);
270                         }
271                         
272                         return FALSE;
273                 }
274         }
275         
276         if (transport_account) {
277                 key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_TRANSPORT_ACCOUNT,
278                                                                FALSE);
279                 ok = modest_conf_set_string (priv->modest_conf, key, transport_account, &err);
280                 g_free (key);
281                 if (!ok) {
282                         g_printerr ("modest: failed to set transport account '%s'\n",
283                                     transport_account);
284                         if (err) {
285                                 g_printerr ("modest: %s\n", err->message);
286                                 g_error_free (err);
287                         }       
288                         return FALSE;
289                 }
290         }
291         modest_account_mgr_set_enabled (self, name, enabled);
292
293         /* if no default account has been defined yet, do so now */
294         default_account = modest_account_mgr_get_default_account (self);
295         if (!default_account)
296                 modest_account_mgr_set_default_account (self, name);
297         g_free (default_account);
298         
299         return TRUE;
300 }
301
302
303
304
305 gboolean
306 modest_account_mgr_add_server_account (ModestAccountMgr * self,
307                                        const gchar * name, const gchar *hostname,
308                                        const gchar * username, const gchar * password,
309                                        ModestProtocol proto,
310                                        ModestProtocol security,
311                                        ModestProtocol auth)
312 {
313         ModestAccountMgrPrivate *priv;
314         gchar *key;
315         ModestProtocolType proto_type;
316         gboolean ok = TRUE;
317         GError *err = NULL;
318         
319         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
320         g_return_val_if_fail (name, FALSE);
321         g_return_val_if_fail (strchr(name, '/') == NULL, FALSE);
322
323         proto_type = modest_protocol_info_get_protocol_type (proto);
324         g_return_val_if_fail (proto_type == MODEST_PROTOCOL_TYPE_TRANSPORT ||
325                               proto_type == MODEST_PROTOCOL_TYPE_STORE, FALSE);
326                               
327         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
328         
329         /* hostname */
330         key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_HOSTNAME, TRUE);
331         if (modest_conf_key_exists (priv->modest_conf, key, &err)) {
332                 g_printerr ("modest: server account '%s' already exists\n", name);
333                 g_free (key);
334                 ok =  FALSE;
335         }
336         if (!ok)
337                 goto cleanup;
338         
339         modest_conf_set_string (priv->modest_conf, key, null_means_empty(hostname), &err);
340         if (err) {
341                 g_printerr ("modest: failed to set %s: %s\n", key, err->message);
342                 g_error_free (err);
343                 ok = FALSE;
344         }
345         g_free (key);
346         if (!ok)
347                 goto cleanup;
348         
349         /* username */
350         key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_USERNAME, TRUE);
351         ok = modest_conf_set_string (priv->modest_conf, key, null_means_empty (username), &err);
352         if (err) {
353                 g_printerr ("modest: failed to set %s: %s\n", key, err->message);
354                 g_error_free (err);
355                 ok = FALSE;
356         }
357         g_free (key);
358         if (!ok)
359                 goto cleanup;
360         
361         
362         /* password */
363         key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_PASSWORD, TRUE);
364         ok = modest_conf_set_string (priv->modest_conf, key, null_means_empty (password), &err);
365         if (err) {
366                 g_printerr ("modest: failed to set %s: %s\n", key, err->message);
367                 g_error_free (err);
368                 ok = FALSE;
369         }
370         g_free (key);
371         if (!ok)
372                 goto cleanup;
373
374         /* proto */
375         key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_PROTO, TRUE);
376         ok = modest_conf_set_string (priv->modest_conf, key,
377                                      modest_protocol_info_get_protocol_name(proto), &err);
378         if (err) {
379                 g_printerr ("modest: failed to set %s: %s\n", key, err->message);
380                 g_error_free (err);
381                 ok = FALSE;
382         }
383         g_free (key);
384         if (!ok)
385                 goto cleanup;
386
387         /* auth mechanism */
388         key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_AUTH_MECH, TRUE);
389         ok = modest_conf_set_string (priv->modest_conf, key,
390                                      modest_protocol_info_get_protocol_name (auth), &err);
391         if (err) {
392                 g_printerr ("modest: failed to set %s: %s\n", key, err->message);
393                 g_error_free (err);
394                 ok = FALSE;
395         }
396         g_free (key);
397         if (!ok)
398                 goto cleanup;
399
400         if (proto_type == MODEST_PROTOCOL_TYPE_STORE) {
401                 /* Add the security settings: */
402                 modest_server_account_set_security (self, name, security);
403         }
404
405 cleanup:
406         if (!ok) {
407                 g_printerr ("modest: failed to add server account\n");
408                 return FALSE;
409         }
410
411         return TRUE;
412 }
413
414 /** modest_account_mgr_add_server_account_uri:
415  * Only used for mbox and maildir accounts.
416  */
417 gboolean
418 modest_account_mgr_add_server_account_uri (ModestAccountMgr * self,
419                                            const gchar *name, ModestProtocol proto,
420                                            const gchar *uri)
421 {
422         ModestAccountMgrPrivate *priv;
423         gchar *key;
424         gboolean ok;
425         
426         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
427         g_return_val_if_fail (name, FALSE);
428         g_return_val_if_fail (strchr(name, '/') == NULL, FALSE);
429         g_return_val_if_fail (uri, FALSE);
430         
431         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
432         
433         
434         /* proto */
435         key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_PROTO, TRUE);
436         ok = modest_conf_set_string (priv->modest_conf, key,
437                                      modest_protocol_info_get_protocol_name(proto), NULL);
438         g_free (key);
439
440         if (!ok) {
441                 g_printerr ("modest: failed to set proto\n");
442                 return FALSE;
443         }
444         
445         /* uri */
446         key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_URI, TRUE);
447         ok = modest_conf_set_string (priv->modest_conf, key, uri, NULL);
448         g_free (key);
449
450         if (!ok) {
451                 g_printerr ("modest: failed to set uri\n");
452                 return FALSE;
453         }
454         return TRUE;
455 }
456
457
458
459 gboolean
460 modest_account_mgr_remove_account (ModestAccountMgr * self,
461                                    const gchar * name,  gboolean server_account)
462 {
463         ModestAccountMgrPrivate *priv;
464         gchar *key;
465         gboolean retval;
466         GError *err = NULL;
467
468         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
469         g_return_val_if_fail (name, FALSE);
470
471         if (!modest_account_mgr_account_exists (self, name, server_account)) {
472                 g_printerr ("modest: account '%s' does not exist\n", name);
473                 return FALSE;
474         }
475
476         /* in case we're not deleting an account, also delete the dependent store and transport account */
477         if (!server_account) {
478                 gchar *server_account_name;
479                 
480                 server_account_name = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_STORE_ACCOUNT,
481                                                                     FALSE);
482                 if (server_account_name) {
483                         if (!modest_account_mgr_remove_account (self, server_account_name, TRUE))
484                                 g_printerr ("modest: failed to remove store account '%s' (%s)\n",
485                                             server_account_name, name);
486                         g_free (server_account_name);
487                 } else
488                         g_printerr ("modest: could not find the store account for %s\n", name);
489                 
490                 server_account_name = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_TRANSPORT_ACCOUNT,
491                                                                     FALSE);
492                 if (server_account_name) {
493                         if (!modest_account_mgr_remove_account (self, server_account_name, TRUE))
494                                 g_printerr ("modest: failed to remove transport account '%s' (%s)\n",
495                                             server_account_name, name);
496                         g_free (server_account_name);
497                 } else
498                         g_printerr ("modest: could not find the transport account for %s\n", name);
499         }                       
500                         
501         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
502         key = _modest_account_mgr_get_account_keyname (name, NULL, server_account);
503         
504         retval = modest_conf_remove_key (priv->modest_conf, key, &err);
505         g_free (key);
506
507         if (err) {
508                 g_printerr ("modest: error removing key: %s\n", err->message);
509                 g_error_free (err);
510         }
511
512         /* If this was the default, then remove that setting: */
513         if (!server_account) {
514                 gchar *default_account_name = modest_account_mgr_get_default_account (self);
515                 if (default_account_name && (strcmp (default_account_name, name) == 0))
516                         modest_account_mgr_unset_default_account (self);
517                 g_free (default_account_name);
518         }
519         
520         return retval;
521 }
522
523
524
525 /* strip the first /n/ character from each element
526  * caller must make sure all elements are strings with
527  * length >= n, and also that data can be freed.
528  * change is in-place
529  */
530 static void
531 strip_prefix_from_elements (GSList * lst, guint n)
532 {
533         while (lst) {
534                 memmove (lst->data, lst->data + n,
535                          strlen(lst->data) - n + 1);
536                 lst = lst->next;
537         }
538 }
539
540
541 GSList*
542 modest_account_mgr_search_server_accounts (ModestAccountMgr * self,
543                                            const gchar * account_name,
544                                            ModestProtocolType type,
545                                            ModestProtocol proto)
546 {
547         GSList *accounts;
548         GSList *cursor;
549         ModestAccountMgrPrivate *priv;
550         gchar *key;
551         GError *err = NULL;
552         
553         g_return_val_if_fail (self, NULL);
554
555         if (proto != MODEST_PROTOCOL_UNKNOWN) {
556                 ModestProtocolType proto_type;
557                 proto_type = modest_protocol_info_get_protocol_type (proto);
558                 g_return_val_if_fail (proto_type == MODEST_PROTOCOL_TYPE_TRANSPORT ||
559                                       proto_type == MODEST_PROTOCOL_TYPE_STORE, NULL);
560         }
561         
562         key      = _modest_account_mgr_get_account_keyname (account_name, NULL, TRUE);
563         priv     = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
564         
565         /* get the list of all server accounts */
566         accounts = modest_conf_list_subkeys (priv->modest_conf, key, &err);
567         if (err) {
568                 g_printerr ("modest: failed to get subkeys for '%s' (%s)\n", key,
569                         err->message);
570                 g_error_free(err);
571                 return NULL;
572         }
573         
574         /* filter out the ones with the wrong protocol */
575         /* we could optimize for unknown proto / unknown type, but it will only
576          * make the code more complex */
577         cursor = accounts;
578         while (cursor) { 
579                 gchar *account   = _modest_account_mgr_account_from_key ((gchar*)cursor->data, NULL, NULL);
580                 gchar *acc_proto = modest_account_mgr_get_string (self, account, MODEST_ACCOUNT_PROTO,TRUE);
581                 ModestProtocol     this_proto = modest_protocol_info_get_protocol (acc_proto);
582                 ModestProtocolType this_type  = modest_protocol_info_get_protocol_type (this_proto);
583
584                 if ((this_type  != MODEST_PROTOCOL_TYPE_UNKNOWN && this_type  != type) ||
585                     (this_proto != MODEST_PROTOCOL_UNKNOWN      && this_proto != proto)) {
586                         GSList *nxt = cursor->next;
587                         accounts = g_slist_delete_link (accounts, cursor);
588                         cursor = nxt;
589                 } else
590                         cursor = cursor->next;
591                 
592                 g_free (account);
593                 g_free (acc_proto);
594         }
595         
596         /* +1 because we must remove the ending '/' as well */
597         strip_prefix_from_elements (accounts, strlen(key)+1);
598         return accounts;        
599 }
600
601
602 GSList*
603 modest_account_mgr_account_names (ModestAccountMgr * self, gboolean only_enabled)
604 {
605         GSList *accounts;
606         ModestAccountMgrPrivate *priv;
607         GError *err = NULL;
608         
609         const size_t prefix_len = strlen (MODEST_ACCOUNT_NAMESPACE "/");
610
611         g_return_val_if_fail (self, NULL);
612
613         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
614         
615         accounts = modest_conf_list_subkeys (priv->modest_conf,
616                                              MODEST_ACCOUNT_NAMESPACE, &err);
617         if (err) {
618                 g_printerr ("modest: failed to get subkeys (%s): %s\n",
619                             MODEST_ACCOUNT_NAMESPACE, err->message);
620                 g_error_free (err);
621                 return NULL; /* assume accounts did not get value when err is set...*/
622         }
623         
624         strip_prefix_from_elements (accounts, prefix_len);
625                 
626         GSList *result = NULL;
627         
628         /* Filter-out the disabled accounts if requested: */
629         if (only_enabled) {
630                 GSList *iter = accounts;
631                 while (iter) {
632                         if (!(iter->data))
633                                 continue;
634                                 
635                         const gchar* account_name = (const gchar*)iter->data;
636                         if (account_name && modest_account_mgr_get_enabled (self, account_name))
637                                 result = g_slist_append (result, g_strdup (account_name));
638                                 
639                         iter = g_slist_next (iter);     
640                 }
641                 
642                 /* TODO: Free the strings too? */
643                 g_slist_free (accounts);
644                 accounts = NULL;
645         }
646         else
647                 result = accounts;
648         
649
650         return result;
651 }
652
653
654 gchar *
655 modest_account_mgr_get_string (ModestAccountMgr *self, const gchar *name,
656                                const gchar *key, gboolean server_account) {
657
658         ModestAccountMgrPrivate *priv;
659
660         gchar *keyname;
661         gchar *retval;
662         GError *err = NULL;
663
664         g_return_val_if_fail (self, NULL);
665         g_return_val_if_fail (name, NULL);
666         g_return_val_if_fail (key, NULL);
667
668         keyname = _modest_account_mgr_get_account_keyname (name, key, server_account);
669         
670         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
671         retval = modest_conf_get_string (priv->modest_conf, keyname, &err);     
672         if (err) {
673                 g_printerr ("modest: error getting string '%s': %s\n", keyname, err->message);
674                 g_error_free (err);
675                 retval = NULL;
676         }
677         g_free (keyname);
678
679         return retval;
680 }
681
682
683 gchar *
684 modest_account_mgr_get_password (ModestAccountMgr *self, const gchar *name,
685                                const gchar *key, gboolean server_account)
686 {
687         return modest_account_mgr_get_string (self, name, key, server_account);
688
689 }
690
691
692
693 gint
694 modest_account_mgr_get_int (ModestAccountMgr *self, const gchar *name, const gchar *key,
695                             gboolean server_account)
696 {
697         ModestAccountMgrPrivate *priv;
698
699         gchar *keyname;
700         gint retval;
701         GError *err = NULL;
702         
703         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), -1);
704         g_return_val_if_fail (name, -1);
705         g_return_val_if_fail (key, -1);
706
707         keyname = _modest_account_mgr_get_account_keyname (name, key, server_account);
708
709         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
710         retval = modest_conf_get_int (priv->modest_conf, keyname, &err);
711         if (err) {
712                 g_printerr ("modest: error getting int '%s': %s\n", keyname, err->message);
713                 g_error_free (err);
714                 retval = -1;
715         }
716         g_free (keyname);
717
718         return retval;
719 }
720
721
722
723 gboolean
724 modest_account_mgr_get_bool (ModestAccountMgr * self, const gchar *account,
725                              const gchar * key, gboolean server_account)
726 {
727         ModestAccountMgrPrivate *priv;
728
729         gchar *keyname;
730         gboolean retval;
731         GError *err = NULL;
732
733         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
734         g_return_val_if_fail (account, FALSE);
735         g_return_val_if_fail (key, FALSE);
736
737         keyname = _modest_account_mgr_get_account_keyname (account, key, server_account);
738         
739         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
740         retval = modest_conf_get_bool (priv->modest_conf, keyname, &err);               
741         if (err) {
742                 g_printerr ("modest: error getting bool '%s': %s\n", keyname, err->message);
743                 g_error_free (err);
744                 retval = FALSE;
745         }
746         g_free (keyname);
747
748         return retval;
749 }
750
751
752
753 GSList * 
754 modest_account_mgr_get_list (ModestAccountMgr *self, const gchar *name,
755                              const gchar *key, ModestConfValueType list_type,
756                              gboolean server_account)
757 {
758         ModestAccountMgrPrivate *priv;
759
760         gchar *keyname;
761         GSList *retval;
762         GError *err = NULL;
763         
764         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), NULL);
765         g_return_val_if_fail (name, NULL);
766         g_return_val_if_fail (key, NULL);
767
768         keyname = _modest_account_mgr_get_account_keyname (name, key, server_account);
769         
770         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
771         retval = modest_conf_get_list (priv->modest_conf, keyname, list_type, &err);
772         if (err) {
773                 g_printerr ("modest: error getting list '%s': %s\n", keyname,
774                             err->message);
775                 g_error_free (err);
776                 retval = FALSE;
777         }
778         g_free (keyname);
779
780         return retval;
781 }
782
783
784 gboolean
785 modest_account_mgr_set_string (ModestAccountMgr * self, const gchar * name,
786                                const gchar * key, const gchar * val, gboolean server_account)
787 {
788         ModestAccountMgrPrivate *priv;
789
790         gchar *keyname;
791         gboolean retval;
792         GError *err = NULL;
793
794         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
795         g_return_val_if_fail (name, FALSE);
796         g_return_val_if_fail (key, FALSE);
797
798         keyname = _modest_account_mgr_get_account_keyname (name, key, server_account);
799         
800         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
801
802         retval = modest_conf_set_string (priv->modest_conf, keyname, val, &err);
803         if (err) {
804                 g_printerr ("modest: error setting string '%s': %s\n", keyname, err->message);
805                 g_error_free (err);
806                 retval = FALSE;
807         }
808         g_free (keyname);       
809         return retval;
810 }
811
812
813 gboolean
814 modest_account_mgr_set_password (ModestAccountMgr * self, const gchar * name,
815                                  const gchar * key, const gchar * val, gboolean server_account)
816 {
817         return modest_account_mgr_set_password (self, name, key, val, server_account);
818 }
819
820
821
822 gboolean
823 modest_account_mgr_set_int (ModestAccountMgr * self, const gchar * name,
824                             const gchar * key, int val, gboolean server_account)
825 {
826         ModestAccountMgrPrivate *priv;
827
828         gchar *keyname;
829         gboolean retval;
830         GError *err = NULL;
831         
832         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
833         g_return_val_if_fail (name, FALSE);
834         g_return_val_if_fail (key, FALSE);
835
836         keyname = _modest_account_mgr_get_account_keyname (name, key, server_account);
837         
838         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
839
840         retval = modest_conf_set_int (priv->modest_conf, keyname, val, &err);
841         if (err) {
842                 g_printerr ("modest: error setting int '%s': %s\n", keyname, err->message);
843                 g_error_free (err);
844                 retval = FALSE;
845         }
846         g_free (keyname);
847         return retval;
848 }
849
850
851
852 gboolean
853 modest_account_mgr_set_bool (ModestAccountMgr * self, const gchar * name,
854                              const gchar * key, gboolean val, gboolean server_account)
855 {
856         ModestAccountMgrPrivate *priv;
857
858         gchar *keyname;
859         gboolean retval;
860         GError *err = NULL;
861
862         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
863         g_return_val_if_fail (name, FALSE);
864         g_return_val_if_fail (key, FALSE);
865
866         keyname = _modest_account_mgr_get_account_keyname (name, key, server_account);
867
868         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
869
870         retval = modest_conf_set_bool (priv->modest_conf, keyname, val, &err);
871         if (err) {
872                 g_printerr ("modest: error setting bool '%s': %s\n", keyname, err->message);
873                 g_error_free (err);
874                 retval = FALSE;
875         }
876         g_free (keyname);
877         return retval;
878 }
879
880
881 gboolean
882 modest_account_mgr_set_list (ModestAccountMgr *self,
883                              const gchar *name,
884                              const gchar *key,
885                              GSList *val,
886                              ModestConfValueType list_type,
887                              gboolean server_account)
888 {
889         ModestAccountMgrPrivate *priv;
890         gchar *keyname;
891         GError *err = NULL;
892         gboolean retval;
893         
894         g_return_val_if_fail (self, FALSE);
895         g_return_val_if_fail (name, FALSE);
896         g_return_val_if_fail (key,  FALSE);
897         g_return_val_if_fail (val,  FALSE);
898
899         keyname = _modest_account_mgr_get_account_keyname (name, key, server_account);
900         
901         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
902         retval = modest_conf_set_list (priv->modest_conf, keyname, val, list_type, &err);
903         if (err) {
904                 g_printerr ("modest: error setting list '%s': %s\n", keyname, err->message);
905                 g_error_free (err);
906                 retval = FALSE;
907         }
908         g_free (keyname);
909
910         return retval;
911 }
912
913 gboolean
914 modest_account_mgr_account_exists (ModestAccountMgr * self, const gchar * name,
915                                    gboolean server_account)
916 {
917         ModestAccountMgrPrivate *priv;
918
919         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
926         keyname = _modest_account_mgr_get_account_keyname (name, NULL, server_account);
927
928         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
929         retval = modest_conf_key_exists (priv->modest_conf, keyname, &err);
930         if (err) {
931                 g_printerr ("modest: error determining existance of '%s': %s\n", keyname,
932                             err->message);
933                 g_error_free (err);
934                 retval = FALSE;
935         }
936         g_free (keyname);
937         return retval;
938 }
939
940 gboolean        modest_account_mgr_account_with_display_name_exists       (ModestAccountMgr *self,
941                                                            const gchar *display_name)
942 {
943         GSList *account_names = NULL;
944         GSList *cursor = NULL;
945         
946         cursor = account_names = modest_account_mgr_account_names (self, 
947                 TRUE /* enabled accounts, because disabled accounts are not user visible. */);
948
949         gboolean found = FALSE;
950         
951         /* Look at each non-server account to check their display names; */
952         while (cursor) {
953                 const gchar * account_name = (gchar*)cursor->data;
954                 
955                 ModestAccountData *account_data = modest_account_mgr_get_account_data (self, account_name);
956                 if (!account_data) {
957                         g_printerr ("modest: failed to get account data for %s\n", account_name);
958                         continue;
959                 }
960
961                 if(account_data->display_name && (strcmp (account_data->display_name, display_name) == 0)) {
962                         found = TRUE;
963                         break;
964                 }
965
966                 modest_account_mgr_free_account_data (self, account_data);
967                 cursor = cursor->next;
968         }
969         g_slist_free (account_names);
970         
971         return found;
972 }
973
974
975
976
977 gboolean 
978 modest_account_mgr_unset (ModestAccountMgr *self, const gchar *name,
979                           const gchar *key, gboolean server_account)
980 {
981         ModestAccountMgrPrivate *priv;
982         
983         gchar *keyname;
984         gboolean retval;
985         GError *err = NULL;
986         
987         g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
988         g_return_val_if_fail (name, FALSE);
989         g_return_val_if_fail (key, FALSE);
990
991         keyname = _modest_account_mgr_get_account_keyname (name, key, server_account);
992
993         priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
994         retval = modest_conf_remove_key (priv->modest_conf, keyname, &err);
995         if (err) {
996                 g_printerr ("modest: error unsetting'%s': %s\n", keyname,
997                             err->message);
998                 g_error_free (err);
999                 retval = FALSE;
1000         }
1001         g_free (keyname);
1002         return retval;
1003 }