NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
hcache.c
Go to the documentation of this file.
1 
35 #include "config.h"
36 #include <assert.h>
37 #include <errno.h>
38 #include <limits.h>
39 #include <stdbool.h>
40 #include <stdint.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <sys/stat.h>
45 #include <unistd.h>
46 #include "mutt/lib.h"
47 #include "config/lib.h"
48 #include "email/lib.h"
49 #include "core/lib.h"
50 #include "lib.h"
51 #include "compress/lib.h"
52 #include "store/lib.h"
53 #include "hcache/hcversion.h"
54 #include "muttlib.h"
55 #include "serialize.h"
56 
57 #if !(defined(HAVE_BDB) || defined(HAVE_GDBM) || defined(HAVE_KC) || \
58  defined(HAVE_LMDB) || defined(HAVE_QDBM) || defined(HAVE_ROCKSDB) || \
59  defined(HAVE_TC) || defined(HAVE_TDB))
60 #error "No hcache backend defined"
61 #endif
62 
63 static unsigned int hcachever = 0x0;
64 
69 static size_t header_size(void)
70 {
71  return sizeof(int) + sizeof(uint32_t);
72 }
73 
85 static void *dump(struct HeaderCache *hc, const struct Email *e, int *off, uint32_t uidvalidity)
86 {
87  struct Email e_dump;
88  bool convert = !CharsetIsUtf8;
89 
90  *off = 0;
91  unsigned char *d = mutt_mem_malloc(4096);
92 
93  d = serial_dump_uint32_t((uidvalidity != 0) ? uidvalidity : mutt_date_epoch(), d, off);
94  d = serial_dump_int(hc->crc, d, off);
95 
96  assert((size_t) *off == header_size());
97 
98  lazy_realloc(&d, *off + sizeof(struct Email));
99  memcpy(&e_dump, e, sizeof(struct Email));
100 
101  /* some fields are not safe to cache */
102  e_dump.tagged = false;
103  e_dump.changed = false;
104  e_dump.threaded = false;
105  e_dump.recip_valid = false;
106  e_dump.searched = false;
107  e_dump.matched = false;
108  e_dump.collapsed = false;
109  e_dump.visible = true;
110  e_dump.num_hidden = 0;
111  e_dump.recipient = 0;
112  e_dump.pair = 0;
113  e_dump.attach_valid = false;
114  e_dump.path = NULL;
115  e_dump.tree = NULL;
116  e_dump.thread = NULL;
117  e_dump.sequence = 0;
118  e_dump.notify = NULL;
119  STAILQ_INIT(&e_dump.tags);
120 #ifdef MIXMASTER
121  STAILQ_INIT(&e_dump.chain);
122 #endif
123  e_dump.edata = NULL;
124 
125  memcpy(d + *off, &e_dump, sizeof(struct Email));
126  *off += sizeof(struct Email);
127 
128  d = serial_dump_envelope(e_dump.env, d, off, convert);
129  d = serial_dump_body(e_dump.body, d, off, convert);
130  d = serial_dump_tags(&e->tags, d, off);
131 
132  return d;
133 }
134 
143 static struct Email *restore(const unsigned char *d)
144 {
145  int off = 0;
146  struct Email *e = email_new();
147  bool convert = !CharsetIsUtf8;
148 
149  /* skip validate */
150  off += sizeof(uint32_t);
151 
152  /* skip crc */
153  off += sizeof(unsigned int);
154 
155  size_t sequence = e->sequence;
156  struct Notify *notify = e->notify;
157  memcpy(e, d + off, sizeof(struct Email));
158  off += sizeof(struct Email);
159  e->sequence = sequence;
160  e->notify = notify;
161 
162  STAILQ_INIT(&e->tags);
163 #ifdef MIXMASTER
164  STAILQ_INIT(&e->chain);
165 #endif
166 
167  e->env = mutt_env_new();
168  serial_restore_envelope(e->env, d, &off, convert);
169 
170  e->body = mutt_body_new();
171  serial_restore_body(e->body, d, &off, convert);
172  serial_restore_tags(&e->tags, d, &off);
173 
174  return e;
175 }
176 
177 struct RealKey
178 {
179  char key[1024];
180  size_t len;
181 };
182 
189 static struct RealKey *realkey(const char *key, size_t keylen)
190 {
191  static struct RealKey rk;
192 #ifdef USE_HCACHE_COMPRESSION
193  const char *const c_header_cache_compress_method =
194  cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
195  if (c_header_cache_compress_method)
196  {
197  const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
198 
199  rk.len = snprintf(rk.key, sizeof(rk.key), "%s-%s", key, cops->name);
200  }
201  else
202 #endif
203  {
204  memcpy(rk.key, key, keylen + 1); // Including NUL byte
205  rk.len = keylen;
206  }
207  return &rk;
208 }
209 
216 static bool create_hcache_dir(const char *path)
217 {
218  char *dir = mutt_str_dup(path);
219  if (!dir)
220  return false;
221 
222  char *p = strrchr(dir, '/');
223  if (!p)
224  {
225  FREE(&dir);
226  return true;
227  }
228 
229  *p = '\0';
230 
231  int rc = mutt_file_mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO);
232  if (rc != 0)
233  mutt_error(_("Can't create %s: %s"), dir, strerror(errno));
234 
235  FREE(&dir);
236  return (rc == 0);
237 }
238 
260 static void hcache_per_folder(struct Buffer *hcpath, const char *path,
261  const char *folder, hcache_namer_t namer)
262 {
263  struct stat sb;
264 
265  int plen = mutt_str_len(path);
266  int rc = stat(path, &sb);
267  bool slash = (path[plen - 1] == '/');
268 
269  if (((rc == 0) && !S_ISDIR(sb.st_mode)) || ((rc == -1) && !slash))
270  {
271  /* An existing file or a non-existing path not ending with a slash */
272  mutt_encode_path(hcpath, path);
274  return;
275  }
276 
277  /* We have a directory - no matter whether it exists, or not */
278  struct Buffer *hcfile = mutt_buffer_pool_get();
279  if (namer)
280  {
281  namer(folder, hcfile);
282  mutt_buffer_concat_path(hcpath, path, mutt_buffer_string(hcfile));
283  }
284  else
285  {
286  unsigned char m[16]; /* binary md5sum */
287  struct Buffer *name = mutt_buffer_pool_get();
288 
289  const char *const c_header_cache_backend =
290  cs_subset_string(NeoMutt->sub, "header_cache_backend");
291  const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
292 
293 #ifdef USE_HCACHE_COMPRESSION
294  const char *const c_header_cache_compress_method =
295  cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
296  const char *cm = c_header_cache_compress_method;
297  mutt_buffer_printf(name, "%s|%s%s", ops->name, folder, cm ? cm : "");
298 #else
299  mutt_buffer_printf(name, "%s|%s", ops->name, folder);
300 #endif
301  mutt_md5(mutt_buffer_string(name), m);
302  mutt_buffer_reset(name);
303  mutt_md5_toascii(m, name->data);
304  mutt_buffer_printf(hcpath, "%s%s%s", path, slash ? "" : "/", mutt_buffer_string(name));
306  }
307 
308  mutt_encode_path(hcpath, mutt_buffer_string(hcpath));
310  mutt_buffer_pool_release(&hcfile);
311 }
312 
318 static char *get_foldername(const char *folder)
319 {
320  /* if the folder is local, canonify the path to avoid
321  * to ensure equivalent paths share the hcache */
322  char *p = mutt_mem_malloc(PATH_MAX + 1);
323  if (!realpath(folder, p))
324  mutt_str_replace(&p, folder);
325 
326  return p;
327 }
328 
332 struct HeaderCache *mutt_hcache_open(const char *path, const char *folder, hcache_namer_t namer)
333 {
334  const char *const c_header_cache_backend =
335  cs_subset_string(NeoMutt->sub, "header_cache_backend");
336  const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
337  if (!ops)
338  return NULL;
339 
340  struct HeaderCache *hc = mutt_mem_calloc(1, sizeof(struct HeaderCache));
341 
342  /* Calculate the current hcache version from dynamic configuration */
343  if (hcachever == 0x0)
344  {
345  union
346  {
347  unsigned char charval[16];
348  unsigned int intval;
349  } digest;
350  struct Md5Ctx md5ctx;
351 
352  hcachever = HCACHEVER;
353 
354  mutt_md5_init_ctx(&md5ctx);
355 
356  /* Seed with the compiled-in header structure hash */
357  mutt_md5_process_bytes(&hcachever, sizeof(hcachever), &md5ctx);
358 
359  /* Mix in user's spam list */
360  struct Replace *sp = NULL;
361  STAILQ_FOREACH(sp, &SpamList, entries)
362  {
363  mutt_md5_process(sp->regex->pattern, &md5ctx);
364  mutt_md5_process(sp->templ, &md5ctx);
365  }
366 
367  /* Mix in user's nospam list */
368  struct RegexNode *np = NULL;
369  STAILQ_FOREACH(np, &NoSpamList, entries)
370  {
371  mutt_md5_process(np->regex->pattern, &md5ctx);
372  }
373 
374  /* Get a hash and take its bytes as an (unsigned int) hash version */
375  mutt_md5_finish_ctx(&md5ctx, digest.charval);
376  hcachever = digest.intval;
377  }
378 
379 #ifdef USE_HCACHE_COMPRESSION
380  const char *const c_header_cache_compress_method =
381  cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
382  if (c_header_cache_compress_method)
383  {
384  const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
385 
386  const short c_header_cache_compress_level =
387  cs_subset_number(NeoMutt->sub, "header_cache_compress_level");
388  hc->cctx = cops->open(c_header_cache_compress_level);
389  if (!hc->cctx)
390  {
391  FREE(&hc);
392  return NULL;
393  }
394 
395  /* remember the buffer of database backend */
396  mutt_debug(LL_DEBUG3, "Header cache will use %s compression\n", cops->name);
397  }
398 #endif
399 
400  hc->folder = get_foldername(folder);
401  hc->crc = hcachever;
402 
403  if (!path || (path[0] == '\0'))
404  {
405  FREE(&hc->folder);
406  FREE(&hc);
407  return NULL;
408  }
409 
410  struct Buffer *hcpath = mutt_buffer_pool_get();
411  hcache_per_folder(hcpath, path, hc->folder, namer);
412 
413  hc->ctx = ops->open(mutt_buffer_string(hcpath));
414  if (!hc->ctx)
415  {
416  /* remove a possibly incompatible version */
417  if (unlink(mutt_buffer_string(hcpath)) == 0)
418  {
419  hc->ctx = ops->open(mutt_buffer_string(hcpath));
420  if (!hc->ctx)
421  {
422  FREE(&hc->folder);
423  FREE(&hc);
424  }
425  }
426  }
427 
428  mutt_buffer_pool_release(&hcpath);
429  return hc;
430 }
431 
436 {
437  const char *const c_header_cache_backend =
438  cs_subset_string(NeoMutt->sub, "header_cache_backend");
439  const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
440  if (!hc || !ops)
441  return;
442 
443 #ifdef USE_HCACHE_COMPRESSION
444  const char *const c_header_cache_compress_method =
445  cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
446  if (c_header_cache_compress_method)
447  {
448  const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
449  cops->close(&hc->cctx);
450  }
451 #endif
452 
453  ops->close(&hc->ctx);
454  FREE(&hc->folder);
455  FREE(&hc);
456 }
457 
461 struct HCacheEntry mutt_hcache_fetch(struct HeaderCache *hc, const char *key,
462  size_t keylen, uint32_t uidvalidity)
463 {
464  struct RealKey *rk = realkey(key, keylen);
465  struct HCacheEntry entry = { 0 };
466 
467  size_t dlen;
468  void *data = mutt_hcache_fetch_raw(hc, rk->key, rk->len, &dlen);
469  void *to_free = data;
470  if (!data)
471  {
472  goto end;
473  }
474 
475  /* restore uidvalidity and crc */
476  size_t hlen = header_size();
477  int off = 0;
478  serial_restore_uint32_t(&entry.uidvalidity, data, &off);
479  serial_restore_int(&entry.crc, data, &off);
480  assert((size_t) off == hlen);
481  if (entry.crc != hc->crc || ((uidvalidity != 0) && uidvalidity != entry.uidvalidity))
482  {
483  goto end;
484  }
485 
486 #ifdef USE_HCACHE_COMPRESSION
487  const char *const c_header_cache_compress_method =
488  cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
489  if (c_header_cache_compress_method)
490  {
491  const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
492 
493  void *dblob = cops->decompress(hc->cctx, (char *) data + hlen, dlen - hlen);
494  if (!dblob)
495  {
496  goto end;
497  }
498  data = (char *) dblob - hlen; /* restore skips uidvalidity and crc */
499  }
500 #endif
501 
502  entry.email = restore(data);
503 
504 end:
505  mutt_hcache_free_raw(hc, &to_free);
506  return entry;
507 }
508 
521 void *mutt_hcache_fetch_raw(struct HeaderCache *hc, const char *key,
522  size_t keylen, size_t *dlen)
523 {
524  const char *const c_header_cache_backend =
525  cs_subset_string(NeoMutt->sub, "header_cache_backend");
526  const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
527 
528  if (!hc || !ops)
529  return NULL;
530 
531  struct Buffer path = mutt_buffer_make(1024);
532  keylen = mutt_buffer_printf(&path, "%s%.*s", hc->folder, (int) keylen, key);
533  void *blob = ops->fetch(hc->ctx, mutt_buffer_string(&path), keylen, dlen);
534  mutt_buffer_dealloc(&path);
535  return blob;
536 }
537 
541 void mutt_hcache_free_raw(struct HeaderCache *hc, void **data)
542 {
543  const char *const c_header_cache_backend =
544  cs_subset_string(NeoMutt->sub, "header_cache_backend");
545  const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
546 
547  if (!hc || !ops || !data || !*data)
548  return;
549 
550  ops->free(hc->ctx, data);
551 }
552 
556 int mutt_hcache_store(struct HeaderCache *hc, const char *key, size_t keylen,
557  struct Email *e, uint32_t uidvalidity)
558 {
559  if (!hc)
560  return -1;
561 
562  int dlen = 0;
563  char *data = dump(hc, e, &dlen, uidvalidity);
564 
565 #ifdef USE_HCACHE_COMPRESSION
566  const char *const c_header_cache_compress_method =
567  cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
568  if (c_header_cache_compress_method)
569  {
570  /* We don't compress uidvalidity and the crc, so we can check them before
571  * decompressing on fetch(). */
572  size_t hlen = header_size();
573 
574  const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
575 
576  /* data / dlen gets ptr to compressed data here */
577  size_t clen = dlen;
578  void *cdata = cops->compress(hc->cctx, data + hlen, dlen - hlen, &clen);
579  if (!cdata)
580  {
581  FREE(&data);
582  return -1;
583  }
584 
585  char *whole = mutt_mem_malloc(hlen + clen);
586  memcpy(whole, data, hlen);
587  memcpy(whole + hlen, cdata, clen);
588 
589  FREE(&data);
590 
591  data = whole;
592  dlen = hlen + clen;
593  }
594 #endif
595 
596  /* store uncompressed data */
597  struct RealKey *rk = realkey(key, keylen);
598  int rc = mutt_hcache_store_raw(hc, rk->key, rk->len, data, dlen);
599 
600  FREE(&data);
601 
602  return rc;
603 }
604 
615 int mutt_hcache_store_raw(struct HeaderCache *hc, const char *key,
616  size_t keylen, void *data, size_t dlen)
617 {
618  const char *const c_header_cache_backend =
619  cs_subset_string(NeoMutt->sub, "header_cache_backend");
620  const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
621 
622  if (!hc || !ops)
623  return -1;
624 
625  struct Buffer path = mutt_buffer_make(1024);
626 
627  keylen = mutt_buffer_printf(&path, "%s%.*s", hc->folder, (int) keylen, key);
628  int rc = ops->store(hc->ctx, mutt_buffer_string(&path), keylen, data, dlen);
629  mutt_buffer_dealloc(&path);
630 
631  return rc;
632 }
633 
637 int mutt_hcache_delete_record(struct HeaderCache *hc, const char *key, size_t keylen)
638 {
639  if (!hc)
640  return -1;
641 
642  const char *const c_header_cache_backend =
643  cs_subset_string(NeoMutt->sub, "header_cache_backend");
644  const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
645 
646  struct Buffer path = mutt_buffer_make(1024);
647 
648  keylen = mutt_buffer_printf(&path, "%s%s", hc->folder, key);
649 
650  int rc = ops->delete_record(hc->ctx, mutt_buffer_string(&path), keylen);
651  mutt_buffer_dealloc(&path);
652  return rc;
653 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:427
char * templ
Template to match.
Definition: regex3.h:113
void * cctx
Definition: lib.h:89
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
static struct RealKey * realkey(const char *key, size_t keylen)
Compute the real key used in the backend, taking into account the compression method.
Definition: hcache.c:189
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
The envelope/body of an email.
Definition: email.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
Wrapper for Email retrieved from the header cache.
Definition: lib.h:95
Cursor for the MD5 hashing.
Definition: md5.h:36
struct Body * body
List of MIME parts.
Definition: email.h:91
Structs that make up an email.
#define mutt_error(...)
Definition: logging.h:88
const struct ComprOps * compress_get_ops(const char *compr)
Get the API functions for a compress backend.
Definition: compress.c:80
size_t len
Definition: hcache.c:180
struct MuttThread * thread
Thread of Emails.
Definition: email.h:95
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
struct Notify * notify
Notifications: ColorId, EventColor.
Definition: color.c:95
short recipient
User_is_recipient()&#39;s return value, cached.
Definition: email.h:78
void serial_restore_body(struct Body *c, const unsigned char *d, int *off, bool convert)
Unpack a Body from a binary blob.
Definition: serialize.c:465
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
unsigned char * serial_dump_envelope(struct Envelope *env, unsigned char *d, int *off, bool convert)
Pack an Envelope into a binary blob.
Definition: serialize.c:491
static size_t header_size(void)
Compute the size of the header with uuid validity and crc.
Definition: hcache.c:69
uint32_t uidvalidity
IMAP-specific UIDVALIDITY.
Definition: lib.h:97
void mutt_md5_process(const char *str, struct Md5Ctx *md5ctx)
Process a NULL-terminated string.
Definition: md5.c:355
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
header cache structure
Definition: lib.h:84
void *(* compress)(void *cctx, const char *data, size_t dlen, size_t *clen)
Definition: lib.h:91
bool threaded
Used for threading.
Definition: email.h:56
String manipulation buffer.
Definition: buffer.h:33
unsigned char * serial_dump_uint32_t(uint32_t s, unsigned char *d, int *off)
Pack a uint32_t into a binary blob.
Definition: serialize.c:83
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
void mutt_md5_init_ctx(struct Md5Ctx *md5ctx)
Initialise the MD5 computation.
Definition: md5.c:262
bool changed
Email has been edited.
Definition: email.h:48
void serial_restore_int(unsigned int *i, const unsigned char *d, int *off)
Unpack an integer from a binary blob.
Definition: serialize.c:98
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
static char * get_foldername(const char *folder)
Where should the cache be stored?
Definition: hcache.c:318
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition: store.c:107
bool searched
Email has been searched.
Definition: email.h:67
Definition: lib.h:63
void *(* fetch)(void *store, const char *key, size_t klen, size_t *vlen)
Definition: lib.h:94
void mutt_hcache_free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition: hcache.c:541
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
struct HeaderCache * mutt_hcache_open(const char *path, const char *folder, hcache_namer_t namer)
Multiplexor for StoreOps::open.
Definition: hcache.c:332
const char * name
Compression name.
Definition: lib.h:61
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
Container for Accounts, Notifications.
Definition: neomutt.h:36
List of regular expressions.
Definition: regex3.h:109
struct Regex * regex
Regex containing a regular expression.
Definition: regex3.h:111
Convenience wrapper for the config headers.
void serial_restore_uint32_t(uint32_t *s, const unsigned char *d, int *off)
Unpack an uint32_t from a binary blob.
Definition: serialize.c:110
static bool create_hcache_dir(const char *path)
Create parent dirs for the hcache database.
Definition: hcache.c:216
struct Email * email_new(void)
Create a new Email.
Definition: email.c:78
unsigned int crc
Definition: lib.h:87
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
API for the header cache compression.
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
Some miscellaneous functions.
void(* close)(void **ptr)
Definition: lib.h:141
bool tagged
Email is tagged.
Definition: email.h:44
void mutt_md5_toascii(const void *digest, char *resbuf)
Convert a binary MD5 digest into ASCII Hexadecimal.
Definition: md5.c:457
static void * dump(struct HeaderCache *hc, const struct Email *e, int *off, uint32_t uidvalidity)
Serialise an Email object.
Definition: hcache.c:85
#define STAILQ_INIT(head)
Definition: queue.h:372
char key[1024]
Definition: hcache.c:179
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:877
int(* store)(void *store, const char *key, size_t klen, void *value, size_t vlen)
Definition: lib.h:119
void * mutt_md5_finish_ctx(struct Md5Ctx *md5ctx, void *resbuf)
Process the remaining bytes in the buffer.
Definition: md5.c:286
struct Envelope * env
Envelope information.
Definition: email.h:90
Convenience wrapper for the core headers.
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
void *(* open)(const char *path)
Definition: lib.h:80
Email-object serialiser.
void(* hcache_namer_t)(const char *path, struct Buffer *dest)
Prototype for function to compose hcache file names.
Definition: lib.h:107
struct TagList tags
For drivers that support server tagging.
Definition: email.h:109
bool visible
Is this message part of the view?
Definition: email.h:74
struct ListHead chain
Mixmaster chain.
Definition: email.h:102
struct RegexList NoSpamList
List of regexes to whitelist non-spam emails.
Definition: globals.c:33
unsigned char * serial_dump_int(unsigned int i, unsigned char *d, int *off)
Pack an integer into a binary blob.
Definition: serialize.c:67
#define PATH_MAX
Definition: mutt.h:40
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
static void hcache_per_folder(struct Buffer *hcpath, const char *path, const char *folder, hcache_namer_t namer)
Generate the hcache pathname.
Definition: hcache.c:260
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
Definition: email.h:75
struct Regex * regex
Regex containing a regular expression.
Definition: regex3.h:101
char * data
Pointer to data.
Definition: buffer.h:35
static unsigned int hcachever
Definition: hcache.c:63
int mutt_hcache_delete_record(struct HeaderCache *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_record.
Definition: hcache.c:637
void *(* open)(short level)
Definition: lib.h:74
size_t sequence
Sequence number assigned on creation.
Definition: email.h:99
bool attach_valid
true when the attachment count is valid
Definition: email.h:70
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:73
int mutt_hcache_store(struct HeaderCache *hc, const char *key, size_t keylen, struct Email *e, uint32_t uidvalidity)
Multiplexor for StoreOps::store.
Definition: hcache.c:556
Notification API.
Definition: notify.c:50
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
char * tree
Character string to print thread tree.
Definition: email.h:94
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
List of regular expressions.
Definition: regex3.h:99
struct Notify * notify
Notifications: NotifyEmail, EventEmail.
Definition: email.h:123
bool CharsetIsUtf8
Is the user&#39;s current character set utf-8?
Definition: charset.c:62
void mutt_hcache_close(struct HeaderCache *hc)
Multiplexor for StoreOps::close.
Definition: hcache.c:435
const char * name
Store name.
Definition: lib.h:65
struct ReplaceList SpamList
List of regexes and patterns to match spam emails.
Definition: globals.c:34
int(* delete_record)(void *store, const char *key, size_t klen)
Definition: lib.h:132
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
Key value store.
void mutt_md5_process_bytes(const void *buf, size_t buflen, struct Md5Ctx *md5ctx)
Process a block of data.
Definition: md5.c:373
void(* free)(void *store, void **ptr)
Definition: lib.h:104
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
Definition: lib.h:59
void * mutt_md5(const char *str, void *buf)
Calculate the MD5 hash of a NULL-terminated string.
Definition: md5.c:317
void * edata
Driver-specific data.
Definition: email.h:111
void serial_restore_tags(struct TagList *tags, const unsigned char *d, int *off)
Unpack a TagList from a binary blob.
Definition: serialize.c:617
void lazy_realloc(void *ptr, size_t size)
Reallocate some memory.
Definition: serialize.c:50
char * path
Path of Email (for local Mailboxes)
Definition: email.h:92
unsigned int crc
CRC of Email/Body/etc structs.
Definition: lib.h:98
void(* close)(void **cctx)
Definition: lib.h:119
unsigned char * serial_dump_tags(const struct TagList *tags, unsigned char *d, int *off)
Pack a TagList into a binary blob.
Definition: serialize.c:592
#define FREE(x)
Definition: memory.h:40
char * folder
Definition: lib.h:86
size_t mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:374
void *(* decompress)(void *cctx, const char *cbuf, size_t clen)
Definition: lib.h:107
unsigned char * serial_dump_body(struct Body *c, unsigned char *d, int *off, bool convert)
Pack an Body into a binary blob.
Definition: serialize.c:425
bool recip_valid
Is_recipient is valid.
Definition: email.h:58
struct HCacheEntry mutt_hcache_fetch(struct HeaderCache *hc, const char *key, size_t keylen, uint32_t uidvalidity)
Multiplexor for StoreOps::fetch.
Definition: hcache.c:461
int mutt_hcache_store_raw(struct HeaderCache *hc, const char *key, size_t keylen, void *data, size_t dlen)
store a key / data pair
Definition: hcache.c:615
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
struct Email * email
Retrieved email.
Definition: lib.h:99
char * pattern
printable version
Definition: regex3.h:91
void * mutt_hcache_fetch_raw(struct HeaderCache *hc, const char *key, size_t keylen, size_t *dlen)
Fetch a message&#39;s header from the cache.
Definition: hcache.c:521
Convenience wrapper for the library headers.
void serial_restore_envelope(struct Envelope *env, const unsigned char *d, int *off, bool convert)
Unpack an Envelope from a binary blob.
Definition: serialize.c:539
int pair
Color-pair to use when displaying in the index.
Definition: email.h:80
Log at debug level 3.
Definition: logging.h:42
bool matched
Search matches this Email.
Definition: email.h:68
static struct Email * restore(const unsigned char *d)
Restore an Email from data retrieved from the cache.
Definition: hcache.c:143
void mutt_encode_path(struct Buffer *buf, const char *src)
Convert a path to &#39;us-ascii&#39;.
Definition: muttlib.c:1490
void * ctx
Definition: lib.h:88