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

_______________________________________________
Evolution-hackers mailing list
Evolution-hackers@gnome.org
http://mail.gnome.org/mailman/listinfo/evolution-hackers

Reply via email to