NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
hcache.c File Reference

Header cache multiplexor. More...

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

Go to the source code of this file.

Data Structures

struct  RealKey
 

Functions

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

Variables

static unsigned int hcachever = 0x0
 

Detailed Description

Header cache multiplexor.

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

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file hcache.c.

Function Documentation

◆ header_size()

static size_t header_size ( void  )
static

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

Definition at line 69 of file hcache.c.

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

◆ dump()

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

Serialise an Email object.

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

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

Definition at line 85 of file hcache.c.

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

◆ restore()

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

Restore an Email from data retrieved from the cache.

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

Definition at line 143 of file hcache.c.

144 {
145  int off = 0;
146  struct Email *e = email_new();
147  bool convert = !CharsetIsUtf8;
148 
149  /* skip validate */
150  off += sizeof(uint32_t);
151 
152  /* skip crc */
153  off += sizeof(unsigned int);
154 
155  size_t sequence = e->sequence;
156  struct Notify *notify = e->notify;
157  memcpy(e, d + off, sizeof(struct Email));
158  off += sizeof(struct Email);
159  e->sequence = sequence;
160  e->notify = notify;
161 
162  STAILQ_INIT(&e->tags);
163 #ifdef MIXMASTER
164  STAILQ_INIT(&e->chain);
165 #endif
166 
167  e->env = mutt_env_new();
168  serial_restore_envelope(e->env, d, &off, convert);
169 
170  e->body = mutt_body_new();
171  serial_restore_body(e->body, d, &off, convert);
172  serial_restore_tags(&e->tags, d, &off);
173 
174  return e;
175 }
The envelope/body of an email.
Definition: email.h:37
struct Body * body
List of MIME parts.
Definition: email.h:91
struct Notify * notify
Notifications: ColorId, EventColor.
Definition: color.c:95
void serial_restore_body(struct Body *c, const unsigned char *d, int *off, bool convert)
Unpack a Body from a binary blob.
Definition: serialize.c:465
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
struct Email * email_new(void)
Create a new Email.
Definition: email.c:78
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
#define STAILQ_INIT(head)
Definition: queue.h:372
struct Envelope * env
Envelope information.
Definition: email.h:90
struct TagList tags
For drivers that support server tagging.
Definition: email.h:109
struct ListHead chain
Mixmaster chain.
Definition: email.h:102
size_t sequence
Sequence number assigned on creation.
Definition: email.h:99
Notification API.
Definition: notify.c:50
struct Notify * notify
Notifications: NotifyEmail, EventEmail.
Definition: email.h:123
bool CharsetIsUtf8
Is the user&#39;s current character set utf-8?
Definition: charset.c:62
void serial_restore_tags(struct TagList *tags, const unsigned char *d, int *off)
Unpack a TagList from a binary blob.
Definition: serialize.c:617
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:539
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ realkey()

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

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

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

Definition at line 189 of file hcache.c.

190 {
191  static struct RealKey rk;
192 #ifdef USE_HCACHE_COMPRESSION
193  const char *const c_header_cache_compress_method =
194  cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
195  if (c_header_cache_compress_method)
196  {
197  const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
198 
199  rk.len = snprintf(rk.key, sizeof(rk.key), "%s-%s", key, cops->name);
200  }
201  else
202 #endif
203  {
204  memcpy(rk.key, key, keylen + 1); // Including NUL byte
205  rk.len = keylen;
206  }
207  return &rk;
208 }
const struct ComprOps * compress_get_ops(const char *compr)
Get the API functions for a compress backend.
Definition: compress.c:80
const char * name
Compression name.
Definition: lib.h:61
Container for Accounts, Notifications.
Definition: neomutt.h:36
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
Definition: lib.h:59
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.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 216 of file hcache.c.

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

◆ hcache_per_folder()

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

Generate the hcache pathname.

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

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

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

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

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

Definition at line 260 of file hcache.c.

262 {
263  struct stat sb;
264 
265  int plen = mutt_str_len(path);
266  int rc = stat(path, &sb);
267  bool slash = (path[plen - 1] == '/');
268 
269  if (((rc == 0) && !S_ISDIR(sb.st_mode)) || ((rc == -1) && !slash))
270  {
271  /* An existing file or a non-existing path not ending with a slash */
272  mutt_encode_path(hcpath, path);
274  return;
275  }
276 
277  /* We have a directory - no matter whether it exists, or not */
278  struct Buffer *hcfile = mutt_buffer_pool_get();
279  if (namer)
280  {
281  namer(folder, hcfile);
282  mutt_buffer_concat_path(hcpath, path, mutt_buffer_string(hcfile));
283  }
284  else
285  {
286  unsigned char m[16]; /* binary md5sum */
287  struct Buffer *name = mutt_buffer_pool_get();
288 
289  const char *const c_header_cache_backend =
290  cs_subset_string(NeoMutt->sub, "header_cache_backend");
291  const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
292 
293 #ifdef USE_HCACHE_COMPRESSION
294  const char *const c_header_cache_compress_method =
295  cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
296  const char *cm = c_header_cache_compress_method;
297  mutt_buffer_printf(name, "%s|%s%s", ops->name, folder, cm ? cm : "");
298 #else
299  mutt_buffer_printf(name, "%s|%s", ops->name, folder);
300 #endif
301  mutt_md5(mutt_buffer_string(name), m);
302  mutt_buffer_reset(name);
303  mutt_md5_toascii(m, name->data);
304  mutt_buffer_printf(hcpath, "%s%s%s", path, slash ? "" : "/", mutt_buffer_string(name));
306  }
307 
308  mutt_encode_path(hcpath, mutt_buffer_string(hcpath));
310  mutt_buffer_pool_release(&hcfile);
311 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition: store.c:107
Definition: lib.h:63
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
Container for Accounts, Notifications.
Definition: neomutt.h:36
static bool create_hcache_dir(const char *path)
Create parent dirs for the hcache database.
Definition: hcache.c:216
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
void mutt_md5_toascii(const void *digest, char *resbuf)
Convert a binary MD5 digest into ASCII Hexadecimal.
Definition: md5.c:457
char * data
Pointer to data.
Definition: buffer.h:35
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
const char * name
Store name.
Definition: lib.h:65
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
void * mutt_md5(const char *str, void *buf)
Calculate the MD5 hash of a NULL-terminated string.
Definition: md5.c:317
size_t mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:374
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
void mutt_encode_path(struct Buffer *buf, const char *src)
Convert a path to &#39;us-ascii&#39;.
Definition: muttlib.c:1490
+ 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 318 of file hcache.c.

319 {
320  /* if the folder is local, canonify the path to avoid
321  * to ensure equivalent paths share the hcache */
322  char *p = mutt_mem_malloc(PATH_MAX + 1);
323  if (!realpath(folder, p))
324  mutt_str_replace(&p, folder);
325 
326  return p;
327 }
#define PATH_MAX
Definition: mutt.h:40
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_open()

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

Multiplexor for StoreOps::open.

open the connection to the header cache

Definition at line 332 of file hcache.c.

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

◆ mutt_hcache_close()

void mutt_hcache_close ( struct HeaderCache hc)

Multiplexor for StoreOps::close.

close the connection to the header cache

Definition at line 435 of file hcache.c.

436 {
437  const char *const c_header_cache_backend =
438  cs_subset_string(NeoMutt->sub, "header_cache_backend");
439  const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
440  if (!hc || !ops)
441  return;
442 
443 #ifdef USE_HCACHE_COMPRESSION
444  const char *const c_header_cache_compress_method =
445  cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
446  if (c_header_cache_compress_method)
447  {
448  const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
449  cops->close(&hc->cctx);
450  }
451 #endif
452 
453  ops->close(&hc->ctx);
454  FREE(&hc->folder);
455  FREE(&hc);
456 }
void * cctx
Definition: lib.h:89
const struct ComprOps * compress_get_ops(const char *compr)
Get the API functions for a compress backend.
Definition: compress.c:80
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition: store.c:107
Definition: lib.h:63
Container for Accounts, Notifications.
Definition: neomutt.h:36
void(* close)(void **ptr)
Definition: lib.h:141
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
Definition: lib.h:59
void(* close)(void **cctx)
Definition: lib.h:119
#define FREE(x)
Definition: memory.h:40
char * folder
Definition: lib.h:86
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
void * ctx
Definition: lib.h:88
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_fetch()

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

Multiplexor for StoreOps::fetch.

fetch and validate a message's header from the cache

Definition at line 461 of file hcache.c.

463 {
464  struct RealKey *rk = realkey(key, keylen);
465  struct HCacheEntry entry = { 0 };
466 
467  size_t dlen;
468  void *data = mutt_hcache_fetch_raw(hc, rk->key, rk->len, &dlen);
469  void *to_free = data;
470  if (!data)
471  {
472  goto end;
473  }
474 
475  /* restore uidvalidity and crc */
476  size_t hlen = header_size();
477  int off = 0;
478  serial_restore_uint32_t(&entry.uidvalidity, data, &off);
479  serial_restore_int(&entry.crc, data, &off);
480  assert((size_t) off == hlen);
481  if (entry.crc != hc->crc || ((uidvalidity != 0) && uidvalidity != entry.uidvalidity))
482  {
483  goto end;
484  }
485 
486 #ifdef USE_HCACHE_COMPRESSION
487  const char *const c_header_cache_compress_method =
488  cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
489  if (c_header_cache_compress_method)
490  {
491  const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
492 
493  void *dblob = cops->decompress(hc->cctx, (char *) data + hlen, dlen - hlen);
494  if (!dblob)
495  {
496  goto end;
497  }
498  data = (char *) dblob - hlen; /* restore skips uidvalidity and crc */
499  }
500 #endif
501 
502  entry.email = restore(data);
503 
504 end:
505  mutt_hcache_free_raw(hc, &to_free);
506  return entry;
507 }
void * cctx
Definition: lib.h:89
static struct RealKey * realkey(const char *key, size_t keylen)
Compute the real key used in the backend, taking into account the compression method.
Definition: hcache.c:189
Wrapper for Email retrieved from the header cache.
Definition: lib.h:95
const struct ComprOps * compress_get_ops(const char *compr)
Get the API functions for a compress backend.
Definition: compress.c:80
size_t len
Definition: hcache.c:180
static size_t header_size(void)
Compute the size of the header with uuid validity and crc.
Definition: hcache.c:69
uint32_t uidvalidity
IMAP-specific UIDVALIDITY.
Definition: lib.h:97
void serial_restore_int(unsigned int *i, const unsigned char *d, int *off)
Unpack an integer from a binary blob.
Definition: serialize.c:98
void mutt_hcache_free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition: hcache.c:541
Container for Accounts, Notifications.
Definition: neomutt.h:36
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:110
unsigned int crc
Definition: lib.h:87
char key[1024]
Definition: hcache.c:179
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
Definition: lib.h:59
unsigned int crc
CRC of Email/Body/etc structs.
Definition: lib.h:98
void *(* decompress)(void *cctx, const char *cbuf, size_t clen)
Definition: lib.h:107
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
struct Email * email
Retrieved email.
Definition: lib.h:99
void * mutt_hcache_fetch_raw(struct HeaderCache *hc, const char *key, size_t keylen, size_t *dlen)
Fetch a message&#39;s header from the cache.
Definition: hcache.c:521
static struct Email * restore(const unsigned char *d)
Restore an Email from data retrieved from the cache.
Definition: hcache.c:143
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_fetch_raw()

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

Fetch a message's header from the cache.

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

Definition at line 521 of file hcache.c.

523 {
524  const char *const c_header_cache_backend =
525  cs_subset_string(NeoMutt->sub, "header_cache_backend");
526  const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
527 
528  if (!hc || !ops)
529  return NULL;
530 
531  struct Buffer path = mutt_buffer_make(1024);
532  keylen = mutt_buffer_printf(&path, "%s%.*s", hc->folder, (int) keylen, key);
533  void *blob = ops->fetch(hc->ctx, mutt_buffer_string(&path), keylen, dlen);
534  mutt_buffer_dealloc(&path);
535  return blob;
536 }
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition: store.c:107
Definition: lib.h:63
void *(* fetch)(void *store, const char *key, size_t klen, size_t *vlen)
Definition: lib.h:94
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
Container for Accounts, Notifications.
Definition: neomutt.h:36
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
char * folder
Definition: lib.h:86
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
void * ctx
Definition: lib.h:88
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_free_raw()

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

Multiplexor for StoreOps::free.

free data fetched with mutt_hcache_fetch_raw()

Definition at line 541 of file hcache.c.

542 {
543  const char *const c_header_cache_backend =
544  cs_subset_string(NeoMutt->sub, "header_cache_backend");
545  const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
546 
547  if (!hc || !ops || !data || !*data)
548  return;
549 
550  ops->free(hc->ctx, data);
551 }
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition: store.c:107
Definition: lib.h:63
Container for Accounts, Notifications.
Definition: neomutt.h:36
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
void(* free)(void *store, void **ptr)
Definition: lib.h:104
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
void * ctx
Definition: lib.h:88
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_store()

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

Multiplexor for StoreOps::store.

store a Header along with a validity datum

Definition at line 556 of file hcache.c.

558 {
559  if (!hc)
560  return -1;
561 
562  int dlen = 0;
563  char *data = dump(hc, e, &dlen, uidvalidity);
564 
565 #ifdef USE_HCACHE_COMPRESSION
566  const char *const c_header_cache_compress_method =
567  cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
568  if (c_header_cache_compress_method)
569  {
570  /* We don't compress uidvalidity and the crc, so we can check them before
571  * decompressing on fetch(). */
572  size_t hlen = header_size();
573 
574  const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
575 
576  /* data / dlen gets ptr to compressed data here */
577  size_t clen = dlen;
578  void *cdata = cops->compress(hc->cctx, data + hlen, dlen - hlen, &clen);
579  if (!cdata)
580  {
581  FREE(&data);
582  return -1;
583  }
584 
585  char *whole = mutt_mem_malloc(hlen + clen);
586  memcpy(whole, data, hlen);
587  memcpy(whole + hlen, cdata, clen);
588 
589  FREE(&data);
590 
591  data = whole;
592  dlen = hlen + clen;
593  }
594 #endif
595 
596  /* store uncompressed data */
597  struct RealKey *rk = realkey(key, keylen);
598  int rc = mutt_hcache_store_raw(hc, rk->key, rk->len, data, dlen);
599 
600  FREE(&data);
601 
602  return rc;
603 }
void * cctx
Definition: lib.h:89
static struct RealKey * realkey(const char *key, size_t keylen)
Compute the real key used in the backend, taking into account the compression method.
Definition: hcache.c:189
const struct ComprOps * compress_get_ops(const char *compr)
Get the API functions for a compress backend.
Definition: compress.c:80
size_t len
Definition: hcache.c:180
static size_t header_size(void)
Compute the size of the header with uuid validity and crc.
Definition: hcache.c:69
void *(* compress)(void *cctx, const char *data, size_t dlen, size_t *clen)
Definition: lib.h:91
Container for Accounts, Notifications.
Definition: neomutt.h:36
static void * dump(struct HeaderCache *hc, const struct Email *e, int *off, uint32_t uidvalidity)
Serialise an Email object.
Definition: hcache.c:85
char key[1024]
Definition: hcache.c:179
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
Definition: lib.h:59
#define FREE(x)
Definition: memory.h:40
int mutt_hcache_store_raw(struct HeaderCache *hc, const char *key, size_t keylen, void *data, size_t dlen)
store a key / data pair
Definition: hcache.c:615
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_store_raw()

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

store a key / data pair

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

Definition at line 615 of file hcache.c.

617 {
618  const char *const c_header_cache_backend =
619  cs_subset_string(NeoMutt->sub, "header_cache_backend");
620  const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
621 
622  if (!hc || !ops)
623  return -1;
624 
625  struct Buffer path = mutt_buffer_make(1024);
626 
627  keylen = mutt_buffer_printf(&path, "%s%.*s", hc->folder, (int) keylen, key);
628  int rc = ops->store(hc->ctx, mutt_buffer_string(&path), keylen, data, dlen);
629  mutt_buffer_dealloc(&path);
630 
631  return rc;
632 }
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition: store.c:107
Definition: lib.h:63
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
Container for Accounts, Notifications.
Definition: neomutt.h:36
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
int(* store)(void *store, const char *key, size_t klen, void *value, size_t vlen)
Definition: lib.h:119
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
char * data
Pointer to data.
Definition: buffer.h:35
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
char * folder
Definition: lib.h:86
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
void * ctx
Definition: lib.h:88
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_delete_record()

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

Multiplexor for StoreOps::delete_record.

delete a key / data pair

Definition at line 637 of file hcache.c.

638 {
639  if (!hc)
640  return -1;
641 
642  const char *const c_header_cache_backend =
643  cs_subset_string(NeoMutt->sub, "header_cache_backend");
644  const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
645 
646  struct Buffer path = mutt_buffer_make(1024);
647 
648  keylen = mutt_buffer_printf(&path, "%s%s", hc->folder, key);
649 
650  int rc = ops->delete_record(hc->ctx, mutt_buffer_string(&path), keylen);
651  mutt_buffer_dealloc(&path);
652  return rc;
653 }
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition: store.c:107
Definition: lib.h:63
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
Container for Accounts, Notifications.
Definition: neomutt.h:36
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
int(* delete_record)(void *store, const char *key, size_t klen)
Definition: lib.h:132
char * folder
Definition: lib.h:86
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
void * ctx
Definition: lib.h:88
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ hcachever

unsigned int hcachever = 0x0
static

Definition at line 63 of file hcache.c.