/*
* Copyright (C) 1996-2000,2010 Michael R. Elkins <me@mutt.org>
* Copyright (C) 2000-2002 Edmund Grimley Evans <edmundo@rano.org>
*
* 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.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "mutt.h"
#include "mime.h"
#include "charset.h"
#include "rfc2047.h"
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.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 /* strlen ("=?.?.?.?=") */
#define HSPACE(x) ((x) == '\0' || (x) == ' ' || (x) == '\t')
#define CONTINUATION_BYTE(c) (((c) & 0xc0) == 0x80)
extern char RFC822Specials[];
typedef size_t (*encoder_t) (char *, ICONV_CONST char *, size_t,
const char *);
static size_t convert_string (ICONV_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);
if (flen >= SIZE_MAX / MB_LEN_MAX)
{
iconv_close (cd);
return (size_t)(-1);
}
obl = MB_LEN_MAX * flen;
ob = buf = safe_malloc (obl + 1);
n = iconv (cd, &f, &flen, &ob, &obl);
if (n == (size_t)(-1) || iconv (cd, 0, 0, &ob, &obl) == (size_t)(-1))
{
e = errno;
FREE (&buf);
iconv_close (cd);
errno = e;
return (size_t)(-1);
}
*ob = '\0';
*tlen = ob - buf;
safe_realloc (&buf, ob - buf + 1);
*t = buf;
iconv_close (cd);
return n;
}
int convert_nonmime_string (char **ps)
{
const char *c, *c1;
for (c = AssumedCharset; c; c = c1 ? c1 + 1 : 0)
{
char *u = *ps;
char *s;
char *fromcode;
size_t m, n;
size_t ulen = mutt_strlen (*ps);
size_t slen;
if (!u || !*u)
return 0;
c1 = strchr (c, ':');
n = c1 ? c1 - c : mutt_strlen (c);
if (!n)
return 0;
fromcode = safe_malloc (n + 1);
strfcpy (fromcode, c, n + 1);
m = convert_string (u, ulen, fromcode, Charset, &s, &slen);
FREE (&fromcode);
if (m != (size_t)(-1))
{
FREE (ps); /* __FREE_CHECKED__ */
*ps = s;
return 0;
}
}
mutt_convert_string (ps,
(const char *)mutt_get_default_charset (),
Charset, MUTT_ICONV_HOOK_FROM);
return -1;
}
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