46#define ENCWORD_LEN_MAX 75
47#define ENCWORD_LEN_MIN 9
49#define HSPACE(ch) (((ch) == '\0') || ((ch) == ' ') || ((ch) == '\t'))
51#define CONTINUATION_BYTE(ch) (((ch) &0xc0) == 0x80)
64typedef size_t (*
encoder_t)(
char *str,
const char *buf,
size_t buflen,
const char *tocode);
69static size_t b_encoder(
char *str,
const char *buf,
size_t buflen,
const char *tocode)
75 memcpy(str, tocode, strlen(tocode));
76 str += strlen(tocode);
77 memcpy(str,
"?B?", 3);
82 char encoded[11] = { 0 };
84 size_t in_len =
MIN(3, buflen);
87 for (
size_t i = 0; i < rc; i++)
102static size_t q_encoder(
char *str,
const char *buf,
size_t buflen,
const char *tocode)
104 static const char hex[] =
"0123456789ABCDEF";
107 memcpy(str,
"=?", 2);
109 memcpy(str, tocode, strlen(tocode));
110 str += strlen(tocode);
111 memcpy(str,
"?Q?", 3);
115 unsigned char c = *buf++;
118 else if ((c >= 0x7f) || (c < 0x20) || (c ==
'_') || strchr(
MimeSpecials, c))
121 *str++ = hex[(c & 0xf0) >> 4];
122 *str++ = hex[c & 0x0f];
127 memcpy(str,
"?=", 2);
144 size_t *charsetlen,
char **text,
size_t *textlen)
186static size_t try_block(
const char *d,
size_t dlen,
const char *fromcode,
187 const char *tocode,
encoder_t *encoder,
size_t *wlen)
190 const char *ib = NULL;
193 int count, len, len_b, len_q;
198 assert(cd != (iconv_t) (-1));
202 obl =
sizeof(buf) - strlen(tocode);
203 if ((iconv(cd, (ICONV_CONST
char **) &ib, &ibl, &ob, &obl) == (
size_t) (-1)) ||
204 (iconv(cd, NULL, NULL, &ob, &obl) == (size_t) (-1)))
206 assert(errno == E2BIG);
209 return ((ib - d) == dlen) ? dlen : ib - d + 1;
215 if (dlen > (
sizeof(buf) - strlen(tocode)))
216 return sizeof(buf) - strlen(tocode) + 1;
217 memcpy(buf, d, dlen);
222 for (
char *p = buf; p < ob; p++)
224 unsigned char c = *p;
226 if ((c >= 0x7f) || (c < 0x20) || (*p ==
'_') ||
234 len_b = len + (((ob - buf) + 2) / 3) * 4;
235 len_q = len + (ob - buf) + 2 *
count;
269static size_t encode_block(
char *str,
char *buf,
size_t buflen,
const char *fromcode,
274 return (*encoder)(str, buf, buflen, tocode);
278 assert(cd != (iconv_t) (-1));
279 const char *ib = buf;
283 size_t obl =
sizeof(tmp) - strlen(tocode);
284 const size_t n1 = iconv(cd, (ICONV_CONST
char **) &ib, &ibl, &ob, &obl);
285 const size_t n2 = iconv(cd, NULL, NULL, &ob, &obl);
286 assert(n1 != (
size_t) (-1) && n2 != (
size_t) (-1));
288 return (*encoder)(str, tmp, ob - tmp, tocode);
307static size_t choose_block(
char *d,
size_t dlen,
int col,
const char *fromcode,
308 const char *tocode,
encoder_t *encoder,
size_t *wlen)
316 const size_t nn =
try_block(d, n, fromcode, tocode, encoder, wlen);
317 if ((nn == 0) && (((col + *wlen) <= (
ENCWORD_LEN_MAX + 1)) || (n <= 1)))
319 n = ((nn != 0) ? nn : n) - 1;
341 char end = charset[charsetlen];
342 charset[charsetlen] =
'\0';
345 charset[charsetlen] = end;
364 const char *end = s + len;
369 for (; it < end; it++)
375 else if ((it[0] ==
'=') && (!(it[1] & ~127) && (
hexval(it[1]) != -1)) &&
376 (!(it[2] & ~127) && (
hexval(it[2]) != -1)))
391 const int olen = 3 * len / 4 + 1;
419static int encode(
const char *d,
size_t dlen,
int col,
const char *fromcode,
420 const struct Slist *charsets,
char **e,
size_t *elen,
const char *specials)
424 size_t bufpos, buflen;
425 char *t0 = NULL, *t1 = NULL, *t = NULL;
426 char *s0 = NULL, *s1 = NULL;
427 size_t ulen, r, wlen = 0;
429 char *tocode1 = NULL;
430 const char *tocode = NULL;
431 const char *icode =
"utf-8";
447 for (t = u; t < (u + ulen); t++)
449 if ((*t & 0x80) || ((*t ==
'=') && (t[1] ==
'?') && ((t == u) ||
HSPACE(*(t - 1)))))
455 else if (specials && *t && strchr(specials, *t))
464 if (t0 && s0 && (s0 < t0))
466 if (t1 && s1 && (s1 > t1))
493 tocode =
"unknown-8bit";
511 if ((
try_block(t0, t - t0, icode, tocode, &encoder, &wlen) == 0) &&
519 for (; t1 < (u + ulen); t1++)
527 if ((
try_block(t, t1 - t, icode, tocode, &encoder, &wlen) == 0) &&
540 memcpy(buf, u, t0 - u);
548 size_t n =
choose_block(t, t1 - t, col, icode, tocode, &encoder, &wlen);
565 assert(t1 < (u + ulen));
566 for (t1++; (t1 < (u + ulen)) && !
HSPACE(*t1); t1++)
571 n =
choose_block(t, n, col, icode, tocode, &encoder, &wlen);
575 const char *line_break =
"\n\t";
576 const int lb_len = 2;
578 if ((bufpos + wlen + lb_len) > buflen)
580 buflen = bufpos + wlen + lb_len;
583 r =
encode_block(buf + bufpos, t, n, icode, tocode, encoder);
586 memcpy(buf + bufpos, line_break, lb_len);
595 buflen = bufpos + wlen + (u + ulen - t1);
597 r =
encode_block(buf + bufpos, t, t1 - t, icode, tocode, encoder);
600 memcpy(buf + bufpos, t1, u + ulen - t1);
622 if (!c_charset || !pd || !*pd)
625 struct Slist *fallback = NULL;
634 encode(*pd, strlen(*pd), col, c_charset, charsets, &e, &elen, specials);
658 char *charset = NULL;
667 char *prev_charset = NULL;
668 size_t prev_charsetlen = 0;
694 if (c_assumed_charset)
711 text[textlen] =
'\0';
718 if (prev.
data && ((prev_charsetlen != charsetlen) ||
728 prev_charset = charset;
729 prev_charsetlen = charsetlen;
730 s = text + textlen + 2;
755 int col = tag ? strlen(tag) + 2 : 32;
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.
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
size_t mutt_buffer_addstr_n(struct Buffer *buf, const char *s, size_t len)
Add a string to a Buffer, expanding it if necessary.
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
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.
Convenience wrapper for the core headers.
Representation of an email header (envelope)
static size_t b_encoder(char *str, const char *buf, size_t buflen, const char *tocode)
Base64 Encode a string - Implements encoder_t -.
static size_t q_encoder(char *str, const char *buf, size_t buflen, const char *tocode)
Quoted-printable Encode a string - Implements encoder_t -.
int mutt_mb_filter_unprintable(char **s)
Replace unprintable characters.
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
const char MimeSpecials[]
Characters that need special treatment in MIME.
Constants and macros for managing MIME encoding.
ContentEncoding
Content-Transfer-Encoding.
@ 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_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
int mutt_ch_convert_nonmime_string(char **ps)
Try to convert a string using a list of character sets.
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.
Convenience wrapper for the library headers.
struct Slist * slist_parse(const char *str, uint32_t flags)
Parse a list of strings into a list.
void slist_free(struct Slist **list)
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.
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.
size_t(* encoder_t)(char *str, const char *buf, size_t buflen, const char *tocode)
#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.
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.
char * mailbox
Mailbox and host address.
char * personal
Real name of address.
String manipulation buffer.
char * data
Pointer to data.
struct AddressList return_path
Return path for the Email.
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.
char * subject
Email's subject.
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.