NeoMutt  2021-02-05-666-ge300cd
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 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() -e.g. 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...
 
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 664 of file alias.c.

665 {
667 }
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 672 of file alias.c.

673 {
674  struct Alias *np = NULL;
675  TAILQ_FOREACH(np, &Aliases, entries)
676  {
678  }
681 }
A shortcut for an email address or addresses.
Definition: alias.h:33
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
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:57
void aliaslist_free(struct AliasList *al)
Free a List of Aliases.
Definition: alias.c:650
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 372 of file alias.c.

373 {
374  struct Address *addr = NULL;
375  char buf[1024], tmp[1024] = { 0 }, prompt[2048];
376  char *pc = NULL;
377  char *err = NULL;
378  char fixed[1024];
379 
380  if (al)
381  {
382  addr = TAILQ_FIRST(al);
383  if (addr && addr->mailbox)
384  {
385  mutt_str_copy(tmp, addr->mailbox, sizeof(tmp));
386  pc = strchr(tmp, '@');
387  if (pc)
388  *pc = '\0';
389  }
390  }
391 
392  /* Don't suggest a bad alias name in the event of a strange local part. */
393  check_alias_name(tmp, buf, sizeof(buf));
394 
395 retry_name:
396  /* L10N: prompt to add a new alias */
397  if ((mutt_get_field(_("Alias as: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS,
398  false, NULL, NULL) != 0) ||
399  (buf[0] == '\0'))
400  {
401  return;
402  }
403 
404  /* check to see if the user already has an alias defined */
405  if (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_copy(buf, fixed, sizeof(buf));
417  goto retry_name;
418  case MUTT_ABORT:
419  return;
420  default:; // do nothing
421  }
422  }
423 
424  struct Alias *alias = alias_new();
425  alias->name = mutt_str_dup(buf);
426 
428 
429  if (addr && addr->mailbox)
430  mutt_str_copy(buf, addr->mailbox, sizeof(buf));
431  else
432  buf[0] = '\0';
433 
434  mutt_addrlist_to_intl(al, NULL);
435 
436  do
437  {
438  if ((mutt_get_field(_("Address: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS,
439  false, NULL, NULL) != 0) ||
440  (buf[0] == '\0'))
441  {
442  alias_free(&alias);
443  return;
444  }
445 
446  mutt_addrlist_parse(&alias->addr, buf);
447  if (TAILQ_EMPTY(&alias->addr))
448  mutt_beep(false);
449  if (mutt_addrlist_to_intl(&alias->addr, &err))
450  {
451  mutt_error(_("Bad IDN: '%s'"), err);
452  FREE(&err);
453  continue;
454  }
455  } while (TAILQ_EMPTY(&alias->addr));
456 
457  if (addr && addr->personal && !mutt_is_mail_list(addr))
458  mutt_str_copy(buf, addr->personal, sizeof(buf));
459  else
460  buf[0] = '\0';
461 
462  if (mutt_get_field(_("Personal name: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS,
463  false, NULL, NULL) != 0)
464  {
465  alias_free(&alias);
466  return;
467  }
468  mutt_str_replace(&TAILQ_FIRST(&alias->addr)->personal, buf);
469 
470  buf[0] = '\0';
471  if (mutt_get_field(_("Comment: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS,
472  false, NULL, NULL) == 0)
473  {
474  mutt_str_replace(&alias->comment, buf);
475  }
476 
477  buf[0] = '\0';
478  mutt_addrlist_write(&alias->addr, buf, sizeof(buf), true);
479  if (alias->comment)
480  {
481  snprintf(prompt, sizeof(prompt), "[%s = %s # %s] %s", alias->name, buf,
482  alias->comment, _("Accept?"));
483  }
484  else
485  {
486  snprintf(prompt, sizeof(prompt), "[%s = %s] %s", alias->name, buf, _("Accept?"));
487  }
488  if (mutt_yesorno(prompt, MUTT_YES) != MUTT_YES)
489  {
490  alias_free(&alias);
491  return;
492  }
493 
494  alias_reverse_add(alias);
495  TAILQ_INSERT_TAIL(&Aliases, alias, entries);
496 
497  const char *const alias_file = cs_subset_path(sub, "alias_file");
498  mutt_str_copy(buf, NONULL(alias_file), sizeof(buf));
499 
500  if (mutt_get_field(_("Save to file: "), buf, sizeof(buf),
501  MUTT_FILE | MUTT_CLEAR, false, NULL, NULL) != 0)
502  {
503  return;
504  }
505  mutt_expand_path(buf, sizeof(buf));
506  FILE *fp_alias = fopen(buf, "a+");
507  if (!fp_alias)
508  {
509  mutt_perror(buf);
510  return;
511  }
512 
513  /* terminate existing file with \n if necessary */
514  if (fseek(fp_alias, 0, SEEK_END))
515  goto fseek_err;
516  if (ftell(fp_alias) > 0)
517  {
518  if (fseek(fp_alias, -1, SEEK_CUR) < 0)
519  goto fseek_err;
520  if (fread(buf, 1, 1, fp_alias) != 1)
521  {
522  mutt_perror(_("Error reading alias file"));
523  mutt_file_fclose(&fp_alias);
524  return;
525  }
526  if (fseek(fp_alias, 0, SEEK_END) < 0)
527  goto fseek_err;
528  if (buf[0] != '\n')
529  fputc('\n', fp_alias);
530  }
531 
532  if (check_alias_name(alias->name, NULL, 0))
533  mutt_file_quote_filename(alias->name, buf, sizeof(buf));
534  else
535  mutt_str_copy(buf, alias->name, sizeof(buf));
536  recode_buf(buf, sizeof(buf));
537  fprintf(fp_alias, "alias %s ", buf);
538  buf[0] = '\0';
539  mutt_addrlist_write(&alias->addr, buf, sizeof(buf), false);
540  recode_buf(buf, sizeof(buf));
541  write_safe_address(fp_alias, buf);
542  if (alias->comment)
543  fprintf(fp_alias, " # %s", alias->comment);
544  fputc('\n', fp_alias);
545  if (mutt_file_fsync_close(&fp_alias) != 0)
546  mutt_perror(_("Trouble adding alias"));
547  else
548  mutt_message(_("Alias added"));
549 
550  return;
551 
552 fseek_err:
553  mutt_perror(_("Error seeking in alias file"));
554  mutt_file_fclose(&fp_alias);
555 }
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:58
#define TAILQ_FIRST(head)
Definition: queue.h:723
#define mutt_error(...)
Definition: logging.h:88
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
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1388
int mutt_get_field(const char *field, char *buf, size_t buflen, CompletionFlags complete, bool multiple, char ***files, int *numfiles)
Ask the user for a string.
Definition: curs_lib.c:335
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:44
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:35
char * mailbox
Mailbox and host address.
Definition: address.h:38
#define mutt_perror(...)
Definition: logging.h:89
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:105
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:122
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:52
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:282
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:618
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:37
struct AliasList Aliases
List of all the user&#39;s email aliases.
Definition: alias.c:57
static int check_alias_name(const char *s, char *dest, size_t destlen)
Sanity-check an alias name.
Definition: alias.c:215
char * comment
Free-form comment string.
Definition: alias.h:37
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:809
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:795
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
void alias_free(struct Alias **ptr)
Free an Alias.
Definition: alias.c:629
#define MUTT_FILE
Do file completion.
Definition: mutt.h:54
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:180
static void write_safe_address(FILE *fp, char *s)
Defang malicious email addresses.
Definition: alias.c:83
char * personal
Real name of address.
Definition: address.h:37
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1305
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:749
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
#define mutt_message(...)
Definition: logging.h:87
#define FREE(x)
Definition: memory.h:40
#define TAILQ_EMPTY(head)
Definition: queue.h:721
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:188
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
+ 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 282 of file alias.c.

283 {
284  struct Alias *a = NULL;
285 
286  TAILQ_FOREACH(a, &Aliases, entries)
287  {
288  if (mutt_istr_equal(name, a->name))
289  return &a->addr;
290  }
291  return NULL;
292 }
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:725
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
struct AliasList Aliases
List of all the user&#39;s email aliases.
Definition: alias.c:57
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
trueThe given address belongs to the user

Definition at line 562 of file alias.c.

563 {
564  if (!addr)
565  {
566  mutt_debug(LL_DEBUG5, "no, NULL address\n");
567  return false;
568  }
569  if (!addr->mailbox)
570  {
571  mutt_debug(LL_DEBUG5, "no, no mailbox\n");
572  return false;
573  }
574 
575  if (mutt_istr_equal(addr->mailbox, Username))
576  {
577  mutt_debug(LL_DEBUG5, "#1 yes, %s = %s\n", addr->mailbox, Username);
578  return true;
579  }
581  {
582  mutt_debug(LL_DEBUG5, "#2 yes, %s = %s @ %s\n", addr->mailbox, Username, ShortHostname);
583  return true;
584  }
585  const char *fqdn = mutt_fqdn(false, NeoMutt->sub);
586  if (string_is_address(addr->mailbox, Username, fqdn))
587  {
588  mutt_debug(LL_DEBUG5, "#3 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
589  return true;
590  }
591  fqdn = mutt_fqdn(true, NeoMutt->sub);
592  if (string_is_address(addr->mailbox, Username, fqdn))
593  {
594  mutt_debug(LL_DEBUG5, "#4 yes, %s = %s @ %s\n", addr->mailbox, Username, NONULL(fqdn));
595  return true;
596  }
597 
598  const struct Address *c_from = cs_subset_address(NeoMutt->sub, "from");
599  if (c_from && mutt_istr_equal(c_from->mailbox, addr->mailbox))
600  {
601  mutt_debug(LL_DEBUG5, "#5 yes, %s = %s\n", addr->mailbox, c_from->mailbox);
602  return true;
603  }
604 
605  if (mutt_alternates_match(addr->mailbox))
606  return true;
607 
608  mutt_debug(LL_DEBUG5, "no, all failed\n");
609  return false;
610 }
#define NONULL(x)
Definition: string2.h:37
bool mutt_alternates_match(const char *addr)
Compare an Address to the Un/Alternates lists.
Definition: alternates.c:153
An email address.
Definition: address.h:35
char * mailbox
Mailbox and host address.
Definition: address.h:38
const struct Address * cs_subset_address(const struct ConfigSubset *sub, const char *name)
Get an Address config item by name.
Definition: helpers.c:49
Container for Accounts, Notifications.
Definition: neomutt.h:36
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:48
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:46
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:1187
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:263
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 314 of file alias.c.

315 {
316  mutt_expand_aliases(&env->from);
317  mutt_expand_aliases(&env->to);
318  mutt_expand_aliases(&env->cc);
319  mutt_expand_aliases(&env->bcc);
322 }
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:300
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 300 of file alias.c.

301 {
302  struct ListHead expn; /* previously expanded aliases to avoid loops */
303 
304  STAILQ_INIT(&expn);
305  expand_aliases_r(al, &expn);
306  mutt_list_free(&expn);
308 }
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:1407
#define STAILQ_INIT(head)
Definition: queue.h:372
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:101
+ 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 332 of file alias.c.

333 {
334  struct AddressList *al = NULL;
335  const char *pfx = NULL;
336 
337  if (mutt_addr_is_user(TAILQ_FIRST(&env->from)))
338  {
339  if (!TAILQ_EMPTY(&env->to) && !mutt_is_mail_list(TAILQ_FIRST(&env->to)))
340  {
341  pfx = "To";
342  al = &env->to;
343  }
344  else
345  {
346  pfx = "Cc";
347  al = &env->cc;
348  }
349  }
350  else if (!TAILQ_EMPTY(&env->reply_to) && !mutt_is_mail_list(TAILQ_FIRST(&env->reply_to)))
351  {
352  pfx = "Reply-To";
353  al = &env->reply_to;
354  }
355  else
356  {
357  al = &env->from;
358  pfx = "From";
359  }
360 
361  if (prefix)
362  *prefix = pfx;
363 
364  return al;
365 }
#define TAILQ_FIRST(head)
Definition: queue.h:723
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:44
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:562
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
#define TAILQ_EMPTY(head)
Definition: queue.h:721
+ Here is the call graph for this function:
+ Here is the caller 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 465 of file dlgalias.c.

466 {
467  struct Alias *np = NULL;
468  char bestname[8192] = { 0 };
469 
470  struct AliasMenuData mdata = { NULL, ARRAY_HEAD_INITIALIZER, sub };
471  mdata.str = mutt_str_dup(buf);
472 
473  if (buf[0] != '\0')
474  {
475  TAILQ_FOREACH(np, &Aliases, entries)
476  {
477  if (np->name && mutt_strn_equal(np->name, buf, strlen(buf)))
478  {
479  if (bestname[0] == '\0') /* init */
480  {
481  mutt_str_copy(bestname, np->name,
482  MIN(mutt_str_len(np->name) + 1, sizeof(bestname)));
483  }
484  else
485  {
486  int i;
487  for (i = 0; np->name[i] && (np->name[i] == bestname[i]); i++)
488  ; // do nothing
489 
490  bestname[i] = '\0';
491  }
492  }
493  }
494 
495  if (bestname[0] != '\0')
496  {
497  /* fake the pattern for menu title */
498  char *mtitle = NULL;
499  mutt_str_asprintf(&mtitle, "~f ^%s", buf);
500  FREE(&mdata.str);
501  mdata.str = mtitle;
502 
503  if (!mutt_str_equal(bestname, buf))
504  {
505  /* we are adding something to the completion */
506  mutt_str_copy(buf, bestname, mutt_str_len(bestname) + 1);
507  FREE(&mdata.str);
508  return 1;
509  }
510 
511  /* build alias list and show it */
512  TAILQ_FOREACH(np, &Aliases, entries)
513  {
514  int aasize = alias_array_alias_add(&mdata.ava, np);
515 
516  struct AliasView *av = ARRAY_GET(&mdata.ava, aasize - 1);
517 
518  if (np->name && !mutt_strn_equal(np->name, buf, strlen(buf)))
519  {
520  av->is_visible = false;
521  }
522  }
523  }
524  }
525 
526  if (ARRAY_EMPTY(&mdata.ava))
527  {
528  TAILQ_FOREACH(np, &Aliases, entries)
529  {
530  alias_array_alias_add(&mdata.ava, np);
531  }
532 
533  mutt_pattern_alias_func(MUTT_LIMIT, NULL, &mdata, NULL);
534  }
535 
536  alias_array_sort(&mdata.ava, mdata.sub);
537 
538  bestname[0] = '\0';
539  dlg_select_alias(bestname, sizeof(bestname), &mdata);
540  if (bestname[0] != '\0')
541  mutt_str_copy(buf, bestname, buflen);
542 
543  struct AliasView *avp = NULL;
544  ARRAY_FOREACH(avp, &mdata.ava)
545  {
546  if (!avp->is_deleted)
547  continue;
548 
549  TAILQ_REMOVE(&Aliases, avp->alias, entries);
550  alias_free(&avp->alias);
551  }
552 
553  ARRAY_FREE(&mdata.ava);
554  FREE(&mdata.str);
555 
556  return 0;
557 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
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:303
#define MIN(a, b)
Definition: memory.h:31
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
AliasView array wrapper with Pattern information -.
Definition: gui.h:52
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:198
Messages in limited view.
Definition: mutt.h:101
#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
GUI data wrapping an Alias.
Definition: gui.h:35
int alias_array_alias_add(struct AliasViewArray *ava, struct Alias *alias)
Add an Alias to the AliasViewArray.
Definition: array.c:45
int mutt_pattern_alias_func(int op, char *prompt, struct AliasMenuData *mdata, struct Menu *menu)
Perform some Pattern matching for Alias.
Definition: pattern.c:241
void alias_array_sort(struct AliasViewArray *ava, const struct ConfigSubset *sub)
Sort and reindex an AliasViewArray.
Definition: sort.c:157
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition: array.h:54
char * str
String representing the limit being used.
Definition: gui.h:54
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:841
bool is_visible
Is visible?
Definition: gui.h:43
struct AliasList Aliases
List of all the user&#39;s email aliases.
Definition: alias.c:57
struct Alias * alias
Alias.
Definition: gui.h:44
void * mdata
Private data.
Definition: lib.h:155
#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:629
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
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:749
struct ConfigSubset * sub
Config items.
Definition: gui.h:56
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:593
#define FREE(x)
Definition: memory.h:40
struct AliasViewArray ava
Array of AliasView.
Definition: gui.h:55
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:1128
bool is_deleted
Is it deleted?
Definition: gui.h:42
+ 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 697 of file dlgquery.c.

698 {
699  const char *const query_command = cs_subset_string(sub, "query_command");
700  if (!query_command)
701  {
702  mutt_warning(_("Query command not defined"));
703  return 0;
704  }
705 
706  struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
707  query_run(buf, true, &al, sub);
708  if (TAILQ_EMPTY(&al))
709  return 0;
710 
711  struct Alias *a_first = TAILQ_FIRST(&al);
712  if (!TAILQ_NEXT(a_first, entries)) // only one response?
713  {
714  struct AddressList addr = TAILQ_HEAD_INITIALIZER(addr);
715  if (alias_to_addrlist(&addr, a_first))
716  {
717  mutt_addrlist_to_local(&addr);
718  buf[0] = '\0';
719  mutt_addrlist_write(&addr, buf, buflen, false);
720  mutt_addrlist_clear(&addr);
721  aliaslist_free(&al);
723  }
724  return 0;
725  }
726 
727  /* multiple results, choose from query menu */
728  dlg_select_query(buf, buflen, &al, true, sub);
729  aliaslist_free(&al);
730  return 0;
731 }
static bool alias_to_addrlist(struct AddressList *al, struct Alias *alias)
Turn an Alias into an AddressList.
Definition: dlgquery.c:121
A shortcut for an email address or addresses.
Definition: alias.h:33
#define TAILQ_FIRST(head)
Definition: queue.h:723
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1388
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1470
#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:418
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:112
#define mutt_warning(...)
Definition: logging.h:86
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:283
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
void aliaslist_free(struct AliasList *al)
Free a List of Aliases.
Definition: alias.c:650
#define TAILQ_NEXT(elm, field)
Definition: queue.h:832
#define TAILQ_EMPTY(head)
Definition: queue.h:721
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
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 737 of file dlgquery.c.

738 {
739  const char *const query_command = cs_subset_string(sub, "query_command");
740  if (!query_command)
741  {
742  mutt_warning(_("Query command not defined"));
743  return;
744  }
745 
746  char buf[256] = { 0 };
747  if ((mutt_get_field(_("Query: "), buf, sizeof(buf), MUTT_COMP_NO_FLAGS, false,
748  NULL, NULL) != 0) ||
749  (buf[0] == '\0'))
750  {
751  return;
752  }
753 
754  struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
755  query_run(buf, false, &al, sub);
756  if (TAILQ_EMPTY(&al))
757  return;
758 
759  dlg_select_query(buf, sizeof(buf), &al, false, sub);
760  aliaslist_free(&al);
761 }
int mutt_get_field(const char *field, char *buf, size_t buflen, CompletionFlags complete, bool multiple, char ***files, int *numfiles)
Ask the user for a string.
Definition: curs_lib.c:335
#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:418
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:52
#define mutt_warning(...)
Definition: logging.h:86
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:283
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
void aliaslist_free(struct AliasList *al)
Free a List of Aliases.
Definition: alias.c:650
#define TAILQ_EMPTY(head)
Definition: queue.h:721
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
+ 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:38
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:

◆ 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 157 of file sort.c.

158 {
159  if (!ava || ARRAY_EMPTY(ava))
160  return;
161 
162  sort_alias = cs_subset_sort(sub, "sort_alias");
164 
165  struct AliasView *avp = NULL;
166  ARRAY_FOREACH(avp, ava)
167  {
168  avp->num = ARRAY_FOREACH_IDX;
169  }
170 }
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:206
GUI data wrapping an Alias.
Definition: gui.h:35
static short sort_alias
Definition: sort.c:41
static sort_t alias_get_sort_function(short sort)
Sorting function decision logic.
Definition: sort.c:137
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
#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:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function: