diff options
Diffstat (limited to 'mail/mutt-devel/files/extra-patch-imap-header-cache')
-rw-r--r-- | mail/mutt-devel/files/extra-patch-imap-header-cache | 873 |
1 files changed, 873 insertions, 0 deletions
diff --git a/mail/mutt-devel/files/extra-patch-imap-header-cache b/mail/mutt-devel/files/extra-patch-imap-header-cache new file mode 100644 index 000000000000..0c6fb7984a37 --- /dev/null +++ b/mail/mutt-devel/files/extra-patch-imap-header-cache @@ -0,0 +1,873 @@ +diff -ru old/globals.h work/mutt-1.5.5.1/globals.h +--- old/globals.h Wed Nov 5 10:41:31 2003 ++++ globals.h Fri Nov 28 18:30:37 2003 +@@ -57,6 +57,7 @@ + WHERE char *ImapHomeNamespace INITVAL (NULL); + WHERE char *ImapPass INITVAL (NULL); + WHERE char *ImapUser INITVAL (NULL); ++WHERE char *ImapHeadercache INITVAL (NULL); + #endif + WHERE char *Inbox; + WHERE char *Ispell; +diff -ru old/imap/Makefile.am work/mutt-1.5.5.1/imap/Makefile.am +--- old/imap/Makefile.am Thu Jan 24 14:35:57 2002 ++++ imap/Makefile.am Fri Nov 28 18:30:37 2003 +@@ -22,4 +22,5 @@ + noinst_HEADERS = auth.h imap_private.h message.h + + libimap_a_SOURCES = auth.c auth_login.c browse.c command.c imap.c imap.h \ +- message.c utf7.c util.c $(AUTHENTICATORS) $(GSSSOURCES) ++ imap_headercache.c imap_headercache.h message.c utf7.c util.c \ ++ $(AUTHENTICATORS) $(GSSSOURCES) +diff -ru old/imap/imap.c work/mutt-1.5.5.1/imap/imap.c +--- old/imap/imap.c Wed Nov 5 10:41:36 2003 ++++ imap/imap.c Fri Nov 28 18:30:37 2003 +@@ -29,6 +29,7 @@ + #include "browser.h" + #include "message.h" + #include "imap_private.h" ++#include "imap_headercache.h" + #ifdef USE_SSL + # include "mutt_ssl.h" + #endif +@@ -546,6 +547,13 @@ + + /* Clean up path and replace the one in the ctx */ + imap_fix_path (idata, mx.mbox, buf, sizeof (buf)); ++ ++ if (idata->hcache) ++ { ++ imap_headercache_close(idata->hcache); ++ idata->hcache = NULL; ++ } ++ + FREE(&(idata->mailbox)); + idata->mailbox = safe_strdup (buf); + imap_qualify_path (buf, sizeof (buf), &mx, idata->mailbox); +@@ -556,6 +564,7 @@ + idata->ctx = ctx; + + /* clear mailbox status */ ++ idata->uidvalidity = 0; + idata->status = 0; + memset (idata->rights, 0, (RIGHTSMAX+7)/8); + idata->newMailCount = 0; +@@ -601,6 +610,15 @@ + if ((pc = imap_get_flags (&(idata->flags), pc)) == NULL) + goto fail; + } ++ /* save UIDVALIDITY for the header cache */ ++ else if (ascii_strncasecmp("OK [UIDVALIDITY", pc, 14) == 0) ++ { ++ dprint(2, (debugfile, "Getting mailbox UIDVALIDITY\n")); ++ pc += 3; ++ pc = imap_next_word(pc); ++ ++ sscanf(pc, "%u", &(idata->uidvalidity)); ++ } + else + { + pc = imap_next_word (pc); +@@ -684,6 +702,9 @@ + ctx->hdrs = safe_calloc (count, sizeof (HEADER *)); + ctx->v2r = safe_calloc (count, sizeof (int)); + ctx->msgcount = 0; ++ ++ idata->hcache = imap_headercache_open(idata); ++ + if (count && (imap_read_headers (idata, 0, count-1) < 0)) + { + mutt_error _("Error opening mailbox"); +@@ -693,6 +714,7 @@ + + dprint (2, (debugfile, "imap_open_mailbox: msgcount is %d\n", ctx->msgcount)); + FREE (&mx.mbox); ++ + return 0; + + fail: +@@ -914,6 +936,7 @@ + int n; + int err_continue = M_NO; /* continue on error? */ + int rc; ++ IMAP_HEADER h; + + idata = (IMAP_DATA*) ctx->data; + +@@ -953,8 +976,20 @@ + /* mark these messages as unchanged so second pass ignores them. Done + * here so BOGUS UW-IMAP 4.7 SILENT FLAGS updates are ignored. */ + for (n = 0; n < ctx->msgcount; n++) +- if (ctx->hdrs[n]->deleted && ctx->hdrs[n]->changed) +- ctx->hdrs[n]->active = 0; ++ { ++ if (ctx->hdrs[n]->deleted) ++ { ++ if (idata->hcache) ++ { ++ h.data = HEADER_DATA(ctx->hdrs[n]); ++ imap_headercache_delete(idata->hcache, &h); ++ } ++ ++ if (ctx->hdrs[n]->changed) ++ ctx->hdrs[n]->active = 0; ++ } ++ } ++ + if (imap_exec (idata, cmd.data, 0) != 0) + { + mutt_error (_("Expunge failed")); +@@ -972,6 +1007,23 @@ + { + ctx->hdrs[n]->changed = 0; + ++ if (idata->hcache) ++ { ++ h.data = HEADER_DATA(ctx->hdrs[n]); ++ ++ h.read = ctx->hdrs[n]->read; ++ h.old = ctx->hdrs[n]->old; ++ h.deleted = ctx->hdrs[n]->deleted; ++ h.flagged = ctx->hdrs[n]->flagged; ++ h.replied = ctx->hdrs[n]->replied; ++ h.changed = ctx->hdrs[n]->changed; ++ h.sid = ctx->hdrs[n]->index + 1; ++ h.received = ctx->hdrs[n]->received; ++ h.content_length = ctx->hdrs[n]->content->length; ++ ++ imap_headercache_update(idata->hcache, &h); ++ } ++ + mutt_message (_("Saving message status flags... [%d/%d]"), n+1, + ctx->msgcount); + +@@ -1099,6 +1151,11 @@ + + idata->reopen &= IMAP_REOPEN_ALLOW; + idata->state = IMAP_AUTHENTICATED; ++ if (idata->hcache) ++ { ++ imap_headercache_close(idata->hcache); ++ idata->hcache = NULL; ++ } + FREE (&(idata->mailbox)); + mutt_free_list (&idata->flags); + idata->ctx = NULL; +diff -ru old/imap/imap_private.h work/mutt-1.5.5.1/imap/imap_private.h +--- old/imap/imap_private.h Wed Nov 5 10:41:36 2003 ++++ imap/imap_private.h Fri Nov 28 18:30:37 2003 +@@ -21,6 +21,7 @@ + #define _IMAP_PRIVATE_H 1 + + #include "imap.h" ++#include "imap_headercache.h" + #include "mutt_socket.h" + + /* -- symbols -- */ +@@ -148,7 +149,7 @@ + int state; + } IMAP_COMMAND; + +-typedef struct ++typedef struct IMAP_DATA + { + /* This data is specific to a CONNECTION to an IMAP server */ + CONNECTION *conn; +@@ -175,6 +176,7 @@ + char *mailbox; + unsigned short check_status; + unsigned char reopen; ++ unsigned int uidvalidity; + unsigned char rights[(RIGHTSMAX + 7)/8]; + unsigned int newMailCount; + IMAP_CACHE cache[IMAP_CACHE_LEN]; +@@ -182,6 +184,7 @@ + + /* all folder flags - system flags AND keywords */ + LIST *flags; ++ IMAP_HEADERCACHE *hcache; + } IMAP_DATA; + /* I wish that were called IMAP_CONTEXT :( */ + +diff -ru old/imap/message.c work/mutt-1.5.5.1/imap/message.c +--- old/imap/message.c Wed Nov 5 10:41:36 2003 ++++ imap/message.c Fri Nov 28 18:30:38 2003 +@@ -25,6 +25,7 @@ + #include "mutt.h" + #include "mutt_curses.h" + #include "imap_private.h" ++#include "imap_headercache.h" + #include "message.h" + #include "mx.h" + +@@ -54,9 +55,14 @@ + int msgno; + IMAP_HEADER h; + int rc, mfhrc, oldmsgcount; ++ IMAP_HEADERCACHE *hc = NULL; ++ int msgbegin_hc; + 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"; + ++ msgno = msgbegin; ++ + ctx = idata->ctx; + + if (mutt_bit_isset (idata->capabilities,IMAP4REV1)) +@@ -87,36 +93,150 @@ + } + unlink (tempfile); + ++ oldmsgcount = ctx->msgcount; ++ ++ msgbegin_hc = msgbegin; ++ ++ hc = idata->hcache; ++ ++restart: + /* make sure context has room to hold the mailbox */ + while ((msgend) >= idata->ctx->hdrmax) + mx_alloc_memory (idata->ctx); + +- oldmsgcount = ctx->msgcount; + idata->reopen &= ~IMAP_NEWMAIL_PENDING; + idata->newMailCount = 0; + ++ if (hc) ++ { ++ snprintf(buf, sizeof(buf), "FETCH %d:%d (UID)", msgbegin_hc + 1, ++ msgend + 1); ++ imap_cmd_start(idata, buf); ++ ++ for (msgno = msgbegin_hc; msgno <= msgend; msgno++) ++ { ++ if (ReadInc && (!msgno || ((msgno+1) % ReadInc == 0))) ++ mutt_message (_("Fetching message UIDs... [%d/%d]"), msgno + 1, ++ msgend + 1); ++ ++ /* XXX */ ++ ctx->hdrs[msgno] = NULL; ++ ++ /* XXX leaking h.data on successful exit */ ++ memset (&h, 0, sizeof (h)); ++ h.data = safe_calloc (1, sizeof (IMAP_HEADER_DATA)); ++ ++ do ++ { ++ FILE *cache_fp; ++ ++ mfhrc = 0; ++ ++ rc = imap_cmd_step (idata); ++ if (rc != IMAP_CMD_CONTINUE) ++ break; ++ ++ if ((mfhrc = msg_fetch_header (idata->ctx, &h, idata->cmd.buf, NULL)) == -1) ++ continue; ++ else if (mfhrc < 0) ++ break; ++ ++ cache_fp = imap_headercache_find(hc, &h); ++ if (cache_fp) ++ { ++ /* update context with message header */ ++ ctx->hdrs[msgno] = mutt_new_header (); ++ ++ ctx->hdrs[msgno]->index = h.sid - 1; ++ ++ /* 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 = h.received; ++ ctx->hdrs[msgno]->data = (void *) (h.data); ++ ++ /* NOTE: if Date: header is missing, mutt_read_rfc822_header depends ++ * on h.received being set */ ++ ctx->hdrs[msgno]->env = mutt_read_rfc822_header (cache_fp, ctx->hdrs[msgno], ++ 0, 0); ++ /* content built as a side-effect of mutt_read_rfc822_header */ ++ ctx->hdrs[msgno]->content->length = h.content_length; ++ ++ imap_headercache_done(hc, cache_fp); ++ } ++ } ++ while (mfhrc == -1); ++ ++ /* in case we get new mail while fetching the headers */ ++ if (idata->reopen & IMAP_NEWMAIL_PENDING) ++ { ++ msgbegin_hc = msgno + 1; ++ msgend = idata->newMailCount - 1; ++ goto restart; ++ } ++ /* XXX freshen... etc */ ++ } ++ } ++ ++ /* Remember where we left if we get new mail while fetching actual headers */ ++ msgbegin_hc = msgno; ++ ++ /* Now, either one of the following is true: ++ * 1. We don't have a headercache (hc == 0) ++ * 2. All messages found in the cache have ctx->hdrs[msgno] != NULL, and ++ * filled up. ++ */ ++ ++ /* ++ * Make one request for everything. This makes fetching headers an ++ * order of magnitude faster if you have a large mailbox. ++ * ++ * If we get more messages while doing this, we make another ++ * request for all the new messages. ++ */ ++ if (!hc) ++ { ++ snprintf (buf, sizeof (buf), ++ "FETCH %d:%d (UID FLAGS INTERNALDATE RFC822.SIZE %s)", msgbegin + 1, ++ msgend + 1, hdrreq); ++ ++ imap_cmd_start (idata, buf); ++ } ++ + 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 (msgno + 1 > fetchlast) ++ /* If the message is in the cache, skip it */ ++ if (hc) + { +- /* +- * Make one request for everything. This makes fetching headers an +- * order of magnitude faster if you have a large mailbox. +- * +- * If we get more messages while doing this, we make another +- * request for all the new messages. +- */ +- snprintf (buf, sizeof (buf), +- "FETCH %d:%d (UID FLAGS INTERNALDATE RFC822.SIZE %s)", msgno + 1, +- msgend + 1, hdrreq); +- +- imap_cmd_start (idata, buf); ++ if (ctx->hdrs[msgno]) ++ { ++ ctx->msgcount++; ++ continue; ++ } ++ else if (msgno >= fetchlast) ++ { ++ /* Find the longest "run" of messages not in the cache and fetch it in ++ * one go ++ */ ++ for (fetchlast = msgno + 1; ++ fetchlast <= msgend && !ctx->hdrs[fetchlast]; fetchlast++); ++ ++ snprintf (buf, sizeof (buf), ++ "FETCH %d:%d (UID FLAGS INTERNALDATE RFC822.SIZE %s)", msgno + 1, ++ fetchlast, hdrreq); + +- fetchlast = msgend + 1; ++ imap_cmd_start (idata, buf); ++ } + } + + /* freshen fp, h */ +@@ -130,6 +250,8 @@ + */ + do + { ++ size_t hdrsz; ++ + mfhrc = 0; + + rc = imap_cmd_step (idata); +@@ -144,12 +266,16 @@ + /* make sure we don't get remnants from older larger message headers */ + fputs ("\n\n", fp); + ++ hdrsz = (size_t)ftell(fp); ++ + /* update context with message header */ + ctx->hdrs[msgno] = mutt_new_header (); + + ctx->hdrs[msgno]->index = h.sid - 1; ++#if 0 + if (h.sid != ctx->msgcount + 1) + dprint (1, (debugfile, "imap_read_headers: msgcount and sequence ID are inconsistent!")); ++#endif + /* messages which have not been expunged are ACTIVE (borrowed from mh + * folders) */ + ctx->hdrs[msgno]->active = 1; +@@ -163,6 +289,13 @@ + ctx->hdrs[msgno]->data = (void *) (h.data); + + rewind (fp); ++ ++ if (hc) ++ { ++ imap_headercache_add(hc, &h, fp, hdrsz); ++ rewind(fp); ++ } ++ + /* NOTE: if Date: header is missing, mutt_read_rfc822_header depends + * on h.received being set */ + ctx->hdrs[msgno]->env = mutt_read_rfc822_header (fp, ctx->hdrs[msgno], +@@ -172,8 +305,7 @@ + + ctx->msgcount++; + } +- while ((rc != IMAP_CMD_OK) && ((mfhrc == -1) || +- ((msgno + 1) >= fetchlast))); ++ while (mfhrc == -1); + + if ((mfhrc < -1) || ((rc != IMAP_CMD_CONTINUE) && (rc != IMAP_CMD_OK))) + { +@@ -186,11 +318,9 @@ + /* in case we get new mail while fetching the headers */ + if (idata->reopen & IMAP_NEWMAIL_PENDING) + { ++ msgbegin = msgno + 1; + msgend = idata->newMailCount - 1; +- while ((msgend) >= ctx->hdrmax) +- mx_alloc_memory (ctx); +- idata->reopen &= ~IMAP_NEWMAIL_PENDING; +- idata->newMailCount = 0; ++ goto restart; + } + } + +@@ -735,6 +865,7 @@ + IMAP_DATA* idata; + long bytes; + int rc = -1; /* default now is that string isn't FETCH response*/ ++ int fetch_rc; + + idata = (IMAP_DATA*) ctx->data; + +@@ -757,9 +888,15 @@ + + /* FIXME: current implementation - call msg_parse_fetch - if it returns -2, + * read header lines and call it again. Silly. */ +- if (msg_parse_fetch (h, buf) != -2) ++ fetch_rc = msg_parse_fetch(h, buf); ++ if (fetch_rc == 0) ++ return 0; ++ else if (fetch_rc != -2) + return rc; +- ++ ++ if (!fp) ++ return -2; ++ + if (imap_get_literal_count (buf, &bytes) < 0) + return rc; + imap_read_literal (fp, idata, bytes); +diff -ru old/init.h work/mutt-1.5.5.1/init.h +--- old/init.h Wed Nov 5 10:41:32 2003 ++++ init.h Fri Nov 28 18:30:37 2003 +@@ -856,6 +856,11 @@ + ** .pp + ** This variable defaults to your user name on the local machine. + */ ++ { "imap_headercache", DT_STR, R_NONE, UL &ImapHeadercache, UL 0 }, ++ /* ++ ** .pp ++ ** The location of the IMAP headercache directory. ++ */ + #endif + { "implicit_autoview", DT_BOOL,R_NONE, OPTIMPLICITAUTOVIEW, 0}, + /* +diff -ruN old/imap/imap_headercache.c work/mutt-1.5.5.1/imap/imap_headercache.c +--- old/imap/imap_headercache.c Thu Jan 1 01:00:00 1970 ++++ imap/imap_headercache.c Fri Nov 28 18:30:55 2003 +@@ -0,0 +1,330 @@ ++/* ++ * Copyright (C) 2002 Tudor Bosman <tudorb-mutt@dwyn.net> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. ++ */ ++ ++#include "mutt.h" ++#include "imap.h" ++#include "imap_private.h" ++#include "imap_headercache.h" ++#include "mx.h" ++#include <stdio.h> ++#include <sys/types.h> ++#include <sys/stat.h> ++#include <fcntl.h> ++#include <errno.h> ++#include <unistd.h> ++#include <dirent.h> ++#include <assert.h> ++ ++/* Delete all messages from headercache */ ++static int imap_headercache_purge(IMAP_HEADERCACHE *hc) ++{ ++ int rc = -1; ++ DIR *dir; ++ struct dirent *ent; ++ ++ dir = opendir(hc->name); ++ if (!dir) ++ { ++ mutt_error(_("IMAP headercache: can't purge directory %s: %s"), hc->name, ++ strerror(errno)); ++ mutt_sleep(2); ++ return -1; ++ } ++ ++ while ((ent = readdir(dir)) != NULL) ++ { ++ if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) ++ continue; ++ ++ sprintf(hc->tmpname, "%s/%s", hc->name, ent->d_name); ++ if (unlink(hc->tmpname) == -1) ++ { ++ mutt_error(_("IMAP headercache: can't unlink file %s: %s"), hc->tmpname, ++ strerror(errno)); ++ mutt_sleep(2); ++ goto bail; ++ } ++ } ++ ++ rc = 0; ++ ++bail: ++ closedir(dir); ++ ++ return rc; ++} ++ ++/* Open headercache */ ++IMAP_HEADERCACHE *imap_headercache_open(IMAP_DATA *idata) ++{ ++ IMAP_HEADERCACHE *hc; ++ char hcdir[_POSIX_PATH_MAX + 1]; ++ FILE *f; ++ size_t len; ++ char *p; ++ ++ if (!ImapHeadercache || ImapHeadercache[0] == '\0') ++ return NULL; ++ ++ strfcpy(hcdir, ImapHeadercache, _POSIX_PATH_MAX); ++ mutt_expand_path(hcdir, _POSIX_PATH_MAX); ++ ++ hc = safe_malloc(sizeof(IMAP_HEADERCACHE)); ++ ++ len = strlen(hcdir) + strlen(idata->conn->account.host) + ++ strlen(idata->mailbox) + 5; ++ ++ hc->name = safe_malloc(len); ++ hc->tmpname = safe_malloc(len + NAME_MAX + 2); ++ ++ sprintf(hc->name, "%s/%s", hcdir, idata->conn->account.host); ++ ++ if (mkdir(hcdir, 0777) == -1 && errno != EEXIST) ++ { ++ mutt_error(_("Can't create IMAP headercache root directory %s: %s"), ++ hcdir, strerror(errno)); ++ mutt_sleep(2); ++ goto bail; ++ } ++ ++ if (mkdir(hc->name, 0700) == -1 && errno != EEXIST) ++ { ++ mutt_error(_("Can't create IMAP headercache server directory %s: %s"), ++ hc->name, strerror(errno)); ++ mutt_sleep(2); ++ goto bail; ++ } ++ ++ p = idata->mailbox; ++ while ((p = strchr(p, '/')) != NULL) ++ { ++ *p = '\0'; ++ sprintf(hc->name, "%s/%s/%s", hcdir, ++ idata->conn->account.host, idata->mailbox); ++ ++ if (mkdir(hc->name, 0700) == -1 && errno != EEXIST) ++ { ++ mutt_error(_("Can't create IMAP headercache mailbox directory %s: %s"), ++ hc->name, strerror(errno)); ++ mutt_sleep(2); ++ goto bail; ++ } ++ ++ *p = '/'; ++ p++; ++ } ++ ++ sprintf(hc->name, "%s/%s/%s", hcdir, ++ idata->conn->account.host, idata->mailbox); ++ ++ if (mkdir(hc->name, 0700) == -1 && errno != EEXIST) ++ { ++ mutt_error(_("Can't create IMAP headercache mailbox directory %s: %s"), ++ hc->name, strerror(errno)); ++ mutt_sleep(2); ++ goto bail; ++ } ++ ++ sprintf(hc->tmpname, "%s/uidvalidity", hc->name); ++ f = fopen(hc->tmpname, "r"); ++ ++ if (f) ++ { ++ fscanf(f, "%u", &hc->uidvalidity); ++ if (idata->uidvalidity != hc->uidvalidity) ++ { ++ fclose(f); ++ f = NULL; ++ } ++ } ++ ++ if (!f) ++ { ++ if (imap_headercache_purge(hc) == -1) ++ goto bail; ++ ++ sprintf(hc->tmpname, "%s/uidvalidity", hc->name); ++ f = fopen(hc->tmpname, "w"); ++ if (!f) ++ { ++ mutt_error(_("Can't create IMAP headercache uidvalidity file %s: %s"), ++ hc->tmpname, strerror(errno)); ++ mutt_sleep(2); ++ goto bail; ++ } ++ ++ hc->uidvalidity = idata->uidvalidity; ++ ++ fprintf(f, "%u\n", hc->uidvalidity); ++ fclose(f); ++ } ++ ++ return hc; ++ ++bail: ++ safe_free((void **)&hc->tmpname); ++ safe_free((void **)&hc->name); ++ safe_free((void **)&hc); ++ ++ return NULL; ++} ++ ++/* Close headercache */ ++void imap_headercache_close(IMAP_HEADERCACHE *hc) ++{ ++ safe_free((void **)&hc->tmpname); ++ safe_free((void **)&hc->name); ++ safe_free((void **)&hc); ++} ++ ++static void imap_headercache_writehdr(FILE *f, IMAP_HEADER *h) ++{ ++ /* Write the stuff in the header. This must have a fixed length, as it is ++ * overwritten in case of imap_headercache_update ++ */ ++ fprintf(f, "%1x %1x %1x %1x %1x %1x %8x %16lx %16lx %8x\n", ++ h->read, h->old, h->deleted, h->flagged, h->replied, h->changed, ++ h->sid, h->received, h->content_length, HEADER_DATA(h)->uid); ++} ++ ++/* Add message to headercache */ ++int imap_headercache_add(IMAP_HEADERCACHE *hc, IMAP_HEADER *h, FILE *from, ++ size_t hdrsz) ++{ ++ FILE *f; ++#define BUFSIZE 4096 ++ char buf[BUFSIZE]; ++ size_t sz; ++ int rc = -1; ++ ++ sprintf(hc->tmpname, "%s/%u", hc->name, HEADER_DATA(h)->uid); ++ ++ f = fopen(hc->tmpname, "w"); ++ if (!f) ++ { ++ mutt_error(_("Can't create IMAP headercache message file %s: %s"), ++ hc->tmpname, strerror(errno)); ++ mutt_sleep(2); ++ goto bail; ++ } ++ ++ imap_headercache_writehdr(f, h); ++ ++ while ((sz = fread(buf, 1, (hdrsz < BUFSIZE ? hdrsz : BUFSIZE), from)) != 0) ++ { ++ hdrsz -= sz; ++ fwrite(buf, 1, sz, f); ++ } ++ ++ fclose(f); ++ ++ rc = 0; ++ ++bail: ++ return rc; ++} ++ ++/* Update flags in headercache message */ ++int imap_headercache_update(IMAP_HEADERCACHE *hc, IMAP_HEADER *h) ++{ ++ FILE *f; ++ int rc = -1; ++ ++ sprintf(hc->tmpname, "%s/%u", hc->name, HEADER_DATA(h)->uid); ++ ++ f = fopen(hc->tmpname, "r+"); ++ if (!f) ++ goto bail; ++ ++ imap_headercache_writehdr(f, h); ++ ++ fclose(f); ++ ++ rc = 0; ++ ++bail: ++ return rc; ++} ++ ++/* Delete message from headercache */ ++int imap_headercache_delete(IMAP_HEADERCACHE *hc, IMAP_HEADER *h) ++{ ++ int rc = -1; ++ ++ sprintf(hc->tmpname, "%s/%u", hc->name, HEADER_DATA(h)->uid); ++ ++ if (unlink(hc->tmpname) == -1) ++ { ++ mutt_error(_("Can't delete IMAP headercache message %s: %s"), ++ hc->tmpname, strerror(errno)); ++ mutt_sleep(2); ++ goto bail; ++ } ++ ++ rc = 0; ++ ++bail: ++ return rc; ++} ++ ++/* Find message in headercache */ ++FILE *imap_headercache_find(IMAP_HEADERCACHE *hc, IMAP_HEADER *h) ++{ ++ FILE *f = NULL; ++ unsigned int flag_read, flag_old, flag_deleted, flag_flagged, flag_replied; ++ unsigned int flag_changed; ++ unsigned int uid; ++ unsigned long received; ++ unsigned long content_length; ++ ++ sprintf(hc->tmpname, "%s/%u", hc->name, HEADER_DATA(h)->uid); ++ ++ f = fopen(hc->tmpname, "r"); ++ if (!f) ++ goto bail; ++ ++ fscanf(f, "%x %x %x %x %x %x %x %lx %lx %x\n", ++ &flag_read, &flag_old, &flag_deleted, &flag_flagged, &flag_replied, ++ &flag_changed, &h->sid, &received, &content_length, &uid); ++ ++ if (uid != HEADER_DATA(h)->uid) ++ { ++ fclose(f); ++ f = NULL; ++ goto bail; ++ } ++ ++ h->received = received; ++ h->read = flag_read; ++ h->old = flag_old; ++ h->deleted = flag_deleted; ++ h->flagged = flag_flagged; ++ h->replied = flag_replied; ++ h->changed = flag_changed; ++ h->content_length = (long)content_length; ++ ++bail: ++ return f; ++} ++ ++/* Close file returned by imap_headercache_find */ ++void imap_headercache_done(IMAP_HEADERCACHE *hc, FILE *f) ++{ ++ fclose(f); ++} ++ +diff -ruN old/imap/imap_headercache.h work/mutt-1.5.5.1/imap/imap_headercache.h +--- old/imap/imap_headercache.h Thu Jan 1 01:00:00 1970 ++++ imap/imap_headercache.h Fri Nov 28 18:30:55 2003 +@@ -0,0 +1,47 @@ ++/* ++ * Copyright (C) 2002 Tudor Bosman <tudorb-mutt@dwyn.net> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. ++ */ ++ ++#ifndef _IMAP_HEADERCACHE_H ++#define _IMAP_HEADERCACHE_H ++#include "imap_private.h" ++#include "message.h" ++ ++typedef struct IMAP_HEADERCACHE ++{ ++ char *name; ++ char *tmpname; ++ unsigned int uidvalidity; ++ int exists; ++} IMAP_HEADERCACHE; ++ ++struct IMAP_DATA; ++ ++IMAP_HEADERCACHE *imap_headercache_open(struct IMAP_DATA *idata); ++ ++void imap_headercache_close(IMAP_HEADERCACHE *hc); ++ ++int imap_headercache_add(IMAP_HEADERCACHE *hc, IMAP_HEADER *h, FILE *from, ++ size_t hdrsz); ++int imap_headercache_update(IMAP_HEADERCACHE *hc, IMAP_HEADER *h); ++int imap_headercache_delete(IMAP_HEADERCACHE *hc, IMAP_HEADER *h); ++ ++FILE *imap_headercache_find(IMAP_HEADERCACHE *hc, IMAP_HEADER *h); ++void imap_headercache_done(IMAP_HEADERCACHE *hc, FILE *f); ++ ++#endif ++ |