Re: [Evolution-hackers] Reviewing imap_update_summary
- From: Philip Van Hoof <spam pvanhoof be>
- To: Evolution Hackers <evolution-hackers gnome org>
- Subject: Re: [Evolution-hackers] Reviewing imap_update_summary
- Date: Tue, 24 Oct 2006 01:56:30 +0200
With "UID FETCH %d:%d FLAGS" being something not all IMAP servers don't
correctly support, I was a little bit forced to rewrite the
imap_update_summary function into these two ones:
I also simplified it a little bit. And removed one of the two/three
GPtrArrays (that are being synchronized and other funny stuff).
ps. I still need to test this one, and recheck for problems, etc etc ...
static guint32
imap_get_uids (CamelFolder *folder, CamelImapStore *store, CamelException *ex, GPtrArray *needheaders, int size, int got)
{
char *resp;
CamelImapResponseType type;
guint32 cnt = 0;
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
GData *data;
camel_operation_start (NULL, _("Fetching summary information for new messages in %s"), folder->name);
while ((type = camel_imap_command_response (store, &resp, ex)) ==
CAMEL_IMAP_RESPONSE_UNTAGGED)
{
cnt++;
data = parse_fetch_response (imap_folder, resp);
g_free (resp);
if (!data)
continue;
g_ptr_array_add (needheaders, g_datalist_get_data (&data, "UID"));
if (size > 0)
camel_operation_progress (NULL, got * 100 / size);
}
camel_operation_end (NULL);
g_free (resp);
return cnt;
}
static void
imap_update_summary (CamelFolder *folder, int exists,
CamelFolderChangeInfo *changes,
CamelException *ex)
{
CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
GPtrArray *fetch_data = NULL, *messages = NULL, *needheaders;
guint32 flags, uidval;
int i, seq, first, size, got;
CamelImapResponseType type;
const char *header_spec;
CamelImapMessageInfo *mi, *info;
CamelStream *stream;
char *uid, *resp;
GData *data;
gboolean more = TRUE;
unsigned int nextn = 1, cnt=0, tcnt=0;
if (store->server_level >= IMAP_LEVEL_IMAP4REV1)
header_spec = "HEADER.FIELDS (" CAMEL_MESSAGE_INFO_HEADERS MAILING_LIST_HEADERS ")";
else
header_spec = "0";
/* Used as a way to fetch all Headers instead of the selective headers.
Support for fetching custom headers could be done in a better way,
using CamelURL and EPlugins. */
if( g_getenv ("EVO_IMAP_FETCH_ALL_HEADERS") )
header_spec = "HEADER";
tcnt = 0;
while (more)
{
seq = camel_folder_summary_count (folder->summary);
first = seq + 1;
if (seq > 0) {
mi = (CamelImapMessageInfo *)camel_folder_summary_index (folder->summary, seq - 1);
uidval = strtoul(camel_message_info_uid (mi), NULL, 10);
camel_message_info_free(&mi->info);
} else
uidval = 0;
size = (exists - seq) * (IMAP_PRETEND_SIZEOF_FLAGS + IMAP_PRETEND_SIZEOF_SIZE + IMAP_PRETEND_SIZEOF_HEADERS);
got = 0;
if (!camel_imap_command_start (store, folder, ex,
"UID FETCH %d:%d FLAGS", uidval + 1, uidval + 1 + nextn))
return;
more = FALSE;
needheaders = g_ptr_array_new ();
cnt = imap_get_uids (folder, store, ex, needheaders, size, got);
tcnt += cnt;
if (tcnt >= (exists - seq))
more = FALSE;
else
more = TRUE;
if (more && (((exists - seq) > nextn) && (cnt < nextn)))
{
if (!camel_imap_command_start (store, folder, ex,
"UID FETCH %d:* FLAGS", uidval + 1))
return;
cnt = imap_get_uids (folder, store, ex, needheaders, size, got);
tcnt += cnt;
more = FALSE;
}
if (nextn < 1000)
nextn += (nextn+5);
else
nextn = 1000;
messages = g_ptr_array_new ();
if (needheaders->len)
{
char *uidset;
int uid = 0;
qsort (needheaders->pdata, needheaders->len,
sizeof (void *), uid_compar);
camel_operation_start (NULL, _("Fetching summary information for new messages in %s"), folder->name);
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 (FLAGS INTERNALDATE 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)
{
gchar *muid;
data = parse_fetch_response (imap_folder, resp);
g_free (resp);
if (!data)
continue;
stream = g_datalist_get_data (&data, "BODY_PART_STREAM");
if (stream) {
mi = add_message_from_data (folder, messages, first, data);
if (mi)
{
flags = GPOINTER_TO_INT (g_datalist_get_data (&data, "FLAGS"));
if (flags) {
mi->server_flags = flags;
mi->info.flags |= flags;
flags_to_label(folder, mi);
}
muid = g_datalist_get_data (&data, "UID");
if (muid) {
mi->info.uid = g_strdup (muid);
mi->info.uid_needs_free = TRUE;
}
}
got += IMAP_PRETEND_SIZEOF_HEADERS;
if (size > 0)
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;
}
}
g_ptr_array_free (needheaders, TRUE);
camel_operation_end (NULL);
}
/* And add the entries to the summary, etc. */
for (i = 0; i < messages->len; i++)
{
mi = messages->pdata[i];
if (!mi)
continue;
uid = (char *)camel_message_info_uid(mi);
if (uid[0] == 0) {
g_warning("Server provided no uid: message %d", i + first);
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Incomplete server response: no UID provided for message %d"),
i + first);
break;
}
info = (CamelImapMessageInfo *)camel_folder_summary_uid(folder->summary, uid);
if (info)
{
for (seq = 0; seq < camel_folder_summary_count (folder->summary); seq++) {
if (folder->summary->messages->pdata[seq] == info)
break;
}
g_warning("Message already present? %s", camel_message_info_uid(mi));
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
_("Unexpected server response: Identical UIDs provided for messages %d and %d"),
seq + 1, i + first);
camel_message_info_free(&info->info);
break;
}
camel_folder_summary_add (folder->summary, (CamelMessageInfo *)mi);
camel_folder_change_info_add_uid (changes, camel_message_info_uid (mi));
if ((mi->info.flags & CAMEL_IMAP_MESSAGE_RECENT))
camel_folder_change_info_recent_uid(changes, camel_message_info_uid (mi));
}
camel_folder_summary_dump_mmap (folder->summary);
for ( ; i < messages->len; i++) {
if ((mi = messages->pdata[i]))
camel_message_info_free(&mi->info);
}
g_ptr_array_free (messages, TRUE);
goto endbmore;
lose:
if (fetch_data) {
for (i = 0; i < fetch_data->len; i++) {
data = fetch_data->pdata[i];
g_datalist_clear (&data);
}
g_ptr_array_free (fetch_data, TRUE);
}
if (messages) {
for (i = 0; i < messages->len; i++) {
if (messages->pdata[i])
camel_message_info_free(messages->pdata[i]);
}
g_ptr_array_free (messages, TRUE);
}
endbmore:
i++; i--;
} /* more */
}
--
Philip Van Hoof, software developer at x-tend
home: me at pvanhoof dot be
gnome: pvanhoof at gnome dot org
work: vanhoof at x-tend dot be
http://www.pvanhoof.be - http://www.x-tend.be
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]