NeoMutt  2023-05-17-33-gce4425
Teaching an old dog new tricks
DOXYGEN
hcache.c File Reference

Header cache multiplexor. More...

#include "config.h"
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "lib.h"
#include "compress/lib.h"
#include "store/lib.h"
#include "hcache/hcversion.h"
#include "muttlib.h"
#include "serialize.h"
+ Include dependency graph for hcache.c:

Go to the source code of this file.

Data Structures

struct  RealKey
 Hcache key name (including compression method) More...
 

Functions

static size_t header_size (void)
 Compute the size of the header with uuid validity and crc. More...
 
static void * dump (struct HeaderCache *hc, const struct Email *e, int *off, uint32_t uidvalidity)
 Serialise an Email object. More...
 
static struct Emailrestore (const unsigned char *d)
 Restore an Email from data retrieved from the cache. More...
 
static struct RealKeyrealkey (const char *key, size_t keylen)
 Compute the real key used in the backend, taking into account the compression method. More...
 
static bool create_hcache_dir (const char *path)
 Create parent dirs for the hcache database. More...
 
static void hcache_per_folder (struct Buffer *hcpath, const char *path, const char *folder, hcache_namer_t namer)
 Generate the hcache pathname. More...
 
static char * get_foldername (const char *folder)
 Where should the cache be stored? More...
 
static void * fetch_raw (struct HeaderCache *hc, const char *key, size_t keylen, size_t *dlen)
 Fetch a message's header from the cache. More...
 
static void free_raw (struct HeaderCache *hc, void **data)
 Multiplexor for StoreOps::free. More...
 
struct HeaderCachemutt_hcache_open (const char *path, const char *folder, hcache_namer_t namer)
 Multiplexor for StoreOps::open. More...
 
void mutt_hcache_close (struct HeaderCache *hc)
 Multiplexor for StoreOps::close. More...
 
struct HCacheEntry mutt_hcache_fetch (struct HeaderCache *hc, const char *key, size_t keylen, uint32_t uidvalidity)
 Multiplexor for StoreOps::fetch. More...
 
bool mutt_hcache_fetch_obj_ (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. More...
 
char * mutt_hcache_fetch_str (struct HeaderCache *hc, const char *key, size_t keylen)
 Fetch a string from the cache. More...
 
int mutt_hcache_store (struct HeaderCache *hc, const char *key, size_t keylen, struct Email *e, uint32_t uidvalidity)
 Multiplexor for StoreOps::store. 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...
 
int mutt_hcache_delete_record (struct HeaderCache *hc, const char *key, size_t keylen)
 Multiplexor for StoreOps::delete_record. More...
 

Variables

static unsigned int HcacheVer = 0x0
 Header Cache version. 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 hcache.c.

Function Documentation

◆ header_size()

static size_t header_size ( void  )
static

Compute the size of the header with uuid validity and crc.

Return values
numSize of the header

Definition at line 70 of file hcache.c.

71{
72 return sizeof(int) + sizeof(uint32_t);
73}
+ Here is the caller graph for this function:

◆ dump()

static void * dump ( struct HeaderCache hc,
const struct Email e,
int *  off,
uint32_t  uidvalidity 
)
static

Serialise an Email object.

Parameters
hcHeader cache handle
eEmail to serialise
offSize of the binary blob
uidvalidityIMAP server identifier
Return values
ptrBinary blob representing the Email

This function transforms an Email into a binary string so that it can be saved to a database.

Definition at line 86 of file hcache.c.

87{
88 struct Email e_dump;
89 bool convert = !CharsetIsUtf8;
90
91 *off = 0;
92 unsigned char *d = mutt_mem_malloc(4096);
93
94 d = serial_dump_uint32_t((uidvalidity != 0) ? uidvalidity : mutt_date_now(), d, off);
95 d = serial_dump_int(hc->crc, d, off);
96
97 assert((size_t) *off == header_size());
98
99 lazy_realloc(&d, *off + sizeof(struct Email));
100 memcpy(&e_dump, e, sizeof(struct Email));
101
102 /* some fields are not safe to cache */
103 e_dump.tagged = false;
104 e_dump.changed = false;
105 e_dump.threaded = false;
106 e_dump.recip_valid = false;
107 e_dump.searched = false;
108 e_dump.matched = false;
109 e_dump.collapsed = false;
110 e_dump.visible = true;
111 e_dump.num_hidden = 0;
112 e_dump.recipient = 0;
113 e_dump.attr_color = NULL;
114 e_dump.attach_valid = false;
115 e_dump.path = NULL;
116 e_dump.tree = NULL;
117 e_dump.thread = NULL;
118 e_dump.sequence = 0;
119 e_dump.notify = NULL;
120 STAILQ_INIT(&e_dump.tags);
121#ifdef MIXMASTER
122 STAILQ_INIT(&e_dump.chain);
123#endif
124 e_dump.edata = NULL;
125
126 memcpy(d + *off, &e_dump, sizeof(struct Email));
127 *off += sizeof(struct Email);
128
129 d = serial_dump_envelope(e_dump.env, d, off, convert);
130 d = serial_dump_body(e_dump.body, d, off, convert);
131 d = serial_dump_tags(&e->tags, d, off);
132
133 return d;
134}
static size_t header_size(void)
Compute the size of the header with uuid validity and crc.
Definition: hcache.c:70
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
bool CharsetIsUtf8
Is the user's current character set utf-8?
Definition: charset.c:59
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:446
#define STAILQ_INIT(head)
Definition: queue.h:372
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:84
unsigned char * serial_dump_int(unsigned int i, unsigned char *d, int *off)
Pack an integer into a binary blob.
Definition: serialize.c:68
void lazy_realloc(void *ptr, size_t size)
Reallocate some memory.
Definition: serialize.c:51
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:490
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:424
unsigned char * serial_dump_tags(const struct TagList *tags, unsigned char *d, int *off)
Pack a TagList into a binary blob.
Definition: serialize.c:596
The envelope/body of an email.
Definition: email.h:37
struct TagList tags
For drivers that support server tagging.
Definition: email.h:70
unsigned int crc
CRC of the cache entry.
Definition: lib.h:90
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ restore()

static struct Email * restore ( const unsigned char *  d)
static

Restore an Email from data retrieved from the cache.

Parameters
dData retrieved using mutt_hcache_dump
Return values
ptrSuccess, the restored header (can't be NULL)
Note
The returned Email must be free'd by caller code with email_free()

Definition at line 144 of file hcache.c.

145{
146 int off = 0;
147 struct Email *e = email_new();
148 bool convert = !CharsetIsUtf8;
149
150 /* skip validate */
151 off += sizeof(uint32_t);
152
153 /* skip crc */
154 off += sizeof(unsigned int);
155
156 size_t sequence = e->sequence;
157 struct Notify *notify = e->notify;
158 memcpy(e, d + off, sizeof(struct Email));
159 off += sizeof(struct Email);
160 e->sequence = sequence;
161 e->notify = notify;
162
163 STAILQ_INIT(&e->tags);
164#ifdef MIXMASTER
165 STAILQ_INIT(&e->chain);
166#endif
167
168 e->env = mutt_env_new();
169 serial_restore_envelope(e->env, d, &off, convert);
170
171 e->body = mutt_body_new();
172 serial_restore_body(e->body, d, &off, convert);
173 serial_restore_tags(&e->tags, d, &off);
174
175 return e;
176}
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
struct Email * email_new(void)
Create a new Email.
Definition: email.c:78
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:43
void serial_restore_tags(struct TagList *tags, const unsigned char *d, int *off)
Unpack a TagList from a binary blob.
Definition: serialize.c:621
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:540
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:464
struct Envelope * env
Envelope information.
Definition: email.h:66
struct Body * body
List of MIME parts.
Definition: email.h:67
struct ListHead chain
Mixmaster chain.
Definition: email.h:89
struct Notify * notify
Notifications: NotifyEmail, EventEmail.
Definition: email.h:71
size_t sequence
Sequence number assigned on creation.
Definition: email.h:65
Notification API.
Definition: notify.c:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ realkey()

static struct RealKey * realkey ( const char *  key,
size_t  keylen 
)
static

Compute the real key used in the backend, taking into account the compression method.

Parameters
keyOriginal key
keylenLength of original key
Return values
ptrStatic location holding data and length of the real key

Definition at line 193 of file hcache.c.

194{
195 static struct RealKey rk;
196#ifdef USE_HCACHE_COMPRESSION
197 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
198 if (c_header_cache_compress_method)
199 {
200 const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
201
202 rk.len = snprintf(rk.key, sizeof(rk.key), "%s-%s", key, cops->name);
203 }
204 else
205#endif
206 {
207 memcpy(rk.key, key, keylen + 1); // Including NUL byte
208 rk.len = keylen;
209 }
210 return &rk;
211}
const struct ComprOps * compress_get_ops(const char *compr)
Get the API functions for a compress backend.
Definition: compress.c:79
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
Definition: lib.h:60
const char * name
Compression name.
Definition: lib.h:61
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Hcache key name (including compression method)
Definition: hcache.c:182
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ create_hcache_dir()

static bool create_hcache_dir ( const char *  path)
static

Create parent dirs for the hcache database.

Parameters
pathDatabase filename
Return values
trueSuccess
falseFailure (errno set)

Definition at line 219 of file hcache.c.

220{
221 char *dir = mutt_str_dup(path);
222 if (!dir)
223 return false;
224
225 char *p = strrchr(dir, '/');
226 if (!p)
227 {
228 FREE(&dir);
229 return true;
230 }
231
232 *p = '\0';
233
234 int rc = mutt_file_mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO);
235 if (rc != 0)
236 mutt_error(_("Can't create %s: %s"), dir, strerror(errno));
237
238 FREE(&dir);
239 return (rc == 0);
240}
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:952
#define mutt_error(...)
Definition: logging2.h:87
#define FREE(x)
Definition: memory.h:43
#define _(a)
Definition: message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:251
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hcache_per_folder()

static void hcache_per_folder ( struct Buffer hcpath,
const char *  path,
const char *  folder,
hcache_namer_t  namer 
)
static

Generate the hcache pathname.

Parameters
hcpathBuffer for the result
pathBase directory, from $header_cache
folderMailbox name (including protocol)
namerCallback to generate database filename - Implements hcache_namer_t

Generate the pathname for the hcache database, it will be of the form: BASE/FOLDER/NAME

  • BASE: Base directory (path)
  • FOLDER: Mailbox name (folder)
  • NAME: Create by namer, or md5sum of folder

This function will create any parent directories needed, so the caller just needs to create the database file.

If path exists and is a directory, it is used. If path has a trailing '/' it is assumed to be a directory. Otherwise path is assumed to be a file.

Definition at line 263 of file hcache.c.

265{
266 struct stat st = { 0 };
267
268 int plen = mutt_str_len(path);
269 int rc = stat(path, &st);
270 bool slash = (path[plen - 1] == '/');
271
272 if (((rc == 0) && !S_ISDIR(st.st_mode)) || ((rc == -1) && !slash))
273 {
274 /* An existing file or a non-existing path not ending with a slash */
275 mutt_encode_path(hcpath, path);
277 return;
278 }
279
280 /* We have a directory - no matter whether it exists, or not */
281 struct Buffer *hcfile = buf_pool_get();
282 if (namer)
283 {
284 namer(folder, hcfile);
285 buf_concat_path(hcpath, path, buf_string(hcfile));
286 }
287 else
288 {
289 unsigned char m[16]; /* binary md5sum */
290 struct Buffer *name = buf_pool_get();
291
292 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
293 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
294 if (!ops)
295 return;
296
297#ifdef USE_HCACHE_COMPRESSION
298 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
299 const char *cm = c_header_cache_compress_method;
300 buf_printf(name, "%s|%s%s", ops->name, folder, cm ? cm : "");
301#else
302 buf_printf(name, "%s|%s", ops->name, folder);
303#endif
306 mutt_md5_toascii(m, name->data);
307 buf_printf(hcpath, "%s%s%s", path, slash ? "" : "/", buf_string(name));
309 }
310
311 mutt_encode_path(hcpath, buf_string(hcpath));
313 buf_pool_release(&hcfile);
314}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:171
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:86
size_t buf_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:432
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:78
static bool create_hcache_dir(const char *path)
Create parent dirs for the hcache database.
Definition: hcache.c:219
void * mutt_md5(const char *str, void *buf)
Calculate the MD5 hash of a NULL-terminated string.
Definition: md5.c:317
void mutt_md5_toascii(const void *digest, char *resbuf)
Convert a binary MD5 digest into ASCII Hexadecimal.
Definition: md5.c:456
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:568
void mutt_encode_path(struct Buffer *buf, const char *src)
Convert a path to 'us-ascii'.
Definition: muttlib.c:1453
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:106
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:119
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition: store.c:106
String manipulation buffer.
Definition: buffer.h:34
Definition: lib.h:66
const char * name
Store name.
Definition: lib.h:67
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_foldername()

static char * get_foldername ( const char *  folder)
static

Where should the cache be stored?

Parameters
folderPath to be canonicalised
Return values
ptrNew string with canonical path

Definition at line 321 of file hcache.c.

322{
323 /* if the folder is local, canonify the path to avoid
324 * to ensure equivalent paths share the hcache */
325 char *p = mutt_mem_malloc(PATH_MAX + 1);
326 if (!realpath(folder, p))
327 mutt_str_replace(&p, folder);
328
329 return p;
330}
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:327
#define PATH_MAX
Definition: mutt.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fetch_raw()

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

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 free_raw().

Definition at line 344 of file hcache.c.

345{
346 if (!hc)
347 return NULL;
348
349 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
350 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
351
352 if (!ops)
353 return NULL;
354
355 struct Buffer path = buf_make(1024);
356 keylen = buf_printf(&path, "%s%.*s", hc->folder, (int) keylen, key);
357 void *blob = ops->fetch(hc->ctx, buf_string(&path), keylen, dlen);
358 buf_dealloc(&path);
359 return blob;
360}
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:352
struct Buffer buf_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:68
void * ctx
Store context (handle)
Definition: lib.h:91
char * folder
Folder name.
Definition: lib.h:89
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:

◆ free_raw()

static void free_raw ( struct HeaderCache hc,
void **  data 
)
static

Multiplexor for StoreOps::free.

Definition at line 365 of file hcache.c.

366{
367 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
368 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
369
370 if (!hc || !ops || !data || !*data)
371 return;
372
373 ops->free(hc->ctx, data);
374}
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_open()

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

Multiplexor for StoreOps::open.

Open the connection to the header cache.

< MD5 digest as a string

< MD5 digest as an integer

Definition at line 379 of file hcache.c.

380{
381 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
382 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
383 if (!ops)
384 return NULL;
385
386 struct HeaderCache *hc = mutt_mem_calloc(1, sizeof(struct HeaderCache));
387
388 /* Calculate the current hcache version from dynamic configuration */
389 if (HcacheVer == 0x0)
390 {
391 union
392 {
393 unsigned char charval[16];
394 unsigned int intval;
395 } digest;
396 struct Md5Ctx md5ctx;
397
398 HcacheVer = HCACHEVER;
399
400 mutt_md5_init_ctx(&md5ctx);
401
402 /* Seed with the compiled-in header structure hash */
403 mutt_md5_process_bytes(&HcacheVer, sizeof(HcacheVer), &md5ctx);
404
405 /* Mix in user's spam list */
406 struct Replace *sp = NULL;
407 STAILQ_FOREACH(sp, &SpamList, entries)
408 {
409 mutt_md5_process(sp->regex->pattern, &md5ctx);
410 mutt_md5_process(sp->templ, &md5ctx);
411 }
412
413 /* Mix in user's nospam list */
414 struct RegexNode *np = NULL;
415 STAILQ_FOREACH(np, &NoSpamList, entries)
416 {
417 mutt_md5_process(np->regex->pattern, &md5ctx);
418 }
419
420 /* Get a hash and take its bytes as an (unsigned int) hash version */
421 mutt_md5_finish_ctx(&md5ctx, digest.charval);
422 HcacheVer = digest.intval;
423 }
424
425 const struct ComprOps *cops = NULL;
426#ifdef USE_HCACHE_COMPRESSION
427 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
428 if (c_header_cache_compress_method)
429 {
430 cops = compress_get_ops(c_header_cache_compress_method);
431
432 const short c_header_cache_compress_level = cs_subset_number(NeoMutt->sub, "header_cache_compress_level");
433 hc->cctx = cops->open(c_header_cache_compress_level);
434 if (!hc->cctx)
435 {
436 FREE(&hc);
437 return NULL;
438 }
439
440 /* remember the buffer of database backend */
441 mutt_debug(LL_DEBUG3, "Header cache will use %s compression\n", cops->name);
442 }
443#endif
444
445 hc->folder = get_foldername(folder);
446 hc->crc = HcacheVer;
447
448 if (!path || (path[0] == '\0'))
449 {
450 if (cops)
451 {
452 cops->close(&hc->cctx);
453 }
454
455 FREE(&hc->folder);
456 FREE(&hc);
457 return NULL;
458 }
459
460 struct Buffer *hcpath = buf_pool_get();
461 hcache_per_folder(hcpath, path, hc->folder, namer);
462
463 hc->ctx = ops->open(buf_string(hcpath));
464 if (!hc->ctx)
465 {
466 /* remove a possibly incompatible version */
467 if (unlink(buf_string(hcpath)) == 0)
468 {
469 hc->ctx = ops->open(buf_string(hcpath));
470 if (!hc->ctx)
471 {
472 if (cops)
473 {
474 cops->close(&hc->cctx);
475 }
476 FREE(&hc->folder);
477 FREE(&hc);
478 }
479 }
480 }
481
482 buf_pool_release(&hcpath);
483 return hc;
484}
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 to match subscribed mailing lists.
Definition: globals.c:45
struct RegexList NoSpamList
List of regexes and patterns to match spam emails.
Definition: globals.c:43
#define mutt_debug(LEVEL,...)
Definition: logging2.h:84
static unsigned int HcacheVer
Header Cache version.
Definition: hcache.c:64
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:263
static char * get_foldername(const char *folder)
Where should the cache be stored?
Definition: hcache.c:321
@ LL_DEBUG3
Log at debug level 3.
Definition: logging2.h:42
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 NULL-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_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
void(* close)(void **cctx)
Definition: lib.h:119
void *(* open)(short level)
Definition: lib.h:74
Header cache structure.
Definition: lib.h:88
void * cctx
Compression context (handle)
Definition: lib.h:92
Cursor for the MD5 hashing.
Definition: md5.h:37
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
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)

Multiplexor for StoreOps::close.

Close the connection to the header cache.

Definition at line 489 of file hcache.c.

490{
491 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
492 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
493 if (!hc || !ops)
494 return;
495
496#ifdef USE_HCACHE_COMPRESSION
497 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
498 if (c_header_cache_compress_method)
499 {
500 const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
501 cops->close(&hc->cctx);
502 }
503#endif
504
505 ops->close(&hc->ctx);
506 FREE(&hc->folder);
507 FREE(&hc);
508}
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_fetch()

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

Multiplexor for StoreOps::fetch.

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

Definition at line 513 of file hcache.c.

515{
516 struct RealKey *rk = realkey(key, keylen);
517 struct HCacheEntry entry = { 0 };
518
519 size_t dlen;
520 void *data = fetch_raw(hc, rk->key, rk->len, &dlen);
521 void *to_free = data;
522 if (!data)
523 {
524 goto end;
525 }
526
527 /* restore uidvalidity and crc */
528 size_t hlen = header_size();
529 if (hlen > dlen)
530 {
531 goto end;
532 }
533 int off = 0;
534 serial_restore_uint32_t(&entry.uidvalidity, data, &off);
535 serial_restore_int(&entry.crc, data, &off);
536 assert((size_t) off == hlen);
537 if (entry.crc != hc->crc || ((uidvalidity != 0) && uidvalidity != entry.uidvalidity))
538 {
539 goto end;
540 }
541
542#ifdef USE_HCACHE_COMPRESSION
543 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
544 if (c_header_cache_compress_method)
545 {
546 const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
547
548 void *dblob = cops->decompress(hc->cctx, (char *) data + hlen, dlen - hlen);
549 if (!dblob)
550 {
551 goto end;
552 }
553 data = (char *) dblob - hlen; /* restore skips uidvalidity and crc */
554 }
555#endif
556
557 entry.email = restore(data);
558
559end:
560 free_raw(hc, &to_free);
561 return entry;
562}
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:193
static struct Email * restore(const unsigned char *d)
Restore an Email from data retrieved from the cache.
Definition: hcache.c:144
static void free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition: hcache.c:365
static void * 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:344
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:99
uint32_t uidvalidity
IMAP-specific UIDVALIDITY.
Definition: lib.h:100
struct Email * email
Retrieved email.
Definition: lib.h:102
unsigned int crc
CRC of Email/Body/etc structs.
Definition: lib.h:101
char key[1024]
Key name.
Definition: hcache.c:183
size_t len
Length of key.
Definition: hcache.c:184
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_fetch_obj_()

