X-Git-Url: http://git.madism.org/?a=blobdiff_plain;f=imap%2Fmessage.c;h=1221e7a55b3a12777a82fd708811281d3459e0e4;hb=93fff313ededa74d6b1350931a37744729498e3b;hp=41d59504e0e8aa47d7c86aa2625bcccfafbfb474;hpb=6833ce8bdca2d64e14485118f2a4417b7e1cb1b1;p=apps%2Fmadmutt.git diff --git a/imap/message.c b/imap/message.c index 41d5950..1221e7a 100644 --- a/imap/message.c +++ b/imap/message.c @@ -39,6 +39,12 @@ static int msg_has_flag (LIST* flag_list, const char* flag); static int msg_parse_fetch (IMAP_HEADER* h, char* s); static char* msg_parse_flags (IMAP_HEADER* h, char* s); +#if USE_HCACHE +static int msg_fetch_header_fetch (CONTEXT* ctx, IMAP_HEADER* h, char* buf, + FILE* fp); +static size_t imap_hcache_keylen (const char *fn); +#endif /* USE_HCACHE */ + /* imap_read_headers: * Changed to read many headers instead of just one. It will return the * msgno of the last message read. It will return a value other than @@ -57,8 +63,18 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend) int fetchlast = 0; const char *want_headers = "DATE FROM SUBJECT TO CC MESSAGE-ID REFERENCES CONTENT-TYPE IN-REPLY-TO REPLY-TO LINES X-LABEL"; +#if USE_HCACHE + void *hc = NULL; + unsigned long long *uid_validity = NULL; + char uid_buf[64]; +#endif /* USE_HCACHE */ + ctx = idata->ctx; +#if USE_HCACHE + hc = mutt_hcache_open (HeaderCache, ctx->path); +#endif /* USE_HCACHE */ + if (mutt_bit_isset (idata->capabilities,IMAP4REV1)) { snprintf (hdrreq, sizeof (hdrreq), "BODY.PEEK[HEADER.FIELDS (%s)]", @@ -73,6 +89,9 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend) { /* Unable to fetch headers for lower versions */ mutt_error _("Unable to fetch headers from this IMAP server version."); mutt_sleep (2); /* pause a moment to let the user see the error */ +#if USE_HCACHE + mutt_hcache_close (hc); +#endif /* USE_HCACHE */ return -1; } @@ -83,6 +102,9 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend) { mutt_error (_("Could not create temporary file %s"), tempfile); mutt_sleep (2); +#if USE_HCACHE + mutt_hcache_close (hc); +#endif /* USE_HCACHE */ return -1; } unlink (tempfile); @@ -95,14 +117,96 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend) idata->reopen &= ~IMAP_NEWMAIL_PENDING; idata->newMailCount = 0; +#if USE_HCACHE + snprintf (buf, sizeof (buf), + "FETCH %d:%d (UID FLAGS)", msgbegin + 1, msgend + 1); + fetchlast = msgend + 1; + + imap_cmd_start (idata, buf); + + for (msgno = msgbegin; msgno <= msgend ; msgno++) + { + if (ReadInc && (!msgno || ((msgno+1) % ReadInc == 0))) + mutt_message (_("Evaluating cache... [%d/%d]"), msgno + 1, + msgend + 1); + + rewind (fp); + memset (&h, 0, sizeof (h)); + h.data = safe_calloc (1, sizeof (IMAP_HEADER_DATA)); + do + { + mfhrc = 0; + + rc = imap_cmd_step (idata); + if (rc != IMAP_CMD_CONTINUE) + break; + + if ((mfhrc = msg_fetch_header_fetch (idata->ctx, &h, idata->cmd.buf, fp)) == -1) + continue; + else if (mfhrc < 0) + break; + + /* make sure we don't get remnants from older larger message headers */ + fputs ("\n\n", fp); + + sprintf(uid_buf, "/%u", h.data->uid); /* XXX --tg 21:41 04-07-11 */ + uid_validity = (unsigned long long *) mutt_hcache_fetch (hc, uid_buf, &imap_hcache_keylen); + + if (uid_validity != NULL + && *uid_validity == idata->uid_validity) { + ctx->hdrs[msgno] = mutt_hcache_restore((unsigned char *) uid_validity, 0); + ctx->hdrs[msgno]->index = h.sid - 1; + if (h.sid != ctx->msgcount + 1) + dprint (1, (debugfile, "imap_read_headers: msgcount and sequence ID are inconsistent!")); + /* messages which have not been expunged are ACTIVE (borrowed from mh + * folders) */ + ctx->hdrs[msgno]->active = 1; + ctx->hdrs[msgno]->read = h.read; + ctx->hdrs[msgno]->old = h.old; + ctx->hdrs[msgno]->deleted = h.deleted; + ctx->hdrs[msgno]->flagged = h.flagged; + ctx->hdrs[msgno]->replied = h.replied; + ctx->hdrs[msgno]->changed = h.changed; + /* ctx->hdrs[msgno]->received is restored from mutt_hcache_restore */ + ctx->hdrs[msgno]->data = (void *) (h.data); + + ctx->msgcount++; + } + rewind (fp); + + FREE(&uid_validity); + + } + while ((rc != IMAP_CMD_OK) && ((mfhrc == -1) || + ((msgno + 1) >= fetchlast))); + + if ((mfhrc < -1) || ((rc != IMAP_CMD_CONTINUE) && (rc != IMAP_CMD_OK))) + { + imap_free_header_data ((void**) &h.data); + fclose (fp); + mutt_hcache_close (hc); + return -1; + } + } + + fetchlast = msgbegin; +#endif /* USE_HCACHE */ + for (msgno = msgbegin; msgno <= msgend ; msgno++) { if (ReadInc && (!msgno || ((msgno+1) % ReadInc == 0))) mutt_message (_("Fetching message headers... [%d/%d]"), msgno + 1, msgend + 1); + if (ctx->hdrs[msgno]) + continue; + if (msgno + 1 > fetchlast) { + fetchlast = msgno + 1; + while((fetchlast <= msgend) && (! ctx->hdrs[fetchlast])) + fetchlast++; + /* * Make one request for everything. This makes fetching headers an * order of magnitude faster if you have a large mailbox. @@ -112,11 +216,9 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend) */ snprintf (buf, sizeof (buf), "FETCH %d:%d (UID FLAGS INTERNALDATE RFC822.SIZE %s)", msgno + 1, - msgend + 1, hdrreq); + fetchlast, hdrreq); imap_cmd_start (idata, buf); - - fetchlast = msgend + 1; } /* freshen fp, h */ @@ -170,6 +272,11 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend) /* content built as a side-effect of mutt_read_rfc822_header */ ctx->hdrs[msgno]->content->length = h.content_length; +#if USE_HCACHE + sprintf(uid_buf, "/%u", h.data->uid); + mutt_hcache_store(hc, uid_buf, ctx->hdrs[msgno], idata->uid_validity, &imap_hcache_keylen); +#endif /* USE_HCACHE */ + ctx->msgcount++; } while ((rc != IMAP_CMD_OK) && ((mfhrc == -1) || @@ -179,7 +286,9 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend) { imap_free_header_data ((void**) &h.data); fclose (fp); - +#if USE_HCACHE + mutt_hcache_close (hc); +#endif /* USE_HCACHE */ return -1; } @@ -194,6 +303,10 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend) } } +#if USE_HCACHE + mutt_hcache_close (hc); +#endif /* USE_HCACHE */ + fclose(fp); if (ctx->msgcount > oldmsgcount) @@ -726,6 +839,7 @@ char* imap_set_flags (IMAP_DATA* idata, HEADER* h, char* s) return s; } + /* msg_fetch_header: import IMAP FETCH response into an IMAP_HEADER. * Expects string beginning with * n FETCH. * Returns: @@ -785,6 +899,56 @@ static int msg_fetch_header (CONTEXT* ctx, IMAP_HEADER* h, char* buf, FILE* fp) return rc; } +#if USE_HCACHE +static size_t imap_hcache_keylen (const char *fn) +{ + return mutt_strlen(fn); +} + +/* msg_fetch_header: import IMAP FETCH response into an IMAP_HEADER. + * Expects string beginning with * n FETCH. + * Returns: + * 0 on success + * -1 if the string is not a fetch response + * -2 if the string is a corrupt fetch response */ +static int msg_fetch_header_fetch (CONTEXT* ctx, IMAP_HEADER* h, char* buf, FILE* fp) +{ + IMAP_DATA* idata; + long bytes; + int rc = -1; /* default now is that string isn't FETCH response*/ + + idata = (IMAP_DATA*) ctx->data; + + if (buf[0] != '*') + return rc; + + /* skip to message number */ + buf = imap_next_word (buf); + h->sid = atoi (buf); + + /* find FETCH tag */ + buf = imap_next_word (buf); + if (ascii_strncasecmp ("FETCH", buf, 5)) + return rc; + + rc = -2; /* we've got a FETCH response, for better or worse */ + if (!(buf = strchr (buf, '('))) + return rc; + buf++; + + if (msg_parse_fetch (h, buf) < 0) { + return -2; + } + + if (!(buf = strchr (buf, ')'))) + return rc; + buf++; + + return 0; +} +#endif /* USE_HCACHE */ + + /* msg_has_flag: do a caseless comparison of the flag against a flag list, * return 1 if found or flag list has '\*', 0 otherwise */ static int msg_has_flag (LIST* flag_list, const char* flag)