6cc12824c0ecca7918bc98cff8175f65c22b6d74
[modest] / src / modest-account-mgr-helpers.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 <modest-account-mgr-helpers.h>
31 #include <modest-account-mgr-priv.h>
32 #include <tny-simple-list.h>
33 #include <modest-runtime.h>
34 #include <string.h>
35
36 gboolean
37 modest_account_mgr_set_enabled (ModestAccountMgr *self, const gchar* name,
38                                         gboolean enabled)
39 {
40         return modest_account_mgr_set_bool (self, name, MODEST_ACCOUNT_ENABLED, enabled,FALSE);
41 }
42
43
44 gboolean
45 modest_account_mgr_get_enabled (ModestAccountMgr *self, const gchar* name)
46 {
47         return modest_account_mgr_get_bool (self, name, MODEST_ACCOUNT_ENABLED, FALSE);
48 }
49
50 gboolean modest_account_mgr_set_signature (ModestAccountMgr *self, const gchar* name, 
51         const gchar* signature, gboolean use_signature)
52 {
53         gboolean result = modest_account_mgr_set_bool (self, name, MODEST_ACCOUNT_USE_SIGNATURE, 
54                 use_signature, FALSE);
55         result = result && modest_account_mgr_set_string (self, name, MODEST_ACCOUNT_SIGNATURE, 
56                 signature, FALSE);
57         return result;
58 }
59
60 gchar* modest_account_mgr_get_signature (ModestAccountMgr *self, const gchar* name, 
61         gboolean* use_signature)
62 {
63         if (use_signature) {
64                 *use_signature = 
65                         modest_account_mgr_get_bool (self, name, MODEST_ACCOUNT_USE_SIGNATURE, FALSE);
66         }
67         
68         return modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_SIGNATURE, FALSE);
69 }
70
71
72 ModestTransportStoreProtocol modest_account_mgr_get_store_protocol (ModestAccountMgr *self, const gchar* name)
73 {
74         ModestTransportStoreProtocol result = MODEST_PROTOCOL_STORE_POP; /* Arbitrary default */
75         
76         gchar *server_account_name = modest_account_mgr_get_string (self, name,
77                                                         MODEST_ACCOUNT_STORE_ACCOUNT,
78                                                         FALSE);
79         if (server_account_name) {
80                 ModestServerAccountData* server_data = 
81                         modest_account_mgr_get_server_account_data (self, server_account_name);
82                 result = server_data->proto;
83                         
84                 modest_account_mgr_free_server_account_data (self, server_data);
85                 
86                 g_free (server_account_name);
87         }
88         
89         return result;
90 }
91
92 gboolean modest_account_mgr_set_connection_specific_smtp (ModestAccountMgr *self, 
93         const gchar* connection_name, const gchar* server_account_name)
94 {
95         modest_account_mgr_remove_connection_specific_smtp (self, connection_name);
96         
97         ModestConf *conf = MODEST_ACCOUNT_MGR_GET_PRIVATE (self)->modest_conf;
98
99         gboolean result = TRUE;
100         GError *err = NULL;
101         GSList *list = modest_conf_get_list (conf, MODEST_CONF_CONNECTION_SPECIFIC_SMTP_LIST,
102                                                     MODEST_CONF_VALUE_STRING, &err);
103         if (err) {
104                 g_printerr ("modest: %s: error getting list: %s.\n", __FUNCTION__, err->message);
105                 g_error_free (err);
106                 err = NULL;
107                 result = FALSE;
108         } else {        
109                 /* The server account is in the item after the connection name: */
110                 GSList *list_connection = g_slist_append (list, (gpointer)connection_name);
111                 list_connection = g_slist_append (list_connection, (gpointer)server_account_name);
112         
113                 /* Reset the changed list: */
114                 modest_conf_set_list (conf, MODEST_CONF_CONNECTION_SPECIFIC_SMTP_LIST, list_connection,
115                                                     MODEST_CONF_VALUE_STRING, &err);
116                 if (err) {
117                         g_printerr ("modest: %s: error setting list: %s.\n", __FUNCTION__, err->message);
118                         g_error_free (err);
119                         result = FALSE;
120                 }
121         }
122                                 
123         /* TODO: Should we free the items too, or just the list? */
124         g_slist_free (list);
125         
126         return result;
127 }
128
129 /**
130  * modest_account_mgr_remove_connection_specific_smtp
131  * @self: a ModestAccountMgr instance
132  * @name: the account name
133  * @connection_name: A libconic IAP connection name
134  * 
135  * Disassacoiate a server account to use with the specific connection for this account.
136  *
137  * Returns: TRUE if it worked, FALSE otherwise
138  */                              
139 gboolean modest_account_mgr_remove_connection_specific_smtp (ModestAccountMgr *self, 
140         const gchar* connection_name)
141 {
142         ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
143         
144         gboolean result = TRUE;
145         GError *err = NULL;
146         GSList *list = modest_conf_get_list (priv->modest_conf, 
147                                                         MODEST_CONF_CONNECTION_SPECIFIC_SMTP_LIST,
148                                                     MODEST_CONF_VALUE_STRING, &err);
149         if (err) {
150                 g_printerr ("modest: %s: error getting list: %s.\n", __FUNCTION__, err->message);
151                 g_error_free (err);
152                 err = NULL;
153                 result = FALSE;
154         }
155
156         if (!list)
157                 return FALSE;
158                 
159         /* The server account is in the item after the connection name: */
160         GSList *list_connection = g_slist_find_custom (list, connection_name, (GCompareFunc)strcmp);
161         if (list_connection) {
162                 /* remove both items: */
163                 GSList *temp = g_slist_delete_link(list_connection, list_connection);
164                 temp = g_slist_delete_link(temp, g_slist_next(temp));
165         }
166         
167         /* Reset the changed list: */
168         modest_conf_set_list (priv->modest_conf, MODEST_CONF_CONNECTION_SPECIFIC_SMTP_LIST, list,
169                                                     MODEST_CONF_VALUE_STRING, &err);
170         if (err) {
171                 g_printerr ("modest: %s: error setting list: %s.\n", __FUNCTION__, err->message);
172                 g_error_free (err);
173                 result = FALSE;
174         }
175                                 
176         /* TODO: Should we free the items too, or just the list? */
177         g_slist_free (list);
178         
179         return result;
180 }
181
182
183 gboolean modest_account_mgr_get_use_connection_specific_smtp (ModestAccountMgr *self, const gchar* account_name)
184 {
185         return modest_account_mgr_get_bool (self, account_name, 
186                 MODEST_ACCOUNT_USE_CONNECTION_SPECIFIC_SMTP, FALSE);
187 }
188
189 gboolean modest_account_mgr_set_use_connection_specific_smtp (ModestAccountMgr *self, const gchar* account_name, 
190         gboolean new_value)
191 {
192         return modest_account_mgr_set_bool (self, account_name, MODEST_ACCOUNT_USE_CONNECTION_SPECIFIC_SMTP, 
193                 new_value, FALSE);
194 }
195
196 /**
197  * modest_account_mgr_get_connection_specific_smtp
198  * @self: a ModestAccountMgr instance
199  * @connection_name: A libconic IAP connection name
200  * 
201  * Retrieve a server account to use with this specific connection for this account.
202  *
203  * Returns: a server account name to use for this connection, or NULL if none is specified.
204  */                      
205 gchar* modest_account_mgr_get_connection_specific_smtp (ModestAccountMgr *self,  const gchar* connection_name)
206 {
207         gchar *result = NULL;
208         
209         ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
210         
211         GError *err = NULL;
212         GSList *list = modest_conf_get_list (priv->modest_conf, MODEST_CONF_CONNECTION_SPECIFIC_SMTP_LIST,
213                                                     MODEST_CONF_VALUE_STRING, &err);
214         if (err) {
215                 g_printerr ("modest: %s: error getting list: %s.\n", __FUNCTION__, err->message);
216                 g_error_free (err);
217                 err = NULL;
218         }
219
220         if (!list)
221                 return NULL;
222
223         /* The server account is in the item after the connection name: */
224         GSList *iter = list;
225         while (iter) {
226                 const gchar* this_connection_name = (const gchar*)(iter->data);
227                 if (strcmp (this_connection_name, connection_name) == 0) {
228                         iter = g_slist_next (iter);
229                         
230                         if (iter) {
231                                 const gchar* account_name = (const gchar*)(iter->data);
232                                 if (account_name) {
233                                         result = g_strdup (account_name);
234                                         break;
235                                 }
236                         }
237                 }
238                 
239                 /* Skip 2 to go to the next connection in the list: */
240                 iter = g_slist_next (iter);
241                 if (iter)
242                         iter = g_slist_next (iter);
243         }
244                 
245         /*
246         if (!result) {
247                 printf ("  debug: no server found for connection_name=%s.\n", connection_name); 
248         }
249         */
250                                 
251         /* TODO: Should we free the items too, or just the list? */
252         g_slist_free (list);
253         
254         return result;
255 }
256                                          
257 gchar*
258 modest_account_mgr_get_server_account_username (ModestAccountMgr *self, const gchar* account_name)
259 {
260         return modest_account_mgr_get_string (self, account_name, MODEST_ACCOUNT_USERNAME, 
261                 TRUE /* server account */);
262 }
263
264 void
265 modest_account_mgr_set_server_account_username (ModestAccountMgr *self, const gchar* account_name, 
266         const gchar* username)
267 {
268         /* Note that this won't work properly as long as the gconf cache is broken 
269          * in Maemo Bora: */
270         gchar *existing_username = modest_account_mgr_get_server_account_username(self, 
271                 account_name);
272         
273         modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_USERNAME, 
274                 username, TRUE /* server account */);
275                 
276         /* We don't know anything about new usernames: */
277         if (strcmp (existing_username, username) != 0)
278                 modest_account_mgr_get_server_account_username_has_succeeded (self, account_name);
279                 
280         g_free (existing_username);
281 }
282
283 gboolean
284 modest_account_mgr_get_server_account_username_has_succeeded (ModestAccountMgr *self, const gchar* account_name)
285 {
286         return modest_account_mgr_get_bool (self, account_name, MODEST_ACCOUNT_USERNAME_HAS_SUCCEEDED, 
287                                             TRUE /* server account */);
288 }
289
290 void
291 modest_account_mgr_set_server_account_username_has_succeeded (ModestAccountMgr *self, 
292                                                   const gchar* account_name, 
293                                                   gboolean succeeded)
294 {
295         modest_account_mgr_set_bool (self, account_name, MODEST_ACCOUNT_USERNAME_HAS_SUCCEEDED, 
296                                      succeeded, TRUE /* server account */);
297 }
298
299 void
300 modest_account_mgr_set_server_account_password (ModestAccountMgr *self, const gchar* account_name, 
301                                     const gchar* password)
302 {
303         modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_PASSWORD, 
304                                        password, TRUE /* server account */);
305 }
306
307         
308 gchar*
309 modest_account_mgr_get_server_account_password (ModestAccountMgr *self, const gchar* account_name)
310 {
311         return modest_account_mgr_get_string (self, account_name, MODEST_ACCOUNT_PASSWORD, 
312                 TRUE /* server account */);     
313 }
314
315 gboolean
316 modest_account_mgr_get_server_account_has_password (ModestAccountMgr *self, const gchar* account_name)
317 {
318         gboolean result = FALSE;
319         gchar *password = modest_account_mgr_get_string (self, account_name, MODEST_ACCOUNT_PASSWORD, 
320                 TRUE /* server account */);
321         if (password && strlen (password)) {
322                 result = TRUE;
323         }
324         
325         g_free (password);
326         return result;
327 }
328                          
329         
330 gchar*
331 modest_account_mgr_get_server_account_hostname (ModestAccountMgr *self, 
332                                                 const gchar* account_name)
333 {
334         return modest_account_mgr_get_string (self, 
335                                               account_name, 
336                                               MODEST_ACCOUNT_HOSTNAME, 
337                                               TRUE /* server account */);
338 }
339  
340 void
341 modest_account_mgr_set_server_account_hostname (ModestAccountMgr *self, 
342                                                 const gchar *server_account_name,
343                                                 const gchar *hostname)
344 {
345         modest_account_mgr_set_string (self, 
346                                        server_account_name,
347                                        MODEST_ACCOUNT_HOSTNAME, 
348                                        hostname, 
349                                        TRUE /* server account */);
350 }
351
352
353 static ModestAuthProtocol
354 get_secure_auth_for_conf_string(const gchar* value)
355 {
356         ModestAuthProtocol result = MODEST_PROTOCOL_AUTH_NONE;
357         if (value) {
358                 if (strcmp(value, MODEST_ACCOUNT_AUTH_MECH_VALUE_NONE) == 0)
359                         result = MODEST_PROTOCOL_AUTH_NONE;
360                 else if (strcmp(value, MODEST_ACCOUNT_AUTH_MECH_VALUE_PASSWORD) == 0)
361                         result = MODEST_PROTOCOL_AUTH_PASSWORD;
362                 else if (strcmp(value, MODEST_ACCOUNT_AUTH_MECH_VALUE_CRAMMD5) == 0)
363                         result = MODEST_PROTOCOL_AUTH_CRAMMD5;
364         }
365         
366         return result;
367 }
368
369 ModestAuthProtocol
370 modest_account_mgr_get_server_account_secure_auth (ModestAccountMgr *self, 
371         const gchar* account_name)
372 {
373         ModestAuthProtocol result = MODEST_PROTOCOL_AUTH_NONE;
374         gchar* value = modest_account_mgr_get_string (self, account_name, MODEST_ACCOUNT_AUTH_MECH, 
375                 TRUE /* server account */);
376         if (value) {
377                 result = get_secure_auth_for_conf_string (value);
378                         
379                 g_free (value);
380         }
381         
382         return result;
383 }
384
385
386 void
387 modest_account_mgr_set_server_account_secure_auth (ModestAccountMgr *self, 
388         const gchar* account_name, ModestAuthProtocol secure_auth)
389 {
390         /* Get the conf string for the enum value: */
391         const gchar* str_value = NULL;
392         if (secure_auth == MODEST_PROTOCOL_AUTH_NONE)
393                 str_value = MODEST_ACCOUNT_AUTH_MECH_VALUE_NONE;
394         else if (secure_auth == MODEST_PROTOCOL_AUTH_PASSWORD)
395                 str_value = MODEST_ACCOUNT_AUTH_MECH_VALUE_PASSWORD;
396         else if (secure_auth == MODEST_PROTOCOL_AUTH_CRAMMD5)
397                 str_value = MODEST_ACCOUNT_AUTH_MECH_VALUE_CRAMMD5;
398         
399         /* Set it in the configuration: */
400         modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_AUTH_MECH, str_value, TRUE);
401 }
402
403 static ModestConnectionProtocol
404 get_security_for_conf_string(const gchar* value)
405 {
406         ModestConnectionProtocol result = MODEST_PROTOCOL_CONNECTION_NORMAL;
407         if (value) {
408                 if (strcmp(value, MODEST_ACCOUNT_SECURITY_VALUE_NONE) == 0)
409                         result = MODEST_PROTOCOL_CONNECTION_NORMAL;
410                 else if (strcmp(value, MODEST_ACCOUNT_SECURITY_VALUE_NORMAL) == 0) {
411                         /* The UI has "Normal (TLS)": */
412                         result = MODEST_PROTOCOL_CONNECTION_TLS;
413                 } else if (strcmp(value, MODEST_ACCOUNT_SECURITY_VALUE_SSL) == 0)
414                         result = MODEST_PROTOCOL_CONNECTION_SSL;
415         }
416         
417         return result;
418 }
419
420 ModestConnectionProtocol
421 modest_account_mgr_get_server_account_security (ModestAccountMgr *self, 
422         const gchar* account_name)
423 {
424         ModestConnectionProtocol result = MODEST_PROTOCOL_CONNECTION_NORMAL;
425         gchar* value = modest_account_mgr_get_string (self, account_name, MODEST_ACCOUNT_SECURITY, 
426                 TRUE /* server account */);
427         if (value) {
428                 result = get_security_for_conf_string (value);
429                         
430                 g_free (value);
431         }
432         
433         return result;
434 }
435
436 void
437 modest_account_mgr_set_server_account_security (ModestAccountMgr *self, 
438         const gchar* account_name, ModestConnectionProtocol security)
439 {
440         /* Get the conf string for the enum value: */
441         const gchar* str_value = NULL;
442         if (security == MODEST_PROTOCOL_CONNECTION_NORMAL)
443                 str_value = MODEST_ACCOUNT_SECURITY_VALUE_NONE;
444         else if (security == MODEST_PROTOCOL_CONNECTION_TLS) {
445                 /* The UI has "Normal (TLS)": */
446                 str_value = MODEST_ACCOUNT_SECURITY_VALUE_NORMAL;
447         } else if (security == MODEST_PROTOCOL_CONNECTION_SSL)
448                 str_value = MODEST_ACCOUNT_SECURITY_VALUE_SSL;
449         
450         /* Set it in the configuration: */
451         modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_SECURITY, str_value, TRUE);
452 }
453
454 ModestServerAccountData*
455 modest_account_mgr_get_server_account_data (ModestAccountMgr *self, const gchar* name)
456 {
457         ModestServerAccountData *data;
458         gchar *proto;
459         
460         g_return_val_if_fail (modest_account_mgr_account_exists (self, name, TRUE), NULL);      
461         data = g_slice_new0 (ModestServerAccountData);
462         
463         data->account_name = g_strdup (name);
464         data->hostname     = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_HOSTNAME,TRUE);
465         data->username     = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_USERNAME,TRUE);  
466         proto              = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_PROTO, TRUE);
467         data->proto        = modest_protocol_info_get_transport_store_protocol (proto);
468         g_free (proto);
469
470         data->port         = modest_account_mgr_get_int (self, name, MODEST_ACCOUNT_PORT, TRUE);
471         
472         gchar *secure_auth_str = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_AUTH_MECH, TRUE);
473         data->secure_auth  = get_secure_auth_for_conf_string(secure_auth_str);
474         g_free (secure_auth_str);
475                 
476         gchar *security_str = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_SECURITY, TRUE);
477         data->security     = get_security_for_conf_string(security_str);
478         g_free (security_str);
479         
480         data->last_updated = modest_account_mgr_get_int    (self, name, MODEST_ACCOUNT_LAST_UPDATED,TRUE);
481         
482         data->password     = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_PASSWORD, TRUE);            
483         
484         return data;
485 }
486
487
488 void
489 modest_account_mgr_free_server_account_data (ModestAccountMgr *self,
490                                              ModestServerAccountData* data)
491 {
492         g_return_if_fail (self);
493
494         if (!data)
495                 return; /* not an error */
496
497         g_free (data->account_name);
498         data->account_name = NULL;
499         
500         g_free (data->hostname);
501         data->hostname = NULL;
502         
503         g_free (data->username);
504         data->username = NULL;
505
506         g_free (data->password);
507         data->password = NULL;
508
509         g_slice_free (ModestServerAccountData, data);
510 }
511
512 /** You must use modest_account_mgr_free_account_data() on the result.
513  */
514 ModestAccountData *
515 modest_account_mgr_get_account_data (ModestAccountMgr *self, 
516                                      const gchar* name)
517 {
518         ModestAccountData *data;
519         gchar *server_account;
520         gchar *default_account;
521         
522         g_return_val_if_fail (self, NULL);
523         g_return_val_if_fail (name, NULL);
524         
525         if (!modest_account_mgr_account_exists (self, name, FALSE)) {
526                 /* For instance, maybe you are mistakenly checking for a server account name? */
527                 g_warning ("%s: Account %s does not exist.", __FUNCTION__, name);
528                 return NULL;
529         }
530         
531         data = g_slice_new0 (ModestAccountData);
532         
533         data->account_name = g_strdup (name);
534
535         data->display_name = modest_account_mgr_get_string (self, name,
536                                                             MODEST_ACCOUNT_DISPLAY_NAME,
537                                                             FALSE);
538         data->fullname     = modest_account_mgr_get_string (self, name,
539                                                               MODEST_ACCOUNT_FULLNAME,
540                                                                FALSE);
541         data->email        = modest_account_mgr_get_string (self, name,
542                                                             MODEST_ACCOUNT_EMAIL,
543                                                             FALSE);
544         data->is_enabled   = modest_account_mgr_get_enabled (self, name);
545
546         default_account    = modest_account_mgr_get_default_account (self);
547         data->is_default   = (default_account && strcmp (default_account, name) == 0);
548         g_free (default_account);
549
550         /* store */
551         server_account     = modest_account_mgr_get_string (self, name,
552                                                             MODEST_ACCOUNT_STORE_ACCOUNT,
553                                                             FALSE);
554         if (server_account) {
555                 data->store_account =
556                         modest_account_mgr_get_server_account_data (self, server_account);
557                 g_free (server_account);
558         }
559
560         /* transport */
561         server_account = modest_account_mgr_get_string (self, name,
562                                                         MODEST_ACCOUNT_TRANSPORT_ACCOUNT,
563                                                         FALSE);
564         if (server_account) {
565                 data->transport_account =
566                         modest_account_mgr_get_server_account_data (self, server_account);
567                 g_free (server_account);
568         }
569
570         return data;
571 }
572
573
574 void
575 modest_account_mgr_free_account_data (ModestAccountMgr *self, ModestAccountData *data)
576 {
577         g_return_if_fail (self);
578
579         if (!data) /* not an error */ 
580                 return;
581
582         g_free (data->account_name);
583         g_free (data->display_name);
584         g_free (data->fullname);
585         g_free (data->email);
586
587         modest_account_mgr_free_server_account_data (self, data->store_account);
588         modest_account_mgr_free_server_account_data (self, data->transport_account);
589         
590         g_slice_free (ModestAccountData, data);
591 }
592
593 gint 
594 on_accounts_list_sort_by_title(gconstpointer a, gconstpointer b)
595 {
596         return g_utf8_collate((const gchar*)a, (const gchar*)b);
597 }
598
599 /** Get the first one, alphabetically, by title. */
600 gchar* 
601 modest_account_mgr_get_first_account_name (ModestAccountMgr *self)
602 {
603         const gchar* account_name = NULL;
604         GSList *account_names = modest_account_mgr_account_names (self, TRUE /* only enabled */);
605
606         /* Return TRUE if there is no account */
607         if (!account_names)
608                 return NULL;
609
610         /* Get the first one, alphabetically, by title: */
611         /* gchar *old_default = modest_account_mgr_get_default_account (self); */
612         GSList* list_sorted = g_slist_sort (account_names, on_accounts_list_sort_by_title);
613
614         GSList* iter = list_sorted;
615         gboolean found = FALSE;
616         while (iter && !found) {
617                 account_name = (const gchar*)list_sorted->data;
618
619                 if (account_name)
620                         found = TRUE;
621
622                 if (!found)
623                         iter = g_slist_next (iter);
624         }
625
626         gchar* result = NULL;
627         if (account_name)
628                 result = g_strdup (account_name);
629                 
630         modest_account_mgr_free_account_names (account_names);
631         account_names = NULL;
632
633         return result;
634 }
635
636 gboolean
637 modest_account_mgr_set_first_account_as_default (ModestAccountMgr *self)
638 {
639         gboolean result = FALSE;
640         
641         gchar* account_name = modest_account_mgr_get_first_account_name(self);
642         if (account_name) {
643                 result = modest_account_mgr_set_default_account (self, account_name);
644                 g_free (account_name);
645         }
646         else
647                 result = TRUE; /* If there are no accounts then it's not a failure. */
648
649         return result;
650 }
651
652 gchar*
653 modest_account_mgr_get_from_string (ModestAccountMgr *self, const gchar* name)
654 {
655         gchar *fullname, *email, *from;
656         
657         g_return_val_if_fail (self, NULL);
658         g_return_val_if_fail (name, NULL);
659
660         fullname      = modest_account_mgr_get_string (self, name,MODEST_ACCOUNT_FULLNAME,
661                                                        FALSE);
662         email         = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_EMAIL,
663                                                        FALSE);
664         from = g_strdup_printf ("%s <%s>",
665                                 fullname ? fullname : "",
666                                 email    ? email    : "");
667         g_free (fullname);
668         g_free (email);
669
670         return from;
671 }
672
673 /* Add a number to the end of the text, or increment a number that is already there.
674  */
675 static gchar*
676 util_increment_name (const gchar* text)
677 {
678         /* Get the end character,
679          * also doing a UTF-8 validation which is required for using g_utf8_prev_char().
680          */
681         const gchar* end = NULL;
682         if (!g_utf8_validate (text, -1, &end))
683                 return NULL;
684   
685         if (!end)
686                 return NULL;
687                 
688         --end; /* Go to before the null-termination. */
689                 
690         /* Look at each UTF-8 characer, starting at the end: */
691         const gchar* p = end;
692         const gchar* alpha_end = NULL;
693         while (p)
694         {       
695                 /* Stop when we reach the first character that is not a numeric digit: */
696                 const gunichar ch = g_utf8_get_char (p);
697                 if (!g_unichar_isdigit (ch)) {
698                         alpha_end = p;
699                         break;
700                 }
701                 
702                 p = g_utf8_prev_char (p);       
703         }
704         
705         if(!alpha_end) {
706                 /* The text must consist completely of numeric digits. */
707                 alpha_end = text;
708         }
709         else
710                 ++alpha_end;
711         
712         /* Intepret and increment the number, if any: */
713         gint num = atol (alpha_end);
714         ++num;
715         
716         /* Get the name part: */
717         gint name_len = alpha_end - text;
718         gchar *name_without_number = g_malloc(name_len + 1);
719         memcpy (name_without_number, text, name_len);
720         name_without_number[name_len] = 0;\
721         
722     /* Concatenate the text part and the new number: */ 
723         gchar *result = g_strdup_printf("%s%d", name_without_number, num);
724         g_free (name_without_number);
725         
726         return result;  
727 }
728
729 gchar*
730 modest_account_mgr_get_unused_account_name (ModestAccountMgr *self, const gchar* starting_name,
731         gboolean server_account)
732 {
733         gchar *account_name = g_strdup (starting_name);
734
735         while (modest_account_mgr_account_exists (self, 
736                 account_name, server_account /*  server_account */)) {
737                         
738                 gchar * account_name2 = util_increment_name (account_name);
739                 g_free (account_name);
740                 account_name = account_name2;
741         }
742         
743         return account_name;
744 }
745
746 gchar*
747 modest_account_mgr_get_unused_account_display_name (ModestAccountMgr *self, const gchar* starting_name)
748 {
749         gchar *account_name = g_strdup (starting_name);
750
751         while (modest_account_mgr_account_with_display_name_exists (self, account_name)) {
752                         
753                 gchar * account_name2 = util_increment_name (account_name);
754                 g_free (account_name);
755                 account_name = account_name2;
756         }
757         
758         return account_name;
759 }
760
761 void 
762 modest_account_mgr_set_leave_on_server (ModestAccountMgr *self, 
763                                         const gchar *account_name, 
764                                         gboolean leave_on_server)
765 {
766         modest_account_mgr_set_bool (self, 
767                                      account_name,
768                                      MODEST_ACCOUNT_LEAVE_ON_SERVER, 
769                                      leave_on_server, 
770                                      FALSE);
771 }
772
773 gboolean 
774 modest_account_mgr_get_leave_on_server (ModestAccountMgr *self, 
775                                         const gchar* account_name)
776 {
777         return modest_account_mgr_get_bool (self, 
778                                             account_name,
779                                             MODEST_ACCOUNT_LEAVE_ON_SERVER, 
780                                             FALSE);
781 }
782
783 gint 
784 modest_account_mgr_get_last_updated (ModestAccountMgr *self, 
785                                      const gchar* account_name)
786 {
787         return modest_account_mgr_get_int (modest_runtime_get_account_mgr (), 
788                                            account_name, 
789                                            MODEST_ACCOUNT_LAST_UPDATED, 
790                                            TRUE);
791 }
792
793 void 
794 modest_account_mgr_set_last_updated (ModestAccountMgr *self, 
795                                      const gchar* account_name,
796                                      gint time)
797 {
798         modest_account_mgr_set_int (self, 
799                                     account_name, 
800                                     MODEST_ACCOUNT_LAST_UPDATED, 
801                                     time, 
802                                     TRUE);
803
804         /* TODO: notify about changes */
805 }
806
807 gint  
808 modest_account_mgr_get_retrieve_limit (ModestAccountMgr *self, 
809                                        const gchar* account_name)
810 {
811         return modest_account_mgr_get_int (self, 
812                                            account_name,
813                                            MODEST_ACCOUNT_LIMIT_RETRIEVE, 
814                                            FALSE);
815 }
816
817 void  
818 modest_account_mgr_set_retrieve_limit (ModestAccountMgr *self, 
819                                        const gchar* account_name,
820                                        gint limit_retrieve)
821 {
822         modest_account_mgr_set_int (self, 
823                                     account_name,
824                                     MODEST_ACCOUNT_LIMIT_RETRIEVE, 
825                                     limit_retrieve, 
826                                     FALSE /* not server account */);
827 }
828
829 gint  
830 modest_account_mgr_get_server_account_port (ModestAccountMgr *self, 
831                                             const gchar* account_name)
832 {
833         return modest_account_mgr_get_int (self, 
834                                            account_name,
835                                            MODEST_ACCOUNT_PORT, 
836                                            TRUE);
837 }
838
839 void
840 modest_account_mgr_set_server_account_port (ModestAccountMgr *self, 
841                                             const gchar *account_name,
842                                             gint port_num)
843 {
844         modest_account_mgr_set_int (self, 
845                                     account_name,
846                                     MODEST_ACCOUNT_PORT, 
847                                     port_num, TRUE /* server account */);
848 }
849
850 gchar* 
851 modest_account_mgr_get_server_account_name (ModestAccountMgr *self, 
852                                             const gchar *account_name,
853                                             TnyAccountType account_type)
854 {
855         return modest_account_mgr_get_string (self, 
856                                               account_name,
857                                               (account_type == TNY_ACCOUNT_TYPE_STORE) ?
858                                               MODEST_ACCOUNT_STORE_ACCOUNT :
859                                               MODEST_ACCOUNT_TRANSPORT_ACCOUNT, 
860                                               FALSE);
861 }
862
863 gchar* 
864 modest_account_mgr_get_retrieve_type (ModestAccountMgr *self, 
865                                       const gchar *account_name)
866 {
867         return modest_account_mgr_get_string (self, 
868                                               account_name,
869                                               MODEST_ACCOUNT_RETRIEVE, 
870                                               FALSE /* not server account */);
871 }
872
873 void 
874 modest_account_mgr_set_retrieve_type (ModestAccountMgr *self, 
875                                       const gchar *account_name,
876                                       const gchar *retrieve_type)
877 {
878         modest_account_mgr_set_string (self, 
879                                        account_name,
880                                        MODEST_ACCOUNT_RETRIEVE, 
881                                        retrieve_type, 
882                                        FALSE /* not server account */);
883 }
884
885
886 void
887 modest_account_mgr_set_user_fullname (ModestAccountMgr *self, 
888                                       const gchar *account_name,
889                                       const gchar *fullname)
890 {
891         modest_account_mgr_set_string (self, 
892                                        account_name,
893                                        MODEST_ACCOUNT_FULLNAME, 
894                                        fullname, 
895                                        FALSE /* not server account */);
896 }
897
898 void
899 modest_account_mgr_set_user_email (ModestAccountMgr *self, 
900                                    const gchar *account_name,
901                                    const gchar *email)
902 {
903         modest_account_mgr_set_string (self, 
904                                        account_name,
905                                        MODEST_ACCOUNT_EMAIL, 
906                                        email, 
907                                        FALSE /* not server account */);
908 }