NeoMutt  2018-07-16 +2388-bcedc8
Teaching an old dog new tricks
DOXYGEN
alias.c File Reference

Representation of a single alias to an email address. More...

#include "config.h"
#include <stddef.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <wctype.h>
#include "mutt/mutt.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "mutt.h"
#include "alias.h"
#include "addrbook.h"
#include "curs_lib.h"
#include "globals.h"
#include "hdrline.h"
#include "mutt_curses.h"
#include "muttlib.h"
#include "sendlib.h"
+ Include dependency graph for alias.c:

Go to the source code of this file.

Functions

static void expand_aliases_r (struct AddressList *al, struct ListHead *expn)
 Expand aliases, recursively. More...
 
struct Aliasmutt_alias_new ()
 Create a new Alias. More...
 
static void write_safe_address (FILE *fp, char *s)
 Defang malicious email addresses. More...
 
static void recode_buf (char *buf, size_t buflen)
 Convert some text between two character sets. More...
 
static int check_alias_name (const char *s, char *dest, size_t destlen)
 Sanity-check an alias name. More...
 
static bool string_is_address (const char *str, const char *u, const char *d)
 Does an email address match a user and domain? More...
 
struct AddressList * mutt_alias_lookup (const char *s)
 Find an Alias. More...
 
void mutt_expand_aliases (struct AddressList *al)
 Expand aliases in a List of Addresses. More...
 
void mutt_expand_aliases_env (struct Envelope *env)
 Expand aliases in all the fields of an Envelope. More...
 
struct AddressList * mutt_get_address (struct Envelope *env, const char **pfxp)
 Get an Address from an Envelope. More...
 
void mutt_alias_create (struct Envelope *cur, struct AddressList *al)
 Create a new Alias from an Envelope or an Address. More...
 
struct Addressmutt_alias_reverse_lookup (const struct Address *a)
 Does the user have an alias for the given address. More...
 
void mutt_alias_add_reverse (struct Alias *t)
 Add an email address lookup for an Alias. More...
 
void mutt_alias_delete_reverse (struct Alias *t)
 Remove an email address lookup for an Alias. More...
 
int mutt_alias_complete (char *buf, size_t buflen)
 alias completion routine More...
 
bool mutt_addr_is_user (const struct Address *addr)
 Does the address belong to the user. More...
 
void mutt_alias_free (struct Alias **p)
 Free an Alias. More...
 
void mutt_aliaslist_free (struct AliasList *a_list)
 Free a List of Aliases. More...
 

Detailed Description

Representation of a single alias to an email address.

Authors
  • Michael R. Elkins
  • Pietro Cerutti

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

Function Documentation

static void expand_aliases_r ( struct AddressList *  al,
struct ListHead *  expn 
)
static

Expand aliases, recursively.

Parameters
[in]alAddress List
[out]expnAlias List
Return values
ptrAddress List with aliases expanded

ListHead expn is used as temporary storage for already-expanded aliases.

Definition at line 61 of file alias.c.

62 {
63  bool i;
64  const char *fqdn = NULL;
65 
66  struct Address *a = TAILQ_FIRST(al);
67  while (a)
68  {
69  if (!a->group && !a->personal && a->mailbox && !strchr(a->mailbox, '@'))
70  {
71  struct AddressList *alias = mutt_alias_lookup(a->mailbox);
72  if (alias)
73  {
74  i = false;
75  struct ListNode *np = NULL;
76  STAILQ_FOREACH(np, expn, entries)
77  {
78  if (mutt_str_strcmp(a->mailbox, np->data) == 0) /* alias already found */
79  {
80  mutt_debug(LL_DEBUG1, "loop in alias found for '%s'\n", a->mailbox);
81  i = true;
82  break;
83  }
84  }
85 
86  if (!i)
87  {
89  struct AddressList copy = TAILQ_HEAD_INITIALIZER(copy);
90  mutt_addrlist_copy(&copy, alias, false);
91  expand_aliases_r(&copy, expn);
92  struct Address *a2 = NULL, *tmp = NULL;
93  TAILQ_FOREACH_SAFE(a2, &copy, entries, tmp)
94  {
95  TAILQ_INSERT_BEFORE(a, a2, entries);
96  }
97  a = TAILQ_PREV(a, AddressList, entries);
98  TAILQ_REMOVE(al, TAILQ_NEXT(a, entries), entries);
99  }
100  }
101  else
102  {
103  struct passwd *pw = getpwnam(a->mailbox);
104 
105  if (pw)
106  {
107  char namebuf[256];
108 
109  mutt_gecos_name(namebuf, sizeof(namebuf), pw);
110  mutt_str_replace(&a->personal, namebuf);
111  }
112  }
113  }
114  a = TAILQ_NEXT(a, entries);
115  }
116 
117  if (C_UseDomain && (fqdn = mutt_fqdn(true)))
118  {
119  /* now qualify all local addresses */
120  mutt_addrlist_qualify(al, fqdn);
121  }
122 }
#define TAILQ_INSERT_BEFORE(listelm, elm, field)
Definition: queue.h:780
struct AddressList * mutt_alias_lookup(const char *s)
Find an Alias.
Definition: alias.c:271
#define TAILQ_FIRST(head)
Definition: queue.h:717
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:724
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:729
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
WHERE bool C_UseDomain
Config: Qualify local addresses using this domain.
Definition: globals.h:274
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:821
struct ListNode * mutt_list_insert_head(struct ListHead *h, char *s)
Insert a string at the beginning of a List.
Definition: list.c:46
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2468
char * personal
Real name of address.
Definition: address.h:36
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:637
char * data
Definition: list.h:35
Log at debug level 1.
Definition: logging.h:56
bool group
Group mailbox?
Definition: address.h:38
char * mutt_gecos_name(char *dest, size_t destlen, struct passwd *pw)
Lookup a user&#39;s real name in /etc/passwd.
Definition: muttlib.c:362
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:61
#define TAILQ_NEXT(elm, field)
Definition: queue.h:816
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
A List node for strings.
Definition: list.h:33
#define TAILQ_PREV(elm, headname, field)
Definition: queue.h:818
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:631
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

struct Alias* mutt_alias_new ( void  )

Create a new Alias.

Return values
ptrNewly allocated Alias

Free the result with mutt_alias_free()

Definition at line 130 of file alias.c.

131 {
132  struct Alias *a = mutt_mem_calloc(1, sizeof(struct Alias));
133  TAILQ_INIT(&a->addr);
134  return a;
135 }
A shortcut for an email address.
Definition: alias.h:37
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define TAILQ_INIT(head)
Definition: queue.h:759
struct AddressList addr
Definition: alias.h:40

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void write_safe_address ( FILE *  fp,
char *  s 
)
static

Defang malicious email addresses.

Parameters
fpFile to write to
sEmail address to defang

if someone has an address like From: Michael /bin/rm -f ~ Elkins me@mu.nosp@m.tt.o.nosp@m.rg and the user creates an alias for this, NeoMutt could wind up executing the backticks because it writes aliases like alias me Michael /bin/rm -f ~ Elkins me@mu.nosp@m.tt.o.nosp@m.rg To avoid this problem, use a backslash () to quote any backticks. We also need to quote backslashes as well, since you could defeat the above by doing From: Michael `/bin/rm -f ~` Elkins me@mu.nosp@m.tt.o.nosp@m.rg since that would get aliased as alias me Michael \`/bin/rm -f ~\` Elkins me@mu.nosp@m.tt.o.nosp@m.rg which still gets evaluated because the double backslash is not a quote.

Additionally, we need to quote ' and " characters - otherwise, neomutt will interpret them on the wrong parsing step.

$ wants to be quoted since it may indicate the start of an environment variable.

Definition at line 161 of file alias.c.

162 {
163  while (*s)
164  {
165  if ((*s == '\\') || (*s == '`') || (*s == '\'') || (*s == '"') || (*s == '$'))
166  fputc('\\', fp);
167  fputc(*s, fp);
168  s++;
169  }
170 }

+ Here is the caller graph for this function:

static void recode_buf ( char *  buf,
size_t  buflen 
)
static

Convert some text between two character sets.

Parameters
bufBuffer to convert
buflenLength of buffer

The 'from' charset is controlled by the 'charset' config variable. The 'to' charset is controlled by the 'config_charset' config variable.

Definition at line 180 of file alias.c.

181 {
182  if (!C_ConfigCharset || !C_Charset)
183  return;
184 
185  char *s = mutt_str_strdup(buf);
186  if (!s)
187  return;
189  mutt_str_strfcpy(buf, s, buflen);
190  FREE(&s);
191 }
int mutt_ch_convert_string(char **ps, const char *from, const char *to, int flags)
Convert a string between encodings.
Definition: charset.c:723
WHERE char * C_ConfigCharset
Config: Character set that the config files are in.
Definition: globals.h:108
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:750
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define FREE(x)
Definition: memory.h:40
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:54

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int check_alias_name ( const char *  s,
char *  dest,
size_t  destlen 
)
static

Sanity-check an alias name.

Parameters
sAlias to check
destBuffer for the result
destlenLength of buffer
Return values
0Success
-1Error

Only characters which are non-special to both the RFC822 and the neomutt configuration parser are permitted.

Definition at line 204 of file alias.c.

205 {
206  wchar_t wc;
207  mbstate_t mb;
208  size_t l;
209  int rc = 0;
210  bool dry = !dest || !destlen;
211 
212  memset(&mb, 0, sizeof(mbstate_t));
213 
214  if (!dry)
215  destlen--;
216  for (; s && *s && (dry || destlen) && (l = mbrtowc(&wc, s, MB_CUR_MAX, &mb)) != 0;
217  s += l, destlen -= l)
218  {
219  bool bad = (l == (size_t)(-1)) || (l == (size_t)(-2)); /* conversion error */
220  bad = bad || (!dry && l > destlen); /* too few room for mb char */
221  if (l == 1)
222  bad = bad || (!strchr("-_+=.", *s) && !iswalnum(wc));
223  else
224  bad = bad || !iswalnum(wc);
225  if (bad)
226  {
227  if (dry)
228  return -1;
229  if (l == (size_t)(-1))
230  memset(&mb, 0, sizeof(mbstate_t));
231  *dest++ = '_';
232  rc = -1;
233  }
234  else if (!dry)
235  {
236  memcpy(dest, s, l);
237  dest += l;
238  }
239  }
240  if (!dry)
241  *dest = '\0';
242  return rc;
243 }

+ Here is the caller graph for this function:

static bool string_is_address ( const char *  str,
const char *  u,
const char *  d 
)
static

Does an email address match a user and domain?

Parameters
strAddress string to test
uUser name
dDomain name
Return values
trueThey match

Definition at line 252 of file alias.c.

253 {
254  char buf[1024];
255 
256  snprintf(buf, sizeof(buf), "%s@%s", NONULL(u), NONULL(d));
257  if (mutt_str_strcasecmp(str, buf) == 0)
258  return true;
259 
260  return false;
261 }
#define NONULL(x)
Definition: string2.h:37
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

struct AddressList* mutt_alias_lookup ( const char *  s)

Find an Alias.

Parameters
sAlias string to find
Return values
ptrAddress for the Alias
NULLNo such Alias
Note
The search is case-insensitive

Definition at line 271 of file alias.c.

272 {
273  struct Alias *a = NULL;
274 
275  TAILQ_FOREACH(a, &Aliases, entries)
276  {
277  if (mutt_str_strcasecmp(s, a->name) == 0)
278  return &a->addr;
279  }
280  return NULL;
281 }
A shortcut for an email address.
Definition: alias.h:37
char * name
Definition: alias.h:39
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
struct AddressList addr
Definition: alias.h:40

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_expand_aliases ( struct AddressList *  al)

Expand aliases in a List of Addresses.

Parameters
alAddressList

Duplicate addresses are dropped

Definition at line 289 of file alias.c.

290 {
291  struct ListHead expn; /* previously expanded aliases to avoid loops */
292 
293  STAILQ_INIT(&expn);
294  expand_aliases_r(al, &expn);
295  mutt_list_free(&expn);
297 }
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:123
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1315
#define STAILQ_INIT(head)
Definition: queue.h:370
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:61

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_expand_aliases_env ( struct Envelope env)

Expand aliases in all the fields of an Envelope.

Parameters
envEnvelope to expand

Definition at line 303 of file alias.c.

304 {
305  mutt_expand_aliases(&env->from);
306  mutt_expand_aliases(&env->to);
307  mutt_expand_aliases(&env->cc);
308  mutt_expand_aliases(&env->bcc);
311 }
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:289
struct AddressList mail_followup_to
Email&#39;s &#39;mail-followup-to&#39;.
Definition: envelope.h:63
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:62
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:60
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

struct AddressList* mutt_get_address ( struct Envelope env,
const char **  pfxp 
)

Get an Address from an Envelope.

Parameters
[in]envEnvelope to examine
[out]pfxpPrefix for the Address, e.g. "To:"
Return values
ptrAddressList in the Envelope
Note
The caller must NOT free the returned AddressList

Definition at line 321 of file alias.c.

322 {
323  struct AddressList *al = NULL;
324  const char *pfx = NULL;
325 
326  if (mutt_addr_is_user(TAILQ_FIRST(&env->from)))
327  {
328  if (!TAILQ_EMPTY(&env->to) && !mutt_is_mail_list(TAILQ_FIRST(&env->to)))
329  {
330  pfx = "To";
331  al = &env->to;
332  }
333  else
334  {
335  pfx = "Cc";
336  al = &env->cc;
337  }
338  }
339  else if (!TAILQ_EMPTY(&env->reply_to) && !mutt_is_mail_list(TAILQ_FIRST(&env->reply_to)))
340  {
341  pfx = "Reply-To";
342  al = &env->reply_to;
343  }
344  else
345  {
346  al = &env->from;
347  pfx = "From";
348  }
349 
350  if (pfxp)
351  *pfxp = pfx;
352 
353  return al;
354 }
#define TAILQ_FIRST(head)
Definition: queue.h:717
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:62
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list?
Definition: hdrline.c:101
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:668
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
#define TAILQ_EMPTY(head)
Definition: queue.h:715

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_alias_create ( struct Envelope cur,
struct AddressList *  al 
)

Create a new Alias from an Envelope or an Address.

Parameters
curEnvelope to use
alAddress to use

Definition at line 361 of file alias.c.

362 {
363  struct Address *addr = NULL;
364  char buf[1024], tmp[1024] = { 0 }, prompt[128];
365  char *pc = NULL;
366  char *err = NULL;
367  char fixed[1024];
368 
369  if (cur)
370  {
371  al = mutt_get_address(cur, NULL);
372  }
373 
374  if (al)
375  {
376  addr = TAILQ_FIRST(al);
377  if (addr && addr->mailbox)
378  {
379  mutt_str_strfcpy(tmp, addr->mailbox, sizeof(tmp));
380  pc = strchr(tmp, '@');
381  if (pc)
382  *pc = '\0';
383  }
384  }
385 
386  /* Don't suggest a bad alias name in the event of a strange local part. */
387  check_alias_name(tmp, buf, sizeof(buf));
388 
389 retry_name:
390  /* L10N: prompt to add a new alias */
391  if ((mutt_get_field(_("Alias as: "), buf, sizeof(buf), 0) != 0) || !buf[0])
392  return;
393 
394  /* check to see if the user already has an alias defined */
395  if (mutt_alias_lookup(buf))
396  {
397  mutt_error(_("You already have an alias defined with that name"));
398  return;
399  }
400 
401  if (check_alias_name(buf, fixed, sizeof(fixed)))
402  {
403  switch (mutt_yesorno(_("Warning: This alias name may not work. Fix it?"), MUTT_YES))
404  {
405  case MUTT_YES:
406  mutt_str_strfcpy(buf, fixed, sizeof(buf));
407  goto retry_name;
408  case MUTT_ABORT:
409  return;
410  default:; // do nothing
411  }
412  }
413 
414  struct Alias *alias = mutt_alias_new();
415  alias->name = mutt_str_strdup(buf);
416 
418 
419  if (addr && addr->mailbox)
420  mutt_str_strfcpy(buf, addr->mailbox, sizeof(buf));
421  else
422  buf[0] = '\0';
423 
424  mutt_addrlist_to_intl(al, NULL);
425 
426  do
427  {
428  if ((mutt_get_field(_("Address: "), buf, sizeof(buf), 0) != 0) || !buf[0])
429  {
430  mutt_alias_free(&alias);
431  return;
432  }
433 
434  mutt_addrlist_parse(&alias->addr, buf);
435  if (TAILQ_EMPTY(&alias->addr))
436  BEEP();
437  if (mutt_addrlist_to_intl(&alias->addr, &err))
438  {
439  mutt_error(_("Bad IDN: '%s'"), err);
440  FREE(&err);
441  continue;
442  }
443  } while (TAILQ_EMPTY(&alias->addr));
444 
445  if (addr && addr->personal && !mutt_is_mail_list(addr))
446  mutt_str_strfcpy(buf, addr->personal, sizeof(buf));
447  else
448  buf[0] = '\0';
449 
450  if (mutt_get_field(_("Personal name: "), buf, sizeof(buf), 0) != 0)
451  {
452  mutt_alias_free(&alias);
453  return;
454  }
455  mutt_str_replace(&TAILQ_FIRST(&alias->addr)->personal, buf);
456 
457  buf[0] = '\0';
458  mutt_addrlist_write(buf, sizeof(buf), &alias->addr, true);
459  snprintf(prompt, sizeof(prompt), _("[%s = %s] Accept?"), alias->name, buf);
460  if (mutt_yesorno(prompt, MUTT_YES) != MUTT_YES)
461  {
462  mutt_alias_free(&alias);
463  return;
464  }
465 
466  mutt_alias_add_reverse(alias);
467  TAILQ_INSERT_TAIL(&Aliases, alias, entries);
468 
469  mutt_str_strfcpy(buf, C_AliasFile, sizeof(buf));
470  if (mutt_get_field(_("Save to file: "), buf, sizeof(buf), MUTT_FILE) != 0)
471  return;
472  mutt_expand_path(buf, sizeof(buf));
473  FILE *fp_alias = fopen(buf, "a+");
474  if (!fp_alias)
475  {
476  mutt_perror(buf);
477  return;
478  }
479 
480  /* terminate existing file with \n if necessary */
481  if (fseek(fp_alias, 0, SEEK_END))
482  goto fseek_err;
483  if (ftell(fp_alias) > 0)
484  {
485  if (fseek(fp_alias, -1, SEEK_CUR) < 0)
486  goto fseek_err;
487  if (fread(buf, 1, 1, fp_alias) != 1)
488  {
489  mutt_perror(_("Error reading alias file"));
490  mutt_file_fclose(&fp_alias);
491  return;
492  }
493  if (fseek(fp_alias, 0, SEEK_END) < 0)
494  goto fseek_err;
495  if (buf[0] != '\n')
496  fputc('\n', fp_alias);
497  }
498 
499  if (check_alias_name(alias->name, NULL, 0))
500  mutt_file_quote_filename(alias->name, buf, sizeof(buf));
501  else
502  mutt_str_strfcpy(buf, alias->name, sizeof(buf));
503  recode_buf(buf, sizeof(buf));
504  fprintf(fp_alias, "alias %s ", buf);
505  buf[0] = '\0';
506  mutt_addrlist_write(buf, sizeof(buf), &alias->addr, false);
507  recode_buf(buf, sizeof(buf));
508  write_safe_address(fp_alias, buf);
509  fputc('\n', fp_alias);
510  if (mutt_file_fsync_close(&fp_alias) != 0)
511  mutt_perror(_("Trouble adding alias"));
512  else
513  mutt_message(_("Alias added"));
514 
515  return;
516 
517 fseek_err:
518  mutt_perror(_("Error seeking in alias file"));
519  mutt_file_fclose(&fp_alias);
520 }
A shortcut for an email address.
Definition: alias.h:37
char * name
Definition: alias.h:39
struct AddressList * mutt_alias_lookup(const char *s)
Find an Alias.
Definition: alias.c:271
#define TAILQ_FIRST(head)
Definition: queue.h:717
#define mutt_perror(...)
Definition: logging.h:85
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:454
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:165
User aborted the question (with Ctrl-G)
Definition: quad.h:37
#define mutt_message(...)
Definition: logging.h:83
struct AddressList * mutt_get_address(struct Envelope *env, const char **pfxp)
Get an Address from an Envelope.
Definition: alias.c:321
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1295
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list?
Definition: hdrline.c:101
#define _(a)
Definition: message.h:28
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
size_t mutt_addrlist_write(char *buf, size_t buflen, const struct AddressList *al, bool display)
Write an Address to a buffer.
Definition: address.c:1134
WHERE char * C_AliasFile
Config: Save new aliases to this file.
Definition: globals.h:100
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:86
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:128
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:332
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
struct Alias * mutt_alias_new()
Create a new Alias.
Definition: alias.c:130
#define BEEP()
Definition: mutt_curses.h:80
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:750
static int check_alias_name(const char *s, char *dest, size_t destlen)
Sanity-check an alias name.
Definition: alias.c:204
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:803
size_t mutt_file_quote_filename(const char *filename, char *buf, size_t buflen)
Quote a filename to survive the shell&#39;s quoting rules.
Definition: file.c:789
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
#define MUTT_FILE
Do file completion.
Definition: mutt.h:65
static void write_safe_address(FILE *fp, char *s)
Defang malicious email addresses.
Definition: alias.c:161
char * personal
Real name of address.
Definition: address.h:36
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1213
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define mutt_error(...)
Definition: logging.h:84
void mutt_alias_add_reverse(struct Alias *t)
Add an email address lookup for an Alias.
Definition: alias.c:539
void mutt_alias_free(struct Alias **p)
Free an Alias.
Definition: alias.c:727
#define FREE(x)
Definition: memory.h:40
#define TAILQ_EMPTY(head)
Definition: queue.h:715
struct AddressList addr
Definition: alias.h:40
static void recode_buf(char *buf, size_t buflen)
Convert some text between two character sets.
Definition: alias.c:180

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

struct Address* mutt_alias_reverse_lookup ( const struct Address a)

Does the user have an alias for the given address.

Parameters
aAddress to lookup
Return values
ptrMatching Address

Definition at line 527 of file alias.c.

528 {
529  if (!a || !a->mailbox)
530  return NULL;
531 
533 }
void * mutt_hash_find(const struct Hash *table, const char *strkey)
Find the HashElem data in a Hash table element using a key.
Definition: hash.c:379
char * mailbox
Mailbox and host address.
Definition: address.h:37
WHERE struct Hash * ReverseAliases
Hash table of aliases (email address -> alias)
Definition: globals.h:58

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_alias_add_reverse ( struct Alias t)

Add an email address lookup for an Alias.

Parameters
tAlias to use

Definition at line 539 of file alias.c.

540 {
541  if (!t)
542  return;
543 
544  /* Note that the address mailbox should be converted to intl form
545  * before using as a key in the hash. This is currently done
546  * by all callers, but added here mostly as documentation. */
547  mutt_addrlist_to_intl(&t->addr, NULL);
548 
549  struct Address *a = NULL;
550  TAILQ_FOREACH(a, &t->addr, entries)
551  {
552  if (!a->group && a->mailbox)
554  }
555 }
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
WHERE struct Hash * ReverseAliases
Hash table of aliases (email address -> alias)
Definition: globals.h:58
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1213
bool group
Group mailbox?
Definition: address.h:38
struct AddressList addr
Definition: alias.h:40
struct HashElem * mutt_hash_insert(struct Hash *table, const char *strkey, void *data)
Add a new element to the Hash table (with string keys)
Definition: hash.c:352

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_alias_delete_reverse ( struct Alias t)

Remove an email address lookup for an Alias.

Parameters
tAlias to use

Definition at line 561 of file alias.c.

