NeoMutt  2024-11-14-138-ge5ca67
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 80 of file hcache.c.

82{
83 static struct RealKey rk;
84
85 rk.keylen = snprintf(rk.key, sizeof(rk.key), "%s/%.*s", hc->folder, (int) keylen, key);
86
87#ifdef USE_HCACHE_COMPRESSION
88 if (compress && hc->compr_ops)
89 {
90 // Append the compression type, e.g. "-zstd"
91 rk.keylen += snprintf(rk.key + rk.keylen, sizeof(rk.key) - rk.keylen, "-%s",
92 hc->compr_ops->name);
93 }
94#endif
95
96 return &rk;
97}
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:67
char key[1024]
Key name.
Definition: hcache.c:68
size_t keylen
Length of key.
Definition: hcache.c:69
+ 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 103 of file hcache.c.

104{
105 if (!ptr || !*ptr)
106 return;
107
108 struct HeaderCache *hc = *ptr;
109 FREE(&hc->folder);
110
111 FREE(ptr);
112}
#define FREE(x)
Definition: memory.h:55
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 118 of file hcache.c.

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

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

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

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

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

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

228{
229 bool convert = !CharsetIsUtf8;
230
231 *off = 0;
232 unsigned char *d = MUTT_MEM_MALLOC(4096, unsigned char);
233
234 d = serial_dump_uint32_t((uidvalidity != 0) ? uidvalidity : mutt_date_now(), d, off);
235 d = serial_dump_int(hc->crc, d, off);
236
237 ASSERT((size_t) *off == header_size());
238
239 uint32_t packed = email_pack_flags(e);
240 d = serial_dump_uint32_t(packed, d, off);
241
242 packed = email_pack_timezone(e);
243 d = serial_dump_uint32_t(packed, d, off);
244
245 uint64_t big = e->date_sent;
246 d = serial_dump_uint64_t(big, d, off);
247 big = e->received;
248 d = serial_dump_uint64_t(big, d, off);
249
250 d = serial_dump_int(e->lines, d, off);
251
252 d = serial_dump_envelope(e->env, d, off, convert);
253 d = serial_dump_body(e->body, d, off, convert);
254 d = serial_dump_tags(&e->tags, d, off);
255
256 return d;
257}
static uint32_t email_pack_flags(const struct Email *e)
Pack the Email flags into a uint32_t.
Definition: hcache.c:139
static uint32_t email_pack_timezone(const struct Email *e)
Pack the Email timezone into a uint32_t.
Definition: hcache.c:189
static size_t header_size(void)
Compute the size of the header with uuid validity and crc.
Definition: hcache.c:127
#define MUTT_MEM_MALLOC(n, type)
Definition: memory.h:41
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:456
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:58
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 267 of file hcache.c.

268{
269 int off = 0;
270 struct Email *e = email_new();
271 bool convert = !CharsetIsUtf8;
272
273 off += sizeof(uint32_t); // skip validate
274 off += sizeof(unsigned int); // skip crc
275
276 uint32_t packed = 0;
277 serial_restore_uint32_t(&packed, d, &off);
278 email_unpack_flags(e, packed);
279
280 packed = 0;
281 serial_restore_uint32_t(&packed, d, &off);
282 email_unpack_timezone(e, packed);
283
284 uint64_t big = 0;
285 serial_restore_uint64_t(&big, d, &off);
286 e->date_sent = big;
287
288 big = 0;
289 serial_restore_uint64_t(&big, d, &off);
290 e->received = big;
291
292 unsigned int num = 0;
293 serial_restore_int(&num, d, &off);
294 e->lines = num;
295
296 e->env = mutt_env_new();
297 serial_restore_envelope(e->env, d, &off, convert);
298
299 e->body = mutt_body_new();
300 serial_restore_body(e->body, d, &off, convert);
301 serial_restore_tags(&e->tags, d, &off);
302
303 return e;
304}
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:46
static void email_unpack_flags(struct Email *e, uint32_t packed)
Unpack the Email flags from a uint32_t.
Definition: hcache.c:164
static void email_unpack_timezone(struct Email *e, uint32_t packed)
Unpack the Email timezone from a uint32_t.
Definition: hcache.c:204
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 312 of file hcache.c.

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

358{
359 struct stat st = { 0 };
360
361 int plen = mutt_str_len(path);
362 int rc = stat(path, &st);
363 bool slash = (path[plen - 1] == '/');
364
365 if (((rc == 0) && !S_ISDIR(st.st_mode)) || ((rc == -1) && !slash))
366 {
367 /* An existing file or a non-existing path not ending with a slash */
368 mutt_encode_path(hcpath, path);
370 return;
371 }
372
373 /* We have a directory - no matter whether it exists, or not */
374 struct Buffer *hcfile = buf_pool_get();
375 if (namer)
376 {
377 namer(hc->folder, hcfile);
378 mutt_encode_path(hcfile, buf_string(hcfile));
379 buf_concat_path(hcpath, path, buf_string(hcfile));
380 }
381 else
382 {
383 unsigned char m[16]; /* binary md5sum */
384 struct Buffer *name = buf_pool_get();
385
386#ifdef USE_HCACHE_COMPRESSION
387 const char *cm = hc->compr_ops ? hc->compr_ops->name : "";
388 buf_printf(name, "%s|%s%s", hc->store_ops->name, hc->folder, cm);
389#else
390 buf_printf(name, "%s|%s", hc->store_ops->name, hc->folder);
391#endif
392 mutt_md5(buf_string(name), m);
393 buf_reset(name);
394 mutt_md5_toascii(m, name->data);
395 mutt_encode_path(name, buf_string(name));
396 buf_printf(hcpath, "%s%s%s", path, slash ? "" : "/", buf_string(name));
397 buf_pool_release(&name);
398 }
399
401 buf_pool_release(&hcfile);
402}
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:312
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:496
void mutt_encode_path(struct Buffer *buf, const char *src)
Convert a path to 'us-ascii'.
Definition: muttlib.c:872
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 409 of file hcache.c.

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

