g_printerr ("modest: cannot find server account for %s", account);
}
+/**
+ * modest_tny_account_store_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
+modest_tny_account_store_forget_password_in_memory (ModestTnyAccountStore *self, const gchar * server_account_name)
+{
+ /* printf ("DEBUG: %s\n", __FUNCTION__); */
+ ModestTnyAccountStorePrivate *priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
+
+ if (server_account_name && priv->password_hash) {
+ g_hash_table_remove (priv->password_hash, server_account_name);
+ }
+}
+
static void
on_account_changed (ModestAccountMgr *acc_mgr, const gchar *account,
const GSList *keys, gboolean server_account, gpointer user_data)
{
ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(user_data);
+ /*
+ printf ("DEBUG: %s\n", __FUNCTION__);
+ const GSList *iter = keys;
+ for (iter = keys; iter; iter = g_slist_next (iter)) {
+ printf (" DEBUG: %s: key=%s\n", __FUNCTION__, (const gchar*)iter->data);
+ }
+ */
+
/* Ignore the change if it's a change in the last_updated value */
if (g_slist_length ((GSList *)keys) == 1 &&
- g_str_has_suffix ((const gchar *) keys->data, MODEST_ACCOUNT_LAST_UPDATED))
+ g_str_has_suffix ((const gchar *) keys->data, MODEST_ACCOUNT_LAST_UPDATED)) {
return;
+ }
/* FIXME: make this more finegrained; changes do not really affect _all_
* accounts
*/
recreate_all_accounts (self);
+
+ /* TODO: This doesn't actually work, because
+ * a) The account name is not sent correctly per key:
+ * b) We should test the end of the key, not the whole keym
+ * c) We don't seem to be getting all keys here.
+ * Instead, we just forget the password for all accounts when we create them, for now.
+ */
+ #if 0
+ /* If a password has changed, then forget the previously cached password for this account: */
+ if (server_account && keys && g_slist_find_custom ((GSList *)keys, MODEST_ACCOUNT_PASSWORD, (GCompareFunc)strcmp)) {
+ printf ("DEBUG: %s: Forgetting cached password for account ID=%s\n", __FUNCTION__, account);
+ modest_tny_account_store_forget_password_in_memory (self, account);
+ }
+ #endif
g_signal_emit (G_OBJECT(self), signals[ACCOUNT_UPDATE_SIGNAL], 0,
account);
found = g_hash_table_lookup_extended (priv->account_settings_dialog_hash,
modest_account_name, NULL, (gpointer*)&dialog_as_gpointer);
}
-
ModestAccountSettingsDialog *dialog = dialog_as_gpointer;
ModestWindow *main_window =
return FALSE; /* Dont' call this again. */
}
+typedef struct
+{
+ GMainLoop *loop;
+ ModestTnyAccountStore* account_store;
+ const gchar* server_account_id;
+ gchar **username;
+ gchar **password;
+ gboolean *cancel;
+ gboolean *remember;
+} IdlePasswordRequest;
+
+static gboolean
+on_idle_request_password (gpointer user_data)
+{
+ gdk_threads_enter();
+
+ IdlePasswordRequest* info = (IdlePasswordRequest*)user_data;
+ g_signal_emit (G_OBJECT(info->account_store), signals[PASSWORD_REQUESTED_SIGNAL], 0,
+ info->server_account_id, /* server_account_name */
+ info->username, info->password, info->cancel, info->remember);
+
+ if (info->loop)
+ g_main_loop_quit (info->loop);
+
+ gdk_threads_leave();
+
+ return FALSE; /* Don't call again. */
+}
+
+static void
+request_password_in_main_loop_and_wait (ModestTnyAccountStore *account_store,
+ const gchar* server_account_id,
+ gchar **username,
+ gchar **password,
+ gboolean *cancel,
+ gboolean *remember)
+{
+ IdlePasswordRequest *data = g_slice_new0 (IdlePasswordRequest);
+ data->account_store = account_store;
+ data->server_account_id = server_account_id;
+ data->username = username;
+ data->password = password;
+ data->cancel = cancel;
+ data->remember = remember;
+
+ data->loop = g_main_loop_new (NULL, FALSE /* not running */);
+
+ /* Cause the function to be run in an idle-handler, which is always
+ * in the main thread:
+ */
+ g_idle_add (&on_idle_request_password, data);
+
+ /* This main loop will run until the idle handler has stopped it: */
+ printf ("DEBUG: %s: before g_main_loop_run()\n", __FUNCTION__);
+ GDK_THREADS_LEAVE();
+ g_main_loop_run (data->loop);
+ GDK_THREADS_ENTER();
+ printf ("DEBUG: %s: after g_main_loop_run()\n", __FUNCTION__);
+ printf ("DEBUG: %s: Finished\n", __FUNCTION__);
+ g_main_loop_unref (data->loop);
+
+ g_slice_free (IdlePasswordRequest, data);
+}
+
/* This callback will be called by Tinymail when it needs the password
* from the user or the account settings.
* It can also call forget_password() before calling this,
account_store = TNY_ACCOUNT_STORE(get_account_store_for_account (account));
if (!server_account_name || !account_store) {
- g_warning ("%s: could not retrieve account_store for account %s",
+ g_warning ("modest: %s: could not retrieve account_store for account %s",
__FUNCTION__, server_account_name ? server_account_name : "<NULL>");
if (cancel)
*cancel = TRUE;
gboolean remember = FALSE;
pwd = NULL;
- g_signal_emit (G_OBJECT(self), signals[PASSWORD_REQUESTED_SIGNAL], 0,
- account_id, /* server_account_name */
+ request_password_in_main_loop_and_wait (self, account_id,
&username, &pwd, cancel, &remember);
if (!*cancel) {
*/
}
+static void
+destroy_password_hashtable (ModestTnyAccountStore *self)
+{
+ ModestTnyAccountStorePrivate *priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
+
+ g_free (priv->cache_dir);
+ priv->cache_dir = NULL;
+
+ if (priv->password_hash) {
+ g_hash_table_destroy (priv->password_hash);
+ priv->password_hash = NULL;
+ }
+}
static void
modest_tny_account_store_finalize (GObject *obj)
priv->password_hash = NULL;
}
- if (priv->account_settings_dialog_hash) {
- g_hash_table_destroy (priv->account_settings_dialog_hash);
- priv->account_settings_dialog_hash = NULL;
- }
+ destroy_password_hashtable (self);
if (priv->account_mgr) {
g_object_unref (G_OBJECT(priv->account_mgr));
get_password,
forget_password);
if (tny_account) {
+ /* Forget any cached password for the account,
+ * so that we use a new account if any.
+ * TODO: Really we should do this in a more precise way in
+ * on_account_changed().
+ */
+ modest_tny_account_store_forget_password_in_memory (
+ MODEST_TNY_ACCOUNT_STORE (self),
+ tny_account_get_id (tny_account));
+
g_object_set_data (G_OBJECT(tny_account), "account_store",
(gpointer)self);
if (list)
TNY_ACCOUNT_STORE_STORE_ACCOUNTS);
modest_tny_account_store_get_accounts (self, list,
TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
+
+ tny_session_camel_set_initialized (priv->session);
+
return;
}
get_server_accounts (self, list, TNY_ACCOUNT_TYPE_STORE);
else
get_cached_accounts (self, list, TNY_ACCOUNT_TYPE_STORE);
+
+ tny_session_camel_set_initialized (priv->session);
} else if (request_type == TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS) {
if (!priv->transport_accounts)
get_server_accounts (self, list, TNY_ACCOUNT_TYPE_TRANSPORT);
else
get_cached_accounts (self, list, TNY_ACCOUNT_TYPE_TRANSPORT);
+
+ tny_session_camel_set_initialized (priv->session);
} else
g_return_if_reached (); /* incorrect req type */
}
static gboolean
-modest_tny_account_store_alert (TnyAccountStore *self, TnyAlertType type,
+modest_tny_account_store_alert (TnyAccountStore *self, TnyAccount *account, TnyAlertType type,
gboolean question, const GError *error)
{
- /* TODO: It would be nice to know what account caused this error. */
-
g_return_val_if_fail (error, FALSE);
if ((error->domain != TNY_ACCOUNT_ERROR)
printf("DEBUG: %s: GError code: %d, message=%s\n",
__FUNCTION__, error->code, error->message);
-
+ /* Get the server name: */
+ const gchar* server_name = NULL;
+ if (account && TNY_IS_ACCOUNT (account)) {
+ server_name = tny_account_get_hostname (account);
+ printf ("modest: %s: account name = %s, server_name=%s\n", __FUNCTION__,
+ tny_account_get_id (account), server_name);
+ }
+
+ if (!server_name)
+ server_name = _("Unknown Server");
+
+ ModestTransportStoreProtocol proto = MODEST_PROTOCOL_STORE_POP; /* Arbitrary default. */
+ if (account) {
+ const gchar *proto_name = tny_account_get_proto (account);
+ if (proto_name)
+ proto = modest_protocol_info_get_transport_store_protocol (proto_name);
+ else {
+ g_warning("modest: %s: account with id=%s has no proto.\n", __FUNCTION__,
+ tny_account_get_id (account));
+ }
+ }
+
/* const gchar *prompt = NULL; */
gchar *prompt = NULL;
switch (error->code) {
__FUNCTION__, error->domain, error->code, error->message);
prompt = NULL;
break;
+
case TNY_ACCOUNT_ERROR_TRY_CONNECT_HOST_LOOKUP_FAILED:
+ /* TODO: Show the appropriate message, depending on whether it's POP or IMAP: */
g_debug ("%s: Handling GError domain=%d, code=%d (lookup failed), message=%s",
__FUNCTION__, error->domain, error->code, error->message);
- prompt = g_strdup (_("emev_ni_ui_pop3_msg_connect_error"));
+
+ switch (proto) {
+ case MODEST_PROTOCOL_STORE_POP:
+ prompt = g_strdup_printf (_("emev_ni_ui_pop3_msg_connect_error"), server_name);
+ break;
+ case MODEST_PROTOCOL_STORE_IMAP:
+ prompt = g_strdup_printf (_("emev_ni_ui_imap_connect_server_error"), server_name);
+ break;
+ case MODEST_PROTOCOL_TRANSPORT_SMTP:
+ default: /* Arbitrary default. */
+ prompt = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
+ break;
+ }
+
/*
prompt = g_strdup_printf(
_("Incorrect Account Settings:\n Host lookup failed.%s"),
error->message);
*/
break;
+
case TNY_ACCOUNT_ERROR_TRY_CONNECT_AUTHENTICATION_NOT_SUPPORTED:
g_debug ("%s: Handling GError domain=%d, code=%d (authentication not supported), message=%s",
__FUNCTION__, error->domain, error->code, error->message);
_("Incorrect Account Settings:\nThe secure authentication method is not supported.\n%s"),
error->message);
break;
+
case TNY_ACCOUNT_ERROR_TRY_CONNECT_CERTIFICATE:
g_debug ("%s: Handling GError domain=%d, code=%d (certificatae), message=%s",
__FUNCTION__, error->domain, error->code, error->message);
_("Incorrect Account Settings"),
error->message);
- /* TODO: If we can ever determine that the problem is a wrong password:
- * In this case, the UI spec wants us to show a banner, and then
- * open the Account Settings dialog. */
- /* Note: Sometimes, the get_password() function seems to be called again
- * when a password is wrong, but sometimes this alert_func is called. */
- #if 0
- GtkWidget *parent_widget =
- GTK_WIDGET (
- modest_window_mgr_get_main_window (
- modest_runtime_get_window_mgr ()));
-
- hildon_banner_show_information (
- parent_widget,
- NULL /* icon name */,
- _("mcen_ib_username_pw_incorrect") );
-
- /* Show the Account Settings window: */
- ModestAccountSettingsDialog *dialog = modest_account_settings_dialog_new ();
- /* TODO: Get the account somehow. Maybe tinymail should send it with the signal. */
- const gchar* modest_account_name =
- modest_tny_account_get_parent_modest_account_name_for_server_account (account);
- g_assert (modest_account_name);
- modest_account_settings_dialog_set_account_name (dialog,
- modest_account_name);
-
- gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (self));
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (GTK_WIDGET (dialog));
- #endif
+ /* Note: If the password was wrong then get_password() would be called again,
+ * instead of this vfunc being called. */
break;
-
- //TODO: We have started receiving errors of
- //domain=TNY_ACCOUNT_ERROR, code=TNY_ACCOUNT_ERROR_TRY_CONNECT, message="Canceled".
- //If this is really a result of us cancelling our own operation then
- //a) this probably shouldn't be an error, and
- //b) should have its own error code.
default:
g_warning ("%s: Unhandled GError code: %d, message=%s",