NeoMutt  2025-12-11-980-ge38c27
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
hcache.c File Reference

Header cache multiplexor. More...

#include "config.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 "module_data.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 struct RealKeyrealkey (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.
 
static void hcache_free (struct HeaderCache **ptr)
 Free a header cache.
 
static struct HeaderCachehcache_new (void)
 Create a new header cache.
 
static size_t header_size (void)
 Compute the size of the header with uuid validity and crc.
 
static uint32_t email_pack_flags (const struct Email *e)
 Pack the Email flags into a uint32_t.
 
static void email_unpack_flags (struct Email *e, uint32_t packed)
 Unpack the Email flags from a uint32_t.
 
static uint32_t email_pack_timezone (const struct Email *e)
 Pack the Email timezone into a uint32_t.
 
static void email_unpack_timezone (struct Email *e, uint32_t packed)
 Unpack the Email timezone from a uint32_t.
 
static void * dump_email (struct HeaderCache *hc, const struct Email *e, int *off, uint32_t uidvalidity)
 Serialise an Email object.
 
static struct Emailrestore_email (const unsigned char *d, size_t dlen)
 Restore an Email from data retrieved from the cache.
 
static bool create_hcache_dir (const char *path)
 Create parent dirs for the hcache database.
 
static void hcache_per_folder (struct HeaderCache *hc, struct Buffer *hcpath, const char *path, hcache_namer_t namer)
 Generate the hcache pathname.
 
static char * get_foldername (const char *folder)
 Where should the cache be stored?
 
static void free_raw (struct HeaderCache *hc, void **data)
 Multiplexor for StoreOps::free.
 
static unsigned int generate_hcachever (void)
 Calculate hcache version from dynamic configuration.
 
struct HeaderCachehcache_open (const char *path, const char *folder, hcache_namer_t namer, bool create)
 Multiplexor for StoreOps::open.
 
void hcache_close (struct HeaderCache **ptr)
 Multiplexor for StoreOps::close.
 
struct HCacheEntry hcache_fetch_email (struct HeaderCache *hc, const char *key, size_t keylen, uint32_t uidvalidity)
 Multiplexor for StoreOps::fetch.
 
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.
 
char * hcache_fetch_raw_str (struct HeaderCache *hc, const char *key, size_t keylen)
 Fetch a string from the cache.
 
int hcache_store_email (struct HeaderCache *hc, const char *key, size_t keylen, struct Email *e, uint32_t uidvalidity)
 Multiplexor for StoreOps::store.
 
int hcache_store_raw (struct HeaderCache *hc, const char *key, size_t keylen, void *data, size_t dlen)
 Store a key / data pair.
 
int hcache_delete_email (struct HeaderCache *hc, const char *key, size_t keylen)
 Multiplexor for StoreOps::delete_record.
 
int hcache_delete_raw (struct HeaderCache *hc, const char *key, size_t keylen)
 Multiplexor for StoreOps::delete_record.
 

Detailed Description

Header cache multiplexor.

Authors
  • Pietro Cerutti
  • Richard Russon
  • 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

◆ realkey()

static struct RealKey * realkey ( struct HeaderCache * hc,
const char * key,
size_t keylen,
bool compress )
static

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

Parameters
hcHeader cache handle
keyOriginal key
keylenLength of original key
compressWill the data be compressed?
Return values
ptrStatic location holding data and length of the real key

Definition at line 78 of file hcache.c.

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}
#define MIN(a, b)
Return the minimum of two values.
Definition memory.h:40
const char * name
Compression name.
Definition lib.h:66
char * folder
Folder name.
Definition lib.h:88
const struct ComprOps * compr_ops
Compression backend.
Definition lib.h:92
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
+ Here is the caller graph for this function:

◆ hcache_free()

static void hcache_free ( struct HeaderCache ** ptr)
static

Free a header cache.

Parameters
ptrheader cache to free

Definition at line 106 of file hcache.c.

107{
108 if (!ptr || !*ptr)
109 return;
110
111 struct HeaderCache *hc = *ptr;
112 FREE(&hc->folder);
113
114 FREE(ptr);
115}
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
Header Cache.
Definition lib.h:87
+ Here is the caller graph for this function:

◆ hcache_new()

static struct HeaderCache * hcache_new ( void )
static

Create a new header cache.

Return values
ptrNewly created header cache

Definition at line 121 of file hcache.c.

122{
123 return MUTT_MEM_CALLOC(1, struct HeaderCache);
124}
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:52
+ Here is the caller graph for this function:

◆ 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 130 of file hcache.c.

131{
132 return sizeof(int) + sizeof(uint32_t);
133}
+ Here is the caller graph for this function:

