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