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