summaryrefslogtreecommitdiff
path: root/mail/mutt-devel
diff options
context:
space:
mode:
authorKirill Ponomarev <krion@FreeBSD.org>2004-08-18 18:02:36 +0000
committerKirill Ponomarev <krion@FreeBSD.org>2004-08-18 18:02:36 +0000
commit0ab5af4b92d71d93251666a7716be6959a9b4d1b (patch)
treeb1a37d81e54a5d0fdcc6cfaedd22eb35f5aa406e /mail/mutt-devel
parentUpdate to 2.0.1. (diff)
Update the maildir header cache patch, which now also
implements the IMAP header cache. This is far more stable than the old IMAP header cache patch. PR: ports/70623 Submitted by: maintainer
Notes
Notes: svn path=/head/; revision=116612
Diffstat (limited to 'mail/mutt-devel')
-rw-r--r--mail/mutt-devel/Makefile42
-rw-r--r--mail/mutt-devel/files/extra-patch-imap-header-cache877
-rw-r--r--mail/mutt-devel/files/extra-patch-maildir-header-cache703
-rw-r--r--mail/mutt-devel/scripts/generate-plist3
4 files changed, 565 insertions, 1060 deletions
diff --git a/mail/mutt-devel/Makefile b/mail/mutt-devel/Makefile
index a9215374b9fd..9b64be2a7951 100644
--- a/mail/mutt-devel/Makefile
+++ b/mail/mutt-devel/Makefile
@@ -44,10 +44,7 @@
# WITH_MUTT_QUOTE_PATCH
# This is a default knob and can be disabled by WITHOUT_MUTT_QUOTE_PATCH
#
-# If you want to have the IMAP header cache define:
-# WITH_MUTT_IMAP_HEADER_CACHE
-#
-# If you want to have the Maildir header cache define:
+# If you want to have the Maildir/IMAP header cache define:
# WITH_MUTT_MAILDIR_HEADER_CACHE
#
# If you want to make SMIME outlook compatible define:
@@ -84,7 +81,7 @@
PORTNAME= mutt-devel
PORTVERSION= 1.5.6
-PORTREVISION= 7
+PORTREVISION= 8
CATEGORIES+= mail ipv6
.if defined(WITH_MUTT_NNTP)
CATEGORIES+= news
@@ -151,6 +148,9 @@ DW_PATCH_VERSION= ${PORTVERSION}
.if !defined(DW_MBOX_PATCH_VERSION)
DW_MBOX_PATCH_VERSION= ${DW_PATCH_VERSION}
.endif
+.if defined(WITH_MUTT_IMAP_HEADER_CACHE)
+WITH_MUTT_MAILDIR_HEADER_CACHE= yes
+.endif
# XXX
# this should be done automagically by aclocal but ....
@@ -215,13 +215,9 @@ CFLAGS+= -I${PREFIX}/include/db42
pre-configure::
@${PATCH} ${PATCH_ARGS} < ${PATCHDIR}/extra-patch-smime-outlook
.endif
-.if defined(WITH_MUTT_IMAP_HEADER_CACHE)
-pre-configure::
- @${PATCH} ${PATCH_ARGS} < ${PATCHDIR}/extra-patch-imap-header-cache
-.endif
.if defined(WITH_MUTT_MAILDIR_HEADER_CACHE)
pre-configure::
- @${PATCH} ${PATCH_ARGS} < ${PATCHDIR}/extra-patch-maildir-header-cache
+ @${PATCH} ${PATCH_ARGS} -p1 < ${PATCHDIR}/extra-patch-maildir-header-cache
.endif
.if defined(WITH_MUTT_MAILDIR_MTIME_PATCH)
pre-configure::
@@ -323,9 +319,6 @@ SCRIPTS_ENV+= MUTT_COMPRESSED_FOLDERS="yes"
.if ! defined(WITHOUT_MUTT_QUOTE_PATCH)
SCRIPTS_ENV+= MUTT_QUOTE_PATCH="yes"
.endif
-.if defined(WITH_MUTT_IMAP_HEADER_CACHE)
-SCRIPTS_ENV+= MUTT_IMAP_HEADER_CACHE="yes"
-.endif
.if defined(WITH_MUTT_MAILDIR_HEADER_CACHE)
SCRIPTS_ENV+= MUTT_MAILDIR_HEADER_CACHE="yes"
CONFIGURE_ARGS+= --enable-hcache
@@ -403,33 +396,14 @@ post-install:
.endif
.endif
.if defined(MUTT_USES_SLANG)
- @${ECHO} "====================================================" >> ${PKGMESSAGE}
+ @${ECHO} "=====================================================" >> ${PKGMESSAGE}
@${ECHO} "You have installed ${PORTNAME} with SLANG support." >> ${PKGMESSAGE}
@${ECHO} "This may work for a color terminal only when defining" >> ${PKGMESSAGE}
@${ECHO} "COLORTERM=yes and COLORFGBG=color,color in your" >> ${PKGMESSAGE}
@${ECHO} "environment." >> ${PKGMESSAGE}
- @${ECHO} "====================================================" >> ${PKGMESSAGE}
-.endif
-.if defined(WITH_MUTT_IMAP_HEADER_CACHE)
- @${ECHO} "====================================================" >> ${PKGMESSAGE}
- @${ECHO} "You have installed ${PORTNAME} with the IMAP header cache enabled." >> ${PKGMESSAGE}
- @${ECHO} "Please be aware that this - at the moment - could result in" >> ${PKGMESSAGE}
- @${ECHO} "incorrect display of message flags if there is another client" >> ${PKGMESSAGE}
- @${ECHO} "simultaneously using the same mailbox." >> ${PKGMESSAGE}
- @${ECHO} "====================================================" >> ${PKGMESSAGE}
-.endif
-.if defined(WITH_MUTT_MAILDIR_HEADER_CACHE) && defined(WITH_MUTT_MAILDIR_MTIME_PATCH)
- @${ECHO} "====================================================" >> ${PKGMESSAGE}
- @${ECHO} "You have installed ${PORTNAME} with the Maildir header" >> ${PKGMESSAGE}
- @${ECHO} "cache and the MAILDIR_MTIME_PATCH enabled." >> ${PKGMESSAGE}
- @${ECHO} >> ${PKGMESSAGE}
- @${ECHO} "For this to work you may have to delete your old" >> ${PKGMESSAGE}
- @${ECHO} "Maildir header cache or otherwise you may face" >> ${PKGMESSAGE}
- @${ECHO} "an \"Out of memory\" error." >> ${PKGMESSAGE}
- @${ECHO} "====================================================" >> ${PKGMESSAGE}
+ @${ECHO} "=====================================================" >> ${PKGMESSAGE}
.endif
.if !defined(BATCH)
- @${ECHO}
@${CAT} ${PKGMESSAGE}
@${ECHO}
.endif
diff --git a/mail/mutt-devel/files/extra-patch-imap-header-cache b/mail/mutt-devel/files/extra-patch-imap-header-cache
deleted file mode 100644
index 221a5d439109..000000000000
--- a/mail/mutt-devel/files/extra-patch-imap-header-cache
+++ /dev/null
@@ -1,877 +0,0 @@
-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
-+
---- PATCHES.orig Tue Nov 6 19:59:33 2001
-+++ PATCHES Tue Nov 6 19:59:42 2001
-@@ -1,0 +1 @@
-+imap-header-cache.1
diff --git a/mail/mutt-devel/files/extra-patch-maildir-header-cache b/mail/mutt-devel/files/extra-patch-maildir-header-cache
index 170d52e44c10..807b3f21b466 100644
--- a/mail/mutt-devel/files/extra-patch-maildir-header-cache
+++ b/mail/mutt-devel/files/extra-patch-maildir-header-cache
@@ -1,20 +1,21 @@
---- Makefile.am.orig Fri Mar 5 15:34:57 2004
-+++ Makefile.am Fri Mar 5 15:35:55 2004
+diff -Nru a/Makefile.am b/Makefile.am
+--- a/Makefile.am 2004-08-18 10:08:12 +02:00
++++ b/Makefile.am 2004-08-18 10:08:12 +02:00
@@ -20,2 +20,3 @@
mutt_SOURCES = $(BUILT_SOURCES) \
+ hcache.c \
addrbook.c alias.c attach.c base64.c browser.c buffy.c color.c \
diff -Nru a/configure.in b/configure.in
---- configure.in.orig Sat Jun 12 09:49:17 2004
-+++ configure.in Sat Jun 12 09:50:18 2004
-@@ -773,6 +773,80 @@
+--- a/configure.in 2004-08-18 10:08:12 +02:00
++++ b/configure.in 2004-08-18 10:08:12 +02:00
+@@ -768,6 +768,80 @@
fi])
+dnl -- start cache --
-+AC_ARG_ENABLE(hcache, [ --enable-hcache Enable header caching for Maildir folders],
++AC_ARG_ENABLE(hcache, [ --enable-hcache Enable header caching],
+[if test x$enableval = xyes; then
-+ AC_DEFINE(USE_HCACHE, 1, [Enable header caching for Maildir style mailboxes])
++ AC_DEFINE(USE_HCACHE, 1, [Enable header caching])
+
+ OLDCPPFLAGS="$CPPFLAGS"
+ OLDLIBS="$LIBS"
@@ -44,17 +45,17 @@ diff -Nru a/configure.in b/configure.in
+ for v in `echo $BDB_VERSIONS`; do
+ CPPFLAGS="$OLDCPPFLAGS -I$BDB_INCLUDE_DIR"
+ LIBS="$OLDLIBS -L$BDB_LIB_DIR -l$v"
-+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
-+ #include <stdlib.h>
++ AC_TRY_LINK([
++ #include <stdlib.h>
+ #include <db.h>
-+ ]],[[
++ ],[
+ DB *db = NULL;
+ db->open(db,NULL,NULL,NULL,0,0,0);
-+ ]])],[
++ ],[
+ ac_cv_dbcreate=yes
+ BDB_LIB="$v"
+ break
-+ ])
++ ])
+ done
+ test x$BDB_LIB != x && break
+ done
@@ -89,25 +90,26 @@ diff -Nru a/configure.in b/configure.in
AC_SUBST(MUTT_LIB_OBJECTS)
AC_SUBST(LIBIMAP)
diff -Nru a/globals.h b/globals.h
---- globals.h 2004-06-10 14:03:44 +02:00
-+++ globals.h 2004-06-10 14:03:44 +02:00
+--- a/globals.h 2004-08-18 10:08:12 +02:00
++++ b/globals.h 2004-08-18 10:08:12 +02:00
@@ -63,6 +63,10 @@
WHERE char *Locale;
WHERE char *MailcapPath;
WHERE char *Maildir;
+#if USE_HCACHE
-+WHERE char *MaildirCache;
-+WHERE short MaildirCachePageSize;
++WHERE char *HeaderCache;
++WHERE short HeaderCachePageSize;
+#endif
WHERE char *MhFlagged;
WHERE char *MhReplied;
WHERE char *MhUnseen;
diff -Nru a/hcache.c b/hcache.c
---- hcache.c.orig Sat Jun 12 09:52:31 2004
-+++ hcache.c Sat Jun 12 09:52:56 2004
-@@ -0,0 +1,676 @@
+--- /dev/null Wed Dec 31 16:00:00 196900
++++ b/hcache.c 2004-08-18 10:08:12 +02:00
+@@ -0,0 +1,794 @@
+/*
+ * Copyright (C) 2004 Thomas Glanzmann <sithglan@stud.uni-erlangen.de>
++ * Copyright (C) 2004 Tobias Werth <sitowert@stud.uni-erlangen.de>
+ * Copyright (C) 2004 Brian Fundakowski Feldman <green@FreeBSD.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
@@ -138,10 +140,39 @@ diff -Nru a/hcache.c b/hcache.c
+#include <errno.h>
+#include <fcntl.h>
+#include "mutt.h"
++#ifdef USE_IMAP
++#include "message.h"
++#endif
+#include "mime.h"
+#include "mx.h"
+#include "lib.h"
+
++#if HAVE_GDBM
++static struct
++header_cache
++{
++ GDBM_FILE db;
++ char *folder;
++ unsigned int crc;
++} HEADER_CACHE;
++#elif HAVE_DB4
++static struct
++header_cache
++{
++ DB_ENV *env;
++ DB *db;
++ unsigned int crc;
++ int fd;
++ char lockfile[_POSIX_PATH_MAX];
++} HEADER_CACHE;
++#endif
++
++typedef union
++{
++ struct timeval timeval;
++ unsigned long long uid_validity;
++} validate;
++
+static unsigned char *
+dump_int(unsigned int i, unsigned char *d, int *off)
+{
@@ -170,7 +201,24 @@ diff -Nru a/hcache.c b/hcache.c
+ return d;
+ }
+
-+ size = strlen(c) + 1;
++ size = mutt_strlen(c) + 1;
++ d = dump_int(size, d, off);
++ safe_realloc(&d, *off + size);
++ memcpy(d + *off, c, size);
++ *off += size;
++
++ return d;
++}
++
++static unsigned char *
++dump_char_size(char *c, unsigned char *d, int *off, ssize_t size)
++{
++ if (c == NULL) {
++ size = 0;
++ d = dump_int(size, d, off);
++ return d;
++ }
++
+ d = dump_int(size, d, off);
+ safe_realloc(&d, *off + size);
+ memcpy(d + *off, c, size);
@@ -195,14 +243,6 @@ diff -Nru a/hcache.c b/hcache.c
+ *off += size;
+}
+
-+static void
-+skip_char(const unsigned char *d, int *off)
-+{
-+ unsigned int size;
-+ restore_int(&size, d, off);
-+ *off += size;
-+}
-+
+static unsigned char *
+dump_address(ADDRESS *a, unsigned char *d, int *off)
+{
@@ -247,7 +287,6 @@ diff -Nru a/hcache.c b/hcache.c
+ }
+
+ *a = NULL;
-+ return;
+}
+
+static unsigned char *
@@ -284,7 +323,43 @@ diff -Nru a/hcache.c b/hcache.c
+ }
+
+ *l = NULL;
-+ return;
++}
++
++static unsigned char *
++dump_buffer(BUFFER *b, unsigned char *d, int *off)
++{
++ if (! b) {
++ d = dump_int(0, d, off);
++ return d;
++ } else {
++ d = dump_int(1, d, off);
++ }
++
++ d = dump_char_size(b->data, d, off, b->dsize + 1);
++ d = dump_int(b->dptr - b->data, d, off);
++ d = dump_int(b->dsize, d, off);
++ d = dump_int(b->destroy, d, off);
++
++ return d;
++}
++
++static void
++restore_buffer(BUFFER **b, const unsigned char *d, int *off)
++{
++ unsigned int used;
++ unsigned int offset;
++ restore_int(&used, d, off);
++ if (! used) {
++ return;
++ }
++
++ *b = safe_malloc(sizeof(BUFFER));
++
++ restore_char(& (*b)->data, d, off);
++ restore_int(& offset, d, off);
++ (*b)->dptr = (*b)->data + offset;
++ restore_int(& (*b)->dsize, d, off);
++ restore_int((unsigned int *) & (*b)->destroy, d, off);
+}
+
+static unsigned char *
@@ -323,7 +398,6 @@ diff -Nru a/hcache.c b/hcache.c
+ }
+
+ *p = NULL;
-+ return;
+}
+
+static unsigned char *
@@ -408,7 +482,7 @@ diff -Nru a/hcache.c b/hcache.c
+ restore_address(& e->mail_followup_to, d, off);
+
+ restore_char(& e->subject, d, off);
-+ restore_int(& real_subj_off, d, off);
++ restore_int((unsigned int *) (& real_subj_off), d, off);
+ if (0 <= real_subj_off) {
+ e->real_subj = e->subject + real_subj_off;
+ } else {
@@ -424,42 +498,72 @@ diff -Nru a/hcache.c b/hcache.c
+ restore_list(& e->userhdrs, d, off);
+}
+
++static
++unsigned int crc32(unsigned int crc, unsigned char const *p, size_t len)
++{
++ int i;
++ while (len--) {
++ crc ^= *p++;
++ for (i = 0; i < 8; i++)
++ crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
++ }
++ return crc;
++}
+
-+/* This function transforms a header into a char so that it is useable by
-+ * gdbm_store */
++static int
++generate_crc32()
++{
++ int crc = 0;
++
++ crc = crc32(crc, (unsigned char const *) "HCACHE V1", mutt_strlen("HCACHE V1"));
+
+#if HAVE_LANGINFO_CODESET
-+int
-+mutt_hcache_charset_matches(const char *d)
++ crc = crc32(crc, (unsigned char const *) Charset, mutt_strlen(Charset));
++ crc = crc32(crc, (unsigned char const *) "HAVE_LANGINFO_CODESET", mutt_strlen("HAVE_LANGINFO_CODESET"));
++#endif
++
++#if EXACT_ADDRESS
++ crc = crc32(crc, (unsigned char const *) "EXACT_ADDRESS", mutt_strlen("EXACT_ADDRESS"));
++#endif
++ return crc;
++}
++
++static int
++crc32_matches(const char *d, unsigned int crc)
+{
-+ int matches;
-+ int off = sizeof(struct timeval);
-+ char *charset = NULL;
++ int off = sizeof(validate);
++ unsigned int mycrc = 0;
++
++ if (! d) {
++ return 0;
++ }
+
-+ restore_char(&charset, (unsigned char *) d, &off);
-+ matches = (0 == mutt_strcmp(charset, Charset));
-+ FREE(&charset);
++ restore_int(&mycrc, (unsigned char *) d, &off);
+
-+ return (matches);
++ return (crc == mycrc);
+}
-+#endif /* HAVE_LANGINFO_CODESET */
+
++/* This function transforms a header into a char so that it is useable by
++ * db_store */
+static void *
-+mutt_hcache_dump(HEADER *h, int *off)
++mutt_hcache_dump(void *_db, HEADER *h, int *off, unsigned long long uid_validity)
+{
++ struct header_cache *db = _db;
+ unsigned char *d = NULL;
-+ struct timeval now;
+ *off = 0;
+
-+ d = safe_malloc(sizeof(struct timeval));
-+ gettimeofday(&now, NULL);
-+ memcpy(d, &now, sizeof(struct timeval));
-+ *off += sizeof(struct timeval);
++ d = safe_malloc(sizeof(validate));
+
-+#if HAVE_LANGINFO_CODESET
-+ d = dump_char(Charset, d, off);
-+#endif /* HAVE_LANGINFO_CODESET */
++ if (uid_validity) {
++ memcpy(d, &uid_validity, sizeof(long long));
++ } else {
++ struct timeval now;
++ gettimeofday(&now, NULL);
++ memcpy(d, &now, sizeof(struct timeval));
++ }
++ *off += sizeof(validate);
+
++ d = dump_int(db->crc, d, off);
+
+ safe_realloc(&d, *off + sizeof(HEADER));
+ memcpy(d + *off, h, sizeof(HEADER));
@@ -478,12 +582,11 @@ diff -Nru a/hcache.c b/hcache.c
+ int off = 0;
+ HEADER *h = mutt_new_header();
+
-+ /* skip timeval */
-+ off += sizeof(struct timeval);
++ /* skip validate */
++ off += sizeof(validate);
+
-+#if HAVE_LANGINFO_CODESET
-+ skip_char(d, &off);
-+#endif /* HAVE_LANGINFO_CODESET */
++ /* skip crc */
++ off += sizeof(unsigned int);
+
+ memcpy(h, d + off, sizeof(HEADER));
+ off += sizeof(HEADER);
@@ -496,45 +599,39 @@ diff -Nru a/hcache.c b/hcache.c
+
+ restore_char(&h->maildir_flags, d, &off);
+
-+ h->old = (*oh)->old;
-+ h->path = safe_strdup((*oh)->path);
-+ mutt_free_header (oh);
++ /* this is needed for maildir style mailboxes */
++ if (oh) {
++ h->old = (*oh)->old;
++ h->path = safe_strdup((*oh)->path);
++ mutt_free_header (oh);
++ }
+
+ return h;
+}
+
-+static size_t mutt_hcache_keylen (const char *fn)
-+{
-+ const char * p = strchr (fn, ':');
-+ return p ? (size_t) (p - fn) : strlen (fn);
-+}
-+
+#if HAVE_GDBM
-+static struct
-+header_cache
-+{
-+ GDBM_FILE db;
-+ char *folder;
-+} HEADER_CACHE;
+
+void *
+mutt_hcache_open(const char *path, const char *folder)
+{
-+ struct header_cache *h = malloc(sizeof(HEADER_CACHE));
++ struct header_cache *h = safe_calloc(1, sizeof(HEADER_CACHE));
+ h->db = NULL;
+ h->folder = safe_strdup (folder);
++ h->crc = generate_crc32();
+
+ if (! path || path[0] == '\0') {
++ FREE(& h->folder);
++ FREE(& h);
+ return NULL;
+ }
+
-+ h->db = gdbm_open((char *) path, (int) MaildirCachePageSize, GDBM_WRCREAT, 00600, NULL);
++ h->db = gdbm_open((char *) path, (int) HeaderCachePageSize, GDBM_WRCREAT, 00600, NULL);
+ if (h->db) {
+ return h;
+ }
+
+ /* if rw failed try ro */
-+ h->db = gdbm_open((char *) path, (int) MaildirCachePageSize, GDBM_READER, 00600, NULL);
++ h->db = gdbm_open((char *) path, (int) HeaderCachePageSize, GDBM_READER, 00600, NULL);
+ if(h->db) {
+ return h;
+ } else {
@@ -560,7 +657,7 @@ diff -Nru a/hcache.c b/hcache.c
+}
+
+void *
-+mutt_hcache_fetch(void *db, const char *filename)
++mutt_hcache_fetch(void *db, const char *filename, size_t (*keylen)(const char *fn))
+{
+ struct header_cache *h = db;
+ datum key;
@@ -572,18 +669,23 @@ diff -Nru a/hcache.c b/hcache.c
+ }
+
+ strncpy(path, h->folder, sizeof(path));
-+ strncat(path, filename, sizeof(path) - strlen(path));
++ strncat(path, filename, sizeof(path) - mutt_strlen(path));
+
+ key.dptr = path;
-+ key.dsize = mutt_hcache_keylen(path);
++ key.dsize = keylen(path);
+
+ data = gdbm_fetch(h->db, key);
+
++ if (! crc32_matches(data.dptr, h->crc)) {
++ free(data.dptr);
++ return NULL;
++ }
++
+ return data.dptr;
+}
+
+int
-+mutt_hcache_store(void *db, const char *filename, HEADER *header)
++mutt_hcache_store(void *db, const char *filename, HEADER *header, unsigned long long uid_validity, size_t (*keylen)(const char *fn))
+{
+ struct header_cache *h = db;
+ datum key;
@@ -596,12 +698,12 @@ diff -Nru a/hcache.c b/hcache.c
+ }
+
+ strncpy(path, h->folder, sizeof(path));
-+ strncat(path, filename, sizeof(path) - strlen(path));
++ strncat(path, filename, sizeof(path) - mutt_strlen(path));
+
+ key.dptr = path;
-+ key.dsize = mutt_hcache_keylen(path);
++ key.dsize = keylen(path);
+
-+ data.dptr = mutt_hcache_dump(header, &data.dsize);
++ data.dptr = mutt_hcache_dump(db, header, &data.dsize, uid_validity);
+
+ ret = gdbm_store(h->db, key, data, GDBM_REPLACE);
+
@@ -611,7 +713,7 @@ diff -Nru a/hcache.c b/hcache.c
+}
+
+int
-+mutt_hcache_delete(void *db, const char *filename)
++mutt_hcache_delete(void *db, const char *filename, size_t (*keylen)(const char *fn))
+{
+ datum key;
+ struct header_cache *h = db;
@@ -622,22 +724,15 @@ diff -Nru a/hcache.c b/hcache.c
+ }
+
+ strncpy(path, h->folder, sizeof(path));
-+ strncat(path, filename, sizeof(path) - strlen(path));
++ strncat(path, filename, sizeof(path) - mutt_strlen(path));
+
+ key.dptr = path;
-+ key.dsize = mutt_hcache_keylen(path);
++ key.dsize = keylen(path);
+
+ return gdbm_delete(h->db, key);
+}
+#elif HAVE_DB4
+
-+static struct
-+header_cache
-+{
-+ DB_ENV *env;
-+ DB *db;
-+} HEADER_CACHE;
-+
+static void
+mutt_hcache_dbt_init(DBT *dbt, void *data, size_t len)
+{
@@ -661,15 +756,32 @@ diff -Nru a/hcache.c b/hcache.c
+ struct stat sb;
+ u_int32_t createflags = DB_CREATE;
+ int ret;
-+ struct header_cache *h = malloc(sizeof(HEADER_CACHE));
++ struct header_cache *h = calloc(1, sizeof(HEADER_CACHE));
++
++ h->crc = generate_crc32();
+
+ if (! path || path[0] == '\0') {
+ FREE(& h);
+ return NULL;
+ }
+
++ snprintf (h->lockfile, _POSIX_PATH_MAX, "%s-lock-hack", path);
++
++ h->fd = open(h->lockfile, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
++ if (h->fd < 0) {
++ FREE (&h);
++ return NULL;
++ }
++
++ if (mx_lock_file(h->lockfile, h->fd, 1, 0, 5)) {
++ close(h->fd);
++ FREE (&h);
++ return NULL;
++ }
++
+ ret = db_env_create(&h->env, 0);
+ if (ret) {
++ mx_unlock_file(h->lockfile, h->fd, 0);
+ FREE(& h);
+ return NULL;
+ }
@@ -679,6 +791,7 @@ diff -Nru a/hcache.c b/hcache.c
+ ret = db_create(&h->db, h->env, 0);
+ if (ret) {
+ h->env->close(h->env, 0);
++ mx_unlock_file(h->lockfile, h->fd, 0);
+ FREE(& h);
+ return NULL;
+ }
@@ -686,13 +799,14 @@ diff -Nru a/hcache.c b/hcache.c
+
+ if (stat(path, &sb) != 0 && errno == ENOENT) {
+ createflags |= DB_EXCL;
-+ h->db->set_pagesize(h->db, (int) MaildirCachePageSize);
++ h->db->set_pagesize(h->db, (int) HeaderCachePageSize);
+ }
+
+ ret = h->db->open(h->db, NULL, path, folder, DB_BTREE, createflags, 0600);
+ if (ret) {
+ h->db->close(h->db, 0);
+ h->env->close(h->env, 0);
++ mx_unlock_file(h->lockfile, h->fd, 0);
+ FREE(& h);
+ return NULL;
+ }
@@ -712,12 +826,12 @@ diff -Nru a/hcache.c b/hcache.c
+
+ h->db->close(h->db, 0);
+ h->env->close(h->env, 0);
-+
++ mx_unlock_file(h->lockfile, h->fd, 0);
+ FREE(& h);
+}
+
+void *
-+mutt_hcache_fetch(void *db, const char *filename)
++mutt_hcache_fetch(void *db, const char *filename, size_t (*keylen)(const char *fn))
+{
+ DBT key;
+ DBT data;
@@ -729,17 +843,22 @@ diff -Nru a/hcache.c b/hcache.c
+
+ filename++; /* skip '/' */
+
-+ mutt_hcache_dbt_init(&key, (void *) filename, mutt_hcache_keylen(filename));
++ mutt_hcache_dbt_init(&key, (void *) filename, keylen(filename));
+ mutt_hcache_dbt_empty_init(&data);
+ data.flags = DB_DBT_MALLOC;
+
+ h->db->get(h->db, NULL, &key, &data, 0);
+
++ if (! crc32_matches(data.data, h->crc)) {
++ free(data.data);
++ return NULL;
++ }
++
+ return data.data;
+}
+
+int
-+mutt_hcache_store(void *db, const char *filename, HEADER *header)
++mutt_hcache_store(void *db, const char *filename, HEADER *header, unsigned long long uid_validity, size_t (*keylen)(const char *fn))
+{
+ DBT key;
+ DBT data;
@@ -752,11 +871,11 @@ diff -Nru a/hcache.c b/hcache.c
+
+ filename++; /* skip '/' */
+
-+ mutt_hcache_dbt_init(&key, (void *) filename, mutt_hcache_keylen(filename));
++ mutt_hcache_dbt_init(&key, (void *) filename, keylen(filename));
+
+ mutt_hcache_dbt_empty_init(&data);
+ data.flags = DB_DBT_USERMEM;
-+ data.data = mutt_hcache_dump(header, (signed int *) &data.size);
++ data.data = mutt_hcache_dump(db, header, (signed int *) &data.size, uid_validity);
+ data.ulen = data.size;
+
+ ret = h->db->put(h->db, NULL, &key, &data, 0);
@@ -767,7 +886,7 @@ diff -Nru a/hcache.c b/hcache.c
+}
+
+int
-+mutt_hcache_delete(void *db, const char *filename)
++mutt_hcache_delete(void *db, const char *filename, size_t (*keylen)(const char *fn))
+{
+ DBT key;
+ struct header_cache *h = db;
@@ -778,31 +897,323 @@ diff -Nru a/hcache.c b/hcache.c
+
+ filename++; /* skip '/' */
+
-+ mutt_hcache_dbt_init(&key, (void *) filename, mutt_hcache_keylen(filename));
++ mutt_hcache_dbt_init(&key, (void *) filename, keylen(filename));
+ return h->db->del(h->db, NULL, &key, 0);
+}
+#endif
+diff -Nru a/imap/imap.c b/imap/imap.c
+--- a/imap/imap.c 2004-08-18 10:08:12 +02:00
++++ b/imap/imap.c 2004-08-18 10:08:12 +02:00
+@@ -602,6 +602,17 @@
+ if ((pc = imap_get_flags (&(idata->flags), pc)) == NULL)
+ goto fail;
+ }
++#ifdef USE_HCACHE
++ /* 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->uid_validity));
++ }
++#endif
+ else
+ {
+ pc = imap_next_word (pc);
+diff -Nru a/imap/imap_private.h b/imap/imap_private.h
+--- a/imap/imap_private.h 2004-08-18 10:08:12 +02:00
++++ b/imap/imap_private.h 2004-08-18 10:08:12 +02:00
+@@ -179,6 +179,9 @@
+ unsigned int newMailCount;
+ IMAP_CACHE cache[IMAP_CACHE_LEN];
+ int noclose : 1;
++#ifdef USE_HCACHE
++ unsigned long long uid_validity;
++#endif
+
+ /* all folder flags - system flags AND keywords */
+ LIST *flags;
+diff -Nru a/imap/message.c b/imap/message.c
+--- a/imap/message.c 2004-08-18 10:08:12 +02:00
++++ b/imap/message.c 2004-08-18 10:08:12 +02:00
+@@ -39,6 +39,12 @@
+ 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 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 @@
+ { /* 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 @@
+ {
+ 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,88 @@
+ 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)));
++ }
++
++ 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 +208,9 @@
+ */
+ 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 +264,11 @@
+ /* 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 +278,9 @@
+ {
+ imap_free_header_data ((void**) &h.data);
+ fclose (fp);
+-
++#if USE_HCACHE
++ mutt_hcache_close (hc);
++#endif /* USE_HCACHE */
+ return -1;
+ }
+
+@@ -194,6 +295,10 @@
+ }
+ }
+
++#if USE_HCACHE
++ mutt_hcache_close (hc);
++#endif /* USE_HCACHE */
++
+ fclose(fp);
+
+ if (ctx->msgcount > oldmsgcount)
+@@ -724,6 +829,7 @@
+ return s;
+ }
+
++
+ /* msg_fetch_header: import IMAP FETCH response into an IMAP_HEADER.
+ * Expects string beginning with * n FETCH.
+ * Returns:
+@@ -782,6 +888,56 @@
+
+ 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 */
diff -Nru a/init.h b/init.h
---- init.h 2004-06-10 14:03:44 +02:00
-+++ init.h 2004-06-10 14:03:44 +02:00
-@@ -981,6 +981,28 @@
+--- a/init.h 2004-08-18 10:08:12 +02:00
++++ b/init.h 2004-08-18 10:08:12 +02:00
+@@ -981,6 +981,30 @@
** \fBDON'T CHANGE THIS SETTING UNLESS YOU ARE REALLY SURE WHAT YOU ARE
** DOING!\fP
*/
+#if USE_HCACHE
-+ { "maildir_cache", DT_PATH, R_NONE, UL &MaildirCache, 0 },
++
++ { "header_cache", DT_PATH, R_NONE, UL &HeaderCache, 0 },
+ /*
+ ** .pp
-+ ** Path to the maildir cache file. If unset no cache will be used.
++ ** Path to the header cache file. If unset no cache will be used. Otherwise
++ ** the cache will be enabled for Maildir and IMAP mailboxes.
+ */
-+ { "maildir_cache_verify", DT_BOOL, R_NONE, OPTHCACHEVERIFY, 1 },
++ { "maildir_header_cache_verify", DT_BOOL, R_NONE, OPTHCACHEVERIFY, 1 },
+ /*
+ ** .pp
-+ ** Check for programs other than mutt having modified maildir
-+ ** files when the header cache is in use. This incurs one stat(2)
-+ ** per message every time the folder is opened.
++ ** Check for Maildir unaware programs other than mutt having modified maildir
++ ** files when the header cache is in use. This incurs one stat(2) per
++ ** message every time the folder is opened.
+ */
-+ { "maildir_cache_page_size", DT_NUM, R_NONE, UL &MaildirCachePageSize, 16384 },
++ { "header_cache_pagesize", DT_NUM, R_NONE, UL &HeaderCachePageSize, 16384 },
+ /*
+ ** .pp
+ ** Change the maildir header cache database page size. Too large
@@ -815,8 +1226,8 @@ diff -Nru a/init.h b/init.h
/*
** .pp
diff -Nru a/main.c b/main.c
---- main.c 2004-06-10 14:03:44 +02:00
-+++ main.c 2004-06-10 14:03:44 +02:00
+--- a/main.c 2004-08-18 10:08:12 +02:00
++++ b/main.c 2004-08-18 10:08:12 +02:00
@@ -411,6 +411,12 @@
"-HAVE_GETADDRINFO "
#endif
@@ -831,13 +1242,20 @@ diff -Nru a/main.c b/main.c
#ifdef ISPELL
diff -Nru a/mh.c b/mh.c
---- mh.c 2004-06-10 14:03:44 +02:00
-+++ mh.c 2004-06-10 14:03:44 +02:00
-@@ -779,11 +779,65 @@
+--- a/mh.c 2004-08-18 10:08:12 +02:00
++++ b/mh.c 2004-08-18 10:08:12 +02:00
+@@ -779,11 +779,68 @@
return r;
}
+#if USE_HCACHE
++
++static size_t maildir_hcache_keylen (const char *fn)
++{
++ const char * p = strchr (fn, ':');
++ return p ? (size_t) (p - fn) : mutt_strlen(fn);
++}
++
/*
* This function does the second parsing pass for a maildir-style
@@ -854,14 +1272,14 @@ diff -Nru a/mh.c b/mh.c
+ struct stat lastchanged;
+ int ret;
+
-+ hc = mutt_hcache_open (MaildirCache, ctx->path);
++ hc = mutt_hcache_open (HeaderCache, ctx->path);
+
+ for (p = md; p; p = p->next) {
+ if (! (p && p->h && !p->header_parsed)) {
+ continue;
+ }
+
-+ data = mutt_hcache_fetch (hc, p->h->path + 3);
++ data = mutt_hcache_fetch (hc, p->h->path + 3, &maildir_hcache_keylen);
+ when = (struct timeval *) data;
+
+ snprintf(fn, sizeof (fn), "%s/%s", ctx->path, p->h->path);
@@ -875,18 +1293,14 @@ diff -Nru a/mh.c b/mh.c
+
+ if (data != NULL
+ && ret == 0
-+ && lastchanged.st_mtime <= when->tv_sec
-+#if HAVE_LANGINFO_CODESET
-+ && mutt_hcache_charset_matches (data)
-+#endif /* HAVE_LANGINFO_CODESET */
-+ ) {
++ && lastchanged.st_mtime <= when->tv_sec) {
+ p->h = mutt_hcache_restore ((unsigned char *)data, &p->h);
+ maildir_parse_flags (p->h, fn);
+
+ } else if (maildir_parse_message (ctx->magic, fn, p->h->old, p->h)) {
+ maildir_parse_flags(p->h, fn);
+ p->header_parsed = 1;
-+ mutt_hcache_store (hc, p->h->path + 3, p->h);
++ mutt_hcache_store (hc, p->h->path + 3, p->h, 0, &maildir_hcache_keylen);
+ } else {
+ mutt_free_header (&p->h);
+ }
@@ -899,7 +1313,7 @@ diff -Nru a/mh.c b/mh.c
void maildir_delayed_parsing (CONTEXT * ctx, struct maildir *md)
{
-@@ -801,7 +855,7 @@
+@@ -801,7 +858,7 @@
}
}
@@ -908,7 +1322,7 @@ diff -Nru a/mh.c b/mh.c
/* Read a MH/maildir style mailbox.
*
-@@ -1293,6 +1347,9 @@
+@@ -1293,6 +1350,9 @@
{
char path[_POSIX_PATH_MAX], tmp[_POSIX_PATH_MAX];
int i, j;
@@ -918,33 +1332,33 @@ diff -Nru a/mh.c b/mh.c
if (ctx->magic == M_MH)
i = mh_check_mailbox (ctx, index_hint);
-@@ -1302,6 +1359,11 @@
+@@ -1302,6 +1362,11 @@
if (i != 0)
return i;
+#if USE_HCACHE
+ if (ctx->magic == M_MAILDIR)
-+ hc = mutt_hcache_open(MaildirCache, ctx->path);
++ hc = mutt_hcache_open(HeaderCache, ctx->path);
+#endif /* USE_HCACHE */
+
for (i = 0; i < ctx->msgcount; i++)
{
if (ctx->hdrs[i]->deleted
-@@ -1310,7 +1372,13 @@
+@@ -1310,7 +1375,13 @@
snprintf (path, sizeof (path), "%s/%s", ctx->path, ctx->hdrs[i]->path);
if (ctx->magic == M_MAILDIR
|| (option (OPTMHPURGE) && ctx->magic == M_MH))
+ {
+#if USE_HCACHE
+ if (ctx->magic == M_MAILDIR)
-+ mutt_hcache_delete (hc, ctx->hdrs[i]->path + 3);
++ mutt_hcache_delete (hc, ctx->hdrs[i]->path + 3, &maildir_hcache_keylen);
+#endif /* USE_HCACHE */
unlink (path);
+ }
else if (ctx->magic == M_MH)
{
/* MH just moves files out of the way when you delete them */
-@@ -1332,16 +1400,21 @@
+@@ -1332,16 +1403,21 @@
if (ctx->magic == M_MAILDIR)
{
if (maildir_sync_message (ctx, i) == -1)
@@ -968,7 +1382,7 @@ diff -Nru a/mh.c b/mh.c
if (ctx->magic == M_MH)
mh_update_sequences (ctx);
-@@ -1362,6 +1435,13 @@
+@@ -1362,6 +1438,13 @@
}
return 0;
@@ -983,8 +1397,8 @@ diff -Nru a/mh.c b/mh.c
static char *maildir_canon_filename (char *dest, const char *src, size_t l)
diff -Nru a/mutt.h b/mutt.h
---- mutt.h 2004-06-10 14:03:44 +02:00
-+++ mutt.h 2004-06-10 14:03:44 +02:00
+--- a/mutt.h 2004-08-18 10:08:12 +02:00
++++ b/mutt.h 2004-08-18 10:08:12 +02:00
@@ -345,6 +345,9 @@
OPTFORCENAME,
OPTFORWDECODE,
@@ -996,9 +1410,9 @@ diff -Nru a/mutt.h b/mutt.h
OPTHEADER,
OPTHELP,
diff -Nru a/protos.h b/protos.h
---- protos.h 2004-06-10 14:03:44 +02:00
-+++ protos.h 2004-06-10 14:03:44 +02:00
-@@ -99,6 +99,19 @@
+--- a/protos.h 2004-08-18 10:08:12 +02:00
++++ b/protos.h 2004-08-18 10:08:12 +02:00
+@@ -99,6 +99,16 @@
ENVELOPE *mutt_read_rfc822_header (FILE *, HEADER *, short, short);
HEADER *mutt_dup_header (HEADER *);
@@ -1006,12 +1420,9 @@ diff -Nru a/protos.h b/protos.h
+void *mutt_hcache_open(const char *path, const char *folder);
+void mutt_hcache_close(void *db);
+HEADER *mutt_hcache_restore(const unsigned char *d, HEADER **oh);
-+void *mutt_hcache_fetch(void *db, const char *filename);
-+int mutt_hcache_store(void *db, const char *filename, HEADER *h);
-+int mutt_hcache_delete(void *db, const char *filename);
-+#if HAVE_LANGINFO_CODESET
-+int mutt_hcache_charset_matches(const char *d);
-+#endif /* HAVE_LANGINFO_CODESET */
++void *mutt_hcache_fetch(void *db, const char *filename, size_t (*keylen)(const char *fn));
++int mutt_hcache_store(void *db, const char *filename, HEADER *h, unsigned long long uid_validity, size_t (*keylen)(const char *fn));
++int mutt_hcache_delete(void *db, const char *filename, size_t (*keylen)(const char *fn));
+#endif /* USE_HCACHE */
+
+
@@ -1021,4 +1432,4 @@ diff -Nru a/protos.h b/protos.h
--- PATCHES.orig Tue Nov 6 19:59:33 2001
+++ PATCHES Tue Nov 6 19:59:42 2001
@@ -1,0 +1 @@
-+maildir-header-cache.19
++patch-1.5.6.tg.hcache.0
diff --git a/mail/mutt-devel/scripts/generate-plist b/mail/mutt-devel/scripts/generate-plist
index 4d2791716c83..1599a4383093 100644
--- a/mail/mutt-devel/scripts/generate-plist
+++ b/mail/mutt-devel/scripts/generate-plist
@@ -146,9 +146,6 @@ EOF
if [ "$MUTT_EDIT_THREADS" = "yes" ]; then
html=$(($html + 3))
fi
- if [ "$MUTT_IMAP_HEADER_CACHE" = "yes" ]; then
- html=$(($html + 1))
- fi
if [ "$MUTT_MAILDIR_HEADER_CACHE" = "yes" ]; then
html=$(($html + 3))
fi