2007-07-09 Murray Cumming <murrayc@murrayc.com>
[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_display_name (ModestAccountMgr *self, 
61         const gchar* name)
62 {
63         return modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_DISPLAY_NAME, FALSE);
64 }
65
66
67
68 gchar* modest_account_mgr_get_signature (ModestAccountMgr *self, const gchar* name, 
69         gboolean* use_signature)
70 {
71         if (use_signature) {
72                 *use_signature = 
73                         modest_account_mgr_get_bool (self, name, MODEST_ACCOUNT_USE_SIGNATURE, FALSE);
74         }
75         
76         return modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_SIGNATURE, FALSE);
77 }
78
79
80 ModestTransportStoreProtocol modest_account_mgr_get_store_protocol (ModestAccountMgr *self, const gchar* name)
81 {
82         ModestTransportStoreProtocol result = MODEST_PROTOCOL_STORE_POP; /* Arbitrary default */
83         
84         gchar *server_account_name = modest_account_mgr_get_string (self, name,
85                                                         MODEST_ACCOUNT_STORE_ACCOUNT,
86                                                         FALSE);
87         if (server_account_name) {
88                 ModestServerAccountData* server_data = 
89                         modest_account_mgr_get_server_account_data (self, server_account_name);
90                 result = server_data->proto;
91                         
92                 modest_account_mgr_free_server_account_data (self, server_data);
93                 
94                 g_free (server_account_name);
95         }
96         
97         return result;
98 }
99
100 gboolean modest_account_mgr_set_connection_specific_smtp (ModestAccountMgr *self, 
101         const gchar* account_name,
102         const gchar* connection_name, const gchar* server_account_name)
103 {
104         modest_account_mgr_remove_connection_specific_smtp (self, account_name, connection_name);
105         
106         GSList *list = modest_account_mgr_get_list (self, account_name, 
107                                                         MODEST_ACCOUNT_CONNECTION_SPECIFIC_SMTP_LIST,
108                                                     MODEST_CONF_VALUE_STRING, FALSE);
109                 
110         /* The server account is in the item after the connection name: */
111         GSList *list_connection = g_slist_append (list, (gpointer)connection_name);
112         list_connection = g_slist_append (list_connection, (gpointer)server_account_name);
113         
114         /* Reset the changed list: */
115         modest_account_mgr_set_list (self, account_name, 
116                                                         MODEST_ACCOUNT_CONNECTION_SPECIFIC_SMTP_LIST, list_connection,
117                                                     MODEST_CONF_VALUE_STRING, FALSE);
118                                 
119         /* TODO: Should we free the items too, or just the list? */
120         g_slist_free (list);
121         
122         return TRUE;
123 }
124
125 /**
126  * modest_account_mgr_remove_connection_specific_smtp
127  * @self: a ModestAccountMgr instance
128  * @name: the account name
129  * @connection_name: A libconic IAP connection name
130  * 
131  * Disassacoiate a server account to use with the specific connection for this account.
132  *
133  * Returns: TRUE if it worked, FALSE otherwise
134  */                              
135 gboolean modest_account_mgr_remove_connection_specific_smtp (ModestAccountMgr *self, 
136         const gchar* account_name, const gchar* connection_name)
137 {
138         GSList *list = modest_account_mgr_get_list (self, account_name, 
139                                                         MODEST_ACCOUNT_CONNECTION_SPECIFIC_SMTP_LIST,
140                                                     MODEST_CONF_VALUE_STRING, FALSE);
141         if (!list)
142                 return FALSE;
143                 
144         /* The server account is in the item after the connection name: */
145         GSList *list_connection = g_slist_find_custom (list, connection_name, (GCompareFunc)strcmp);
146         if (list_connection) {
147                 /* remove both items: */
148                 GSList *temp = g_slist_delete_link(list_connection, list_connection);
149                 temp = g_slist_delete_link(temp, g_slist_next(temp));
150         }
151         
152         /* Reset the changed list: */
153         modest_account_mgr_set_list (self, account_name, 
154                                                         MODEST_ACCOUNT_CONNECTION_SPECIFIC_SMTP_LIST, list,
155                                                     MODEST_CONF_VALUE_STRING, FALSE);
156                                 
157         /* TODO: Should we free the items too, or just the list? */
158         g_slist_free (list);
159         
160         return TRUE;
161 }
162
163 gboolean modest_account_mgr_get_has_connection_specific_smtp (ModestAccountMgr *self, const gchar* account_name)
164 {
165         GSList *list = modest_account_mgr_get_list (self, account_name, 
166                                                         MODEST_ACCOUNT_CONNECTION_SPECIFIC_SMTP_LIST,
167                                                     MODEST_CONF_VALUE_STRING, FALSE);
168         if (!list)
169                 return FALSE;
170         
171         /* TODO: Should we free the items too, or just the list? */
172         g_slist_free (list);
173         
174         return TRUE;
175 }
176
177 /**
178  * modest_account_mgr_get_connection_specific_smtp
179  * @self: a ModestAccountMgr instance
180  * @name: the account name
181  * @connection_name: A libconic IAP connection name
182  * 
183  * Retrieve a server account to use with this specific connection for this account.
184  *
185  * Returns: a server account name to use for this connection, or NULL if none is specified.
186  */                      
187 gchar* modest_account_mgr_get_connection_specific_smtp (ModestAccountMgr *self, const gchar* account_name,
188                                          const gchar* connection_name)
189 {
190         gchar *result = NULL;
191         
192         GSList *list = modest_account_mgr_get_list (self, account_name, 
193                                                         MODEST_ACCOUNT_CONNECTION_SPECIFIC_SMTP_LIST,
194                                                     MODEST_CONF_VALUE_STRING, FALSE);
195         if (!list)
196                 return NULL;
197
198         /* The server account is in the item after the connection name: */
199         GSList *iter = list;
200         while (iter) {
201                 const gchar* this_connection_name = (const gchar*)(iter->data);
202                 if (strcmp (this_connection_name, connection_name) == 0) {
203                         iter = g_slist_next (iter);
204                         
205                         if (iter) {
206                                 const gchar* account_name = (const gchar*)(iter->data);
207                                 if (account_name) {
208                                         result = g_strdup (account_name);
209                                         break;
210                                 }
211                         }
212                 }
213                 
214                 /* Skip 2 to go to the next connection in the list: */
215                 iter = g_slist_next (iter);
216                 if (iter)
217                         iter = g_slist_next (iter);
218         }
219                 
220         /*
221         if (!result) {
222                 printf ("  debug: no server found for connection_name=%s.\n", connection_name); 
223         }
224         */
225                                 
226         /* TODO: Should we free the items too, or just the list? */
227         g_slist_free (list);
228         
229         return result;
230 }
231                                          
232 gchar*
233 modest_server_account_get_username (ModestAccountMgr *self, const gchar* account_name)
234 {
235         return modest_account_mgr_get_string (self, account_name, MODEST_ACCOUNT_USERNAME, 
236                 TRUE /* server account */);
237 }
238
239 void
240 modest_server_account_set_username (ModestAccountMgr *self, const gchar* account_name, 
241         const gchar* username)
242 {
243         /* Note that this won't work properly as long as the gconf cache is broken 
244          * in Maemo Bora: */
245         gchar *existing_username = modest_server_account_get_username(self, 
246                 account_name);
247         
248         modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_USERNAME, 
249                 username, TRUE /* server account */);
250                 
251         /* We don't know anything about new usernames: */
252         if (strcmp (existing_username, username) != 0)
253                 modest_server_account_set_username_has_succeeded (self, 
254                 account_name, FALSE);
255                 
256         g_free (existing_username);
257 }
258
259 gboolean
260 modest_server_account_get_username_has_succeeded (ModestAccountMgr *self, const gchar* account_name)
261 {
262         return modest_account_mgr_get_bool (self, account_name, MODEST_ACCOUNT_USERNAME_HAS_SUCCEEDED, 
263                                             TRUE /* server account */);
264 }
265
266 void
267 modest_server_account_set_username_has_succeeded (ModestAccountMgr *self, const gchar* account_name, 
268         gboolean succeeded)
269 {
270         modest_account_mgr_set_bool (self, account_name, MODEST_ACCOUNT_USERNAME_HAS_SUCCEEDED, 
271                                      succeeded, TRUE /* server account */);
272 }
273
274 void
275 modest_server_account_set_password (ModestAccountMgr *self, const gchar* account_name, 
276                                     const gchar* password)
277 {
278         modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_PASSWORD, 
279                                        password, TRUE /* server account */);
280 }
281         
282 gchar*
283 modest_server_account_get_hostname (ModestAccountMgr *self, const gchar* account_name)
284 {
285         return modest_account_mgr_get_string (self, account_name, MODEST_ACCOUNT_HOSTNAME, 
286                 TRUE /* server account */);
287 }
288  
289
290 static ModestAuthProtocol
291 get_secure_auth_for_conf_string(const gchar* value)
292 {
293         ModestAuthProtocol result = MODEST_PROTOCOL_AUTH_NONE;
294         if (value) {
295                 if (strcmp(value, MODEST_ACCOUNT_AUTH_MECH_VALUE_NONE) == 0)
296                         result = MODEST_PROTOCOL_AUTH_NONE;
297                 else if (strcmp(value, MODEST_ACCOUNT_AUTH_MECH_VALUE_PASSWORD) == 0)
298                         result = MODEST_PROTOCOL_AUTH_PASSWORD;
299                 else if (strcmp(value, MODEST_ACCOUNT_AUTH_MECH_VALUE_CRAMMD5) == 0)
300                         result = MODEST_PROTOCOL_AUTH_CRAMMD5;
301         }
302         
303         return result;
304 }
305
306 ModestAuthProtocol
307 modest_server_account_get_secure_auth (ModestAccountMgr *self, 
308         const gchar* account_name)
309 {
310         ModestAuthProtocol result = MODEST_PROTOCOL_AUTH_NONE;
311         gchar* value = modest_account_mgr_get_string (self, account_name, MODEST_ACCOUNT_AUTH_MECH, 
312                 TRUE /* server account */);
313         if (value) {
314                 result = get_secure_auth_for_conf_string (value);
315                         
316                 g_free (value);
317         }
318         
319         return result;
320 }
321
322
323 void
324 modest_server_account_set_secure_auth (ModestAccountMgr *self, 
325         const gchar* account_name, ModestAuthProtocol secure_auth)
326 {
327         /* Get the conf string for the enum value: */
328         const gchar* str_value = NULL;
329         if (secure_auth == MODEST_PROTOCOL_AUTH_NONE)
330                 str_value = MODEST_ACCOUNT_AUTH_MECH_VALUE_NONE;
331         else if (secure_auth == MODEST_PROTOCOL_AUTH_PASSWORD)
332                 str_value = MODEST_ACCOUNT_AUTH_MECH_VALUE_PASSWORD;
333         else if (secure_auth == MODEST_PROTOCOL_AUTH_CRAMMD5)
334                 str_value = MODEST_ACCOUNT_AUTH_MECH_VALUE_CRAMMD5;
335         
336         /* Set it in the configuration: */
337         modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_AUTH_MECH, str_value, TRUE);
338 }
339
340 static ModestConnectionProtocol
341 get_security_for_conf_string(const gchar* value)
342 {
343         ModestConnectionProtocol result = MODEST_PROTOCOL_CONNECTION_NORMAL;
344         if (value) {
345                 if (strcmp(value, MODEST_ACCOUNT_SECURITY_VALUE_NONE) == 0)
346                         result = MODEST_PROTOCOL_CONNECTION_NORMAL;
347                 else if (strcmp(value, MODEST_ACCOUNT_SECURITY_VALUE_NORMAL) == 0) {
348                         /* The UI has "Normal (TLS)": */
349                         result = MODEST_PROTOCOL_CONNECTION_TLS;
350                 } else if (strcmp(value, MODEST_ACCOUNT_SECURITY_VALUE_SSL) == 0)
351                         result = MODEST_PROTOCOL_CONNECTION_SSL;
352         }
353         
354         return result;
355 }
356
357 ModestConnectionProtocol
358 modest_server_account_get_security (ModestAccountMgr *self, 
359         const gchar* account_name)
360 {
361         ModestConnectionProtocol result = MODEST_PROTOCOL_CONNECTION_NORMAL;
362         gchar* value = modest_account_mgr_get_string (self, account_name, MODEST_ACCOUNT_SECURITY, 
363                 TRUE /* server account */);
364         if (value) {
365                 result = get_security_for_conf_string (value);
366                         
367                 g_free (value);
368         }
369         
370         return result;
371 }
372
373 void
374 modest_server_account_set_security (ModestAccountMgr *self, 
375         const gchar* account_name, ModestConnectionProtocol security)
376 {
377         /* Get the conf string for the enum value: */
378         const gchar* str_value = NULL;
379         if (security == MODEST_PROTOCOL_CONNECTION_NORMAL)
380                 str_value = MODEST_ACCOUNT_SECURITY_VALUE_NONE;
381         else if (security == MODEST_PROTOCOL_CONNECTION_TLS) {
382                 /* The UI has "Normal (TLS)": */
383                 str_value = MODEST_ACCOUNT_SECURITY_VALUE_NORMAL;
384         } else if (security == MODEST_PROTOCOL_CONNECTION_SSL)
385                 str_value = MODEST_ACCOUNT_SECURITY_VALUE_SSL;
386         
387         /* Set it in the configuration: */
388         modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_SECURITY, str_value, TRUE);
389 }
390
391 ModestServerAccountData*
392 modest_account_mgr_get_server_account_data (ModestAccountMgr *self, const gchar* name)
393 {
394         ModestServerAccountData *data;
395         gchar *proto;
396         
397         g_return_val_if_fail (modest_account_mgr_account_exists (self, name, TRUE), NULL);      
398         data = g_slice_new0 (ModestServerAccountData);
399         
400         data->account_name = g_strdup (name);
401         data->hostname     = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_HOSTNAME,TRUE);
402         data->username     = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_USERNAME,TRUE);  
403         proto              = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_PROTO, TRUE);
404         data->proto        = modest_protocol_info_get_transport_store_protocol (proto);
405         g_free (proto);
406
407         data->port         = modest_account_mgr_get_int (self, name, MODEST_ACCOUNT_PORT, TRUE);
408         
409         gchar *secure_auth_str = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_AUTH_MECH, TRUE);
410         data->secure_auth  = get_secure_auth_for_conf_string(secure_auth_str);
411         g_free (secure_auth_str);
412                 
413         gchar *security_str = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_SECURITY, TRUE);
414         data->security     = get_security_for_conf_string(security_str);
415         g_free (security_str);
416         
417         data->last_updated = modest_account_mgr_get_int    (self, name, MODEST_ACCOUNT_LAST_UPDATED,TRUE);
418         
419         data->password     = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_PASSWORD, TRUE);            
420         
421         return data;
422 }
423
424
425 void
426 modest_account_mgr_free_server_account_data (ModestAccountMgr *self,
427                                              ModestServerAccountData* data)
428 {
429         g_return_if_fail (self);
430
431         if (!data)
432                 return; /* not an error */
433
434         g_free (data->account_name);
435         data->account_name = NULL;
436         
437         g_free (data->hostname);
438         data->hostname = NULL;
439         
440         g_free (data->username);
441         data->username = NULL;
442
443         g_free (data->password);
444         data->password = NULL;
445
446         g_slice_free (ModestServerAccountData, data);
447 }
448
449 /** You must use modest_account_mgr_free_account_data() on the result.
450  */
451 ModestAccountData*
452 modest_account_mgr_get_account_data     (ModestAccountMgr *self, const gchar* name)
453 {
454         ModestAccountData *data;
455         gchar *server_account;
456         gchar *default_account;
457         
458         g_return_val_if_fail (self, NULL);
459         g_return_val_if_fail (name, NULL);
460         
461         if (!modest_account_mgr_account_exists (self, name, FALSE)) {
462                 /* For instance, maybe you are mistakenly checking for a server account name? */
463                 g_warning ("%s: Account %s does not exist.", __FUNCTION__, name);
464                 return NULL;
465         }
466         
467         data = g_slice_new0 (ModestAccountData);
468         
469         data->account_name = g_strdup (name);
470
471         data->display_name = modest_account_mgr_get_string (self, name,
472                                                             MODEST_ACCOUNT_DISPLAY_NAME,
473                                                             FALSE);
474         data->fullname     = modest_account_mgr_get_string (self, name,
475                                                               MODEST_ACCOUNT_FULLNAME,
476                                                                FALSE);
477         data->email        = modest_account_mgr_get_string (self, name,
478                                                             MODEST_ACCOUNT_EMAIL,
479                                                             FALSE);
480         data->is_enabled   = modest_account_mgr_get_enabled (self, name);
481
482         default_account    = modest_account_mgr_get_default_account (self);
483         data->is_default   = (default_account && strcmp (default_account, name) == 0);
484         g_free (default_account);
485
486         /* store */
487         server_account     = modest_account_mgr_get_string (self, name,
488                                                             MODEST_ACCOUNT_STORE_ACCOUNT,
489                                                             FALSE);
490         if (server_account) {
491                 data->store_account =
492                         modest_account_mgr_get_server_account_data (self, server_account);
493                 g_free (server_account);
494         }
495
496         /* transport */
497         server_account = modest_account_mgr_get_string (self, name,
498                                                         MODEST_ACCOUNT_TRANSPORT_ACCOUNT,
499                                                         FALSE);
500         if (server_account) {
501                 data->transport_account =
502                         modest_account_mgr_get_server_account_data (self, server_account);
503                 g_free (server_account);
504         }
505
506         return data;
507 }
508
509
510 void
511 modest_account_mgr_free_account_data (ModestAccountMgr *self, ModestAccountData *data)
512 {
513         g_return_if_fail (self);
514
515         if (!data) /* not an error */ 
516                 return;
517
518         g_free (data->account_name);
519         g_free (data->display_name);
520         g_free (data->fullname);
521         g_free (data->email);
522
523         modest_account_mgr_free_server_account_data (self, data->store_account);
524         modest_account_mgr_free_server_account_data (self, data->transport_account);
525         
526         g_slice_free (ModestAccountData, data);
527 }
528
529
530 gchar*
531 modest_account_mgr_get_default_account  (ModestAccountMgr *self)
532 {
533         gchar *account; 
534         ModestConf *conf;
535         GError *err = NULL;
536         
537         g_return_val_if_fail (self, NULL);
538
539         conf = MODEST_ACCOUNT_MGR_GET_PRIVATE (self)->modest_conf;
540         account = modest_conf_get_string (conf, MODEST_CONF_DEFAULT_ACCOUNT, &err);
541         
542         if (err) {
543                 g_printerr ("modest: failed to get '%s': %s\n",
544                             MODEST_CONF_DEFAULT_ACCOUNT, err->message);
545                 g_error_free (err);
546                 g_free (account);
547                 return  NULL;
548         }
549         
550         /* sanity check */
551         if (account && !modest_account_mgr_account_exists (self, account, FALSE)) {
552                 g_printerr ("modest: default account does not exist\n");
553                 g_free (account);
554                 return NULL;
555         }
556
557         return account;
558 }
559
560
561 gboolean
562 modest_account_mgr_set_default_account  (ModestAccountMgr *self, const gchar* account)
563 {
564         ModestConf *conf;
565         
566         g_return_val_if_fail (self,    FALSE);
567         g_return_val_if_fail (account, FALSE);
568         g_return_val_if_fail (modest_account_mgr_account_exists (self, account, FALSE),
569                               FALSE);
570         
571         conf = MODEST_ACCOUNT_MGR_GET_PRIVATE (self)->modest_conf;
572
573         return modest_conf_set_string (conf, MODEST_CONF_DEFAULT_ACCOUNT,
574                                        account, NULL);
575
576 }
577
578 gboolean
579 modest_account_mgr_unset_default_account  (ModestAccountMgr *self)
580 {
581         ModestConf *conf;
582         
583         g_return_val_if_fail (self,    FALSE);
584
585         conf = MODEST_ACCOUNT_MGR_GET_PRIVATE (self)->modest_conf;
586                 
587         return modest_conf_remove_key (conf, MODEST_CONF_DEFAULT_ACCOUNT, NULL /* err */);
588
589 }
590
591 gint on_accounts_list_sort_by_title(gconstpointer a, gconstpointer b)
592 {
593         return g_utf8_collate((const gchar*)a, (const gchar*)b);
594 }
595
596 gboolean
597 modest_account_mgr_set_first_account_as_default  (ModestAccountMgr *self)
598 {
599         gboolean result = FALSE;
600         GSList *account_names = modest_account_mgr_account_names (self, TRUE /* only enabled */);
601
602         /* Return TRUE if there is no account */
603         if (!account_names)
604                 return TRUE;
605                 
606         /* Get the first one, alphabetically, by title: */
607         GSList* list_sorted = g_slist_sort (account_names, 
608                 on_accounts_list_sort_by_title);
609         if(list_sorted) {
610                 const gchar* account_name = (const gchar*)list_sorted->data;
611                 if (account_name) 
612                         result = modest_account_mgr_set_default_account (self, account_name);
613         }
614
615         modest_account_mgr_free_account_names (account_names);
616         account_names = NULL;
617
618         return result;
619 }
620
621 gchar*
622 modest_account_mgr_get_from_string (ModestAccountMgr *self, const gchar* name)
623 {
624         gchar *fullname, *email, *from;
625         
626         g_return_val_if_fail (self, NULL);
627         g_return_val_if_fail (name, NULL);
628
629         fullname      = modest_account_mgr_get_string (self, name,MODEST_ACCOUNT_FULLNAME,
630                                                        FALSE);
631         email         = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_EMAIL,
632                                                        FALSE);
633         from = g_strdup_printf ("%s <%s>",
634                                 fullname ? fullname : "",
635                                 email    ? email    : "");
636         g_free (fullname);
637         g_free (email);
638
639         return from;
640 }
641
642 /* Add a number to the end of the text, or increment a number that is already there.
643  */
644 static gchar*
645 util_increment_name (const gchar* text)
646 {
647         /* Get the end character,
648          * also doing a UTF-8 validation which is required for using g_utf8_prev_char().
649          */
650         const gchar* end = NULL;
651         if (!g_utf8_validate (text, -1, &end))
652                 return NULL;
653   
654         if (!end)
655                 return NULL;
656                 
657         --end; /* Go to before the null-termination. */
658                 
659         /* Look at each UTF-8 characer, starting at the end: */
660         const gchar* p = end;
661         const gchar* alpha_end = NULL;
662         while (p)
663         {       
664                 /* Stop when we reach the first character that is not a numeric digit: */
665                 const gunichar ch = g_utf8_get_char (p);
666                 if (!g_unichar_isdigit (ch)) {
667                         alpha_end = p;
668                         break;
669                 }
670                 
671                 p = g_utf8_prev_char (p);       
672         }
673         
674         if(!alpha_end) {
675                 /* The text must consist completely of numeric digits. */
676                 alpha_end = text;
677         }
678         else
679                 ++alpha_end;
680         
681         /* Intepret and increment the number, if any: */
682         gint num = atol (alpha_end);
683         ++num;
684         
685         /* Get the name part: */
686         gint name_len = alpha_end - text;
687         gchar *name_without_number = g_malloc(name_len + 1);
688         memcpy (name_without_number, text, name_len);
689         name_without_number[name_len] = 0;\
690         
691     /* Concatenate the text part and the new number: */ 
692         gchar *result = g_strdup_printf("%s%d", name_without_number, num);
693         g_free (name_without_number);
694         
695         return result;  
696 }
697
698 gchar*
699 modest_account_mgr_get_unused_account_name (ModestAccountMgr *self, const gchar* starting_name,
700         gboolean server_account)
701 {
702         gchar *account_name = g_strdup (starting_name);
703
704         while (modest_account_mgr_account_exists (self, 
705                 account_name, server_account /*  server_account */)) {
706                         
707                 gchar * account_name2 = util_increment_name (account_name);
708                 g_free (account_name);
709                 account_name = account_name2;
710         }
711         
712         return account_name;
713 }
714
715 gchar*
716 modest_account_mgr_get_unused_account_display_name (ModestAccountMgr *self, const gchar* starting_name)
717 {
718         gchar *account_name = g_strdup (starting_name);
719
720         while (modest_account_mgr_account_with_display_name_exists (self, account_name)) {
721                         
722                 gchar * account_name2 = util_increment_name (account_name);
723                 g_free (account_name);
724                 account_name = account_name2;
725         }
726         
727         return account_name;
728 }