bool mutt_hcache_fetch_obj_ ( 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.

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]dstPointer to the destination object
[in]dstlenSize of the destination object
Return values
trueSuccess, the data was found and the length matches
falseOtherwise

Definition at line 574 of file hcache.c.

576{
577 bool rc = true;
578 size_t srclen = 0;
579 void *src = fetch_raw(hc, key, keylen, &srclen);
580 if (src && srclen == dstlen)
581 {
582 memcpy(dst, src, dstlen);
583 }
584 else
585 {
586 rc = false;
587 }
588 free_raw(hc, &src);
589 return rc;
590}
+ Here is the call graph for this function:

◆ mutt_hcache_fetch_str()

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

Fetch a string 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
Return values
ptrSuccess, the data if found
NULLOtherwise

Definition at line 600 of file hcache.c.

601{
602 char *res = NULL;
603 size_t dlen = 0;
604 void *data = fetch_raw(hc, key, keylen, &dlen);
605 if (data)
606 {
607 res = mutt_strn_dup(data, dlen);
608 free_raw(hc, &data);
609 }
610 return res;
611}
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:452
+ 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 
)

Multiplexor for StoreOps::store.

Store a Header along with a validity datum.

Definition at line 616 of file hcache.c.

618{
619 if (!hc)
620 return -1;
621
622 int dlen = 0;
623 char *data = dump(hc, e, &dlen, uidvalidity);
624
625#ifdef USE_HCACHE_COMPRESSION
626 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
627 if (c_header_cache_compress_method)
628 {
629 /* We don't compress uidvalidity and the crc, so we can check them before
630 * decompressing on fetch(). */
631 size_t hlen = header_size();
632
633 const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
634
635 /* data / dlen gets ptr to compressed data here */
636 size_t clen = dlen;
637 void *cdata = cops->compress(hc->cctx, data + hlen, dlen - hlen, &clen);
638 if (!cdata)
639 {
640 FREE(&data);
641 return -1;
642 }
643
644 char *whole = mutt_mem_malloc(hlen + clen);
645 memcpy(whole, data, hlen);
646 memcpy(whole + hlen, cdata, clen);
647
648 FREE(&data);
649
650 data = whole;
651 dlen = hlen + clen;
652 }
653#endif
654
655 /* store uncompressed data */
656 struct RealKey *rk = realkey(key, keylen);
657 int rc = mutt_hcache_store_raw(hc, rk->key, rk->len, data, dlen);
658
659 FREE(&data);
660
661 return rc;
662}
static void * dump(struct HeaderCache *hc, const struct Email *e, int *off, uint32_t uidvalidity)
Serialise an Email object.
Definition: hcache.c:86
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:674
void *(* compress)(void *cctx, const char *data, size_t dlen, size_t *clen)
Definition: lib.h:91
+ 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 674 of file hcache.c.

676{
677 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
678 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
679
680 if (!hc || !ops)
681 return -1;
682
683 struct Buffer path = buf_make(1024);
684
685 keylen = buf_printf(&path, "%s%.*s", hc->folder, (int) keylen, key);
686 int rc = ops->store(hc->ctx, buf_string(&path), keylen, data, dlen);
687 buf_dealloc(&path);
688
689 return rc;
690}
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_delete_record()

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

Multiplexor for StoreOps::delete_record.

Delete a key / data pair.

Definition at line 695 of file hcache.c.

696{
697 if (!hc)
698 return -1;
699
700 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
701 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
702 if (!ops)
703 return -1;
704
705 struct Buffer path = buf_make(1024);
706
707 keylen = buf_printf(&path, "%s%s", hc->folder, key);
708
709 int rc = ops->delete_record(hc->ctx, buf_string(&path), keylen);
710 buf_dealloc(&path);
711 return rc;
712}
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:

Variable Documentation

◆ HcacheVer

unsigned int HcacheVer = 0x0
static

Header Cache version.

Definition at line 64 of file hcache.c.