◆ email_pack_flags()

static uint32_t email_pack_flags ( const struct Email * e)
inlinestatic

Pack the Email flags into a uint32_t.

Parameters
eEmail to pack
Return values
numuint32_t of packed flags
Note
Order of packing must match email_unpack_flags()

Definition at line 142 of file hcache.c.

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}
bool read
Email is read.
Definition email.h:50
bool mime
Has a MIME-Version header?
Definition email.h:48
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition email.h:43
bool old
Email is seen, but unread.
Definition email.h:49
bool flagged
Marked important?
Definition email.h:47
bool replied
Email has been replied to.
Definition email.h:51
bool expired
Already expired?
Definition email.h:46
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
+ Here is the caller graph for this function:

◆ email_unpack_flags()

static void email_unpack_flags ( struct Email * e,
uint32_t packed )
inlinestatic

Unpack the Email flags from a uint32_t.

Parameters
eEmail to unpack into
packedPacked flags
Note
Order of packing must match email_pack_flags()

Definition at line 167 of file hcache.c.

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}
+ Here is the caller graph for this function:

◆ email_pack_timezone()

static uint32_t email_pack_timezone ( const struct Email * e)
inlinestatic

Pack the Email timezone into a uint32_t.

Parameters
eEmail to pack
Return values
numuint32_t of packed timezone
Note
Order of packing must match email_unpack_timezone()

Definition at line 192 of file hcache.c.

193{
194 if (!e)
195 return 0;
196
197 return e->zhours + (e->zminutes << 5) + (e->zoccident << 11);
198}
unsigned int zminutes
Minutes away from UTC.
Definition email.h:57
bool zoccident
True, if west of UTC, False if east.
Definition email.h:58
unsigned int zhours
Hours away from UTC.
Definition email.h:56
+ Here is the caller graph for this function:

◆ email_unpack_timezone()

static void email_unpack_timezone ( struct Email * e,
uint32_t packed )
inlinestatic

Unpack the Email timezone from a uint32_t.

Parameters
eEmail to unpack into
packedPacked timezone
Note
Order of packing must match email_pack_timezone()

Definition at line 207 of file hcache.c.

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}
+ Here is the caller graph for this function:

◆ dump_email()

static void * dump_email ( 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 230 of file hcache.c.

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}
static uint32_t email_pack_flags(const struct Email *e)
Pack the Email flags into a uint32_t.
Definition hcache.c:142
static uint32_t email_pack_timezone(const struct Email *e)
Pack the Email timezone into a uint32_t.
Definition hcache.c:192
static size_t header_size(void)
Compute the size of the header with uuid validity and crc.
Definition hcache.c:130
#define MUTT_MEM_MALLOC(n, type)
Definition memory.h:53
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
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
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
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
#define ASSERT(COND)
Definition signal2.h:59
struct Envelope * env
Envelope information.
Definition email.h:68
int lines
How many lines in the body of this message?
Definition email.h:62
struct Body * body
List of MIME parts.
Definition email.h:69
time_t date_sent
Time when the message was sent (UTC)
Definition email.h:60
struct TagList tags
For drivers that support server tagging.
Definition email.h:72
time_t received
Time when the message was placed in the mailbox.
Definition email.h:61
unsigned int crc
CRC of the cache entry.
Definition lib.h:89
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ restore_email()

static struct Email * restore_email ( const unsigned char * d,
size_t dlen )
static

Restore an Email from data retrieved from the cache.

Parameters
dData retrieved using hcache_fetch_email()
dlenLength of the retrieved data
Return values
ptrSuccess, the restored header
NULLThe entry was truncated or corrupt
Note
The returned Email must be free'd by caller code with email_free()

Definition at line 272 of file hcache.c.

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}
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
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition envelope.c:45
static void email_unpack_flags(struct Email *e, uint32_t packed)
Unpack the Email flags from a uint32_t.
Definition hcache.c:167
static void email_unpack_timezone(struct Email *e, uint32_t packed)
Unpack the Email timezone from a uint32_t.
Definition hcache.c:207
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
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
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
The envelope/body of an email.
Definition email.h:39
+ 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 330 of file hcache.c.

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}
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 _(a)
Definition message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
+ 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 HeaderCache * hc,
struct Buffer * hcpath,
const char * path,
hcache_namer_t namer )
static

Generate the hcache pathname.

