NeoMutt  2025-09-05-55-g97fc89
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 "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)
 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.
 

Variables

static unsigned int HcacheVer = 0x0
 Header Cache version.
 

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

84{
85 static struct RealKey rk;
86
87 rk.keylen = snprintf(rk.key, sizeof(rk.key), "%s/%.*s", hc->folder, (int) keylen, key);
88
89#ifdef USE_HCACHE_COMPRESSION
90 if (compress && hc->compr_ops)
91 {
92 // Append the compression type, e.g. "-zstd"
93 rk.keylen += snprintf(rk.key + rk.keylen, sizeof(rk.key) - rk.keylen, "-%s",
94 hc->compr_ops->name);
95 }
96#endif
97
98 return &rk;
99}
const char * name
Compression name.
Definition lib.h:65
char * folder
Folder name.
Definition lib.h:87
const struct ComprOps * compr_ops
Compression backend.
Definition lib.h:91
Hcache key name (including compression method)
Definition hcache.c:69
char key[1024]
Key name.
Definition hcache.c:70
size_t keylen
Length of key.
Definition hcache.c:71
+ 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 105 of file hcache.c.

106{
107 if (!ptr || !*ptr)
108 return;
109
110 struct HeaderCache *hc = *ptr;
111 FREE(&hc->folder);
112
113 FREE(ptr);
114}
#define FREE(x)
Definition memory.h:62
Header Cache.
Definition lib.h:86
+ 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 120 of file hcache.c.

121{
122 return MUTT_MEM_CALLOC(1, struct HeaderCache);
123}
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:47
+ 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 129 of file hcache.c.

130{
131 return sizeof(int) + sizeof(uint32_t);
132}
+ 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 141 of file hcache.c.

142{
143 if (!e)
144 return 0;
145
146 // clang-format off
147 return e->security +
148 (e->expired << 16) +
149 (e->flagged << 17) +
150 (e->mime << 18) +
151 (e->old << 19) +
152 (e->read << 20) +
153 (e->replied << 21) +
154 (e->superseded << 22) +
155 (e->trash << 23);
156 // clang-format on
157}
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 166 of file hcache.c.

167{
168 if (!e)
169 return;
170
171 // clang-format off
172 e->security = (packed & ((1 << 16) - 1)); // bits 0-15
173 e->expired = (packed & (1 << 16));
174 e->flagged = (packed & (1 << 17));
175 e->mime = (packed & (1 << 18));
176 e->old = (packed & (1 << 19));
177 e->read = (packed & (1 << 20));
178 e->replied = (packed & (1 << 21));
179 e->superseded = (packed & (1 << 22));
180 e->trash = (packed & (1 << 23));
181 // clang-format on
182}
+ 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 191 of file hcache.c.

192{
193 if (!e)
194 return 0;
195
196 return e->zhours + (e->zminutes << 5) + (e->zoccident << 11);
197}
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 206 of file hcache.c.

207{
208 if (!e)
209 return;
210
211 // clang-format off
212 e->zhours = (packed & ((1 << 5) - 1)); // bits 0-4 (5)
213 e->zminutes = ((packed >> 5) & ((1 << 6) - 1)); // bits 5-10 (6)
214 e->zoccident = (packed & (1 << 11)); // bit 11 (1)
215 // clang-format on
216}
+ 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 229 of file hcache.c.

230{
231 bool convert = !CharsetIsUtf8;
232
233 *off = 0;
234 unsigned char *d = MUTT_MEM_MALLOC(4096, unsigned char);
235
236 d = serial_dump_uint32_t((uidvalidity != 0) ? uidvalidity : mutt_date_now(), d, off);
237 d = serial_dump_int(hc->crc, d, off);
238
239 ASSERT((size_t) *off == header_size());
240
241 uint32_t packed = email_pack_flags(e);
242 d = serial_dump_uint32_t(packed, d, off);
243
244 packed = email_pack_timezone(e);
245 d = serial_dump_uint32_t(packed, d, off);
246
247 uint64_t big = e->date_sent;
248 d = serial_dump_uint64_t(big, d, off);
249 big = e->received;
250 d = serial_dump_uint64_t(big, d, off);
251
252 d = serial_dump_int(e->lines, d, off);
253
254 d = serial_dump_envelope(e->env, d, off, convert);
255 d = serial_dump_body(e->body, d, off, convert);
256 d = serial_dump_tags(&e->tags, d, off);
257
258 return d;
259}
static uint32_t email_pack_flags(const struct Email *e)
Pack the Email flags into a uint32_t.
Definition hcache.c:141
static uint32_t email_pack_timezone(const struct Email *e)
Pack the Email timezone into a uint32_t.
Definition hcache.c:191
static size_t header_size(void)
Compute the size of the header with uuid validity and crc.
Definition hcache.c:129
#define MUTT_MEM_MALLOC(n, type)
Definition memory.h:48
bool CharsetIsUtf8
Is the user's current character set utf-8?
Definition charset.c:66
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition date.c:455
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:519
unsigned char * serial_dump_tags(const struct TagList *tl, unsigned char *d, int *off)
Pack a TagList into a binary blob.
Definition serialize.c:688
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:99
unsigned char * serial_dump_int(const unsigned int i, unsigned char *d, int *off)
Pack an integer into a binary blob.
Definition serialize.c:67
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:586
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:83
#define ASSERT(COND)
Definition signal2.h:60
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:88
+ 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)
static

Restore an Email from data retrieved from the cache.

Parameters
dData retrieved using hcache_fetch_email()
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 269 of file hcache.c.

270{
271 int off = 0;
272 struct Email *e = email_new();
273 bool convert = !CharsetIsUtf8;
274
275 off += sizeof(uint32_t); // skip validate
276 off += sizeof(unsigned int); // skip crc
277
278 uint32_t packed = 0;
279 serial_restore_uint32_t(&packed, d, &off);
280 email_unpack_flags(e, packed);
281
282 packed = 0;
283 serial_restore_uint32_t(&packed, d, &off);
284 email_unpack_timezone(e, packed);
285
286 uint64_t big = 0;
287 serial_restore_uint64_t(&big, d, &off);
288 e->date_sent = big;
289
290 big = 0;
291 serial_restore_uint64_t(&big, d, &off);
292 e->received = big;
293
294 unsigned int num = 0;
295 serial_restore_int(&num, d, &off);
296 e->lines = num;
297
298 e->env = mutt_env_new();
299 serial_restore_envelope(e->env, d, &off, convert);
300
301 e->body = mutt_body_new();
302 serial_restore_body(e->body, d, &off, convert);
303 serial_restore_tags(&e->tags, d, &off);
304
305 return e;
306}
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
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:166
static void email_unpack_timezone(struct Email *e, uint32_t packed)
Unpack the Email timezone from a uint32_t.
Definition hcache.c:206
void serial_restore_tags(struct TagList *tl, const unsigned char *d, int *off)
Unpack a TagList from a binary blob.
Definition serialize.c:713
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:634
void serial_restore_uint64_t(uint64_t *s, const unsigned char *d, int *off)
Unpack an uint64_t from a binary blob.
Definition serialize.c:138
void serial_restore_body(struct Body *b, const unsigned char *d, int *off, bool convert)
Unpack a Body from a binary blob.
Definition serialize.c:551
void serial_restore_int(unsigned int *i, const unsigned char *d, int *off)
Unpack an integer from a binary blob.
Definition serialize.c:114
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:126
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 314 of file hcache.c.

315{
316 char *dir = mutt_str_dup(path);
317 if (!dir)
318 return false;
319
320 char *p = strrchr(dir, '/');
321 if (!p)
322 {
323 FREE(&dir);
324 return true;
325 }
326
327 *p = '\0';
328
329 int rc = mutt_file_mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO);
330 if (rc != 0)
331 mutt_error(_("Can't create %s: %s"), dir, strerror(errno));
332
333 FREE(&dir);
334 return (rc == 0);
335}
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition file.c:851
#define mutt_error(...)
Definition logging2.h:93
#define _(a)
Definition message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:255
+ 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 358 of file hcache.c.

360{
361 struct stat st = { 0 };
362
363 int plen = mutt_str_len(path);
364 int rc = stat(path, &st);
365 bool slash = (path[plen - 1] == '/');
366
367 if (((rc == 0) && !S_ISDIR(st.st_mode)) || ((rc == -1) && !slash))
368 {
369 /* An existing file or a non-existing path not ending with a slash */
370 mutt_encode_path(hcpath, path);
372 return;
373 }
374
375 /* We have a directory - no matter whether it exists, or not */
376 struct Buffer *hcfile = buf_pool_get();
377 if (namer)
378 {
379 namer(hc->folder, hcfile);
380 mutt_encode_path(hcfile, buf_string(hcfile));
381 buf_concat_path(hcpath, path, buf_string(hcfile));
382 }
383 else
384 {
385 unsigned char m[16]; /* binary md5sum */
386 struct Buffer *name = buf_pool_get();
387
388#ifdef USE_HCACHE_COMPRESSION
389 const char *cm = hc->compr_ops ? hc->compr_ops->name : "";
390 buf_printf(name, "%s|%s%s", hc->store_ops->name, hc->folder, cm);
391#else
392 buf_printf(name, "%s|%s", hc->store_ops->name, hc->folder);
393#endif
394 mutt_md5(buf_string(name), m);
395 buf_reset(name);
396 mutt_md5_toascii(m, name->data);
397 mutt_encode_path(name, buf_string(name));
398 buf_printf(hcpath, "%s%s%s", path, slash ? "" : "/", buf_string(name));
399 buf_pool_release(&name);
400 }
401
403 buf_pool_release(&hcfile);
404}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
size_t buf_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition buffer.c:509
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:314
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:498
void mutt_encode_path(struct Buffer *buf, const char *src)
Convert a path to 'us-ascii'.
Definition muttlib.c:857
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:96
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:89
const char * name
Store name.
Definition lib.h:70
+ 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 411 of file hcache.c.

412{
413 /* if the folder is local, canonify the path to ensure equivalent paths share
414 * the hcache */
415 char *p = MUTT_MEM_MALLOC(PATH_MAX + 1, char);
416 if (!realpath(folder, p))
417 mutt_str_replace(&p, folder);
418
419 return p;
420}
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:282
#define PATH_MAX
Definition mutt.h:42
+ 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 425 of file hcache.c.

426{
427 hc->store_ops->free(hc->store_handle, data);
428}
StoreHandle * store_handle
Store handle.
Definition lib.h:90
void(* free)(StoreHandle *store, void **ptr)
Definition lib.h:110
+ 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 434 of file hcache.c.

435{
436 union
437 {
438 unsigned char charval[16];
439 unsigned int intval;
440 } digest;
441 struct Md5Ctx md5ctx = { 0 };
442
443 mutt_md5_init_ctx(&md5ctx);
444
445 /* Seed with the compiled-in header structure hash */
446 unsigned int ver = HCACHEVER;
447 mutt_md5_process_bytes(&ver, sizeof(ver), &md5ctx);
448
449 /* Mix in user's spam list */
450 struct Replace *sp = NULL;
451 STAILQ_FOREACH(sp, &SpamList, entries)
452 {
453 mutt_md5_process(sp->regex->pattern, &md5ctx);
454 mutt_md5_process(sp->templ, &md5ctx);
455 }
456
457 /* Mix in user's nospam list */
458 struct RegexNode *np = NULL;
459 STAILQ_FOREACH(np, &NoSpamList, entries)
460 {
461 mutt_md5_process(np->regex->pattern, &md5ctx);
462 }
463
464 /* Get a hash and take its bytes as an (unsigned int) hash version */
465 mutt_md5_finish_ctx(&md5ctx, digest.charval);
466
467 return digest.intval;
468}
struct ReplaceList SpamList
List of regexes to match subscribed mailing lists.
Definition globals.c:46
struct RegexList NoSpamList
List of regexes and patterns to match spam emails.
Definition globals.c:44
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
#define STAILQ_FOREACH(var, head, field)
Definition queue.h:390
Cursor for the MD5 hashing.
Definition md5.h:37
List of regular expressions.
Definition regex3.h:96
struct Regex * regex
Regex containing a regular expression.
Definition regex3.h:97
char * pattern
printable version
Definition regex3.h:87
List of regular expressions.
Definition regex3.h:106
char * templ
Template to match.
Definition regex3.h:109
struct Regex * regex
Regex containing a regular expression.
Definition regex3.h:107
+ 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 473 of file hcache.c.

