67#define is_special(ch, mask) \
68 ((ch) >= 32 && (ch) < 96 && ((mask >> ((ch) - 32)) & 1))
71#define ADDRESS_SPECIAL_MASK 0x380000015c005304ULL
74#define USER_SPECIAL_MASK 0x280000015c001200ULL
77#define DOMAIN_SPECIAL_MASK 0x000000015c001204ULL
80#define ROUTE_SPECIAL_MASK 0x000000015c000204ULL
91static const char *
parse_comment(
const char *s,
char *comment,
size_t *commentlen,
size_t commentmax)
114 if (*commentlen < commentmax)
115 comment[(*commentlen)++] = *s;
134static const char *
parse_quote(
const char *s,
char *token,
size_t *tokenlen,
size_t tokenmax)
138 if (*tokenlen < tokenmax)
139 token[*tokenlen] = *s;
145 if (*tokenlen < tokenmax)
146 token[*tokenlen] = *s;
166static const char *
next_token(
const char *s,
char *token,
size_t *tokenlen,
size_t tokenmax)
171 return parse_quote(s + 1, token, tokenlen, tokenmax);
174 if (*tokenlen < tokenmax)
175 token[(*tokenlen)++] = *s;
182 if (*tokenlen < tokenmax)
183 token[(*tokenlen)++] = *s;
214 char *
mailbox,
size_t *mailboxlen,
215 size_t mailboxmax,
char *comment,
216 size_t *commentlen,
size_t commentmax)
218 const char *ps = NULL;
231 if (*commentlen && (*commentlen < commentmax))
232 comment[(*commentlen)++] =
' ';
233 ps =
next_token(s, comment, commentlen, commentmax);
260static const char *
parse_address(
const char *s,
char *token,
size_t *tokenlen,
261 size_t tokenmax,
char *comment,
size_t *commentlen,
262 size_t commentmax,
struct Address *addr)
265 comment, commentlen, commentmax);
271 if (*tokenlen < tokenmax)
272 token[(*tokenlen)++] =
'@';
274 tokenmax, comment, commentlen, commentmax);
301 size_t commentmax,
struct Address *addr)
303 char token[1024] = { 0 };
311 while (s && (*s ==
'@'))
313 if (tokenlen < (
sizeof(token) - 1))
314 token[tokenlen++] =
'@';
316 sizeof(token) - 1, comment, commentlen, commentmax);
318 if (!s || (*s !=
':'))
323 if (tokenlen < (
sizeof(token) - 1))
324 token[tokenlen++] =
':';
328 s =
parse_address(s, token, &tokenlen,
sizeof(token) - 1, comment, commentlen,
357 size_t commentmax,
struct Address *addr)
359 char token[1024] = { 0 };
362 s =
parse_address(s, token, &tokenlen,
sizeof(token) - 1, comment, commentlen,
364 if (s && *s && (*s !=
',') && (*s !=
';'))
381 char *comment,
size_t *commentlen,
size_t commentmax)
444 struct Address *a = NULL, *tmp = NULL;
486 char comment[1024] = { 0 };
487 char phrase[1024] = { 0 };
488 size_t phraselen = 0, commentlen = 0;
502 if (
add_addrspec(al, phrase, comment, &commentlen,
sizeof(comment) - 1))
507 else if (commentlen != 0)
529 if ((commentlen != 0) && (commentlen < (
sizeof(comment) - 1)))
530 comment[commentlen++] =
' ';
531 s =
next_token(s, comment, &commentlen,
sizeof(comment) - 1);
540 if ((phraselen != 0) && (phraselen < (
sizeof(phrase) - 1)))
541 phrase[phraselen++] =
' ';
542 s =
parse_quote(s + 1, phrase, &phraselen,
sizeof(phrase) - 1);
589 if ((phraselen != 0) && (phraselen < (
sizeof(phrase) - 1)) && ws_pending)
590 phrase[phraselen++] =
' ';
594 if (*s && (phraselen < (
sizeof(phrase) - 1)))
596 phrase[phraselen++] = *s;
600 s =
next_token(s, phrase, &phraselen,
sizeof(phrase) - 1);
617 if (
add_addrspec(al, phrase, comment, &commentlen,
sizeof(comment) - 1))
622 else if (commentlen != 0)
646 if (!s || (*s ==
'\0'))
652 if (!strpbrk(s,
"\"<>():;,\\"))
656 while ((r = strtok(r,
" \t")))
682 if (!al || !host || (*host ==
'\0'))
708void mutt_addr_cat(
char *buf,
size_t buflen,
const char *value,
const char *specials)
710 if (!buf || !value || !specials)
713 if (strpbrk(value, specials))
715 char tmp[256] = { 0 };
717 size_t tmplen =
sizeof(tmp) - 3;
720 for (; *value && (tmplen > 1); value++)
722 if ((*value ==
'\\') || (*value ==
'"'))
815 if (!msgid || (*msgid ==
'\0'))
821 if ((msgid[0] !=
'<') || (msgid[l - 1] !=
'>'))
823 if (!(strrchr(msgid,
'@')))
827 for (
size_t i = 0; i < l; i++)
828 if ((
unsigned char) msgid[i] > 127)
844 return !(ala || alb);
862 return !(ana || anb);
911 if (!needle || !haystack)
959 if (!mbox || !user || !domain)
962 char *ptr = strchr(mbox,
'@');
965 if (!ptr || (ptr == mbox) || (ptr[1] ==
'\0'))
1017 char *user = NULL, *domain = NULL;
1018 static char *buf = NULL;
1035 FREE(&local_mailbox);
1057 const size_t initial_len =
buf_len(buf);
1066 if ((*pc ==
'"') || (*pc ==
'\\'))
1110 return buf_len(buf) - initial_len;
1127 bool display,
const char *header,
int cols)
1137 size_t cur_col =
buf_len(buf);
1138 bool in_group =
false;
1150 const size_t cur_len =
buf_len(buf);
1152 if ((cols > 0) && (cur_col > cols) && (a !=
TAILQ_FIRST(al)))
1190 struct Buffer *buf,
const char *header)
1226 struct Buffer buf = { 0 };
1269 char *domain = NULL;
1282 FREE(&intl_mailbox);
1310 char *domain = NULL;
1328 FREE(&intl_mailbox);
1353 char *domain = NULL;
1369 FREE(&local_mailbox);
1438 struct Address *aa = NULL, *ab = NULL, *tmp = NULL;
1509 if ((
unsigned char) *str & (1 << 7))
static bool addr_is_intl(const struct Address *a)
Does the Address have IDN components.
struct Address * mutt_addr_create(const char *personal, const char *mailbox)
Create and populate a new Address.
static bool add_addrspec(struct AddressList *al, const char *phrase, char *comment, size_t *commentlen, size_t commentmax)
Parse an email address and add an Address to a list.
static const char * parse_addr_spec(const char *s, char *comment, size_t *commentlen, size_t commentmax, struct Address *addr)
Parse an email address.
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
static int addr_mbox_to_udomain(const char *mbox, char **user, char **domain)
Split a mailbox name into user and domain.
static bool addr_is_local(const struct Address *a)
Does the Address have NO IDN components.
static const char * parse_address(const char *s, char *token, size_t *tokenlen, size_t tokenmax, char *comment, size_t *commentlen, size_t commentmax, struct Address *addr)
Extract an email address.
bool mutt_addrlist_equal(const struct AddressList *ala, const struct AddressList *alb)
Compare two Address lists for equality.
static const char * parse_route_addr(const char *s, char *comment, size_t *commentlen, size_t commentmax, struct Address *addr)
Parse an email addresses.
static const char * parse_mailboxdomain(const char *s, uint64_t special_mask, char *mailbox, size_t *mailboxlen, size_t mailboxmax, char *comment, size_t *commentlen, size_t commentmax)
Extract part of an email address (and a comment)
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
static const char * next_token(const char *s, char *token, size_t *tokenlen, size_t tokenmax)
Find the next word, skipping quoted and parenthesised text.
size_t mutt_addrlist_write_list(const struct AddressList *al, struct ListHead *list)
Write Addresses to a List.
void mutt_addr_free(struct Address **ptr)
Free a single Address.
bool mutt_addr_valid_msgid(const char *msgid)
Is this a valid Message ID?
static void addr_set_intl(struct Address *a, char *intl_mailbox)
Mark an Address as having IDN components.
size_t mutt_addr_write(struct Buffer *buf, struct Address *addr, bool display)
Write a single Address to a buffer.
static void addr_set_local(struct Address *a, char *local_mailbox)
Mark an Address as having NO IDN components.
bool mutt_addrlist_uses_unicode(const struct AddressList *al)
Do any of a list of addresses use Unicode characters.
void mutt_addr_cat(char *buf, size_t buflen, const char *value, const char *specials)
Copy a string and wrap it in quotes if it contains special characters.
bool mutt_addr_cmp(const struct Address *a, const struct Address *b)
Compare two e-mail addresses.
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
size_t mutt_addrlist_write_wrap(const struct AddressList *al, struct Buffer *buf, const char *header)
Write an AddressList to a buffer, perform line wrapping.
struct Address * mutt_addr_new(void)
Create a new Address.
static size_t addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display, const char *header, int cols)
Write an AddressList to a buffer, optionally perform line wrapping and display conversion.
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
bool mutt_addr_uses_unicode(const char *str)
Does this address use Unicode character.
int mutt_addrlist_parse2(struct AddressList *al, const char *s)
Parse a list of email addresses.
struct Address * mutt_addr_copy(const struct Address *addr)
Copy the real address.
const char AddressSpecials[]
Characters with special meaning for email addresses.
#define USER_SPECIAL_MASK
AddressSpecials except " ( .
#define ROUTE_SPECIAL_MASK
AddressSpecials except ( , .
bool mutt_addr_to_local(struct Address *a)
Convert an Address from Punycode.
void mutt_addrlist_remove_xrefs(const struct AddressList *a, struct AddressList *b)
Remove cross-references.
int mutt_addrlist_count_recips(const struct AddressList *al)
Count the number of Addresses with valid recipients.
#define ADDRESS_SPECIAL_MASK
AddressSpecials, for is_special()
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
void mutt_addrlist_prepend(struct AddressList *al, struct Address *a)
Prepend an Address to an AddressList.
static const char * parse_comment(const char *s, char *comment, size_t *commentlen, size_t commentmax)
Extract a comment (parenthesised string)
void mutt_addrlist_write_file(const struct AddressList *al, FILE *fp, const char *header)
Wrapper for mutt_write_address()
#define DOMAIN_SPECIAL_MASK
AddressSpecials except ( .
#define is_special(ch, mask)
Is this character special to an email address?
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
bool mutt_addr_to_intl(struct Address *a)
Convert an Address to Punycode.
int mutt_addrlist_remove(struct AddressList *al, const char *mailbox)
Remove an Address from a list.
bool mutt_addrlist_search(const struct AddressList *haystack, const struct Address *needle)
Search for an e-mail address in a list.
static const char * parse_quote(const char *s, char *token, size_t *tokenlen, size_t tokenmax)
Extract a quoted string.
const char * mutt_addr_for_display(const struct Address *a)
Convert an Address for display purposes.
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Representation of an email address.
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
bool buf_istr_equal(const struct Buffer *a, const struct Buffer *b)
Return if two buffers are equal, case insensitive.
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
void buf_free(struct Buffer **ptr)
Deallocates a buffer.
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
bool buf_str_equal(const struct Buffer *a, const struct Buffer *b)
Return if two buffers are equal.
struct Buffer * buf_dup(const struct Buffer *buf)
Copy a Buffer into a new allocated buffer.
const char * buf_find_char(const struct Buffer *buf, const char c)
Return a pointer to a char found in the buffer.
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
size_t buf_insert(struct Buffer *buf, size_t offset, const char *s)
Add a string in the middle of a buffer.
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
#define mutt_debug(LEVEL,...)
Handling of international domain names.
#define MI_MAY_BE_IRREVERSIBLE
char * mutt_idna_local_to_intl(const char *user, const char *domain)
Convert an email's domain to Punycode.
char * mutt_idna_intl_to_local(const char *user, const char *domain, uint8_t flags)
Convert an email's domain from Punycode.
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
@ LL_DEBUG2
Log at debug level 2.
#define MUTT_MEM_CALLOC(n, type)
Convenience wrapper for the library headers.
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
char * mutt_str_dup(const char *str)
Copy a string, safely.
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
#define TAILQ_FOREACH(var, head, field)
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
#define TAILQ_INSERT_TAIL(head, elm, field)
#define TAILQ_FIRST(head)
#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar)
#define TAILQ_REMOVE(head, elm, field)
#define TAILQ_NEXT(elm, field)
#define TAILQ_EMPTY(head)
#define TAILQ_LAST(head, headname)
#define TAILQ_INSERT_HEAD(head, elm, field)
#define terminate_string(str, strlen, buflen)
#define terminate_buffer(str, strlen)
static bool mutt_str_is_email_wsp(char c)
Is this a whitespace character (for an email header)
struct Buffer * personal
Real name of address.
struct Buffer * mailbox
Mailbox and host address.
bool intl_checked
Checked for IDN?
bool is_intl
International Domain Name.
String manipulation buffer.