NeoMutt  2022-04-29-249-gaae397
Teaching an old dog new tricks
DOXYGEN
lib.h File Reference

Header cache multiplexor. More...

#include <stddef.h>
#include <stdint.h>
+ Include dependency graph for lib.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  HeaderCache
 Header cache structure. More...
 
struct  HCacheEntry
 Wrapper for Email retrieved from the header cache. More...
 

Typedefs

typedef void(* hcache_namer_t) (const char *path, struct Buffer *dest)
 

Functions

struct HeaderCachemutt_hcache_open (const char *path, const char *folder, hcache_namer_t namer)
 Open the connection to the header cache. More...
 
void mutt_hcache_close (struct HeaderCache *hc)
 Close the connection to the header cache. More...
 
int mutt_hcache_store (struct HeaderCache *hc, const char *key, size_t keylen, struct Email *e, uint32_t uidvalidity)
 Store a Header along with a validity datum. More...
 
struct HCacheEntry mutt_hcache_fetch (struct HeaderCache *hc, const char *key, size_t keylen, uint32_t uidvalidity)
 Fetch and validate a message's header from the cache. More...
 
int mutt_hcache_store_raw (struct HeaderCache *hc, const char *key, size_t keylen, void *data, size_t dlen)
 Store a key / data pair. More...
 
void * mutt_hcache_fetch_raw (struct HeaderCache *hc, const char *key, size_t keylen, size_t *dlen)
 Fetch a message's header from the cache. More...
 
void mutt_hcache_free_raw (struct HeaderCache *hc, void **data)
 Free data fetched with mutt_hcache_fetch_raw() More...
 
int mutt_hcache_delete_record (struct HeaderCache *hc, const char *key, size_t keylen)
 Delete a key / data pair. More...
 

Detailed Description

Header cache multiplexor.

Authors
  • Thomas Glanzmann
  • Tobias Werth
  • Brian Fundakowski Feldman
  • Pietro Cerutti
  • Tino Reichardt

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, see http://www.gnu.org/licenses/.

Definition in file lib.h.

Typedef Documentation

◆ hcache_namer_t

typedef void(* hcache_namer_t) (const char *path, struct Buffer *dest)

Definition at line 112 of file lib.h.

Function Documentation

◆ mutt_hcache_open()

struct HeaderCache * mutt_hcache_open ( const char *  path,
const char *  folder,
hcache_namer_t  namer 
)

Open the connection to the header cache.

Parameters
pathLocation of the header cache (often as specified by the user)
folderName of the folder containing the messages
namerOptional (might be NULL) client-specific function to form the final name of the hcache database file.
Return values
ptrSuccess, struct HeaderCache struct
NULLOtherwise

Open the connection to the header cache.

< MD5 digest as a string

< MD5 digest as an integer

Definition at line 332 of file hcache.c.

333{
334 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
335 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
336 if (!ops)
337 return NULL;
338
339 struct HeaderCache *hc = mutt_mem_calloc(1, sizeof(struct HeaderCache));
340
341 /* Calculate the current hcache version from dynamic configuration */
342 if (hcachever == 0x0)
343 {
344 union
345 {
346 unsigned char charval[16];
347 unsigned int intval;
348 } digest;
349 struct Md5Ctx md5ctx;
350
351 hcachever = HCACHEVER;
352
353 mutt_md5_init_ctx(&md5ctx);
354
355 /* Seed with the compiled-in header structure hash */
356 mutt_md5_process_bytes(&hcachever, sizeof(hcachever), &md5ctx);
357
358 /* Mix in user's spam list */
359 struct Replace *sp = NULL;
360 STAILQ_FOREACH(sp, &SpamList, entries)
361 {
362 mutt_md5_process(sp->regex->pattern, &md5ctx);
363 mutt_md5_process(sp->templ, &md5ctx);
364 }
365
366 /* Mix in user's nospam list */
367 struct RegexNode *np = NULL;
368 STAILQ_FOREACH(np, &NoSpamList, entries)
369 {
370 mutt_md5_process(np->regex->pattern, &md5ctx);
371 }
372
373 /* Get a hash and take its bytes as an (unsigned int) hash version */
374 mutt_md5_finish_ctx(&md5ctx, digest.charval);
375 hcachever = digest.intval;
376 }
377
378 const struct ComprOps *cops = NULL;
379#ifdef USE_HCACHE_COMPRESSION
380 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
381 if (c_header_cache_compress_method)
382 {
383 cops = compress_get_ops(c_header_cache_compress_method);
384
385 const short c_header_cache_compress_level = cs_subset_number(NeoMutt->sub, "header_cache_compress_level");
386 hc->cctx = cops->open(c_header_cache_compress_level);
387 if (!hc->cctx)
388 {
389 FREE(&hc);
390 return NULL;
391 }
392
393 /* remember the buffer of database backend */
394 mutt_debug(LL_DEBUG3, "Header cache will use %s compression\n", cops->name);
395 }
396#endif
397
398 hc->folder = get_foldername(folder);
399 hc->crc = hcachever;
400
401 if (!path || (path[0] == '\0'))
402 {
403 if (cops)
404 {
405 cops->close(&hc->cctx);
406 }
407
408 FREE(&hc->folder);
409 FREE(&hc);
410 return NULL;
411 }
412
413 struct Buffer *hcpath = mutt_buffer_pool_get();
414 hcache_per_folder(hcpath, path, hc->folder, namer);
415
416 hc->ctx = ops->open(mutt_buffer_string(hcpath));
417 if (!hc->ctx)
418 {
419 /* remove a possibly incompatible version */
420 if (unlink(mutt_buffer_string(hcpath)) == 0)
421 {
422 hc->ctx = ops->open(mutt_buffer_string(hcpath));
423 if (!hc->ctx)
424 {
425 if (cops)
426 {
427 cops->close(&hc->cctx);
428 }
429 FREE(&hc->folder);
430 FREE(&hc);
431 }
432 }
433 }
434
436 return hc;
437}
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
const struct ComprOps * compress_get_ops(const char *compr)
Get the API functions for a compress backend.
Definition: compress.c:80
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
struct ReplaceList SpamList
List of regexes and patterns to match spam emails.
Definition: globals.c:34
struct RegexList NoSpamList
List of regexes to whitelist non-spam emails.
Definition: globals.c:33
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
static unsigned int hcachever
Definition: hcache.c:63
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:262
static char * get_foldername(const char *folder)
Where should the cache be stored?
Definition: hcache.c:318
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
void mutt_md5_process_bytes(const void *buf, size_t buflen, struct Md5Ctx *md5ctx)
Process a block of data.
Definition: md5.c:374
void mutt_md5_process(const char *str, struct Md5Ctx *md5ctx)
Process a NULL-terminated string.
Definition: md5.c:356
void mutt_md5_init_ctx(struct Md5Ctx *md5ctx)
Initialise the MD5 computation.
Definition: md5.c:262
void * mutt_md5_finish_ctx(struct Md5Ctx *md5ctx, void *resbuf)
Process the remaining bytes in the buffer.
Definition: md5.c:286
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define FREE(x)
Definition: memory.h:43
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition: store.c:107
String manipulation buffer.
Definition: buffer.h:34
Definition: lib.h:60
void(* close)(void **cctx)
Definition: lib.h:119
void *(* open)(short level)
Definition: lib.h:74
const char * name
Compression name.
Definition: lib.h:61
Header cache structure.
Definition: lib.h:87
void * ctx
Store context (handle)
Definition: lib.h:90
unsigned int crc
CRC of the cache entry.
Definition: lib.h:89
char * folder
Folder name.
Definition: lib.h:88
void * cctx
Compression context (handle)
Definition: lib.h:91
Cursor for the MD5 hashing.
Definition: md5.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
List of regular expressions.
Definition: regex3.h:99
struct Regex * regex
Regex containing a regular expression.
Definition: regex3.h:100
char * pattern
printable version
Definition: regex3.h:90
List of regular expressions.
Definition: regex3.h:109
char * templ
Template to match.
Definition: regex3.h:112
struct Regex * regex
Regex containing a regular expression.
Definition: regex3.h:110
Definition: lib.h:66
void *(* open)(const char *path)
Definition: lib.h:82
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_close()

void mutt_hcache_close ( struct HeaderCache hc)

Close the connection to the header cache.

Parameters
hcPointer to the struct HeaderCache structure got by mutt_hcache_open()

Close the connection to the header cache.

Definition at line 442 of file hcache.c.

443{
444 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
445 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
446 if (!hc || !ops)
447 return;
448
449#ifdef USE_HCACHE_COMPRESSION
450 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
451 if (c_header_cache_compress_method)
452 {
453 const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
454 cops->close(&hc->cctx);
455 }
456#endif
457
458 ops->close(&hc->ctx);
459 FREE(&hc->folder);
460 FREE(&hc);
461}
void(* close)(void **ptr)
Definition: lib.h:143
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_store()

int mutt_hcache_store ( struct HeaderCache hc,
const char *  key,
size_t  keylen,
struct Email e,
uint32_t  uidvalidity 
)

Store a Header along with a validity datum.

Parameters
hcPointer to the struct HeaderCache structure got by mutt_hcache_open()
keyMessage identification string
keylenLength of the key string
eEmail to store
uidvalidityIMAP-specific UIDVALIDITY value, or 0 to use the current time
Return values
0Success
numGeneric or backend-specific error code otherwise

Store a Header along with a validity datum.

Definition at line 562 of file hcache.c.

564{
565 if (!hc)
566 return -1;
567
568 int dlen = 0;
569 char *data = dump(hc, e, &dlen, uidvalidity);
570
571#ifdef USE_HCACHE_COMPRESSION
572 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
573 if (c_header_cache_compress_method)
574 {
575 /* We don't compress uidvalidity and the crc, so we can check them before
576 * decompressing on fetch(). */
577 size_t hlen = header_size();
578
579 const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
580
581 /* data / dlen gets ptr to compressed data here */
582 size_t clen = dlen;
583 void *cdata = cops->compress(hc->cctx, data + hlen, dlen - hlen, &clen);
584 if (!cdata)
585 {
586 FREE(&data);
587 return -1;
588 }
589
590 char *whole = mutt_mem_malloc(hlen + clen);
591 memcpy(whole, data, hlen);
592 memcpy(whole + hlen, cdata, clen);
593
594 FREE(&data);
595
596 data = whole;
597 dlen = hlen + clen;
598 }
599#endif
600
601 /* store uncompressed data */
602 struct RealKey *rk = realkey(key, keylen);
603 int rc = mutt_hcache_store_raw(hc, rk->key, rk->len, data, dlen);
604
605 FREE(&data);
606
607 return rc;
608}
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:192
static void * dump(struct HeaderCache *hc, const struct Email *e, int *off, uint32_t uidvalidity)
Serialise an Email object.
Definition: hcache.c:85
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:620
static size_t header_size(void)
Compute the size of the header with uuid validity and crc.
Definition: hcache.c:69
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
void *(* compress)(void *cctx, const char *data, size_t dlen, size_t *clen)
Definition: lib.h:91
Hcache key name (including compression method)
Definition: hcache.c:181
char key[1024]
Key name.
Definition: hcache.c:182
size_t len
Length of key.
Definition: hcache.c:183
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_fetch()

struct HCacheEntry mutt_hcache_fetch ( struct HeaderCache hc,
const char *  key,
size_t  keylen,
uint32_t  uidvalidity 
)

Fetch and validate a message's header from the cache.

Parameters
hcPointer to the struct HeaderCache structure got by mutt_hcache_open()
keyMessage identification string
keylenLength of the string pointed to by key
uidvalidityOnly restore if it matches the stored uidvalidity
Return values
objHCacheEntry containing an Email, empty on failure
Note
This function performs a check on the validity of the data found by comparing it with the crc value of the struct HeaderCache structure.

Fetch and validate a message's header from the cache.

Definition at line 466 of file hcache.c.

468{
469 struct RealKey *rk = realkey(key, keylen);
470 struct HCacheEntry entry = { 0 };
471
472 size_t dlen;
473 void *data = mutt_hcache_fetch_raw(hc, rk->key, rk->len, &dlen);
474 void *to_free = data;
475 if (!data)
476 {
477 goto end;
478 }
479
480 /* restore uidvalidity and crc */
481 size_t hlen = header_size();
482 if (hlen > dlen)
483 {
484 goto end;
485 }
486 int off = 0;
487 serial_restore_uint32_t(&entry.uidvalidity, data, &off);
488 serial_restore_int(&entry.crc, data, &off);
489 assert((size_t) off == hlen);
490 if (entry.crc != hc->crc || ((uidvalidity != 0) && uidvalidity != entry.uidvalidity))
491 {
492 goto end;
493 }
494
495#ifdef USE_HCACHE_COMPRESSION
496 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
497 if (c_header_cache_compress_method)
498 {
499 const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
500
501 void *dblob = cops->decompress(hc->cctx, (char *) data + hlen, dlen - hlen);
502 if (!dblob)
503 {
504 goto end;
505 }
506 data = (char *) dblob - hlen; /* restore skips uidvalidity and crc */
507 }
508#endif
509
510 entry.email = restore(data);
511
512end:
513 mutt_hcache_free_raw(hc, &to_free);
514 return entry;
515}
void * mutt_hcache_fetch_raw(struct HeaderCache *hc, const char *key, size_t keylen, size_t *dlen)
Fetch a message's header from the cache.
Definition: hcache.c:529
static struct Email * restore(const unsigned char *d)
Restore an Email from data retrieved from the cache.
Definition: hcache.c:143
void mutt_hcache_free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition: hcache.c:548
void serial_restore_int(unsigned int *i, const unsigned char *d, int *off)
Unpack an integer from a binary blob.
Definition: serialize.c:99
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:111
void *(* decompress)(void *cctx, const char *cbuf, size_t clen)
Definition: lib.h:107
Wrapper for Email retrieved from the header cache.
Definition: lib.h:98
uint32_t uidvalidity
IMAP-specific UIDVALIDITY.
Definition: lib.h:99
struct Email * email
Retrieved email.
Definition: lib.h:101
unsigned int crc
CRC of Email/Body/etc structs.
Definition: lib.h:100
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_store_raw()

