NeoMutt  2018-07-16 +1783-b00bd9
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 "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 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 61 of file alias.c.

62 {
63  struct Address *head = NULL, *last = NULL, *t = NULL, *w = NULL;
64  bool i;
65  const char *fqdn = NULL;
66 
67  while (a)
68  {
69  if (!a->group && !a->personal && a->mailbox && !strchr(a->mailbox, '@'))
70  {
71  t = mutt_alias_lookup(a->mailbox);
72 
73  if (t)
74  {
75  i = false;
76  struct ListNode *np = NULL;
77  STAILQ_FOREACH(np, expn, entries)
78  {
79  if (mutt_str_strcmp(a->mailbox, np->data) == 0) /* alias already found */
80  {
81  mutt_debug(LL_DEBUG1, "loop in alias found for '%s'\n", a->mailbox);
82  i = true;
83  break;
84  }
85  }
86 
87  if (!i)
88  {
90  w = mutt_addr_copy_list(t, false);
91  w = expand_aliases_r(w, expn);
92  if (head)
93  last->next = w;
94  else
95  {
96  head = w;
97  last = w;
98  }
99  while (last && last->next)
100  last = last->next;
101  }
102  t = a;
103  a = a->next;
104  t->next = NULL;
105  mutt_addr_free(&t);
106  continue;
107  }
108  else
109  {
110  struct passwd *pw = getpwnam(a->mailbox);
111 
112  if (pw)
113  {
114  char namebuf[256];
115 
116  mutt_gecos_name(namebuf, sizeof(namebuf), pw);
117  mutt_str_replace(&a->personal, namebuf);
118  }
119  }
120  }
121 
122  if (head)
123  {
124  last->next = a;
125  last = last->next;
126  }
127  else
128  {
129  head = a;
130  last = a;
131  }
132  a = a->next;
133  last->next = NULL;
134  }
135 
136  if (C_UseDomain && (fqdn = mutt_fqdn(true)))
137  {
138  /* now qualify all local addresses */
139  mutt_addr_qualify(head, fqdn);
140  }
141 
142  return head;
143 }
struct Address * mutt_addr_copy_list(struct Address *addr, bool prune)
Copy a list of addresses.
Definition: address.c:750
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:279
WHERE bool C_UseDomain
Config: Qualify local addresses using this domain.
Definition: globals.h:257
static struct Address * expand_aliases_r(struct Address *a, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:61
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:456
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2453
void mutt_addr_qualify(struct Address *addr, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:674
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:363
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
void mutt_addr_free(struct Address **p)
Free a list of Addresses.
Definition: address.c:451
#define mutt_debug(LEVEL,...)
Definition: logging.h:80
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:618
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 169 of file alias.c.

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

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

189 {
191  return;
192 
193  char *s = mutt_str_strdup(buf);
194  if (!s)
195  return;
197  mutt_str_strfcpy(buf, s, buflen);
198  FREE(&s);
199 }
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:99
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:753
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 212 of file alias.c.

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

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

261 {
262  char buf[1024];
263 
264  snprintf(buf, sizeof(buf), "%s@%s", NONULL(u), NONULL(d));
265  if (mutt_str_strcasecmp(str, buf) == 0)
266  return true;
267 
268  return false;
269 }
#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:631

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

280 {
281  struct Alias *a = NULL;
282 
283  TAILQ_FOREACH(a, &Aliases, entries)
284  {
285  if (mutt_str_strcasecmp(s, a->name) == 0)
286  return a->addr;
287  }
288  return NULL;
289 }
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:631
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 298 of file alias.c.

299 {
300  struct Address *t = NULL;
301  struct ListHead expn; /* previously expanded aliases to avoid loops */
302 
303  STAILQ_INIT(&expn);
304  t = expand_aliases_r(a, &expn);
305  mutt_list_free(&expn);
306  return mutt_addrlist_dedupe(t);
307 }
An email address.
Definition: address.h:32
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:117
#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:61
struct Address * mutt_addrlist_dedupe(struct Address *addr)
Remove duplicate addresses.
Definition: address.c:1322

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

314 {
315  env->from = mutt_expand_aliases(env->from);
316  env->to = mutt_expand_aliases(env->to);
317  env->cc = mutt_expand_aliases(env->cc);
318  env->bcc = mutt_expand_aliases(env->bcc);
321 }
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:298
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 329 of file alias.c.

330 {
331  struct Address *addr = NULL;
332  const char *pfx = NULL;
333 
334  if (mutt_addr_is_user(env->from))
335  {
336  if (env->to && !mutt_is_mail_list(env->to))
337  {
338  pfx = "To";
339  addr = env->to;
340  }
341  else
342  {
343  pfx = "Cc";
344  addr = env->cc;
345  }
346  }
347  else if (env->reply_to && !mutt_is_mail_list(env->reply_to))
348  {
349  pfx = "Reply-To";
350  addr = env->reply_to;
351  }
352  else
353  {
354  addr = env->from;
355  pfx = "From";
356  }
357 
358  if (pfxp)
359  *pfxp = pfx;
360 
361  return addr;
362 }
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:101
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:677

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

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

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

539 {
540  if (!a || !a->mailbox)
541  return NULL;
542 
544 }
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:35
WHERE struct Hash * ReverseAliases
Hash table of aliases (email address -> alias)
Definition: globals.h:58

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

551 {
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 (struct Address *ap = t->addr; ap; ap = ap->next)
561  {
562  if (!ap->group && ap->mailbox)
563  mutt_hash_insert(ReverseAliases, ap->mailbox, ap);
564  }
565 }
An email address.
Definition: address.h:32
int mutt_addrlist_to_intl(struct Address *a, char **err)
Convert an Address list to Punycode.
Definition: address.c:1249
WHERE struct Hash * ReverseAliases
Hash table of aliases (email address -> alias)
Definition: globals.h:58
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:352
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  if (!t)
574  return;
575 
576  /* If the alias addresses were converted to local form, they won't
577  * match the hash entries. */
578  mutt_addrlist_to_intl(t->addr, NULL);
579 
580  for (struct Address *ap = t->addr; ap; ap = ap->next)
581  {
582  if (!ap->group && ap->mailbox)
583  mutt_hash_delete(ReverseAliases, ap->mailbox, ap);
584  }
585 }
void mutt_hash_delete(struct Hash *table, const char *strkey, const void *data)
Remove an element from a Hash table.
Definition: hash.c:444
An email address.
Definition: address.h:32
int mutt_addrlist_to_intl(struct Address *a, char **err)
Convert an Address list to Punycode.
Definition: address.c:1249
WHERE struct Hash * ReverseAliases
Hash table of aliases (email address -> alias)
Definition: globals.h:58
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 598 of file alias.c.

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

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

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

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

738 {
739  if (!p || !*p)
740  return;
741 
743  FREE(&(*p)->name);
744  mutt_addr_free(&(*p)->addr);
745  FREE(p);
746 }
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:451

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

753 {
754  struct Alias *a = NULL, *tmp = NULL;
755  TAILQ_FOREACH_SAFE(a, a_list, entries, tmp)
756  {
757  TAILQ_REMOVE(a_list, a, entries);
758  mutt_alias_free(&a);
759  }
760  TAILQ_INIT(a_list);
761 }
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:737

+ Here is the call graph for this function:

+ Here is the caller graph for this function: