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