break;
case 'r':
addr[0] = '\0';
- mutt_addr_write(addr, sizeof(addr), alias->addr, true);
+ mutt_addresslist_write(addr, sizeof(addr), &alias->addr, true);
snprintf(fmt, sizeof(fmt), "%%%ss", prec);
snprintf(buf, buflen, fmt, addr);
break;
*/
static int alias_sort_address(const void *a, const void *b)
{
- struct Address *pa = (*(struct Alias **) a)->addr;
- struct Address *pb = (*(struct Alias **) b)->addr;
+ struct AddressList *pal = &(*(struct Alias **) a)->addr;
+ struct AddressList *pbl = &(*(struct Alias **) b)->addr;
int r;
- if (pa == pb)
+ if (pal == pbl)
r = 0;
- else if (!pa)
+ else if (!pal)
r = -1;
- else if (!pb)
+ else if (!pbl)
r = 1;
- else if (pa->personal)
+ else
{
- if (pb->personal)
- r = mutt_str_strcasecmp(pa->personal, pb->personal);
+ struct Address *pa = TAILQ_FIRST(pal)->addr;
+ struct Address *pb = TAILQ_FIRST(pbl)->addr;
+ if (pa->personal)
+ {
+ if (pb->personal)
+ r = mutt_str_strcasecmp(pa->personal, pb->personal);
+ else
+ r = 1;
+ }
+ else if (pb->personal)
+ r = -1;
else
- r = 1;
+ r = mutt_str_strcasecmp(pa->mailbox, pb->mailbox);
}
- else if (pb->personal)
- r = -1;
- else
- r = mutt_str_strcasecmp(pa->mailbox, pb->mailbox);
return RSORT(r);
}
{
if (alias_table[i]->tagged)
{
- mutt_addr_write(buf, buflen, alias_table[i]->addr, true);
+ mutt_addresslist_write(buf, buflen, &alias_table[i]->addr, true);
t = -1;
}
}
if (t != -1)
{
- mutt_addr_write(buf, buflen, alias_table[t]->addr, true);
+ mutt_addresslist_write(buf, buflen, &alias_table[t]->addr, true);
}
mutt_menu_pop_current(menu);
* @retval ptr Top of the address list
* @retval NULL Error
*/
-struct Address *mutt_addr_parse_list(struct Address *top, const char *s)
+void mutt_addresslist_parse(struct AddressList *al, const char *s)
{
if (!s)
- return NULL;
+ return;
- struct AddressList *al = mutt_addr_to_addresslist(top);
char comment[1024], phrase[1024];
size_t phraselen = 0, commentlen = 0;
AddressError = 0;
s = next_token(s, comment, &commentlen, sizeof(comment) - 1);
if (!s)
{
- mutt_addresslist_free(&al);
- return NULL;
+ mutt_addresslist_free_all(al);
+ return;
}
break;
s = parse_quote(s + 1, phrase, &phraselen, sizeof(phrase) - 1);
if (!s)
{
- mutt_addresslist_free(&al);
- return NULL;
+ mutt_addresslist_free_all(al);
+ return;
}
break;
s = parse_route_addr(s + 1, comment, &commentlen, sizeof(comment) - 1, a);
if (!s)
{
- mutt_addresslist_free(&al);
+ mutt_addresslist_free_all(al);
free_address(&a);
- return NULL;
+ return;
}
mutt_addresslist_append(al, a);
phraselen = 0;
s = next_token(s, phrase, &phraselen, sizeof(phrase) - 1);
if (!s)
{
- mutt_addresslist_free(&al);
- return NULL;
+ mutt_addresslist_free_all(al);
+ return;
}
break;
} // switch (*s)
last->addr->personal = mutt_str_strdup(comment);
}
}
+}
+
+struct Address *mutt_addr_parse_list(struct Address *top, const char *s)
+{
+ if (!s)
+ return NULL;
+ struct AddressList *al = mutt_addr_to_addresslist(top);
+ mutt_addresslist_parse(al, s);
top = mutt_addresslist_to_addr(al);
- mutt_addresslist_free(&al);
+ FREE(&al);
return top;
}
*
* The email addresses can be separated by whitespace or commas.
*/
-struct Address *mutt_addr_parse_list2(struct Address *p, const char *s)
+void mutt_addresslist_parse2(struct AddressList *al, const char *s)
{
if (!s)
- return NULL;
+ return;
/* check for a simple whitespace separated list of addresses */
const char *q = strpbrk(s, "\"<>():;,\\");
char *r = tmp->data;
while ((r = strtok(r, " \t")))
{
- p = mutt_addr_parse_list(p, r);
+ mutt_addresslist_parse(al, r);
r = NULL;
}
mutt_buffer_free(&tmp);
}
else
- p = mutt_addr_parse_list(p, s);
+ mutt_addresslist_parse(al, s);
+}
+struct Address *mutt_addr_parse_list2(struct Address *p, const char *s)
+{
+ if (!s)
+ return NULL;
+
+ struct AddressList *al = mutt_addr_to_addresslist(p);
+ mutt_addresslist_parse2(al, s);
+ p = mutt_addresslist_to_addr(al);
+ FREE(&al);
return p;
}
*
* @note It is assumed that `buf` is nul terminated!
*/
-size_t mutt_addr_write(char *buf, size_t buflen, struct Address *addr, bool display)
+size_t mutt_addresslist_write(char *buf, size_t buflen, struct AddressList *al, bool display)
{
- if (!buf || !addr)
+ if (!buf || !al)
return 0;
char *pbuf = buf;
buflen--;
}
- struct AddressList *al = mutt_addr_to_addresslist(addr);
struct AddressNode *np = NULL;
TAILQ_FOREACH(np, al, entries)
{
}
}
- mutt_addresslist_to_addr(al);
- FREE(&al);
-
done:
*pbuf = '\0';
return pbuf - buf;
}
+size_t mutt_addr_write(char *buf, size_t buflen, struct Address *addr, bool display)
+{
+ struct AddressList *al = mutt_addr_to_addresslist(addr);
+ size_t ret = mutt_addresslist_write(buf, buflen, al, display);
+ mutt_addresslist_to_addr(al);
+ FREE(&al);
+ return ret;
+}
+
/**
* mutt_addrlist_to_intl - Convert an Address list to Punycode
* @param[in] a Address list to modify
* @retval 0 Success, all addresses converted
* @retval -1 Error, err will be set to the failed address
*/
-int mutt_addrlist_to_intl(struct Address *a, char **err)
+int mutt_addresslist_to_intl(struct AddressList *al, char **err)
{
char *user = NULL, *domain = NULL;
char *intl_mailbox = NULL;
if (err)
*err = NULL;
- struct AddressList *al = mutt_addr_to_addresslist(a);
struct AddressNode *an = NULL;
TAILQ_FOREACH(an, al, entries)
{
mutt_addr_set_intl(an->addr, intl_mailbox);
}
- mutt_addresslist_to_addr(al);
- FREE(&al);
+ return rc;
+}
+int mutt_addrlist_to_intl(struct Address *a, char **err)
+{
+ struct AddressList *al = mutt_addr_to_addresslist(a);
+ int rc = mutt_addresslist_to_intl(al, err);
+ a = mutt_addresslist_to_addr(al);
+ FREE(&al);
return rc;
}
void mutt_addresslist_free(struct AddressList **al);
void mutt_addresslist_free_one(struct AddressList *al, struct AddressNode *anode);
void mutt_addresslist_free_all(struct AddressList *al);
+size_t mutt_addresslist_write(char *buf, size_t buflen, struct AddressList* addr, bool display);
+void mutt_addresslist_parse(struct AddressList *top, const char *s);
+void mutt_addresslist_parse2(struct AddressList *top, const char *s);
+int mutt_addresslist_to_intl(struct AddressList *a, char **err);
#endif /* MUTT_EMAIL_ADDRESS_H */
* @param head GroupList to add to
* @param a Address to add
*/
-void mutt_grouplist_add_addrlist(struct GroupList *head, struct Address *a)
+void mutt_grouplist_add_addresslist(struct GroupList *head, struct AddressList *al)
{
- if (!head || !a)
+ if (!head || !al)
return;
- struct AddressList *al = mutt_addr_to_addresslist(a);
-
struct GroupNode *np = NULL;
STAILQ_FOREACH(np, head, entries)
{
group_add_addrlist(np->group, al);
}
+}
+void mutt_grouplist_add_addrlist(struct GroupList *head, struct Address *a)
+{
+ if (!head || !a)
+ return;
+
+ struct AddressList *al = mutt_addr_to_addresslist(a);
+ mutt_grouplist_add_addresslist(head, al);
mutt_addresslist_to_addr(al);
FREE(&al);
}
void mutt_grouplist_free(void);
void mutt_grouplist_add(struct GroupList *head, struct Group *group);
void mutt_grouplist_add_addrlist(struct GroupList *head, struct Address *a);
+void mutt_grouplist_add_addresslist(struct GroupList *head, struct AddressList *a);
int mutt_grouplist_add_regex(struct GroupList *head, const char *s,
int flags, struct Buffer *err);
void mutt_grouplist_destroy(struct GroupList *head);
*/
static struct Address *expand_aliases_r(struct Address *a, struct ListHead *expn)
{
- struct Address *head = NULL, *last = NULL, *t = NULL, *w = NULL;
+ struct Address *head = NULL, *last = NULL, *w = NULL;
+ struct AddressList *t = NULL;
bool i;
const char *fqdn = NULL;
if (!i)
{
mutt_list_insert_head(expn, mutt_str_strdup(a->mailbox));
- w = mutt_addr_copy_list(t, false);
+ struct AddressList *al2 = mutt_addresslist_copy(t, false);
+ w = mutt_addresslist_to_addr(al2);
+ FREE(&al2);
w = expand_aliases_r(w, expn);
if (head)
last->next = w;
while (last && last->next)
last = last->next;
}
- t = a;
+ struct Address *tmp = a;
a = a->next;
- t->next = NULL;
- mutt_addr_free(&t);
+ tmp->next = NULL;
+ mutt_addr_free(&tmp);
continue;
}
else
return head;
}
+/**
+ * mutt_alias_new - Create a new Alias
+ * @retval ptr Newly allocated Alias
+ *
+ * Free the result with mutt_alias_free()
+ */
+struct Alias *mutt_alias_new()
+{
+ struct Alias *a = mutt_mem_calloc(1, sizeof(struct Alias));
+ TAILQ_INIT(&a->addr);
+ return a;
+}
+
/**
* write_safe_address - Defang malicious email addresses
* @param fp File to write to
*
* @note The search is case-insensitive
*/
-struct Address *mutt_alias_lookup(const char *s)
+struct AddressList *mutt_alias_lookup(const char *s)
{
struct Alias *a = NULL;
TAILQ_FOREACH(a, &Aliases, entries)
{
if (mutt_str_strcasecmp(s, a->name) == 0)
- return a->addr;
+ return &a->addr;
}
return NULL;
}
}
}
- new = mutt_mem_calloc(1, sizeof(struct Alias));
+ new = mutt_alias_new();
new->name = mutt_str_strdup(buf);
mutt_addrlist_to_local(addr);
return;
}
- new->addr = mutt_addr_parse_list(new->addr, buf);
- if (!new->addr)
+ mutt_addresslist_parse(&new->addr, buf);
+ if (TAILQ_EMPTY(&new->addr))
BEEP();
- if (mutt_addrlist_to_intl(new->addr, &err))
+ if (mutt_addresslist_to_intl(&new->addr, &err))
{
mutt_error(_("Bad IDN: '%s'"), err);
FREE(&err);
continue;
}
- } while (!new->addr);
+ } while (TAILQ_EMPTY(&new->addr));
if (addr && addr->personal && !mutt_is_mail_list(addr))
mutt_str_strfcpy(buf, addr->personal, sizeof(buf));
mutt_alias_free(&new);
return;
}
- mutt_str_replace(&new->addr->personal, buf);
+ mutt_str_replace(&TAILQ_FIRST(&new->addr)->addr->personal, buf);
buf[0] = '\0';
- mutt_addr_write(buf, sizeof(buf), new->addr, true);
+ mutt_addresslist_write(buf, sizeof(buf), &new->addr, true);
snprintf(prompt, sizeof(prompt), _("[%s = %s] Accept?"), new->name, buf);
if (mutt_yesorno(prompt, MUTT_YES) != MUTT_YES)
{
recode_buf(buf, sizeof(buf));
fprintf(fp_alias, "alias %s ", buf);
buf[0] = '\0';
- mutt_addr_write(buf, sizeof(buf), new->addr, false);
+ mutt_addresslist_write(buf, sizeof(buf), &new->addr, false);
recode_buf(buf, sizeof(buf));
write_safe_address(fp_alias, buf);
fputc('\n', fp_alias);
/* Note that the address mailbox should be converted to intl form
* before using as a key in the hash. This is currently done
* by all callers, but added here mostly as documentation. */
- mutt_addrlist_to_intl(t->addr, NULL);
+ mutt_addresslist_to_intl(&t->addr, NULL);
- for (struct Address *ap = t->addr; ap; ap = ap->next)
+ struct AddressNode *an = NULL;
+ TAILQ_FOREACH(an, &t->addr, entries)
{
- if (!ap->group && ap->mailbox)
- mutt_hash_insert(ReverseAliases, ap->mailbox, ap);
+ if (!an->addr->group && an->addr->mailbox)
+ mutt_hash_insert(ReverseAliases, an->addr->mailbox, an->addr);
}
}
/* If the alias addresses were converted to local form, they won't
* match the hash entries. */
- mutt_addrlist_to_intl(t->addr, NULL);
+ mutt_addresslist_to_intl(&t->addr, NULL);
- for (struct Address *ap = t->addr; ap; ap = ap->next)
+ struct AddressNode *an = NULL;
+ TAILQ_FOREACH(an, &t->addr, entries)
{
- if (!ap->group && ap->mailbox)
- mutt_hash_delete(ReverseAliases, ap->mailbox, ap);
+ if (!an->addr->group && an->addr->mailbox)
+ mutt_hash_delete(ReverseAliases, an->addr->mailbox, an->addr);
}
}
mutt_alias_delete_reverse(*p);
FREE(&(*p)->name);
- mutt_addr_free(&(*p)->addr);
+ mutt_addresslist_free_all(&((*p)->addr));
FREE(p);
}
#include <stddef.h>
#include <stdbool.h>
#include "mutt/mutt.h"
+#include "address/address.h"
-struct Address;
struct Envelope;
/**
struct Alias
{
char *name;
- struct Address *addr;
+ struct AddressList addr;
bool tagged;
bool del;
short num;
};
TAILQ_HEAD(AliasList, Alias);
-void mutt_alias_create(struct Envelope *cur, struct Address *iaddr);
+struct Alias *mutt_alias_new(void);
void mutt_alias_free(struct Alias **p);
+void mutt_alias_create(struct Envelope *cur, struct Address *iaddr);
void mutt_aliaslist_free(struct AliasList *a_list);
-struct Address *mutt_alias_lookup(const char *s);
+struct AddressList *mutt_alias_lookup(const char *s);
void mutt_expand_aliases_env(struct Envelope *env);
struct Address *mutt_expand_aliases(struct Address *a);
struct Address *mutt_get_address(struct Envelope *env, const char **pfxp);
if (!tmp)
{
/* create a new alias */
- tmp = mutt_mem_calloc(1, sizeof(struct Alias));
+ tmp = mutt_alias_new();
tmp->name = mutt_str_strdup(buf->data);
TAILQ_INSERT_TAIL(&Aliases, tmp, entries);
/* give the main addressbook code a chance */
{
mutt_alias_delete_reverse(tmp);
/* override the previous value */
- mutt_addr_free(&tmp->addr);
+ mutt_addresslist_free_all(&tmp->addr);
if (CurrentMenu == MENU_ALIAS)
mutt_menu_set_current_redraw_full();
}
mutt_extract_token(buf, s, MUTT_TOKEN_QUOTE | MUTT_TOKEN_SPACE | MUTT_TOKEN_SEMICOLON);
mutt_debug(5, "Second token is '%s'\n", buf->data);
- tmp->addr = mutt_addr_parse_list2(tmp->addr, buf->data);
+ mutt_addresslist_parse2(&tmp->addr, buf->data);
- if (mutt_addrlist_to_intl(tmp->addr, &estr))
+ if (mutt_addresslist_to_intl(&tmp->addr, &estr))
{
mutt_buffer_printf(err, _("Warning: Bad IDN '%s' in alias '%s'"), estr, tmp->name);
FREE(&estr);
goto bail;
}
- mutt_grouplist_add_addrlist(&gc, tmp->addr);
+ mutt_grouplist_add_addresslist(&gc, &tmp->addr);
mutt_alias_add_reverse(tmp);
if (C_DebugLevel > LL_DEBUG4)
{
/* A group is terminated with an empty address, so check a->mailbox */
- for (struct Address *a = tmp->addr; a && a->mailbox; a = a->next)
+ struct AddressNode *an = NULL;
+ TAILQ_FOREACH(an, &tmp->addr, entries)
{
- if (a->group)
- mutt_debug(5, " Group %s\n", a->mailbox);
+ if (!an->addr->mailbox)
+ break;
+
+ if (an->addr->group)
+ mutt_debug(5, " Group %s\n", an->addr->mailbox);
else
- mutt_debug(5, " %s\n", a->mailbox);
+ mutt_debug(5, " %s\n", an->addr->mailbox);
}
}
mutt_grouplist_destroy(&gc);
if (!STAILQ_EMPTY(&alias_queries))
{
rc = 0;
- struct Address *a = NULL;
for (; optind < argc; optind++)
mutt_list_insert_tail(&alias_queries, mutt_str_strdup(argv[optind]));
struct ListNode *np = NULL;
STAILQ_FOREACH(np, &alias_queries, entries)
{
- a = mutt_alias_lookup(np->data);
- if (a)
+ struct AddressList *al = mutt_alias_lookup(np->data);
+ if (al)
{
/* output in machine-readable form */
- mutt_addrlist_to_intl(a, NULL);
- mutt_write_address_list(a, stdout, 0, 0);
+ mutt_addresslist_to_intl(al, NULL);
+ mutt_write_addresslist(al, stdout, 0, 0);
}
else
{
case '@':
{
- struct Address *alias = mutt_alias_lookup(s + 1);
+ struct AddressList *al = mutt_addresslist_copy(mutt_alias_lookup(s + 1), false);
+ struct Address *alias = mutt_addresslist_to_addr(al);
+ FREE(&al);
if (alias)
{
struct Email *e = mutt_email_new();
else if (buf[0] == '@')
{
/* elm compatibility, @ expands alias to user name */
- struct Address *alias = mutt_alias_lookup(buf + 1);
+ struct AddressList *al = mutt_addresslist_copy(mutt_alias_lookup(buf + 1), false);
+ struct Address *alias = mutt_addresslist_to_addr(al);
+ FREE(&al);
if (!alias)
break;
* So we can handle very large recipient lists without needing a huge temporary
* buffer in memory
*/
-void mutt_write_address_list(struct Address *addr, FILE *fp, int linelen, bool display)
+void mutt_write_addresslist(struct AddressList *al, FILE *fp, int linelen, bool display)
{
- struct Address *tmp = NULL;
char buf[1024];
int count = 0;
- while (addr)
+ struct AddressNode *an = NULL;
+ TAILQ_FOREACH(an, al, entries)
{
- tmp = addr->next;
- addr->next = NULL;
+ struct Address *addr = an->addr;
buf[0] = '\0';
mutt_addr_write(buf, sizeof(buf), addr, display);
size_t len = mutt_str_strlen(buf);
linelen += len;
}
fputs(buf, fp);
- addr->next = tmp;
- if (!addr->group && addr->next && addr->next->mailbox)
+ struct AddressNode *next = TAILQ_NEXT(an, entries);
+ if (!addr->group && next && next->addr->mailbox)
{
linelen++;
fputc(',', fp);
}
- addr = addr->next;
count++;
}
fputc('\n', fp);
}
+void mutt_write_address_list(struct Address *addr, FILE *fp, int linelen, bool display)
+{
+ struct AddressList *al = mutt_addr_to_addresslist(addr);
+ mutt_write_addresslist(al, fp, linelen, display);
+ mutt_addresslist_to_addr(al);
+ FREE(&al);
+}
/**
* mutt_write_references - Add the message references to a list
#include "copy.h"
struct Address;
+struct AddressList;
struct Body;
struct Email;
struct Envelope;
void mutt_unprepare_envelope(struct Envelope *env);
void mutt_update_encoding(struct Body *a);
void mutt_write_address_list(struct Address *addr, FILE *fp, int linelen, bool display);
+void mutt_write_addresslist(struct AddressList *addr, FILE *fp, int linelen, bool display);
int mutt_write_fcc(const char *path, struct Email *e, const char *msgid, bool post, char *fcc, char **finalpath);
int mutt_write_mime_body(struct Body *a, FILE *fp);
int mutt_write_mime_header(struct Body *a, FILE *fp);