[PATCH] Invalidate header caches when spam rules change
# HG changeset patch
# User David Champion <dgc@xxxxxxxxxxxx>
# Date 1284612296 18000
# Branch HEAD
# Node ID 6cf2dabfe8226904eb8f86786f4f4bab028d5ef2
# Parent c64a45baed14d182e4fd0f2ba24acee832d862f4
Invalidate header caches when spam rules change.
User 'exg' on #mutt reported a problem when using header cache with IMAP
and spam rules. Spam tags are retrieved from cache and not updated when
spam rules change.
1. Enable header caching in muttrc
2. Set spam rules in muttrc
3. Use IMAP (or POP or Maildir). Your spam rules store spam tags into
your message headers, and these get cached.
4. Quit mutt
5. Change your spam rules in muttrc
6. Relaunch mutt
7. Because of header caching, the rfc822 headers are not reparsed, and
spam rules are not reapplied. User has outdated spam tags.
Spam rules are applied during rfc822 header parsing because it's the
only time we get a full and unadulterated view of all headers. Once
header parse is done we have only processed headers and 'user headers'
(X-headers). We might do spam rule matching against the struct HEADER
copy of headers, except that:
a. the header might not be in HEADER if it's non-standard and not an
X-header;
b. spam rules are regular expressions matching any arbitrary header
line, and we would need to map these regexps to the header used to
create the HEADER fields. This would change the syntax and behavior
of spam rules dramatically.
One solution, perhaps stopgap, is to invalidate the header cache when
spam rules change. That's what this patch does. It alters the hcache
versioning algorithm so that in addition to using the compiled-in
checksum of mutt's structures definitions, we also mix in the user's
runtime spam rules. Any time spam rules change the hcachever hash value
changes, causing the hcache to be rewritten.
diff -r c64a45baed14 -r 6cf2dabfe822 hcache.c
--- a/hcache.c Wed Sep 15 23:44:56 2010 -0500
+++ b/hcache.c Wed Sep 15 23:44:56 2010 -0500
@@ -47,6 +47,8 @@
#include "md5.h"
#include "rfc822.h"
+unsigned int hcachever = 0x0;
+
#if HAVE_QDBM
static struct header_cache
{
@@ -1119,9 +1121,41 @@
hcache_open = hcache_open_db4;
#endif
+ /* Calculate the current hcache version from dynamic configuration */
+ if (hcachever == 0x0) {
+ unsigned char digest[16];
+ struct md5_ctx ctx;
+ SPAM_LIST *spam;
+ RX_LIST *nospam;
+
+ hcachever = HCACHEVER;
+
+ md5_init_ctx(&ctx);
+
+ /* Seed with the compiled-in header structure hash */
+ md5_process_bytes(&hcachever, sizeof(hcachever), &ctx);
+
+ /* Mix in user's spam list */
+ for (spam = SpamList; spam; spam = spam->next)
+ {
+ md5_process_bytes(spam->rx->pattern, strlen(spam->rx->pattern), &ctx);
+ md5_process_bytes(spam->template, strlen(spam->template), &ctx);
+ }
+
+ /* Mix in user's nospam list */
+ for (nospam = NoSpamList; nospam; nospam = nospam->next)
+ {
+ md5_process_bytes(nospam->rx->pattern, strlen(nospam->rx->pattern),
&ctx);
+ }
+
+ /* Get a hash and take its bytes as an (unsigned int) hash version */
+ md5_finish_ctx(&ctx, digest);
+ hcachever = *((unsigned int *)digest);
+ }
+
h->db = NULL;
h->folder = get_foldername(folder);
- h->crc = HCACHEVER;
+ h->crc = hcachever;
if (!path || path[0] == '\0')
{