NeoMutt  2025-12-11-980-ge38c27
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
hcache.c
Go to the documentation of this file.
1
24
34
35#include "config.h"
36#include <errno.h>
37#include <limits.h>
38#include <stdbool.h>
39#include <stdint.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <sys/stat.h>
44#include <unistd.h>
45#include "mutt/lib.h"
46#include "config/lib.h"
47#include "email/lib.h"
48#include "core/lib.h"
49#include "lib.h"
50#include "compress/lib.h"
51#include "store/lib.h"
52#include "hcache/hcversion.h" // path needed by out-of-tree build
53#include "module_data.h"
54#include "muttlib.h"
55#include "serialize.h"
56
57#if !(defined(HAVE_GDBM) || defined(HAVE_LMDB) || defined(HAVE_ROCKSDB) || defined(HAVE_TDB))
58#error "No hcache backend defined"
59#endif
60
64struct RealKey
65{
66 char key[1024];
67 size_t keylen;
68};
69
78static struct RealKey *realkey(struct HeaderCache *hc, const char *key,
79 size_t keylen, bool compress)
80{
81 static struct RealKey rk;
82
83 int n = snprintf(rk.key, sizeof(rk.key), "%s/%.*s", hc->folder, (int) keylen, key);
84 if (n < 0)
85 n = 0;
86 rk.keylen = MIN((size_t) n, sizeof(rk.key) - 1);
87
88#ifdef USE_HCACHE_COMPRESSION
89 if (compress && hc->compr_ops)
90 {
91 // Append the compression type, e.g. "-zstd"
92 n = snprintf(rk.key + rk.keylen, sizeof(rk.key) - rk.keylen, "-%s",
93 hc->compr_ops->name);
94 if (n > 0)
95 rk.keylen += MIN((size_t) n, sizeof(rk.key) - 1 - rk.keylen);
96 }
97#endif
98
99 return &rk;
100}
101
106static void hcache_free(struct HeaderCache **ptr)
107{
108 if (!ptr || !*ptr)
109 return;
110
111 struct HeaderCache *hc = *ptr;
112 FREE(&hc->folder);
113
114 FREE(ptr);
115}
116
121static struct HeaderCache *hcache_new(void)
122{
123 return MUTT_MEM_CALLOC(1, struct HeaderCache);
124}
125
130static size_t header_size(void)
131{
132 return sizeof(int) + sizeof(uint32_t);
133}
134
142static inline uint32_t email_pack_flags(const struct Email *e)
143{
144 if (!e)
145 return 0;
146
147 // clang-format off
148 return e->security +
149 (e->expired << 16) +
150 (e->flagged << 17) +
151 (e->mime << 18) +
152 (e->old << 19) +
153 (e->read << 20) +
154 (e->replied << 21) +
155 (e->superseded << 22) +
156 (e->trash << 23);
157 // clang-format on
158}
159
167static inline void email_unpack_flags(struct Email *e, uint32_t packed)
168{
169 if (!e)
170 return;
171
172 // clang-format off
173 e->security = (packed & ((1 << 16) - 1)); // bits 0-15
174 e->expired = (packed & (1 << 16));
175 e->flagged = (packed & (1 << 17));
176 e->mime = (packed & (1 << 18));
177 e->old = (packed & (1 << 19));
178 e->read = (packed & (1 << 20));
179 e->replied = (packed & (1 << 21));
180 e->superseded = (packed & (1 << 22));
181 e->trash = (packed & (1 << 23));
182 // clang-format on
183}
184
192static inline uint32_t email_pack_timezone(const struct Email *e)
193{
194 if (!e)
195 return 0;
196
197 return e->zhours + (e->zminutes << 5) + (e->zoccident << 11);
198}
199
207static inline void email_unpack_timezone(struct Email *e, uint32_t packed)
208{
209 if (!e)
210 return;
211
212 // clang-format off
213 e->zhours = (packed & ((1 << 5) - 1)); // bits 0-4 (5)
214 e->zminutes = ((packed >> 5) & ((1 << 6) - 1)); // bits 5-10 (6)
215 e->zoccident = (packed & (1 << 11)); // bit 11 (1)
216 // clang-format on
217}
218
230static void *dump_email(struct HeaderCache *hc, const struct Email *e, int *off, uint32_t uidvalidity)
231{
232 bool convert = !CharsetIsUtf8;
233
234 *off = 0;
235 unsigned char *d = MUTT_MEM_MALLOC(4096, unsigned char);
236
237 d = serial_dump_uint32_t((uidvalidity != 0) ? uidvalidity : mutt_date_now(), d, off);
238 d = serial_dump_int(hc->crc, d, off);
239
240 ASSERT((size_t) *off == header_size());
241
242 uint32_t packed = email_pack_flags(e);
243 d = serial_dump_uint32_t(packed, d, off);
244
245 packed = email_pack_timezone(e);
246 d = serial_dump_uint32_t(packed, d, off);
247
248 uint64_t big = e->date_sent;
249 d = serial_dump_uint64_t(big, d, off);
250 big = e->received;
251 d = serial_dump_uint64_t(big, d, off);
252
253 d = serial_dump_int(e->lines, d, off);
254
255 d = serial_dump_envelope(e->env, d, off, convert);
256 d = serial_dump_body(e->body, d, off, convert);
257 d = serial_dump_tags(&e->tags, d, off);
258
259 return d;
260}
261
272static struct Email *restore_email(const unsigned char *d, size_t dlen)
273{
274 int off = 0;
275 struct Email *e = email_new();
276 bool convert = !CharsetIsUtf8;
277 uint32_t packed = 0;
278 uint64_t big = 0;
279 unsigned int num = 0;
280
281 off += sizeof(uint32_t); // skip validate
282 off += sizeof(unsigned int); // skip crc
283
284 if (!serial_restore_uint32_t(&packed, d, &off, dlen))
285 goto fail;
286 email_unpack_flags(e, packed);
287
288 packed = 0;
289 if (!serial_restore_uint32_t(&packed, d, &off, dlen))
290 goto fail;
291 email_unpack_timezone(e, packed);
292
293 if (!serial_restore_uint64_t(&big, d, &off, dlen))
294 goto fail;
295 e->date_sent = big;
296
297 big = 0;
298 if (!serial_restore_uint64_t(&big, d, &off, dlen))
299 goto fail;
300 e->received = big;
301
302 if (!serial_restore_int(&num, d, &off, dlen))
303 goto fail;
304 e->lines = num;
305
306 e->env = mutt_env_new();
307 if (!serial_restore_envelope(e->env, d, &off, dlen, convert))
308 goto fail;
309
310 e->body = mutt_body_new();
311 if (!serial_restore_body(e->body, d, &off, dlen, convert))
312 goto fail;
313
314 if (!serial_restore_tags(&e->tags, d, &off, dlen))
315 goto fail;
316
317 return e;
318
319fail:
320 email_free(&e);
321 return NULL;
322}
323
330static bool create_hcache_dir(const char *path)
331{
332 char *dir = mutt_str_dup(path);
333 if (!dir)
334 return false;
335
336 char *p = strrchr(dir, '/');
337 if (!p)
338 {
339 FREE(&dir);
340 return true;
341 }
342
343 *p = '\0';
344
345 int rc = mutt_file_mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO);
346 if (rc != 0)
347 mutt_error(_("Can't create %s: %s"), dir, strerror(errno));
348
349 FREE(&dir);
350 return (rc == 0);
351}
352
374static void hcache_per_folder(struct HeaderCache *hc, struct Buffer *hcpath,
375 const char *path, hcache_namer_t namer)
376{
377 struct stat st = { 0 };
378
379 int plen = mutt_str_len(path);
380 int rc = stat(path, &st);
381 bool slash = (path[plen - 1] == '/');
382
383 if (((rc == 0) && !S_ISDIR(st.st_mode)) || ((rc == -1) && !slash))
384 {
385 /* An existing file or a non-existing path not ending with a slash */
386 mutt_encode_path(hcpath, path);
388 return;
389 }
390
391 /* We have a directory - no matter whether it exists, or not */
392 struct Buffer *hcfile = buf_pool_get();
393 if (namer)
394 {
395 namer(hc->store_ops, hc->folder, hcfile);
396 mutt_encode_path(hcfile, buf_string(hcfile));
397 buf_concat_path(hcpath, path, buf_string(hcfile));
398 }
399 else
400 {
401 unsigned char m[16] = { 0 }; /* binary md5sum */
402 struct Buffer *name = buf_pool_get();
403
404#ifdef USE_HCACHE_COMPRESSION
405 const char *cm = hc->compr_ops ? hc->compr_ops->name : "";
406 buf_printf(name, "%s|%s%s", hc->store_ops->name, hc->folder, cm);
407#else
408 buf_printf(name, "%s|%s", hc->store_ops->name, hc->folder);
409#endif
410 mutt_md5(buf_string(name), m);
411 buf_reset(name);
412 mutt_md5_toascii(m, name->data);
413 mutt_encode_path(name, buf_string(name));
414 buf_printf(hcpath, "%s%s%s", path, slash ? "" : "/", buf_string(name));
415 buf_pool_release(&name);
416 }
417
419 buf_pool_release(&hcfile);
420}
421
427static char *get_foldername(const char *folder)
428{
429 /* if the folder is local, canonify the path to ensure equivalent paths share
430 * the hcache */
431 char *p = MUTT_MEM_MALLOC(PATH_MAX + 1, char);
432 if (!realpath(folder, p))
433 mutt_str_replace(&p, folder);
434
435 return p;
436}
437
441static void free_raw(struct HeaderCache *hc, void **data)
442{
443 hc->store_ops->free(hc->store_handle, data);
444}
445
450static unsigned int generate_hcachever(void)
451{
452 union
453 {
454 unsigned char charval[16];
455 unsigned int intval;
456 } digest = { 0 };
457 struct Md5Ctx md5ctx = { 0 };
458
459 mutt_md5_init_ctx(&md5ctx);
460
461 /* Seed with the compiled-in header structure hash */
462 unsigned int ver = HCACHEVER;
463 mutt_md5_process_bytes(&ver, sizeof(ver), &md5ctx);
464
466 ASSERT(mod_data);
467
468 /* Mix in user's spam list */
469 struct Replace *sp = NULL;
470 STAILQ_FOREACH(sp, &mod_data->spam, entries)
471 {
472 mutt_md5_process(sp->regex->pattern, &md5ctx);
473 mutt_md5_process(sp->templ, &md5ctx);
474 }
475
476 /* Mix in user's nospam list */
477 struct RegexNode *np = NULL;
478 STAILQ_FOREACH(np, &mod_data->no_spam, entries)
479 {
480 mutt_md5_process(np->regex->pattern, &md5ctx);
481 }
482
483 /* Get a hash and take its bytes as an (unsigned int) hash version */
484 mutt_md5_finish_ctx(&md5ctx, digest.charval);
485
486 return digest.intval;
487}
488
492struct HeaderCache *hcache_open(const char *path, const char *folder,
493 hcache_namer_t namer, bool create)
494{
495 if (!path || (path[0] == '\0'))
496 return NULL;
497
499 if (mod_data->hcache_ver == 0x0)
500 mod_data->hcache_ver = generate_hcachever();
501
502 struct HeaderCache *hc = hcache_new();
503
505 hc->crc = mod_data->hcache_ver;
506
507 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
508 hc->store_ops = store_get_backend_ops(c_header_cache_backend);
509 if (!hc->store_ops)
510 {
511 hcache_free(&hc);
512 return NULL;
513 }
514
515#ifdef USE_HCACHE_COMPRESSION
516 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
517 if (c_header_cache_compress_method)
518 {
519 hc->compr_ops = compress_get_ops(c_header_cache_compress_method);
520
521 const short c_header_cache_compress_level = cs_subset_number(NeoMutt->sub, "header_cache_compress_level");
522 hc->compr_handle = hc->compr_ops->open(c_header_cache_compress_level);
523 if (!hc->compr_handle)
524 {
525 hcache_free(&hc);
526 return NULL;
527 }
528
529 /* remember the buffer of database backend */
530 mutt_debug(LL_DEBUG3, "Header cache will use %s compression\n",
531 hc->compr_ops->name);
532 }
533#endif
534
535 struct Buffer *hcpath = buf_pool_get();
536 hcache_per_folder(hc, hcpath, path, namer);
537
538 hc->store_handle = hc->store_ops->open(buf_string(hcpath), create);
539 if (!hc->store_handle)
540 {
541 /* remove a possibly incompatible version */
542 if (unlink(buf_string(hcpath)) == 0)
543 {
544 hc->store_handle = hc->store_ops->open(buf_string(hcpath), create);
545 }
546 }
547
548 if (!hc->store_handle)
549 {
550 if (hc->compr_ops)
551 {
552 hc->compr_ops->close(&hc->compr_handle);
553 }
554 hcache_free(&hc);
555 }
556
557 buf_pool_release(&hcpath);
558 return hc;
559}
560
564void hcache_close(struct HeaderCache **ptr)
565{
566 if (!ptr || !*ptr)
567 return;
568
569 struct HeaderCache *hc = *ptr;
570
571#ifdef USE_HCACHE_COMPRESSION
572 if (hc->compr_ops)
573 hc->compr_ops->close(&hc->compr_handle);
574#endif
575
576 hc->store_ops->close(&hc->store_handle);
577
578 hcache_free(ptr);
579}
580
584struct HCacheEntry hcache_fetch_email(struct HeaderCache *hc, const char *key,
585 size_t keylen, uint32_t uidvalidity)
586{
587 struct HCacheEntry hce = { 0 };
588 if (!hc)
589 return hce;
590
591 size_t dlen = 0;
592 struct RealKey *rk = realkey(hc, key, keylen, true);
593 void *data = hc->store_ops->fetch(hc->store_handle, rk->key, rk->keylen, &dlen);
594 void *to_free = data;
595 if (!data)
596 {
597 goto end;
598 }
599
600 /* restore uidvalidity and crc */
601 size_t hlen = header_size();
602 if (hlen > dlen)
603 {
604 goto end;
605 }
606 int off = 0;
607 serial_restore_uint32_t(&hce.uidvalidity, data, &off, dlen);
608 serial_restore_int(&hce.crc, data, &off, dlen);
609 ASSERT((size_t) off == hlen);
610 if ((hce.crc != hc->crc) || ((uidvalidity != 0) && (uidvalidity != hce.uidvalidity)))
611 {
612 goto end;
613 }
614
615#ifdef USE_HCACHE_COMPRESSION
616 if (hc->compr_ops)
617 {
618 size_t ulen = 0;
619 void *dblob = hc->compr_ops->decompress(hc->compr_handle, (char *) data + hlen,
620 dlen - hlen, &ulen);
621 if (!dblob)
622 {
623 goto end;
624 }
625 data = (char *) dblob - hlen; /* restore skips uidvalidity and crc */
626 dlen = hlen + ulen;
627 }
628#endif
629
630 hce.email = restore_email(data, dlen);
631
632end:
633 free_raw(hc, &to_free);
634 return hce;
635}
636
647bool hcache_fetch_raw_obj_full(struct HeaderCache *hc, const char *key,
648 size_t keylen, void *dst, size_t dstlen)
649{
650 if (!hc)
651 return false;
652
653 bool rc = true;
654 size_t srclen = 0;
655
656 struct RealKey *rk = realkey(hc, key, keylen, false);
657 void *src = hc->store_ops->fetch(hc->store_handle, rk->key, rk->keylen, &srclen);
658
659 if (src && (srclen == dstlen))
660 {
661 memcpy(dst, src, dstlen);
662 }
663 else
664 {
665 rc = false;
666 }
667 free_raw(hc, &src);
668 return rc;
669}
670
679char *hcache_fetch_raw_str(struct HeaderCache *hc, const char *key, size_t keylen)
680{
681 if (!hc)
682 return NULL;
683
684 char *res = NULL;
685 size_t dlen = 0;
686
687 struct RealKey *rk = realkey(hc, key, keylen, false);
688 void *data = hc->store_ops->fetch(hc->store_handle, rk->key, rk->keylen, &dlen);
689 if (data)
690 {
691 res = mutt_strn_dup(data, dlen);
692 free_raw(hc, &data);
693 }
694 return res;
695}
696
700int hcache_store_email(struct HeaderCache *hc, const char *key, size_t keylen,
701 struct Email *e, uint32_t uidvalidity)
702{
703 if (!hc)
704 return -1;
705
706 int dlen = 0;
707 char *data = dump_email(hc, e, &dlen, uidvalidity);
708
709#ifdef USE_HCACHE_COMPRESSION
710 if (hc->compr_ops)
711 {
712 /* We don't compress uidvalidity and the crc, so we can check them before
713 * decompressing on fetch(). */
714 size_t hlen = header_size();
715
716 /* data / dlen gets ptr to compressed data here */
717 size_t clen = dlen;
718 void *cdata = hc->compr_ops->compress(hc->compr_handle, data + hlen, dlen - hlen, &clen);
719 if (!cdata)
720 {
721 FREE(&data);
722 return -1;
723 }
724
725 char *whole = MUTT_MEM_MALLOC(hlen + clen, char);
726 memcpy(whole, data, hlen);
727 memcpy(whole + hlen, cdata, clen);
728
729 FREE(&data);
730
731 data = whole;
732 dlen = hlen + clen;
733 }
734#endif
735
736 struct RealKey *rk = realkey(hc, key, keylen, true);
737 int rc = hc->store_ops->store(hc->store_handle, rk->key, rk->keylen, data, dlen);
738
739 FREE(&data);
740
741 return rc;
742}
743
754int hcache_store_raw(struct HeaderCache *hc, const char *key, size_t keylen,
755 void *data, size_t dlen)
756{
757 if (!hc)
758 return -1;
759
760 struct RealKey *rk = realkey(hc, key, keylen, false);
761 int rc = hc->store_ops->store(hc->store_handle, rk->key, rk->keylen, data, dlen);
762
763 return rc;
764}
765
769int hcache_delete_email(struct HeaderCache *hc, const char *key, size_t keylen)
770{
771 if (!hc)
772 return -1;
773
774 struct RealKey *rk = realkey(hc, key, keylen, true);
775
776 return hc->store_ops->delete_record(hc->store_handle, rk->key, rk->keylen);
777}
778
782int hcache_delete_raw(struct HeaderCache *hc, const char *key, size_t keylen)
783{
784 if (!hc)
785 return -1;
786
787 struct RealKey *rk = realkey(hc, key, keylen, false);
788
789 return hc->store_ops->delete_record(hc->store_handle, rk->key, rk->keylen);
790}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:168
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:89
size_t buf_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition buffer.c:515
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
const struct ComprOps * compress_get_ops(const char *compr)
Get the API functions for a compress backend.
Definition compress.c:78
API for the header cache compression.
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition helpers.c:143
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
struct Body * mutt_body_new(void)
Create a new Body.
Definition body.c:44
struct Email * email_new(void)
Create a new Email.
Definition email.c:77
void email_free(struct Email **ptr)
Free an Email.
Definition email.c:46
Structs that make up an email.
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition envelope.c:45
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition file.c:844
#define mutt_error(...)
Definition logging2.h:94
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
static void hcache_free(struct HeaderCache **ptr)
Free a header cache.
Definition hcache.c:106
static struct HeaderCache * hcache_new(void)
Create a new header cache.
Definition hcache.c:121
static void email_unpack_flags(struct Email *e, uint32_t packed)
Unpack the Email flags from a uint32_t.
Definition hcache.c:167
static bool create_hcache_dir(const char *path)
Create parent dirs for the hcache database.
Definition hcache.c:330
struct HeaderCache * hcache_open(const char *path, const char *folder, hcache_namer_t namer, bool create)
Multiplexor for StoreOps::open.
Definition hcache.c:492
static void email_unpack_timezone(struct Email *e, uint32_t packed)
Unpack the Email timezone from a uint32_t.
Definition hcache.c:207
int hcache_delete_email(struct HeaderCache *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_record.
Definition hcache.c:769
void hcache_close(struct HeaderCache **ptr)
Multiplexor for StoreOps::close.
Definition hcache.c:564
static void free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition hcache.c:441
static void * dump_email(struct HeaderCache *hc, const struct Email *e, int *off, uint32_t uidvalidity)
Serialise an Email object.
Definition hcache.c:230
struct HCacheEntry hcache_fetch_email(struct HeaderCache *hc, const char *key, size_t keylen, uint32_t uidvalidity)
Multiplexor for StoreOps::fetch.
Definition hcache.c:584
static struct Email * restore_email(const unsigned char *d, size_t dlen)
Restore an Email from data retrieved from the cache.
Definition hcache.c:272
static uint32_t email_pack_flags(const struct Email *e)
Pack the Email flags into a uint32_t.
Definition hcache.c:142
static unsigned int generate_hcachever(void)
Calculate hcache version from dynamic configuration.
Definition hcache.c:450
static uint32_t email_pack_timezone(const struct Email *e)
Pack the Email timezone into a uint32_t.
Definition hcache.c:192
int hcache_store_email(struct HeaderCache *hc, const char *key, size_t keylen, struct Email *e, uint32_t uidvalidity)
Multiplexor for StoreOps::store.
Definition hcache.c:700
char * hcache_fetch_raw_str(struct HeaderCache *hc, const char *key, size_t keylen)
Fetch a string from the cache.
Definition hcache.c:679
bool hcache_fetch_raw_obj_full(struct HeaderCache *hc, const char *key, size_t keylen, void *dst, size_t dstlen)
Fetch a message's header from the cache into a destination object.
Definition hcache.c:647
int hcache_delete_raw(struct HeaderCache *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_record.
Definition hcache.c:782
static struct RealKey * realkey(struct HeaderCache *hc, const char *key, size_t keylen, bool compress)
Compute the real key used in the backend, taking into account the compression method.
Definition hcache.c:78
static size_t header_size(void)
Compute the size of the header with uuid validity and crc.
Definition hcache.c:130
int 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:754
static void hcache_per_folder(struct HeaderCache *hc, struct Buffer *hcpath, const char *path, hcache_namer_t namer)
Generate the hcache pathname.
Definition hcache.c:374
static char * get_foldername(const char *folder)
Where should the cache be stored?
Definition hcache.c:427
Header cache multiplexor.
void(* hcache_namer_t)(const struct StoreOps *store_ops, const char *path, struct Buffer *dest)
Definition lib.h:119
Hcache private Module data.
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:47
void * mutt_md5(const char *str, void *buf)
Calculate the MD5 hash of a NUL-terminated string.
Definition md5.c:317
void mutt_md5_process_bytes(const void *buf, size_t buflen, struct Md5Ctx *md5ctx)
Process a block of data.
Definition md5.c:373
void mutt_md5_process(const char *str, struct Md5Ctx *md5ctx)
Process a NUL-terminated string.
Definition md5.c:355
void mutt_md5_init_ctx(struct Md5Ctx *md5ctx)
Initialise the MD5 computation.
Definition md5.c:261
void * mutt_md5_finish_ctx(struct Md5Ctx *md5ctx, void *resbuf)
Process the remaining bytes in the buffer.
Definition md5.c:285
void mutt_md5_toascii(const void *digest, char *resbuf)
Convert a binary MD5 digest into ASCII Hexadecimal.
Definition md5.c:456
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define MIN(a, b)
Return the minimum of two values.
Definition memory.h:40
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:52
#define MUTT_MEM_MALLOC(n, type)
Definition memory.h:53
@ MODULE_ID_EMAIL
ModuleEmail, Email code
Definition module_api.h:64
@ MODULE_ID_HCACHE
ModuleHcache, Email Header Cache
Definition module_api.h:68
bool CharsetIsUtf8
Is the user's current character set utf-8?
Definition charset.c:67
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition date.c:459
Convenience wrapper for the library headers.
#define _(a)
Definition message.h:28
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition string.c:384
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:503
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:284
#define PATH_MAX
Definition mutt.h:49
void mutt_encode_path(struct Buffer *buf, const char *src)
Convert a path to 'us-ascii'.
Definition muttlib.c:803
Some miscellaneous functions.
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:666
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
#define STAILQ_FOREACH(var, head, field)
Definition queue.h:390
unsigned char * serial_dump_body(const struct Body *b, unsigned char *d, int *off, bool convert)
Pack an Body into a binary blob.
Definition serialize.c:611
bool serial_restore_uint32_t(uint32_t *s, const unsigned char *d, int *off, size_t dlen)
Unpack an uint32_t from a binary blob.
Definition serialize.c:159
unsigned char * serial_dump_tags(const struct TagList *tl, unsigned char *d, int *off)
Pack a TagList into a binary blob.
Definition serialize.c:821
unsigned char * serial_dump_uint64_t(const uint64_t s, unsigned char *d, int *off)
Pack a uint64_t into a binary blob.
Definition serialize.c:122
unsigned char * serial_dump_int(const unsigned int i, unsigned char *d, int *off)
Pack an integer into a binary blob.
Definition serialize.c:90
unsigned char * serial_dump_envelope(const struct Envelope *env, unsigned char *d, int *off, bool convert)
Pack an Envelope into a binary blob.
Definition serialize.c:695
bool serial_restore_uint64_t(uint64_t *s, const unsigned char *d, int *off, size_t dlen)
Unpack an uint64_t from a binary blob.
Definition serialize.c:178
bool serial_restore_tags(struct TagList *tl, const unsigned char *d, int *off, size_t dlen)
Unpack a TagList from a binary blob.
Definition serialize.c:849
unsigned char * serial_dump_uint32_t(const uint32_t s, unsigned char *d, int *off)
Pack a uint32_t into a binary blob.
Definition serialize.c:106
bool serial_restore_int(unsigned int *i, const unsigned char *d, int *off, size_t dlen)
Unpack an integer from a binary blob.
Definition serialize.c:140
bool serial_restore_body(struct Body *b, const unsigned char *d, int *off, size_t dlen, bool convert)
Unpack a Body from a binary blob.
Definition serialize.c:646
bool serial_restore_envelope(struct Envelope *env, const unsigned char *d, int *off, size_t dlen, bool convert)
Unpack an Envelope from a binary blob.
Definition serialize.c:746
Email-object serialiser.
#define ASSERT(COND)
Definition signal2.h:59
Key value store.
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition store.c:88
String manipulation buffer.
Definition buffer.h:36
char * data
Pointer to data.
Definition buffer.h:37
ComprHandle *(* open)(short level)
Definition lib.h:79
const char * name
Compression name.
Definition lib.h:66
void *(* compress)(ComprHandle *handle, const char *data, size_t dlen, size_t *clen)
Definition lib.h:96
void(* close)(ComprHandle **ptr)
Definition lib.h:125
Email private Module data.
Definition module_data.h:32
struct ReplaceList spam
Regexes and patterns to match spam emails.
Definition module_data.h:40
struct RegexList no_spam
Regexes to identify non-spam emails.
Definition module_data.h:39
The envelope/body of an email.
Definition email.h:39
bool read
Email is read.
Definition email.h:50
unsigned int zminutes
Minutes away from UTC.
Definition email.h:57
struct Envelope * env
Envelope information.
Definition email.h:68
bool mime
Has a MIME-Version header?
Definition email.h:48
int lines
How many lines in the body of this message?
Definition email.h:62
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition email.h:43
struct Body * body
List of MIME parts.
Definition email.h:69
bool old
Email is seen, but unread.
Definition email.h:49
bool zoccident
True, if west of UTC, False if east.
Definition email.h:58
bool flagged
Marked important?
Definition email.h:47
unsigned int zhours
Hours away from UTC.
Definition email.h:56
time_t date_sent
Time when the message was sent (UTC)
Definition email.h:60
bool replied
Email has been replied to.
Definition email.h:51
bool expired
Already expired?
Definition email.h:46
struct TagList tags
For drivers that support server tagging.
Definition email.h:72
char * path
Path of Email (for local Mailboxes)
Definition email.h:70
bool trash
Message is marked as trashed on disk (used by the maildir_trash option)
Definition email.h:53
bool superseded
Got superseded?
Definition email.h:52
time_t received
Time when the message was placed in the mailbox.
Definition email.h:61
Wrapper for Email retrieved from the header cache.
Definition lib.h:100
uint32_t uidvalidity
IMAP-specific UIDVALIDITY.
Definition lib.h:101
struct Email * email
Retrieved email.
Definition lib.h:103
unsigned int crc
CRC of Email/Body/etc structs.
Definition lib.h:102
Hcache private Module data.
Definition module_data.h:30
unsigned int hcache_ver
Header Cache version.
Definition module_data.h:32
Header Cache.
Definition lib.h:87
ComprHandle * compr_handle
Compression handle.
Definition lib.h:93
unsigned int crc
CRC of the cache entry.
Definition lib.h:89
char * folder
Folder name.
Definition lib.h:88
const struct StoreOps * store_ops
Store backend.
Definition lib.h:90
StoreHandle * store_handle
Store handle.
Definition lib.h:91
const struct ComprOps * compr_ops
Compression backend.
Definition lib.h:92
Cursor for the MD5 hashing.
Definition md5.h:37
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
Hcache key name (including compression method)
Definition hcache.c:65
char key[1024]
Key name.
Definition hcache.c:66
size_t keylen
Length of key.
Definition hcache.c:67
List of regular expressions.
Definition regex3.h:95
struct Regex * regex
Regex containing a regular expression.
Definition regex3.h:96
char * pattern
printable version
Definition regex3.h:86
List of regular expressions.
Definition regex3.h:105
char * templ
Template to match.
Definition regex3.h:108
struct Regex * regex
Regex containing a regular expression.
Definition regex3.h:106
void(* close)(StoreHandle **ptr)
Definition lib.h:144
int(* store)(StoreHandle *store, const char *key, size_t klen, void *value, size_t vlen)
Definition lib.h:122
const char * name
Store name.
Definition lib.h:67
int(* delete_record)(StoreHandle *store, const char *key, size_t klen)
Definition lib.h:135
StoreHandle *(* open)(const char *path, bool create)
Definition lib.h:83
void *(* fetch)(StoreHandle *store, const char *key, size_t klen, size_t *vlen)
Definition lib.h:97
void(* free)(StoreHandle *store, void **ptr)
Definition lib.h:107