424{
425 hc->store_ops->free(hc->store_handle, data);
426}
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 432 of file hcache.c.

433{
434 union
435 {
436 unsigned char charval[16];
437 unsigned int intval;
438 } digest;
439 struct Md5Ctx md5ctx = { 0 };
440
441 mutt_md5_init_ctx(&md5ctx);
442
443 /* Seed with the compiled-in header structure hash */
444 unsigned int ver = HCACHEVER;
445 mutt_md5_process_bytes(&ver, sizeof(ver), &md5ctx);
446
447 /* Mix in user's spam list */
448 struct Replace *sp = NULL;
449 STAILQ_FOREACH(sp, &SpamList, entries)
450 {
451 mutt_md5_process(sp->regex->pattern, &md5ctx);
452 mutt_md5_process(sp->templ, &md5ctx);
453 }
454
455 /* Mix in user's nospam list */
456 struct RegexNode *np = NULL;
457 STAILQ_FOREACH(np, &NoSpamList, entries)
458 {
459 mutt_md5_process(np->regex->pattern, &md5ctx);
460 }
461
462 /* Get a hash and take its bytes as an (unsigned int) hash version */
463 mutt_md5_finish_ctx(&md5ctx, digest.charval);
464
465 return digest.intval;
466}
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 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
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
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 471 of file hcache.c.

473{
474 if (!path || (path[0] == '\0'))
475 return NULL;
476
477 if (HcacheVer == 0x0)
479
480 struct HeaderCache *hc = hcache_new();
481
483 hc->crc = HcacheVer;
484
485 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
486 hc->store_ops = store_get_backend_ops(c_header_cache_backend);
487 if (!hc->store_ops)
488 {
489 hcache_free(&hc);
490 return NULL;
491 }
492
493#ifdef USE_HCACHE_COMPRESSION
494 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
495 if (c_header_cache_compress_method)
496 {
497 hc->compr_ops = compress_get_ops(c_header_cache_compress_method);
498
499 const short c_header_cache_compress_level = cs_subset_number(NeoMutt->sub, "header_cache_compress_level");
500 hc->compr_handle = hc->compr_ops->open(c_header_cache_compress_level);
501 if (!hc->compr_handle)
502 {
503 hcache_free(&hc);
504 return NULL;
505 }
506
507 /* remember the buffer of database backend */
508 mutt_debug(LL_DEBUG3, "Header cache will use %s compression\n",
509 hc->compr_ops->name);
510 }
511#endif
512
513 struct Buffer *hcpath = buf_pool_get();
514 hcache_per_folder(hc, hcpath, path, namer);
515
516 hc->store_handle = hc->store_ops->open(buf_string(hcpath), create);
517 if (!hc->store_handle)
518 {
519 /* remove a possibly incompatible version */
520 if (unlink(buf_string(hcpath)) == 0)
521 {
522 hc->store_handle = hc->store_ops->open(buf_string(hcpath), create);
523 }
524 }
525
526 if (!hc->store_handle)
527 {
528 if (hc->compr_ops)
529 {
530 hc->compr_ops->close(&hc->compr_handle);
531 }
532 hcache_free(&hc);
533 }
534
535 buf_pool_release(&hcpath);
536 return hc;
537}
const struct ComprOps * compress_get_ops(const char *compr)
Get the API functions for a compress backend.
Definition: compress.c:81
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:89
static unsigned int HcacheVer
Header Cache version.
Definition: hcache.c:61
static void hcache_free(struct HeaderCache **ptr)
Free a header cache.
Definition: hcache.c:103
static struct HeaderCache * hcache_new(void)
Create a new header cache.
Definition: hcache.c:118
static unsigned int generate_hcachever(void)
Calculate hcache version from dynamic configuration.
Definition: hcache.c:432
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:356
static char * get_foldername(const char *folder)
Where should the cache be stored?
Definition: hcache.c:409
@ LL_DEBUG3
Log at debug level 3.
Definition: logging2.h:45
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition: store.c:107
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:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
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 542 of file hcache.c.

543{
544 if (!ptr || !*ptr)
545 return;
546
547 struct HeaderCache *hc = *ptr;
548
549#ifdef USE_HCACHE_COMPRESSION
550 if (hc->compr_ops)
551 hc->compr_ops->close(&hc->compr_handle);
552#endif
553
554 hc->store_ops->close(&hc->store_handle);
555
556 hcache_free(ptr);
557}
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 562 of file hcache.c.

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

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

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

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

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

740{
741 if (!hc)
742 return -1;
743
744 struct RealKey *rk = realkey(hc, key, keylen, true);
745
746 return hc->store_ops->delete_record(hc->store_handle, rk->key, rk->keylen);
747}
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 752 of file hcache.c.

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