[evolution-data-server/gnome-3-6] Bug #680497 - POP3 re-adds messages to local Inbox
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/gnome-3-6] Bug #680497 - POP3 re-adds messages to local Inbox
- Date: Thu, 25 Oct 2012 10:03:06 +0000 (UTC)
commit 2b8c404fd91eda2bb4335ef7a2019e2fa1374ee1
Author: Milan Crha <mcrha redhat com>
Date: Thu Oct 25 12:02:42 2012 +0200
Bug #680497 - POP3 re-adds messages to local Inbox
camel/providers/pop3/camel-pop3-engine.c | 58 +++++++++++++++++---------
camel/providers/pop3/camel-pop3-engine.h | 10 +++-
camel/providers/pop3/camel-pop3-folder.c | 66 ++++++++++++++++++++++--------
camel/providers/pop3/camel-pop3-store.c | 22 +++++++---
4 files changed, 110 insertions(+), 46 deletions(-)
---
diff --git a/camel/providers/pop3/camel-pop3-engine.c b/camel/providers/pop3/camel-pop3-engine.c
index 916fa95..7ee2843 100644
--- a/camel/providers/pop3/camel-pop3-engine.c
+++ b/camel/providers/pop3/camel-pop3-engine.c
@@ -41,7 +41,7 @@ extern CamelServiceAuthType camel_pop3_apop_authtype;
#define dd(x) (camel_debug ("pop3")?(x):0)
-static void get_capabilities (CamelPOP3Engine *pe, GCancellable *cancellable);
+static gboolean get_capabilities (CamelPOP3Engine *pe, GCancellable *cancellable, GError **error);
G_DEFINE_TYPE (CamelPOP3Engine, camel_pop3_engine, CAMEL_TYPE_OBJECT)
@@ -124,6 +124,7 @@ read_greeting (CamelPOP3Engine *pe,
* @source: source stream
* @flags: engine flags
* @cancellable: optional #GCancellable object, or %NULL
+ * @error: optional #GError, or %NULL
*
* Returns a NULL stream. A null stream is always at eof, and
* always returns success for all reads and writes.
@@ -133,7 +134,8 @@ read_greeting (CamelPOP3Engine *pe,
CamelPOP3Engine *
camel_pop3_engine_new (CamelStream *source,
guint32 flags,
- GCancellable *cancellable)
+ GCancellable *cancellable,
+ GError **error)
{
CamelPOP3Engine *pe;
@@ -143,13 +145,12 @@ camel_pop3_engine_new (CamelStream *source,
pe->state = CAMEL_POP3_ENGINE_AUTH;
pe->flags = flags;
- if (read_greeting (pe, cancellable) == -1) {
+ if (read_greeting (pe, cancellable) == -1 ||
+ !get_capabilities (pe, cancellable, error)) {
g_object_unref (pe);
return NULL;
}
- get_capabilities (pe, cancellable);
-
return pe;
}
@@ -157,16 +158,18 @@ camel_pop3_engine_new (CamelStream *source,
* camel_pop3_engine_reget_capabilities:
* @engine: pop3 engine
* @cancellable: optional #GCancellable object, or %NULL
+ * @error: optional #GError, or %NULL
*
* Regets server capabilities (needed after a STLS command is issued for example).
**/
-void
+gboolean
camel_pop3_engine_reget_capabilities (CamelPOP3Engine *engine,
- GCancellable *cancellable)
+ GCancellable *cancellable,
+ GError **error)
{
- g_return_if_fail (CAMEL_IS_POP3_ENGINE (engine));
+ g_return_val_if_fail (CAMEL_IS_POP3_ENGINE (engine), FALSE);
- get_capabilities (engine, cancellable);
+ return get_capabilities (engine, cancellable, error);
}
/* TODO: read implementation too?
@@ -186,6 +189,7 @@ static void
cmd_capa (CamelPOP3Engine *pe,
CamelPOP3Stream *stream,
GCancellable *cancellable,
+ GError **error,
gpointer data)
{
guchar *line, *tok, *next;
@@ -199,7 +203,7 @@ cmd_capa (CamelPOP3Engine *pe,
g_return_if_fail (pe != NULL);
do {
- ret = camel_pop3_stream_line (stream, &line, &len, cancellable, NULL);
+ ret = camel_pop3_stream_line (stream, &line, &len, cancellable, error);
if (ret >= 0) {
if (strncmp ((gchar *) line, "SASL ", 5) == 0) {
tok = line + 5;
@@ -227,13 +231,15 @@ cmd_capa (CamelPOP3Engine *pe,
} while (ret > 0);
}
-static void
+static gboolean
get_capabilities (CamelPOP3Engine *pe,
- GCancellable *cancellable)
+ GCancellable *cancellable,
+ GError **error)
{
CamelPOP3Command *pc;
+ GError *local_error = NULL;
- g_return_if_fail (pe != NULL);
+ g_return_val_if_fail (pe != NULL, FALSE);
if (!(pe->flags & CAMEL_POP3_ENGINE_DISABLE_EXTENSIONS)) {
pc = camel_pop3_engine_command_new (pe, CAMEL_POP3_COMMAND_MULTI, cmd_capa, NULL, cancellable, NULL, "CAPA\r\n");
@@ -243,8 +249,8 @@ get_capabilities (CamelPOP3Engine *pe,
if (pe->state == CAMEL_POP3_ENGINE_TRANSACTION && !(pe->capa & CAMEL_POP3_CAP_UIDL)) {
/* check for UIDL support manually */
- pc = camel_pop3_engine_command_new (pe, CAMEL_POP3_COMMAND_SIMPLE, NULL, NULL, cancellable, NULL, "UIDL 1\r\n");
- while (camel_pop3_engine_iterate (pe, pc, cancellable, NULL) > 0)
+ pc = camel_pop3_engine_command_new (pe, CAMEL_POP3_COMMAND_SIMPLE, NULL, NULL, cancellable, &local_error, "UIDL 1\r\n");
+ while (camel_pop3_engine_iterate (pe, pc, cancellable, &local_error) > 0)
;
if (pc->state == CAMEL_POP3_COMMAND_OK)
@@ -253,6 +259,13 @@ get_capabilities (CamelPOP3Engine *pe,
camel_pop3_engine_command_free (pe, pc);
}
}
+
+ if (local_error) {
+ g_propagate_error (error, local_error);
+ return FALSE;
+ }
+
+ return TRUE;
}
/* returns true if the command was sent, false if it was just queued */
@@ -324,23 +337,28 @@ camel_pop3_engine_iterate (CamelPOP3Engine *pe,
camel_pop3_stream_set_mode (pe->stream, CAMEL_POP3_STREAM_DATA);
if (pc->func)
- pc->func (pe, pe->stream, cancellable, pc->func_data);
+ pc->func (pe, pe->stream, cancellable, error, pc->func_data);
/* Make sure we get all data before going back to command mode */
- while (camel_pop3_stream_getd (pe->stream, &p, &len, cancellable, NULL) > 0)
+ while (camel_pop3_stream_getd (pe->stream, &p, &len, cancellable, error) > 0)
;
camel_pop3_stream_set_mode (pe->stream, CAMEL_POP3_STREAM_LINE);
} else {
pc->state = CAMEL_POP3_COMMAND_OK;
}
break;
- case '-':
+ case '-': {
+ const gchar *text = (const gchar *) p;
+
pc->state = CAMEL_POP3_COMMAND_ERR;
+ pc->error_str = g_strdup (g_ascii_strncasecmp (text, "-ERR ", 5) == 0 ? text + 5 : text + 1);
+ }
break;
default:
/* what do we do now? f'knows! */
g_warning ("Bad server response: %s\n", p);
pc->state = CAMEL_POP3_COMMAND_ERR;
+ pc->error_str = g_strdup ((const gchar *) p + 1);
break;
}
@@ -360,7 +378,7 @@ camel_pop3_engine_iterate (CamelPOP3Engine *pe,
&& pe->current != NULL)
break;
- if (camel_stream_write ((CamelStream *) pe->stream, pc->data, strlen (pc->data), cancellable, NULL) == -1)
+ if (camel_stream_write ((CamelStream *) pe->stream, pc->data, strlen (pc->data), cancellable, error) == -1)
goto ioerror;
pe->sentlen += strlen (pc->data);
@@ -428,6 +446,7 @@ camel_pop3_engine_command_new (CamelPOP3Engine *pe,
pc->data = g_strdup_vprintf (fmt, ap);
va_end (ap);
pc->state = CAMEL_POP3_COMMAND_IDLE;
+ pc->error_str = NULL;
/* TODO: what about write errors? */
engine_command_queue (pe, pc, cancellable, error);
@@ -441,6 +460,7 @@ camel_pop3_engine_command_free (CamelPOP3Engine *pe,
{
if (pe && pe->current != pc)
g_queue_remove (&pe->done, pc);
+ g_free (pc->error_str);
g_free (pc->data);
g_free (pc);
}
diff --git a/camel/providers/pop3/camel-pop3-engine.h b/camel/providers/pop3/camel-pop3-engine.h
index 35ba1c7..cc58001 100644
--- a/camel/providers/pop3/camel-pop3-engine.h
+++ b/camel/providers/pop3/camel-pop3-engine.h
@@ -94,11 +94,13 @@ enum {
typedef void (*CamelPOP3CommandFunc) (CamelPOP3Engine *pe,
CamelPOP3Stream *stream,
GCancellable *cancellable,
+ GError **error,
gpointer data);
struct _CamelPOP3Command {
guint32 flags;
camel_pop3_command_t state;
+ gchar *error_str;
CamelPOP3CommandFunc func;
gpointer func_data;
@@ -141,10 +143,12 @@ GType camel_pop3_engine_get_type (void);
CamelPOP3Engine *
camel_pop3_engine_new (CamelStream *source,
guint32 flags,
- GCancellable *cancellable);
-void camel_pop3_engine_reget_capabilities
+ GCancellable *cancellable,
+ GError **error);
+gboolean camel_pop3_engine_reget_capabilities
(CamelPOP3Engine *engine,
- GCancellable *cancellable);
+ GCancellable *cancellable,
+ GError **error);
void camel_pop3_engine_command_free (CamelPOP3Engine *pe,
CamelPOP3Command *pc);
gint camel_pop3_engine_iterate (CamelPOP3Engine *pe,
diff --git a/camel/providers/pop3/camel-pop3-folder.c b/camel/providers/pop3/camel-pop3-folder.c
index 6eb6398..4c0a407 100644
--- a/camel/providers/pop3/camel-pop3-folder.c
+++ b/camel/providers/pop3/camel-pop3-folder.c
@@ -63,6 +63,7 @@ static void
cmd_uidl (CamelPOP3Engine *pe,
CamelPOP3Stream *stream,
GCancellable *cancellable,
+ GError **error,
gpointer data)
{
gint ret;
@@ -74,7 +75,7 @@ cmd_uidl (CamelPOP3Engine *pe,
CamelPOP3Folder *folder = data;
do {
- ret = camel_pop3_stream_line (stream, &line, &len, cancellable, NULL);
+ ret = camel_pop3_stream_line (stream, &line, &len, cancellable, error);
if (ret >= 0) {
if (strlen ((gchar *) line) > 1024)
line[1024] = 0;
@@ -97,6 +98,7 @@ static void
cmd_builduid (CamelPOP3Engine *pe,
CamelPOP3Stream *stream,
GCancellable *cancellable,
+ GError **error,
gpointer data)
{
GChecksum *checksum;
@@ -145,6 +147,7 @@ static void
cmd_list (CamelPOP3Engine *pe,
CamelPOP3Stream *stream,
GCancellable *cancellable,
+ GError **error,
gpointer data)
{
gint ret;
@@ -173,7 +176,7 @@ cmd_list (CamelPOP3Engine *pe,
g_object_unref (settings);
do {
- ret = camel_pop3_stream_line (stream, &line, &len, cancellable, NULL);
+ ret = camel_pop3_stream_line (stream, &line, &len, cancellable, error);
if (ret >= 0) {
if (sscanf ((gchar *) line, "%u %u", &id, &size) == 2) {
fi = g_malloc0 (sizeof (*fi));
@@ -185,7 +188,7 @@ cmd_list (CamelPOP3Engine *pe,
pe,
CAMEL_POP3_COMMAND_MULTI,
cmd_builduid, fi,
- cancellable, NULL,
+ cancellable, error,
"TOP %u 0\r\n", id);
g_ptr_array_add (pop3_folder->uids, fi);
g_hash_table_insert (
@@ -319,22 +322,23 @@ static void
cmd_tocache (CamelPOP3Engine *pe,
CamelPOP3Stream *stream,
GCancellable *cancellable,
+ GError **error,
gpointer data)
{
CamelPOP3FolderInfo *fi = data;
gchar buffer[2048];
gint w = 0, n;
- GError *error = NULL;
+ GError *local_error = NULL;
/* What if it fails? */
/* We write an '*' to the start of the stream to say its not complete yet */
/* This should probably be part of the cache code */
- if ((n = camel_stream_write (fi->stream, "*", 1, cancellable, &error)) == -1)
+ if ((n = camel_stream_write (fi->stream, "*", 1, cancellable, &local_error)) == -1)
goto done;
- while ((n = camel_stream_read ((CamelStream *) stream, buffer, sizeof (buffer), cancellable, &error)) > 0) {
- n = camel_stream_write (fi->stream, buffer, n, cancellable, &error);
+ while ((n = camel_stream_read ((CamelStream *) stream, buffer, sizeof (buffer), cancellable, &local_error)) > 0) {
+ n = camel_stream_write (fi->stream, buffer, n, cancellable, &local_error);
if (n == -1)
break;
@@ -346,17 +350,16 @@ cmd_tocache (CamelPOP3Engine *pe,
}
/* it all worked, output a '#' to say we're a-ok */
- if (error == NULL) {
+ if (local_error == NULL) {
g_seekable_seek (
G_SEEKABLE (fi->stream),
0, G_SEEK_SET, cancellable, NULL);
- camel_stream_write (fi->stream, "#", 1, cancellable, &error);
+ camel_stream_write (fi->stream, "#", 1, cancellable, &local_error);
}
done:
- if (error != NULL) {
- g_warning ("POP3 retrieval failed: %s", error->message);
- g_error_free (error);
+ if (local_error != NULL) {
+ g_propagate_error (error, local_error);
}
g_object_unref (fi->stream);
@@ -574,7 +577,7 @@ pop3_folder_get_message_sync (CamelFolder *folder,
pop3_store->engine,
CAMEL_POP3_COMMAND_MULTI,
cmd_tocache, fi,
- cancellable, NULL,
+ cancellable, error,
"RETR %u\r\n", fi->id);
/* Also initiate retrieval of some of the following
@@ -597,7 +600,7 @@ pop3_folder_get_message_sync (CamelFolder *folder,
pop3_store->engine,
CAMEL_POP3_COMMAND_MULTI,
cmd_tocache, pfi,
- cancellable, NULL,
+ cancellable, error,
"RETR %u\r\n", pfi->id);
}
}
@@ -730,28 +733,57 @@ pop3_folder_refresh_info_sync (CamelFolder *folder,
cmd_uidl, folder,
cancellable, &local_error,
"UIDL\r\n");
- while ((i = camel_pop3_engine_iterate (pop3_store->engine, NULL, cancellable, error)) > 0)
+ while ((i = camel_pop3_engine_iterate (pop3_store->engine, NULL, cancellable, &local_error)) > 0)
;
if (local_error) {
g_propagate_error (error, local_error);
+ g_prefix_error (error, _("Cannot get POP summary: "));
success = FALSE;
} else if (i == -1) {
- g_prefix_error (error, _("Cannot get POP summary: "));
+ g_set_error_literal (error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Cannot get POP summary: "));
success = FALSE;
}
/* TODO: check every id has a uid & commands returned OK too? */
- if (pcl)
+ if (pcl) {
+ if (success && pcl->state == CAMEL_POP3_COMMAND_ERR) {
+ success = FALSE;
+
+ if (pcl->error_str)
+ g_set_error_literal (error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, pcl->error_str);
+ else
+ g_set_error_literal (error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Cannot get POP summary: "));
+ }
+
camel_pop3_engine_command_free (pop3_store->engine, pcl);
+ }
if (pcu) {
+ if (success && pcu->state == CAMEL_POP3_COMMAND_ERR) {
+ success = FALSE;
+
+ if (pcu->error_str)
+ g_set_error_literal (error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, pcu->error_str);
+ else
+ g_set_error_literal (error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Cannot get POP summary: "));
+ }
+
camel_pop3_engine_command_free (pop3_store->engine, pcu);
} else {
for (i = 0; i < pop3_folder->uids->len; i++) {
CamelPOP3FolderInfo *fi = pop3_folder->uids->pdata[i];
if (fi->cmd) {
+ if (success && fi->cmd->state == CAMEL_POP3_COMMAND_ERR) {
+ success = FALSE;
+
+ if (fi->cmd->error_str)
+ g_set_error_literal (error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, fi->cmd->error_str);
+ else
+ g_set_error_literal (error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Cannot get POP summary: "));
+ }
+
camel_pop3_engine_command_free (pop3_store->engine, fi->cmd);
fi->cmd = NULL;
}
diff --git a/camel/providers/pop3/camel-pop3-store.c b/camel/providers/pop3/camel-pop3-store.c
index f721668..187d2e5 100644
--- a/camel/providers/pop3/camel-pop3-store.c
+++ b/camel/providers/pop3/camel-pop3-store.c
@@ -102,6 +102,7 @@ connect_to_server (CamelService *service,
gchar *host;
guint32 flags = 0;
gint ret;
+ GError *local_error = NULL;
settings = camel_service_ref_settings (service);
@@ -133,11 +134,15 @@ connect_to_server (CamelService *service,
if (disable_extensions)
flags |= CAMEL_POP3_ENGINE_DISABLE_EXTENSIONS;
- if (!(store->engine = camel_pop3_engine_new (tcp_stream, flags, cancellable))) {
- g_set_error (
- error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
- _("Failed to read a valid greeting from POP server %s"),
- host);
+ if (!(store->engine = camel_pop3_engine_new (tcp_stream, flags, cancellable, &local_error)) ||
+ local_error != NULL) {
+ if (local_error)
+ g_propagate_error (error, local_error);
+ else
+ g_set_error (
+ error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
+ _("Failed to read a valid greeting from POP server %s"),
+ host);
g_object_unref (tcp_stream);
success = FALSE;
goto exit;
@@ -195,7 +200,8 @@ connect_to_server (CamelService *service,
/* rfc2595, section 4 states that after a successful STLS
* command, the client MUST discard prior CAPA responses */
- camel_pop3_engine_reget_capabilities (store->engine, cancellable);
+ if (!camel_pop3_engine_reget_capabilities (store->engine, cancellable, error))
+ goto exception;
goto exit;
@@ -212,6 +218,7 @@ stls_exception:
camel_pop3_engine_command_free (store->engine, pc);
}*/
+ exception:
g_object_unref (store->engine);
g_object_unref (tcp_stream);
store->engine = NULL;
@@ -446,7 +453,8 @@ pop3_store_connect_sync (CamelService *service,
/* Now that we are in the TRANSACTION state,
* try regetting the capabilities */
store->engine->state = CAMEL_POP3_ENGINE_TRANSACTION;
- camel_pop3_engine_reget_capabilities (store->engine, cancellable);
+ if (!camel_pop3_engine_reget_capabilities (store->engine, cancellable, error))
+ success = FALSE;
exit:
g_free (mechanism);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]