475{
476 if (!path || (path[0] == '\0'))
477 return NULL;
478
479 if (HcacheVer == 0x0)
481
482 struct HeaderCache *hc = hcache_new();
483
485 hc->crc = HcacheVer;
486
487 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
488 hc->store_ops = store_get_backend_ops(c_header_cache_backend);
489 if (!hc->store_ops)
490 {
491 hcache_free(&hc);
492 return NULL;
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 hc->compr_ops = compress_get_ops(c_header_cache_compress_method);
500
501 const short c_header_cache_compress_level = cs_subset_number(NeoMutt->sub, "header_cache_compress_level");
502 hc->compr_handle = hc->compr_ops->open(c_header_cache_compress_level);
503 if (!hc->compr_handle)
504 {
505 hcache_free(&hc);
506 return NULL;
507 }
508
509 /* remember the buffer of database backend */
510 mutt_debug(LL_DEBUG3, "Header cache will use %s compression\n",
511 hc->compr_ops->name);
512 }
513#endif
514
515 struct Buffer *hcpath = buf_pool_get();
516 hcache_per_folder(hc, hcpath, path, namer);
517
518 hc->store_handle = hc->store_ops->open(buf_string(hcpath), create);
519 if (!hc->store_handle)
520 {
521 /* remove a possibly incompatible version */
522 if (unlink(buf_string(hcpath)) == 0)
523 {
524 hc->store_handle = hc->store_ops->open(buf_string(hcpath), create);
525 }
526 }
527
528 if (!hc->store_handle)
529 {
530 if (hc->compr_ops)
531 {
532 hc->compr_ops->close(&hc->compr_handle);
533 }
534 hcache_free(&hc);
535 }
536
537 buf_pool_release(&hcpath);
538 return hc;
539}
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:90
static unsigned int HcacheVer
Header Cache version.
Definition hcache.c:63
static void hcache_free(struct HeaderCache **ptr)
Free a header cache.
Definition hcache.c:105
static struct HeaderCache * hcache_new(void)
Create a new header cache.
Definition hcache.c:120
static unsigned int generate_hcachever(void)
Calculate hcache version from dynamic configuration.
Definition hcache.c:434
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:358
static char * get_foldername(const char *folder)
Where should the cache be stored?
Definition hcache.c:411
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:46
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition store.c:104
ComprHandle *(* open)(short level)
Definition lib.h:78
void(* close)(ComprHandle **ptr)
Definition lib.h:123
ComprHandle * compr_handle
Compression handle.
Definition lib.h:92
Container for Accounts, Notifications.
Definition neomutt.h:43
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:47
StoreHandle *(* open)(const char *path, bool create)
Definition lib.h:86
+ 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 544 of file hcache.c.

545{
546 if (!ptr || !*ptr)
547 return;
548
549 struct HeaderCache *hc = *ptr;
550
551#ifdef USE_HCACHE_COMPRESSION
552 if (hc->compr_ops)
553 hc->compr_ops->close(&hc->compr_handle);
554#endif
555
556 hc->store_ops->close(&hc->store_handle);
557
558 hcache_free(ptr);
559}
void(* close)(StoreHandle **ptr)
Definition lib.h:147
+ 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 564 of file hcache.c.

566{
567 struct HCacheEntry hce = { 0 };
568 if (!hc)
569 return hce;
570
571 size_t dlen = 0;
572 struct RealKey *rk = realkey(hc, key, keylen, true);
573 void *data = hc->store_ops->fetch(hc->store_handle, rk->key, rk->keylen, &dlen);
574 void *to_free = data;
575 if (!data)
576 {
577 goto end;
578 }
579
580 /* restore uidvalidity and crc */
581 size_t hlen = header_size();
582 if (hlen > dlen)
583 {
584 goto end;
585 }
586 int off = 0;
587 serial_restore_uint32_t(&hce.uidvalidity, data, &off);
588 serial_restore_int(&hce.crc, data, &off);
589 ASSERT((size_t) off == hlen);
590 if ((hce.crc != hc->crc) || ((uidvalidity != 0) && (uidvalidity != hce.uidvalidity)))
591 {
592 goto end;
593 }
594
595#ifdef USE_HCACHE_COMPRESSION
596 if (hc->compr_ops)
597 {
598 void *dblob = hc->compr_ops->decompress(hc->compr_handle,
599 (char *) data + hlen, dlen - hlen);
600 if (!dblob)
601 {
602 goto end;
603 }
604 data = (char *) dblob - hlen; /* restore skips uidvalidity and crc */
605 }
606#endif
607
608 hce.email = restore_email(data);
609
610end:
611 free_raw(hc, &to_free);
612 return hce;
613}
static struct Email * restore_email(const unsigned char *d)
Restore an Email from data retrieved from the cache.
Definition hcache.c:269
static void free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition hcache.c:425
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:82
void *(* decompress)(ComprHandle *handle, const char *cbuf, size_t clen)
Definition lib.h:111
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
void *(* fetch)(StoreHandle *store, const char *key, size_t klen, size_t *vlen)
Definition lib.h:100
+ 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 625 of file hcache.c.