int mutt_hcache_store_raw ( struct HeaderCache hc,
const char *  key,
size_t  keylen,
void *  data,
size_t  dlen 
)

Store a key / data pair.

Parameters
hcPointer to the struct HeaderCache structure got by mutt_hcache_open()
keyMessage identification string
keylenLength of the string pointed to by key
dataPayload to associate with key
dlenLength of the buffer pointed to by the data parameter
Return values
0Success
numGeneric or backend-specific error code otherwise

Definition at line 620 of file hcache.c.

622{
623 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
624 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
625
626 if (!hc || !ops)
627 return -1;
628
629 struct Buffer path = mutt_buffer_make(1024);
630
631 keylen = mutt_buffer_printf(&path, "%s%.*s", hc->folder, (int) keylen, key);
632 int rc = ops->store(hc->ctx, mutt_buffer_string(&path), keylen, data, dlen);
633 mutt_buffer_dealloc(&path);
634
635 return rc;
636}
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:67
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:309
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:168
char * data
Pointer to data.
Definition: buffer.h:35
int(* store)(void *store, const char *key, size_t klen, void *value, size_t vlen)
Definition: lib.h:121
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_fetch_raw()

void * mutt_hcache_fetch_raw ( struct HeaderCache hc,
const char *  key,
size_t  keylen,
size_t *  dlen 
)

Fetch a message's header from the cache.

Parameters
[in]hcPointer to the struct HeaderCache structure got by mutt_hcache_open()
[in]keyMessage identification string
[in]keylenLength of the string pointed to by key
[out]dlenLength of the fetched data
Return values
ptrSuccess, the data if found
NULLOtherwise
Note
This function does not perform any check on the validity of the data found.
The returned data must be free with mutt_hcache_free_raw().

Definition at line 529 of file hcache.c.

531{
532 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
533 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
534
535 if (!hc || !ops)
536 return NULL;
537
538 struct Buffer path = mutt_buffer_make(1024);
539 keylen = mutt_buffer_printf(&path, "%s%.*s", hc->folder, (int) keylen, key);
540 void *blob = ops->fetch(hc->ctx, mutt_buffer_string(&path), keylen, dlen);
541 mutt_buffer_dealloc(&path);
542 return blob;
543}
void *(* fetch)(void *store, const char *key, size_t klen, size_t *vlen)
Definition: lib.h:96
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_free_raw()

void mutt_hcache_free_raw ( struct HeaderCache hc,
void **  data 
)

Free data fetched with mutt_hcache_fetch_raw()

Parameters
hcPointer to the struct HeaderCache structure got by mutt_hcache_open()
dataPointer to the data got using mutt_hcache_fetch_raw

Free data fetched with mutt_hcache_fetch_raw()

Definition at line 548 of file hcache.c.

549{
550 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
551 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
552
553 if (!hc || !ops || !data || !*data)
554 return;
555
556 ops->free(hc->ctx, data);
557}
void(* free)(void *store, void **ptr)
Definition: lib.h:106
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_delete_record()

int mutt_hcache_delete_record ( struct HeaderCache hc,
const char *  key,
size_t  keylen 
)

Delete a key / data pair.

Parameters
hcPointer to the struct HeaderCache structure got by mutt_hcache_open()
keyMessage identification string
keylenLength of the string pointed to by key
Return values
0Success
numGeneric or backend-specific error code otherwise

Delete a key / data pair.

Definition at line 641 of file hcache.c.

642{
643 if (!hc)
644 return -1;
645
646 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
647 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
648
649 struct Buffer path = mutt_buffer_make(1024);
650
651 keylen = mutt_buffer_printf(&path, "%s%s", hc->folder, key);
652
653 int rc = ops->delete_record(hc->ctx, mutt_buffer_string(&path), keylen);
654 mutt_buffer_dealloc(&path);
655 return rc;
656}
int(* delete_record)(void *store, const char *key, size_t klen)
Definition: lib.h:134
+ Here is the call graph for this function:
+ Here is the caller graph for this function: