NeoMutt  2018-07-16 +952-a2da0a
Teaching an old dog new tricks
DOXYGEN
hook.c File Reference

Parse and execute user-defined hooks. More...

#include "config.h"
#include <limits.h>
#include <regex.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "mutt/mutt.h"
#include "email/lib.h"
#include "mutt.h"
#include "hook.h"
#include "alias.h"
#include "context.h"
#include "globals.h"
#include "hdrline.h"
#include "mutt_attach.h"
#include "muttlib.h"
#include "mx.h"
#include "ncrypt/ncrypt.h"
#include "pattern.h"
#include "compress.h"
+ Include dependency graph for hook.c:

Go to the source code of this file.

Data Structures

struct  Hook
 A list of user hooks. More...
 

Functions

static TAILQ_HEAD (Hook)
 
static void delete_hook (struct Hook *h)
 Delete a Hook. More...
 
void mutt_delete_hooks (int type)
 Delete matching hooks. More...
 
int mutt_parse_unhook (struct Buffer *buf, struct Buffer *s, unsigned long data, struct Buffer *err)
 Parse the 'unhook' command - Implements command_t. More...
 
void mutt_folder_hook (const char *path)
 Perform a folder hook. More...
 
char * mutt_find_hook (int type, const char *pat)
 Find a matching hook. More...
 
void mutt_message_hook (struct Mailbox *m, struct Email *e, int type)
 Perform a message hook. More...
 
static int addr_hook (char *path, size_t pathlen, int type, struct Context *ctx, struct Email *e)
 Perform an address hook (get a path) More...
 
void mutt_default_save (char *path, size_t pathlen, struct Email *e)
 Find the default save path for an email. More...
 
void mutt_select_fcc (char *path, size_t pathlen, struct Email *e)
 Select the FCC path for an email. More...
 
static void list_hook (struct ListHead *matches, const char *match, int hook)
 Find hook strings matching. More...
 
void mutt_crypt_hook (struct ListHead *list, struct Address *addr)
 Find crypto hooks for an Address. More...
 
void mutt_account_hook (const char *url)
 Perform an account hook. More...
 
void mutt_timeout_hook (void)
 Execute any timeout hooks. More...
 
void mutt_startup_shutdown_hook (int type)
 Execute any startup/shutdown hooks. More...
 

Variables

char * DefaultHook
 Config: Pattern to use for hooks that only have a simple regex. More...
 
bool ForceName
 Config: Save outgoing mail in a folder of their name. More...
 
bool SaveName
 Config: Save outgoing message to mailbox of recipient's name if it exists. More...
 

Detailed Description

Parse and execute user-defined hooks.

Authors
  • Michael R. Elkins, and others

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 hook.c.

Function Documentation

static TAILQ_HEAD ( Hook  )
static

Definition at line 71 of file hook.c.

82 {
83  struct Hook *ptr = NULL;
84  struct Buffer command, pattern;
85  int rc;
86  bool not = false;
87  regex_t *rx = NULL;
88  struct Pattern *pat = NULL;
89  char path[PATH_MAX];
90 
91  mutt_buffer_init(&pattern);
92  mutt_buffer_init(&command);
93 
94  if (~data & MUTT_GLOBAL_HOOK) /* NOT a global hook */
95  {
96  if (*s->dptr == '!')
97  {
98  s->dptr++;
99  SKIPWS(s->dptr);
100  not = true;
101  }
102 
103  mutt_extract_token(&pattern, s, 0);
104 
105  if (!MoreArgs(s))
106  {
107  mutt_buffer_printf(err, _("%s: too few arguments"), buf->data);
108  goto error;
109  }
110  }
111 
112  mutt_extract_token(&command, s,
116  0);
117 
118  if (!command.data)
119  {
120  mutt_buffer_printf(err, _("%s: too few arguments"), buf->data);
121  goto error;
122  }
123 
124  if (MoreArgs(s))
125  {
126  mutt_buffer_printf(err, _("%s: too many arguments"), buf->data);
127  goto error;
128  }
129 
130  if (data & (MUTT_FOLDER_HOOK | MUTT_MBOX_HOOK))
131  {
132  /* Accidentally using the ^ mailbox shortcut in the .neomuttrc is a
133  * common mistake */
134  if ((*pattern.data == '^') && (!CurrentFolder))
135  {
136  mutt_buffer_strcpy(err, _("current mailbox shortcut '^' is unset"));
137  goto error;
138  }
139 
140  mutt_str_strfcpy(path, pattern.data, sizeof(path));
141  mutt_expand_path_regex(path, sizeof(path), true);
142 
143  /* Check for other mailbox shortcuts that expand to the empty string.
144  * This is likely a mistake too */
145  if (!*path && *pattern.data)
146  {
147  mutt_buffer_strcpy(err, _("mailbox shortcut expanded to empty regex"));
148  goto error;
149  }
150 
151  FREE(&pattern.data);
152  mutt_buffer_init(&pattern);
153  pattern.data = mutt_str_strdup(path);
154  }
155 #ifdef USE_COMPRESSED
156  else if (data & (MUTT_APPEND_HOOK | MUTT_OPEN_HOOK | MUTT_CLOSE_HOOK))
157  {
158  if (mutt_comp_valid_command(command.data) == 0)
159  {
160  mutt_buffer_strcpy(err, _("badly formatted command string"));
161  return -1;
162  }
163  }
164 #endif
165  else if (DefaultHook && (~data & MUTT_GLOBAL_HOOK) &&
167  (!WithCrypto || !(data & MUTT_CRYPT_HOOK)))
168  {
169  char tmp[HUGE_STRING];
170 
171  /* At this stage remain only message-hooks, reply-hooks, send-hooks,
172  * send2-hooks, save-hooks, and fcc-hooks: All those allowing full
173  * patterns. If given a simple regex, we expand $default_hook.
174  */
175  mutt_str_strfcpy(tmp, pattern.data, sizeof(tmp));
176  mutt_check_simple(tmp, sizeof(tmp), DefaultHook);
177  FREE(&pattern.data);
178  mutt_buffer_init(&pattern);
179  pattern.data = mutt_str_strdup(tmp);
180  }
181 
183  {
184  mutt_str_strfcpy(path, command.data, sizeof(path));
185  mutt_expand_path(path, sizeof(path));
186  FREE(&command.data);
187  mutt_buffer_init(&command);
188  command.data = mutt_str_strdup(path);
189  }
190 
191  /* check to make sure that a matching hook doesn't already exist */
192  TAILQ_FOREACH(ptr, &Hooks, entries)
193  {
194  if (data & MUTT_GLOBAL_HOOK)
195  {
196  /* Ignore duplicate global hooks */
197  if (mutt_str_strcmp(ptr->command, command.data) == 0)
198  {
199  FREE(&command.data);
200  return 0;
201  }
202  }
203  else if (ptr->type == data &&
204  ptr->regex.not == not&&(mutt_str_strcmp(pattern.data, ptr->regex.pattern) == 0))
205  {
207  MUTT_ACCOUNT_HOOK | MUTT_REPLY_HOOK | MUTT_CRYPT_HOOK |
209  {
210  /* these hooks allow multiple commands with the same
211  * pattern, so if we've already seen this pattern/command pair, just
212  * ignore it instead of creating a duplicate */
213  if (mutt_str_strcmp(ptr->command, command.data) == 0)
214  {
215  FREE(&command.data);
216  FREE(&pattern.data);
217  return 0;
218  }
219  }
220  else
221  {
222  /* other hooks only allow one command per pattern, so update the
223  * entry with the new command. this currently does not change the
224  * order of execution of the hooks, which i think is desirable since
225  * a common action to perform is to change the default (.) entry
226  * based upon some other information. */
227  FREE(&ptr->command);
228  ptr->command = command.data;
229  FREE(&pattern.data);
230  return 0;
231  }
232  }
233  }
234 
235  if (data & (MUTT_CHARSET_HOOK | MUTT_ICONV_HOOK))
236  {
237  /* These are managed separately by the charset code */
239  if (!mutt_ch_lookup_add(type, pattern.data, command.data, err))
240  goto error;
241  FREE(&pattern.data);
242  FREE(&command.data);
243  return 0;
244  }
245  else if (data & (MUTT_SEND_HOOK | MUTT_SEND2_HOOK | MUTT_SAVE_HOOK |
247  {
248  pat = mutt_pattern_comp(
249  pattern.data,
250  (data & (MUTT_SEND_HOOK | MUTT_SEND2_HOOK | MUTT_FCC_HOOK)) ? 0 : MUTT_FULL_MSG, err);
251  if (!pat)
252  goto error;
253  }
254  else if (~data & MUTT_GLOBAL_HOOK) /* NOT a global hook */
255  {
256  /* Hooks not allowing full patterns: Check syntax of regex */
257  rx = mutt_mem_malloc(sizeof(regex_t));
258  rc = REGCOMP(rx, NONULL(pattern.data), ((data & MUTT_CRYPT_HOOK) ? REG_ICASE : 0));
259  if (rc != 0)
260  {
261  regerror(rc, rx, err->data, err->dsize);
262  FREE(&rx);
263  goto error;
264  }
265  }
266 
267  ptr = mutt_mem_calloc(1, sizeof(struct Hook));
268  ptr->type = data;
269  ptr->command = command.data;
270  ptr->pattern = pat;
271  ptr->regex.pattern = pattern.data;
272  ptr->regex.regex = rx;
273  ptr->regex.not = not;
274  TAILQ_INSERT_TAIL(&Hooks, ptr, entries);
275  return 0;
276 
277 error:
278  if (~data & MUTT_GLOBAL_HOOK) /* NOT a global hook */
279  FREE(&pattern.data);
280  FREE(&command.data);
281  return -1;
282 }
#define MUTT_SEND_HOOK
Definition: hook.h:43
bool not
do not match
Definition: regex3.h:61
Character set conversion.
Definition: charset.h:78
#define NONULL(x)
Definition: string2.h:39
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
#define MUTT_SHUTDOWN_HOOK
Definition: hook.h:60
bool not
Definition: pattern.h:47
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
regex_t * regex
compiled expression
Definition: regex3.h:60
#define MUTT_FULL_MSG
Definition: pattern.h:39
String manipulation buffer.
Definition: buffer.h:33
A list of user hooks.
Definition: hook.c:63
#define _(a)
Definition: message.h:28
#define MUTT_CHARSET_HOOK
Definition: hook.h:46
#define MUTT_MESSAGE_HOOK
Definition: hook.h:48
bool mutt_ch_lookup_add(enum LookupType type, const char *pat, const char *replace, struct Buffer *err)
Add a new character set lookup.
Definition: charset.c:444
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:200
#define MUTT_CRYPT_HOOK
Definition: hook.h:49
A simple (non-regex) pattern.
Definition: pattern.h:44
char * command
filename, command or pattern to execute
Definition: hook.c:67
int mutt_comp_valid_command(const char *cmd)
Is this command string allowed?
Definition: compress.c:455
char * mutt_expand_path_regex(char *buf, size_t buflen, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:171
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:157
#define MoreArgs(buf)
Definition: buffer.h:44
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, int flags)
Extract one token from a string.
Definition: init.c:2520
#define MUTT_ICONV_HOOK
Definition: hook.h:47
struct Pattern * pattern
used for fcc,save,send-hook
Definition: hook.c:68
LookupType
Types of character set lookups.
Definition: charset.h:75
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: globals.h:52
struct Regex regex
regular expression
Definition: hook.c:66
#define MUTT_APPEND_HOOK
Definition: hook.h:55
#define MUTT_MBOX_HOOK
Definition: hook.h:42
#define MUTT_GLOBAL_HOOK
Definition: hook.h:61
int type
hook type
Definition: hook.c:65
#define HUGE_STRING
Definition: string2.h:37
#define MUTT_SAVE_HOOK
Definition: hook.h:45
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:316
#define PATH_MAX
Definition: mutt.h:46
char * DefaultHook
Config: Pattern to use for hooks that only have a simple regex.
Definition: hook.c:53
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:99
#define MUTT_CLOSE_HOOK
Definition: hook.h:56
#define MUTT_TOKEN_SPACE
don&#39;t treat whitespace as a term
Definition: mutt.h:73
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:742
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:803
#define MUTT_OPEN_HOOK
Definition: hook.h:54
struct Pattern * mutt_pattern_comp(char *s, int flags, struct Buffer *err)
Create a Pattern.
Definition: pattern.c:1289
#define MUTT_TIMEOUT_HOOK
Definition: hook.h:58
#define MUTT_SEND2_HOOK
Definition: hook.h:52
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
void mutt_check_simple(char *s, size_t len, const char *simple)
Convert a simple search into a real request.
Definition: pattern.c:2117
#define MUTT_REPLY_HOOK
Definition: hook.h:51
#define FREE(x)
Definition: memory.h:46
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:66
char * pattern
printable version
Definition: regex3.h:59
#define WithCrypto
Definition: ncrypt.h:154
#define MUTT_STARTUP_HOOK
Definition: hook.h:59
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:612
Alias for another character set.
Definition: charset.h:77
#define MUTT_FCC_HOOK
Definition: hook.h:44
#define REGCOMP(X, Y, Z)
Compile a regular expression.
Definition: regex3.h:52
#define MUTT_ACCOUNT_HOOK
Definition: hook.h:50
#define SKIPWS(c)
Definition: string2.h:49
#define MUTT_FOLDER_HOOK
Definition: hook.h:41

+ Here is the call graph for this function:

static void delete_hook ( struct Hook h)
static

Delete a Hook.

Parameters
hHook to delete

Definition at line 288 of file hook.c.

289 {
290  FREE(&h->command);
291  FREE(&h->regex.pattern);
292  if (h->regex.regex)
293  {
294  regfree(h->regex.regex);
295  FREE(&h->regex.regex);
296  }
298  FREE(&h);
299 }
regex_t * regex
compiled expression
Definition: regex3.h:60
void mutt_pattern_free(struct Pattern **pat)
Free a Pattern.
Definition: pattern.c:1248
char * command
filename, command or pattern to execute
Definition: hook.c:67
struct Pattern * pattern
used for fcc,save,send-hook
Definition: hook.c:68
struct Regex regex
regular expression
Definition: hook.c:66
#define FREE(x)
Definition: memory.h:46
char * pattern
printable version
Definition: regex3.h:59

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_delete_hooks ( int  type)

Delete matching hooks.

Parameters
typeHook type to delete, e.g. MUTT_SEND_HOOK

If 0 is passed, all the hooks will be deleted.

Definition at line 307 of file hook.c.

308 {
309  struct Hook *h = NULL;
310  struct Hook *tmp = NULL;
311 
312  TAILQ_FOREACH_SAFE(h, &Hooks, entries, tmp)
313  {
314  if (type == 0 || type == h->type)
315  {
316  TAILQ_REMOVE(&Hooks, h, entries);
317  delete_hook(h);
318  }
319  }
320 }
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:729
A list of user hooks.
Definition: hook.c:63
int type
hook type
Definition: hook.c:65
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:821
static void delete_hook(struct Hook *h)
Delete a Hook.
Definition: hook.c:288

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_parse_unhook ( struct Buffer buf,
struct Buffer s,
unsigned long  data,
struct Buffer err 
)

Parse the 'unhook' command - Implements command_t.

Definition at line 325 of file hook.c.

327 {
328  while (MoreArgs(s))
329  {
330  mutt_extract_token(buf, s, 0);
331  if (mutt_str_strcmp("*", buf->data) == 0)
332  {
333  if (current_hook_type)
334  {
335  mutt_buffer_printf(err, "%s", _("unhook: Can't do unhook * from within a hook"));
336  return -1;
337  }
340  }
341  else
342  {
343  int type = mutt_get_hook_type(buf->data);
344 
345  if (!type)
346  {
347  mutt_buffer_printf(err, _("unhook: unknown hook type: %s"), buf->data);
348  return -1;
349  }
350  if (type & (MUTT_CHARSET_HOOK | MUTT_ICONV_HOOK))
351  {
353  return 0;
354  }
355  if (current_hook_type == type)
356  {
357  mutt_buffer_printf(err, _("unhook: Can't delete a %s from within a %s"),
358  buf->data, buf->data);
359  return -1;
360  }
361  mutt_delete_hooks(type);
362  }
363  }
364  return 0;
365 }
#define _(a)
Definition: message.h:28
#define MUTT_CHARSET_HOOK
Definition: hook.h:46
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:200
#define MoreArgs(buf)
Definition: buffer.h:44
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, int flags)
Extract one token from a string.
Definition: init.c:2520
#define MUTT_ICONV_HOOK
Definition: hook.h:47
int type
hook type
Definition: hook.c:65
char * data
pointer to data
Definition: buffer.h:35
void mutt_delete_hooks(int type)
Delete matching hooks.
Definition: hook.c:307
void mutt_ch_lookup_remove(void)
Remove all the character set lookups.
Definition: charset.c:476
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:612
int mutt_get_hook_type(const char *name)
Find a hook by name.
Definition: init.c:2844

+ Here is the call graph for this function:

void mutt_folder_hook ( const char *  path)

Perform a folder hook.

Parameters
pathPath to match

Definition at line 371 of file hook.c.

372 {
373  struct Hook *tmp = NULL;
374  struct Buffer err, token;
375 
376  current_hook_type = MUTT_FOLDER_HOOK;
377 
378  mutt_buffer_init(&err);
379  err.dsize = STRING;
380  err.data = mutt_mem_malloc(err.dsize);
381  mutt_buffer_init(&token);
382  TAILQ_FOREACH(tmp, &Hooks, entries)
383  {
384  if (!tmp->command)
385  continue;
386 
387  if (tmp->type & MUTT_FOLDER_HOOK)
388  {
389  if ((regexec(tmp->regex.regex, path, 0, NULL, 0) == 0) ^ tmp->regex.not)
390  {
391  if (mutt_parse_rc_line(tmp->command, &token, &err) == -1)
392  {
393  mutt_error("%s", err.data);
394  FREE(&token.data);
395  current_hook_type = 0;
396  FREE(&err.data);
397 
398  return;
399  }
400  }
401  }
402  }
403  FREE(&token.data);
404  FREE(&err.data);
405 
406  current_hook_type = 0;
407 }
bool not
do not match
Definition: regex3.h:61
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
regex_t * regex
compiled expression
Definition: regex3.h:60
int mutt_parse_rc_line(char *line, struct Buffer *token, struct Buffer *err)
Parse a line of user config.
Definition: init.c:3119
String manipulation buffer.
Definition: buffer.h:33
A list of user hooks.
Definition: hook.c:63
char * command
filename, command or pattern to execute
Definition: hook.c:67
struct Regex regex
regular expression
Definition: hook.c:66
int type
hook type
Definition: hook.c:65
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:99
#define STRING
Definition: string2.h:35
#define mutt_error(...)
Definition: logging.h:88
#define FREE(x)
Definition: memory.h:46
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:66
#define MUTT_FOLDER_HOOK
Definition: hook.h:41

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

char* mutt_find_hook ( int  type,
const char *  pat 
)

Find a matching hook.

Parameters
typeType, e.g. MUTT_FOLDER_HOOK
patPattern to match
Return values
ptrCommand string
Note
The returned string must not be freed.

Definition at line 417 of file hook.c.

418 {
419  struct Hook *tmp = NULL;
420 
421  TAILQ_FOREACH(tmp, &Hooks, entries)
422  {
423  if (tmp->type & type)
424  {
425  if (regexec(tmp->regex.regex, pat, 0, NULL, 0) == 0)
426  return tmp->command;
427  }
428  }
429  return NULL;
430 }
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
regex_t * regex
compiled expression
Definition: regex3.h:60
A list of user hooks.
Definition: hook.c:63
char * command
filename, command or pattern to execute
Definition: hook.c:67
struct Regex regex
regular expression
Definition: hook.c:66
int type
hook type
Definition: hook.c:65

+ Here is the caller graph for this function:

void mutt_message_hook ( struct Mailbox m,
struct Email e,
int  type 
)

Perform a message hook.

Parameters
mMailbox Context
eEmail
typeHook type, e.g. MUTT_MESSAGE_HOOK

Definition at line 438 of file hook.c.

439 {
440  struct Buffer err, token;
441  struct Hook *hook = NULL;
442  struct PatternCache cache = { 0 };
443 
444  current_hook_type = type;
445 
446  mutt_buffer_init(&err);
447  err.dsize = STRING;
448  err.data = mutt_mem_malloc(err.dsize);
449  mutt_buffer_init(&token);
450  TAILQ_FOREACH(hook, &Hooks, entries)
451  {
452  if (!hook->command)
453  continue;
454 
455  if (hook->type & type)
456  {
457  if ((mutt_pattern_exec(hook->pattern, 0, m, e, &cache) > 0) ^
458  hook->regex.not)
459  {
460  if (mutt_parse_rc_line(hook->command, &token, &err) == -1)
461  {
462  FREE(&token.data);
463  mutt_error("%s", err.data);
464  current_hook_type = 0;
465  FREE(&err.data);
466 
467  return;
468  }
469  /* Executing arbitrary commands could affect the pattern results,
470  * so the cache has to be wiped */
471  memset(&cache, 0, sizeof(cache));
472  }
473  }
474  }
475  FREE(&token.data);
476  FREE(&err.data);
477 
478  current_hook_type = 0;
479 }
bool not
do not match
Definition: regex3.h:61
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
int mutt_parse_rc_line(char *line, struct Buffer *token, struct Buffer *err)
Parse a line of user config.
Definition: init.c:3119
String manipulation buffer.
Definition: buffer.h:33
A list of user hooks.
Definition: hook.c:63
char * command
filename, command or pattern to execute
Definition: hook.c:67
struct Pattern * pattern
used for fcc,save,send-hook
Definition: hook.c:68
struct Regex regex
regular expression
Definition: hook.c:66
int type
hook type
Definition: hook.c:65
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:99
#define STRING
Definition: string2.h:35
#define mutt_error(...)
Definition: logging.h:88
#define FREE(x)
Definition: memory.h:46
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:66
Cache commonly-used patterns.
Definition: pattern.h:80
int mutt_pattern_exec(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:1837

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int addr_hook ( char *  path,
size_t  pathlen,
int  type,
struct Context ctx,
struct Email e 
)
static

Perform an address hook (get a path)

Parameters
pathBuffer for path
pathlenLength of buffer
typeType e.g. MUTT_FCC_HOOK
ctxMailbox Context
eEmail
Return values
0Success
-1Failure

Definition at line 491 of file hook.c.

493 {
494  struct Hook *hook = NULL;
495  struct PatternCache cache = { 0 };
496 
497  /* determine if a matching hook exists */
498  TAILQ_FOREACH(hook, &Hooks, entries)
499  {
500  if (!hook->command)
501  continue;
502 
503  if (hook->type & type)
504  {
505  struct Mailbox *m = ctx ? ctx->mailbox : NULL;
506  if ((mutt_pattern_exec(hook->pattern, 0, m, e, &cache) > 0) ^ hook->regex.not)
507  {
508  mutt_make_string_flags(path, pathlen, hook->command, ctx, e, MUTT_FORMAT_PLAIN);
509  return 0;
510  }
511  }
512  }
513 
514  return -1;
515 }
bool not
do not match
Definition: regex3.h:61
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
A list of user hooks.
Definition: hook.c:63
char * command
filename, command or pattern to execute
Definition: hook.c:67
struct Mailbox * mailbox
Definition: context.h:50
struct Pattern * pattern
used for fcc,save,send-hook
Definition: hook.c:68
struct Regex regex
regular expression
Definition: hook.c:66
int type
hook type
Definition: hook.c:65
A mailbox.
Definition: mailbox.h:76
char path[PATH_MAX]
Definition: mailbox.h:78
do not prepend DISP_TO, DISP_CC ...
Definition: format_flags.h:41
void mutt_make_string_flags(char *buf, size_t buflen, const char *s, struct Context *ctx, struct Email *e, enum FormatFlag flags)
Create formatted strings using mailbox expandos.
Definition: hdrline.c:1454
Cache commonly-used patterns.
Definition: pattern.h:80
int mutt_pattern_exec(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:1837

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_default_save ( char *  path,
size_t  pathlen,
struct Email e 
)

Find the default save path for an email.

Parameters
pathBuffer for the path
pathlenLength of buffer
eEmail

Definition at line 523 of file hook.c.

524 {
525  *path = '\0';
526  if (addr_hook(path, pathlen, MUTT_SAVE_HOOK, Context, e) == 0)
527  return;
528 
529  struct Address *addr = NULL;
530  struct Envelope *env = e->env;
531  bool from_me = mutt_addr_is_user(env->from);
532 
533  if (!from_me && env->reply_to && env->reply_to->mailbox)
534  addr = env->reply_to;
535  else if (!from_me && env->from && env->from->mailbox)
536  addr = env->from;
537  else if (env->to && env->to->mailbox)
538  addr = env->to;
539  else if (env->cc && env->cc->mailbox)
540  addr = env->cc;
541  else
542  addr = NULL;
543  if (addr)
544  {
545  char tmp[PATH_MAX];
546  mutt_safe_path(tmp, sizeof(tmp), addr);
547  snprintf(path, pathlen, "=%s", tmp);
548  }
549 }
The "current" mailbox.
Definition: context.h:36
void mutt_safe_path(char *buf, size_t buflen, struct Address *a)
Make a safe filename from an email address.
Definition: muttlib.c:797
struct Address * to
Definition: envelope.h:36
An email address.
Definition: address.h:32
char * mailbox
mailbox and host address
Definition: address.h:35
struct Address * reply_to
Definition: envelope.h:40
static int addr_hook(char *path, size_t pathlen, int type, struct Context *ctx, struct Email *e)
Perform an address hook (get a path)
Definition: hook.c:491
struct Envelope * env
envelope information
Definition: email.h:91
struct Address * from
Definition: envelope.h:35
#define MUTT_SAVE_HOOK
Definition: hook.h:45
#define PATH_MAX
Definition: mutt.h:46
char path[PATH_MAX]
Definition: mailbox.h:78
struct Address * cc
Definition: envelope.h:37
The header of an email.
Definition: envelope.h:32
bool mutt_addr_is_user(struct Address *addr)
Does the address belong to the user.
Definition: alias.c:676

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_select_fcc ( char *  path,
size_t  pathlen,
struct Email e 
)

Select the FCC path for an email.

Parameters
pathBuffer for the path
pathlenLength of the buffer
eEmail

Definition at line 557 of file hook.c.

558 {
559  if (addr_hook(path, pathlen, MUTT_FCC_HOOK, NULL, e) != 0)
560  {
561  struct Envelope *env = e->env;
562  if ((SaveName || ForceName) && (env->to || env->cc || env->bcc))
563  {
564  struct Address *addr = env->to ? env->to : (env->cc ? env->cc : env->bcc);
565  char buf[PATH_MAX];
566  mutt_safe_path(buf, sizeof(buf), addr);
567  mutt_path_concat(path, NONULL(Folder), buf, pathlen);
568  if (!ForceName && mx_access(path, W_OK) != 0)
569  mutt_str_strfcpy(path, Record, pathlen);
570  }
571  else
572  mutt_str_strfcpy(path, Record, pathlen);
573  }
574  mutt_pretty_mailbox(path, pathlen);
575 }
#define NONULL(x)
Definition: string2.h:39
void mutt_pretty_mailbox(char *s, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:606
void mutt_safe_path(char *buf, size_t buflen, struct Address *a)
Make a safe filename from an email address.
Definition: muttlib.c:797
struct Address * to
Definition: envelope.h:36
An email address.
Definition: address.h:32
static int addr_hook(char *path, size_t pathlen, int type, struct Context *ctx, struct Email *e)
Perform an address hook (get a path)
Definition: hook.c:491
struct Envelope * env
envelope information
Definition: email.h:91
bool ForceName
Config: Save outgoing mail in a folder of their name.
Definition: hook.c:57
A folder/dir in the browser.
Definition: browser.h:47
struct Address * bcc
Definition: envelope.h:38
#define PATH_MAX
Definition: mutt.h:46
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:742
WHERE char * Record
Config: Folder to save &#39;sent&#39; messages.
Definition: globals.h:134
bool SaveName
Config: Save outgoing message to mailbox of recipient&#39;s name if it exists.
Definition: hook.c:58
int mx_access(const char *path, int flags)
Wrapper for access, checks permissions on a given mailbox.
Definition: mx.c:162
char * mutt_path_concat(char *d, const char *dir, const char *fname, size_t l)
Join a directory name and a filename.
Definition: path.c:323
#define MUTT_FCC_HOOK
Definition: hook.h:44
struct Address * cc
Definition: envelope.h:37
The header of an email.
Definition: envelope.h:32

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void list_hook ( struct ListHead *  matches,
const char *  match,
int  hook 
)
static

Find hook strings matching.

Parameters
[out]matchesList of hook strings
[in]matchString to match
[in]hookHook type, e.g. MUTT_CRYPT_HOOK

Definition at line 583 of file hook.c.

584 {
585  struct Hook *tmp = NULL;
586 
587  TAILQ_FOREACH(tmp, &Hooks, entries)
588  {
589  if ((tmp->type & hook) && ((match && regexec(tmp->regex.regex, match, 0, NULL, 0) == 0) ^
590  tmp->regex.not))
591  {
593  }
594  }
595 }
bool not
do not match
Definition: regex3.h:61
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
regex_t * regex
compiled expression
Definition: regex3.h:60
A list of user hooks.
Definition: hook.c:63
char * command
filename, command or pattern to execute
Definition: hook.c:67
struct Regex regex
regular expression
Definition: hook.c:66
int type
hook type
Definition: hook.c:65
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:58
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_crypt_hook ( struct ListHead *  list,
struct Address addr 
)

Find crypto hooks for an Address.

Parameters
[out]listList of keys
[in]addrAddress to match

The crypt-hook associates keys with addresses.

Definition at line 604 of file hook.c.

605 {
606  list_hook(list, addr->mailbox, MUTT_CRYPT_HOOK);
607 }
char * mailbox
mailbox and host address
Definition: address.h:35
#define MUTT_CRYPT_HOOK
Definition: hook.h:49
static void list_hook(struct ListHead *matches, const char *match, int hook)
Find hook strings matching.
Definition: hook.c:583

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_account_hook ( const char *  url)

Perform an account hook.

Parameters
urlAccount URL to match

Definition at line 614 of file hook.c.

615 {
616  /* parsing commands with URLs in an account hook can cause a recursive
617  * call. We just skip processing if this occurs. Typically such commands
618  * belong in a folder-hook -- perhaps we should warn the user. */
619  static bool inhook = false;
620 
621  struct Hook *hook = NULL;
622  struct Buffer token;
623  struct Buffer err;
624 
625  if (inhook)
626  return;
627 
628  mutt_buffer_init(&err);
629  err.dsize = STRING;
630  err.data = mutt_mem_malloc(err.dsize);
631  mutt_buffer_init(&token);
632 
633  TAILQ_FOREACH(hook, &Hooks, entries)
634  {
635  if (!(hook->command && (hook->type & MUTT_ACCOUNT_HOOK)))
636  continue;
637 
638  if ((regexec(hook->regex.regex, url, 0, NULL, 0) == 0) ^ hook->regex.not)
639  {
640  inhook = true;
641 
642  if (mutt_parse_rc_line(hook->command, &token, &err) == -1)
643  {
644  FREE(&token.data);
645  mutt_error("%s", err.data);
646  FREE(&err.data);
647 
648  inhook = false;
649  return;
650  }
651 
652  inhook = false;
653  }
654  }
655 
656  FREE(&token.data);
657  FREE(&err.data);
658 }
struct Url url
Definition: url.c:45
bool not
do not match
Definition: regex3.h:61
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
regex_t * regex
compiled expression
Definition: regex3.h:60
int mutt_parse_rc_line(char *line, struct Buffer *token, struct Buffer *err)
Parse a line of user config.
Definition: init.c:3119
String manipulation buffer.
Definition: buffer.h:33
A list of user hooks.
Definition: hook.c:63
char * command
filename, command or pattern to execute
Definition: hook.c:67
struct Regex regex
regular expression
Definition: hook.c:66
int type
hook type
Definition: hook.c:65
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:99
#define STRING
Definition: string2.h:35
#define mutt_error(...)
Definition: logging.h:88
#define FREE(x)
Definition: memory.h:46
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:66
#define MUTT_ACCOUNT_HOOK
Definition: hook.h:50

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_timeout_hook ( void  )

Execute any timeout hooks.

The user can configure hooks to be run on timeout. This function finds all the matching hooks and executes them.

Definition at line 667 of file hook.c.

668 {
669  struct Hook *hook = NULL;
670  struct Buffer token;
671  struct Buffer err;
672  char buf[STRING];
673 
674  mutt_buffer_init(&err);
675  err.data = buf;
676  err.dsize = sizeof(buf);
677  mutt_buffer_init(&token);
678 
679  TAILQ_FOREACH(hook, &Hooks, entries)
680  {
681  if (!(hook->command && (hook->type & MUTT_TIMEOUT_HOOK)))
682  continue;
683 
684  if (mutt_parse_rc_line(hook->command, &token, &err) == -1)
685  {
686  mutt_error("%s", err.data);
687  mutt_buffer_reset(&err);
688 
689  /* The hooks should be independent of each other, so even though this on
690  * failed, we'll carry on with the others. */
691  }
692  }
693  FREE(&token.data);
694 
695  /* Delete temporary attachment files */
697 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:81
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
int mutt_parse_rc_line(char *line, struct Buffer *token, struct Buffer *err)
Parse a line of user config.
Definition: init.c:3119
String manipulation buffer.
Definition: buffer.h:33
A list of user hooks.
Definition: hook.c:63
void mutt_unlink_temp_attachments(void)
Delete all temporary attachments.
Definition: mutt_attach.c:1176
char * command
filename, command or pattern to execute
Definition: hook.c:67
int type
hook type
Definition: hook.c:65
#define MUTT_TIMEOUT_HOOK
Definition: hook.h:58
#define STRING
Definition: string2.h:35
#define mutt_error(...)
Definition: logging.h:88
#define FREE(x)
Definition: memory.h:46
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:66

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_startup_shutdown_hook ( int  type)

Execute any startup/shutdown hooks.

Parameters
typeHook type: MUTT_STARTUP_HOOK or MUTT_SHUTDOWN_HOOK

The user can configure hooks to be run on startup/shutdown. This function finds all the matching hooks and executes them.

Definition at line 706 of file hook.c.

707 {
708  struct Hook *hook = NULL;
709  struct Buffer token = { 0 };
710  struct Buffer err = { 0 };
711  char buf[STRING];
712 
713  err.data = buf;
714  err.dsize = sizeof(buf);
715  mutt_buffer_init(&token);
716 
717  TAILQ_FOREACH(hook, &Hooks, entries)
718  {
719  if (!(hook->command && (hook->type & type)))
720  continue;
721 
722  if (mutt_parse_rc_line(hook->command, &token, &err) == -1)
723  {
724  mutt_error("%s", err.data);
725  mutt_buffer_reset(&err);
726  }
727  }
728  FREE(&token.data);
729 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:81
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
int mutt_parse_rc_line(char *line, struct Buffer *token, struct Buffer *err)
Parse a line of user config.
Definition: init.c:3119
String manipulation buffer.
Definition: buffer.h:33
A list of user hooks.
Definition: hook.c:63
char * command
filename, command or pattern to execute
Definition: hook.c:67
size_t dsize
length of data
Definition: buffer.h:37
int type
hook type
Definition: hook.c:65
char * data
pointer to data
Definition: buffer.h:35
#define STRING
Definition: string2.h:35
#define mutt_error(...)
Definition: logging.h:88
#define FREE(x)
Definition: memory.h:46
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:66

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Variable Documentation

char* DefaultHook

Config: Pattern to use for hooks that only have a simple regex.

Definition at line 53 of file hook.c.

bool ForceName

Config: Save outgoing mail in a folder of their name.

Definition at line 57 of file hook.c.

bool SaveName

Config: Save outgoing message to mailbox of recipient's name if it exists.

Definition at line 58 of file hook.c.