NeoMutt  2018-07-16 +1360-3df4a2
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 <errno.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 "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 struct Addressexpand_aliases_r (struct Address *a, struct ListHead *expn)
 Expand aliases, recursively. 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 Addressmutt_alias_lookup (const char *s)
 Find an Alias. More...
 
struct Addressmutt_expand_aliases (struct Address *a)
 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 Addressmutt_get_address (struct Envelope *env, const char **pfxp)
 Get an Address from an Envelope. More...
 
void mutt_alias_create (struct Envelope *cur, struct Address *iaddr)
 Create a new Alias from an Envelope or an Address. More...
 
struct Addressmutt_alias_reverse_lookup (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 (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

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 struct Address* expand_aliases_r ( struct Address a,
struct ListHead *  expn 
)
static

Expand aliases, recursively.

Parameters
[in]aAddress 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 60 of file alias.c.

61 {
62  struct Address *head = NULL, *last = NULL, *t = NULL, *w = NULL;
63  bool i;
64  const char *fqdn = NULL;
65 
66  while (a)
67  {
68  if (!a->group && !a->personal && a->mailbox && !strchr(a->mailbox, '@'))
69  {
70  t = mutt_alias_lookup(a->mailbox);
71 
72  if (t)
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  w = mutt_addr_copy_list(t, false);
90  w = expand_aliases_r(w, expn);
91  if (head)
92  last->next = w;
93  else
94  {
95  head = w;
96  last = w;
97  }
98  while (last && last->next)
99  last = last->next;
100  }
101  t = a;
102  a = a->next;
103  t->next = NULL;
104  mutt_addr_free(&t);
105  continue;
106  }
107  else
108  {
109  struct passwd *pw = getpwnam(a->mailbox);
110 
111  if (pw)
112  {
113  char namebuf[256];
114 
115  mutt_gecos_name(namebuf, sizeof(namebuf), pw);
116  mutt_str_replace(&a->personal, namebuf);
117  }
118  }
119  }
120 
121  if (head)
122  {
123  last->next = a;
124  last = last->next;
125  }
126  else
127  {
128  head = a;
129  last = a;
130  }
131  a = a->next;
132  last->next = NULL;
133  }
134 
135  if (C_UseDomain && (fqdn = mutt_fqdn(true)))
136  {
137  /* now qualify all local addresses */
138  mutt_addr_qualify(head, fqdn);
139  }
140 
141  return head;
142 }
An email address.
Definition: address.h:32
char * mailbox
mailbox and host address
Definition: address.h:35
struct Address * mutt_alias_lookup(const char *s)
Find an Alias.
Definition: alias.c:278
WHERE bool C_UseDomain
Config: Qualify local addresses using this domain.
Definition: globals.h:265
static struct Address * expand_aliases_r(struct Address *a, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:60
void mutt_addr_qualify(struct Address *addr, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:660
struct ListNode * mutt_list_insert_head(struct ListHead *h, char *s)
Insert a string at the beginning of a List.
Definition: list.c:44
#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:459
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2432
char * personal
real name of address
Definition: address.h:34
char * data
Definition: list.h:35
Log at debug level 1.
Definition: logging.h:56
bool group
group mailbox?
Definition: address.h:36
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:353
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
struct Address * mutt_addr_copy_list(struct Address *addr, bool prune)
Copy a list of addresses.
Definition: address.c:730
void mutt_addr_free(struct Address **p)
Free a list of Addresses.
Definition: address.c:446
A List node for strings.
Definition: list.h:33
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:611
struct Address * next
Definition: address.h:39

+ 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 168 of file alias.c.

169 {
170  while (*s)
171  {
172  if ((*s == '\\') || (*s == '`') || (*s == '\'') || (*s == '"') || (*s == '$'))
173  fputc('\\', fp);
174  fputc(*s, fp);
175  s++;
176  }
177 }

+ 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 187 of file alias.c.

188 {
190  return;
191 
192  char *s = mutt_str_strdup(buf);
193  if (!s)
194  return;
196  mutt_str_strfcpy(buf, s, buflen);
197  FREE(&s);
198 }
int mutt_ch_convert_string(char **ps, const char *from, const char *to, int flags)
Convert a string between encodings.
Definition: charset.c:717
WHERE char * C_ConfigCharset
Config: Character set that the config files are in.
Definition: globals.h:107
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:741
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
#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 211 of file alias.c.

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

+ 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 259 of file alias.c.

260 {
261  char buf[1024];
262 
263  snprintf(buf, sizeof(buf), "%s@%s", NONULL(u), NONULL(d));
264  if (mutt_str_strcasecmp(str, buf) == 0)
265  return true;
266 
267  return false;
268 }
#define NONULL(x)
Definition: string2.h:36
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:624

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

struct Address* 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 278 of file alias.c.

279 {
280  struct Alias *a = NULL;
281 
282  TAILQ_FOREACH(a, &Aliases, entries)
283  {
284  if (mutt_str_strcasecmp(s, a->name) == 0)
285  return a->addr;
286  }
287  return NULL;
288 }
A shortcut for an email address.
Definition: alias.h:36
char * name
Definition: alias.h:38
#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:624
struct Address * addr
Definition: alias.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

struct Address* mutt_expand_aliases ( struct Address a)

Expand aliases in a List of Addresses.

Parameters
aFirst Address
Return values
ptrTop of the de-duped list

Duplicate addresses are dropped

Definition at line 297 of file alias.c.

298 {
299  struct Address *t = NULL;
300  struct ListHead expn; /* previously expanded aliases to avoid loops */
301 
302  STAILQ_INIT(&expn);
303  t = expand_aliases_r(a, &expn);
304  mutt_list_free(&expn);
305  return mutt_addrlist_dedupe(t);
306 }
struct Address * mutt_addrlist_dedupe(struct Address *addr)
Remove duplicate addresses.
Definition: address.c:1281
An email address.
Definition: address.h:32
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:105
#define STAILQ_INIT(head)
Definition: queue.h:370
static struct Address * expand_aliases_r(struct Address *a, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:60

+ 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 312 of file alias.c.

313 {
314  env->from = mutt_expand_aliases(env->from);
315  env->to = mutt_expand_aliases(env->to);
316  env->cc = mutt_expand_aliases(env->cc);
317  env->bcc = mutt_expand_aliases(env->bcc);
320 }
struct Address * to
Definition: envelope.h:42
struct Address * reply_to
Definition: envelope.h:46
struct Address * mail_followup_to
Definition: envelope.h:47
struct Address * from
Definition: envelope.h:41
struct Address * bcc
Definition: envelope.h:44
struct Address * mutt_expand_aliases(struct Address *a)
Expand aliases in a List of Addresses.
Definition: alias.c:297
struct Address * cc
Definition: envelope.h:43

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

struct Address* 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
ptrAddress in the Envelope

Definition at line 328 of file alias.c.

329 {
330  struct Address *addr = NULL;
331  const char *pfx = NULL;
332 
333  if (mutt_addr_is_user(env->from))
334  {
335  if (env->to && !mutt_is_mail_list(env->to))
336  {
337  pfx = "To";
338  addr = env->to;
339  }
340  else
341  {
342  pfx = "Cc";
343  addr = env->cc;
344  }
345  }
346  else if (env->reply_to && !mutt_is_mail_list(env->reply_to))
347  {
348  pfx = "Reply-To";
349  addr = env->reply_to;
350  }
351  else
352  {
353  addr = env->from;
354  pfx = "From";
355  }
356 
357  if (pfxp)
358  *pfxp = pfx;
359 
360  return addr;
361 }
struct Address * to
Definition: envelope.h:42
An email address.
Definition: address.h:32
bool mutt_is_mail_list(struct Address *addr)
Is this the email address of a mailing list?
Definition: hdrline.c:99
struct Address * reply_to
Definition: envelope.h:46
struct Address * from
Definition: envelope.h:41
struct Address * cc
Definition: envelope.h:43
bool mutt_addr_is_user(struct Address *addr)
Does the address belong to the user.
Definition: alias.c:678

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_alias_create ( struct Envelope cur,
struct Address iaddr 
)

Create a new Alias from an Envelope or an Address.

Parameters
curEnvelope to use
iaddrAddress to use

Definition at line 368 of file alias.c.

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

struct Address* mutt_alias_reverse_lookup ( struct Address a)

Does the user have an alias for the given address.

Parameters
aAddress to lookup
Return values
ptrMatching Address

Definition at line 537 of file alias.c.

538 {
539  if (!a || !a->mailbox)
540  return NULL;
541 
543 }
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:373
char * mailbox
mailbox and host address
Definition: address.h:35
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 549 of file alias.c.

550 {
551  struct Address *ap = NULL;
552  if (!t)
553  return;
554 
555  /* Note that the address mailbox should be converted to intl form
556  * before using as a key in the hash. This is currently done
557  * by all callers, but added here mostly as documentation. */
558  mutt_addrlist_to_intl(t->addr, NULL);
559 
560  for (ap = t->addr; ap; ap = ap->next)
561  {
562  if (!ap->group && ap->mailbox)
564  }
565 }
An email address.
Definition: address.h:32
char * mailbox
mailbox and host address
Definition: address.h:35
int mutt_addrlist_to_intl(struct Address *a, char **err)
Convert an Address list to Punycode.
Definition: address.c:1208
WHERE struct Hash * ReverseAliases
Hash table of aliases (email address -> alias)
Definition: globals.h:58
bool group
group mailbox?
Definition: address.h:36
struct Address * addr
Definition: alias.h:39
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:348
struct Address * next
Definition: address.h:39

+ 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 571 of file alias.c.

572 {
573  struct Address *ap = NULL;
574  if (!t)
575  return;
576 
577  /* If the alias addresses were converted to local form, they won't
578  * match the hash entries. */
579  mutt_addrlist_to_intl(t->addr, NULL);
580 
581  for (ap = t->addr; ap; ap = ap->next)
582  {
583  if (!ap->group && ap->mailbox)
585  }
586 }
void mutt_hash_delete(struct Hash *table, const char *strkey, const void *data)
Remove an element from a Hash table.
Definition: hash.c:433
An email address.
Definition: address.h:32
char * mailbox
mailbox and host address
Definition: address.h:35
int mutt_addrlist_to_intl(struct Address *a, char **err)
Convert an Address list to Punycode.
Definition: address.c:1208
WHERE struct Hash * ReverseAliases
Hash table of aliases (email address -> alias)
Definition: globals.h:58
bool group
group mailbox?
Definition: address.h:36
struct Address * addr
Definition: alias.h:39
struct Address * next
Definition: address.h:39

+ 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 599 of file alias.c.

600 {
601  struct Alias *a = NULL, *tmp = NULL;
602  struct AliasList a_list = TAILQ_HEAD_INITIALIZER(a_list);
603  char bestname[8192] = { 0 };
604 
605  if (buf[0] != '\0') /* avoid empty string as strstr argument */
606  {
607  TAILQ_FOREACH(a, &Aliases, entries)
608  {
609  if (a->name && (strncmp(a->name, buf, strlen(buf)) == 0))
610  {
611  if (bestname[0] == '\0') /* init */
612  {
613  mutt_str_strfcpy(bestname, a->name,
614  MIN(mutt_str_strlen(a->name) + 1, sizeof(bestname)));
615  }
616  else
617  {
618  int i;
619  for (i = 0; a->name[i] && (a->name[i] == bestname[i]); i++)
620  ;
621  bestname[i] = '\0';
622  }
623  }
624  }
625 
626  if (bestname[0] != '\0')
627  {
628  if (mutt_str_strcmp(bestname, buf) != 0)
629  {
630  /* we are adding something to the completion */
631  mutt_str_strfcpy(buf, bestname, mutt_str_strlen(bestname) + 1);
632  return 1;
633  }
634 
635  /* build alias list and show it */
636  TAILQ_FOREACH(a, &Aliases, entries)
637  {
638  if (a->name && (strncmp(a->name, buf, strlen(buf)) == 0))
639  {
640  tmp = mutt_mem_calloc(1, sizeof(struct Alias));
641  memcpy(tmp, a, sizeof(struct Alias));
642  TAILQ_INSERT_TAIL(&a_list, tmp, entries);
643  }
644  }
645  }
646  }
647 
648  bestname[0] = '\0';
649  mutt_alias_menu(bestname, sizeof(bestname), !TAILQ_EMPTY(&a_list) ? &a_list : &Aliases);
650  if (bestname[0] != '\0')
651  mutt_str_strfcpy(buf, bestname, buflen);
652 
653  /* free the alias list */
654  TAILQ_FOREACH_SAFE(a, &a_list, entries, tmp)
655  {
656  TAILQ_REMOVE(&a_list, a, entries);
657  FREE(&a);
658  }
659 
660  /* remove any aliases marked for deletion */
661  TAILQ_FOREACH_SAFE(a, &Aliases, entries, tmp)
662  {
663  if (a->del)
664  {
665  TAILQ_REMOVE(&Aliases, a, entries);
666  mutt_alias_free(&a);
667  }
668  }
669 
670  return 0;
671 }
A shortcut for an email address.
Definition: alias.h:36
char * name
Definition: alias.h:38
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
#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:662
bool del
Definition: alias.h:41
void mutt_alias_menu(char *buf, size_t buflen, struct AliasList *aliases)
Display a menu of Aliases.
Definition: addrbook.c:188
#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:741
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:803
void mutt_alias_free(struct Alias **p)
Free an Alias.
Definition: alias.c:740
#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:611

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool mutt_addr_is_user ( 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 678 of file alias.c.

679 {
680  const char *fqdn = NULL;
681 
682  /* NULL address is assumed to be the user. */
683  if (!addr)
684  {
685  mutt_debug(5, "yes, NULL address\n");
686  return true;
687  }
688  if (!addr->mailbox)
689  {
690  mutt_debug(5, "no, no mailbox\n");
691  return false;
692  }
693 
694  if (mutt_str_strcasecmp(addr->mailbox, Username) == 0)
695  {
696  mutt_debug(5, "#1 yes, %s = %s\n", addr->mailbox, Username);
697  return true;
698  }
700  {
701  mutt_debug(5, "#2 yes, %s = %s @ %s\n", addr->mailbox, Username, ShortHostname);
702  return true;
703  }
704  fqdn = mutt_fqdn(false);
705  if (string_is_address(addr->mailbox, Username, fqdn))
706  {
707  mutt_debug(5, "#3 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
708  return true;
709  }
710  fqdn = mutt_fqdn(true);
711  if (string_is_address(addr->mailbox, Username, fqdn))
712  {
713  mutt_debug(5, "#4 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
714  return true;
715  }
716 
717  if (C_From && (mutt_str_strcasecmp(C_From->mailbox, addr->mailbox) == 0))
718  {
719  mutt_debug(5, "#5 yes, %s = %s\n", addr->mailbox, C_From->mailbox);
720  return true;
721  }
722 
723  if (mutt_regexlist_match(&Alternates, addr->mailbox))
724  {
725  mutt_debug(5, "yes, %s matched by alternates.\n", addr->mailbox);
726  if (mutt_regexlist_match(&UnAlternates, addr->mailbox))
727  mutt_debug(5, "but, %s matched by unalternates.\n", addr->mailbox);
728  else
729  return true;
730  }
731 
732  mutt_debug(5, "no, all failed.\n");
733  return false;
734 }
WHERE char * Username
User&#39;s login name.
Definition: globals.h:51
#define NONULL(x)
Definition: string2.h:36
char * mailbox
mailbox and host address
Definition: address.h:35
WHERE struct Address * C_From
Config: Default &#39;From&#39; address to use, if isn&#39;t otherwise set.
Definition: globals.h:101
bool mutt_regexlist_match(struct RegexList *rl, const char *str)
Does a string match any Regex in the list?
Definition: regex.c:188
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:259
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2432
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:624
WHERE char * ShortHostname
Short version of the hostname.
Definition: globals.h:49
#define mutt_debug(LEVEL,...)
Definition: logging.h:85

+ 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 740 of file alias.c.

741 {
742  if (!p || !*p)
743  return;
744 
746  FREE(&(*p)->name);
747  mutt_addr_free(&(*p)->addr);
748  FREE(p);
749 }
void mutt_alias_delete_reverse(struct Alias *t)
Remove an email address lookup for an Alias.
Definition: alias.c:571
#define FREE(x)
Definition: memory.h:40
void mutt_addr_free(struct Address **p)
Free a list of Addresses.
Definition: address.c:446

+ 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 755 of file alias.c.

756 {
757  struct Alias *a = NULL, *tmp = NULL;
758  TAILQ_FOREACH_SAFE(a, a_list, entries, tmp)
759  {
760  TAILQ_REMOVE(a_list, a, entries);
761  mutt_alias_free(&a);
762  }
763  TAILQ_INIT(a_list);
764 }
A shortcut for an email address.
Definition: alias.h:36
#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:740

+ Here is the call graph for this function:

+ Here is the caller graph for this function: