summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffrey Stedfast <fejj@novell.com>2008-05-12 14:04:02 +0000
committerJeffrey Stedfast <fejj@src.gnome.org>2008-05-12 14:04:02 +0000
commit19b882def5d95e0b1164df449de139c57b2c9e2e (patch)
treed8bb5d2ddc5cf19e81331350d20a1b7753cc41e7
parent17c80f764ed29fd924e6c91b678542602c88f745 (diff)
downloadevolution-data-server-19b882def5d95e0b1164df449de139c57b2c9e2e.tar.gz
Properly handle empty folders.
2008-05-12 Jeffrey Stedfast <fejj@novell.com> * camel-imap4-summary.c (camel_imap4_summary_flush_updates): Properly handle empty folders. * camel-imap4-store.c (connect_to_server): Disconnect the engine if SSL negotiations fail (there's no other way for the engine to know that failed). * camel-imap4-engine.c (camel_imap4_engine_disconnect): New convenience function. 2008-05-11 Jeffrey Stedfast <fejj@novell.com> * camel-imap4-utils.c (camel_imap4_build_folder_info_tree): New utility function. * camel-imap4-store-summary.c (camel_imap4_store_summary_get_folder_info): Use a custom imap4 routine to create a folderinfo tree. * camel-imap4-summary.c (imap4_fetch_all_add): Need to ref the CamelMessageInfo after adding to the summary because camel_folder_summary_add() does not ref. * camel-imap4-store.c: Define some symbols that might not exist in the version of camel we are linking against. (imap4_build_folder_info_tree): New function to build a tree structure of CamelFolderInfo's from an array. svn path=/trunk/; revision=8783
-rw-r--r--camel/providers/imap4/ChangeLog18
-rw-r--r--camel/providers/imap4/camel-imap4-engine.c33
-rw-r--r--camel/providers/imap4/camel-imap4-engine.h2
-rw-r--r--camel/providers/imap4/camel-imap4-store-summary.c7
-rw-r--r--camel/providers/imap4/camel-imap4-store.c80
-rw-r--r--camel/providers/imap4/camel-imap4-summary.c4
-rw-r--r--camel/providers/imap4/camel-imap4-utils.c67
-rw-r--r--camel/providers/imap4/camel-imap4-utils.h3
8 files changed, 130 insertions, 84 deletions
diff --git a/camel/providers/imap4/ChangeLog b/camel/providers/imap4/ChangeLog
index b4b8289ee..fb9a1a1d7 100644
--- a/camel/providers/imap4/ChangeLog
+++ b/camel/providers/imap4/ChangeLog
@@ -1,5 +1,23 @@
+2008-05-12 Jeffrey Stedfast <fejj@novell.com>
+
+ * camel-imap4-summary.c (camel_imap4_summary_flush_updates):
+ Properly handle empty folders.
+
+ * camel-imap4-store.c (connect_to_server): Disconnect the engine
+ if SSL negotiations fail (there's no other way for the engine to
+ know that failed).
+
+ * camel-imap4-engine.c (camel_imap4_engine_disconnect): New
+ convenience function.
+
2008-05-11 Jeffrey Stedfast <fejj@novell.com>
+ * camel-imap4-utils.c (camel_imap4_build_folder_info_tree): New
+ utility function.
+
+ * camel-imap4-store-summary.c (camel_imap4_store_summary_get_folder_info):
+ Use a custom imap4 routine to create a folderinfo tree.
+
* camel-imap4-summary.c (imap4_fetch_all_add): Need to ref the
CamelMessageInfo after adding to the summary because
camel_folder_summary_add() does not ref.
diff --git a/camel/providers/imap4/camel-imap4-engine.c b/camel/providers/imap4/camel-imap4-engine.c
index 78ce87722..b15374eff 100644
--- a/camel/providers/imap4/camel-imap4-engine.c
+++ b/camel/providers/imap4/camel-imap4-engine.c
@@ -227,14 +227,33 @@ camel_imap4_engine_take_stream (CamelIMAP4Engine *engine, CamelStream *stream, C
exception:
+ camel_imap4_engine_disconnect (engine);
+
+ return -1;
+}
+
+
+/**
+ * camel_imap4_engine_disconnect:
+ * @engine: IMAP4 engine
+ *
+ * Closes the engine's connection to the IMAP4 server and sets state
+ * to #CAMEL_IMAP4_ENGINE_DISCONNECTED.
+ **/
+void
+camel_imap4_engine_disconnect (CamelIMAP4Engine *engine)
+{
engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED;
- camel_object_unref (engine->istream);
- engine->istream = NULL;
- camel_object_unref (engine->ostream);
- engine->ostream = NULL;
+ if (engine->istream) {
+ camel_object_unref (engine->istream);
+ engine->istream = NULL;
+ }
- return -1;
+ if (engine->ostream) {
+ camel_object_unref (engine->ostream);
+ engine->ostream = NULL;
+ }
}
@@ -245,7 +264,7 @@ camel_imap4_engine_take_stream (CamelIMAP4Engine *engine, CamelStream *stream, C
*
* Forces the IMAP4 engine to query the IMAP4 server for a list of capabilities.
*
- * Returns 0 on success or -1 on fail.
+ * Returns %0 on success or %-1 on fail.
**/
int
camel_imap4_engine_capability (CamelIMAP4Engine *engine, CamelException *ex)
@@ -1540,7 +1559,7 @@ camel_imap4_engine_dequeue (CamelIMAP4Engine *engine, CamelIMAP4Command *ic)
* failure and updates the engine state to DISCONNECTED if the stream
* gets disconencted.
*
- * Returns 0 on success or -1 on fail.
+ * Returns %0 on success or %-1 on fail.
**/
int
camel_imap4_engine_next_token (CamelIMAP4Engine *engine, camel_imap4_token_t *token, CamelException *ex)
diff --git a/camel/providers/imap4/camel-imap4-engine.h b/camel/providers/imap4/camel-imap4-engine.h
index de0a811cd..bd8aafa87 100644
--- a/camel/providers/imap4/camel-imap4-engine.h
+++ b/camel/providers/imap4/camel-imap4-engine.h
@@ -200,6 +200,8 @@ CamelIMAP4Engine *camel_imap4_engine_new (CamelService *service, CamelIMAP4Recon
/* returns 0 on success or -1 on error */
int camel_imap4_engine_take_stream (CamelIMAP4Engine *engine, CamelStream *stream, CamelException *ex);
+void camel_imap4_engine_disconnect (CamelIMAP4Engine *engine);
+
int camel_imap4_engine_capability (CamelIMAP4Engine *engine, CamelException *ex);
int camel_imap4_engine_namespace (CamelIMAP4Engine *engine, CamelException *ex);
diff --git a/camel/providers/imap4/camel-imap4-store-summary.c b/camel/providers/imap4/camel-imap4-store-summary.c
index 96f10700a..92df4b694 100644
--- a/camel/providers/imap4/camel-imap4-store-summary.c
+++ b/camel/providers/imap4/camel-imap4-store-summary.c
@@ -353,14 +353,14 @@ store_info_to_folder_info (CamelStoreSummary *s, CamelStoreInfo *si)
{
CamelFolderInfo *fi;
const char *name;
-
+
fi = camel_folder_info_new ();
fi->full_name = g_strdup (camel_store_info_path (s, si));
fi->uri = g_strdup (camel_store_info_uri (s, si));
fi->flags = si->flags;
fi->unread = si->unread;
fi->total = si->total;
-
+
name = camel_store_info_name (s, si);
if (!g_ascii_strcasecmp (fi->full_name, "INBOX")) {
fi->flags |= CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_TYPE_INBOX;
@@ -372,6 +372,7 @@ store_info_to_folder_info (CamelStoreSummary *s, CamelStoreInfo *si)
return fi;
}
+
CamelFolderInfo *
camel_imap4_store_summary_get_folder_info (CamelIMAP4StoreSummary *s, const char *top, guint32 flags)
{
@@ -404,7 +405,7 @@ camel_imap4_store_summary_get_folder_info (CamelIMAP4StoreSummary *s, const char
g_ptr_array_add (folders, store_info_to_folder_info (ss, si));
}
- fi = camel_folder_info_build (folders, top, '/', TRUE);
+ fi = camel_imap4_build_folder_info_tree (folders, top);
g_ptr_array_free (folders, TRUE);
return fi;
diff --git a/camel/providers/imap4/camel-imap4-store.c b/camel/providers/imap4/camel-imap4-store.c
index 04b86037d..5ed81cc80 100644
--- a/camel/providers/imap4/camel-imap4-store.c
+++ b/camel/providers/imap4/camel-imap4-store.c
@@ -328,6 +328,7 @@ connect_to_server (CamelIMAP4Engine *engine, struct addrinfo *ai, int ssl_mode,
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Failed to connect to IMAP server %s in secure mode: %s"),
service->url->host, _("TLS negotiations failed"));
+ camel_imap4_engine_disconnect (engine);
return FALSE;
}
@@ -859,22 +860,22 @@ imap4_folder_create (CamelStore *store, const char *folder_name, const char *sub
CamelURL *url;
const char *c;
int id;
-
+
CAMEL_SERVICE_REC_LOCK (store, connect_lock);
-
+
utf7_name = imap4_folder_utf7_name (store, folder_name, '\0');
ic = camel_imap4_engine_queue (engine, NULL, "CREATE %S%s\r\n", utf7_name, subfolder_hint);
g_free (utf7_name);
-
+
while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1)
;
-
+
if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) {
camel_exception_xfer (ex, &ic->ex);
camel_imap4_command_unref (ic);
goto done;
}
-
+
switch (ic->result) {
case CAMEL_IMAP4_RESULT_OK:
url = camel_url_copy (engine->url);
@@ -1336,73 +1337,6 @@ imap4_subscription_info (CamelStore *store, CamelFolderInfo *fi)
}
static CamelFolderInfo *
-imap4_build_folder_info_tree (GPtrArray *array, const char *top)
-{
- CamelFolderInfo *cur, *fi, *root = NULL;
- const char *p;
- size_t n = 0;
- char *pname;
- int i;
-
- if (array->len == 0)
- return NULL;
-
- if (array->len == 1)
- return array->pdata[0];
-
- if (top)
- n = strlen (top);
-
- cur = root = array->pdata[0];
-
- for (i = 1; i < array->len; i++) {
- fi = (CamelFolderInfo *) array->pdata[i];
- if (top && strncmp (fi->full_name, top, n) != 0) {
- /* this folder info was not requested */
- camel_folder_info_free (fi);
- continue;
- }
-
- if ((p = strrchr (fi->full_name, '/'))) {
- pname = g_strndup (fi->full_name, p - fi->full_name);
- if (!strcmp (cur->full_name, pname)) {
- /* cur is our parent */
- fi->parent = cur;
- cur->child = fi;
- cur = fi;
- } else if (cur->parent && !strcmp (cur->parent->full_name, pname)) {
- /* cur is our sibling */
- fi->parent = cur->parent;
- cur->next = fi;
- cur = fi;
- } else {
- /* search back for our parent */
- while (cur->parent) {
- if (!strcmp (cur->parent->full_name, pname))
- break;
- cur = cur->parent;
- }
-
- /* cur should now be our sibling */
- fi->parent = cur->parent;
- cur->next = fi;
- cur = fi;
- }
- g_free (pname);
- } else {
- /* traverse back to most recent top-level fi */
- while (cur->parent)
- cur = cur->parent;
-
- cur->next = fi;
- cur = fi;
- }
- }
-
- return root;
-}
-
-static CamelFolderInfo *
imap4_build_folder_info (CamelStore *store, const char *top, guint32 flags, GPtrArray *array)
{
CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine;
@@ -1478,7 +1412,7 @@ imap4_build_folder_info (CamelStore *store, const char *top, guint32 flags, GPtr
g_free (list);
}
- fi = imap4_build_folder_info_tree (array, top);
+ fi = camel_imap4_build_folder_info_tree (array, top);
camel_url_free (url);
diff --git a/camel/providers/imap4/camel-imap4-summary.c b/camel/providers/imap4/camel-imap4-summary.c
index cf052a571..e3bd0d89f 100644
--- a/camel/providers/imap4/camel-imap4-summary.c
+++ b/camel/providers/imap4/camel-imap4-summary.c
@@ -1304,6 +1304,7 @@ imap4_summary_fetch_flags (CamelFolderSummary *summary)
engine = ((CamelIMAP4Store *) folder->parent_store)->engine;
scount = camel_folder_summary_count (summary);
+ g_assert (scount > 0);
info[0] = camel_folder_summary_index (summary, 0);
if (scount > 1)
@@ -1581,7 +1582,8 @@ camel_imap4_summary_flush_updates (CamelFolderSummary *summary, CamelException *
summary->flags ^= CAMEL_IMAP4_SUMMARY_HAVE_MLIST;
engine = ((CamelIMAP4Store *) summary->folder->parent_store)->engine;
- scount = camel_folder_summary_count (summary);
+ if ((scount = camel_folder_summary_count (summary)) == 0)
+ imap4_summary->update_flags = FALSE;
if (imap4_summary->uidvalidity_changed) {
/* need to refetch everything */
diff --git a/camel/providers/imap4/camel-imap4-utils.c b/camel/providers/imap4/camel-imap4-utils.c
index 2f81d0904..a479b3e60 100644
--- a/camel/providers/imap4/camel-imap4-utils.c
+++ b/camel/providers/imap4/camel-imap4-utils.c
@@ -44,6 +44,73 @@
#define d(x)
+CamelFolderInfo *
+camel_imap4_build_folder_info_tree (GPtrArray *array, const char *top)
+{
+ CamelFolderInfo *cur, *fi, *root = NULL;
+ const char *p;
+ size_t n = 0;
+ char *pname;
+ int i;
+
+ if (array->len == 0)
+ return NULL;
+
+ if (array->len == 1)
+ return array->pdata[0];
+
+ if (top)
+ n = strlen (top);
+
+ cur = root = array->pdata[0];
+
+ for (i = 1; i < array->len; i++) {
+ fi = (CamelFolderInfo *) array->pdata[i];
+ if (top && strncmp (fi->full_name, top, n) != 0) {
+ /* this folder info was not requested */
+ camel_folder_info_free (fi);
+ continue;
+ }
+
+ if ((p = strrchr (fi->full_name, '/'))) {
+ pname = g_strndup (fi->full_name, p - fi->full_name);
+ if (!strcmp (cur->full_name, pname)) {
+ /* cur is our parent */
+ fi->parent = cur;
+ cur->child = fi;
+ cur = fi;
+ } else if (cur->parent && !strcmp (cur->parent->full_name, pname)) {
+ /* cur is our sibling */
+ fi->parent = cur->parent;
+ cur->next = fi;
+ cur = fi;
+ } else {
+ /* search back for our parent */
+ while (cur->parent) {
+ if (!strcmp (cur->parent->full_name, pname))
+ break;
+ cur = cur->parent;
+ }
+
+ /* cur should now be our sibling */
+ fi->parent = cur->parent;
+ cur->next = fi;
+ cur = fi;
+ }
+ g_free (pname);
+ } else {
+ /* traverse back to most recent top-level fi */
+ while (cur->parent)
+ cur = cur->parent;
+
+ cur->next = fi;
+ cur = fi;
+ }
+ }
+
+ return root;
+}
+
void
camel_imap4_flags_diff (flags_diff_t *diff, guint32 old, guint32 new)
{
diff --git a/camel/providers/imap4/camel-imap4-utils.h b/camel/providers/imap4/camel-imap4-utils.h
index 00eb88b10..d67698809 100644
--- a/camel/providers/imap4/camel-imap4-utils.h
+++ b/camel/providers/imap4/camel-imap4-utils.h
@@ -40,6 +40,7 @@ guint32 camel_imap4_flags_merge (flags_diff_t *diff, guint32 flags);
guint32 camel_imap4_merge_flags (guint32 original, guint32 local, guint32 server);
+struct _CamelFolderInfo;
struct _CamelIMAP4Engine;
struct _CamelIMAP4Command;
struct _CamelFolderSummary;
@@ -48,6 +49,8 @@ struct _CamelIMAP4StoreSummary;
struct _CamelIMAP4NamespaceList;
struct _CamelIMAP4Namespace;
+struct _CamelFolderInfo *camel_imap4_build_folder_info_tree (GPtrArray *array, const char *top);
+
void camel_imap4_namespace_clear (struct _CamelIMAP4Namespace **ns);
struct _CamelIMAP4NamespaceList *camel_imap4_namespace_list_copy (const struct _CamelIMAP4NamespaceList *nsl);
void camel_imap4_namespace_list_free (struct _CamelIMAP4NamespaceList *nsl);