* Fixes NB#91650, fixes a potential problem with strftime
[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 <modest-defs.h>
35 #include <string.h>
36 #include <strings.h>
37
38 static const gchar * null_means_empty (const gchar * str);
39
40 static const gchar *
41 null_means_empty (const gchar * str)
42 {
43         return str ? str : "";
44 }
45
46 gboolean
47 modest_account_mgr_set_enabled (ModestAccountMgr *self, const gchar* name,
48                                         gboolean enabled)
49 {
50         return modest_account_mgr_set_bool (self, name, MODEST_ACCOUNT_ENABLED, enabled,FALSE);
51 }
52
53
54 gboolean
55 modest_account_mgr_get_enabled (ModestAccountMgr *self, const gchar* name)
56 {
57         return modest_account_mgr_get_bool (self, name, MODEST_ACCOUNT_ENABLED, FALSE);
58 }
59
60 gboolean modest_account_mgr_set_signature (ModestAccountMgr *self, const gchar* name, 
61         const gchar* signature, gboolean use_signature)
62 {
63         gboolean result = modest_account_mgr_set_bool (self, name, MODEST_ACCOUNT_USE_SIGNATURE, 
64                 use_signature, FALSE);
65         result = result && modest_account_mgr_set_string (self, name, MODEST_ACCOUNT_SIGNATURE, 
66                                                           null_means_empty (signature), FALSE);
67         return result;
68 }
69
70 gchar* 
71 modest_account_mgr_get_signature (ModestAccountMgr *self, 
72                                   const gchar* name, 
73                                   gboolean* use_signature)
74 {
75         *use_signature = 
76                 modest_account_mgr_get_bool (self, name, MODEST_ACCOUNT_USE_SIGNATURE, FALSE);
77         
78         return modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_SIGNATURE, FALSE);
79 }
80
81 ModestProtocolType modest_account_mgr_get_store_protocol (ModestAccountMgr *self, const gchar* name)
82 {
83        ModestProtocolType result = MODEST_PROTOCOLS_STORE_POP; /* Arbitrary default */
84        
85        gchar *server_account_name = modest_account_mgr_get_string (self, name,
86                                                                    MODEST_ACCOUNT_STORE_ACCOUNT,
87                                                                    FALSE);
88        if (server_account_name) {
89                ModestServerAccountSettings* server_settings = 
90                        modest_account_mgr_load_server_settings (self, server_account_name, FALSE);
91                result = modest_server_account_settings_get_protocol (server_settings);
92                
93                g_object_unref (server_settings);
94                
95                g_free (server_account_name);
96        }
97        
98        return result;
99 }
100
101
102 gboolean modest_account_mgr_set_connection_specific_smtp (ModestAccountMgr *self, 
103         const gchar* connection_id, const gchar* server_account_name)
104 {
105         modest_account_mgr_remove_connection_specific_smtp (self, connection_id);
106         
107         ModestConf *conf = MODEST_ACCOUNT_MGR_GET_PRIVATE (self)->modest_conf;
108
109         gboolean result = TRUE;
110         GError *err = NULL;
111         GSList *list = modest_conf_get_list (conf, MODEST_CONF_CONNECTION_SPECIFIC_SMTP_LIST,
112                                                     MODEST_CONF_VALUE_STRING, &err);
113         if (err) {
114                 g_printerr ("modest: %s: error getting list: %s.\n", __FUNCTION__, err->message);
115                 g_error_free (err);
116                 err = NULL;
117                 result = FALSE;
118         } else {        
119                 /* The server account is in the item after the connection name: */
120                 list = g_slist_append (list, (gpointer)connection_id);
121                 list = g_slist_append (list, (gpointer)server_account_name);
122         
123                 /* Reset the changed list: */
124                 modest_conf_set_list (conf, MODEST_CONF_CONNECTION_SPECIFIC_SMTP_LIST, list,
125                                                     MODEST_CONF_VALUE_STRING, &err);
126                 if (err) {
127                         g_printerr ("modest: %s: error setting list: %s.\n", __FUNCTION__, err->message);
128                         g_error_free (err);
129                         result = FALSE;
130                 }
131         }
132                                 
133         /* TODO: Should we free the items too, or just the list? */
134         g_slist_free (list);
135         
136         return result;
137 }
138
139 /**
140  * modest_account_mgr_remove_connection_specific_smtp
141  * @self: a ModestAccountMgr instance
142  * @name: the account name
143  * @connection_id: A libconic IAP connection id
144  * 
145  * Disassacoiate a server account to use with the specific connection for this account.
146  *
147  * Returns: TRUE if it worked, FALSE otherwise
148  */                              
149 gboolean modest_account_mgr_remove_connection_specific_smtp (ModestAccountMgr *self, 
150         const gchar* connection_id)
151 {
152         ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
153         
154         gboolean result = TRUE;
155         GError *err = NULL;
156         GSList *list = modest_conf_get_list (priv->modest_conf, 
157                                              MODEST_CONF_CONNECTION_SPECIFIC_SMTP_LIST,
158                                              MODEST_CONF_VALUE_STRING, &err);
159         if (err) {
160                 g_printerr ("modest: %s: error getting list: %s.\n", __FUNCTION__, err->message);
161                 g_error_free (err);
162                 err = NULL;
163                 result = FALSE;
164         }
165
166         if (!list)
167                 return FALSE;
168                 
169         /* The server account is in the item after the connection name: */
170         GSList *list_connection = g_slist_find_custom (list, connection_id, (GCompareFunc)strcmp);
171         if (list_connection) {
172                 GSList *account_node = g_slist_next (list_connection);
173                 /* remove both items: */
174                 list = g_slist_delete_link(list, list_connection);
175                 list = g_slist_delete_link(list, account_node);
176         }
177         
178         /* Reset the changed list: */
179         modest_conf_set_list (priv->modest_conf, MODEST_CONF_CONNECTION_SPECIFIC_SMTP_LIST, list,
180                                                     MODEST_CONF_VALUE_STRING, &err);
181         if (err) {
182                 g_printerr ("modest: %s: error setting list: %s.\n", __FUNCTION__, err->message);
183                 g_error_free (err);
184                 result = FALSE;
185         }
186                                 
187         /* TODO: Should we free the items too, or just the list? */
188         g_slist_free (list);
189         
190         return result;
191 }
192
193
194 gboolean modest_account_mgr_get_use_connection_specific_smtp (ModestAccountMgr *self, const gchar* account_name)
195 {
196         return modest_account_mgr_get_bool (self, account_name, 
197                 MODEST_ACCOUNT_USE_CONNECTION_SPECIFIC_SMTP, FALSE);
198 }
199
200 gboolean modest_account_mgr_set_use_connection_specific_smtp (ModestAccountMgr *self, const gchar* account_name, 
201         gboolean new_value)
202 {
203         return modest_account_mgr_set_bool (self, account_name, MODEST_ACCOUNT_USE_CONNECTION_SPECIFIC_SMTP, 
204                 new_value, FALSE);
205 }
206
207 /**
208  * modest_account_mgr_get_connection_specific_smtp
209  * @self: a ModestAccountMgr instance
210  * @connection_id: A libconic IAP connection id
211  * 
212  * Retrieve a server account to use with this specific connection for this account.
213  *
214  * Returns: a server account name to use for this connection, or NULL if none is specified.
215  */                      
216 gchar* modest_account_mgr_get_connection_specific_smtp (ModestAccountMgr *self,  const gchar* connection_id)
217 {
218         gchar *result = NULL;
219         
220         ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
221         
222         GError *err = NULL;
223         GSList *list = modest_conf_get_list (priv->modest_conf, MODEST_CONF_CONNECTION_SPECIFIC_SMTP_LIST,
224                                                     MODEST_CONF_VALUE_STRING, &err);
225         if (err) {
226                 g_printerr ("modest: %s: error getting list: %s.\n", __FUNCTION__, err->message);
227                 g_error_free (err);
228                 err = NULL;
229         }
230
231         if (!list)
232                 return NULL;
233
234         /* The server account is in the item after the connection name: */
235         GSList *iter = list;
236         while (iter) {
237                 const gchar* this_connection_id = (const gchar*)(iter->data);
238                 if (strcmp (this_connection_id, connection_id) == 0) {
239                         iter = g_slist_next (iter);
240                         
241                         if (iter) {
242                                 const gchar* account_name = (const gchar*)(iter->data);
243                                 if (account_name) {
244                                         result = g_strdup (account_name);
245                                         break;
246                                 }
247                         }
248                 }
249                 
250                 /* Skip 2 to go to the next connection in the list: */
251                 iter = g_slist_next (iter);
252                 if (iter)
253                         iter = g_slist_next (iter);
254         }
255                 
256         /*
257         if (!result) {
258                 printf ("  debug: no server found for connection_id=%s.\n", connection_id);     
259         }
260         */
261                                 
262         /* TODO: Should we free the items too, or just the list? */
263         g_slist_free (list);
264         
265         return result;
266 }
267                                          
268 gchar*
269 modest_account_mgr_get_server_account_username (ModestAccountMgr *self, const gchar* account_name)
270 {
271         return modest_account_mgr_get_string (self, account_name, MODEST_ACCOUNT_USERNAME, 
272                 TRUE /* server account */);
273 }
274
275 void
276 modest_account_mgr_set_server_account_username (ModestAccountMgr *self, const gchar* account_name, 
277         const gchar* username)
278 {
279         /* Note that this won't work properly as long as the gconf cache is broken 
280          * in Maemo Bora: */
281         gchar *existing_username = modest_account_mgr_get_server_account_username(self, 
282                 account_name);
283         
284         modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_USERNAME, 
285                 username, TRUE /* server account */);
286                 
287         /* We don't know anything about new usernames: */
288         if (strcmp (existing_username, username) != 0)
289                 modest_account_mgr_set_server_account_username_has_succeeded (self, account_name, FALSE);
290                 
291         g_free (existing_username);
292 }
293
294 gboolean
295 modest_account_mgr_get_server_account_username_has_succeeded (ModestAccountMgr *self, const gchar* account_name)
296 {
297         return modest_account_mgr_get_bool (self, account_name, MODEST_ACCOUNT_USERNAME_HAS_SUCCEEDED, 
298                                             TRUE /* server account */);
299 }
300
301 void
302 modest_account_mgr_set_server_account_username_has_succeeded (ModestAccountMgr *self, 
303                                                   const gchar* account_name, 
304                                                   gboolean succeeded)
305 {
306         modest_account_mgr_set_bool (self, account_name, MODEST_ACCOUNT_USERNAME_HAS_SUCCEEDED, 
307                                      succeeded, TRUE /* server account */);
308 }
309
310 gchar*
311 modest_account_mgr_get_server_account_password (ModestAccountMgr *self, const gchar* account_name)
312 {
313         return modest_account_mgr_get_string (self, account_name, MODEST_ACCOUNT_PASSWORD, 
314                 TRUE /* server account */);     
315 }
316
317 gboolean
318 modest_account_mgr_get_server_account_has_password (ModestAccountMgr *self, const gchar* account_name)
319 {
320         gboolean result = FALSE;
321         gchar *password = modest_account_mgr_get_string (self, account_name, MODEST_ACCOUNT_PASSWORD, 
322                 TRUE /* server account */);
323         if (password && strlen (password)) {
324                 result = TRUE;
325         
326                 /* Clean password */
327                 bzero (password, strlen (password));
328         }
329
330         g_free (password);
331         return result;
332 }
333                          
334         
335 gchar*
336 modest_account_mgr_get_server_account_hostname (ModestAccountMgr *self, 
337                                                 const gchar* account_name)
338 {
339         return modest_account_mgr_get_string (self, 
340                                               account_name, 
341                                               MODEST_ACCOUNT_HOSTNAME, 
342                                               TRUE /* server account */);
343 }
344  
345 void
346 modest_account_mgr_set_server_account_hostname (ModestAccountMgr *self, 
347                                                 const gchar *server_account_name,
348                                                 const gchar *hostname)
349 {
350         modest_account_mgr_set_string (self, 
351                                        server_account_name,
352                                        MODEST_ACCOUNT_HOSTNAME, 
353                                        hostname, 
354                                        TRUE /* server account */);
355 }
356
357
358
359 ModestProtocolType
360 modest_account_mgr_get_server_account_secure_auth (ModestAccountMgr *self, 
361         const gchar* account_name)
362 {
363         ModestProtocolRegistry *protocol_registry;
364         ModestProtocolType result = MODEST_PROTOCOLS_AUTH_NONE;
365         gchar* value;
366
367         protocol_registry = modest_runtime_get_protocol_registry ();
368         value = modest_account_mgr_get_string (self, account_name, MODEST_ACCOUNT_AUTH_MECH, 
369                                                TRUE /* server account */);
370         if (value) {
371                 ModestProtocol *protocol;
372
373                 protocol = modest_protocol_registry_get_protocol_by_name (protocol_registry, MODEST_PROTOCOL_REGISTRY_AUTH_PROTOCOLS, value);
374                 g_free (value);
375
376                 if (protocol)
377                         result = modest_protocol_get_type_id (protocol);
378                         
379         }
380         
381         return result;
382 }
383
384
385 void
386 modest_account_mgr_set_server_account_secure_auth (ModestAccountMgr *self, 
387         const gchar* account_name, ModestProtocolType secure_auth)
388 {
389         const gchar* str_value;
390         ModestProtocolRegistry *protocol_registry;
391         ModestProtocol *protocol;
392
393         /* Get the conf string for the protocol: */
394         protocol_registry = modest_runtime_get_protocol_registry ();
395         protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, secure_auth);
396         str_value = modest_protocol_get_name (protocol);
397         
398         /* Set it in the configuration: */
399         modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_AUTH_MECH, str_value, TRUE);
400 }
401
402 ModestProtocolType
403 modest_account_mgr_get_server_account_security (ModestAccountMgr *self, 
404         const gchar* account_name)
405 {
406         ModestProtocolType result = MODEST_PROTOCOLS_CONNECTION_NONE;
407         gchar* value;
408
409         value = modest_account_mgr_get_string (self, account_name, MODEST_ACCOUNT_SECURITY, 
410                                                TRUE /* server account */);
411         if (value) {
412                 ModestProtocolRegistry *protocol_registry;
413                 ModestProtocol *protocol;
414
415                 protocol_registry = modest_runtime_get_protocol_registry ();
416                 protocol = modest_protocol_registry_get_protocol_by_name (protocol_registry,
417                                                                           MODEST_PROTOCOL_REGISTRY_CONNECTION_PROTOCOLS,
418                                                                           value);
419                 g_free (value);
420
421                 if (protocol)
422                         result = modest_protocol_get_type_id (protocol);
423         }
424         
425         return result;
426 }
427
428 void
429 modest_account_mgr_set_server_account_security (ModestAccountMgr *self, 
430                                                 const gchar* account_name, 
431                                                 ModestProtocolType security)
432 {
433         const gchar* str_value;
434         ModestProtocolRegistry *protocol_registry;
435         ModestProtocol *protocol;
436
437         /* Get the conf string for the protocol type: */
438         protocol_registry = modest_runtime_get_protocol_registry ();
439         protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, security);
440         str_value = modest_protocol_get_name (protocol);
441         
442         /* Set it in the configuration: */
443         modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_SECURITY, str_value, TRUE);
444 }
445
446 ModestServerAccountSettings*
447 modest_account_mgr_load_server_settings (ModestAccountMgr *self, const gchar* name, gboolean is_transport_and_not_store)
448 {
449         ModestServerAccountSettings *settings;
450         ModestProtocol *protocol;
451         ModestProtocolRegistry *registry;
452         gchar *string;
453         
454         g_return_val_if_fail (modest_account_mgr_account_exists (self, name, TRUE), NULL);
455         registry = modest_runtime_get_protocol_registry ();
456         settings = modest_server_account_settings_new ();
457
458         modest_server_account_settings_set_account_name (settings, name);
459
460         string = modest_account_mgr_get_string (self, name, 
461                                                 MODEST_ACCOUNT_HOSTNAME,TRUE);
462         modest_server_account_settings_set_hostname (settings, string);
463         g_free (string);
464
465         string = modest_account_mgr_get_string (self, name, 
466                                                 MODEST_ACCOUNT_USERNAME,TRUE);
467         modest_server_account_settings_set_username (settings, string); 
468         g_free (string);
469
470         string = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_PROTO, TRUE);
471         if (is_transport_and_not_store) {
472                 protocol = modest_protocol_registry_get_protocol_by_name (registry, MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS, string);
473         } else {
474                 protocol = modest_protocol_registry_get_protocol_by_name (registry, MODEST_PROTOCOL_REGISTRY_STORE_PROTOCOLS, string);
475         }
476         modest_server_account_settings_set_protocol (settings,
477                                                      modest_protocol_get_type_id (protocol));
478         g_free (string);
479
480         modest_server_account_settings_set_port (settings,
481                                                  modest_account_mgr_get_int (self, name, MODEST_ACCOUNT_PORT, TRUE));
482
483         string = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_AUTH_MECH, TRUE);
484         if (string) {
485                 protocol = modest_protocol_registry_get_protocol_by_name (registry, MODEST_PROTOCOL_REGISTRY_AUTH_PROTOCOLS, string);
486                 modest_server_account_settings_set_auth_protocol (settings,
487                                                                   modest_protocol_get_type_id (protocol));
488                 g_free (string);
489         } else {
490                 modest_server_account_settings_set_auth_protocol (settings, MODEST_PROTOCOLS_AUTH_NONE);
491         }
492         
493         string = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_SECURITY, TRUE);
494         if (string) {
495                 protocol = modest_protocol_registry_get_protocol_by_name (registry, MODEST_PROTOCOL_REGISTRY_CONNECTION_PROTOCOLS, string);
496                 modest_server_account_settings_set_security_protocol (settings,
497                                                                       modest_protocol_get_type_id (protocol));
498                 g_free (string);
499         } else {
500                 modest_server_account_settings_set_security_protocol (settings,
501                                                                       MODEST_PROTOCOLS_CONNECTION_NONE);
502         }
503
504         string = modest_account_mgr_get_string (self, name, 
505                                                 MODEST_ACCOUNT_PASSWORD, TRUE);
506         modest_server_account_settings_set_password (settings, string);
507         g_free (string);
508         
509         string = modest_account_mgr_get_string (self, name, 
510                                                 MODEST_ACCOUNT_URI, TRUE);
511         modest_server_account_settings_set_uri (settings, string);
512         g_free (string);
513         
514         return settings;
515 }
516
517 gboolean 
518 modest_account_mgr_save_server_settings (ModestAccountMgr *self,
519                                          ModestServerAccountSettings *settings)
520 {
521         gboolean has_errors = FALSE;
522         const gchar *account_name;
523         const gchar *protocol_name;
524         const gchar *uri;
525         ModestProtocolRegistry *protocol_registry;
526         ModestProtocol *protocol;
527         
528         g_return_val_if_fail (MODEST_IS_SERVER_ACCOUNT_SETTINGS (settings), FALSE);
529         protocol_registry = modest_runtime_get_protocol_registry ();
530         account_name = modest_server_account_settings_get_account_name (settings);
531
532         /* if we don't have a valid account name we cannot save */
533         g_return_val_if_fail (account_name, FALSE);
534
535         protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry,
536                                                                   modest_server_account_settings_get_protocol (settings));
537         protocol_name = modest_protocol_get_name (protocol);
538         uri = modest_server_account_settings_get_uri (settings);
539         if (!uri) {
540                 const gchar *hostname;
541                 const gchar *username;
542                 const gchar *password;
543                 gint port;
544                 const gchar *auth_protocol_name;
545                 const gchar *security_name;
546
547                 hostname = null_means_empty (modest_server_account_settings_get_hostname (settings));
548                 username = null_means_empty (modest_server_account_settings_get_username (settings));
549                 password = null_means_empty (modest_server_account_settings_get_password (settings));
550                 port = modest_server_account_settings_get_port (settings);
551                 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry,
552                                                                           modest_server_account_settings_get_auth_protocol (settings));
553                 auth_protocol_name = modest_protocol_get_name (protocol);
554                 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry,
555                                                                           modest_server_account_settings_get_security_protocol (settings));
556                 security_name = modest_protocol_get_name (protocol);
557
558                 has_errors = !modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_HOSTNAME, 
559                                                             hostname, TRUE);
560                 if (!has_errors)
561                         (has_errors = !modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_USERNAME,
562                                                                            username, TRUE));
563                 if (!has_errors)
564                         (has_errors = !modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_PASSWORD,
565                                                                            password, TRUE));
566                 if (!has_errors)
567                         (has_errors = !modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_PROTO,
568                                                                            protocol_name, TRUE));
569                 if (!has_errors)
570                         (has_errors = !modest_account_mgr_set_int (self, account_name, MODEST_ACCOUNT_PORT,
571                                                                         port, TRUE));
572                 if (!has_errors)
573                         (has_errors = !modest_account_mgr_set_string (self, account_name, 
574                                                                            MODEST_ACCOUNT_AUTH_MECH,
575                                                                            auth_protocol_name, TRUE));          
576                 if (!has_errors)
577                         (has_errors = !modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_SECURITY,
578                                                                            security_name,
579                                                                            TRUE));
580         } else {
581                 const gchar *uri = modest_server_account_settings_get_uri (settings);
582                 has_errors = !modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_URI,
583                                                             uri, TRUE);
584                 if (!has_errors)
585                         (has_errors = !modest_account_mgr_set_string (self, account_name, MODEST_ACCOUNT_PROTO,
586                                                                            protocol_name, TRUE));
587         }
588
589         return !has_errors;
590
591 }
592
593
594 ModestAccountSettings *
595 modest_account_mgr_load_account_settings (ModestAccountMgr *self, 
596                                           const gchar* name)
597 {
598         ModestAccountSettings *settings;
599         gchar *string;
600         gchar *server_account;
601         gchar *default_account;
602         gboolean use_signature = FALSE;
603         
604         g_return_val_if_fail (self, NULL);
605         g_return_val_if_fail (name, NULL);
606         
607         if (!modest_account_mgr_account_exists (self, name, FALSE)) {
608                 /* For instance, maybe you are mistakenly checking for a server account name? */
609                 g_warning ("%s: Account %s does not exist.", __FUNCTION__, name);
610                 return NULL;
611         }
612         
613         settings = modest_account_settings_new ();
614
615         modest_account_settings_set_account_name (settings, name);
616
617         string = modest_account_mgr_get_string (self, name,
618                                                 MODEST_ACCOUNT_DISPLAY_NAME,
619                                                 FALSE);
620         modest_account_settings_set_display_name (settings, string);
621         g_free (string);
622
623         string = modest_account_mgr_get_string (self, name,
624                                                 MODEST_ACCOUNT_FULLNAME,
625                                                 FALSE);
626         modest_account_settings_set_fullname (settings, string);
627         g_free (string);
628
629         string = modest_account_mgr_get_string (self, name,
630                                                 MODEST_ACCOUNT_EMAIL,
631                                                 FALSE);
632         modest_account_settings_set_email_address (settings, string);
633         g_free (string);
634
635         modest_account_settings_set_enabled (settings, modest_account_mgr_get_enabled (self, name));
636         modest_account_settings_set_retrieve_type (settings, modest_account_mgr_get_retrieve_type (self, name));
637         modest_account_settings_set_retrieve_limit (settings, modest_account_mgr_get_retrieve_limit (self, name));
638
639         default_account    = modest_account_mgr_get_default_account (self);
640         modest_account_settings_set_is_default (settings,
641                                                 (default_account && strcmp (default_account, name) == 0));
642         g_free (default_account);
643
644         string = modest_account_mgr_get_signature (self, name, &use_signature);
645         modest_account_settings_set_use_signature (settings, use_signature);
646         modest_account_settings_set_signature (settings, string);
647         g_free (string);
648
649         modest_account_settings_set_leave_messages_on_server 
650                 (settings, modest_account_mgr_get_leave_on_server (self, name));
651         modest_account_settings_set_use_connection_specific_smtp 
652                 (settings, modest_account_mgr_get_use_connection_specific_smtp (self, name));
653
654         /* store */
655         server_account     = modest_account_mgr_get_string (self, name,
656                                                             MODEST_ACCOUNT_STORE_ACCOUNT,
657                                                             FALSE);
658         if (server_account) {
659                 ModestServerAccountSettings *store_settings;
660                 store_settings = modest_account_mgr_load_server_settings (self, server_account, FALSE);
661                 modest_account_settings_set_store_settings (settings,
662                                                             store_settings);
663                 g_object_unref (store_settings);
664                 g_free (server_account);
665         }
666
667         /* transport */
668         server_account = modest_account_mgr_get_string (self, name,
669                                                         MODEST_ACCOUNT_TRANSPORT_ACCOUNT,
670                                                         FALSE);
671         if (server_account) {
672                 ModestServerAccountSettings *transport_settings;
673                 transport_settings = modest_account_mgr_load_server_settings (self, server_account, TRUE);
674                 modest_account_settings_set_transport_settings (settings, transport_settings);
675                 g_object_unref (transport_settings);
676                 g_free (server_account);
677         }
678
679         return settings;
680 }
681
682 void
683 modest_account_mgr_save_account_settings (ModestAccountMgr *mgr,
684                                           ModestAccountSettings *settings)
685 {
686         g_return_if_fail (MODEST_IS_ACCOUNT_MGR (mgr));
687         g_return_if_fail (MODEST_IS_ACCOUNT_SETTINGS (settings));
688
689         const gchar *account_name;
690         const gchar *store_account_name;
691         const gchar *transport_account_name;
692         ModestServerAccountSettings *store_settings;
693         ModestServerAccountSettings *transport_settings;
694
695         account_name = modest_account_settings_get_account_name (settings);
696         g_return_if_fail (account_name != NULL);
697
698         modest_account_mgr_set_display_name (mgr, account_name,
699                                              modest_account_settings_get_display_name (settings));
700         modest_account_mgr_set_user_fullname (mgr, account_name,
701                                               modest_account_settings_get_fullname (settings));
702         modest_account_mgr_set_user_email (mgr, account_name,
703                                            modest_account_settings_get_email_address (settings));
704         modest_account_mgr_set_retrieve_type (mgr, account_name,
705                                               modest_account_settings_get_retrieve_type (settings));
706         modest_account_mgr_set_retrieve_limit (mgr, account_name,
707                                                modest_account_settings_get_retrieve_limit (settings));
708         modest_account_mgr_set_leave_on_server (mgr, account_name,
709                                                 modest_account_settings_get_leave_messages_on_server (settings));
710         modest_account_mgr_set_signature (mgr, account_name,
711                                           modest_account_settings_get_signature (settings),
712                                           modest_account_settings_get_use_signature (settings));
713         modest_account_mgr_set_use_connection_specific_smtp 
714                 (mgr, account_name,
715                  modest_account_settings_get_use_connection_specific_smtp (settings));
716
717         store_settings = modest_account_settings_get_store_settings (settings);
718         store_account_name = modest_server_account_settings_get_account_name (store_settings);
719         if (store_settings != NULL) {
720                 modest_account_mgr_save_server_settings (mgr, store_settings);
721         }
722         modest_account_mgr_set_string (mgr, account_name, MODEST_ACCOUNT_STORE_ACCOUNT, store_account_name, FALSE);
723         g_object_unref (store_settings);
724
725         transport_settings = modest_account_settings_get_transport_settings (settings);
726         transport_account_name = modest_server_account_settings_get_account_name (transport_settings);
727         if (transport_settings != NULL) {
728                 modest_account_mgr_save_server_settings (mgr, transport_settings);
729         }
730         modest_account_mgr_set_string (mgr, account_name, MODEST_ACCOUNT_TRANSPORT_ACCOUNT, transport_account_name, FALSE);
731         g_object_unref (transport_settings);
732         modest_account_mgr_set_enabled (mgr, account_name, TRUE);
733 }
734
735
736 gint 
737 on_accounts_list_sort_by_title(gconstpointer a, gconstpointer b)
738 {
739         return g_utf8_collate((const gchar*)a, (const gchar*)b);
740 }
741
742 /** Get the first one, alphabetically, by title. */
743 gchar* 
744 modest_account_mgr_get_first_account_name (ModestAccountMgr *self)
745 {
746         const gchar* account_name = NULL;
747         GSList *account_names = modest_account_mgr_account_names (self, TRUE /* only enabled */);
748
749         /* Return TRUE if there is no account */
750         if (!account_names)
751                 return NULL;
752
753         /* Get the first one, alphabetically, by title: */
754         /* gchar *old_default = modest_account_mgr_get_default_account (self); */
755         GSList* list_sorted = g_slist_sort (account_names, on_accounts_list_sort_by_title);
756
757         GSList* iter = list_sorted;
758         gboolean found = FALSE;
759         while (iter && !found) {
760                 account_name = (const gchar*)list_sorted->data;
761
762                 if (account_name)
763                         found = TRUE;
764
765                 if (!found)
766                         iter = g_slist_next (iter);
767         }
768
769         gchar* result = NULL;
770         if (account_name)
771                 result = g_strdup (account_name);
772                 
773         modest_account_mgr_free_account_names (account_names);
774         account_names = NULL;
775
776         return result;
777 }
778
779 gboolean
780 modest_account_mgr_set_first_account_as_default (ModestAccountMgr *self)
781 {
782         gboolean result = FALSE;
783         
784         gchar* account_name = modest_account_mgr_get_first_account_name(self);
785         if (account_name) {
786                 result = modest_account_mgr_set_default_account (self, account_name);
787                 g_free (account_name);
788         }
789         else
790                 result = TRUE; /* If there are no accounts then it's not a failure. */
791
792         return result;
793 }
794
795 gchar*
796 modest_account_mgr_get_from_string (ModestAccountMgr *self, const gchar* name)
797 {
798         gchar *fullname, *email, *from;
799         
800         g_return_val_if_fail (self, NULL);
801         g_return_val_if_fail (name, NULL);
802
803         fullname      = modest_account_mgr_get_string (self, name,MODEST_ACCOUNT_FULLNAME,
804                                                        FALSE);
805         email         = modest_account_mgr_get_string (self, name, MODEST_ACCOUNT_EMAIL,
806                                                        FALSE);
807         from = g_strdup_printf ("%s <%s>",
808                                 fullname ? fullname : "",
809                                 email    ? email    : "");
810         g_free (fullname);
811         g_free (email);
812
813         return from;
814 }
815
816 /* Add a number to the end of the text, or increment a number that is already there.
817  */
818 static gchar*
819 util_increment_name (const gchar* text)
820 {
821         g_return_val_if_fail (text, NULL);
822
823         /* Get the end character,
824          * also doing a UTF-8 validation which is required for using g_utf8_prev_char().
825          */
826         const gchar* end = NULL;
827         if (!g_utf8_validate (text, -1, &end))
828                 return NULL;
829   
830         if (!end)
831                 return NULL;
832                 
833         --end; /* Go to before the null-termination. */
834                 
835         /* Look at each UTF-8 characer, starting at the end: */
836         const gchar* p = end;
837         const gchar* alpha_end = NULL;
838         while (p)
839         {       
840                 /* Stop when we reach the first character that is not a numeric digit: */
841                 const gunichar ch = g_utf8_get_char (p);
842                 if (!g_unichar_isdigit (ch)) {
843                         alpha_end = p;
844                         break;
845                 }
846                 
847                 p = g_utf8_find_prev_char (text, p);    
848         }
849         
850         if(!alpha_end) {
851                 /* The text must consist completely of numeric digits. */
852                 alpha_end = text;
853         }
854         else
855                 ++alpha_end;
856         
857         /* Intepret and increment the number, if any: */
858         gint num = atol (alpha_end);
859         ++num;
860         
861         /* Get the name part: */
862         gint name_len = alpha_end - text;
863         gchar *name_without_number = g_malloc(name_len + 1);
864         memcpy (name_without_number, text, name_len);
865         name_without_number[name_len] = 0;\
866         
867     /* Concatenate the text part and the new number: */ 
868         gchar *result = g_strdup_printf("%s%d", name_without_number, num);
869         g_free (name_without_number);
870         
871         return result;  
872 }
873
874 gchar*
875 modest_account_mgr_get_unused_account_name (ModestAccountMgr *self, const gchar* starting_name,
876         gboolean server_account)
877 {
878         gchar *account_name = g_strdup (starting_name);
879
880         while (modest_account_mgr_account_exists (self, 
881                 account_name, server_account /*  server_account */)) {
882                         
883                 gchar * account_name2 = util_increment_name (account_name);
884                 g_free (account_name);
885                 account_name = account_name2;
886         }
887         
888         return account_name;
889 }
890
891 gchar*
892 modest_account_mgr_get_unused_account_display_name (ModestAccountMgr *self, const gchar* starting_name)
893 {
894         gchar *account_name = g_strdup (starting_name);
895
896         while (modest_account_mgr_account_with_display_name_exists (self, account_name)) {
897                         
898                 gchar * account_name2 = util_increment_name (account_name);
899                 g_free (account_name);
900                 account_name = account_name2;
901         }
902         
903         return account_name;
904 }
905
906 void 
907 modest_account_mgr_set_leave_on_server (ModestAccountMgr *self, 
908                                         const gchar *account_name, 
909                                         gboolean leave_on_server)
910 {
911         modest_account_mgr_set_bool (self, 
912                                      account_name,
913                                      MODEST_ACCOUNT_LEAVE_ON_SERVER, 
914                                      leave_on_server, 
915                                      FALSE);
916 }
917
918 gboolean 
919 modest_account_mgr_get_leave_on_server (ModestAccountMgr *self, 
920                                         const gchar* account_name)
921 {
922         return modest_account_mgr_get_bool (self, 
923                                             account_name,
924                                             MODEST_ACCOUNT_LEAVE_ON_SERVER, 
925                                             FALSE);
926 }
927
928 gint 
929 modest_account_mgr_get_last_updated (ModestAccountMgr *self, 
930                                      const gchar* account_name)
931 {
932         return modest_account_mgr_get_int (modest_runtime_get_account_mgr (), 
933                                            account_name, 
934                                            MODEST_ACCOUNT_LAST_UPDATED, 
935                                            TRUE);
936 }
937
938 void 
939 modest_account_mgr_set_last_updated (ModestAccountMgr *self, 
940                                      const gchar* account_name,
941                                      gint time)
942 {
943         modest_account_mgr_set_int (self, 
944                                     account_name, 
945                                     MODEST_ACCOUNT_LAST_UPDATED, 
946                                     time, 
947                                     TRUE);
948
949         /* TODO: notify about changes */
950 }
951
952 gint  
953 modest_account_mgr_get_retrieve_limit (ModestAccountMgr *self, 
954                                        const gchar* account_name)
955 {
956         return modest_account_mgr_get_int (self, 
957                                            account_name,
958                                            MODEST_ACCOUNT_LIMIT_RETRIEVE, 
959                                            FALSE);
960 }
961
962 void  
963 modest_account_mgr_set_retrieve_limit (ModestAccountMgr *self, 
964                                        const gchar* account_name,
965                                        gint limit_retrieve)
966 {
967         modest_account_mgr_set_int (self, 
968                                     account_name,
969                                     MODEST_ACCOUNT_LIMIT_RETRIEVE, 
970                                     limit_retrieve, 
971                                     FALSE /* not server account */);
972 }
973
974 gint  
975 modest_account_mgr_get_server_account_port (ModestAccountMgr *self, 
976                                             const gchar* account_name)
977 {
978         return modest_account_mgr_get_int (self, 
979                                            account_name,
980                                            MODEST_ACCOUNT_PORT, 
981                                            TRUE);
982 }
983
984 void
985 modest_account_mgr_set_server_account_port (ModestAccountMgr *self, 
986                                             const gchar *account_name,
987                                             gint port_num)
988 {
989         modest_account_mgr_set_int (self, 
990                                     account_name,
991                                     MODEST_ACCOUNT_PORT, 
992                                     port_num, TRUE /* server account */);
993 }
994
995 gchar* 
996 modest_account_mgr_get_server_account_name (ModestAccountMgr *self, 
997                                             const gchar *account_name,
998                                             TnyAccountType account_type)
999 {
1000         return modest_account_mgr_get_string (self, 
1001                                               account_name,
1002                                               (account_type == TNY_ACCOUNT_TYPE_STORE) ?
1003                                               MODEST_ACCOUNT_STORE_ACCOUNT :
1004                                               MODEST_ACCOUNT_TRANSPORT_ACCOUNT, 
1005                                               FALSE);
1006 }
1007
1008 static const gchar *
1009 get_retrieve_type_name (ModestAccountRetrieveType retrieve_type)
1010 {
1011         switch(retrieve_type) {
1012         case MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY:
1013                 return MODEST_ACCOUNT_RETRIEVE_VALUE_HEADERS_ONLY;
1014                 break;
1015         case MODEST_ACCOUNT_RETRIEVE_MESSAGES:
1016                 return MODEST_ACCOUNT_RETRIEVE_VALUE_MESSAGES;
1017                 break;
1018         case MODEST_ACCOUNT_RETRIEVE_MESSAGES_AND_ATTACHMENTS:
1019                 return MODEST_ACCOUNT_RETRIEVE_VALUE_MESSAGES_AND_ATTACHMENTS;
1020                 break;
1021         default:
1022                 return MODEST_ACCOUNT_RETRIEVE_VALUE_HEADERS_ONLY;
1023         };
1024 }
1025
1026 static ModestAccountRetrieveType
1027 get_retrieve_type (const gchar *name)
1028 {
1029         if (!name || name[0] == 0)
1030                 return MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY;
1031         if (strcmp (name, MODEST_ACCOUNT_RETRIEVE_VALUE_MESSAGES) == 0) {
1032                 return MODEST_ACCOUNT_RETRIEVE_MESSAGES;
1033         } else if (strcmp (name, MODEST_ACCOUNT_RETRIEVE_VALUE_MESSAGES_AND_ATTACHMENTS) == 0) {
1034                 return MODEST_ACCOUNT_RETRIEVE_MESSAGES_AND_ATTACHMENTS;
1035         } else {
1036                 /* we fall back to headers only */
1037                 return MODEST_ACCOUNT_RETRIEVE_HEADERS_ONLY;
1038         }
1039 }
1040
1041 ModestAccountRetrieveType
1042 modest_account_mgr_get_retrieve_type (ModestAccountMgr *self, 
1043                                       const gchar *account_name)
1044 {
1045         gchar *string;
1046         ModestAccountRetrieveType result;
1047
1048         string =  modest_account_mgr_get_string (self, 
1049                                                  account_name,
1050                                                  MODEST_ACCOUNT_RETRIEVE, 
1051                                                  FALSE /* not server account */);
1052         result = get_retrieve_type (string);
1053         g_free (string);
1054
1055         return result;
1056 }
1057
1058 void 
1059 modest_account_mgr_set_retrieve_type (ModestAccountMgr *self, 
1060                                       const gchar *account_name,
1061                                       ModestAccountRetrieveType retrieve_type)
1062 {
1063         modest_account_mgr_set_string (self, 
1064                                        account_name,
1065                                        MODEST_ACCOUNT_RETRIEVE, 
1066                                        get_retrieve_type_name (retrieve_type), 
1067                                        FALSE /* not server account */);
1068 }
1069
1070
1071 void
1072 modest_account_mgr_set_user_fullname (ModestAccountMgr *self, 
1073                                       const gchar *account_name,
1074                                       const gchar *fullname)
1075 {
1076         modest_account_mgr_set_string (self, 
1077                                        account_name,
1078                                        MODEST_ACCOUNT_FULLNAME, 
1079                                        fullname, 
1080                                        FALSE /* not server account */);
1081 }
1082
1083 void
1084 modest_account_mgr_set_user_email (ModestAccountMgr *self, 
1085                                    const gchar *account_name,
1086                                    const gchar *email)
1087 {
1088         modest_account_mgr_set_string (self, 
1089                                        account_name,
1090                                        MODEST_ACCOUNT_EMAIL, 
1091                                        email, 
1092                                        FALSE /* not server account */);
1093 }