Modified webpage: now tinymail repository is in gitorious.
[modest] / src / modest-tny-account-store.c
index 50ad50b..b560a8e 100644 (file)
@@ -62,6 +62,8 @@
 #include <modest-platform.h>
 #include "modest-ui-actions.h"
 #include <widgets/modest-account-settings-dialog.h>
+#include <tny-camel-bs-msg-receive-strategy.h>
+#include <modest-tny-msg.h>
 
 #ifdef MODEST_PLATFORM_MAEMO
 #include <tny-maemo-conic-device.h>
@@ -104,9 +106,6 @@ static void    on_vfs_volume_unmounted     (GnomeVFSVolumeMonitor *volume_monito
                                            GnomeVFSVolume *volume, 
                                            gpointer user_data);
 
-static void    forget_password_in_memory (ModestTnyAccountStore *self, 
-                                         const gchar *server_account_name);
-
 static void    add_connection_specific_transport_accounts         (ModestTnyAccountStore *self);
 
 static void    remove_connection_specific_transport_accounts      (ModestTnyAccountStore *self);
@@ -149,13 +148,6 @@ struct _ModestTnyAccountStorePrivate {
                                                       MODEST_TYPE_TNY_ACCOUNT_STORE, \
                                                       ModestTnyAccountStorePrivate))
 
-#define RETRY_ATTEMPTS 3
-
-typedef struct _PwdAttempt {
-       gint count;
-       gchar *pwd;
-} PwdAttempt;
-
 /* globals */
 static GObjectClass *parent_class = NULL;
 
@@ -259,20 +251,6 @@ modest_tny_account_store_class_init (ModestTnyAccountStoreClass *klass)
 }
 
 static void
-free_pwd_attempt (gpointer data)
-{
-       PwdAttempt *attempt = (PwdAttempt *) data;
-
-       /* Note that we sometimes insert NULL */
-       if (!attempt)
-               return;
-
-       if (attempt->pwd)
-               g_free (attempt->pwd);
-       g_slice_free (PwdAttempt, attempt);
-}
-
-static void
 modest_tny_account_store_instance_init (ModestTnyAccountStore *obj)
 {
        ModestTnyAccountStorePrivate *priv;
@@ -296,7 +274,7 @@ modest_tny_account_store_instance_init (ModestTnyAccountStore *obj)
          * so they need to be asked for from the user once in each session:
          */
        priv->password_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
-                                                    g_free, free_pwd_attempt);
+                                                    g_free, g_free);
 }
 
 /* disconnect the list of TnyAccounts */
@@ -435,23 +413,14 @@ on_vfs_volume_unmounted(GnomeVFSVolumeMonitor *volume_monitor,
        g_free (uri);
 }
 
-/**
- * forget_password_in_memory
- * @self: a TnyAccountStore instance
- * @account: A server account.
- * 
- * Forget any password stored in memory for this account.
- * For instance, this should be called when the user has changed the password in the account settings.
- */
-static void
-forget_password_in_memory (ModestTnyAccountStore *self, 
+void
+modest_tny_account_store_forget_password_in_memory (ModestTnyAccountStore *self, 
                           const gchar * server_account_name)
 {
        ModestTnyAccountStorePrivate *priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
 
-       if (server_account_name && priv->password_hash) {
+       if (server_account_name && priv->password_hash)
                g_hash_table_remove (priv->password_hash, server_account_name);
-       }
 }
 
 static void
@@ -488,10 +457,30 @@ on_account_changed (ModestAccountMgr *acc_mgr,
        g_object_unref (iter);
 }
 
-static void 
-show_wrong_password_dialog (TnyAccount *account, 
+static void
+show_wrong_password_dialog (TnyAccountStore *self,
+                           TnyAccount *account,
                            gboolean show_banner)
-{ 
+{
+       TnyDevice *device;
+       gboolean is_online;
+
+       g_debug ("%s: %s", __FUNCTION__, tny_account_get_id (account));
+
+       device = tny_account_store_get_device (self);
+       is_online = tny_device_is_online (device);
+       g_object_unref (device);
+
+       if (!is_online) {
+               g_debug ("%s: not showing the acc settings dialog. Device OFFLINE", __FUNCTION__);
+               return;
+       }
+
+       if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()) == 0) {
+               g_debug ("%s: not showing the account settings dialog. NO windows", __FUNCTION__);
+               return;
+       }
+
        if (g_object_get_data (G_OBJECT (account), "connection_specific") != NULL) {
                modest_ui_actions_on_smtp_servers (NULL, NULL);
        } else {
@@ -509,17 +498,18 @@ show_wrong_password_dialog (TnyAccount *account,
 
                /* Create and show the dialog */
                if (proto && MODEST_IS_ACCOUNT_PROTOCOL (proto)) {
-                       GtkWindow *parent;
-                       ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
                        ModestAccountSettingsDialog *dialog =
                                modest_account_protocol_get_account_settings_dialog (proto, modest_account_name);
 
-                       parent = modest_window_mgr_get_modal (mgr);
-                       if (!parent)
-                               parent = (GtkWindow *) modest_window_mgr_get_current_top (mgr);
+                       if (dialog) {
+                               ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
+                               GtkWindow *parent = modest_window_mgr_get_modal (mgr);
+                               if (!parent)
+                                       parent = (GtkWindow *) modest_window_mgr_get_current_top (mgr);
 
-                       modest_window_mgr_set_modal (mgr, GTK_WINDOW (dialog), parent);
-                       gtk_widget_show (GTK_WIDGET (dialog));
+                               modest_window_mgr_set_modal (mgr, GTK_WINDOW (dialog), parent);
+                               gtk_widget_show (GTK_WIDGET (dialog));
+                       }
                }
        }
        /* Show an explanatory temporary banner: */
@@ -539,17 +529,14 @@ get_password (TnyAccount *account, const gchar * prompt_not_used, gboolean *canc
        ModestTnyAccountStorePrivate *priv;
        gchar *username = NULL;
        gchar *pwd = NULL;
+       gpointer pwd_ptr;
        gboolean already_asked = FALSE;
        const gchar *server_account_name;
        gchar *url_string;
-       PwdAttempt *attempt = NULL;
-       gpointer attempt_ptr = NULL;
 
        g_return_val_if_fail (account, NULL);
 
-       MODEST_DEBUG_BLOCK(
-               g_debug ("%s: prompt (not shown) = %s\n", __FUNCTION__, prompt_not_used);
-       );
+       g_debug ("%s: %s", __FUNCTION__, prompt_not_used);
 
        /* Get a reference to myself */
        self = MODEST_TNY_ACCOUNT_STORE (g_object_get_data (G_OBJECT(account), "account_store"));
@@ -586,25 +573,23 @@ get_password (TnyAccount *account, const gchar * prompt_not_used, gboolean *canc
        }
 
        /* We need to do this to avoid "dereferencing type-punned pointer will break strict-aliasing rules" */
-       attempt_ptr = (gpointer) &attempt;
+       pwd_ptr = (gpointer) &pwd;
 
        /* This hash map stores passwords, including passwords that are not stored in gconf. */
        /* Is it in the hash? if it's already there, it must be wrong... */
        already_asked = priv->password_hash && g_hash_table_lookup_extended (priv->password_hash,
                                                                             server_account_name,
                                                                             NULL,
-                                                                            attempt_ptr);
+                                                                            pwd_ptr);
 
        /* If the password is not already there, try ModestConf */
        if (!already_asked) {
                pwd  = modest_account_mgr_get_server_account_password (priv->account_mgr,
                                                                       server_account_name);
-               PwdAttempt *new_attempt = g_slice_new0 (PwdAttempt);
-               new_attempt->count = RETRY_ATTEMPTS;
-               new_attempt->pwd = g_strdup (pwd);
-               g_hash_table_insert (priv->password_hash, g_strdup (server_account_name), new_attempt);
-       } else if (attempt) {
-               pwd = g_strdup (attempt->pwd);
+               g_hash_table_insert (priv->password_hash, g_strdup (server_account_name), g_strdup (pwd));
+       } else {
+               /* We need to get it again because forget_password has cleared it */
+               pwd = modest_account_mgr_get_server_account_password (priv->account_mgr, server_account_name);
        }
 
        /* This is horrible but we need it until we don't get a proper
@@ -614,22 +599,11 @@ get_password (TnyAccount *account, const gchar * prompt_not_used, gboolean *canc
           cases it makes no sense to ask the user. It's better just
           to cancel cleanly */
        if (g_strstr_len (prompt_not_used, -1, "Connection timed out")) {
-               g_debug ("%s, Incorrect get_password with connection issue %s",
-                        __FUNCTION__, (attempt && (attempt->count > 0)) ? "retrying" : "canceling");
-               if (attempt) {
-                       if (attempt->count == 0) {
-                               modest_tny_account_store_reset_attempt_count (self, account);
-                               if (cancel)
-                                       *cancel = TRUE;
-                               return NULL;
-                       } else {
-                               return pwd;
-                       }
-               } else {
-                       if (cancel)
-                               *cancel = TRUE;
-                       return NULL;
-               }
+               g_debug ("%s, Incorrect get_password with connection issue", __FUNCTION__);
+               modest_tny_account_store_forget_password_in_memory (self, tny_account_get_id (account));
+               if (cancel)
+                       *cancel = TRUE;
+               return NULL;
        }
 
        /* If it was already asked, it must have been wrong, so ask again */
@@ -686,7 +660,7 @@ get_password (TnyAccount *account, const gchar * prompt_not_used, gboolean *canc
                                                                                             server_account_name);
                                /* If the login has ever succeeded then show a specific message */
                                if (username_known)
-                                       msg = _CS ("ecdg_ib_set_password_incorrect");
+                                       msg = _CS_SET_PASSWORD_INCORRECT;
                                else
                                        msg = _("mcen_ib_username_pw_incorrect");
                                if (modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()))
@@ -695,13 +669,22 @@ get_password (TnyAccount *account, const gchar * prompt_not_used, gboolean *canc
                }
 
                if (settings_have_password) {
-                       /* The password must be wrong, so show the account settings dialog so it can be corrected: */
-                       show_wrong_password_dialog (account, TRUE);
+                       if (pwd) {
+                               /* The password must be wrong, so show
+                                  the account settings dialog so it
+                                  can be corrected: */
+                               g_debug ("%s: going to show the settings dialog", __FUNCTION__);
+                               show_wrong_password_dialog ((TnyAccountStore *) self, account, TRUE);
 
-                       if (cancel)
-                               *cancel = TRUE;
+                               if (cancel)
+                                       *cancel = TRUE;
 
-                       return NULL;
+                               return NULL;
+                       } else {
+                               /* Get the password from the account settings */
+                               return modest_account_mgr_get_server_account_password (priv->account_mgr,
+                                                                                      server_account_name);
+                       }
                }
 
                /* we don't have it yet. Get the password from the user */
@@ -768,7 +751,7 @@ forget_password (TnyAccount *account)
        ModestTnyAccountStorePrivate *priv;
        const TnyAccountStore *account_store;
        const gchar *key;
-       PwdAttempt *attempt;
+       gchar *pwd;
 
         account_store = TNY_ACCOUNT_STORE(g_object_get_data (G_OBJECT(account),
                                                             "account_store"));
@@ -778,15 +761,11 @@ forget_password (TnyAccount *account)
 
        /* Do not remove the key, this will allow us to detect that we
           have already asked for it at least once */
-       attempt = g_hash_table_lookup (priv->password_hash, key);
-       if (attempt) {
-               attempt->count--;
-               g_debug ("%s, remaining %d for account %s", __FUNCTION__, attempt->count, key);
-               if (attempt->count == 0) {
-                       if (attempt->pwd)
-                               memset (attempt->pwd, 0, strlen (attempt->pwd));
-                       g_hash_table_insert (priv->password_hash, g_strdup (key), NULL);
-               }
+       pwd = g_hash_table_lookup (priv->password_hash, key);
+       if (pwd) {
+               g_debug ("%s, forgetting %s for account %s", __FUNCTION__, pwd, key);
+               memset (pwd, 0, strlen (pwd));
+               g_hash_table_insert (priv->password_hash, g_strdup (key), NULL);
        }
 }
 
@@ -902,6 +881,36 @@ volume_path_is_mounted (const gchar* path)
        return result;
 }
 
+static void _bodies_filter (TnyMsg *msg, TnyList *list)
+{
+       TnyMimePart *html_part, *text_part, *calendar_part;
+
+       html_part = modest_tny_msg_find_body_part (msg, TRUE);
+       text_part = modest_tny_msg_find_body_part (msg, FALSE);
+       calendar_part = modest_tny_msg_find_calendar (msg);
+
+       if (text_part && TNY_IS_MIME_PART (text_part) && html_part == text_part) {
+               g_object_unref (text_part);
+               text_part = NULL;
+       }
+
+       if (html_part && TNY_IS_MIME_PART (html_part)) {
+               tny_list_prepend (list, G_OBJECT (html_part));
+               g_object_unref (html_part);
+       }
+
+       if (text_part && TNY_IS_MIME_PART (text_part)) {
+               tny_list_prepend (list, G_OBJECT (text_part));
+               g_object_unref (text_part);
+       }
+
+       if (calendar_part && TNY_IS_MIME_PART (calendar_part)) {
+               tny_list_prepend (list, G_OBJECT (calendar_part));
+               g_object_unref (calendar_part);
+       }
+}
+
+
 ModestTnyAccountStore*
 modest_tny_account_store_new (ModestAccountMgr *account_mgr,
                              TnyDevice *device)
@@ -912,10 +921,14 @@ modest_tny_account_store_new (ModestAccountMgr *account_mgr,
        TnyLockable *lockable;
        GnomeVFSVolumeMonitor* monitor = NULL;
        gboolean auto_update;
+       const gchar *mmc_path = NULL;
 
        g_return_val_if_fail (account_mgr, NULL);
        g_return_val_if_fail (device, NULL);
 
+       tny_camel_bs_msg_receive_strategy_set_global_bodies_filter (
+               (TnyCamelBsMsgReceiveStrategyBodiesFilter) _bodies_filter);
+
        obj  = G_OBJECT(g_object_new(MODEST_TYPE_TNY_ACCOUNT_STORE, NULL));
        priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(obj);
 
@@ -987,7 +1000,8 @@ modest_tny_account_store_new (ModestAccountMgr *account_mgr,
                add_connection_specific_transport_accounts (MODEST_TNY_ACCOUNT_STORE(obj));
 
        /* This is a singleton, so it does not need to be unrefed. */
-       if (volume_path_is_mounted (g_getenv (MODEST_MMC1_VOLUMEPATH_ENV))) {
+       mmc_path = g_getenv (MODEST_MMC1_VOLUMEPATH_ENV);
+       if (mmc_path && volume_path_is_mounted (mmc_path)) {
                /* It is mounted: */
                add_mmc_account (MODEST_TNY_ACCOUNT_STORE (obj), FALSE /* don't emit the insert signal. */);
        }
@@ -1168,15 +1182,20 @@ modest_tny_account_store_alert (TnyAccountStore *self,
                                                                                        tny_account_get_id (account));
 
                if (!success) {
+                       gboolean show_banner;
+
+                       g_debug ("%s: %s alert received (%s)", __FUNCTION__,
+                                (error->code == TNY_SERVICE_ERROR_CONNECT) ? "connect" : "aunthenticate",
+                                error->message);
 
-                       modest_platform_run_information_dialog (NULL, prompt, TRUE);
+                       if (tny_device_is_online (device) &&
+                           modest_window_mgr_get_num_windows (modest_runtime_get_window_mgr ()))
+                               modest_platform_run_information_dialog (NULL, prompt, TRUE);
 
-                       /* Show the account dialog. Checking the online status
-                          allows us to minimize the number of times that we
-                          incorrectly show the dialog */
-                       if (tny_device_is_online (device))
-                               show_wrong_password_dialog (account,
-                                                           (error->code == TNY_SERVICE_ERROR_CONNECT) ? FALSE : TRUE);
+                       /* Show the account dialog */
+                       show_banner = (error->code == TNY_SERVICE_ERROR_CONNECT) ? FALSE : TRUE;
+                       g_debug ("%s: going to show settings dialog", __FUNCTION__);
+                       show_wrong_password_dialog (self, account, show_banner);
                        retval = TRUE;
                }
        }
@@ -1568,7 +1587,7 @@ create_tny_account (ModestTnyAccountStore *self,
        if (account) {
                /* Forget any cached password for the account, so that
                   we use a new account if any */
-               forget_password_in_memory (self, tny_account_get_id (account));
+               modest_tny_account_store_forget_password_in_memory (self, tny_account_get_id (account));
 
                /* Set the account store */
                g_object_set_data (G_OBJECT(account), "account_store", self);
@@ -1890,7 +1909,7 @@ on_account_removed (ModestAccountMgr *acc_mgr,
           with the configuration system this could not exist */
        if (TNY_IS_STORE_ACCOUNT(store_account)) {
                /* Forget any cached password for the account */
-               forget_password_in_memory (self, tny_account_get_id (store_account));
+               modest_tny_account_store_forget_password_in_memory (self, tny_account_get_id (store_account));
 
                /* Remove it from the list of accounts and notify the
                   observers. Do not need to wait for account
@@ -1916,7 +1935,7 @@ on_account_removed (ModestAccountMgr *acc_mgr,
        if (TNY_IS_TRANSPORT_ACCOUNT(transport_account)) {
 
                /* Forget any cached password for the account */
-               forget_password_in_memory (self, tny_account_get_id (transport_account));
+               modest_tny_account_store_forget_password_in_memory (self, tny_account_get_id (transport_account));
 
                /* Remove transport account. It'll free the reference
                   added by get_server_account */
@@ -2418,20 +2437,3 @@ modest_tny_account_store_is_disk_full_error (ModestTnyAccountStore *self,
                return FALSE;
        }
 }
-
-void
-modest_tny_account_store_reset_attempt_count (ModestTnyAccountStore *self,
-                                             TnyAccount *account)
-{
-       ModestTnyAccountStorePrivate *priv;
-       PwdAttempt *attempt;
-
-        priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
-
-       /* Reset the count */
-       attempt = g_hash_table_lookup (priv->password_hash, tny_account_get_id (account));
-       if (attempt) {
-               attempt->count = RETRY_ATTEMPTS;
-               g_debug ("%s, reseting the attempt count for account %s", __FUNCTION__, tny_account_get_id (account));
-       }
-}