replace str_replace with m_strreplace. I don't like that function at all.
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
char namebuf[STRING];
mutt_gecos_name (namebuf, sizeof (namebuf), pw);
- str_replace (&a->personal, namebuf);
+ m_strreplace (&a->personal, namebuf);
}
}
}
if ((fpin = fopen (a->filename, "r")) && (fpout = safe_fopen (tempfile, "w"))) { /* __FOPEN_CHECKED__ */
mutt_copy_stream (fpin, fpout);
- str_replace (&a->filename, tempfile);
+ m_strreplace(&a->filename, tempfile);
a->unlink = 1;
if (a->stamp >= st.st_mtime)
mutt_error ("%s", buf);
}
else {
- str_replace (&Mask.pattern, buf);
+ m_strreplace(&Mask.pattern, buf);
regfree (Mask.rx);
p_delete(&Mask.rx);
Mask.rx = rx;
# define my_iconv(a,b,c,d,e) 0
# define iconv_close(a) 0
#else
-static inline size_t my_iconv(iconv_t ict, const char **inbuf, size_t *ilen,
- char **outbuf, size_t *olen)
+static inline ssize_t my_iconv(iconv_t ict, const char **inbuf, size_t *ilen,
+ char **outbuf, size_t *olen)
{
return iconv(ict, (char **)inbuf, ilen, outbuf, olen);
}
else
buf[0] = 0;
if (mutt_get_field ("Subject: ", buf, sizeof (buf), 0) == 0) {
- str_replace (&msg->env->subject, buf);
+ m_strreplace(&msg->env->subject, buf);
move (HDR_SUBJECT, HDR_XOFFSET + SW);
clrtoeol ();
if (msg->env->subject)
NONULL(idx[menu->current]->content->description));
/* header names should not be translated */
if (mutt_get_field ("Description: ", buf, sizeof (buf), 0) == 0) {
- str_replace (&idx[menu->current]->content->description, buf);
+ m_strreplace(&idx[menu->current]->content->description, buf);
menu->redraw = REDRAW_CURRENT;
}
mutt_message_hook (NULL, msg, M_SEND2HOOK);
if (mutt_rename_file (idx[menu->current]->content->filename, fname))
break;
- str_replace (&idx[menu->current]->content->filename, fname);
+ m_strreplace(&idx[menu->current]->content->filename, fname);
menu->redraw = REDRAW_CURRENT;
if (idx[menu->current]->content->stamp >= st.st_mtime)
update_idx (menu, idx, idxlen++);
idx[menu->current]->content->type = itype;
- str_replace (&idx[menu->current]->content->subtype, p);
+ m_strreplace(&idx[menu->current]->content->subtype, p);
idx[menu->current]->content->unlink = 1;
menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
if (whatfor) {
if (l)
- str_replace (&l->dflt, resp);
+ m_strreplace(&l->dflt, resp);
else {
l = p_new(struct crypt_cache, 1);
l->next = id_defaults;
is_smime ? APPLICATION_SMIME :
APPLICATION_PGP, NULL))) {
snprintf (input_signas, sizeof (input_signas), "0x%s", crypt_keyid (p));
- str_replace (is_smime ? &SmimeDefaultKey : &PgpSignAs,
+ m_strreplace(is_smime ? &SmimeDefaultKey : &PgpSignAs,
input_signas);
crypt_free_key (&p);
mutt_error (_("%s is not a mailbox."), buf);
break;
}
- str_replace (&CurrentFolder, buf);
+ m_strreplace(&CurrentFolder, buf);
if (Context) {
int check;
#ifdef USE_COMPRESSED
if (Context->compressinfo && Context->realpath)
- str_replace (&LastFolder, Context->realpath);
+ m_strreplace(&LastFolder, Context->realpath);
else
#endif
- str_replace (&LastFolder, Context->path);
+ m_strreplace(&LastFolder, Context->path);
oldcount = Context ? Context->msgcount : 0;
if ((check = mx_close_mailbox (Context, &index_hint)) != 0) {
addstr ("Subject: ");
m_strcpy(tmp, sizeof(tmp), NONULL(e->subject));
if (mutt_enter_string (tmp, sizeof (tmp), LINES - 1, 9, 0) == 0)
- str_replace (&e->subject, tmp);
+ m_strreplace(&e->subject, tmp);
addch ('\n');
}
addstr (_("missing filename.\n"));
break;
case 's':
- str_replace (&msg->env->subject, p);
+ m_strreplace(&msg->env->subject, p);
break;
case 't':
msg->env->to = rfc822_parse_adrlist (msg->env->to, p);
debug_print (2, ("key id: %s\n", p));
if (!(*is_subkey && option (OPTPGPIGNORESUB)))
- str_replace (&k->keyid, p);
+ m_strreplace(&k->keyid, p);
break;
}
if ((devnull = open ("/dev/null", O_RDWR)) == -1)
return NULL;
- str_replace (&_chs, Charset);
+ m_strreplace(&_chs, Charset);
thepid = pgp_invoke_list_keys (NULL, &fp, NULL, -1, -1, devnull,
keyring, hints);
if (prev < 0)
prev = HistSize - 1;
if (!h->hist[prev] || m_strcmp(h->hist[prev], s) != 0) {
- str_replace (&h->hist[h->last++], s);
+ m_strreplace(&h->hist[h->last++], s);
if (h->last > HistSize - 1)
h->last = 0;
}
path[0] = '\0';
m_strcpy(path, sizeof(path), val);
mutt_expand_path (path, sizeof(path));
- str_replace ((char **) dst->data, path);
+ m_strreplace((char **) dst->data, path);
return (1);
}
if (!check_special (dst->option, (unsigned long) val, errbuf, errlen))
return (0);
- str_replace ((char**) dst->data, val);
+ m_strreplace((char**) dst->data, val);
return (1);
}
dst->data = (unsigned long) m_strdup(val);
else {
char* s = (char*) dst->data;
- str_replace (&s, val);
+ m_strreplace(&s, val);
}
if (m_strlen(dst->init) == 0)
dst->init = m_strdup((char*) dst->data);
p_delete(&p->rx);
}
- str_replace (&p->pattern, val);
+ m_strreplace(&p->pattern, val);
p->rx = rx;
p->not = not;
return len ? p_dup(s, len + 1) : NULL;
}
+static inline char *m_strreplace(char **p, const char *s) {
+ p_delete(p);
+ return (*p = m_strdup(s));
+}
+
ssize_t m_strcpy(char *dst, ssize_t n, const char *src);
ssize_t m_strncpy(char *dst, ssize_t n, const char *src, ssize_t l);
noinst_LIBRARIES = libmime.a
-libmime_a_SOURCES = mime.h mime.c rfc822.c rfc2231.c
+libmime_a_SOURCES = mime.h mime.c rfc822.c rfc2047.c rfc2231.c
noinst_HEADERS = mime.h
char *mutt_choose_charset(const char *fromcode, const char *charsets,
char *u, size_t ulen, char **d, size_t *dlen);
-void _rfc2047_encode_string(char **, int, int);
+void rfc2047_encode_string(char **);
void rfc2047_encode_adrlist(address_t *, const char *);
-#define rfc2047_encode_string(a) _rfc2047_encode_string (a, 0, 32);
-
void rfc2047_decode(char **);
void rfc2047_decode_adrlist(address_t *);
void rfc2047_decode_envelope(ENVELOPE* e);
--- /dev/null
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * Copyright © 2006 Pierre Habouzit
+ */
+
+/*
+ * Copyright notice from original mutt:
+ * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
+ * Copyright (C) 2000-2001 Edmund Grimley Evans <edmundo@rano.org>
+ *
+ * This file is part of mutt-ng, see http://www.muttng.org/.
+ * It's licensed under the GNU General Public License,
+ * please see the file GPL in the top level source directory.
+ */
+
+#include <lib-lib/mem.h>
+#include <lib-lib/str.h>
+#include <lib-lib/ascii.h>
+
+#include <lib-mime/mime.h>
+
+#include "mutt.h"
+#include "charset.h"
+#include "thread.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* If you are debugging this file, comment out the following line. */
+/*#define NDEBUG*/
+
+#ifdef NDEBUG
+#define assert(x)
+#else
+#include <assert.h>
+#endif
+
+#define ENCWORD_LEN_MAX 75
+#define ENCWORD_LEN_MIN 9 /* m_strlen("=?.?.?.?=") */
+
+#define HSPACE(x) ((x) == '\0' || (x) == ' ' || (x) == '\t')
+
+#define CONTINUATION_BYTE(c) (((c) & 0xc0) == 0x80)
+
+typedef size_t (*encoder_t) (char *, const char *, size_t,
+ const char *);
+
+/* converts f of len flen and charset from
+ into *t of len *tlen and charset to
+
+ returns -1 on error
+ returns number of converted chars from f, see iconv(3)
+ */
+static ssize_t
+convert_string(const char *from, const char *f, ssize_t flen,
+ const char *to, char **t, size_t *tlen)
+{
+ iconv_t cd;
+ char *buf, *ob;
+ size_t obl, n;
+ int e;
+
+ cd = mutt_iconv_open(to, from, 0);
+
+ if (cd == (iconv_t)(-1))
+ return -1;
+
+ obl = 4 * flen + 1;
+ ob = buf = p_new(char, obl);
+ n = my_iconv(cd, &f, &flen, &ob, &obl);
+
+ if (n < 0 || my_iconv(cd, 0, 0, &ob, &obl) < 0) {
+ e = errno;
+ p_delete(&buf);
+ iconv_close (cd);
+ errno = e;
+ return -1;
+ }
+
+ *ob = '\0';
+ *tlen = ob - buf;
+
+ p_realloc(&buf, ob - buf + 1);
+ *t = buf;
+ iconv_close (cd);
+
+ return n;
+}
+
+char *mutt_choose_charset(const char *fromcode, const char *charsets,
+ char *u, size_t ulen, char **d, size_t *dlen)
+{
+ char canonical_buff[LONG_STRING];
+ char *e = 0, *tocode = 0;
+ size_t elen = 0, bestn = 0;
+ const char *p, *q;
+
+ for (p = charsets; p; p = q ? q + 1 : 0) {
+ char *s, *t;
+ size_t slen, n;
+
+ q = strchr (p, ':');
+
+ n = q ? q - p : m_strlen(p);
+
+ if (!n ||
+ /* Assume that we never need more than 12 characters of
+ encoded-text to encode a single character. */
+ n > (ENCWORD_LEN_MAX - ENCWORD_LEN_MIN + 2 - 12))
+ continue;
+
+ t = p_dupstr(p, n);
+
+ n = convert_string(fromcode, u, ulen, t, &s, &slen);
+ if (n == (size_t) (-1))
+ continue;
+
+ if (!tocode || n < bestn) {
+ bestn = n;
+ p_delete(&tocode);
+ tocode = t;
+ if (d) {
+ p_delete(&e);
+ e = s;
+ } else {
+ p_delete(&s);
+ }
+ elen = slen;
+ if (!bestn)
+ break;
+ } else {
+ p_delete(&t);
+ p_delete(&s);
+ }
+ }
+
+ if (tocode) {
+ if (d)
+ *d = e;
+ if (dlen)
+ *dlen = elen;
+
+ mutt_canonical_charset(canonical_buff, sizeof(canonical_buff), tocode);
+ m_strreplace(&tocode, canonical_buff);
+ }
+
+ return tocode;
+}
+
+static size_t b_encoder (char *s, const char *d, size_t dlen,
+ const char *tocode)
+{
+ char *s0 = s;
+
+ memcpy (s, "=?", 2), s += 2;
+ memcpy (s, tocode, m_strlen(tocode)), s += m_strlen(tocode);
+ memcpy (s, "?B?", 3), s += 3;
+ for (;;) {
+ if (!dlen)
+ break;
+ else if (dlen == 1) {
+ *s++ = __m_b64chars[(*d >> 2) & 0x3f];
+ *s++ = __m_b64chars[(*d & 0x03) << 4];
+ *s++ = '=';
+ *s++ = '=';
+ break;
+ }
+ else if (dlen == 2) {
+ *s++ = __m_b64chars[(*d >> 2) & 0x3f];
+ *s++ = __m_b64chars[((*d & 0x03) << 4) | ((d[1] >> 4) & 0x0f)];
+ *s++ = __m_b64chars[(d[1] & 0x0f) << 2];
+ *s++ = '=';
+ break;
+ }
+ else {
+ *s++ = __m_b64chars[(*d >> 2) & 0x3f];
+ *s++ = __m_b64chars[((*d & 0x03) << 4) | ((d[1] >> 4) & 0x0f)];
+ *s++ = __m_b64chars[((d[1] & 0x0f) << 2) | ((d[2] >> 6) & 0x03)];
+ *s++ = __m_b64chars[d[2] & 0x3f];
+ d += 3, dlen -= 3;
+ }
+ }
+ memcpy (s, "?=", 2), s += 2;
+ return s - s0;
+}
+
+static size_t q_encoder (char *s, const char *d, size_t dlen,
+ const char *tocode)
+{
+ char *s0 = s;
+
+ memcpy (s, "=?", 2), s += 2;
+ memcpy (s, tocode, m_strlen(tocode)), s += m_strlen(tocode);
+ memcpy (s, "?Q?", 3), s += 3;
+ while (dlen--) {
+ unsigned char c = *d++;
+
+ if (c == ' ')
+ *s++ = '_';
+ else if (c >= 0x7f || c < 0x20 || c == '_' || strchr (MimeSpecials, c)) {
+ *s++ = '=';
+ *s++ = __m_b36chars_upper[c >> 4];
+ *s++ = __m_b36chars_upper[c & 0xf];
+ }
+ else
+ *s++ = c;
+ }
+ memcpy (s, "?=", 2), s += 2;
+ return s - s0;
+}
+
+/*
+ * Return 0 if and set *encoder and *wlen if the data (d, dlen) could
+ * be converted to an encoded word of length *wlen using *encoder.
+ * Otherwise return an upper bound on the maximum length of the data
+ * which could be converted.
+ * The data is converted from fromcode (which must be stateless) to
+ * tocode, unless fromcode is 0, in which case the data is assumed to
+ * be already in tocode, which should be 8-bit and stateless.
+ */
+static size_t try_block (const char *d, size_t dlen,
+ const char *fromcode, const char *tocode,
+ encoder_t * encoder, size_t * wlen)
+{
+ char buf1[ENCWORD_LEN_MAX - ENCWORD_LEN_MIN + 1];
+ iconv_t cd;
+ const char *ib;
+ char *ob, *p;
+ size_t ibl, obl;
+ int count, len, len_b, len_q;
+
+ if (fromcode) {
+ cd = mutt_iconv_open (tocode, fromcode, 0);
+ assert (cd != (iconv_t) (-1));
+ ib = d, ibl = dlen, ob = buf1, obl = sizeof (buf1) - m_strlen(tocode);
+ if (my_iconv(cd, &ib, &ibl, &ob, &obl) == (size_t) (-1) ||
+ my_iconv(cd, 0, 0, &ob, &obl) == (size_t) (-1)) {
+ assert (errno == E2BIG);
+ iconv_close (cd);
+ assert (ib > d);
+ return (ib - d == dlen) ? dlen : ib - d + 1;
+ }
+ iconv_close (cd);
+ }
+ else {
+ if (dlen > sizeof (buf1) - m_strlen(tocode))
+ return sizeof (buf1) - m_strlen(tocode) + 1;
+ memcpy (buf1, d, dlen);
+ ob = buf1 + dlen;
+ }
+
+ count = 0;
+ for (p = buf1; p < ob; p++) {
+ unsigned char c = *p;
+
+ assert (strchr (MimeSpecials, '?'));
+ if (c >= 0x7f || c < 0x20 || *p == '_' ||
+ (c != ' ' && strchr (MimeSpecials, *p)))
+ ++count;
+ }
+
+ len = ENCWORD_LEN_MIN - 2 + m_strlen(tocode);
+ len_b = len + (((ob - buf1) + 2) / 3) * 4;
+ len_q = len + (ob - buf1) + 2 * count;
+
+ /* Apparently RFC 1468 says to use B encoding for iso-2022-jp. */
+ if (!ascii_strcasecmp (tocode, "ISO-2022-JP"))
+ len_q = ENCWORD_LEN_MAX + 1;
+
+ if (len_b < len_q && len_b <= ENCWORD_LEN_MAX) {
+ *encoder = b_encoder;
+ *wlen = len_b;
+ return 0;
+ }
+ else if (len_q <= ENCWORD_LEN_MAX) {
+ *encoder = q_encoder;
+ *wlen = len_q;
+ return 0;
+ }
+ else
+ return dlen;
+}
+
+/*
+ * Encode the data (d, dlen) into s using the encoder.
+ * Return the length of the encoded word.
+ */
+static size_t encode_block (char *s, char *d, size_t dlen,
+ const char *fromcode, const char *tocode,
+ encoder_t encoder)
+{
+ char buf1[ENCWORD_LEN_MAX - ENCWORD_LEN_MIN + 1];
+ iconv_t cd;
+ const char *ib;
+ char *ob;
+ size_t ibl, obl, n1, n2;
+
+ if (fromcode) {
+ cd = mutt_iconv_open (tocode, fromcode, 0);
+ assert (cd != (iconv_t) (-1));
+ ib = d, ibl = dlen, ob = buf1, obl = sizeof (buf1) - m_strlen(tocode);
+ n1 = my_iconv(cd, &ib, &ibl, &ob, &obl);
+ n2 = my_iconv(cd, 0, 0, &ob, &obl);
+ assert (n1 != (size_t) (-1) && n2 != (size_t) (-1));
+ iconv_close (cd);
+ return (*encoder) (s, buf1, ob - buf1, tocode);
+ }
+ else
+ return (*encoder) (s, d, dlen, tocode);
+}
+
+/*
+ * Discover how much of the data (d, dlen) can be converted into
+ * a single encoded word. Return how much data can be converted,
+ * and set the length *wlen of the encoded word and *encoder.
+ * We start in column col, which limits the length of the word.
+ */
+static size_t choose_block (char *d, size_t dlen, int col,
+ const char *fromcode, const char *tocode,
+ encoder_t * encoder, size_t * wlen)
+{
+ size_t n, nn;
+ int utf8 = fromcode && !ascii_strcasecmp (fromcode, "UTF-8");
+
+ n = dlen;
+ for (;;) {
+ assert (d + n > d);
+ nn = try_block (d, n, fromcode, tocode, encoder, wlen);
+ if (!nn && (col + *wlen <= ENCWORD_LEN_MAX + 1 || n <= 1))
+ break;
+ n = (nn ? nn : n) - 1;
+ assert (n > 0);
+ if (utf8)
+ while (n > 1 && CONTINUATION_BYTE (d[n]))
+ --n;
+ }
+ return n;
+}
+
+/*
+ * Place the result of RFC-2047-encoding (d, dlen) into the dynamically
+ * allocated buffer (e, elen). The input data is in charset fromcode
+ * and is converted into a charset chosen from charsets.
+ * Return 1 if the conversion to UTF-8 failed, 2 if conversion from UTF-8
+ * failed, otherwise 0. If conversion failed, fromcode is assumed to be
+ * compatible with us-ascii and the original data is used.
+ * The input data is assumed to be a single line starting at column col;
+ * if col is non-zero, the preceding character was a space.
+ */
+static int rfc2047_encode (const char *d, size_t dlen, int col,
+ const char *fromcode, const char *charsets,
+ char **e, size_t * elen, char *specials)
+{
+ int ret = 0;
+ char *buf;
+ size_t bufpos, buflen;
+ char *u, *t0, *t1, *t;
+ char *s0, *s1;
+ size_t ulen, r, n, wlen;
+ encoder_t encoder;
+ char *tocode1 = 0;
+ const char *tocode;
+ const char *icode = "UTF-8";
+
+ /* Try to convert to UTF-8. */
+ if (convert_string(fromcode, d, dlen, icode, &u, &ulen)) {
+ ret = 1;
+ icode = 0;
+ u = p_dupstr(d, ulen = dlen);
+ }
+
+ /* Find earliest and latest things we must encode. */
+ s0 = s1 = t0 = t1 = 0;
+ for (t = u; t < u + ulen; t++) {
+ if ((*t & 0x80) ||
+ (*t == '=' && t[1] == '?' && (t == u || HSPACE (*(t - 1))))) {
+ if (!t0)
+ t0 = t;
+ t1 = t;
+ }
+ else if (specials && strchr (specials, *t)) {
+ if (!s0)
+ s0 = t;
+ s1 = t;
+ }
+ }
+
+ /* If we have something to encode, include RFC822 specials */
+ if (t0 && s0 && s0 < t0)
+ t0 = s0;
+ if (t1 && s1 && s1 > t1)
+ t1 = s1;
+
+ if (!t0) {
+ /* No encoding is required. */
+ *e = u;
+ *elen = ulen;
+ return ret;
+ }
+
+ /* Choose target charset. */
+ tocode = fromcode;
+ if (icode) {
+ if ((tocode1 = mutt_choose_charset (icode, charsets, u, ulen, 0, 0)))
+ tocode = tocode1;
+ else
+ ret = 2, icode = 0;
+ }
+
+ /* Hack to avoid labelling 8-bit data as us-ascii. */
+ if (!icode && mutt_is_us_ascii (tocode))
+ tocode = "unknown-8bit";
+
+ /* Adjust t0 for maximum length of line. */
+ t = u + (ENCWORD_LEN_MAX + 1) - col - ENCWORD_LEN_MIN;
+ if (t < u)
+ t = u;
+ if (t < t0)
+ t0 = t;
+
+
+ /* Adjust t0 until we can encode a character after a space. */
+ for (; t0 > u; t0--) {
+ if (!HSPACE (*(t0 - 1)))
+ continue;
+ t = t0 + 1;
+ if (icode)
+ while (t < u + ulen && CONTINUATION_BYTE (*t))
+ ++t;
+ if (!try_block (t0, t - t0, icode, tocode, &encoder, &wlen) &&
+ col + (t0 - u) + wlen <= ENCWORD_LEN_MAX + 1)
+ break;
+ }
+
+ /* Adjust t1 until we can encode a character before a space. */
+ for (; t1 < u + ulen; t1++) {
+ if (!HSPACE (*t1))
+ continue;
+ t = t1 - 1;
+ if (icode)
+ while (CONTINUATION_BYTE (*t))
+ --t;
+ if (!try_block (t, t1 - t, icode, tocode, &encoder, &wlen) &&
+ 1 + wlen + (u + ulen - t1) <= ENCWORD_LEN_MAX + 1)
+ break;
+ }
+
+ /* We shall encode the region [t0,t1). */
+
+ /* Initialise the output buffer with the us-ascii prefix. */
+ buflen = 2 * ulen;
+ buf = p_new(char, buflen);
+ bufpos = t0 - u;
+ memcpy (buf, u, t0 - u);
+
+ col += t0 - u;
+
+ t = t0;
+ for (;;) {
+ /* Find how much we can encode. */
+ n = choose_block (t, t1 - t, col, icode, tocode, &encoder, &wlen);
+ if (n == t1 - t) {
+ /* See if we can fit the us-ascii suffix, too. */
+ if (col + wlen + (u + ulen - t1) <= ENCWORD_LEN_MAX + 1)
+ break;
+ n = t1 - t - 1;
+ if (icode)
+ while (CONTINUATION_BYTE (t[n]))
+ --n;
+ assert (t + n >= t);
+ if (!n) {
+ /* This should only happen in the really stupid case where the
+ only word that needs encoding is one character long, but
+ there is too much us-ascii stuff after it to use a single
+ encoded word. We add the next word to the encoded region
+ and try again. */
+ assert (t1 < u + ulen);
+ for (t1++; t1 < u + ulen && !HSPACE (*t1); t1++);
+ continue;
+ }
+ n = choose_block (t, n, col, icode, tocode, &encoder, &wlen);
+ }
+
+ /* Add to output buffer. */
+#define LINEBREAK "\n\t"
+ if (bufpos + wlen + m_strlen(LINEBREAK) > buflen) {
+ buflen = bufpos + wlen + m_strlen(LINEBREAK);
+ p_realloc(&buf, buflen);
+ }
+ r = encode_block (buf + bufpos, t, n, icode, tocode, encoder);
+ assert (r == wlen);
+ bufpos += wlen;
+ memcpy (buf + bufpos, LINEBREAK, m_strlen(LINEBREAK));
+ bufpos += m_strlen(LINEBREAK);
+#undef LINEBREAK
+
+ col = 1;
+
+ t += n;
+ }
+
+ /* Add last encoded word and us-ascii suffix to buffer. */
+ buflen = bufpos + wlen + (u + ulen - t1);
+ p_realloc(&buf, buflen + 1);
+ r = encode_block (buf + bufpos, t, t1 - t, icode, tocode, encoder);
+ assert (r == wlen);
+ bufpos += wlen;
+ memcpy (buf + bufpos, t1, u + ulen - t1);
+
+ p_delete(&tocode1);
+ p_delete(&u);
+
+ buf[buflen] = '\0';
+
+ *e = buf;
+ *elen = buflen + 1;
+ return ret;
+}
+
+void _rfc2047_encode_string (char **pd, int encode_specials, int col)
+{
+ char *e;
+ size_t elen;
+ const char *charsets;
+
+ if (!Charset || !*pd)
+ return;
+
+ charsets = SendCharset;
+ if (!charsets || !*charsets)
+ charsets = "UTF-8";
+
+ rfc2047_encode (*pd, m_strlen(*pd), col,
+ Charset, charsets, &e, &elen,
+ encode_specials ? RFC822Specials : NULL);
+
+ p_delete(pd);
+ *pd = e;
+}
+
+void rfc2047_encode_string(char **pd) {
+ _rfc2047_encode_string(a, 0, 32);
+}
+
+void rfc2047_encode_adrlist (address_t * addr, const char *tag)
+{
+ address_t *ptr = addr;
+ int col = tag ? m_strlen(tag) + 2 : 32;
+
+ while (ptr) {
+ if (ptr->personal)
+ _rfc2047_encode_string (&ptr->personal, 1, col);
+ ptr = ptr->next;
+ }
+}
+
+static int rfc2047_decode_word (char *d, const char *s, size_t len)
+{
+ const char *pp, *pp1;
+ char *pd, *d0;
+ const char *t, *t1;
+ int enc = 0, count = 0;
+ char *charset = NULL;
+
+ pd = d0 = p_new(char, m_strlen(s));
+
+ for (pp = s; (pp1 = strchr (pp, '?')); pp = pp1 + 1) {
+ count++;
+ switch (count) {
+ case 2:
+ /* ignore language specification a la RFC 2231 */
+ t = pp1;
+ if ((t1 = memchr (pp, '*', t - pp)))
+ t = t1;
+ charset = p_dupstr(pp, t - pp);
+ break;
+ case 3:
+ if (toupper ((unsigned char) *pp) == 'Q')
+ enc = ENCQUOTEDPRINTABLE;
+ else if (toupper ((unsigned char) *pp) == 'B')
+ enc = ENCBASE64;
+ else {
+ p_delete(&charset);
+ p_delete(&d0);
+ return (-1);
+ }
+ break;
+ case 4:
+ if (enc == ENCQUOTEDPRINTABLE) {
+ for (; pp < pp1; pp++) {
+ if (*pp == '_')
+ *pd++ = ' ';
+ else if (*pp == '=' && hexval(pp[1]) >= 0 && hexval(pp[2]) >= 0) {
+ *pd++ = (hexval (pp[1]) << 4) | hexval (pp[2]);
+ pp += 2;
+ }
+ else
+ *pd++ = *pp;
+ }
+ *pd = 0;
+ }
+ else if (enc == ENCBASE64) {
+ int c, b = 0, k = 0;
+
+ for (; pp < pp1; pp++) {
+ if (*pp == '=')
+ break;
+ if ((c = base64val(*pp)) < 0)
+ continue;
+ if (k + 6 >= 8) {
+ k -= 2;
+ *pd++ = b | (c >> k);
+ b = c << (8 - k);
+ }
+ else {
+ b |= c << (k + 2);
+ k += 6;
+ }
+ }
+ *pd = 0;
+ }
+ break;
+ }
+ }
+
+ if (charset)
+ mutt_convert_string (&d0, charset, Charset, M_ICONV_HOOK_FROM);
+ m_strcpy(d, len, d0);
+ p_delete(&charset);
+ p_delete(&d0);
+ return (0);
+}
+
+/*
+ * Find the start and end of the first encoded word in the string.
+ * We use the grammar in section 2 of RFC 2047, but the "encoding"
+ * must be B or Q. Also, we don't require the encoded word to be
+ * separated by linear-white-space (section 5(1)).
+ */
+static const char *find_encoded_word (const char *s, const char **x)
+{
+ const char *p, *q;
+
+ q = s;
+ while ((p = strstr (q, "=?"))) {
+ for (q = p + 2;
+ 0x20 < *q && *q < 0x7f && !strchr ("()<>@,;:\"/[]?.=", *q); q++);
+ if (q[0] != '?' || !strchr ("BbQq", q[1]) || q[2] != '?')
+ continue;
+ for (q = q + 3; 0x20 <= *q && *q < 0x7f && *q != '?'; q++);
+ if (q[0] != '?' || q[1] != '=') {
+ --q;
+ continue;
+ }
+
+ *x = q + 2;
+ return p;
+ }
+
+ return 0;
+}
+
+/* return length of linear white space */
+static size_t lwslen (const char *s, size_t n)
+{
+ const char *p = s;
+ size_t len = n;
+
+ if (n <= 0)
+ return 0;
+
+ for (; p < s + n; p++)
+ if (!strchr (" \t\r\n", *p)) {
+ len = (size_t) (p - s);
+ break;
+ }
+ if (strchr ("\r\n", *(p - 1))) /* LWS doesn't end with CRLF */
+ len = (size_t) 0;
+ return len;
+}
+
+/* return length of linear white space : reverse */
+static size_t lwsrlen (const char *s, size_t n)
+{
+ const char *p = s + n - 1;
+ size_t len = n;
+
+ if (n <= 0)
+ return 0;
+
+ if (strchr ("\r\n", *p)) /* LWS doesn't end with CRLF */
+ return (size_t) 0;
+
+ for (; p >= s; p--)
+ if (!strchr (" \t\r\n", *p)) {
+ len = (size_t) (s + n - 1 - p);
+ break;
+ }
+ return len;
+}
+
+/* try to decode anything that looks like a valid RFC2047 encoded
+ * header field, ignoring RFC822 parsing rules
+ */
+void rfc2047_decode (char **pd)
+{
+ const char *p, *q;
+ size_t m, n;
+ int found_encoded = 0;
+ char *d0, *d;
+ const char *s = *pd;
+ size_t dlen;
+
+ if (!s || !*s)
+ return;
+
+ dlen = 4 * m_strlen(s); /* should be enough */
+ d = d0 = p_new(char, dlen + 1);
+
+ while (*s && dlen > 0) {
+ if (!(p = find_encoded_word (s, &q))) {
+ /* no encoded words */
+ if (!option (OPTSTRICTMIME)) {
+ n = m_strlen(s);
+ if (found_encoded && (m = lwslen (s, n)) != 0) {
+ if (m != n)
+ *d = ' ', d++, dlen--;
+ n -= m, s += m;
+ }
+ if (ascii_strcasecmp (AssumedCharset, "us-ascii")) {
+ char *t;
+ size_t tlen;
+
+ t = p_dupstr(s, n);
+ if (mutt_convert_nonmime_string (&t) == 0) {
+ tlen = m_strlen(t);
+ strncpy (d, t, tlen);
+ d += tlen;
+ }
+ else {
+ strncpy (d, s, n);
+ d += n;
+ }
+ p_delete(&t);
+ break;
+ }
+ }
+ strncpy (d, s, dlen);
+ d += dlen;
+ break;
+ }
+
+ if (p != s) {
+ n = (size_t) (p - s);
+ /* ignore spaces between encoded words
+ * and linear white spaces between encoded word and *text */
+ if (!option (OPTSTRICTMIME)) {
+ if (found_encoded && (m = lwslen (s, n)) != 0) {
+ if (m != n)
+ *d = ' ', d++, dlen--;
+ n -= m, s += m;
+ }
+
+ if ((m = n - lwsrlen (s, n)) != 0) {
+ if (m > dlen)
+ m = dlen;
+ memcpy (d, s, m);
+ d += m;
+ dlen -= m;
+ if (m != n)
+ *d = ' ', d++, dlen--;
+ }
+ }
+ else if (!found_encoded || strspn (s, " \t\r\n") != n) {
+ if (n > dlen)
+ n = dlen;
+ memcpy (d, s, n);
+ d += n;
+ dlen -= n;
+ }
+ }
+
+ rfc2047_decode_word (d, p, dlen);
+ found_encoded = 1;
+ s = q;
+ n = m_strlen(d);
+ dlen -= n;
+ d += n;
+ }
+ *d = 0;
+
+ p_delete(pd);
+ *pd = d0;
+ str_adjust (pd);
+}
+
+void rfc2047_decode_adrlist (address_t * a)
+{
+ while (a) {
+ if (a->personal)
+ rfc2047_decode (&a->personal);
+ a = a->next;
+ }
+}
+
+void rfc2047_decode_envelope (ENVELOPE* e) {
+
+ if (!e)
+ return;
+
+ /* do RFC2047 decoding */
+ rfc2047_decode_adrlist (e->from);
+ rfc2047_decode_adrlist (e->to);
+ rfc2047_decode_adrlist (e->cc);
+ rfc2047_decode_adrlist (e->bcc);
+ rfc2047_decode_adrlist (e->reply_to);
+ rfc2047_decode_adrlist (e->mail_followup_to);
+ rfc2047_decode_adrlist (e->return_path);
+ rfc2047_decode_adrlist (e->sender);
+
+ if (e->subject) {
+ rfc2047_decode (&e->subject);
+ mutt_adjust_subject (e);
+ }
+}
#include "str.h"
-void str_replace (char **p, const char *s)
-{
- p_delete(p);
- *p = m_strdup(s);
-}
-
void str_adjust (char **p)
{
if (!p || !*p)
char *str_tolower (char*);
char *str_substrcpy (char*, const char*, const char*, size_t);
char *str_substrdup (const char*, const char*);
-void str_replace (char**, const char*);
void str_adjust (char**);
int str_eq (const char*, const char*);
const char *str_isstr (const char*, const char*);
break;
case 'F':
- str_replace (&Muttrc, optarg);
+ m_strreplace(&Muttrc, optarg);
break;
case 'f':
#endif
mutt_expand_path (folder, sizeof (folder));
- str_replace (&CurrentFolder, folder);
- str_replace (&LastFolder, folder);
+ m_strreplace(&CurrentFolder, folder);
+ m_strreplace(&LastFolder, folder);
if (flags & M_IGNORE) {
/* check to see if there are any messages in the folder */
_("Reverse search for: "),
buf, sizeof (buf), M_CLEAR) != 0 || !buf[0])
return (-1);
- str_replace (&menu->searchBuf, buf);
+ m_strreplace(&menu->searchBuf, buf);
menu->searchDir = (op == OP_SEARCH) ? M_SEARCH_DOWN : M_SEARCH_UP;
}
else {
if ((p = strrchr (path, ':')) != NULL && m_strncmp(p + 1, "2,", 2) == 0) {
p += 3;
- str_replace (&h->maildir_flags, p);
+ m_strreplace(&h->maildir_flags, p);
q = h->maildir_flags;
while (*p) {
if (safe_rename (msg->path, full) == 0) {
if (hdr)
- str_replace (&hdr->path, path);
+ m_strreplace(&hdr->path, path);
p_delete(&msg->path);
/*
snprintf (path, sizeof (path), "%s/%s", ctx->path, tmp);
if (safe_rename (msg->path, path) == 0) {
if (hdr)
- str_replace (&hdr->path, tmp);
+ m_strreplace(&hdr->path, tmp);
p_delete(&msg->path);
break;
}
if (ctx->magic == M_MH && rc == 0) {
snprintf (newpath, _POSIX_PATH_MAX, "%s/%s", ctx->path, h->path);
if ((rc = safe_rename (newpath, oldpath)) == 0)
- str_replace (&h->path, partpath);
+ m_strreplace(&h->path, partpath);
}
}
else
mutt_perror ("rename");
return (-1);
}
- str_replace (&h->path, partpath);
+ m_strreplace(&h->path, partpath);
}
return (0);
}
* subdirectory. If so, update the associated filename.
*/
if (m_strcmp(ctx->hdrs[i]->path, p->h->path))
- str_replace (&ctx->hdrs[i]->path, p->h->path);
+ m_strreplace(&ctx->hdrs[i]->path, p->h->path);
/* if the user hasn't modified the flags on this message, update
* the flags we just detected.
for (q = *p; q; q = q->next) {
if (ascii_strcasecmp (attribute, q->attribute) == 0) {
- str_replace (&q->value, value);
+ m_strreplace(&q->value, value);
return;
}
}
(_("File is a directory, save under it? [(y)es, (n)o, (a)ll]"),
_("yna"))) {
case 3: /* all */
- str_replace (directory, fname);
+ m_strreplace(directory, fname);
break;
case 1: /* yes */
p_delete(directory);
s = vskipspaces(s + 1);
if ((s = mutt_get_parameter("filename",
(parms = parse_parameters (s)))) != 0)
- str_replace (&ct->filename, s);
+ m_strreplace(&ct->filename, s);
if ((s = mutt_get_parameter ("name", parms)) != 0)
ct->form_name = m_strdup(s);
mutt_free_parameter (&parms);
else if (!ascii_strcasecmp ("disposition", line + 8))
parse_content_disposition (c, p);
else if (!ascii_strcasecmp ("description", line + 8)) {
- str_replace (&p->description, c);
+ m_strreplace(&p->description, c);
rfc2047_decode (&p->description);
}
}
else if (!ascii_strcasecmp ("content-lines", line + 6))
mutt_set_parameter ("content-lines", c, &(p->parameter));
else if (!ascii_strcasecmp ("data-description", line + 6)) {
- str_replace (&p->description, c);
+ m_strreplace(&p->description, c);
rfc2047_decode (&p->description);
}
}
/* try to recover from parsing error */
if (!b->parts) {
b->type = TYPETEXT;
- str_replace (&b->subtype, "plain");
+ m_strreplace(&b->subtype, "plain");
}
}
}
else if (ascii_strcasecmp (line + 8, "description") == 0) {
if (hdr) {
- str_replace (&hdr->content->description, p);
+ m_strreplace(&hdr->content->description, p);
rfc2047_decode (&hdr->content->description);
}
matched = 1;
case 'd':
if (!ascii_strcasecmp ("ate", line + 1)) {
- str_replace (&e->date, p);
+ m_strreplace(&e->date, p);
if (hdr)
hdr->date_sent = mutt_parse_date (p, hdr);
matched = 1;
pgp_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN,
PGP_PUBRING))) {
snprintf (input_signas, sizeof (input_signas), "0x%s", pgp_keyid (p));
- str_replace (&PgpSignAs, input_signas);
+ m_strreplace(&PgpSignAs, input_signas);
pgp_free_key (&p);
msg->security |= SIGN;
if (whatfor) {
if (l)
- str_replace (&l->dflt, resp);
+ m_strreplace(&l->dflt, resp);
else {
l = p_new(struct pgp_cache, 1);
l->next = id_defaults;
/* the cryptalg field must not be empty */
if ((WithCrypto & APPLICATION_SMIME) && *smime_cryptalg)
- str_replace (&SmimeCryptAlg, smime_cryptalg);
+ m_strreplace(&SmimeCryptAlg, smime_cryptalg);
if ((WithCrypto & APPLICATION_PGP) && (set_signas || *pgp_sign_as))
- str_replace (&PgpSignAs, pgp_sign_as);
+ m_strreplace(&PgpSignAs, pgp_sign_as);
return pgp;
}
newhdr->security |= mutt_is_application_pgp (newhdr->content);
b->type = TYPETEXT;
- str_replace (&b->subtype, "plain");
+ m_strreplace(&b->subtype, "plain");
mutt_delete_parameter ("x-action", &b->parameter);
}
else
if (safe_fclose (&s.fpout) != 0)
goto bail;
- str_replace (&b->filename, file);
+ m_strreplace(&b->filename, file);
b->unlink = 1;
mutt_stamp_attachment (b);
if (idx[x]->tree) {
if (m_strcmp(idx[x]->tree, buf) != 0)
- str_replace (&idx[x]->tree, buf);
+ m_strreplace(&idx[x]->tree, buf);
}
else
idx[x]->tree = m_strdup(buf);
if (*field == '=') {
if (entry) {
field = vskipspaces(field + 1);
- str_replace (entry, field);
+ m_strreplace(entry, field);
}
return 1;
}
+++ /dev/null
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- *
- * Copyright © 2006 Pierre Habouzit
- */
-
-/*
- * Copyright notice from original mutt:
- * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
- * Copyright (C) 2000-2001 Edmund Grimley Evans <edmundo@rano.org>
- *
- * This file is part of mutt-ng, see http://www.muttng.org/.
- * It's licensed under the GNU General Public License,
- * please see the file GPL in the top level source directory.
- */
-
-#if HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <lib-lib/mem.h>
-#include <lib-lib/str.h>
-#include <lib-lib/ascii.h>
-
-#include <lib-mime/mime.h>
-
-#include "mutt.h"
-#include "charset.h"
-#include "thread.h"
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* If you are debugging this file, comment out the following line. */
-/*#define NDEBUG*/
-
-#ifdef NDEBUG
-#define assert(x)
-#else
-#include <assert.h>
-#endif
-
-#define ENCWORD_LEN_MAX 75
-#define ENCWORD_LEN_MIN 9 /* m_strlen("=?.?.?.?=") */
-
-#define HSPACE(x) ((x) == '\0' || (x) == ' ' || (x) == '\t')
-
-#define CONTINUATION_BYTE(c) (((c) & 0xc0) == 0x80)
-
-typedef size_t (*encoder_t) (char *, const char *, size_t,
- const char *);
-
-static size_t convert_string (const char *f, size_t flen,
- const char *from, const char *to,
- char **t, size_t * tlen)
-{
- iconv_t cd;
- char *buf, *ob;
- size_t obl, n;
- int e;
-
- cd = mutt_iconv_open (to, from, 0);
- if (cd == (iconv_t) (-1))
- return (size_t) (-1);
- obl = 4 * flen + 1;
- ob = buf = p_new(char, obl);
- n = my_iconv(cd, &f, &flen, &ob, &obl);
- if (n == (size_t) (-1) || my_iconv(cd, 0, 0, &ob, &obl) == (size_t) (-1)) {
- e = errno;
- p_delete(&buf);
- iconv_close (cd);
- errno = e;
- return (size_t) (-1);
- }
- *ob = '\0';
-
- *tlen = ob - buf;
-
- p_realloc(&buf, ob - buf + 1);
- *t = buf;
- iconv_close (cd);
-
- return n;
-}
-
-char *mutt_choose_charset (const char *fromcode, const char *charsets,
- char *u, size_t ulen, char **d, size_t * dlen)
-{
- char canonical_buff[LONG_STRING];
- char *e = 0, *tocode = 0;
- size_t elen = 0, bestn = 0;
- const char *p, *q;
-
- for (p = charsets; p; p = q ? q + 1 : 0) {
- char *s, *t;
- size_t slen, n;
-
- q = strchr (p, ':');
-
- n = q ? q - p : m_strlen(p);
-
- if (!n ||
- /* Assume that we never need more than 12 characters of
- encoded-text to encode a single character. */
- n > (ENCWORD_LEN_MAX - ENCWORD_LEN_MIN + 2 - 12))
- continue;
-
- t = p_dupstr(p, n);
-
- n = convert_string (u, ulen, fromcode, t, &s, &slen);
- if (n == (size_t) (-1))
- continue;
-
- if (!tocode || n < bestn) {
- bestn = n;
- p_delete(&tocode);
- tocode = t;
- if (d) {
- p_delete(&e);
- e = s;
- }
- else
- p_delete(&s);
- elen = slen;
- if (!bestn)
- break;
- }
- else {
- p_delete(&t);
- p_delete(&s);
- }
- }
- if (tocode) {
- if (d)
- *d = e;
- if (dlen)
- *dlen = elen;
-
- mutt_canonical_charset (canonical_buff, sizeof (canonical_buff), tocode);
- str_replace (&tocode, canonical_buff);
- }
- return tocode;
-}
-
-static size_t b_encoder (char *s, const char *d, size_t dlen,
- const char *tocode)
-{
- char *s0 = s;
-
- memcpy (s, "=?", 2), s += 2;
- memcpy (s, tocode, m_strlen(tocode)), s += m_strlen(tocode);
- memcpy (s, "?B?", 3), s += 3;
- for (;;) {
- if (!dlen)
- break;
- else if (dlen == 1) {
- *s++ = __m_b64chars[(*d >> 2) & 0x3f];
- *s++ = __m_b64chars[(*d & 0x03) << 4];
- *s++ = '=';
- *s++ = '=';
- break;
- }
- else if (dlen == 2) {
- *s++ = __m_b64chars[(*d >> 2) & 0x3f];
- *s++ = __m_b64chars[((*d & 0x03) << 4) | ((d[1] >> 4) & 0x0f)];
- *s++ = __m_b64chars[(d[1] & 0x0f) << 2];
- *s++ = '=';
- break;
- }
- else {
- *s++ = __m_b64chars[(*d >> 2) & 0x3f];
- *s++ = __m_b64chars[((*d & 0x03) << 4) | ((d[1] >> 4) & 0x0f)];
- *s++ = __m_b64chars[((d[1] & 0x0f) << 2) | ((d[2] >> 6) & 0x03)];
- *s++ = __m_b64chars[d[2] & 0x3f];
- d += 3, dlen -= 3;
- }
- }
- memcpy (s, "?=", 2), s += 2;
- return s - s0;
-}
-
-static size_t q_encoder (char *s, const char *d, size_t dlen,
- const char *tocode)
-{
- char hex[] = "0123456789ABCDEF";
- char *s0 = s;
-
- memcpy (s, "=?", 2), s += 2;
- memcpy (s, tocode, m_strlen(tocode)), s += m_strlen(tocode);
- memcpy (s, "?Q?", 3), s += 3;
- while (dlen--) {
- unsigned char c = *d++;
-
- if (c == ' ')
- *s++ = '_';
- else if (c >= 0x7f || c < 0x20 || c == '_' || strchr (MimeSpecials, c)) {
- *s++ = '=';
- *s++ = hex[(c & 0xf0) >> 4];
- *s++ = hex[c & 0x0f];
- }
- else
- *s++ = c;
- }
- memcpy (s, "?=", 2), s += 2;
- return s - s0;
-}
-
-/*
- * Return 0 if and set *encoder and *wlen if the data (d, dlen) could
- * be converted to an encoded word of length *wlen using *encoder.
- * Otherwise return an upper bound on the maximum length of the data
- * which could be converted.
- * The data is converted from fromcode (which must be stateless) to
- * tocode, unless fromcode is 0, in which case the data is assumed to
- * be already in tocode, which should be 8-bit and stateless.
- */
-static size_t try_block (const char *d, size_t dlen,
- const char *fromcode, const char *tocode,
- encoder_t * encoder, size_t * wlen)
-{
- char buf1[ENCWORD_LEN_MAX - ENCWORD_LEN_MIN + 1];
- iconv_t cd;
- const char *ib;
- char *ob, *p;
- size_t ibl, obl;
- int count, len, len_b, len_q;
-
- if (fromcode) {
- cd = mutt_iconv_open (tocode, fromcode, 0);
- assert (cd != (iconv_t) (-1));
- ib = d, ibl = dlen, ob = buf1, obl = sizeof (buf1) - m_strlen(tocode);
- if (my_iconv(cd, &ib, &ibl, &ob, &obl) == (size_t) (-1) ||
- my_iconv(cd, 0, 0, &ob, &obl) == (size_t) (-1)) {
- assert (errno == E2BIG);
- iconv_close (cd);
- assert (ib > d);
- return (ib - d == dlen) ? dlen : ib - d + 1;
- }
- iconv_close (cd);
- }
- else {
- if (dlen > sizeof (buf1) - m_strlen(tocode))
- return sizeof (buf1) - m_strlen(tocode) + 1;
- memcpy (buf1, d, dlen);
- ob = buf1 + dlen;
- }
-
- count = 0;
- for (p = buf1; p < ob; p++) {
- unsigned char c = *p;
-
- assert (strchr (MimeSpecials, '?'));
- if (c >= 0x7f || c < 0x20 || *p == '_' ||
- (c != ' ' && strchr (MimeSpecials, *p)))
- ++count;
- }
-
- len = ENCWORD_LEN_MIN - 2 + m_strlen(tocode);
- len_b = len + (((ob - buf1) + 2) / 3) * 4;
- len_q = len + (ob - buf1) + 2 * count;
-
- /* Apparently RFC 1468 says to use B encoding for iso-2022-jp. */
- if (!ascii_strcasecmp (tocode, "ISO-2022-JP"))
- len_q = ENCWORD_LEN_MAX + 1;
-
- if (len_b < len_q && len_b <= ENCWORD_LEN_MAX) {
- *encoder = b_encoder;
- *wlen = len_b;
- return 0;
- }
- else if (len_q <= ENCWORD_LEN_MAX) {
- *encoder = q_encoder;
- *wlen = len_q;
- return 0;
- }
- else
- return dlen;
-}
-
-/*
- * Encode the data (d, dlen) into s using the encoder.
- * Return the length of the encoded word.
- */
-static size_t encode_block (char *s, char *d, size_t dlen,
- const char *fromcode, const char *tocode,
- encoder_t encoder)
-{
- char buf1[ENCWORD_LEN_MAX - ENCWORD_LEN_MIN + 1];
- iconv_t cd;
- const char *ib;
- char *ob;
- size_t ibl, obl, n1, n2;
-
- if (fromcode) {
- cd = mutt_iconv_open (tocode, fromcode, 0);
- assert (cd != (iconv_t) (-1));
- ib = d, ibl = dlen, ob = buf1, obl = sizeof (buf1) - m_strlen(tocode);
- n1 = my_iconv(cd, &ib, &ibl, &ob, &obl);
- n2 = my_iconv(cd, 0, 0, &ob, &obl);
- assert (n1 != (size_t) (-1) && n2 != (size_t) (-1));
- iconv_close (cd);
- return (*encoder) (s, buf1, ob - buf1, tocode);
- }
- else
- return (*encoder) (s, d, dlen, tocode);
-}
-
-/*
- * Discover how much of the data (d, dlen) can be converted into
- * a single encoded word. Return how much data can be converted,
- * and set the length *wlen of the encoded word and *encoder.
- * We start in column col, which limits the length of the word.
- */
-static size_t choose_block (char *d, size_t dlen, int col,
- const char *fromcode, const char *tocode,
- encoder_t * encoder, size_t * wlen)
-{
- size_t n, nn;
- int utf8 = fromcode && !ascii_strcasecmp (fromcode, "UTF-8");
-
- n = dlen;
- for (;;) {
- assert (d + n > d);
- nn = try_block (d, n, fromcode, tocode, encoder, wlen);
- if (!nn && (col + *wlen <= ENCWORD_LEN_MAX + 1 || n <= 1))
- break;
- n = (nn ? nn : n) - 1;
- assert (n > 0);
- if (utf8)
- while (n > 1 && CONTINUATION_BYTE (d[n]))
- --n;
- }
- return n;
-}
-
-/*
- * Place the result of RFC-2047-encoding (d, dlen) into the dynamically
- * allocated buffer (e, elen). The input data is in charset fromcode
- * and is converted into a charset chosen from charsets.
- * Return 1 if the conversion to UTF-8 failed, 2 if conversion from UTF-8
- * failed, otherwise 0. If conversion failed, fromcode is assumed to be
- * compatible with us-ascii and the original data is used.
- * The input data is assumed to be a single line starting at column col;
- * if col is non-zero, the preceding character was a space.
- */
-static int rfc2047_encode (const char *d, size_t dlen, int col,
- const char *fromcode, const char *charsets,
- char **e, size_t * elen, char *specials)
-{
- int ret = 0;
- char *buf;
- size_t bufpos, buflen;
- char *u, *t0, *t1, *t;
- char *s0, *s1;
- size_t ulen, r, n, wlen;
- encoder_t encoder;
- char *tocode1 = 0;
- const char *tocode;
- const char *icode = "UTF-8";
-
- /* Try to convert to UTF-8. */
- if (convert_string (d, dlen, fromcode, icode, &u, &ulen)) {
- ret = 1;
- icode = 0;
- u = p_dupstr(d, ulen = dlen);
- }
-
- /* Find earliest and latest things we must encode. */
- s0 = s1 = t0 = t1 = 0;
- for (t = u; t < u + ulen; t++) {
- if ((*t & 0x80) ||
- (*t == '=' && t[1] == '?' && (t == u || HSPACE (*(t - 1))))) {
- if (!t0)
- t0 = t;
- t1 = t;
- }
- else if (specials && strchr (specials, *t)) {
- if (!s0)
- s0 = t;
- s1 = t;
- }
- }
-
- /* If we have something to encode, include RFC822 specials */
- if (t0 && s0 && s0 < t0)
- t0 = s0;
- if (t1 && s1 && s1 > t1)
- t1 = s1;
-
- if (!t0) {
- /* No encoding is required. */
- *e = u;
- *elen = ulen;
- return ret;
- }
-
- /* Choose target charset. */
- tocode = fromcode;
- if (icode) {
- if ((tocode1 = mutt_choose_charset (icode, charsets, u, ulen, 0, 0)))
- tocode = tocode1;
- else
- ret = 2, icode = 0;
- }
-
- /* Hack to avoid labelling 8-bit data as us-ascii. */
- if (!icode && mutt_is_us_ascii (tocode))
- tocode = "unknown-8bit";
-
- /* Adjust t0 for maximum length of line. */
- t = u + (ENCWORD_LEN_MAX + 1) - col - ENCWORD_LEN_MIN;
- if (t < u)
- t = u;
- if (t < t0)
- t0 = t;
-
-
- /* Adjust t0 until we can encode a character after a space. */
- for (; t0 > u; t0--) {
- if (!HSPACE (*(t0 - 1)))
- continue;
- t = t0 + 1;
- if (icode)
- while (t < u + ulen && CONTINUATION_BYTE (*t))
- ++t;
- if (!try_block (t0, t - t0, icode, tocode, &encoder, &wlen) &&
- col + (t0 - u) + wlen <= ENCWORD_LEN_MAX + 1)
- break;
- }
-
- /* Adjust t1 until we can encode a character before a space. */
- for (; t1 < u + ulen; t1++) {
- if (!HSPACE (*t1))
- continue;
- t = t1 - 1;
- if (icode)
- while (CONTINUATION_BYTE (*t))
- --t;
- if (!try_block (t, t1 - t, icode, tocode, &encoder, &wlen) &&
- 1 + wlen + (u + ulen - t1) <= ENCWORD_LEN_MAX + 1)
- break;
- }
-
- /* We shall encode the region [t0,t1). */
-
- /* Initialise the output buffer with the us-ascii prefix. */
- buflen = 2 * ulen;
- buf = p_new(char, buflen);
- bufpos = t0 - u;
- memcpy (buf, u, t0 - u);
-
- col += t0 - u;
-
- t = t0;
- for (;;) {
- /* Find how much we can encode. */
- n = choose_block (t, t1 - t, col, icode, tocode, &encoder, &wlen);
- if (n == t1 - t) {
- /* See if we can fit the us-ascii suffix, too. */
- if (col + wlen + (u + ulen - t1) <= ENCWORD_LEN_MAX + 1)
- break;
- n = t1 - t - 1;
- if (icode)
- while (CONTINUATION_BYTE (t[n]))
- --n;
- assert (t + n >= t);
- if (!n) {
- /* This should only happen in the really stupid case where the
- only word that needs encoding is one character long, but
- there is too much us-ascii stuff after it to use a single
- encoded word. We add the next word to the encoded region
- and try again. */
- assert (t1 < u + ulen);
- for (t1++; t1 < u + ulen && !HSPACE (*t1); t1++);
- continue;
- }
- n = choose_block (t, n, col, icode, tocode, &encoder, &wlen);
- }
-
- /* Add to output buffer. */
-#define LINEBREAK "\n\t"
- if (bufpos + wlen + m_strlen(LINEBREAK) > buflen) {
- buflen = bufpos + wlen + m_strlen(LINEBREAK);
- p_realloc(&buf, buflen);
- }
- r = encode_block (buf + bufpos, t, n, icode, tocode, encoder);
- assert (r == wlen);
- bufpos += wlen;
- memcpy (buf + bufpos, LINEBREAK, m_strlen(LINEBREAK));
- bufpos += m_strlen(LINEBREAK);
-#undef LINEBREAK
-
- col = 1;
-
- t += n;
- }
-
- /* Add last encoded word and us-ascii suffix to buffer. */
- buflen = bufpos + wlen + (u + ulen - t1);
- p_realloc(&buf, buflen + 1);
- r = encode_block (buf + bufpos, t, t1 - t, icode, tocode, encoder);
- assert (r == wlen);
- bufpos += wlen;
- memcpy (buf + bufpos, t1, u + ulen - t1);
-
- p_delete(&tocode1);
- p_delete(&u);
-
- buf[buflen] = '\0';
-
- *e = buf;
- *elen = buflen + 1;
- return ret;
-}
-
-void _rfc2047_encode_string (char **pd, int encode_specials, int col)
-{
- char *e;
- size_t elen;
- const char *charsets;
-
- if (!Charset || !*pd)
- return;
-
- charsets = SendCharset;
- if (!charsets || !*charsets)
- charsets = "UTF-8";
-
- rfc2047_encode (*pd, m_strlen(*pd), col,
- Charset, charsets, &e, &elen,
- encode_specials ? RFC822Specials : NULL);
-
- p_delete(pd);
- *pd = e;
-}
-
-void rfc2047_encode_adrlist (address_t * addr, const char *tag)
-{
- address_t *ptr = addr;
- int col = tag ? m_strlen(tag) + 2 : 32;
-
- while (ptr) {
- if (ptr->personal)
- _rfc2047_encode_string (&ptr->personal, 1, col);
- ptr = ptr->next;
- }
-}
-
-static int rfc2047_decode_word (char *d, const char *s, size_t len)
-{
- const char *pp, *pp1;
- char *pd, *d0;
- const char *t, *t1;
- int enc = 0, count = 0;
- char *charset = NULL;
-
- pd = d0 = p_new(char, m_strlen(s));
-
- for (pp = s; (pp1 = strchr (pp, '?')); pp = pp1 + 1) {
- count++;
- switch (count) {
- case 2:
- /* ignore language specification a la RFC 2231 */
- t = pp1;
- if ((t1 = memchr (pp, '*', t - pp)))
- t = t1;
- charset = p_dupstr(pp, t - pp);
- break;
- case 3:
- if (toupper ((unsigned char) *pp) == 'Q')
- enc = ENCQUOTEDPRINTABLE;
- else if (toupper ((unsigned char) *pp) == 'B')
- enc = ENCBASE64;
- else {
- p_delete(&charset);
- p_delete(&d0);
- return (-1);
- }
- break;
- case 4:
- if (enc == ENCQUOTEDPRINTABLE) {
- for (; pp < pp1; pp++) {
- if (*pp == '_')
- *pd++ = ' ';
- else if (*pp == '=' && hexval(pp[1]) >= 0 && hexval(pp[2]) >= 0) {
- *pd++ = (hexval (pp[1]) << 4) | hexval (pp[2]);
- pp += 2;
- }
- else
- *pd++ = *pp;
- }
- *pd = 0;
- }
- else if (enc == ENCBASE64) {
- int c, b = 0, k = 0;
-
- for (; pp < pp1; pp++) {
- if (*pp == '=')
- break;
- if ((c = base64val(*pp)) < 0)
- continue;
- if (k + 6 >= 8) {
- k -= 2;
- *pd++ = b | (c >> k);
- b = c << (8 - k);
- }
- else {
- b |= c << (k + 2);
- k += 6;
- }
- }
- *pd = 0;
- }
- break;
- }
- }
-
- if (charset)
- mutt_convert_string (&d0, charset, Charset, M_ICONV_HOOK_FROM);
- m_strcpy(d, len, d0);
- p_delete(&charset);
- p_delete(&d0);
- return (0);
-}
-
-/*
- * Find the start and end of the first encoded word in the string.
- * We use the grammar in section 2 of RFC 2047, but the "encoding"
- * must be B or Q. Also, we don't require the encoded word to be
- * separated by linear-white-space (section 5(1)).
- */
-static const char *find_encoded_word (const char *s, const char **x)
-{
- const char *p, *q;
-
- q = s;
- while ((p = strstr (q, "=?"))) {
- for (q = p + 2;
- 0x20 < *q && *q < 0x7f && !strchr ("()<>@,;:\"/[]?.=", *q); q++);
- if (q[0] != '?' || !strchr ("BbQq", q[1]) || q[2] != '?')
- continue;
- for (q = q + 3; 0x20 <= *q && *q < 0x7f && *q != '?'; q++);
- if (q[0] != '?' || q[1] != '=') {
- --q;
- continue;
- }
-
- *x = q + 2;
- return p;
- }
-
- return 0;
-}
-
-/* return length of linear white space */
-static size_t lwslen (const char *s, size_t n)
-{
- const char *p = s;
- size_t len = n;
-
- if (n <= 0)
- return 0;
-
- for (; p < s + n; p++)
- if (!strchr (" \t\r\n", *p)) {
- len = (size_t) (p - s);
- break;
- }
- if (strchr ("\r\n", *(p - 1))) /* LWS doesn't end with CRLF */
- len = (size_t) 0;
- return len;
-}
-
-/* return length of linear white space : reverse */
-static size_t lwsrlen (const char *s, size_t n)
-{
- const char *p = s + n - 1;
- size_t len = n;
-
- if (n <= 0)
- return 0;
-
- if (strchr ("\r\n", *p)) /* LWS doesn't end with CRLF */
- return (size_t) 0;
-
- for (; p >= s; p--)
- if (!strchr (" \t\r\n", *p)) {
- len = (size_t) (s + n - 1 - p);
- break;
- }
- return len;
-}
-
-/* try to decode anything that looks like a valid RFC2047 encoded
- * header field, ignoring RFC822 parsing rules
- */
-void rfc2047_decode (char **pd)
-{
- const char *p, *q;
- size_t m, n;
- int found_encoded = 0;
- char *d0, *d;
- const char *s = *pd;
- size_t dlen;
-
- if (!s || !*s)
- return;
-
- dlen = 4 * m_strlen(s); /* should be enough */
- d = d0 = p_new(char, dlen + 1);
-
- while (*s && dlen > 0) {
- if (!(p = find_encoded_word (s, &q))) {
- /* no encoded words */
- if (!option (OPTSTRICTMIME)) {
- n = m_strlen(s);
- if (found_encoded && (m = lwslen (s, n)) != 0) {
- if (m != n)
- *d = ' ', d++, dlen--;
- n -= m, s += m;
- }
- if (ascii_strcasecmp (AssumedCharset, "us-ascii")) {
- char *t;
- size_t tlen;
-
- t = p_dupstr(s, n);
- if (mutt_convert_nonmime_string (&t) == 0) {
- tlen = m_strlen(t);
- strncpy (d, t, tlen);
- d += tlen;
- }
- else {
- strncpy (d, s, n);
- d += n;
- }
- p_delete(&t);
- break;
- }
- }
- strncpy (d, s, dlen);
- d += dlen;
- break;
- }
-
- if (p != s) {
- n = (size_t) (p - s);
- /* ignore spaces between encoded words
- * and linear white spaces between encoded word and *text */
- if (!option (OPTSTRICTMIME)) {
- if (found_encoded && (m = lwslen (s, n)) != 0) {
- if (m != n)
- *d = ' ', d++, dlen--;
- n -= m, s += m;
- }
-
- if ((m = n - lwsrlen (s, n)) != 0) {
- if (m > dlen)
- m = dlen;
- memcpy (d, s, m);
- d += m;
- dlen -= m;
- if (m != n)
- *d = ' ', d++, dlen--;
- }
- }
- else if (!found_encoded || strspn (s, " \t\r\n") != n) {
- if (n > dlen)
- n = dlen;
- memcpy (d, s, n);
- d += n;
- dlen -= n;
- }
- }
-
- rfc2047_decode_word (d, p, dlen);
- found_encoded = 1;
- s = q;
- n = m_strlen(d);
- dlen -= n;
- d += n;
- }
- *d = 0;
-
- p_delete(pd);
- *pd = d0;
- str_adjust (pd);
-}
-
-void rfc2047_decode_adrlist (address_t * a)
-{
- while (a) {
- if (a->personal)
- rfc2047_decode (&a->personal);
- a = a->next;
- }
-}
-
-void rfc2047_decode_envelope (ENVELOPE* e) {
-
- if (!e)
- return;
-
- /* do RFC2047 decoding */
- rfc2047_decode_adrlist (e->from);
- rfc2047_decode_adrlist (e->to);
- rfc2047_decode_adrlist (e->cc);
- rfc2047_decode_adrlist (e->bcc);
- rfc2047_decode_adrlist (e->reply_to);
- rfc2047_decode_adrlist (e->mail_followup_to);
- rfc2047_decode_adrlist (e->return_path);
- rfc2047_decode_adrlist (e->sender);
-
- if (e->subject) {
- rfc2047_decode (&e->subject);
- mutt_adjust_subject (e);
- }
-}
fclose (out);
mutt_set_mtime (hdr->content->filename, tmpfile);
unlink (hdr->content->filename);
- str_replace (&hdr->content->filename, tmpfile);
+ m_strreplace(&hdr->content->filename, tmpfile);
}
return (-1);
}
- str_replace (&en->subject, buf);
+ m_strreplace(&en->subject, buf);
return 0;
}
env->reply_to = rfc822_parse_adrlist (env->reply_to, uh->data + 9);
}
else if (ascii_strncasecmp ("message-id:", uh->data, 11) == 0)
- str_replace (&env->message_id, uh->data + 11);
+ m_strreplace(&env->message_id, uh->data + 11);
else if (ascii_strncasecmp ("to:", uh->data, 3) != 0 &&
ascii_strncasecmp ("cc:", uh->data, 3) != 0 &&
ascii_strncasecmp ("bcc:", uh->data, 4) != 0 &&
/* set the default subject for the message. */
mutt_make_string (buffer, sizeof (buffer), NONULL (ForwFmt), ctx, cur);
- str_replace (&env->subject, buffer);
+ m_strreplace(&env->subject, buffer);
}
void mutt_make_misc_reply_headers (ENVELOPE * env, CONTEXT * ctx,
if (type != TYPEOTHER || *xtype != '\0') {
att->type = type;
- str_replace (&att->subtype, subtype);
- str_replace (&att->xtype, xtype);
+ m_strreplace(&att->subtype, subtype);
+ m_strreplace(&att->xtype, xtype);
}
return (type);
switch (choice = mutt_multi_choice (_("1: DES, 2: Triple-DES "),
_("dt"))) {
case 1:
- str_replace (&SmimeCryptAlg, "des");
+ m_strreplace(&SmimeCryptAlg, "des");
break;
case 2:
- str_replace (&SmimeCryptAlg, "des3");
+ m_strreplace(&SmimeCryptAlg, "des3");
break;
}
break;
switch (choice = mutt_multi_choice (_("1: RC2-40, 2: RC2-64, 3: RC2-128 "),
_("468"))) {
case 1:
- str_replace (&SmimeCryptAlg, "rc2-40");
+ m_strreplace(&SmimeCryptAlg, "rc2-40");
break;
case 2:
- str_replace (&SmimeCryptAlg, "rc2-64");
+ m_strreplace(&SmimeCryptAlg, "rc2-64");
break;
case 3:
- str_replace (&SmimeCryptAlg, "rc2-128");
+ m_strreplace(&SmimeCryptAlg, "rc2-128");
break;
}
break;
switch (choice = mutt_multi_choice (_("1: AES128, 2: AES192, 3: AES256 "),
_("895"))) {
case 1:
- str_replace (&SmimeCryptAlg, "aes128");
+ m_strreplace(&SmimeCryptAlg, "aes128");
break;
case 2:
- str_replace (&SmimeCryptAlg, "aes192");
+ m_strreplace(&SmimeCryptAlg, "aes192");
break;
case 3:
- str_replace (&SmimeCryptAlg, "aes256");
+ m_strreplace(&SmimeCryptAlg, "aes256");
break;
}
break;
case 4: /* sign (a)s */
if ((p = smime_ask_for_key (_("Sign as: "), NULL, 0))) {
- str_replace (&SmimeDefaultKey, p);
+ m_strreplace(&SmimeDefaultKey, p);
msg->security |= SIGN;
if (!ascii_strcasecmp (tag, "body")) {
if (body)
- str_replace (body, value);
+ m_strreplace(body, value);
}
else {
#define SAFEPFX (option (OPTSTRICTMAILTO) ? "" : "X-Mailto-")