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