NeoMutt  2020-06-26-89-g172cd3
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 "email/lib.h"
48 #include "lib.h"
49 #include "hcache/hcversion.h"
50 #include "muttlib.h"
51 #include "serialize.h"
52 #include "compress/lib.h"
53 #include "store/lib.h"
54 
55 #if !(defined(HAVE_BDB) || defined(HAVE_GDBM) || defined(HAVE_KC) || \
56  defined(HAVE_LMDB) || defined(HAVE_QDBM) || defined(HAVE_ROCKSDB) || \
57  defined(HAVE_TC) || defined(HAVE_TDB))
58 #error "No hcache backend defined"
59 #endif
60 
61 static unsigned int hcachever = 0x0;
62 
63 #define hcache_get_ops() store_get_backend_ops(C_HeaderCacheBackend)
64 
65 #ifdef USE_HCACHE_COMPRESSION
66 #define compr_get_ops() compress_get_ops(C_HeaderCacheCompressMethod)
67 #endif
68 
73 static size_t header_size(void)
74 {
75  return sizeof(int) + sizeof(uint32_t);
76 }
77 
89 static void *dump(header_cache_t *hc, const struct Email *e, int *off, uint32_t uidvalidity)
90 {
91  struct Email e_dump;
92  bool convert = !CharsetIsUtf8;
93 
94  *off = 0;
95  unsigned char *d = mutt_mem_malloc(4096);
96 
97  d = serial_dump_uint32_t((uidvalidity != 0) ? uidvalidity : mutt_date_epoch(), d, off);
98  d = serial_dump_int(hc->crc, d, off);
99 
100  assert((size_t) *off == header_size());
101 
102  lazy_realloc(&d, *off + sizeof(struct Email));
103  memcpy(&e_dump, e, sizeof(struct Email));
104 
105  /* some fields are not safe to cache */
106  e_dump.tagged = false;
107  e_dump.changed = false;
108  e_dump.threaded = false;
109  e_dump.recip_valid = false;
110  e_dump.searched = false;
111  e_dump.matched = false;
112  e_dump.collapsed = false;
113  e_dump.limited = false;
114  e_dump.num_hidden = 0;
115  e_dump.recipient = 0;
116  e_dump.pair = 0;
117  e_dump.attach_valid = false;
118  e_dump.path = NULL;
119  e_dump.tree = NULL;
120  e_dump.thread = NULL;
121  STAILQ_INIT(&e_dump.tags);
122 #ifdef MIXMASTER
123  STAILQ_INIT(&e_dump.chain);
124 #endif
125  e_dump.edata = NULL;
126 
127  memcpy(d + *off, &e_dump, sizeof(struct Email));
128  *off += sizeof(struct Email);
129 
130  d = serial_dump_envelope(e_dump.env, d, off, convert);
131  d = serial_dump_body(e_dump.content, d, off, convert);
132  d = serial_dump_char(e_dump.maildir_flags, d, off, convert);
133 
134  return d;
135 }
136 
145 static struct Email *restore(const unsigned char *d)
146 {
147  int off = 0;
148  struct Email *e = email_new();
149  bool convert = !CharsetIsUtf8;
150 
151  /* skip validate */
152  off += sizeof(uint32_t);
153 
154  /* skip crc */
155  off += sizeof(unsigned int);
156 
157  memcpy(e, d + off, sizeof(struct Email));
158  off += sizeof(struct Email);
159 
160  STAILQ_INIT(&e->tags);
161 #ifdef MIXMASTER
162  STAILQ_INIT(&e->chain);
163 #endif
164 
165  e->env = mutt_env_new();
166  serial_restore_envelope(e->env, d, &off, convert);
167 
168  e->content = mutt_body_new();
169  serial_restore_body(e->content, d, &off, convert);
170 
171  serial_restore_char(&e->maildir_flags, d, &off, convert);
172 
173  return e;
174 }
175 
176 struct RealKey
177 {
178  char key[1024];
179  size_t len;
180 };
181 
188 static struct RealKey *realkey(const char *key, size_t keylen)
189 {
190  static struct RealKey rk;
191 #ifdef USE_HCACHE_COMPRESSION
193  {
194  rk.len = snprintf(rk.key, sizeof(rk.key), "%s-%s", key, compr_get_ops()->name);
195  }
196  else
197 #endif
198  {
199  memcpy(rk.key, key, keylen + 1); // Including NUL byte
200  rk.len = keylen;
201  }
202  return &rk;
203 }
204 
211 static bool create_hcache_dir(const char *path)
212 {
213  char *dir = mutt_str_dup(path);
214  if (!dir)
215  return false;
216 
217  char *p = strrchr(dir, '/');
218  if (!p)
219  {
220  FREE(&dir);
221  return true;
222  }
223 
224  *p = '\0';
225 
226  int rc = mutt_file_mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO);
227  if (rc != 0)
228  mutt_error(_("Can't create %s: %s"), dir, strerror(errno));
229 
230  FREE(&dir);
231  return (rc == 0);
232 }
233 
257 static void hcache_per_folder(struct Buffer *hcpath, const char *path,
258  const char *folder, hcache_namer_t namer)
259 {
260  struct stat sb;
261 
262  int plen = mutt_str_len(path);
263  int rc = stat(path, &sb);
264  bool slash = (path[plen - 1] == '/');
265 
266  if (((rc == 0) && !S_ISDIR(sb.st_mode)) || ((rc == -1) && !slash))
267  {
268  /* An existing file or a non-existing path not ending with a slash */
269  mutt_encode_path(hcpath, path);
270  return;
271  }
272 
273  /* We have a directory - no matter whether it exists, or not */
274  struct Buffer *hcfile = mutt_buffer_pool_get();
275  if (namer)
276  {
277  namer(folder, hcfile);
278  mutt_buffer_concat_path(hcpath, path, mutt_b2s(hcfile));
279  }
280  else
281  {
282  unsigned char m[16]; /* binary md5sum */
283  struct Buffer *name = mutt_buffer_pool_get();
284 #ifdef USE_HCACHE_COMPRESSION
285  const char *cm = C_HeaderCacheCompressMethod;
286  mutt_buffer_printf(name, "%s|%s%s", hcache_get_ops()->name, folder, cm ? cm : "");
287 #else
288  mutt_buffer_printf(name, "%s|%s", hcache_get_ops()->name, folder);
289 #endif
290  mutt_md5(mutt_b2s(name), m);
291  mutt_buffer_reset(name);
292  mutt_md5_toascii(m, name->data);
293  mutt_buffer_printf(hcpath, "%s%s%s", path, slash ? "" : "/", mutt_b2s(name));
295  }
296 
297  mutt_encode_path(hcpath, mutt_b2s(hcpath));
298  create_hcache_dir(mutt_b2s(hcpath));
299  mutt_buffer_pool_release(&hcfile);
300 }
301 
307 static char *get_foldername(const char *folder)
308 {
309  /* if the folder is local, canonify the path to avoid
310  * to ensure equivalent paths share the hcache */
311  char *p = mutt_mem_malloc(PATH_MAX + 1);
312  if (!realpath(folder, p))
313  mutt_str_replace(&p, folder);
314 
315  return p;
316 }
317 
321 header_cache_t *mutt_hcache_open(const char *path, const char *folder, hcache_namer_t namer)
322 {
323  const struct StoreOps *ops = hcache_get_ops();
324  if (!ops)
325  return NULL;
326 
328 
329  /* Calculate the current hcache version from dynamic configuration */
330  if (hcachever == 0x0)
331  {
332  union
333  {
334  unsigned char charval[16];
335  unsigned int intval;
336  } digest;
337  struct Md5Ctx md5ctx;
338 
339  hcachever = HCACHEVER;
340 
341  mutt_md5_init_ctx(&md5ctx);
342 
343  /* Seed with the compiled-in header structure hash */
344  mutt_md5_process_bytes(&hcachever, sizeof(hcachever), &md5ctx);
345 
346  /* Mix in user's spam list */
347  struct Replace *sp = NULL;
348  STAILQ_FOREACH(sp, &SpamList, entries)
349  {
350  mutt_md5_process(sp->regex->pattern, &md5ctx);
351  mutt_md5_process(sp->templ, &md5ctx);
352  }
353 
354  /* Mix in user's nospam list */
355  struct RegexNode *np = NULL;
356  STAILQ_FOREACH(np, &NoSpamList, entries)
357  {
358  mutt_md5_process(np->regex->pattern, &md5ctx);
359  }
360 
361  /* Get a hash and take its bytes as an (unsigned int) hash version */
362  mutt_md5_finish_ctx(&md5ctx, digest.charval);
363  hcachever = digest.intval;
364  }
365 
366 #ifdef USE_HCACHE_COMPRESSION
368  {
369  const struct ComprOps *cops = compr_get_ops();
370 
371  hc->cctx = cops->open(C_HeaderCacheCompressLevel);
372  if (!hc->cctx)
373  {
374  FREE(&hc);
375  return NULL;
376  }
377 
378  /* remember the buffer of database backend */
379  mutt_debug(LL_DEBUG3, "Header cache will use %s compression\n", cops->name);
380  }
381 #endif
382 
383  hc->folder = get_foldername(folder);
384  hc->crc = hcachever;
385 
386  if (!path || (path[0] == '\0'))
387  {
388  FREE(&hc->folder);
389  FREE(&hc);
390  return NULL;
391  }
392 
393  struct Buffer *hcpath = mutt_buffer_pool_get();
394  hcache_per_folder(hcpath, path, hc->folder, namer);
395 
396  hc->ctx = ops->open(mutt_b2s(hcpath));
397  if (!hc->ctx)
398  {
399  /* remove a possibly incompatible version */
400  if (unlink(mutt_b2s(hcpath)) == 0)
401  {
402  hc->ctx = ops->open(mutt_b2s(hcpath));
403  if (!hc->ctx)
404  {
405  FREE(&hc->folder);
406  FREE(&hc);
407  }
408  }
409  }
410 
411  mutt_buffer_pool_release(&hcpath);
412  return hc;
413 }
414 
419 {
420  const struct StoreOps *ops = hcache_get_ops();
421  if (!hc || !ops)
422  return;
423 
424 #ifdef USE_HCACHE_COMPRESSION
426  compr_get_ops()->close(&hc->cctx);
427 #endif
428 
429  ops->close(&hc->ctx);
430  FREE(&hc->folder);
431  FREE(&hc);
432 }
433 
438  size_t keylen, uint32_t uidvalidity)
439 {
440  struct RealKey *rk = realkey(key, keylen);
441  struct HCacheEntry entry = { 0 };
442 
443  size_t dlen;
444  void *data = mutt_hcache_fetch_raw(hc, rk->key, rk->len, &dlen);
445  void *to_free = data;
446  if (!data)
447  {
448  goto end;
449  }
450 
451  /* restore uidvalidity and crc */
452  size_t hlen = header_size();
453  int off = 0;
454  serial_restore_uint32_t(&entry.uidvalidity, data, &off);
455  serial_restore_int(&entry.crc, data, &off);
456  assert((size_t) off == hlen);
457  if (entry.crc != hc->crc || ((uidvalidity != 0) && uidvalidity != entry.uidvalidity))
458  {
459  goto end;
460  }
461 
462 #ifdef USE_HCACHE_COMPRESSION
464  {
465  const struct ComprOps *cops = compr_get_ops();
466 
467  void *dblob = cops->decompress(hc->cctx, (char *) data + hlen, dlen - hlen);
468  if (!dblob)
469  {
470  goto end;
471  }
472  data = (char *) dblob - hlen; /* restore skips uidvalidity and crc */
473  }
474 #endif
475 
476  entry.email = restore(data);
477 
478 end:
479  mutt_hcache_free_raw(hc, &to_free);
480  return entry;
481 }
482 
495 void *mutt_hcache_fetch_raw(header_cache_t *hc, const char *key, size_t keylen, size_t *dlen)
496 {
497  const struct StoreOps *ops = hcache_get_ops();
498 
499  if (!hc || !ops)
500  return NULL;
501 
502  struct Buffer path = mutt_buffer_make(1024);
503  keylen = mutt_buffer_printf(&path, "%s%.*s", hc->folder, (int) keylen, key);
504  void *blob = ops->fetch(hc->ctx, mutt_b2s(&path), keylen, dlen);
505  mutt_buffer_dealloc(&path);
506  return blob;
507 }
508 
513 {
514  const struct StoreOps *ops = hcache_get_ops();
515 
516  if (!hc || !ops || !data || !*data)
517  return;
518 
519  ops->free(hc->ctx, data);
520 }
521 
525 int mutt_hcache_store(header_cache_t *hc, const char *key, size_t keylen,
526  struct Email *e, uint32_t uidvalidity)
527 {
528  if (!hc)
529  return -1;
530 
531  int dlen = 0;
532  char *data = dump(hc, e, &dlen, uidvalidity);
533 
534 #ifdef USE_HCACHE_COMPRESSION
536  {
537  /* We don't compress uidvalidity and the crc, so we can check them before
538  * decompressing on fetch(). */
539  size_t hlen = header_size();
540 
541  const struct ComprOps *cops = compr_get_ops();
542 
543  /* data / dlen gets ptr to compressed data here */
544  size_t clen = dlen;
545  void *cdata = cops->compress(hc->cctx, data + hlen, dlen - hlen, &clen);
546  if (!cdata)
547  {
548  FREE(&data);
549  return -1;
550  }
551 
552  char *whole = mutt_mem_malloc(hlen + clen);
553  memcpy(whole, data, hlen);
554  memcpy(whole + hlen, cdata, clen);
555 
556  FREE(&data);
557 
558  data = whole;
559  dlen = hlen + clen;
560  }
561 #endif
562 
563  /* store uncompressed data */
564  struct RealKey *rk = realkey(key, keylen);
565  int rc = mutt_hcache_store_raw(hc, rk->key, rk->len, data, dlen);
566 
567  FREE(&data);
568 
569  return rc;
570 }
571 
582 int mutt_hcache_store_raw(header_cache_t *hc, const char *key, size_t keylen,
583  void *data, size_t dlen)
584 {
585  const struct StoreOps *ops = hcache_get_ops();
586 
587  if (!hc || !ops)
588  return -1;
589 
590  struct Buffer path = mutt_buffer_make(1024);
591 
592  keylen = mutt_buffer_printf(&path, "%s%.*s", hc->folder, (int) keylen, key);
593  int rc = ops->store(hc->ctx, mutt_b2s(&path), keylen, data, dlen);
594  mutt_buffer_dealloc(&path);
595 
596  return rc;
597 }
598 
602 int mutt_hcache_delete_header(header_cache_t *hc, const char *key, size_t keylen)
603 {
604  const struct StoreOps *ops = hcache_get_ops();
605  if (!hc)
606  return -1;
607 
608  struct Buffer path = mutt_buffer_make(1024);
609 
610  keylen = mutt_buffer_printf(&path, "%s%s", hc->folder, key);
611 
612  int rc = ops->delete_record(hc->ctx, mutt_b2s(&path), keylen);
613  mutt_buffer_dealloc(&path);
614  return rc;
615 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:414
char * C_HeaderCacheCompressMethod
Config: (hcache) Enable generic hcache database compression.
Definition: config.c:41
char * templ
Template to match.
Definition: regex3.h:112
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:188
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:98
Cursor for the MD5 hashing.
Definition: md5.h:36
Structs that make up an email.
static void * dump(header_cache_t *hc, const struct Email *e, int *off, uint32_t uidvalidity)
Serialise an Email object.
Definition: hcache.c:89
size_t len
Definition: hcache.c:179
struct MuttThread * thread
Thread of Emails.
Definition: email.h:94
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
short recipient
User_is_recipient()&#39;s return value, cached.
Definition: email.h:77
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:461
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:487
static size_t header_size(void)
Compute the size of the header with uuid validity and crc.
Definition: hcache.c:73
uint32_t uidvalidity
IMAP-specific UIDVALIDITY.
Definition: lib.h:100
struct Body * content
List of MIME parts.
Definition: email.h:90
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
void serial_restore_char(char **c, const unsigned char *d, int *off, bool convert)
Unpack a variable-length string from a binary blob.
Definition: serialize.c:175
struct HCacheEntry mutt_hcache_fetch(header_cache_t *hc, const char *key, size_t keylen, uint32_t uidvalidity)
Multiplexor for StoreOps::fetch.
Definition: hcache.c:437
void *(* compress)(void *cctx, const char *data, size_t dlen, size_t *clen)
Compress header cache data.
Definition: lib.h:81
bool threaded
Used for threading.
Definition: email.h:56
String manipulation buffer.
Definition: buffer.h:33
void * mutt_hcache_fetch_raw(header_cache_t *hc, const char *key, size_t keylen, size_t *dlen)
Fetch a message&#39;s header from the cache.
Definition: hcache.c:495
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:81
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
#define _(a)
Definition: message.h:28
char * folder
Definition: lib.h:87
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:96
static char * get_foldername(const char *folder)
Where should the cache be stored?
Definition: hcache.c:307
int mutt_hcache_store_raw(header_cache_t *hc, const char *key, size_t keylen, void *data, size_t dlen)
store a key / data pair
Definition: hcache.c:582
bool searched
Email has been searched.
Definition: email.h:67
Key Value Store API.
Definition: lib.h:61
void *(* fetch)(void *store, const char *key, size_t klen, size_t *vlen)
Fetch a Value from the Store.
Definition: lib.h:86
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
const char * name
Compression name.
Definition: lib.h:57
List of regular expressions.
Definition: regex3.h:108
void * cctx
Definition: lib.h:90
struct Regex * regex
Regex containing a regular expression.
Definition: regex3.h:110
void mutt_hcache_close(header_cache_t *hc)
Multiplexor for StoreOps::close.
Definition: hcache.c:418
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:108
static bool create_hcache_dir(const char *path)
Create parent dirs for the hcache database.
Definition: hcache.c:211
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)
Close a Store connection.
Definition: lib.h:121
bool tagged
Email is tagged.
Definition: email.h:44
int mutt_hcache_store(header_cache_t *hc, const char *key, size_t keylen, struct Email *e, uint32_t uidvalidity)
Multiplexor for StoreOps::store.
Definition: hcache.c:525
void mutt_md5_toascii(const void *digest, char *resbuf)
Convert a binary MD5 digest into ASCII Hexadecimal.
Definition: md5.c:456
#define STAILQ_INIT(head)
Definition: queue.h:369
char key[1024]
Definition: hcache.c:178
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:875
int(* store)(void *store, const char *key, size_t klen, void *value, size_t vlen)
Write a Value to the Store.
Definition: lib.h:105
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:89
short C_HeaderCacheCompressLevel
Config: (hcache) Level of compression for method.
Definition: config.c:40
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
void *(* open)(const char *path)
Open a connection to a Store.
Definition: lib.h:75
Email-object serialiser.
bool limited
Is this message in a limited view?
Definition: email.h:74
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
void(* hcache_namer_t)(const char *path, struct Buffer *dest)
Prototype for function to compose hcache file names.
Definition: lib.h:110
header_cache_t * mutt_hcache_open(const char *path, const char *folder, hcache_namer_t namer)
Multiplexor for StoreOps::open.
Definition: hcache.c:321
struct TagList tags
For drivers that support server tagging.
Definition: email.h:102
unsigned int crc
Definition: lib.h:88
#define mutt_b2s(buf)
Definition: buffer.h:41
int mutt_hcache_delete_header(header_cache_t *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_header.
Definition: hcache.c:602
struct ListHead chain
Mixmaster chain.
Definition: email.h:99
struct RegexList NoSpamList
List of regexes to whitelist non-spam emails.
Definition: globals.c:43
unsigned char * serial_dump_int(unsigned int i, unsigned char *d, int *off)
Pack an integer into a binary blob.
Definition: serialize.c:65
#define PATH_MAX
Definition: mutt.h:44
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:257
size_t num_hidden
Number of hidden messages in this view.
Definition: email.h:75
struct Regex * regex
Regex containing a regular expression.
Definition: regex3.h:100
char * data
Pointer to data.
Definition: buffer.h:35
static unsigned int hcachever
Definition: hcache.c:61
void *(* open)(short level)
Open a compression context.
Definition: lib.h:67
bool attach_valid
true when the attachment count is valid
Definition: email.h:70
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:73
unsigned char * serial_dump_char(char *c, unsigned char *d, int *off, bool convert)
Pack a variable-length string into a binary blob.
Definition: serialize.c:163
void * ctx
Definition: lib.h:89
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
char * tree
Character string to print thread tree.
Definition: email.h:93
List of regular expressions.
Definition: regex3.h:98
struct ReplaceList SpamList
List of regexes and patterns to match spam emails.
Definition: globals.c:44
int(* delete_record)(void *store, const char *key, size_t klen)
Delete a record from the Store.
Definition: lib.h:115
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
Key value store.
bool CharsetIsUtf8
Is the user&#39;s current character set utf-8?
Definition: charset.c:63
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)
Free a Value returned by fetch()
Definition: lib.h:93
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:451
Header Cache Compression API.
Definition: lib.h:55
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:106
void mutt_hcache_free_raw(header_cache_t *hc, void **data)
Multiplexor for StoreOps::free.
Definition: hcache.c:512
#define mutt_error(...)
Definition: logging.h:84
char * maildir_flags
Unknown maildir flags.
Definition: email.h:104
void lazy_realloc(void *ptr, size_t size)
Reallocate some memory.
Definition: serialize.c:48
char * path
Path of Email (for local Mailboxes)
Definition: email.h:91
unsigned int crc
CRC of Email/Body/etc structs.
Definition: lib.h:101
#define FREE(x)
Definition: memory.h:40
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
#define compr_get_ops()
Definition: hcache.c:66
void *(* decompress)(void *cctx, const char *cbuf, size_t clen)
Decompress header cache data.
Definition: lib.h:94
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:421
bool recip_valid
Is_recipient is valid.
Definition: email.h:58
struct Email * email_new(void)
Create a new Email.
Definition: email.c:68
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct Email * email
Retrieved email.
Definition: lib.h:102
char * pattern
printable version
Definition: regex3.h:90
header cache structure
Definition: lib.h:85
Convenience wrapper for the library headers.
#define hcache_get_ops()
Definition: hcache.c:63
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:535
int pair
Color-pair to use when displaying in the index.
Definition: email.h:79
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:145
void mutt_encode_path(struct Buffer *buf, const char *src)
Convert a path to &#39;us-ascii&#39;.
Definition: muttlib.c:1474