Parameters
hcHeader cache handle
hcpathBuffer for the result
pathBase directory, from $header_cache
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 (hc->folder)
  • NAME: Create by namer, or md5sum of hc->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 374 of file hcache.c.

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}
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
static bool create_hcache_dir(const char *path)
Create parent dirs for the hcache database.
Definition hcache.c:330
void * mutt_md5(const char *str, void *buf)
Calculate the MD5 hash of a NUL-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:503
void mutt_encode_path(struct Buffer *buf, const char *src)
Convert a path to 'us-ascii'.
Definition muttlib.c:803
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
String manipulation buffer.
Definition buffer.h:36
char * data
Pointer to data.
Definition buffer.h:37
const struct StoreOps * store_ops
Store backend.
Definition lib.h:90
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 427 of file hcache.c.

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}
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
+ 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 441 of file hcache.c.

442{
443 hc->store_ops->free(hc->store_handle, data);
444}
StoreHandle * store_handle
Store handle.
Definition lib.h:91
void(* free)(StoreHandle *store, void **ptr)
Definition lib.h:107
+ Here is the caller graph for this function:

◆ generate_hcachever()

static unsigned int generate_hcachever ( void )
static

Calculate hcache version from dynamic configuration.

Return values
numHeader cache version

< MD5 digest as a string

< MD5 digest as an integer

Definition at line 450 of file hcache.c.

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}
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
@ MODULE_ID_EMAIL
ModuleEmail, Email code
Definition module_api.h:64
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:666
#define STAILQ_FOREACH(var, head, field)
Definition queue.h:390
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
Cursor for the MD5 hashing.
Definition md5.h:37
Container for Accounts, Notifications.
Definition neomutt.h:41
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hcache_open()

struct HeaderCache * hcache_open ( const char * path,
const char * folder,
hcache_namer_t namer,
bool create )

Multiplexor for StoreOps::open.

Open the connection to the header cache.

Definition at line 492 of file hcache.c.

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}
const struct ComprOps * compress_get_ops(const char *compr)
Get the API functions for a compress backend.
Definition compress.c:78
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
#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 unsigned int generate_hcachever(void)
Calculate hcache version from dynamic configuration.
Definition hcache.c:450
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
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:47
@ MODULE_ID_HCACHE
ModuleHcache, Email Header Cache
Definition module_api.h:68
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition store.c:88
ComprHandle *(* open)(short level)
Definition lib.h:79
void(* close)(ComprHandle **ptr)
Definition lib.h:125
Hcache private Module data.
Definition module_data.h:30
unsigned int hcache_ver
Header Cache version.
Definition module_data.h:32
ComprHandle * compr_handle
Compression handle.
Definition lib.h:93
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
StoreHandle *(* open)(const char *path, bool create)
Definition lib.h:83
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hcache_close()

void hcache_close ( struct HeaderCache ** ptr)

Multiplexor for StoreOps::close.

Close the connection to the header cache.

Definition at line 564 of file hcache.c.

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}
void(* close)(StoreHandle **ptr)
Definition lib.h:144
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hcache_fetch_email()

struct HCacheEntry hcache_fetch_email ( 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 584 of file hcache.c.

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}
static void free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition hcache.c:441
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 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
void *(* decompress)(ComprHandle *handle, const char *cbuf, size_t clen, size_t *dlen)
Definition lib.h:113
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
void *(* fetch)(StoreHandle *store, const char *key, size_t klen, size_t *vlen)
Definition lib.h:97
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hcache_fetch_raw_obj_full()

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.

Parameters
[in]hcPointer to the struct HeaderCache structure got by 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 647 of file hcache.c.

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}
+ Here is the call graph for this function:

◆ hcache_fetch_raw_str()

char * hcache_fetch_raw_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 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 679 of file hcache.c.

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}
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition string.c:384
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hcache_store_email()

int hcache_store_email ( 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 700 of file hcache.c.

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}
static void * dump_email(struct HeaderCache *hc, const struct Email *e, int *off, uint32_t uidvalidity)
Serialise an Email object.
Definition hcache.c:230
void *(* compress)(ComprHandle *handle, const char *data, size_t dlen, size_t *clen)
Definition lib.h:96
int(* store)(StoreHandle *store, const char *key, size_t klen, void *value, size_t vlen)
Definition lib.h:122
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hcache_store_raw()

int 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 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 754 of file hcache.c.

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}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hcache_delete_email()

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

Multiplexor for StoreOps::delete_record.

Delete a key / data pair.

Definition at line 769 of file hcache.c.

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}
int(* delete_record)(StoreHandle *store, const char *key, size_t klen)
Definition lib.h:135
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hcache_delete_raw()

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

Multiplexor for StoreOps::delete_record.

Delete a key / data pair.

Definition at line 782 of file hcache.c.

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}
+ Here is the call graph for this function:
+ Here is the caller graph for this function: