47#define ENCWORD_LEN_MAX 75
48#define ENCWORD_LEN_MIN 9
50#define HSPACE(ch) (((ch) == '\0') || ((ch) == ' ') || ((ch) == '\t'))
52#define CONTINUATION_BYTE(ch) (((ch) & 0xc0) == 0x80)
65typedef size_t (*
encoder_t)(
char *res,
const char *buf,
size_t buflen,
const char *tocode);
70static size_t b_encoder(
char *res,
const char *src,
size_t srclen,
const char *tocode)
76 memcpy(res, tocode, strlen(tocode));
77 res += strlen(tocode);
78 memcpy(res,
"?B?", 3);
83 char encoded[11] = { 0 };
85 size_t in_len =
MIN(3, srclen);
88 for (
size_t i = 0; i < rc; i++)
103static size_t q_encoder(
char *res,
const char *src,
size_t srclen,
const char *tocode)
105 static const char hex[] =
"0123456789ABCDEF";
108 memcpy(res,
"=?", 2);
110 memcpy(res, tocode, strlen(tocode));
111 res += strlen(tocode);
112 memcpy(res,
"?Q?", 3);
116 unsigned char c = *src++;
121 else if ((c >= 0x7f) || (c < 0x20) || (c ==
'_') || strchr(
MimeSpecials, c))
124 *res++ = hex[(c & 0xf0) >> 4];
125 *res++ = hex[c & 0x0f];
132 memcpy(res,
"?=", 2);
149 size_t *charsetlen,
char **text,
size_t *textlen)
191static size_t try_block(
const char *d,
size_t dlen,
const char *fromcode,
192 const char *tocode,
encoder_t *encoder,
size_t *wlen)
195 const char *ib = NULL;
198 int count, len, len_b, len_q;
207 obl =
sizeof(buf) - strlen(tocode);
208 if ((iconv(cd, (ICONV_CONST
char **) &ib, &ibl, &ob, &obl) ==
ICONV_ILLEGAL_SEQ) ||
213 return ((ib - d) == dlen) ? dlen : ib - d + 1;
218 if (dlen > (
sizeof(buf) - strlen(tocode)))
219 return sizeof(buf) - strlen(tocode) + 1;
220 memcpy(buf, d, dlen);
225 for (
char *p = buf; p < ob; p++)
227 unsigned char c = *p;
229 if ((c >= 0x7f) || (c < 0x20) || (*p ==
'_') ||
237 len_b = len + (((ob - buf) + 2) / 3) * 4;
238 len_q = len + (ob - buf) + 2 *
count;
274static size_t encode_block(
char *str,
char *buf,
size_t buflen,
const char *fromcode,
279 return (*encoder)(str, buf, buflen, tocode);
284 const char *ib = buf;
288 size_t obl =
sizeof(tmp) - strlen(tocode);
289 const size_t n1 = iconv(cd, (ICONV_CONST
char **) &ib, &ibl, &ob, &obl);
290 const size_t n2 = iconv(cd, NULL, NULL, &ob, &obl);
292 return (*encoder)(str, tmp, ob - tmp, tocode);
311static size_t choose_block(
char *d,
size_t dlen,
int col,
const char *fromcode,
312 const char *tocode,
encoder_t *encoder,
size_t *wlen)
320 const size_t nn =
try_block(d, n, fromcode, tocode, encoder, wlen);
321 if ((nn == 0) && (((col + *wlen) <= (
ENCWORD_LEN_MAX + 1)) || (n <= 1)))
323 n = ((nn != 0) ? nn : n) - 1;
345 char end = charset[charsetlen];
346 charset[charsetlen] =
'\0';
348 charset[charsetlen] = end;
368 const char *end = s + len;
375 for (; it < end; it++)
381 else if ((it[0] ==
'=') && (!(it[1] & ~127) && (
hexval(it[1]) != -1)) &&
382 (!(it[2] & ~127) && (
hexval(it[2]) != -1)))
398 const int olen = 3 * len / 4 + 1;
426static int encode(
const char *d,
size_t dlen,
int col,
const char *fromcode,
427 const struct Slist *charsets,
char **e,
size_t *elen,
const char *specials)
431 size_t bufpos, buflen;
432 char *t0 = NULL, *t1 = NULL, *t = NULL;
433 char *s0 = NULL, *s1 = NULL;
434 size_t ulen, r, wlen = 0;
436 char *tocode1 = NULL;
437 const char *tocode = NULL;
438 const char *icode =
"utf-8";
454 for (t = u; t < (u + ulen); t++)
456 if ((*t & 0x80) || ((*t ==
'=') && (t[1] ==
'?') && ((t == u) ||
HSPACE(*(t - 1)))))
462 else if (specials && *t && strchr(specials, *t))
471 if (t0 && s0 && (s0 < t0))
473 if (t1 && s1 && (s1 > t1))
502 tocode =
"unknown-8bit";
520 if ((
try_block(t0, t - t0, icode, tocode, &encoder, &wlen) == 0) &&
528 for (; t1 < (u + ulen); t1++)
536 if ((
try_block(t, t1 - t, icode, tocode, &encoder, &wlen) == 0) &&
549 memcpy(buf, u, t0 - u);
557 size_t n =
choose_block(t, t1 - t, col, icode, tocode, &encoder, &wlen);
575 for (t1++; (t1 < (u + ulen)) && !
HSPACE(*t1); t1++)
580 n =
choose_block(t, n, col, icode, tocode, &encoder, &wlen);
584 const char *line_break =
"\n\t";
585 const int lb_len = 2;
587 if ((bufpos + wlen + lb_len) > buflen)
589 buflen = bufpos + wlen + lb_len;
592 r =
encode_block(buf + bufpos, t, n, icode, tocode, encoder);
595 memcpy(buf + bufpos, line_break, lb_len);
604 buflen = bufpos + wlen + (u + ulen - t1);
606 r =
encode_block(buf + bufpos, t, t1 - t, icode, tocode, encoder);
609 memcpy(buf + bufpos, t1, u + ulen - t1);
637 struct Slist *fallback = NULL;
646 encode(*pd, strlen(*pd), col, c_charset, charsets, &e, &elen, specials);
670 char *charset = NULL;
679 char *prev_charset = NULL;
680 size_t prev_charsetlen = 0;
722 text[textlen] =
'\0';
728 if (!
buf_is_empty(prev) && ((prev_charsetlen != charsetlen) ||
738 prev_charset = charset;
739 prev_charsetlen = charsetlen;
740 s = text + textlen + 2;
771 int col = tag ? strlen(tag) + 2 : 32;
847 *(
char **) &env->
subject = NULL;
872 *(
char **) &env->
subject = NULL;
const char AddressSpecials[]
Characters with special meaning for email addresses.
size_t mutt_b64_encode(const char *in, size_t inlen, char *out, size_t outlen)
Convert raw bytes to null-terminated base64 string.
int mutt_b64_decode(const char *in, char *out, size_t olen)
Convert null-terminated base64 string to raw bytes.
size_t buf_addstr_n(struct Buffer *buf, const char *s, size_t len)
Add a string to a Buffer, expanding it if necessary.
const char * buf_find_string(const struct Buffer *buf, const char *s)
Return a pointer to a substring found in the buffer.
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
struct Buffer * buf_init(struct Buffer *buf)
Initialise 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.
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
const struct Slist * cs_subset_slist(const struct ConfigSubset *sub, const char *name)
Get a string-list config item by name.
Convenience wrapper for the config headers.
const char * cc_charset(void)
Get the cached value of $charset.
const struct Slist * cc_assumed_charset(void)
Get the cached value of $assumed_charset.
Convenience wrapper for the core headers.
void mutt_env_set_subject(struct Envelope *env, const char *subj)
Set both subject and real_subj to subj.
Representation of an email header (envelope)
static size_t b_encoder(char *res, const char *src, size_t srclen, const char *tocode)
Base64 Encode a string - Implements encoder_t -.
static size_t q_encoder(char *res, const char *src, size_t srclen, const char *tocode)
Quoted-printable Encode a string - Implements encoder_t -.
int mutt_mb_filter_unprintable(char **s)
Replace unprintable characters.
#define MUTT_MEM_REALLOC(pptr, n, type)
#define MUTT_MEM_MALLOC(n, type)
const char MimeSpecials[]
Characters that need special treatment in MIME.
Constants and macros for managing MIME encoding.
ContentEncoding
Content-Transfer-Encoding.
@ ENC_OTHER
Encoding unknown.
@ ENC_BASE64
Base-64 encoded text.
@ ENC_QUOTED_PRINTABLE
Quoted-printable text.
char * mutt_ch_choose(const char *fromcode, const struct Slist *charsets, const char *u, size_t ulen, char **d, size_t *dlen)
Figure the best charset to encode a string.
int mutt_ch_convert_nonmime_string(const struct Slist *const assumed_charset, const char *charset, char **ps)
Try to convert a string using a list of character sets.
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
iconv_t mutt_ch_iconv_open(const char *tocode, const char *fromcode, uint8_t flags)
Set up iconv for conversions.
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
#define mutt_ch_is_us_ascii(str)
#define MUTT_ICONV_NO_FLAGS
No flags are set.
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
static bool iconv_t_valid(const iconv_t cd)
Is the conversion descriptor valid?
Convenience wrapper for the library headers.
struct Slist * slist_parse(const char *str, uint32_t flags)
Parse a list of strings into a list.
bool slist_is_empty(const struct Slist *list)
Is the slist empty?
void slist_free(struct Slist **ptr)
Free an Slist object.
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.
size_t mutt_str_lws_len(const char *s, size_t n)
Measure the linear-white-space at the beginning of a string.
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
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.
regmatch_t * mutt_prex_capture(enum Prex which, const char *str)
Match a precompiled regex against a string.
@ PREX_RFC2047_ENCODED_WORD_MATCH_ENCODING
=?utf-8?[Q]?=E8=81...?=
@ PREX_RFC2047_ENCODED_WORD_MATCH_TEXT
=?utf-8?Q?[=E8=81...]?=
@ PREX_RFC2047_ENCODED_WORD_MATCH_CHARSET
=?[utf-8]?Q?=E8=81...?=
@ PREX_RFC2047_ENCODED_WORD_MATCH_FULL
[=?utf-8?Q?=E8=81...?=]
@ PREX_RFC2047_ENCODED_WORD
[=?utf-8?Q?=E8=81=AA=E6=98=8E=E7=9A=84?=]
#define TAILQ_FOREACH(var, head, field)
static size_t mutt_regmatch_len(const regmatch_t *match)
Return the length of a match.
static regoff_t mutt_regmatch_start(const regmatch_t *match)
Return the start of a match.
#define CONTINUATION_BYTE(ch)
void rfc2047_encode_addrlist(struct AddressList *al, const char *tag)
Encode any RFC2047 headers, where required, in an Address list.
void rfc2047_encode(char **pd, const char *specials, int col, const struct Slist *charsets)
RFC-2047-encode a string.
static size_t choose_block(char *d, size_t dlen, int col, const char *fromcode, const char *tocode, encoder_t *encoder, size_t *wlen)
Calculate how much data can be converted.
void rfc2047_decode_envelope(struct Envelope *env)
Decode the fields of an Envelope.
static char * parse_encoded_word(char *str, enum ContentEncoding *enc, char **charset, size_t *charsetlen, char **text, size_t *textlen)
Parse a string and report RFC2047 elements.
size_t(* encoder_t)(char *res, const char *buf, size_t buflen, const char *tocode)
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
static size_t encode_block(char *str, char *buf, size_t buflen, const char *fromcode, const char *tocode, encoder_t encoder)
Encode a block of text using an encoder.
static char * decode_word(const char *s, size_t len, enum ContentEncoding enc)
Decode an RFC2047-encoded string.
void rfc2047_decode_addrlist(struct AddressList *al)
Decode any RFC2047 headers in an Address list.
void rfc2047_encode_envelope(struct Envelope *env)
Encode the fields of an Envelope.
static int encode(const char *d, size_t dlen, int col, const char *fromcode, const struct Slist *charsets, char **e, size_t *elen, const char *specials)
RFC2047-encode a string.
static size_t try_block(const char *d, size_t dlen, const char *fromcode, const char *tocode, encoder_t *encoder, size_t *wlen)
Attempt to convert a block of text.
static void finalize_chunk(struct Buffer *res, struct Buffer *buf, char *charset, size_t charsetlen)
Perform charset conversion and filtering.
RFC2047 MIME extensions encoding / decoding routines.
struct Buffer * personal
Real name of address.
struct Buffer * mailbox
Mailbox and host address.
String manipulation buffer.
char * data
Pointer to data.
struct AddressList return_path
Return path for the Email.
char *const subject
Email's subject.
struct AddressList to
Email's 'To' list.
struct AddressList reply_to
Email's 'reply-to'.
struct AddressList mail_followup_to
Email's 'mail-followup-to'.
struct AddressList cc
Email's 'Cc' list.
struct AddressList sender
Email's sender.
struct AddressList bcc
Email's 'Bcc' list.
struct AddressList from
Email's 'From' list.
Container for Accounts, Notifications.
struct ConfigSubset * sub
Inherited config items.
size_t count
Number of values in list.
#define D_SLIST_SEP_COLON
Slist items are colon-separated.