NeoMutt  2018-07-16 +952-a2da0a
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(1, "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[STRING];
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 (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:277
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:460
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2425
char * personal
real name of address
Definition: address.h:34
char * data
Definition: list.h:35
#define STRING
Definition: string2.h:35
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:355
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
#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
WHERE bool UseDomain
Config: Qualify local addresses using this domain.
Definition: globals.h:261
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:612
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 {
189  if (!ConfigCharset || !*ConfigCharset || !Charset)
190  return;
191 
192  char *s = mutt_str_strdup(buf);
193  if (!s)
194  return;
195  if (mutt_ch_convert_string(&s, Charset, ConfigCharset, 0) == 0)
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:715
char * Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:52
WHERE char * ConfigCharset
Config: Character set that the config files are in.
Definition: globals.h:106
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:742
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
#define FREE(x)
Definition: memory.h:46

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

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

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

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

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

297 {
298  struct Address *t = NULL;
299  struct ListHead expn; /* previously expanded aliases to avoid loops */
300 
301  STAILQ_INIT(&expn);
302  t = expand_aliases_r(a, &expn);
303  mutt_list_free(&expn);
304  return mutt_addrlist_dedupe(t);
305 }
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 311 of file alias.c.

312 {
313  env->from = mutt_expand_aliases(env->from);
314  env->to = mutt_expand_aliases(env->to);
315  env->cc = mutt_expand_aliases(env->cc);
316  env->bcc = mutt_expand_aliases(env->bcc);
319 }
struct Address * to
Definition: envelope.h:36
struct Address * reply_to
Definition: envelope.h:40
struct Address * mail_followup_to
Definition: envelope.h:41
struct Address * from
Definition: envelope.h:35
struct Address * bcc
Definition: envelope.h:38
struct Address * mutt_expand_aliases(struct Address *a)
Expand aliases in a List of Addresses.
Definition: alias.c:296
struct Address * cc
Definition: envelope.h:37

+ 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
envEnvelope to examine
pfxpPrefix for the Address, e.g. "To:"
Return values
ptrAddress in the Envelope

Definition at line 327 of file alias.c.

328 {
329  struct Address *addr = NULL;
330  const char *pfx = NULL;
331 
332  if (mutt_addr_is_user(env->from))
333  {
334  if (env->to && !mutt_is_mail_list(env->to))
335  {
336  pfx = "To";
337  addr = env->to;
338  }
339  else
340  {
341  pfx = "Cc";
342  addr = env->cc;
343  }
344  }
345  else if (env->reply_to && !mutt_is_mail_list(env->reply_to))
346  {
347  pfx = "Reply-To";
348  addr = env->reply_to;
349  }
350  else
351  {
352  addr = env->from;
353  pfx = "From";
354  }
355 
356  if (pfxp)
357  *pfxp = pfx;
358 
359  return addr;
360 }
struct Address * to
Definition: envelope.h:36
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:98
struct Address * reply_to
Definition: envelope.h:40
struct Address * from
Definition: envelope.h:35
struct Address * cc
Definition: envelope.h:37
bool mutt_addr_is_user(struct Address *addr)
Does the address belong to the user.
Definition: alias.c:676

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_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 367 of file alias.c.

368 {
369  struct Alias *new = NULL;
370  char buf[LONG_STRING], tmp[LONG_STRING], prompt[SHORT_STRING], *pc = NULL;
371  char *err = NULL;
372  char fixed[LONG_STRING];
373  FILE *rc = NULL;
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  }
420  }
421 
422  new = mutt_mem_calloc(1, sizeof(struct Alias));
423  new->name = mutt_str_strdup(buf);
424 
426 
427  if (addr && addr->mailbox)
428  mutt_str_strfcpy(buf, addr->mailbox, sizeof(buf));
429  else
430  buf[0] = '\0';
431 
432  mutt_addrlist_to_intl(addr, NULL);
433 
434  do
435  {
436  if (mutt_get_field(_("Address: "), buf, sizeof(buf), 0) != 0 || !buf[0])
437  {
438  mutt_alias_free(&new);
439  return;
440  }
441 
442  new->addr = mutt_addr_parse_list(new->addr, buf);
443  if (!new->addr)
444  BEEP();
445  if (mutt_addrlist_to_intl(new->addr, &err))
446  {
447  mutt_error(_("Bad IDN: '%s'"), err);
448  FREE(&err);
449  continue;
450  }
451  } while (!new->addr);
452 
453  if (addr && addr->personal && !mutt_is_mail_list(addr))
454  mutt_str_strfcpy(buf, addr->personal, sizeof(buf));
455  else
456  buf[0] = '\0';
457 
458  if (mutt_get_field(_("Personal name: "), buf, sizeof(buf), 0) != 0)
459  {
460  mutt_alias_free(&new);
461  return;
462  }
463  mutt_str_replace(&new->addr->personal, buf);
464 
465  buf[0] = '\0';
466  mutt_addr_write(buf, sizeof(buf), new->addr, true);
467  snprintf(prompt, sizeof(prompt), _("[%s = %s] Accept?"), new->name, buf);
468  if (mutt_yesorno(prompt, MUTT_YES) != MUTT_YES)
469  {
470  mutt_alias_free(&new);
471  return;
472  }
473 
475 
476  TAILQ_INSERT_TAIL(&Aliases, new, entries);
477 
478  mutt_str_strfcpy(buf, AliasFile, sizeof(buf));
479  if (mutt_get_field(_("Save to file: "), buf, sizeof(buf), MUTT_FILE) != 0)
480  return;
481  mutt_expand_path(buf, sizeof(buf));
482  rc = fopen(buf, "a+");
483  if (rc)
484  {
485  /* terminate existing file with \n if necessary */
486  if (fseek(rc, 0, SEEK_END))
487  goto fseek_err;
488  if (ftell(rc) > 0)
489  {
490  if (fseek(rc, -1, SEEK_CUR) < 0)
491  goto fseek_err;
492  if (fread(buf, 1, 1, rc) != 1)
493  {
494  mutt_perror(_("Error reading alias file"));
495  mutt_file_fclose(&rc);
496  return;
497  }
498  if (fseek(rc, 0, SEEK_END) < 0)
499  goto fseek_err;
500  if (buf[0] != '\n')
501  fputc('\n', rc);
502  }
503 
504  if (check_alias_name(new->name, NULL, 0))
505  mutt_file_quote_filename(new->name, buf, sizeof(buf));
506  else
507  mutt_str_strfcpy(buf, new->name, sizeof(buf));
508  recode_buf(buf, sizeof(buf));
509  fprintf(rc, "alias %s ", buf);
510  buf[0] = '\0';
511  mutt_addr_write(buf, sizeof(buf), new->addr, false);
512  recode_buf(buf, sizeof(buf));
513  write_safe_address(rc, buf);
514  fputc('\n', rc);
515  if (mutt_file_fsync_close(&rc) != 0)
516  mutt_perror(_("Trouble adding alias"));
517  else
518  mutt_message(_("Alias added"));
519  }
520  else
521  mutt_perror(buf);
522 
523  return;
524 
525 fseek_err:
526  mutt_perror(_("Error seeking in alias file"));
527  mutt_file_fclose(&rc);
528 }
A shortcut for an email address.
Definition: alias.h:36
int mutt_file_fsync_close(FILE **f)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:166
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
#define SHORT_STRING
Definition: string2.h:34
#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:327
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
int mutt_yesorno(const char *msg, int def)
Ask the user a Yes/No question.
Definition: curs_lib.c:330
#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:277
#define LONG_STRING
Definition: string2.h:36
bool mutt_is_mail_list(struct Address *addr)
Is this the email address of a mailing list?
Definition: hdrline.c:98
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
int mutt_addrlist_to_local(struct Address *a)
Convert an Address list from Punycode.
Definition: address.c:1249
WHERE char * AliasFile
Config: Save new aliases to this file.
Definition: globals.h:102
#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:742
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
#define mutt_get_field(A, B, C, D)
Definition: curs_lib.h:78
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:460
#define MUTT_FILE
do file completion
Definition: mutt.h:59
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:384
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#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:547
void mutt_alias_free(struct Alias **p)
Free an Alias.
Definition: alias.c:738
#define FREE(x)
Definition: memory.h:46
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:749
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 535 of file alias.c.

536 {
537  if (!a || !a->mailbox)
538  return NULL;
539 
541 }
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:374
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 547 of file alias.c.

548 {
549  struct Address *ap = NULL;
550  if (!t)
551  return;
552 
553  /* Note that the address mailbox should be converted to intl form
554  * before using as a key in the hash. This is currently done
555  * by all callers, but added here mostly as documentation. */
556  mutt_addrlist_to_intl(t->addr, NULL);
557 
558  for (ap = t->addr; ap; ap = ap->next)
559  {
560  if (!ap->group && ap->mailbox)
562  }
563 }
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:349
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 569 of file alias.c.

570 {
571  struct Address *ap = NULL;
572  if (!t)
573  return;
574 
575  /* If the alias addresses were converted to local form, they won't
576  * match the hash entries. */
577  mutt_addrlist_to_intl(t->addr, NULL);
578 
579  for (ap = t->addr; ap; ap = ap->next)
580  {
581  if (!ap->group && ap->mailbox)
583  }
584 }
void mutt_hash_delete(struct Hash *table, const char *strkey, const void *data)
Remove an element from a Hash table.
Definition: hash.c:434
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 597 of file alias.c.

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

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

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

Definition at line 738 of file alias.c.

739 {
740  if (!p || !*p)
741  return;
742 
744  FREE(&(*p)->name);
745  mutt_addr_free(&(*p)->addr);
746  FREE(p);
747 }
void mutt_alias_delete_reverse(struct Alias *t)
Remove an email address lookup for an Alias.
Definition: alias.c:569
#define FREE(x)
Definition: memory.h:46
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 753 of file alias.c.

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function: