[evolution-data-server/gnome-3-0] Bug #648468 - POP3 doesn't recover or claim error after lost connection
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/gnome-3-0] Bug #648468 - POP3 doesn't recover or claim error after lost connection
- Date: Tue, 21 Jun 2011 10:31:28 +0000 (UTC)
commit 75c691d7d3d0baf860dc55026dc4ae2916d170d7
Author: Milan Crha <mcrha redhat com>
Date: Tue Jun 21 12:30:57 2011 +0200
Bug #648468 - POP3 doesn't recover or claim error after lost connection
camel/providers/pop3/camel-pop3-engine.c | 14 +++---
camel/providers/pop3/camel-pop3-engine.h | 2 +-
camel/providers/pop3/camel-pop3-folder.c | 79 ++++++++++++++++++------------
camel/providers/pop3/camel-pop3-folder.h | 2 +-
camel/providers/pop3/camel-pop3-store.c | 23 +++++----
camel/providers/pop3/camel-pop3-stream.c | 8 +++-
6 files changed, 76 insertions(+), 52 deletions(-)
---
diff --git a/camel/providers/pop3/camel-pop3-engine.c b/camel/providers/pop3/camel-pop3-engine.c
index b07f302..db36f21 100644
--- a/camel/providers/pop3/camel-pop3-engine.c
+++ b/camel/providers/pop3/camel-pop3-engine.c
@@ -221,14 +221,14 @@ get_capabilities (CamelPOP3Engine *pe)
CamelPOP3Command *pc;
if (!(pe->flags & CAMEL_POP3_ENGINE_DISABLE_EXTENSIONS)) {
- pc = camel_pop3_engine_command_new(pe, CAMEL_POP3_COMMAND_MULTI, cmd_capa, NULL, "CAPA\r\n");
+ pc = camel_pop3_engine_command_new(pe, CAMEL_POP3_COMMAND_MULTI, cmd_capa, NULL, NULL, NULL, "CAPA\r\n");
while (camel_pop3_engine_iterate (pe, pc) > 0)
;
camel_pop3_engine_command_free (pe, pc);
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, "UIDL 1\r\n");
+ pc = camel_pop3_engine_command_new (pe, CAMEL_POP3_COMMAND_SIMPLE, NULL, NULL, NULL, NULL, "UIDL 1\r\n");
while (camel_pop3_engine_iterate (pe, pc) > 0)
;
@@ -241,8 +241,8 @@ get_capabilities (CamelPOP3Engine *pe)
}
/* returns true if the command was sent, false if it was just queued */
-static gint
-engine_command_queue (CamelPOP3Engine *pe, CamelPOP3Command *pc)
+static gboolean
+engine_command_queue (CamelPOP3Engine *pe, CamelPOP3Command *pc, GCancellable *cancellable, GError **error)
{
if (((pe->capa & CAMEL_POP3_CAP_PIPE) == 0 || (pe->sentlen + strlen (pc->data)) > CAMEL_POP3_SEND_LIMIT)
&& pe->current != NULL) {
@@ -251,7 +251,7 @@ engine_command_queue (CamelPOP3Engine *pe, CamelPOP3Command *pc)
}
/* ??? */
- if (camel_stream_write ((CamelStream *)pe->stream, pc->data, strlen (pc->data), NULL, NULL) == -1) {
+ if (camel_stream_write ((CamelStream *)pe->stream, pc->data, strlen (pc->data), cancellable, error) == -1) {
camel_dlist_addtail (&pe->queue, (CamelDListNode *)pc);
return FALSE;
}
@@ -377,7 +377,7 @@ ioerror:
}
CamelPOP3Command *
-camel_pop3_engine_command_new (CamelPOP3Engine *pe, guint32 flags, CamelPOP3CommandFunc func, gpointer data, const gchar *fmt, ...)
+camel_pop3_engine_command_new (CamelPOP3Engine *pe, guint32 flags, CamelPOP3CommandFunc func, gpointer data, GCancellable *cancellable, GError **error, const gchar *fmt, ...)
{
CamelPOP3Command *pc;
va_list ap;
@@ -392,7 +392,7 @@ camel_pop3_engine_command_new (CamelPOP3Engine *pe, guint32 flags, CamelPOP3Comm
pc->state = CAMEL_POP3_COMMAND_IDLE;
/* TODO: what about write errors? */
- engine_command_queue (pe, pc);
+ engine_command_queue (pe, pc, cancellable, error);
return pc;
}
diff --git a/camel/providers/pop3/camel-pop3-engine.h b/camel/providers/pop3/camel-pop3-engine.h
index d766cb4..e7ff7c5 100644
--- a/camel/providers/pop3/camel-pop3-engine.h
+++ b/camel/providers/pop3/camel-pop3-engine.h
@@ -146,7 +146,7 @@ void camel_pop3_engine_command_free (CamelPOP3Engine *pe, CamelPOP3
gint camel_pop3_engine_iterate (CamelPOP3Engine *pe, CamelPOP3Command *pc);
-CamelPOP3Command *camel_pop3_engine_command_new (CamelPOP3Engine *pe, guint32 flags, CamelPOP3CommandFunc func, gpointer data, const gchar *fmt, ...);
+CamelPOP3Command *camel_pop3_engine_command_new (CamelPOP3Engine *pe, guint32 flags, CamelPOP3CommandFunc func, gpointer data, GCancellable *cancellable, GError **error, const gchar *fmt, ...);
G_END_DECLS
diff --git a/camel/providers/pop3/camel-pop3-folder.c b/camel/providers/pop3/camel-pop3-folder.c
index 991eff8..d200404 100644
--- a/camel/providers/pop3/camel-pop3-folder.c
+++ b/camel/providers/pop3/camel-pop3-folder.c
@@ -63,7 +63,7 @@ cmd_uidl (CamelPOP3Engine *pe,
if (fi) {
camel_operation_progress (NULL, (fi->index+1) * 100 / folder->uids->len);
fi->uid = g_strdup (uid);
- g_hash_table_insert (folder->uids_uid, fi->uid, fi);
+ g_hash_table_insert (folder->uids_fi, fi->uid, fi);
} else {
g_warning("ID %u (uid: %s) not in previous LIST output", id, uid);
}
@@ -143,7 +143,7 @@ cmd_list (CamelPOP3Engine *pe, CamelPOP3Stream *stream, gpointer data)
fi->id = id;
fi->index = ((CamelPOP3Folder *)folder)->uids->len;
if ((pop3_store->engine->capa & CAMEL_POP3_CAP_UIDL) == 0)
- fi->cmd = camel_pop3_engine_command_new(pe, CAMEL_POP3_COMMAND_MULTI, cmd_builduid, fi, "TOP %u 0\r\n", id);
+ fi->cmd = camel_pop3_engine_command_new(pe, CAMEL_POP3_COMMAND_MULTI, cmd_builduid, fi, NULL, NULL, "TOP %u 0\r\n", id);
g_ptr_array_add (((CamelPOP3Folder *)folder)->uids, fi);
g_hash_table_insert (((CamelPOP3Folder *)folder)->uids_id, GINT_TO_POINTER (id), fi);
}
@@ -201,29 +201,34 @@ pop3_folder_dispose (GObject *object)
{
CamelPOP3Folder *pop3_folder = CAMEL_POP3_FOLDER (object);
CamelPOP3FolderInfo **fi = (CamelPOP3FolderInfo **)pop3_folder->uids->pdata;
- CamelPOP3Store *pop3_store;
+ CamelPOP3Store *pop3_store = NULL;
CamelStore *parent_store;
- gint i;
parent_store = camel_folder_get_parent_store (CAMEL_FOLDER (object));
- if (parent_store) {
+ if (parent_store)
pop3_store = CAMEL_POP3_STORE (parent_store);
- if (pop3_folder->uids) {
- for (i = 0; i < pop3_folder->uids->len; i++, fi++) {
- if (fi[0]->cmd) {
- while (camel_pop3_engine_iterate (pop3_store->engine, fi[0]->cmd) > 0)
- ;
- camel_pop3_engine_command_free (pop3_store->engine, fi[0]->cmd);
- }
+ if (pop3_folder->uids) {
+ gint i;
- g_free (fi[0]->uid);
- g_free (fi[0]);
+ for (i = 0; i < pop3_folder->uids->len; i++, fi++) {
+ if (fi[0]->cmd && pop3_store) {
+ while (camel_pop3_engine_iterate (pop3_store->engine, fi[0]->cmd) > 0)
+ ;
+ camel_pop3_engine_command_free (pop3_store->engine, fi[0]->cmd);
}
- g_ptr_array_free (pop3_folder->uids, TRUE);
- g_hash_table_destroy (pop3_folder->uids_uid);
+ g_free (fi[0]->uid);
+ g_free (fi[0]);
}
+
+ g_ptr_array_free (pop3_folder->uids, TRUE);
+ pop3_folder->uids = NULL;
+ }
+
+ if (pop3_folder->uids_fi) {
+ g_hash_table_destroy (pop3_folder->uids_fi);
+ pop3_folder->uids_fi = NULL;
}
/* Chain up to parent's dispose() method. */
@@ -269,7 +274,7 @@ pop3_folder_get_filename (CamelFolder *folder,
pop3_folder = CAMEL_POP3_FOLDER (folder);
pop3_store = CAMEL_POP3_STORE (parent_store);
- fi = g_hash_table_lookup (pop3_folder->uids_uid, uid);
+ fi = g_hash_table_lookup (pop3_folder->uids_fi, uid);
if (fi == NULL) {
g_set_error (
error, CAMEL_FOLDER_ERROR,
@@ -292,7 +297,7 @@ pop3_folder_set_message_flags (CamelFolder *folder,
CamelPOP3FolderInfo *fi;
gboolean res = FALSE;
- fi = g_hash_table_lookup (pop3_folder->uids_uid, uid);
+ fi = g_hash_table_lookup (pop3_folder->uids_fi, uid);
if (fi) {
guint32 new = (fi->flags & ~flags) | (set & flags);
@@ -328,7 +333,7 @@ pop3_folder_get_message_sync (CamelFolder *folder,
pop3_folder = CAMEL_POP3_FOLDER (folder);
pop3_store = CAMEL_POP3_STORE (parent_store);
- fi = g_hash_table_lookup (pop3_folder->uids_uid, uid);
+ fi = g_hash_table_lookup (pop3_folder->uids_fi, uid);
if (fi == NULL) {
g_set_error (
error, CAMEL_FOLDER_ERROR,
@@ -388,7 +393,7 @@ pop3_folder_get_message_sync (CamelFolder *folder,
/* ref it, the cache storage routine unref's when done */
fi->stream = g_object_ref (stream);
fi->err = EIO;
- pcr = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, cmd_tocache, fi, "RETR %u\r\n", fi->id);
+ pcr = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, cmd_tocache, fi, NULL, NULL, "RETR %u\r\n", fi->id);
/* Also initiate retrieval of some of the following messages, assume we'll be receiving them */
if (pop3_store->cache != NULL) {
@@ -404,7 +409,7 @@ pop3_folder_get_message_sync (CamelFolder *folder,
if (pfi->stream) {
pfi->err = EIO;
pfi->cmd = camel_pop3_engine_command_new (pop3_store->engine, CAMEL_POP3_COMMAND_MULTI,
- cmd_tocache, pfi, "RETR %u\r\n", pfi->id);
+ cmd_tocache, pfi, NULL, NULL, "RETR %u\r\n", pfi->id);
}
}
}
@@ -479,6 +484,7 @@ pop3_folder_refresh_info_sync (CamelFolder *folder,
CamelPOP3Folder *pop3_folder = (CamelPOP3Folder *) folder;
CamelPOP3Command *pcl, *pcu = NULL;
gboolean success = TRUE;
+ GError *local_error = NULL;
gint i;
parent_store = camel_folder_get_parent_store (folder);
@@ -487,18 +493,19 @@ pop3_folder_refresh_info_sync (CamelFolder *folder,
camel_operation_push_message (
cancellable, _("Retrieving POP summary"));
- pop3_folder->uids = g_ptr_array_new ();
- pop3_folder->uids_uid = g_hash_table_new (g_str_hash, g_str_equal);
/* only used during setup */
pop3_folder->uids_id = g_hash_table_new (NULL, NULL);
- pcl = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, cmd_list, folder, "LIST\r\n");
- if (pop3_store->engine->capa & CAMEL_POP3_CAP_UIDL)
- pcu = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, cmd_uidl, folder, "UIDL\r\n");
+ pcl = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, cmd_list, folder, cancellable, &local_error, "LIST\r\n");
+ if (!local_error && (pop3_store->engine->capa & CAMEL_POP3_CAP_UIDL) != 0)
+ pcu = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, cmd_uidl, folder, cancellable, &local_error, "UIDL\r\n");
while ((i = camel_pop3_engine_iterate (pop3_store->engine, NULL)) > 0)
;
- if (i == -1) {
+ if (local_error) {
+ g_propagate_error (error, local_error);
+ success = FALSE;
+ } else if (i == -1) {
if (errno == EINTR)
g_set_error (
error, G_IO_ERROR,
@@ -515,9 +522,10 @@ pop3_folder_refresh_info_sync (CamelFolder *folder,
/* TODO: check every id has a uid & commands returned OK too? */
- camel_pop3_engine_command_free (pop3_store->engine, pcl);
+ if (pcl)
+ camel_pop3_engine_command_free (pop3_store->engine, pcl);
- if (pop3_store->engine->capa & CAMEL_POP3_CAP_UIDL) {
+ if (pcu) {
camel_pop3_engine_command_free (pop3_store->engine, pcu);
} else {
for (i=0;i<pop3_folder->uids->len;i++) {
@@ -526,16 +534,21 @@ pop3_folder_refresh_info_sync (CamelFolder *folder,
camel_pop3_engine_command_free (pop3_store->engine, fi->cmd);
fi->cmd = NULL;
}
- if (fi->uid)
- g_hash_table_insert (pop3_folder->uids_uid, fi->uid, fi);
+ if (fi->uid) {
+ g_hash_table_insert (pop3_folder->uids_fi, fi->uid, fi);
+ }
}
}
/* dont need this anymore */
g_hash_table_destroy (pop3_folder->uids_id);
+ pop3_folder->uids_id = NULL;
camel_operation_pop_message (cancellable);
+ if (!success)
+ camel_service_disconnect_sync ((CamelService *) pop3_store, TRUE, NULL);
+
return success;
}
@@ -591,6 +604,7 @@ pop3_folder_synchronize_sync (CamelFolder *folder,
0,
NULL,
NULL,
+ NULL, NULL,
"DELE %u\r\n",
fi->id);
@@ -643,6 +657,8 @@ camel_pop3_folder_class_init (CamelPOP3FolderClass *class)
static void
camel_pop3_folder_init (CamelPOP3Folder *pop3_folder)
{
+ pop3_folder->uids = g_ptr_array_new ();
+ pop3_folder->uids_fi = g_hash_table_new (g_str_hash, g_str_equal);
}
CamelFolder *
@@ -784,6 +800,7 @@ camel_pop3_delete_old (CamelFolder *folder,
0,
NULL,
NULL,
+ NULL, NULL,
"DELE %u\r\n",
fi->id);
/* also remove from cache */
diff --git a/camel/providers/pop3/camel-pop3-folder.h b/camel/providers/pop3/camel-pop3-folder.h
index 6a5592a..42e4be0 100644
--- a/camel/providers/pop3/camel-pop3-folder.h
+++ b/camel/providers/pop3/camel-pop3-folder.h
@@ -68,7 +68,7 @@ struct _CamelPOP3Folder {
CamelFolder parent;
GPtrArray *uids;
- GHashTable *uids_uid; /* messageinfo by uid */
+ GHashTable *uids_fi; /* messageinfo uid to CamelPOP3FolderInfo *, which is stored in uids array */
GHashTable *uids_id; /* messageinfo by id */
};
diff --git a/camel/providers/pop3/camel-pop3-store.c b/camel/providers/pop3/camel-pop3-store.c
index 7c0b7b4..f7a90cc 100644
--- a/camel/providers/pop3/camel-pop3-store.c
+++ b/camel/providers/pop3/camel-pop3-store.c
@@ -201,7 +201,7 @@ connect_to_server (CamelService *service,
goto stls_exception;
}
- pc = camel_pop3_engine_command_new (store->engine, 0, NULL, NULL, "STLS\r\n");
+ pc = camel_pop3_engine_command_new (store->engine, 0, NULL, NULL, cancellable, error, "STLS\r\n");
while (camel_pop3_engine_iterate (store->engine, NULL) > 0)
;
@@ -250,7 +250,7 @@ connect_to_server (CamelService *service,
stls_exception:
if (clean_quit) {
/* try to disconnect cleanly */
- pc = camel_pop3_engine_command_new (store->engine, 0, NULL, NULL, "QUIT\r\n");
+ pc = camel_pop3_engine_command_new (store->engine, 0, NULL, NULL, NULL, NULL, "QUIT\r\n");
while (camel_pop3_engine_iterate (store->engine, NULL) > 0)
;
camel_pop3_engine_command_free (store->engine, pc);
@@ -422,8 +422,8 @@ pop3_try_authenticate (CamelService *service,
if (!service->url->authmech) {
/* pop engine will take care of pipelining ability */
- pcu = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, "USER %s\r\n", service->url->user);
- pcp = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, "PASS %s\r\n", service->url->passwd);
+ pcu = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, cancellable, error, "USER %s\r\n", service->url->user);
+ pcp = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, cancellable, error, "PASS %s\r\n", service->url->passwd);
} else if (strcmp(service->url->authmech, "+APOP") == 0 && store->engine->apop) {
gchar *secret, *md5asc, *d;
@@ -449,8 +449,8 @@ pop3_try_authenticate (CamelService *service,
secret = g_alloca (strlen (store->engine->apop)+strlen (service->url->passwd)+1);
sprintf(secret, "%s%s", store->engine->apop, service->url->passwd);
md5asc = g_compute_checksum_for_string (G_CHECKSUM_MD5, secret, -1);
- pcp = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, "APOP %s %s\r\n",
- service->url->user, md5asc);
+ pcp = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, cancellable, error,
+ "APOP %s %s\r\n", service->url->user, md5asc);
g_free (md5asc);
} else {
CamelServiceAuthType *auth;
@@ -642,11 +642,12 @@ pop3_store_disconnect_sync (CamelService *service,
{
CamelServiceClass *service_class;
CamelPOP3Store *store = CAMEL_POP3_STORE (service);
+ gboolean success;
if (clean) {
CamelPOP3Command *pc;
- pc = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, "QUIT\r\n");
+ pc = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, cancellable, error, "QUIT\r\n");
while (camel_pop3_engine_iterate (store->engine, NULL) > 0)
;
camel_pop3_engine_command_free (store->engine, pc);
@@ -654,13 +655,13 @@ pop3_store_disconnect_sync (CamelService *service,
/* Chain up to parent's disconnect() method. */
service_class = CAMEL_SERVICE_CLASS (camel_pop3_store_parent_class);
- if (!service_class->disconnect_sync (service, clean, cancellable, error))
- return FALSE;
+
+ success = service_class->disconnect_sync (service, clean, cancellable, error);
g_object_unref (store->engine);
store->engine = NULL;
- return TRUE;
+ return success;
}
static GList *
@@ -792,7 +793,7 @@ camel_pop3_store_expunge (CamelPOP3Store *store,
CamelPOP3Command *pc;
pc = camel_pop3_engine_command_new (
- store->engine, 0, NULL, NULL, "QUIT\r\n");
+ store->engine, 0, NULL, NULL, NULL, error, "QUIT\r\n");
while (camel_pop3_engine_iterate (store->engine, NULL) > 0)
;
diff --git a/camel/providers/pop3/camel-pop3-stream.c b/camel/providers/pop3/camel-pop3-stream.c
index 7c803db..43f3500 100644
--- a/camel/providers/pop3/camel-pop3-stream.c
+++ b/camel/providers/pop3/camel-pop3-stream.c
@@ -72,6 +72,7 @@ stream_fill (CamelPOP3Stream *is,
GError **error)
{
gint left = 0;
+ GError *local_error = NULL;
if (is->source) {
left = is->end - is->ptr;
@@ -81,7 +82,12 @@ stream_fill (CamelPOP3Stream *is,
left = camel_stream_read (
is->source, (gchar *) is->end,
CAMEL_POP3_STREAM_SIZE - (is->end - is->buf),
- cancellable, error);
+ cancellable, &local_error);
+ if (local_error) {
+ dd (printf ("POP3_STREAM_FILL: Failed to read bytes: %s\n", local_error->message));
+ g_propagate_error (error, local_error);
+ }
+
if (left > 0) {
is->end += left;
is->end[0] = '\n';
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]