NeoMutt  2020-11-20
Teaching an old dog new tricks
DOXYGEN
lib.h File Reference

Email Aliases. More...

#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "mutt_commands.h"
#include "sort.h"
#include "gui.h"
+ Include dependency graph for lib.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void alias_init (void)
 Set up the Alias globals. More...
 
void alias_shutdown (void)
 Clean up the Alias globals. More...
 
void alias_create (struct AddressList *al, const struct ConfigSubset *sub)
 Create a new Alias from an Address. More...
 
struct AddressList * alias_lookup (const char *name)
 Find an Alias. More...
 
bool mutt_addr_is_user (const struct Address *addr)
 Does the address belong to the user. More...
 
void mutt_expand_aliases_env (struct Envelope *env)
 Expand aliases in all the fields of an Envelope. More...
 
void mutt_expand_aliases (struct AddressList *al)
 Expand aliases in a List of Addresses. More...
 
struct AddressList * mutt_get_address (struct Envelope *env, const char **prefix)
 Get an Address from an Envelope. More...
 
enum CommandResult parse_alias (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse the 'alias' command - Implements Command::parse() More...
 
enum CommandResult parse_unalias (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse the 'unalias' command - Implements Command::parse() More...
 
int alias_complete (char *buf, size_t buflen, struct ConfigSubset *sub)
 alias completion routine More...
 
int query_complete (char *buf, size_t buflen, struct ConfigSubset *sub)
 Perform auto-complete using an Address Query. More...
 
void query_index (struct ConfigSubset *sub)
 Perform an Alias Query and display the results. More...
 
struct Addressalias_reverse_lookup (const struct Address *addr)
 Does the user have an alias for the given address. More...
 
bool config_init_alias (struct ConfigSet *cs)
 Register alias config variables - Implements module_init_config_t. More...
 
void alias_array_sort (struct AliasViewArray *ava, const struct ConfigSubset *sub)
 Sort and reindex an AliasViewArray. More...
 

Detailed Description

Email Aliases.

Authors
  • Richard Russon

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 lib.h.

Function Documentation

◆ alias_init()

void alias_init ( void  )

Set up the Alias globals.

Definition at line 653 of file alias.c.

654 {
656 }
void alias_reverse_init(void)
Set up the Reverse Alias Hash Table.
Definition: reverse.c:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alias_shutdown()

void alias_shutdown ( void  )

Clean up the Alias globals.

Definition at line 661 of file alias.c.

662 {
663  struct Alias *np = NULL;
664  TAILQ_FOREACH(np, &Aliases, entries)
665  {
667  }
670 }
A shortcut for an email address or addresses.
Definition: alias.h:33
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
void alias_reverse_shutdown(void)
Clear up the Reverse Alias Hash Table.
Definition: reverse.c:52
struct AliasList Aliases
List of all the user&#39;s email aliases.
Definition: alias.c:55
void aliaslist_free(struct AliasList *al)
Free a List of Aliases.
Definition: alias.c:639
void alias_reverse_delete(struct Alias *alias)
Remove an email address lookup for an Alias.
Definition: reverse.c:83
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alias_create()

void alias_create ( struct AddressList *  al,
const struct ConfigSubset sub 
)

Create a new Alias from an Address.

Parameters
alAddress to use
subConfig items

Definition at line 366 of file alias.c.

367 {
368  struct Address *addr = NULL;
369  char buf[1024], tmp[1024] = { 0 }, prompt[2048];
370  char *pc = NULL;
371  char *err = NULL;
372  char fixed[1024];
373 
374  if (al)
375  {
376  addr = TAILQ_FIRST(al);
377  if (addr && addr->mailbox)
378  {
379  mutt_str_copy(tmp, addr->mailbox, sizeof(tmp));
380  pc = strchr(tmp, '@');
381  if (pc)
382  *pc = '\0';
383  }
384  }
385 
386  /* Don't suggest a bad alias name in the event of a strange local part. */
387  check_alias_name(tmp, buf, sizeof(buf));
388 
389 retry_name:
390  /* L10N: prompt to add a new alias */
391  if ((mutt_get_field(_("Alias as: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0) ||
392  (buf[0] == '\0'))
393  {
394  return;
395  }
396 
397  /* check to see if the user already has an alias defined */
398  if (alias_lookup(buf))
399  {
400  mutt_error(_("You already have an alias defined with that name"));
401  return;
402  }
403 
404  if (check_alias_name(buf, fixed, sizeof(fixed)))
405  {
406  switch (mutt_yesorno(_("Warning: This alias name may not work. Fix it?"), MUTT_YES))
407  {
408  case MUTT_YES:
409  mutt_str_copy(buf, fixed, sizeof(buf));
410  goto retry_name;
411  case MUTT_ABORT:
412  return;
413  default:; // do nothing
414  }
415  }
416 
417  struct Alias *alias = alias_new();
418  alias->name = mutt_str_dup(buf);
419 
421 
422  if (addr && addr->mailbox)
423  mutt_str_copy(buf, addr->mailbox, sizeof(buf));
424  else
425  buf[0] = '\0';
426 
427  mutt_addrlist_to_intl(al, NULL);
428 
429  do
430  {
431  if ((mutt_get_field(_("Address: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0) ||
432  (buf[0] == '\0'))
433  {
434  alias_free(&alias);
435  return;
436  }
437 
438  mutt_addrlist_parse(&alias->addr, buf);
439  if (TAILQ_EMPTY(&alias->addr))
440  mutt_beep(false);
441  if (mutt_addrlist_to_intl(&alias->addr, &err))
442  {
443  mutt_error(_("Bad IDN: '%s'"), err);
444  FREE(&err);
445  continue;
446  }
447  } while (TAILQ_EMPTY(&alias->addr));
448 
449  if (addr && addr->personal && !mutt_is_mail_list(addr))
450  mutt_str_copy(buf, addr->personal, sizeof(buf));
451  else
452  buf[0] = '\0';
453 
454  if (mutt_get_field(_("Personal name: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0)
455  {
456  alias_free(&alias);
457  return;
458  }
459  mutt_str_replace(&TAILQ_FIRST(&alias->addr)->personal, buf);
460 
461  buf[0] = '\0';
462  if (mutt_get_field(_("Comment: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) == 0)
463  mutt_str_replace(&alias->comment, buf);
464 
465  buf[0] = '\0';
466  mutt_addrlist_write(&alias->addr, buf, sizeof(buf), true);
467  if (alias->comment)
468  {
469  snprintf(prompt, sizeof(prompt), "[%s = %s # %s] %s", alias->name, buf,
470  alias->comment, _("Accept?"));
471  }
472  else
473  {
474  snprintf(prompt, sizeof(prompt), "[%s = %s] %s", alias->name, buf, _("Accept?"));
475  }
476  if (mutt_yesorno(prompt, MUTT_YES) != MUTT_YES)
477  {
478  alias_free(&alias);
479  return;
480  }
481 
482  alias_reverse_add(alias);
483  TAILQ_INSERT_TAIL(&Aliases, alias, entries);
484 
485  const char *alias_file = cs_subset_string(sub, "alias_file");
486  mutt_str_copy(buf, NONULL(alias_file), sizeof(buf));
487 
488  if (mutt_get_field(_("Save to file: "), buf, sizeof(buf), MUTT_FILE | MUTT_CLEAR) != 0)
489  return;
490  mutt_expand_path(buf, sizeof(buf));
491  FILE *fp_alias = fopen(buf, "a+");
492  if (!fp_alias)
493  {
494  mutt_perror(buf);
495  return;
496  }
497 
498  /* terminate existing file with \n if necessary */
499  if (fseek(fp_alias, 0, SEEK_END))
500  goto fseek_err;
501  if (ftell(fp_alias) > 0)
502  {
503  if (fseek(fp_alias, -1, SEEK_CUR) < 0)
504  goto fseek_err;
505  if (fread(buf, 1, 1, fp_alias) != 1)
506  {
507  mutt_perror(_("Error reading alias file"));
508  mutt_file_fclose(&fp_alias);
509  return;
510  }
511  if (fseek(fp_alias, 0, SEEK_END) < 0)
512  goto fseek_err;
513  if (buf[0] != '\n')
514  fputc('\n', fp_alias);
515  }
516 
517  if (check_alias_name(alias->name, NULL, 0))
518  mutt_file_quote_filename(alias->name, buf, sizeof(buf));
519  else
520  mutt_str_copy(buf, alias->name, sizeof(buf));
521  recode_buf(buf, sizeof(buf));
522  fprintf(fp_alias, "alias %s ", buf);
523  buf[0] = '\0';
524  mutt_addrlist_write(&alias->addr, buf, sizeof(buf), false);
525  recode_buf(buf, sizeof(buf));
526  write_safe_address(fp_alias, buf);
527  if (alias->comment)
528  fprintf(fp_alias, " # %s", alias->comment);
529  fputc('\n', fp_alias);
530  if (mutt_file_fsync_close(&fp_alias) != 0)
531  mutt_perror(_("Trouble adding alias"));
532  else
533  mutt_message(_("Alias added"));
534 
535  return;
536 
537 fseek_err:
538  mutt_perror(_("Error seeking in alias file"));
539  mutt_file_fclose(&fp_alias);
540 }
A shortcut for an email address or addresses.
Definition: alias.h:33
char * name
Short name.
Definition: alias.h:35
#define NONULL(x)
Definition: string2.h:37
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:62
#define TAILQ_FIRST(head)
Definition: queue.h:716
#define mutt_perror(...)
Definition: logging.h:85
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:169
#define mutt_message(...)
Definition: logging.h:83
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1386
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list? - Implements addr_predicate_t.
Definition: maillist.c:45
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:91
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:99
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:128
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:379
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:276
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct Alias * alias_new(void)
Create a new Alias.
Definition: alias.c:608
void alias_reverse_add(struct Alias *alias)
Add an email address lookup for an Alias.
Definition: reverse.c:61
User aborted the question (with Ctrl-G)
Definition: quad.h:38
struct AliasList Aliases
List of all the user&#39;s email aliases.
Definition: alias.c:55
static int check_alias_name(const char *s, char *dest, size_t destlen)
Sanity-check an alias name.
Definition: alias.c:209
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:241
char * comment
Free-form comment string.
Definition: alias.h:37
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:802
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:793
void alias_free(struct Alias **ptr)
Free an Alias.
Definition: alias.c:619
#define MUTT_FILE
Do file completion.
Definition: mutt.h:58
static void write_safe_address(FILE *fp, char *s)
Defang malicious email addresses.
Definition: alias.c:81
char * personal
Real name of address.
Definition: address.h:36
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1304
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
#define TAILQ_EMPTY(head)
Definition: queue.h:714
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
size_t mutt_addrlist_write(const struct AddressList *al, char *buf, size_t buflen, bool display)
Write an Address to a buffer.
Definition: address.c:1150
static void recode_buf(char *buf, size_t buflen)
Convert some text between two character sets.
Definition: alias.c:185
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alias_lookup()

struct AddressList* alias_lookup ( const char *  name)

Find an Alias.

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

Definition at line 276 of file alias.c.

277 {
278  struct Alias *a = NULL;
279 
280  TAILQ_FOREACH(a, &Aliases, entries)
281  {
282  if (mutt_istr_equal(name, a->name))
283  return &a->addr;
284  }
285  return NULL;
286 }
A shortcut for an email address or addresses.
Definition: alias.h:33
char * name
Short name.
Definition: alias.h:35
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
struct AliasList Aliases
List of all the user&#39;s email aliases.
Definition: alias.c:55
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_addr_is_user()

bool mutt_addr_is_user ( const struct Address addr)

Does the address belong to the user.

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

Definition at line 547 of file alias.c.

548 {
549  if (!addr)
550  {
551  mutt_debug(LL_DEBUG5, "no, NULL address\n");
552  return false;
553  }
554  if (!addr->mailbox)
555  {
556  mutt_debug(LL_DEBUG5, "no, no mailbox\n");
557  return false;
558  }
559 
560  if (mutt_istr_equal(addr->mailbox, Username))
561  {
562  mutt_debug(LL_DEBUG5, "#1 yes, %s = %s\n", addr->mailbox, Username);
563  return true;
564  }
566  {
567  mutt_debug(LL_DEBUG5, "#2 yes, %s = %s @ %s\n", addr->mailbox, Username, ShortHostname);
568  return true;
569  }
570  const char *fqdn = mutt_fqdn(false, NeoMutt->sub);
571  if (string_is_address(addr->mailbox, Username, fqdn))
572  {
573  mutt_debug(LL_DEBUG5, "#3 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
574  return true;
575  }
576  fqdn = mutt_fqdn(true, NeoMutt->sub);
577  if (string_is_address(addr->mailbox, Username, fqdn))
578  {
579  mutt_debug(LL_DEBUG5, "#4 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
580  return true;
581  }
582 
583  if (C_From && mutt_istr_equal(C_From->mailbox, addr->mailbox))
584  {
585  mutt_debug(LL_DEBUG5, "#5 yes, %s = %s\n", addr->mailbox, C_From->mailbox);
586  return true;
587  }
588 
589  if (mutt_regexlist_match(&Alternates, addr->mailbox))
590  {
591  mutt_debug(LL_DEBUG5, "yes, %s matched by alternates\n", addr->mailbox);
592  if (mutt_regexlist_match(&UnAlternates, addr->mailbox))
593  mutt_debug(LL_DEBUG5, "but, %s matched by unalternates\n", addr->mailbox);
594  else
595  return true;
596  }
597 
598  mutt_debug(LL_DEBUG5, "no, all failed\n");
599  return false;
600 }
#define NONULL(x)
Definition: string2.h:37
char * mailbox
Mailbox and host address.
Definition: address.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:36
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:52
bool mutt_regexlist_match(struct RegexList *rl, const char *str)
Does a string match any Regex in the list?
Definition: regex.c:190
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:50
WHERE struct Address * C_From
Config: Default &#39;From&#39; address to use, if isn&#39;t otherwise set.
Definition: mutt_globals.h:81
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:1181
static bool string_is_address(const char *str, const char *user, const char *domain)
Does an email address match a user and domain?
Definition: alias.c:257
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Log at debug level 5.
Definition: logging.h:44
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_expand_aliases_env()

void mutt_expand_aliases_env ( struct Envelope env)

Expand aliases in all the fields of an Envelope.

Parameters
envEnvelope to expand

Definition at line 308 of file alias.c.

309 {
310  mutt_expand_aliases(&env->from);
311  mutt_expand_aliases(&env->to);
312  mutt_expand_aliases(&env->cc);
313  mutt_expand_aliases(&env->bcc);
316 }
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:294
struct AddressList mail_followup_to
Email&#39;s &#39;mail-followup-to&#39;.
Definition: envelope.h:63
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:62
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:60
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_expand_aliases()

void mutt_expand_aliases ( struct AddressList *  al)

Expand aliases in a List of Addresses.

Parameters
alAddressList

Duplicate addresses are dropped

Definition at line 294 of file alias.c.

295 {
296  struct ListHead expn; /* previously expanded aliases to avoid loops */
297 
298  STAILQ_INIT(&expn);
299  expand_aliases_r(al, &expn);
300  mutt_list_free(&expn);
302 }
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1405
#define STAILQ_INIT(head)
Definition: queue.h:369
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:99
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_get_address()

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

Get an Address from an Envelope.

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

Definition at line 326 of file alias.c.

327 {
328  struct AddressList *al = NULL;
329  const char *pfx = NULL;
330 
331  if (mutt_addr_is_user(TAILQ_FIRST(&env->from)))
332  {
333  if (!TAILQ_EMPTY(&env->to) && !mutt_is_mail_list(TAILQ_FIRST(&env->to)))
334  {
335  pfx = "To";
336  al = &env->to;
337  }
338  else
339  {
340  pfx = "Cc";
341  al = &env->cc;
342  }
343  }
344  else if (!TAILQ_EMPTY(&env->reply_to) && !mutt_is_mail_list(TAILQ_FIRST(&env->reply_to)))
345  {
346  pfx = "Reply-To";
347  al = &env->reply_to;
348  }
349  else
350  {
351  al = &env->from;
352  pfx = "From";
353  }
354 
355  if (prefix)
356  *prefix = pfx;
357 
358  return al;
359 }
#define TAILQ_FIRST(head)
Definition: queue.h:716
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:62
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list? - Implements addr_predicate_t.
Definition: maillist.c:45
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:547
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
#define TAILQ_EMPTY(head)
Definition: queue.h:714
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_alias()

enum CommandResult parse_alias ( struct Buffer buf,
struct Buffer s,
intptr_t  data,
struct Buffer err 
)

Parse the 'alias' command - Implements Command::parse()

e.g. "alias jim James Smith <js@example.com> # Pointy-haired boss"

Definition at line 49 of file commands.c.

51 {
52  struct Alias *tmp = NULL;
53  struct GroupList gl = STAILQ_HEAD_INITIALIZER(gl);
54  enum NotifyAlias event;
55 
56  if (!MoreArgs(s))
57  {
58  mutt_buffer_strcpy(err, _("alias: no address"));
59  return MUTT_CMD_WARNING;
60  }
61 
62  /* name */
64  mutt_debug(LL_DEBUG5, "First token is '%s'\n", buf->data);
65  if (parse_grouplist(&gl, buf, s, err) == -1)
66  {
67  return MUTT_CMD_ERROR;
68  }
69  char *name = mutt_str_dup(buf->data);
70 
71  /* address list */
73  mutt_debug(LL_DEBUG5, "Second token is '%s'\n", buf->data);
74  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
75  int parsed = mutt_addrlist_parse2(&al, buf->data);
76  if (parsed == 0)
77  {
78  mutt_buffer_printf(err, _("Warning: Bad address '%s' in alias '%s'"), buf->data, name);
79  FREE(&name);
80  goto bail;
81  }
82 
83  /* IDN */
84  char *estr = NULL;
85  if (mutt_addrlist_to_intl(&al, &estr))
86  {
87  mutt_buffer_printf(err, _("Warning: Bad IDN '%s' in alias '%s'"), estr, name);
88  FREE(&name);
89  FREE(&estr);
90  goto bail;
91  }
92 
93  /* check to see if an alias with this name already exists */
94  TAILQ_FOREACH(tmp, &Aliases, entries)
95  {
96  if (mutt_istr_equal(tmp->name, name))
97  break;
98  }
99 
100  if (tmp)
101  {
102  FREE(&name);
104  /* override the previous value */
105  mutt_addrlist_clear(&tmp->addr);
106  FREE(&tmp->comment);
107  event = NT_ALIAS_CHANGED;
108  }
109  else
110  {
111  /* create a new alias */
112  tmp = alias_new();
113  tmp->name = name;
114  TAILQ_INSERT_TAIL(&Aliases, tmp, entries);
115  event = NT_ALIAS_NEW;
116  }
117  tmp->addr = al;
118 
119  mutt_grouplist_add_addrlist(&gl, &tmp->addr);
120 
121  if (C_DebugLevel > LL_DEBUG4)
122  {
123  /* A group is terminated with an empty address, so check a->mailbox */
124  struct Address *a = NULL;
125  TAILQ_FOREACH(a, &tmp->addr, entries)
126  {
127  if (!a->mailbox)
128  break;
129 
130  if (a->group)
131  mutt_debug(LL_DEBUG5, " Group %s\n", a->mailbox);
132  else
133  mutt_debug(LL_DEBUG5, " %s\n", a->mailbox);
134  }
135  }
137  if (!MoreArgs(s) && (s->dptr[0] == '#'))
138  {
139  char *comment = s->dptr + 1;
140  SKIPWS(comment);
141  tmp->comment = mutt_str_dup(comment);
142  }
143 
144  alias_reverse_add(tmp);
145 
146  struct EventAlias ea = { tmp };
147  notify_send(NeoMutt->notify, NT_ALIAS, event, &ea);
148 
149  return MUTT_CMD_SUCCESS;
150 
151 bail:
153  return MUTT_CMD_ERROR;
154 }
A shortcut for an email address or addresses.
Definition: alias.h:33
int parse_grouplist(struct GroupList *gl, struct Buffer *buf, struct Buffer *s, struct Buffer *err)
Parse a group context.
Log at debug level 4.
Definition: logging.h:43
char * name
Short name.
Definition: alias.h:35
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
Error: Can&#39;t help the user.
Definition: mutt_commands.h:36
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1468
Alias has changed, NotifyAlias, EventAlias.
Definition: notify_type.h:44
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
An alias-change event.
Definition: alias.h:59
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
void mutt_grouplist_add_addrlist(struct GroupList *gl, struct AddressList *al)
Add Address list to a GroupList.
Definition: group.c:226
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
int mutt_addrlist_parse2(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:616
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define MoreArgs(buf)
Definition: buffer.h:43
An Alias has been changed.
Definition: alias.h:52
#define SKIPWS(ch)
Definition: string2.h:46
struct Alias * alias_new(void)
Create a new Alias.
Definition: alias.c:608
void alias_reverse_add(struct Alias *alias)
Add an email address lookup for an Alias.
Definition: reverse.c:61
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
#define MUTT_TOKEN_QUOTE
Don&#39;t interpret quotes.
Definition: mutt.h:74
struct AliasList Aliases
List of all the user&#39;s email aliases.
Definition: alias.c:55
short C_DebugLevel
Config: Logging level for debug logs.
Definition: mutt_logging.c:48
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:394
A new Alias has been created.
Definition: alias.h:51
char * dptr
Current read/write position.
Definition: buffer.h:36
#define MUTT_TOKEN_SPACE
Don&#39;t treat whitespace as a term.
Definition: mutt.h:73
char * data
Pointer to data.
Definition: buffer.h:35
char * comment
Free-form comment string.
Definition: alias.h:37
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:802
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
#define MUTT_TOKEN_SEMICOLON
Don&#39;t treat ; as special.
Definition: mutt.h:77
Success: Command worked.
Definition: mutt_commands.h:38
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1304
bool group
Group mailbox?
Definition: address.h:38
Warning: Help given to the user.
Definition: mutt_commands.h:37
NotifyAlias
Alias notification types.
Definition: alias.h:49
void mutt_grouplist_destroy(struct GroupList *gl)
Free a GroupList.
Definition: group.c:157
#define FREE(x)
Definition: memory.h:40
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
Log at debug level 5.
Definition: logging.h:44
void alias_reverse_delete(struct Alias *alias)
Remove an email address lookup for an Alias.
Definition: reverse.c:83
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:70
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:152
+ Here is the call graph for this function:

◆ parse_unalias()

enum CommandResult parse_unalias ( struct Buffer buf,
struct Buffer s,
intptr_t  data,
struct Buffer err 
)

Parse the 'unalias' command - Implements Command::parse()

Definition at line 159 of file commands.c.

161 {
162  do
163  {
165 
166  struct Alias *np = NULL;
167  if (mutt_str_equal("*", buf->data))
168  {
169  TAILQ_FOREACH(np, &Aliases, entries)
170  {
172  }
173 
175  return MUTT_CMD_SUCCESS;
176  }
177 
178  TAILQ_FOREACH(np, &Aliases, entries)
179  {
180  if (!mutt_istr_equal(buf->data, np->name))
181  continue;
182 
183  TAILQ_REMOVE(&Aliases, np, entries);
185  alias_free(&np);
186  break;
187  }
188  } while (MoreArgs(s));
189  return MUTT_CMD_SUCCESS;
190 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
A shortcut for an email address or addresses.
Definition: alias.h:33
char * name
Short name.
Definition: alias.h:35
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
#define MoreArgs(buf)
Definition: buffer.h:43
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:834
struct AliasList Aliases
List of all the user&#39;s email aliases.
Definition: alias.c:55
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:394
char * data
Pointer to data.
Definition: buffer.h:35
void alias_free(struct Alias **ptr)
Free an Alias.
Definition: alias.c:619
void aliaslist_free(struct AliasList *al)
Free a List of Aliases.
Definition: alias.c:639
Success: Command worked.
Definition: mutt_commands.h:38
void alias_reverse_delete(struct Alias *alias)
Remove an email address lookup for an Alias.
Definition: reverse.c:83
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:70
+ Here is the call graph for this function:

◆ alias_complete()

int alias_complete ( char *  buf,
size_t  buflen,
struct ConfigSubset sub 
)

alias completion routine

Parameters
bufPartial Alias to complete
buflenLength of buffer
subConfig items
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 375 of file dlgalias.c.

376 {
377  struct Alias *np = NULL;
378  char bestname[8192] = { 0 };
379 
380  struct AliasMenuData mdata = { NULL, NULL, ARRAY_HEAD_INITIALIZER, sub };
381  mdata.str = mutt_str_dup(buf);
382 
383  if (buf[0] != '\0')
384  {
385  TAILQ_FOREACH(np, &Aliases, entries)
386  {
387  if (np->name && mutt_strn_equal(np->name, buf, strlen(buf)))
388  {
389  if (bestname[0] == '\0') /* init */
390  {
391  mutt_str_copy(bestname, np->name,
392  MIN(mutt_str_len(np->name) + 1, sizeof(bestname)));
393  }
394  else
395  {
396  int i;
397  for (i = 0; np->name[i] && (np->name[i] == bestname[i]); i++)
398  ; // do nothing
399 
400  bestname[i] = '\0';
401  }
402  }
403  }
404 
405  if (bestname[0] != '\0')
406  {
407  /* fake the pattern for menu title */
408  char *mtitle = NULL;
409  mutt_str_asprintf(&mtitle, "~f ^%s", buf);
410  FREE(&mdata.str);
411  mdata.str = mtitle;
412 
413  if (!mutt_str_equal(bestname, buf))
414  {
415  /* we are adding something to the completion */
416  mutt_str_copy(buf, bestname, mutt_str_len(bestname) + 1);
417  FREE(&mdata.str);
418  return 1;
419  }
420 
421  /* build alias list and show it */
422  TAILQ_FOREACH(np, &Aliases, entries)
423  {
424  int aasize = alias_array_alias_add(&mdata.ava, np);
425 
426  struct AliasView *av = ARRAY_GET(&mdata.ava, aasize - 1);
427 
428  if (np->name && !mutt_strn_equal(np->name, buf, strlen(buf)))
429  {
430  av->is_visible = false;
431  }
432  }
433  }
434  }
435 
436  if (ARRAY_EMPTY(&mdata.ava))
437  {
438  TAILQ_FOREACH(np, &Aliases, entries)
439  {
440  alias_array_alias_add(&mdata.ava, np);
441  }
442 
443  mutt_pattern_alias_func(MUTT_LIMIT, NULL, _("Aliases"), &mdata, NULL);
444  }
445 
446  alias_array_sort(&mdata.ava, mdata.sub);
447 
448  bestname[0] = '\0';
449  dlg_select_alias(bestname, sizeof(bestname), &mdata);
450  if (bestname[0] != '\0')
451  mutt_str_copy(buf, bestname, buflen);
452 
453  struct AliasView *avp = NULL;
454  ARRAY_FOREACH(avp, &mdata.ava)
455  {
456  if (!avp->is_deleted)
457  continue;
458 
459  TAILQ_REMOVE(&Aliases, avp->alias, entries);
460  alias_free(&avp->alias);
461  }
462 
463  ARRAY_FREE(&mdata.ava);
464  FREE(&mdata.str);
465 
466  return 0;
467 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
A shortcut for an email address or addresses.
Definition: alias.h:33
char * name
Short name.
Definition: alias.h:35
static void dlg_select_alias(char *buf, size_t buflen, struct AliasMenuData *mdata)
Display a menu of Aliases.
Definition: dlgalias.c:194
#define MIN(a, b)
Definition: memory.h:31
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
AliasMenuData - AliasView array wrapper with Pattern information.
Definition: gui.h:53
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:198
Messages in limited view.
Definition: mutt.h:105
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:206
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:105
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
GUI data wrapping an Alias.
Definition: gui.h:36
int alias_array_alias_add(struct AliasViewArray *ava, struct Alias *alias)
Add an Alias to the AliasViewArray.
Definition: array.c:45
void alias_array_sort(struct AliasViewArray *ava, const struct ConfigSubset *sub)
Sort and reindex an AliasViewArray.
Definition: sort.c:158
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition: array.h:54
char * str
String representing the limit being used.
Definition: gui.h:55
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:834
bool is_visible
Is visible?
Definition: gui.h:44
struct AliasList Aliases
List of all the user&#39;s email aliases.
Definition: alias.c:55
struct Alias * alias
Alias.
Definition: gui.h:45
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition: array.h:70
void alias_free(struct Alias **ptr)
Free an Alias.
Definition: alias.c:619
bool mutt_strn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:593
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
struct ConfigSubset * sub
Config items.
Definition: gui.h:58
#define FREE(x)
Definition: memory.h:40
struct AliasViewArray ava
Array of AliasView.
Definition: gui.h:57
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:1095
int mutt_pattern_alias_func(int op, char *prompt, char *title, struct AliasMenuData *mdata, struct Menu *menu)
Perform some Pattern matching for Alias.
Definition: pattern.c:236
bool is_deleted
Is it deleted?
Definition: gui.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_complete()

int query_complete ( char *  buf,
size_t  buflen,
struct ConfigSubset sub 
)

Perform auto-complete using an Address Query.

Parameters
bufBuffer for completion
buflenLength of buffer
subConfig item
Return values
0Always

Definition at line 605 of file dlgquery.c.

606 {
607  const char *query_command = cs_subset_string(sub, "query_command");
608  if (!query_command)
609  {
610  mutt_warning(_("Query command not defined"));
611  return 0;
612  }
613 
614  struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
615  query_run(buf, true, &al, sub);
616  if (TAILQ_EMPTY(&al))
617  return 0;
618 
619  struct Alias *a_first = TAILQ_FIRST(&al);
620  if (!TAILQ_NEXT(a_first, entries)) // only one response?
621  {
622  struct AddressList addr = TAILQ_HEAD_INITIALIZER(addr);
623  if (alias_to_addrlist(&addr, a_first))
624  {
625  mutt_addrlist_to_local(&addr);
626  buf[0] = '\0';
627  mutt_addrlist_write(&addr, buf, buflen, false);
628  mutt_addrlist_clear(&addr);
629  aliaslist_free(&al);
631  }
632  return 0;
633  }
634 
635  /* multiple results, choose from query menu */
636  dlg_select_query(buf, buflen, &al, true, sub);
637  aliaslist_free(&al);
638  return 0;
639 }
static bool alias_to_addrlist(struct AddressList *al, struct Alias *alias)
Turn an Alias into an AddressList.
Definition: dlgquery.c:76
A shortcut for an email address or addresses.
Definition: alias.h:33
#define mutt_warning(...)
Definition: logging.h:82
#define TAILQ_FIRST(head)
Definition: queue.h:716
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1386
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1468
#define _(a)
Definition: message.h:28
static void dlg_select_query(char *buf, size_t buflen, struct AliasList *all, bool retbuf, struct ConfigSubset *sub)
Get the user to enter an Address Query.
Definition: dlgquery.c:310
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
static int query_run(char *s, bool verbose, struct AliasList *al, const struct ConfigSubset *sub)
Run an external program to find Addresses.
Definition: dlgquery.c:236
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:241
void aliaslist_free(struct AliasList *al)
Free a List of Aliases.
Definition: alias.c:639
#define TAILQ_NEXT(elm, field)
Definition: queue.h:825
#define TAILQ_EMPTY(head)
Definition: queue.h:714
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
size_t mutt_addrlist_write(const struct AddressList *al, char *buf, size_t buflen, bool display)
Write an Address to a buffer.
Definition: address.c:1150
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_index()

void query_index ( struct ConfigSubset sub)

Perform an Alias Query and display the results.

Parameters
subConfig item

Definition at line 645 of file dlgquery.c.

646 {
647  const char *query_command = cs_subset_string(sub, "query_command");
648  if (!query_command)
649  {
650  mutt_warning(_("Query command not defined"));
651  return;
652  }
653 
654  char buf[256] = { 0 };
655  if ((mutt_get_field(_("Query: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS) != 0) ||
656  (buf[0] == '\0'))
657  {
658  return;
659  }
660 
661  struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
662  query_run(buf, false, &al, sub);
663  if (TAILQ_EMPTY(&al))
664  return;
665 
666  dlg_select_query(buf, sizeof(buf), &al, false, sub);
667  aliaslist_free(&al);
668 }
#define mutt_warning(...)
Definition: logging.h:82
#define _(a)
Definition: message.h:28
static void dlg_select_query(char *buf, size_t buflen, struct AliasList *all, bool retbuf, struct ConfigSubset *sub)
Get the user to enter an Address Query.
Definition: dlgquery.c:310
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:91
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
static int query_run(char *s, bool verbose, struct AliasList *al, const struct ConfigSubset *sub)
Run an external program to find Addresses.
Definition: dlgquery.c:236
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:241
void aliaslist_free(struct AliasList *al)
Free a List of Aliases.
Definition: alias.c:639
#define TAILQ_EMPTY(head)
Definition: queue.h:714
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alias_reverse_lookup()

struct Address* alias_reverse_lookup ( const struct Address addr)

Does the user have an alias for the given address.

Parameters
addrAddress to lookup
Return values
ptrMatching Address

Definition at line 105 of file reverse.c.

106 {
107  if (!addr || !addr->mailbox)
108  return NULL;
109 
110  return mutt_hash_find(ReverseAliases, addr->mailbox);
111 }
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
Definition: hash.c:354
char * mailbox
Mailbox and host address.
Definition: address.h:37
static struct HashTable * ReverseAliases
Hash Table of aliases (email address -> alias)
Definition: reverse.c:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ config_init_alias()

bool config_init_alias ( struct ConfigSet cs)

Register alias config variables - Implements module_init_config_t.

Definition at line 69 of file config.c.

70 {
72 }
#define DT_NO_VARIABLE
Config item doesn&#39;t have a backing global variable.
Definition: types.h:84
struct ConfigDef AliasVars[]
Definition: config.c:45
bool cs_register_variables(const struct ConfigSet *cs, struct ConfigDef vars[], int flags)
Register a set of config items.
Definition: set.c:286
+ Here is the call graph for this function:

◆ alias_array_sort()

void alias_array_sort ( struct AliasViewArray *  ava,
const struct ConfigSubset sub 
)

Sort and reindex an AliasViewArray.

Parameters
avaArray of Aliases
subConfig items

Definition at line 158 of file sort.c.

159 {
160  if (!ava || ARRAY_EMPTY(ava))
161  return;
162 
163  sort_alias = cs_subset_sort(sub, "sort_alias");
165 
166  struct AliasView *avp = NULL;
167  ARRAY_FOREACH(avp, ava)
168  {
169  avp->num = ARRAY_FOREACH_IDX;
170  }
171 }
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:206
GUI data wrapping an Alias.
Definition: gui.h:36
static short sort_alias
Definition: sort.c:42
static sort_t alias_get_sort_function(short sort)
Sorting function decision logic.
Definition: sort.c:138
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:219
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition: array.h:70
#define ARRAY_SORT(head, fn)
Sort an array.
Definition: array.h:271
int num
Index number in list.
Definition: gui.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function: