Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 18 Aug 2004 18:47:05 +0200 (CEST)
From:      Udo Schweigert <udo.schweigert@siemens.com>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   ports/70623: maintainer-update of mail/mutt-devel
Message-ID:  <200408181647.i7IGl5DH004521@alaska.cert.siemens.com>
Resent-Message-ID: <200408181650.i7IGoTR9043046@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         70623
>Category:       ports
>Synopsis:       maintainer-update of mail/mutt-devel
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          maintainer-update
>Submitter-Id:   current-users
>Arrival-Date:   Wed Aug 18 16:50:29 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Udo Schweigert
>Release:        FreeBSD 4.10-STABLE i386
>Organization:
>Environment:

>Description:

Maintainer update of mail/mutt-devel:

	- Update the maildir header cache patch, which now also implements an
	  IMAP header cache. This is far more stable than the old IMAP header
	  cache patch, thus I bumped PORTREVISION.

Committer: cvs rm -f files/extra-patch-imap-header-cache 

>How-To-Repeat:
>Fix:

diff -ru  /usr/ports/mail/mutt-devel/Makefile ./Makefile
--- /usr/ports/mail/mutt-devel/Makefile	Tue Aug  3 06:51:13 2004
+++ ./Makefile	Wed Aug 18 18:24:10 2004
@@ -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 @@
 .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 @@
 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 @@
 .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 @@
 .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 -ru  /usr/ports/mail/mutt-devel/files/extra-patch-imap-header-cache ./files/extra-patch-imap-header-cache
--- /usr/ports/mail/mutt-devel/files/extra-patch-imap-header-cache	Sat Jun 12 14:36:28 2004
+++ ./files/extra-patch-imap-header-cache	Thu Jan  1 01:00:00 1970
@@ -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 -ru  /usr/ports/mail/mutt-devel/files/extra-patch-maildir-header-cache ./files/extra-patch-maildir-header-cache
--- /usr/ports/mail/mutt-devel/files/extra-patch-maildir-header-cache	Tue Aug  3 06:51:13 2004
+++ ./files/extra-patch-maildir-header-cache	Wed Aug 18 18:16:41 2004
@@ -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 @@
 +        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 @@
  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 @@
 +#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 @@
 +		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 @@
 +	*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 @@
 +	}
 +
 +	*a = NULL;
-+	return;
 +}
 +
 +static unsigned char *
@@ -284,7 +323,43 @@
 +	}
 +
 +	*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 @@
 +	}
 +
 +	*p = NULL;
-+	return;
 +}
 +
 +static unsigned char *
@@ -408,7 +482,7 @@
 +	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 @@
 +	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 @@
 +	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 @@
 +
 +	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 @@
 +}
 +
 +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 @@
 +	}
 +
 +	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 @@
 +	}
 +
 +	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 @@
 +}
 +
 +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 @@
 +	}
 +
 +	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 @@
 +	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 @@
 +		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 @@
 +
 +	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 @@
 +
 +	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 @@
 +
 +	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 @@
 +
 +	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 @@
 +}
 +
 +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 @@
 +
 +	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 @@
    /*
    ** .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 @@
  
  #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 @@
 +	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 @@
 +
 +		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 @@
  
  void maildir_delayed_parsing (CONTEXT * ctx, struct maildir *md)
  {
-@@ -801,7 +855,7 @@
+@@ -801,7 +858,7 @@
      }
  }
  
@@ -908,7 +1322,7 @@
  
  /* 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 @@
  
    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 @@
    if (ctx->magic == M_MH)
      mh_update_sequences (ctx);
  
-@@ -1362,6 +1435,13 @@
+@@ -1362,6 +1438,13 @@
    }
  
    return 0;
@@ -983,8 +1397,8 @@
  
  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 @@
    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 @@
 +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 @@
 --- 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 -ru  /usr/ports/mail/mutt-devel/scripts/generate-plist ./scripts/generate-plist
--- /usr/ports/mail/mutt-devel/scripts/generate-plist	Thu Jul  8 15:17:55 2004
+++ ./scripts/generate-plist	Wed Aug 18 14:17:05 2004
@@ -146,9 +146,6 @@
     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
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200408181647.i7IGl5DH004521>