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