aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers/imap
diff options
context:
space:
mode:
Diffstat (limited to 'camel/providers/imap')
-rw-r--r--camel/providers/imap/Makefile.am3
-rw-r--r--camel/providers/imap/camel-imap-command.c49
-rw-r--r--camel/providers/imap/camel-imap-folder.c386
-rw-r--r--camel/providers/imap/camel-imap-store.h1
-rw-r--r--camel/providers/imap/camel-imap-utils.c357
5 files changed, 203 insertions, 593 deletions
diff --git a/camel/providers/imap/Makefile.am b/camel/providers/imap/Makefile.am
index dbee888f39..bf183aa3ce 100644
--- a/camel/providers/imap/Makefile.am
+++ b/camel/providers/imap/Makefile.am
@@ -9,6 +9,7 @@ INCLUDES = -I.. \
-I$(srcdir)/.. \
-I$(top_srcdir)/camel \
-I$(top_srcdir)/intl \
+ -I$(top_srcdir)/libibex \
-I$(top_srcdir)/e-util \
-I$(top_srcdir) \
-I$(includedir) \
@@ -39,7 +40,7 @@ libcamelimapinclude_HEADERS = \
camel-imap-utils.h \
camel-imap-wrapper.h
-libcamelimap_la_LDFLAGS = -avoid-version -module
+libcamelimap_la_LDFLAGS = -version-info 0:0:0
noinst_HEADERS = \
camel-imap-private.h
diff --git a/camel/providers/imap/camel-imap-command.c b/camel/providers/imap/camel-imap-command.c
index 6a2382b3c8..f6fb0dde8e 100644
--- a/camel/providers/imap/camel-imap-command.c
+++ b/camel/providers/imap/camel-imap-command.c
@@ -267,25 +267,18 @@ camel_imap_command_response (CamelImapStore *store, char **response,
switch (*respbuf) {
case '*':
- if (!g_strncasecmp (respbuf, "* BYE", 5)) {
+ type = CAMEL_IMAP_RESPONSE_UNTAGGED;
+
+ /* Read the rest of the response if it is multi-line. */
+ respbuf = imap_read_untagged (store, respbuf, ex);
+ if (!respbuf)
+ type = CAMEL_IMAP_RESPONSE_ERROR;
+ else if (!g_strncasecmp (respbuf, "* BYE", 5)) {
/* Connection was lost, no more data to fetch */
- camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
- camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("Server unexpectedly disconnected: %s"),
- _("Unknown error")); /* g_strerror (104)); FIXME after 1.0 is released */
store->connected = FALSE;
g_free (respbuf);
- respbuf = NULL;
type = CAMEL_IMAP_RESPONSE_ERROR;
- break;
}
-
- /* Read the rest of the response. */
- type = CAMEL_IMAP_RESPONSE_UNTAGGED;
- respbuf = imap_read_untagged (store, respbuf, ex);
- if (!respbuf)
- type = CAMEL_IMAP_RESPONSE_ERROR;
-
break;
case '+':
type = CAMEL_IMAP_RESPONSE_CONTINUATION;
@@ -299,7 +292,6 @@ camel_imap_command_response (CamelImapStore *store, char **response,
if (type == CAMEL_IMAP_RESPONSE_ERROR ||
type == CAMEL_IMAP_RESPONSE_TAGGED)
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
-
return type;
}
@@ -406,16 +398,17 @@ imap_read_untagged (CamelImapStore *store, char *line, CamelException *ex)
str->str + 1, length);
if (nread == -1) {
if (errno == EINTR)
- camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled"));
+ camel_exception_set(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled"));
else
- camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, g_strerror (errno));
+ camel_exception_set(ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, strerror(errno));
camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
goto lose;
}
if (nread < length) {
- camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("Server response ended too soon."));
- camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
+ _("Server response ended too soon."));
+ camel_service_disconnect (CAMEL_SERVICE (store),
+ FALSE, NULL);
goto lose;
}
str->str[length + 1] = '\0';
@@ -588,14 +581,12 @@ camel_imap_response_extract (CamelImapStore *store,
int len = strlen (type), i;
char *resp;
- len = strlen (type);
-
for (i = 0; i < response->untagged->len; i++) {
resp = response->untagged->pdata[i];
/* Skip "* ", and initial sequence number, if present */
strtoul (resp + 2, &resp, 10);
if (*resp == ' ')
- resp = (char *) imap_next_word (resp);
+ resp = imap_next_word (resp);
if (!g_strncasecmp (resp, type, len))
break;
@@ -702,7 +693,7 @@ imap_command_strdup_vprintf (CamelImapStore *store, const char *fmt,
len += arglen * 2;
start = p + 1;
break;
-
+
case '%':
start = p;
break;
@@ -743,14 +734,8 @@ imap_command_strdup_vprintf (CamelImapStore *store, const char *fmt,
case 'S':
case 'F':
string = args->pdata[i++];
- if (*p == 'F') {
- char *mailbox;
-
- mailbox = imap_namespace_concat (store, string);
- string = imap_mailbox_encode (mailbox, strlen (mailbox));
- g_free (mailbox);
- }
-
+ if (*p == 'F')
+ string = imap_namespace_concat (store, string);
if (store->capabilities & IMAP_CAPABILITY_LITERALPLUS) {
op += sprintf (op, "{%d+}\r\n%s",
strlen (string), string);
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index 811533d25a..45dad9f6b0 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -64,11 +64,6 @@
#include "camel-stream.h"
#include "string-utils.h"
-
-/* set to -1 for infinite size */
-#define UID_SET_LIMIT (4096)
-
-
#define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(o)))
static CamelDiscoFolderClass *disco_folder_class = NULL;
@@ -231,8 +226,6 @@ camel_imap_folder_new (CamelStore *parent, const char *folder_name,
!g_strcasecmp (folder_name, "INBOX"))
folder->folder_flags |= CAMEL_FOLDER_FILTER_RECENT;
- imap_folder->search = camel_imap_search_new(folder_dir);
-
return folder;
}
@@ -453,8 +446,7 @@ imap_rescan (CamelFolder *folder, int exists, CamelException *ex)
CamelImapMessageInfo *iinfo;
GArray *removed;
gboolean ok;
- CamelFolderChangeInfo *changes = NULL;
-
+
CAMEL_IMAP_STORE_ASSERT_LOCKED (store, command_lock);
imap_folder->need_rescan = FALSE;
@@ -544,20 +536,15 @@ imap_rescan (CamelFolder *folder, int exists, CamelException *ex)
info->flags = (info->flags | server_set) & ~server_cleared;
iinfo->server_flags = new[i].flags;
-
- if (changes == NULL)
- changes = camel_folder_change_info_new();
- camel_folder_change_info_change_uid(changes, new[i].uid);
+
+ camel_object_trigger_event (CAMEL_OBJECT (folder),
+ "message_changed",
+ new[i].uid);
}
camel_folder_summary_info_free (folder->summary, info);
g_free (new[i].uid);
}
-
- if (changes) {
- camel_object_trigger_event(CAMEL_OBJECT (folder), "folder_changed", changes);
- camel_folder_change_info_free(changes);
- }
seq = i + 1;
@@ -578,14 +565,11 @@ imap_rescan (CamelFolder *folder, int exists, CamelException *ex)
g_array_free (removed, TRUE);
}
-/* the max number of chars that an unsigned 32-bit int can be is 10 chars plus 1 for a possible : */
-#define UID_SET_FULL(setlen, maxlen) (maxlen > 0 ? setlen + 11 >= maxlen : FALSE)
-
/* Find all messages in @folder with flags matching @flags and @mask.
* If no messages match, returns %NULL. Otherwise, returns an array of
* CamelMessageInfo and sets *@set to a message set corresponding the
- * UIDs of the matched messages (up to @UID_SET_LIMIT bytes). The
- * caller must free the infos, the array, and the set string.
+ * UIDs of the matched messages. The caller must free the infos, the
+ * array, and the set string.
*/
static GPtrArray *
get_matching (CamelFolder *folder, guint32 flags, guint32 mask, char **set)
@@ -594,12 +578,12 @@ get_matching (CamelFolder *folder, guint32 flags, guint32 mask, char **set)
CamelMessageInfo *info;
int i, max, range;
GString *gset;
-
+
matches = g_ptr_array_new ();
gset = g_string_new ("");
max = camel_folder_summary_count (folder->summary);
range = -1;
- for (i = 0; i < max && !UID_SET_FULL (gset->len, UID_SET_LIMIT); i++) {
+ for (i = 0; i < max; i++) {
info = camel_folder_summary_index (folder->summary, i);
if (!info)
continue;
@@ -614,7 +598,7 @@ get_matching (CamelFolder *folder, guint32 flags, guint32 mask, char **set)
}
continue;
}
-
+
g_ptr_array_add (matches, info);
if (range != -1)
continue;
@@ -623,12 +607,11 @@ get_matching (CamelFolder *folder, guint32 flags, guint32 mask, char **set)
g_string_append_c (gset, ',');
g_string_sprintfa (gset, "%s", camel_message_info_uid (info));
}
-
if (range != -1 && range != max - 1) {
info = matches->pdata[matches->len - 1];
g_string_sprintfa (gset, ":%s", camel_message_info_uid (info));
}
-
+
if (matches->len) {
*set = gset->str;
g_string_free (gset, FALSE);
@@ -674,19 +657,14 @@ imap_sync_online (CamelFolder *folder, CamelException *ex)
}
/* Note: Cyrus is broken and will not accept an
- empty-set of flags so... if this is true then we
- want to unset the previously set flags.*/
+ empty-set of flags so... if this is true then we
+ want to unset the previously set flags.*/
unset = !(info->flags & CAMEL_IMAP_SERVER_FLAGS);
/* FIXME: since we don't know the previously set
- flags, if unset is TRUE then just unset all the flags? */
+ flags, if unset is TRUE then just unset all the flags? */
flaglist = imap_create_flag_list (unset ? CAMEL_IMAP_SERVER_FLAGS : info->flags);
- /* Note: get_matching() uses UID_SET_LIMIT to limit
- the size of the uid-set string. We don't have to
- loop here to flush all the matching uids because
- they will be scooped up later by our parent loop (I
- think?). -- Jeff */
matches = get_matching (folder, info->flags & (CAMEL_IMAP_SERVER_FLAGS | CAMEL_MESSAGE_FOLDER_FLAGGED),
CAMEL_IMAP_SERVER_FLAGS | CAMEL_MESSAGE_FOLDER_FLAGGED, &set);
camel_folder_summary_info_free (folder->summary, info);
@@ -751,34 +729,28 @@ imap_expunge_uids_online (CamelFolder *folder, GPtrArray *uids, CamelException *
{
CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
CamelImapResponse *response;
- int uid = 0;
char *set;
+ set = imap_uid_array_to_set (folder->summary, uids);
CAMEL_IMAP_STORE_LOCK (store, command_lock);
-
- while (uid < uids->len) {
- set = imap_uid_array_to_set (folder->summary, uids, uid, UID_SET_LIMIT, &uid);
- response = camel_imap_command (store, folder, ex,
- "UID STORE %s +FLAGS.SILENT \\Deleted",
- set);
- if (response)
- camel_imap_response_free (store, response);
- if (camel_exception_is_set (ex)) {
- CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
- g_free (set);
- return;
- }
-
- if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) {
- response = camel_imap_command (store, folder, ex,
- "UID EXPUNGE %s", set);
- } else
- response = camel_imap_command (store, folder, ex, "EXPUNGE");
-
- if (response)
- camel_imap_response_free (store, response);
+ response = camel_imap_command (store, folder, ex,
+ "UID STORE %s +FLAGS.SILENT \\Deleted",
+ set);
+ if (response)
+ camel_imap_response_free (store, response);
+ if (camel_exception_is_set (ex)) {
+ CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
+ g_free (set);
+ return;
}
+ if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) {
+ response = camel_imap_command (store, folder, ex,
+ "UID EXPUNGE %s", set);
+ } else
+ response = camel_imap_command (store, folder, ex, "EXPUNGE");
+ if (response)
+ camel_imap_response_free (store, response);
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
}
@@ -802,21 +774,20 @@ static void
imap_expunge_uids_resyncing (CamelFolder *folder, GPtrArray *uids, CamelException *ex)
{
CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
- GPtrArray *keep_uids, *mark_uids;
CamelImapResponse *response;
- char *result;
+ char *result, *keep_uidset, *mark_uidset;
if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) {
imap_expunge_uids_online (folder, uids, ex);
return;
}
-
+
/* If we don't have UID EXPUNGE we need to avoid expunging any
* of the wrong messages. So we search for deleted messages,
* and any that aren't in our to-expunge list get temporarily
* marked un-deleted.
*/
-
+
CAMEL_IMAP_STORE_LOCK (store, command_lock);
response = camel_imap_command (store, folder, ex, "UID SEARCH DELETED");
if (!response) {
@@ -828,125 +799,100 @@ imap_expunge_uids_resyncing (CamelFolder *folder, GPtrArray *uids, CamelExceptio
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
return;
}
-
+
+ keep_uidset = mark_uidset = NULL;
if (result[8] == ' ') {
+ GPtrArray *keep_uids, *mark_uids;
char *uid, *lasts = NULL;
unsigned long euid, kuid;
int ei, ki;
-
+
keep_uids = g_ptr_array_new ();
mark_uids = g_ptr_array_new ();
-
+
/* Parse SEARCH response */
for (uid = strtok_r (result + 9, " ", &lasts); uid; uid = strtok_r (NULL, " ", &lasts))
g_ptr_array_add (keep_uids, uid);
qsort (keep_uids->pdata, keep_uids->len,
sizeof (void *), uid_compar);
-
+
/* Fill in "mark_uids", empty out "keep_uids" as needed */
for (ei = ki = 0; ei < uids->len; ei++) {
euid = strtoul (uids->pdata[ei], NULL, 10);
-
+
for (kuid = 0; ki < keep_uids->len; ki++) {
kuid = strtoul (keep_uids->pdata[ki], NULL, 10);
-
+
if (kuid >= euid)
break;
}
-
+
if (euid == kuid)
g_ptr_array_remove_index (keep_uids, ki);
else
g_ptr_array_add (mark_uids, uids->pdata[ei]);
}
+
+ if (keep_uids->len)
+ keep_uidset = imap_uid_array_to_set (folder->summary, keep_uids);
+ g_ptr_array_free (keep_uids, TRUE);
+
+ if (mark_uids->len)
+ mark_uidset = imap_uid_array_to_set (folder->summary, mark_uids);
+ g_ptr_array_free (mark_uids, TRUE);
} else {
/* Empty SEARCH result, meaning nothing is marked deleted
* on server.
*/
-
- keep_uids = NULL;
- mark_uids = NULL;
+ mark_uidset = imap_uid_array_to_set (folder->summary, uids);
}
-
g_free (result);
-
+
/* Unmark messages to be kept */
- if (keep_uids) {
- char *uidset;
- int uid = 0;
-
- while (uid < keep_uids->len) {
- uidset = imap_uid_array_to_set (folder->summary, keep_uids, uid, UID_SET_LIMIT, &uid);
-
- response = camel_imap_command (store, folder, ex,
- "UID STORE %s -FLAGS.SILENT \\Deleted",
- uidset);
-
- g_free (uidset);
-
- if (!response) {
- g_ptr_array_free (keep_uids, TRUE);
- g_ptr_array_free (mark_uids, TRUE);
- CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
- return;
- }
- camel_imap_response_free (store, response);
+ if (keep_uidset) {
+ response = camel_imap_command (store, folder, ex,
+ "UID STORE %s -FLAGS.SILENT \\Deleted",
+ keep_uidset);
+ if (!response) {
+ g_free (keep_uidset);
+ g_free (mark_uidset);
+ CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
+ return;
}
+ camel_imap_response_free (store, response);
}
-
+
/* Mark any messages that still need to be marked */
- if (mark_uids) {
- char *uidset;
- int uid = 0;
-
- while (uid < mark_uids->len) {
- uidset = imap_uid_array_to_set (folder->summary, mark_uids, uid, UID_SET_LIMIT, &uid);
-
- response = camel_imap_command (store, folder, ex,
- "UID STORE %s +FLAGS.SILENT \\Deleted",
- uidset);
-
- g_free (uidset);
-
- if (!response) {
- g_ptr_array_free (keep_uids, TRUE);
- g_ptr_array_free (mark_uids, TRUE);
- CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
- return;
- }
- camel_imap_response_free (store, response);
+ if (mark_uidset) {
+ response = camel_imap_command (store, folder, ex,
+ "UID STORE %s +FLAGS.SILENT \\Deleted",
+ mark_uidset);
+ g_free (mark_uidset);
+ if (!response) {
+ g_free (keep_uidset);
+ CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
+ return;
}
-
- g_ptr_array_free (mark_uids, TRUE);
+ camel_imap_response_free (store, response);
}
-
+
/* Do the actual expunging */
response = camel_imap_command (store, folder, ex, "EXPUNGE");
if (response)
camel_imap_response_free (store, response);
-
+
/* And fix the remaining messages if we mangled them */
- if (keep_uids) {
- char *uidset;
- int uid = 0;
-
- while (uid < keep_uids->len) {
- uidset = imap_uid_array_to_set (folder->summary, keep_uids, uid, UID_SET_LIMIT, &uid);
-
- /* Don't pass ex if it's already been set */
- response = camel_imap_command (store, folder,
- camel_exception_is_set (ex) ? NULL : ex,
- "UID STORE %s +FLAGS.SILENT \\Deleted",
- uidset);
-
- g_free (uidset);
- if (response)
- camel_imap_response_free (store, response);
- }
-
- g_ptr_array_free (keep_uids, TRUE);
+ if (keep_uidset) {
+ /* Don't pass ex if it's already been set */
+ response = camel_imap_command (store, folder,
+ camel_exception_is_set (ex) ? NULL : ex,
+ "UID STORE %s +FLAGS.SILENT \\Deleted",
+ keep_uidset);
+ g_free (keep_uidset);
+ if (response)
+ camel_imap_response_free (store, response);
}
-
+
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
}
@@ -1240,22 +1186,16 @@ do_copy (CamelFolder *source, GPtrArray *uids,
{
CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store);
CamelImapResponse *response;
- char *uidset;
- int uid = 0;
-
- while (uid < uids->len && !camel_exception_is_set (ex)) {
- uidset = imap_uid_array_to_set (source->summary, uids, uid, UID_SET_LIMIT, &uid);
-
- response = camel_imap_command (store, source, ex, "UID COPY %s %F",
- uidset, destination->full_name);
-
- g_free (uidset);
-
- if (response && (store->capabilities & IMAP_CAPABILITY_UIDPLUS))
- handle_copyuid (response, source, destination);
-
- camel_imap_response_free (store, response);
- }
+ char *set;
+
+ set = imap_uid_array_to_set (source->summary, uids);
+ response = camel_imap_command (store, source, ex, "UID COPY %s %F",
+ set, destination->full_name);
+ if (response && (store->capabilities & IMAP_CAPABILITY_UIDPLUS))
+ handle_copyuid (response, source, destination);
+
+ camel_imap_response_free (store, response);
+ g_free (set);
}
static void
@@ -1374,6 +1314,9 @@ imap_search_by_expression (CamelFolder *folder, const char *expression, CamelExc
command channel too */
CAMEL_IMAP_FOLDER_LOCK(folder, search_lock);
+ if (!imap_folder->search)
+ imap_folder->search = camel_imap_search_new ();
+
camel_folder_search_set_folder (imap_folder->search, folder);
summary = camel_folder_get_summary(folder);
camel_folder_search_set_summary(imap_folder->search, summary);
@@ -1410,6 +1353,9 @@ imap_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids
CAMEL_IMAP_FOLDER_LOCK(folder, search_lock);
+ if (imap_folder->search == NULL)
+ imap_folder->search = camel_imap_search_new();
+
camel_folder_search_set_folder(imap_folder->search, folder);
camel_folder_search_set_summary(imap_folder->search, summary);
@@ -1465,7 +1411,6 @@ get_content (CamelImapFolder *imap_folder, const char *uid,
body_mp = camel_multipart_new ();
camel_data_wrapper_set_mime_type_field (
CAMEL_DATA_WRAPPER (body_mp), ci->type);
-
camel_multipart_set_boundary (body_mp, NULL);
speclen = strlen (part_spec);
@@ -1505,7 +1450,7 @@ get_content (CamelImapFolder *imap_folder, const char *uid,
camel_object_unref (CAMEL_OBJECT (content));
camel_multipart_add_part (body_mp, part);
camel_object_unref (CAMEL_OBJECT (part));
-
+
ci = ci->next;
}
g_free (child_spec);
@@ -1731,7 +1676,7 @@ add_message_from_data (CamelFolder *folder, GPtrArray *messages,
if (seq - first >= messages->len)
g_ptr_array_set_size (messages, seq - first + 1);
-
+
msg = camel_mime_message_new ();
if (camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), stream) == -1) {
camel_object_unref (CAMEL_OBJECT (msg));
@@ -1813,13 +1758,13 @@ imap_update_summary (CamelFolder *folder, int exists,
g_free (resp);
if (!data)
continue;
-
+
seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE"));
if (seq < first) {
g_datalist_clear (&data);
continue;
}
-
+
if (g_datalist_get_data (&data, "FLAGS"))
got += IMAP_PRETEND_SIZEOF_FLAGS;
if (g_datalist_get_data (&data, "RFC822.SIZE"))
@@ -1827,22 +1772,22 @@ imap_update_summary (CamelFolder *folder, int exists,
stream = g_datalist_get_data (&data, "BODY_PART_STREAM");
if (stream) {
got += IMAP_PRETEND_SIZEOF_HEADERS;
-
+
/* Use the stream now so we don't tie up many
* many fds if we're fetching many many messages.
*/
add_message_from_data (folder, messages, first, data);
g_datalist_set_data (&data, "BODY_PART_STREAM", NULL);
}
-
+
camel_operation_progress (NULL, got * 100 / size);
g_ptr_array_add (fetch_data, data);
}
camel_operation_end (NULL);
-
+
if (type == CAMEL_IMAP_RESPONSE_ERROR)
goto lose;
-
+
/* Figure out which headers we still need to fetch. */
needheaders = g_ptr_array_new ();
size = got = 0;
@@ -1850,67 +1795,55 @@ imap_update_summary (CamelFolder *folder, int exists,
data = fetch_data->pdata[i];
if (g_datalist_get_data (&data, "BODY_PART_LEN"))
continue;
-
+
uid = g_datalist_get_data (&data, "UID");
if (uid) {
g_ptr_array_add (needheaders, uid);
size += IMAP_PRETEND_SIZEOF_HEADERS;
}
}
-
+
/* And fetch them */
if (needheaders->len) {
- char *uidset;
- int uid = 0;
-
- qsort (needheaders->pdata, needheaders->len,
- sizeof (void *), uid_compar);
-
+ char *set;
+
+ /* FIXME: sort needheaders */
+ set = imap_uid_array_to_set (folder->summary, needheaders);
+ g_ptr_array_free (needheaders, TRUE);
+ if (!camel_imap_command_start (store, folder, ex,
+ "UID FETCH %s BODY.PEEK[%s]",
+ set, header_spec)) {
+ g_free (set);
+ goto lose;
+ }
+ g_free (set);
+
camel_operation_start (NULL, _("Fetching summary information for new messages"));
-
- while (uid < needheaders->len) {
- uidset = imap_uid_array_to_set (folder->summary, needheaders, uid, UID_SET_LIMIT, &uid);
- if (!camel_imap_command_start (store, folder, ex,
- "UID FETCH %s BODY.PEEK[%s]",
- uidset, header_spec)) {
- g_ptr_array_free (needheaders, TRUE);
- camel_operation_end (NULL);
- g_free (uidset);
- goto lose;
- }
- g_free (uidset);
-
- while ((type = camel_imap_command_response (store, &resp, ex))
- == CAMEL_IMAP_RESPONSE_UNTAGGED) {
- data = parse_fetch_response (imap_folder, resp);
- g_free (resp);
- if (!data)
- continue;
-
- stream = g_datalist_get_data (&data, "BODY_PART_STREAM");
- if (stream) {
- add_message_from_data (folder, messages, first, data);
- got += IMAP_PRETEND_SIZEOF_HEADERS;
- camel_operation_progress (NULL, got * 100 / size);
- }
- g_datalist_clear (&data);
- }
-
- if (type == CAMEL_IMAP_RESPONSE_ERROR) {
- g_ptr_array_free (needheaders, TRUE);
- camel_operation_end (NULL);
- goto lose;
+ while ((type = camel_imap_command_response (store, &resp, ex))
+ == CAMEL_IMAP_RESPONSE_UNTAGGED) {
+ data = parse_fetch_response (imap_folder, resp);
+ g_free (resp);
+ if (!data)
+ continue;
+
+ stream = g_datalist_get_data (&data, "BODY_PART_STREAM");
+ if (stream) {
+ add_message_from_data (folder, messages, first, data);
+ got += IMAP_PRETEND_SIZEOF_HEADERS;
+ camel_operation_progress (NULL, got * 100 / size);
}
+ g_datalist_clear (&data);
}
-
- g_ptr_array_free (needheaders, TRUE);
camel_operation_end (NULL);
+
+ if (type == CAMEL_IMAP_RESPONSE_ERROR)
+ goto lose;
}
-
+
/* Now finish up summary entries (fix UIDs, set flags and size) */
for (i = 0; i < fetch_data->len; i++) {
data = fetch_data->pdata[i];
-
+
seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE"));
if (seq >= first + messages->len) {
g_datalist_clear (&data);
@@ -1939,11 +1872,7 @@ imap_update_summary (CamelFolder *folder, int exists,
break;
}
- if (pmi == NULL) {
- /* Server response is *really* fucked up,
- I guess we just pretend it never happened? */
- continue;
- }
+ g_assert (pmi);
mi = camel_message_info_new ();
camel_message_info_dup_to (pmi, mi);
@@ -1963,11 +1892,11 @@ imap_update_summary (CamelFolder *folder, int exists,
size = GPOINTER_TO_INT (g_datalist_get_data (&data, "RFC822.SIZE"));
if (size)
mi->size = size;
-
+
g_datalist_clear (&data);
}
g_ptr_array_free (fetch_data, TRUE);
-
+
/* And add the entries to the summary, etc. */
for (i = 0; i < messages->len; i++) {
mi = messages->pdata[i];
@@ -1977,30 +1906,13 @@ imap_update_summary (CamelFolder *folder, int exists,
}
camel_folder_summary_add (folder->summary, mi);
camel_folder_change_info_add_uid (changes, camel_message_info_uid (mi));
-
+
if ((mi->flags & CAMEL_IMAP_MESSAGE_RECENT))
camel_folder_change_info_recent_uid(changes, camel_message_info_uid (mi));
}
g_ptr_array_free (messages, TRUE);
-
- /* Kludge around Microsoft Exchange 5.5 IMAP - See bug #5348 for details */
- if (camel_folder_summary_count (folder->summary) != exists) {
- CamelImapStore *imap_store = (CamelImapStore *) folder->parent_store;
- CamelImapResponse *response;
-
- /* forget the currently selected folder */
- if (imap_store->current_folder) {
- camel_object_unref (CAMEL_OBJECT (imap_store->current_folder));
- imap_store->current_folder = NULL;
- }
-
- /* now re-select it and process the EXISTS response */
- response = camel_imap_command (imap_store, folder, ex, NULL);
- camel_imap_response_free (imap_store, response);
- }
-
return;
-
+
lose:
if (fetch_data) {
for (i = 0; i < fetch_data->len; i++) {
@@ -2109,7 +2021,7 @@ camel_imap_folder_fetch_data (CamelImapFolder *imap_folder, const char *uid,
CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
return stream;
- }
+ }
if (camel_disco_store_status (CAMEL_DISCO_STORE (store)) == CAMEL_DISCO_STORE_OFFLINE) {
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
diff --git a/camel/providers/imap/camel-imap-store.h b/camel/providers/imap/camel-imap-store.h
index 9a6c6655ad..43c9b8e1f0 100644
--- a/camel/providers/imap/camel-imap-store.h
+++ b/camel/providers/imap/camel-imap-store.h
@@ -71,7 +71,6 @@ typedef enum {
#define IMAP_CAPABILITY_UIDPLUS (1 << 4)
#define IMAP_CAPABILITY_LITERALPLUS (1 << 5)
#define IMAP_CAPABILITY_useful_lsub (1 << 6)
-#define IMAP_CAPABILITY_utf8_search (1 << 7)
#define IMAP_PARAM_OVERRIDE_NAMESPACE (1 << 0)
#define IMAP_PARAM_CHECK_ALL (1 << 1)
diff --git a/camel/providers/imap/camel-imap-utils.c b/camel/providers/imap/camel-imap-utils.c
index 91d2efb702..d5466bf9ac 100644
--- a/camel/providers/imap/camel-imap-utils.c
+++ b/camel/providers/imap/camel-imap-utils.c
@@ -24,7 +24,6 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
-#include <iconv.h>
#include "camel-imap-utils.h"
#include "camel-imap-summary.h"
@@ -33,13 +32,13 @@
#define d(x) x
-const char *
+char *
imap_next_word (const char *buf)
{
- const char *word;
+ char *word;
/* skip over current word */
- for (word = buf; *word && *word != ' '; word++);
+ for (word = (char *)buf; *word && *word != ' '; word++);
/* skip over white space */
for ( ; *word && *word == ' '; word++);
@@ -63,8 +62,8 @@ imap_next_word (const char *buf)
gboolean
imap_parse_list_response (CamelImapStore *store, const char *buf, int *flags, char *sep, char **folder)
{
- const char *word;
- size_t len;
+ char *word;
+ int len;
if (*buf != '*')
return FALSE;
@@ -117,34 +116,22 @@ imap_parse_list_response (CamelImapStore *store, const char *buf, int *flags, ch
return FALSE;
if (folder) {
- char *astring, *mailbox;
- size_t nlen;
+ char *real_name;
+ int n_len;
/* get the folder name */
word = imap_next_word (word);
- astring = imap_parse_astring ((char **) &word, &len);
- if (!astring)
- return FALSE;
-
- mailbox = imap_mailbox_decode (astring, strlen (astring));
- g_free (astring);
- if (!mailbox)
- return FALSE;
-
- nlen = strlen (store->namespace);
-
- if (!strncmp (mailbox, store->namespace, nlen)) {
- /* strip off the namespace */
- if (nlen > 0)
- memmove (mailbox, mailbox + nlen, (len - nlen) + 1);
- *folder = mailbox;
- } else if (!g_strcasecmp (mailbox, "INBOX")) {
- *folder = mailbox;
+ real_name = imap_parse_astring (&word, &len);
+ n_len = strlen (store->namespace);
+ if (!strncmp (real_name, store->namespace, n_len))
+ *folder = g_strdup (real_name + n_len);
+ else if (!g_strcasecmp (real_name, "INBOX")) {
+ *folder = g_strdup (real_name);
} else {
- g_warning ("IMAP folder name \"%s\" does not begin with \"%s\"", mailbox, store->namespace);
- *folder = mailbox;
+ g_warning ("IMAP folder name \"%s\" does not begin with \"%s\"", real_name, store->namespace);
+ *folder = g_strdup (real_name);
}
-
+ g_free (real_name);
return *folder != NULL;
}
@@ -286,7 +273,7 @@ static char imap_atom_specials[128] = {
/**
* imap_parse_string_generic:
* @str_p: a pointer to a string
- * @len: a pointer to a size_t to return the length in
+ * @len: a pointer to an int to return the length in
* @type: type of string (#IMAP_STRING, #IMAP_ASTRING, or #IMAP_NSTRING)
* to parse.
*
@@ -305,7 +292,7 @@ static char imap_atom_specials[128] = {
* latter, it will point to the character after the NIL.)
**/
char *
-imap_parse_string_generic (char **str_p, size_t *len, int type)
+imap_parse_string_generic (char **str_p, int *len, int type)
{
char *str = *str_p;
char *out;
@@ -314,7 +301,7 @@ imap_parse_string_generic (char **str_p, size_t *len, int type)
return NULL;
else if (*str == '"') {
char *p;
- size_t size;
+ int size;
str++;
size = strcspn (str, "\"") + 1;
@@ -486,7 +473,7 @@ imap_parse_body (char **body_p, CamelFolder *folder,
char *body = *body_p;
CamelMessageContentInfo *child;
CamelContentType *type;
- size_t len;
+ int len;
if (!body || *body++ != '(') {
*body_p = NULL;
@@ -543,7 +530,7 @@ imap_parse_body (char **body_p, CamelFolder *folder,
/* single part */
char *main_type, *subtype;
char *id, *description, *encoding;
- guint32 size = 0;
+ guint32 size;
main_type = imap_parse_string (&body, &len);
skip_char (&body, ' ');
@@ -661,54 +648,44 @@ get_summary_uid_numeric (CamelFolderSummary *summary, int index)
return uid;
}
-/* the max number of chars that an unsigned 32-bit int can be is 10 chars plus 1 for a possible : */
-#define UID_SET_FULL(setlen, maxlen) (maxlen > 0 ? setlen + 11 >= maxlen : FALSE)
-
/**
* imap_uid_array_to_set:
* @summary: summary for the folder the UIDs come from
* @uids: a (sorted) array of UIDs
- * @uid: uid index to start at
- * @maxlen: max length of the set string (or -1 for infinite)
- * @lastuid: index offset of the last uid used
*
- * Creates an IMAP "set" up to @maxlen bytes long, covering the listed
- * UIDs starting at index @uid and not covering any UIDs that are in
- * @summary but not in @uids. It doesn't actually require that all (or
- * any) of the UIDs be in @summary.
- *
- * After calling, @lastuid will be set the index of the first uid
- * *not* included in the returned set string.
+ * Creates an IMAP "set" covering the listed UIDs and not covering
+ * any UIDs that are in @summary but not in @uids. It doesn't
+ * actually require that all (or any) of the UIDs be in @summary.
*
* Return value: the set, which the caller must free with g_free()
**/
char *
-imap_uid_array_to_set (CamelFolderSummary *summary, GPtrArray *uids, int uid, ssize_t maxlen, int *lastuid)
+imap_uid_array_to_set (CamelFolderSummary *summary, GPtrArray *uids)
{
+ int ui, si, scount;
unsigned long last_uid, next_summary_uid, this_uid;
gboolean range = FALSE;
- int si, scount;
GString *gset;
char *set;
- g_return_val_if_fail (uids->len > uid, NULL);
+ g_return_val_if_fail (uids->len > 0, NULL);
- gset = g_string_new (uids->pdata[uid]);
- last_uid = strtoul (uids->pdata[uid], NULL, 10);
+ gset = g_string_new (uids->pdata[0]);
+ last_uid = strtoul (uids->pdata[0], NULL, 10);
next_summary_uid = 0;
scount = camel_folder_summary_count (summary);
- for (uid++, si = 0; uid < uids->len && !UID_SET_FULL (gset->len, maxlen); uid++) {
+ for (ui = 1, si = 0; ui < uids->len; ui++) {
/* Find the next UID in the summary after the one we
* just wrote out.
*/
- for ( ; last_uid >= next_summary_uid && si < scount; si++)
+ for (; last_uid >= next_summary_uid && si < scount; si++)
next_summary_uid = get_summary_uid_numeric (summary, si);
if (last_uid >= next_summary_uid)
next_summary_uid = (unsigned long) -1;
/* Now get the next UID from @uids */
- this_uid = strtoul (uids->pdata[uid], NULL, 10);
+ this_uid = strtoul (uids->pdata[ui], NULL, 10);
if (this_uid == next_summary_uid || this_uid == last_uid + 1)
range = TRUE;
else {
@@ -725,8 +702,6 @@ imap_uid_array_to_set (CamelFolderSummary *summary, GPtrArray *uids, int uid, ss
if (range)
g_string_sprintfa (gset, ":%lu", last_uid);
- *lastuid = uid;
-
set = gset->str;
g_string_free (gset, FALSE);
@@ -825,7 +800,7 @@ imap_uid_array_free (GPtrArray *arr)
char *
imap_concat (CamelImapStore *imap_store, const char *prefix, const char *suffix)
{
- size_t len;
+ int len;
len = strlen (prefix);
if (len == 0 || prefix[len - 1] == imap_store->dir_sep)
@@ -843,7 +818,7 @@ imap_namespace_concat (CamelImapStore *store, const char *name)
else
return g_strdup ("");
}
-
+
if (!g_strcasecmp (name, "INBOX"))
return g_strdup ("INBOX");
@@ -851,268 +826,6 @@ imap_namespace_concat (CamelImapStore *store, const char *name)
g_warning ("Trying to concat NULL namespace to \"%s\"!", name);
return g_strdup (name);
}
-
- return imap_concat (store, store->namespace, name);
-}
-
-
-#define UTF8_TO_UTF7_LEN(len) ((len * 3) + 8)
-#define UTF7_TO_UTF8_LEN(len) (len)
-
-enum {
- MODE_USASCII,
- MODE_AMPERSAND,
- MODE_MODUTF7
-};
-
-#define is_usascii(c) (((c) >= 0x20 && (c) <= 0x25) || ((c) >= 0x27 && (c) <= 0x7e))
-#define encode_mode(c) (is_usascii (c) ? MODE_USASCII : (c) == '&' ? MODE_AMPERSAND : MODE_MODUTF7)
-
-char *
-imap_mailbox_encode (const unsigned char *in, size_t inlen)
-{
- const unsigned char *start, *inptr, *inend;
- unsigned char *mailbox, *m, *mend;
- size_t inleft, outleft, conv;
- char *inbuf, *outbuf;
- iconv_t cd;
- int mode;
-
- cd = (iconv_t) -1;
- m = mailbox = g_malloc (UTF8_TO_UTF7_LEN (inlen) + 1);
- mend = mailbox + UTF8_TO_UTF7_LEN (inlen);
-
- start = inptr = in;
- inend = in + inlen;
- mode = MODE_USASCII;
-
- while (inptr < inend) {
- int new_mode;
-
- new_mode = encode_mode (*inptr);
-
- if (new_mode != mode) {
- switch (mode) {
- case MODE_USASCII:
- memcpy (m, start, inptr - start);
- m += (inptr - start);
- break;
- case MODE_AMPERSAND:
- while (start < inptr) {
- *m++ = '&';
- *m++ = '-';
- start++;
- }
- break;
- case MODE_MODUTF7:
- inbuf = (char *) start;
- inleft = inptr - start;
- outbuf = (char *) m;
- outleft = mend - m;
-
- if (cd == (iconv_t) -1)
- cd = iconv_open ("UTF-7", "UTF-8");
-
- conv = iconv (cd, &inbuf, &inleft, &outbuf, &outleft);
- if (conv == (size_t) -1) {
- g_warning ("error converting mailbox to UTF-7!");
- }
- iconv (cd, NULL, NULL, &outbuf, &outleft);
-
- /* shift into modified UTF-7 mode (overwrite UTF-7's '+' shift)... */
- *m++ = '&';
-
- while (m < (unsigned char *) outbuf) {
- /* replace '/' with ',' */
- if (*m == '/')
- *m = ',';
-
- m++;
- }
-
- break;
- }
-
- mode = new_mode;
- start = inptr;
- }
-
- inptr++;
- }
-
- switch (mode) {
- case MODE_USASCII:
- memcpy (m, start, inptr - start);
- m += (inptr - start);
- break;
- case MODE_AMPERSAND:
- while (start < inptr) {
- *m++ = '&';
- *m++ = '-';
- start++;
- }
- break;
- case MODE_MODUTF7:
- inbuf = (char *) start;
- inleft = inptr - start;
- outbuf = (char *) m;
- outleft = mend - m;
-
- if (cd == (iconv_t) -1)
- cd = iconv_open ("UTF-7", "UTF-8");
-
- conv = iconv (cd, &inbuf, &inleft, &outbuf, &outleft);
- if (conv == (size_t) -1) {
- g_warning ("error converting mailbox to UTF-7!");
- }
- iconv (cd, NULL, NULL, &outbuf, &outleft);
-
- /* shift into modified UTF-7 mode (overwrite UTF-7's '+' shift)... */
- *m++ = '&';
-
- while (m < (unsigned char *) outbuf) {
- /* replace '/' with ',' */
- if (*m == '/')
- *m = ',';
-
- m++;
- }
-
- break;
- }
-
- *m = '\0';
-
- if (cd != (iconv_t) -1)
- iconv_close (cd);
-
- return mailbox;
-}
-
-char *
-imap_mailbox_decode (const unsigned char *in, size_t inlen)
-{
- const unsigned char *start, *inptr, *inend;
- unsigned char *mailbox, *m, *mend;
- unsigned char mode_switch;
- iconv_t cd;
-
- cd = (iconv_t) -1;
- m = mailbox = g_malloc (UTF7_TO_UTF8_LEN (inlen) + 1);
- mend = mailbox + UTF7_TO_UTF8_LEN (inlen);
-
- start = inptr = in;
- inend = in + inlen;
- mode_switch = '&';
-
- while (inptr < inend) {
- if (*inptr == mode_switch) {
- if (mode_switch == '&') {
- /* mode switch from US-ASCII to UTF-7 */
- mode_switch = '-';
- memcpy (m, start, inptr - start);
- m += (inptr - start);
- start = inptr;
- } else if (mode_switch == '-') {
- /* mode switch from UTF-7 to US-ASCII or an ampersand (&) */
- mode_switch = '&';
- start++;
- if (start == inptr) {
- /* we had the sequence "&-" which becomes "&" when decoded */
- *m++ = '&';
- } else {
- char *buffer, *inbuf, *outbuf;
- size_t buflen, outleft, conv;
-
- buflen = (inptr - start) + 2;
- inbuf = buffer = alloca (buflen);
- *inbuf++ = '+';
- while (start < inptr) {
- *inbuf++ = *start == ',' ? '/' : *start;
- start++;
- }
- *inbuf = '-';
-
- inbuf = buffer;
- outbuf = (char *) m;
- outleft = mend - m;
-
- if (cd == (iconv_t) -1)
- cd = iconv_open ("UTF-8", "UTF-7");
-
- conv = iconv (cd, &inbuf, &buflen, &outbuf, &outleft);
- if (conv == (size_t) -1) {
- g_warning ("error decoding mailbox: %.*s", inlen, in);
- }
- iconv (cd, NULL, NULL, NULL, NULL);
-
- m = (unsigned char *) outbuf;
- }
-
- /* point to the char after the '-' */
- start = inptr + 1;
- }
- }
-
- inptr++;
- }
-
- if (*inptr == mode_switch) {
- if (mode_switch == '&') {
- /* the remaining text is US-ASCII */
- memcpy (m, start, inptr - start);
- m += (inptr - start);
- start = inptr;
- } else if (mode_switch == '-') {
- /* We've got encoded UTF-7 or else an ampersand */
- start++;
- if (start == inptr) {
- /* we had the sequence "&-" which becomes "&" when decoded */
- *m++ = '&';
- } else {
- char *buffer, *inbuf, *outbuf;
- size_t buflen, outleft, conv;
-
- buflen = (inptr - start) + 2;
- inbuf = buffer = alloca (buflen);
- *inbuf++ = '+';
- while (start < inptr) {
- *inbuf++ = *start == ',' ? '/' : *start;
- start++;
- }
- *inbuf = '-';
-
- inbuf = buffer;
- outbuf = (char *) m;
- outleft = mend - m;
-
- if (cd == (iconv_t) -1)
- cd = iconv_open ("UTF-8", "UTF-7");
-
- conv = iconv (cd, &inbuf, &buflen, &outbuf, &outleft);
- if (conv == (size_t) -1) {
- g_warning ("error decoding mailbox: %.*s", inlen, in);
- }
- iconv (cd, NULL, NULL, NULL, NULL);
-
- m = (unsigned char *) outbuf;
- }
- }
- } else {
- if (mode_switch == '-') {
- /* illegal encoded mailbox... */
- g_warning ("illegal mailbox name encountered: %.*s", inlen, in);
- }
-
- memcpy (m, start, inptr - start);
- m += (inptr - start);
- }
-
- *m = '\0';
-
- if (cd != (iconv_t) -1)
- iconv_close (cd);
-
- return mailbox;
+ return imap_concat (store, store->namespace, name);
}