627{
628 bool rc = true;
629 size_t srclen = 0;
630
631 struct RealKey *rk = realkey(hc, key, keylen, false);
632 void *src = hc->store_ops->fetch(hc->store_handle, rk->key, rk->keylen, &srclen);
633
634 if (src && (srclen == dstlen))
635 {
636 memcpy(dst, src, dstlen);
637 }
638 else
639 {
640 rc = false;
641 }
642 free_raw(hc, &src);
643 return rc;
644}
+ 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 654 of file hcache.c.

655{
656 char *res = NULL;
657 size_t dlen = 0;
658
659 struct RealKey *rk = realkey(hc, key, keylen, false);
660 void *data = hc->store_ops->fetch(hc->store_handle, rk->key, rk->keylen, &dlen);
661 if (data)
662 {
663 res = mutt_strn_dup(data, dlen);
664 free_raw(hc, &data);
665 }
666 return res;
667}
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition string.c:382
+ 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 672 of file hcache.c.

674{
675 if (!hc)
676 return -1;
677
678 int dlen = 0;
679 char *data = dump_email(hc, e, &dlen, uidvalidity);
680
681#ifdef USE_HCACHE_COMPRESSION
682 if (hc->compr_ops)
683 {
684 /* We don't compress uidvalidity and the crc, so we can check them before
685 * decompressing on fetch(). */
686 size_t hlen = header_size();
687
688 /* data / dlen gets ptr to compressed data here */
689 size_t clen = dlen;
690 void *cdata = hc->compr_ops->compress(hc->compr_handle, data + hlen, dlen - hlen, &clen);
691 if (!cdata)
692 {
693 FREE(&data);
694 return -1;
695 }
696
697 char *whole = MUTT_MEM_MALLOC(hlen + clen, char);
698 memcpy(whole, data, hlen);
699 memcpy(whole + hlen, cdata, clen);
700
701 FREE(&data);
702
703 data = whole;
704 dlen = hlen + clen;
705 }
706#endif
707
708 struct RealKey *rk = realkey(hc, key, keylen, true);
709 int rc = hc->store_ops->store(hc->store_handle, rk->key, rk->keylen, data, dlen);
710
711 FREE(&data);
712
713 return rc;
714}
static void * dump_email(struct HeaderCache *hc, const struct Email *e, int *off, uint32_t uidvalidity)
Serialise an Email object.
Definition hcache.c:229
void *(* compress)(ComprHandle *handle, const char *data, size_t dlen, size_t *clen)
Definition lib.h:95
int(* store)(StoreHandle *store, const char *key, size_t klen, void *value, size_t vlen)
Definition lib.h:125
+ 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 726 of file hcache.c.

728{
729 if (!hc)
730 return -1;
731
732 struct RealKey *rk = realkey(hc, key, keylen, false);
733 int rc = hc->store_ops->store(hc->store_handle, rk->key, rk->keylen, data, dlen);
734
735 return rc;
736}
+ 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 741 of file hcache.c.

742{
743 if (!hc)
744 return -1;
745
746 struct RealKey *rk = realkey(hc, key, keylen, true);
747
748 return hc->store_ops->delete_record(hc->store_handle, rk->key, rk->keylen);
749}
int(* delete_record)(StoreHandle *store, const char *key, size_t klen)
Definition lib.h:138
+ 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 754 of file hcache.c.

755{
756 if (!hc)
757 return -1;
758
759 struct RealKey *rk = realkey(hc, key, keylen, false);
760
761 return hc->store_ops->delete_record(hc->store_handle, rk->key, rk->keylen);
762}
+ 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 63 of file hcache.c.