+ /* The key is an escaped string, so unescape it to get the actual account name */
+ unescaped_name = modest_conf_key_unescape (account);
+ g_free (account);
+ }
+
+ return unescaped_name;
+}
+
+
+
+
+
+/* optimization: only with non-alphanum chars, escaping is needed */
+inline static gboolean
+is_alphanum (const gchar* str)
+{
+ const gchar *cursor;
+ for (cursor = str; cursor && *cursor; ++cursor) {
+ const char c = *cursor;
+ /* we cannot trust isalnum(3), because it might consider locales */
+ /* numbers ALPHA alpha */
+ if (!((c>=48 && c<=57)||(c>=65 && c<=90)||(c>=97 && c<=122)))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+
+
+/* must be freed by caller */
+gchar *
+_modest_account_mgr_get_account_keyname (const gchar *account_name, const gchar* name,
+ gboolean server_account)
+{
+ gchar *retval = NULL;
+ gchar *namespace = server_account ? (gchar *) MODEST_SERVER_ACCOUNT_NAMESPACE : (gchar *) MODEST_ACCOUNT_NAMESPACE;
+ gchar *escaped_account_name, *escaped_name;
+
+ if (!account_name)
+ return g_strdup (namespace);
+
+ /* optimization: only escape names when need to be escaped */
+ if (is_alphanum (account_name))
+ escaped_account_name = (gchar*)account_name;
+ else
+ escaped_account_name = modest_conf_key_escape (account_name);
+
+ if (is_alphanum (name))
+ escaped_name = (gchar*)name;
+ else
+ escaped_name = modest_conf_key_escape (name);
+ //////////////////////////////////////////////////////////////
+
+ if (escaped_account_name && escaped_name)
+ retval = g_strconcat (namespace, "/", escaped_account_name, "/", escaped_name, NULL);
+ else if (escaped_account_name)
+ retval = g_strconcat (namespace, "/", escaped_account_name, NULL);
+
+ /* Sanity check: */
+ if (!retval || !modest_conf_key_is_valid (retval)) {
+ g_warning ("%s: Generated conf key was invalid: %s", __FUNCTION__,
+ retval ? retval: "<empty>");
+ g_free (retval);
+ retval = NULL;
+ }
+
+ /* g_free is only needed if we actually allocated anything */
+ if (name != escaped_name)
+ g_free (escaped_name);
+ if (account_name != escaped_account_name)
+ g_free (escaped_account_name);
+
+ return retval;
+}
+
+static const gchar *
+_modest_account_mgr_get_account_keyname_cached (ModestAccountMgrPrivate *priv,
+ const gchar* account_name,
+ const gchar *name,
+ gboolean is_server)
+{
+ GHashTable *hash = is_server ? priv->server_account_key_hash : priv->account_key_hash;
+ GHashTable *account_hash;
+ gchar *key = NULL;
+ const gchar *search_name;
+
+ if (!account_name)
+ return is_server ? MODEST_SERVER_ACCOUNT_NAMESPACE : MODEST_ACCOUNT_NAMESPACE;
+
+ search_name = name ? name : "<dummy>";
+
+ account_hash = g_hash_table_lookup (hash, account_name);
+ if (!account_hash) { /* no hash for this account yet? create it */
+ account_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ key = _modest_account_mgr_get_account_keyname (account_name, name, is_server);
+ g_hash_table_insert (account_hash, g_strdup(search_name), key);
+ g_hash_table_insert (hash, g_strdup(account_name), account_hash);
+ return key;
+ }
+
+ /* we have a hash for this account, but do we have the key? */
+ key = g_hash_table_lookup (account_hash, search_name);
+ if (!key) {
+ key = _modest_account_mgr_get_account_keyname (account_name, name, is_server);
+ g_hash_table_insert (account_hash, g_strdup(search_name), key);
+ }
+
+ return key;
+}
+
+
+gboolean
+modest_account_mgr_has_accounts (ModestAccountMgr* self, gboolean enabled)
+{
+ ModestAccountMgrPrivate* priv;
+ GSList *account_names;
+ gboolean accounts_exist;
+
+ g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
+
+ priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
+
+ if (enabled && priv->has_enabled_accounts)
+ return TRUE;
+ else if (priv->has_accounts)
+ return TRUE;
+
+ /* Check that at least one account exists: */
+ account_names = modest_account_mgr_account_names (self,enabled);
+ accounts_exist = account_names != NULL;
+ modest_account_mgr_free_account_names (account_names);
+ account_names = NULL;
+
+ /* cache it. */
+ if (enabled)
+ priv->has_enabled_accounts = accounts_exist;
+ else
+ priv->has_accounts = accounts_exist;
+
+ return accounts_exist;
+}
+
+static int
+compare_account_name(gconstpointer a, gconstpointer b)
+{
+ const gchar* account_name = (const gchar*) a;
+ const gchar* account_name2 = (const gchar*) b;
+ return strcmp(account_name, account_name2);
+}
+
+void
+modest_account_mgr_set_account_busy(ModestAccountMgr* self,
+ const gchar* account_name,
+ gboolean busy)
+{
+ ModestAccountMgrPrivate* priv;
+
+ g_return_if_fail (MODEST_IS_ACCOUNT_MGR(self));
+ g_return_if_fail (account_name);
+
+ priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
+ if (busy) {
+ GSList *account_names = modest_account_mgr_account_names (self, TRUE);
+ GSList* account = g_slist_find_custom(account_names, account_name,
+ (GCompareFunc) compare_account_name);
+
+ if (account && !modest_account_mgr_account_is_busy(self, account_name)) {
+ priv->busy_accounts = g_slist_append(priv->busy_accounts, g_strdup(account_name));
+ g_signal_emit (G_OBJECT(self), signals[ACCOUNT_BUSY_SIGNAL],
+ 0, account_name, TRUE);
+ }
+ modest_account_mgr_free_account_names (account_names);
+ account_names = NULL;
+ } else {
+ GSList* account =
+ g_slist_find_custom(priv->busy_accounts, account_name, (GCompareFunc) compare_account_name);
+
+ if (account) {
+ g_free(account->data);
+ priv->busy_accounts = g_slist_delete_link(priv->busy_accounts, account);
+ g_signal_emit (G_OBJECT(self), signals[ACCOUNT_BUSY_SIGNAL],
+ 0, account_name, FALSE);
+ }
+ }
+}
+
+gboolean
+modest_account_mgr_account_is_busy (ModestAccountMgr* self, const gchar* account_name)
+{
+ ModestAccountMgrPrivate* priv;
+
+ g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
+ g_return_val_if_fail (account_name, FALSE);
+
+ priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
+
+ return (g_slist_find_custom(priv->busy_accounts, account_name, (GCompareFunc) compare_account_name)
+ != NULL);
+}
+
+void
+modest_account_mgr_notify_account_update (ModestAccountMgr* self,
+ const gchar *server_account_name)
+{
+ ModestProtocolType proto;
+ ModestAccountMgrPrivate* priv;
+ ModestProtocolRegistry *protocol_registry;
+ gchar *proto_name = NULL;
+
+ g_return_if_fail (self);
+ g_return_if_fail (server_account_name);
+