562 {
563  if (!t)
564  return;
565 
566  /* If the alias addresses were converted to local form, they won't
567  * match the hash entries. */
568  mutt_addrlist_to_intl(&t->addr, NULL);
569 
570  struct Address *a = NULL;
571  TAILQ_FOREACH(a, &t->addr, entries)
572  {
573  if (!a->group && a->mailbox)
575  }
576 }
void mutt_hash_delete(struct Hash *table, const char *strkey, const void *data)
Remove an element from a Hash table.
Definition: hash.c:444
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
WHERE struct Hash * ReverseAliases
Hash table of aliases (email address -> alias)
Definition: globals.h:58
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1213
bool group
Group mailbox?
Definition: address.h:38
struct AddressList addr
Definition: alias.h:40

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_alias_complete ( char *  buf,
size_t  buflen 
)

alias completion routine

Parameters
bufPartial Alias to complete
buflenLength of buffer
Return values
1Success
0Error

Given a partial alias, this routine attempts to fill in the alias from the alias list as much as possible. if given empty search string or found nothing, present all aliases

Definition at line 589 of file alias.c.

590 {
591  struct Alias *a = NULL, *tmp = NULL;
592  struct AliasList a_list = TAILQ_HEAD_INITIALIZER(a_list);
593  char bestname[8192] = { 0 };
594 
595  if (buf[0] != '\0') /* avoid empty string as strstr argument */
596  {
597  TAILQ_FOREACH(a, &Aliases, entries)
598  {
599  if (a->name && (strncmp(a->name, buf, strlen(buf)) == 0))
600  {
601  if (bestname[0] == '\0') /* init */
602  {
603  mutt_str_strfcpy(bestname, a->name,
604  MIN(mutt_str_strlen(a->name) + 1, sizeof(bestname)));
605  }
606  else
607  {
608  int i;
609  for (i = 0; a->name[i] && (a->name[i] == bestname[i]); i++)
610  ;
611  bestname[i] = '\0';
612  }
613  }
614  }
615 
616  if (bestname[0] != '\0')
617  {
618  if (mutt_str_strcmp(bestname, buf) != 0)
619  {
620  /* we are adding something to the completion */
621  mutt_str_strfcpy(buf, bestname, mutt_str_strlen(bestname) + 1);
622  return 1;
623  }
624 
625  /* build alias list and show it */
626  TAILQ_FOREACH(a, &Aliases, entries)
627  {
628  if (a->name && (strncmp(a->name, buf, strlen(buf)) == 0))
629  {
630  tmp = mutt_mem_calloc(1, sizeof(struct Alias));
631  memcpy(tmp, a, sizeof(struct Alias));
632  TAILQ_INSERT_TAIL(&a_list, tmp, entries);
633  }
634  }
635  }
636  }
637 
638  bestname[0] = '\0';
639  mutt_alias_menu(bestname, sizeof(bestname), !TAILQ_EMPTY(&a_list) ? &a_list : &Aliases);
640  if (bestname[0] != '\0')
641  mutt_str_strfcpy(buf, bestname, buflen);
642 
643  /* free the alias list */
644  TAILQ_FOREACH_SAFE(a, &a_list, entries, tmp)
645  {
646  TAILQ_REMOVE(&a_list, a, entries);
647  FREE(&a);
648  }
649 
650  /* remove any aliases marked for deletion */
651  TAILQ_FOREACH_SAFE(a, &Aliases, entries, tmp)
652  {
653  if (a->del)
654  {
655  TAILQ_REMOVE(&Aliases, a, entries);
656  mutt_alias_free(&a);
657  }
658  }
659 
660  return 0;
661 }
A shortcut for an email address.
Definition: alias.h:37
char * name
Definition: alias.h:39
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define MIN(a, b)
Definition: memory.h:31
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:729
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
bool del
Definition: alias.h:42
void mutt_alias_menu(char *buf, size_t buflen, struct AliasList *aliases)
Display a menu of Aliases.
Definition: addrbook.c:193
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:821
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:750
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:803
void mutt_alias_free(struct Alias **p)
Free an Alias.
Definition: alias.c:727
#define FREE(x)
Definition: memory.h:40
#define TAILQ_EMPTY(head)
Definition: queue.h:715
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:631
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool mutt_addr_is_user ( const struct Address addr)

Does the address belong to the user.

Parameters
addrAddress to check
Return values
trueif the given address belongs to the user

Definition at line 668 of file alias.c.

669 {
670  if (!addr)
671  {
672  mutt_debug(LL_DEBUG5, "no, NULL address\n");
673  return false;
674  }
675  if (!addr->mailbox)
676  {
677  mutt_debug(LL_DEBUG5, "no, no mailbox\n");
678  return false;
679  }
680 
681  if (mutt_str_strcasecmp(addr->mailbox, Username) == 0)
682  {
683  mutt_debug(LL_DEBUG5, "#1 yes, %s = %s\n", addr->mailbox, Username);
684  return true;
685  }
687  {
688  mutt_debug(LL_DEBUG5, "#2 yes, %s = %s @ %s\n", addr->mailbox, Username, ShortHostname);
689  return true;
690  }
691  const char *fqdn = mutt_fqdn(false);
692  if (string_is_address(addr->mailbox, Username, fqdn))
693  {
694  mutt_debug(LL_DEBUG5, "#3 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
695  return true;
696  }
697  fqdn = mutt_fqdn(true);
698  if (string_is_address(addr->mailbox, Username, fqdn))
699  {
700  mutt_debug(LL_DEBUG5, "#4 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
701  return true;
702  }
703 
704  if (C_From && (mutt_str_strcasecmp(C_From->mailbox, addr->mailbox) == 0))
705  {
706  mutt_debug(LL_DEBUG5, "#5 yes, %s = %s\n", addr->mailbox, C_From->mailbox);
707  return true;
708  }
709 
710  if (mutt_regexlist_match(&Alternates, addr->mailbox))
711  {
712  mutt_debug(LL_DEBUG5, "yes, %s matched by alternates\n", addr->mailbox);
713  if (mutt_regexlist_match(&UnAlternates, addr->mailbox))
714  mutt_debug(LL_DEBUG5, "but, %s matched by unalternates\n", addr->mailbox);
715  else
716  return true;
717  }
718 
719  mutt_debug(LL_DEBUG5, "no, all failed\n");
720  return false;
721 }
WHERE char * Username
User&#39;s login name.
Definition: globals.h:51
#define NONULL(x)
Definition: string2.h:37
char * mailbox
Mailbox and host address.
Definition: address.h:37
WHERE struct Address * C_From
Config: Default &#39;From&#39; address to use, if isn&#39;t otherwise set.
Definition: globals.h:98
bool mutt_regexlist_match(struct RegexList *rl, const char *str)
Does a string match any Regex in the list?
Definition: regex.c:191
static bool string_is_address(const char *str, const char *u, const char *d)
Does an email address match a user and domain?
Definition: alias.c:252
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2468
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
WHERE char * ShortHostname
Short version of the hostname.
Definition: globals.h:49
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Log at debug level 5.
Definition: logging.h:60

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_alias_free ( struct Alias **  p)

Free an Alias.

Parameters
[out]pAlias to free

Definition at line 727 of file alias.c.

728 {
729  if (!p || !*p)
730  return;
731 
733  FREE(&(*p)->name);
734  mutt_addrlist_clear(&((*p)->addr));
735  FREE(p);
736 }
void mutt_alias_delete_reverse(struct Alias *t)
Remove an email address lookup for an Alias.
Definition: alias.c:561
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1378
#define FREE(x)
Definition: memory.h:40

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_aliaslist_free ( struct AliasList *  a_list)

Free a List of Aliases.

Parameters
a_listAliasList to free

Definition at line 742 of file alias.c.

743 {
744  struct Alias *a = NULL, *tmp = NULL;
745  TAILQ_FOREACH_SAFE(a, a_list, entries, tmp)
746  {
747  TAILQ_REMOVE(a_list, a, entries);
748  mutt_alias_free(&a);
749  }
750  TAILQ_INIT(a_list);
751 }
A shortcut for an email address.
Definition: alias.h:37
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:729
#define TAILQ_INIT(head)
Definition: queue.h:759
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:821
void mutt_alias_free(struct Alias **p)
Free an Alias.
Definition: alias.c:727

+ Here is the call graph for this function:

+ Here is the caller graph for this function: