From 9b87576a7ebf2e52a7ca6a0e2dba12fa24bd34dd Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Wed, 28 Nov 2007 15:10:56 +0100 Subject: [PATCH] Revert "we use glibc, and gconv. Don't need our own transcoding stuff, glibc does" This reverts commit 2c0e197ef42e4cdff1eff705c8b1b1d07336bf24. --- charset.cpkg | 101 ++++++++++++++++++++++++++++++++++++++++----- charset.h | 7 +++- lib-mime/rfc2047.c | 16 +++---- lib-mx/hcache.c | 2 +- sendlib.c | 8 ++-- state.c | 4 +- 6 files changed, 111 insertions(+), 27 deletions(-) diff --git a/charset.cpkg b/charset.cpkg index a58b013..89905b8 100644 --- a/charset.cpkg +++ b/charset.cpkg @@ -226,41 +226,117 @@ iconv_t mutt_iconv_open(const char *tocode, const char *fromcode, int flags) charset_canonicalize(from1, sizeof(from1), fromcode); } - m_strcat(to1, sizeof(to1), "//TRANSLIT"); if ((cd = iconv_open(to1, from1)) != MUTT_ICONV_ERROR) return cd; if (rx_list_match2(iconv_hooks, to1, to2, sizeof(to2)) - && rx_list_match2(iconv_hooks, from1, from2, sizeof(from2))) { - m_strcat(to2, sizeof(to2), "//TRANSLIT"); + && rx_list_match2(iconv_hooks, from1, from2, sizeof(from2))) return iconv_open(to2, from2); - } return MUTT_ICONV_ERROR; } +/* Like iconv, but keeps going even when the input is invalid + If you're supplying inrepls, the source charset should be stateless; + if you're supplying an outrepl, the target charset should be. */ +/* XXX: MC: I do not understand what it does yet */ +ssize_t mutt_iconv(iconv_t cd, + const char **inbuf, ssize_t *inbytesleft, + char **outbuf, ssize_t *outbytesleft, + const char **inrepls, const char *outrepl) +{ + ssize_t ret = 0, ret1; + const char *ib = *inbuf; + ssize_t ibl = *inbytesleft; + char *ob = *outbuf; + ssize_t obl = *outbytesleft; + + for (;;) { + ret1 = my_iconv(cd, &ib, &ibl, &ob, &obl); + if (ret1 != -1) + ret += ret1; + + if (ibl && obl && errno == EILSEQ) { + if (inrepls) { + /* Try replacing the input */ + const char **t; + + for (t = inrepls; *t; t++) { + const char *ib1 = *t; + ssize_t ibl1 = m_strlen(*t); + char *ob1 = ob; + ssize_t obl1 = obl; + + my_iconv(cd, &ib1, &ibl1, &ob1, &obl1); + if (!ibl1) { + ++ib, --ibl; + ob = ob1, obl = obl1; + ++ret; + break; + } + } + if (*t) + continue; + } + /* Replace the output */ + if (!outrepl) + outrepl = "?"; + my_iconv(cd, 0, 0, &ob, &obl); + if (obl) { + ssize_t n = m_strlen(outrepl); + + if (n > obl) { + outrepl = "?"; + n = 1; + } + memcpy(ob, outrepl, n); + ++ib, --ibl; + ob += n, obl -= n; + ++ret; + my_iconv(cd, 0, 0, 0, 0); /* for good measure */ + continue; + } + } + *inbuf = ib, *inbytesleft = ibl; + *outbuf = ob, *outbytesleft = obl; + return ret; + } +} + /* Convert a string */ int mutt_convert_string(char **ps, const char *from, const char *to, int flags) { iconv_t cd; + const char *repls[] = { "\357\277\275", "?", 0 }; + if (m_strisempty(*ps)) return 0; cd = mutt_iconv_open(to, from, flags); if (cd != MUTT_ICONV_ERROR) { + const char **inrepls = NULL; + const char *outrepl = NULL; const char *ib; char *buf, *ob; ssize_t ibl, obl; + if (charset_is_utf8(to)) + outrepl = "\357\277\275"; + else + if (charset_is_utf8(from)) + inrepls = repls; + else + outrepl = "?"; + ibl = m_strlen(*ps) + 1; ib = *ps; obl = MB_LEN_MAX * ibl; ob = buf = p_new(char, obl + 1); - mutt_iconv(cd, &ib, &ibl, &ob, &obl); + mutt_iconv(cd, &ib, &ibl, &ob, &obl, inrepls, outrepl); iconv_close(cd); *ob = '\0'; @@ -288,9 +364,9 @@ static ssize_t convert_string(const char *f, ssize_t flen, obl = 4 * flen + 1; ob = buf = p_new(char, obl); - n = mutt_iconv(cd, &f, &flen, &ob, &obl); + n = my_iconv(cd, &f, &flen, &ob, &obl); - if (n < 0 || mutt_iconv(cd, 0, 0, &ob, &obl) < 0) { + if (n < 0 || my_iconv(cd, 0, 0, &ob, &obl) < 0) { e = errno; p_delete(&buf); iconv_close(cd); @@ -352,11 +428,14 @@ struct fgetconv_t { char *ob; char *ib; ssize_t ibl; + const char **inrepls; }; fgetconv_t * fgetconv_open(FILE *file, const char *from, const char *to, int flags) { + static const char *repls[] = { "\357\277\275", "?", 0 }; + struct fgetconv_t *fc = p_new(struct fgetconv_t, 1); fc->file = file; @@ -368,6 +447,7 @@ fgetconv_open(FILE *file, const char *from, const char *to, int flags) fc->p = fc->ob = fc->bufo; fc->ib = fc->bufi; fc->ibl = 0; + fc->inrepls = repls + charset_is_utf8(to); } return fc; } @@ -377,7 +457,7 @@ void fgetconv_close(fgetconv_t **fcp) struct fgetconv_t *fc = *fcp; if (fc->cd != MUTT_ICONV_ERROR) - iconv_close(fc->cd); + iconv_close (fc->cd); p_delete(fcp); } @@ -400,7 +480,7 @@ int fgetconv(fgetconv_t *fc) if (fc->ibl) { ssize_t obl = ssizeof(fc->bufo); - mutt_iconv(fc->cd, (const char **)&fc->ib, &fc->ibl, &fc->ob, &obl); + my_iconv(fc->cd, (const char **)&fc->ib, &fc->ibl, &fc->ob, &obl); if (fc->p < fc->ob) return (unsigned char)*(fc->p)++; } @@ -426,7 +506,8 @@ int fgetconv(fgetconv_t *fc) if (fc->ibl) { ssize_t obl = ssizeof(fc->bufo); - mutt_iconv(fc->cd, (const char **)&fc->ib, &fc->ibl, &fc->ob, &obl); + mutt_iconv(fc->cd, (const char **)&fc->ib, &fc->ibl, &fc->ob, &obl, + fc->inrepls, 0); if (fc->p < fc->ob) { return (unsigned char)*(fc->p)++; } diff --git a/charset.h b/charset.h index 646526b..3b7566d 100644 --- a/charset.h +++ b/charset.h @@ -56,15 +56,18 @@ const char *charset_getfirst(const char *); #include -iconv_t mutt_iconv_open(const char *, const char *, int); static inline ssize_t -mutt_iconv(iconv_t ict, const char **in, ssize_t *il, char **out, ssize_t *ol) { +my_iconv(iconv_t ict, const char **in, ssize_t *il, char **out, ssize_t *ol) { return iconv(ict, (char **)in, (size_t*)il, out, (size_t*)ol); } #define M_ICONV_HOOK_FROM 1 #define M_ICONV_HOOK_TO 2 +iconv_t mutt_iconv_open(const char *, const char *, int); +ssize_t mutt_iconv(iconv_t, const char **, ssize_t *, char **, ssize_t *, + const char **, const char *); + int mutt_convert_string(char **, const char *, const char *, int); int mutt_convert_nonmime_string (char **); diff --git a/lib-mime/rfc2047.c b/lib-mime/rfc2047.c index a2629a9..1d42403 100644 --- a/lib-mime/rfc2047.c +++ b/lib-mime/rfc2047.c @@ -69,9 +69,9 @@ convert_string(const char *from, const char *f, ssize_t flen, obl = 4 * flen + 1; ob = buf = p_new(char, obl); - n = mutt_iconv(cd, &f, &flen, &ob, &obl); + n = my_iconv(cd, &f, &flen, &ob, &obl); - if (n < 0 || mutt_iconv(cd, 0, 0, &ob, &obl) < 0) { + if (n < 0 || my_iconv(cd, 0, 0, &ob, &obl) < 0) { int e = errno; iconv_close(cd); errno = e; @@ -266,14 +266,14 @@ static size_t try_block(const char *d, ssize_t dlen, ob = buf1; - if (mutt_iconv(cd, &ib, &ibl, &ob, &obl) < 0 - || mutt_iconv(cd, 0, 0, &ob, &obl) < 0) + if (my_iconv(cd, &ib, &ibl, &ob, &obl) < 0 + || my_iconv(cd, 0, 0, &ob, &obl) < 0) { assert (errno == E2BIG && ib > d); iconv_close(cd); return (ib - d == dlen) ? dlen : ib - d + 1; } - iconv_close(cd); + iconv_close (cd); } else { if (dlen > obl) return obl + 1; @@ -331,10 +331,10 @@ encode_block(char *s, char *d, ssize_t dlen, cd = mutt_iconv_open(tocode, fromcode, 0); assert (cd != MUTT_ICONV_ERROR); ib = d, ibl = dlen, ob = buf1, obl = sizeof(buf1) - m_strlen(tocode); - n1 = mutt_iconv(cd, &ib, &ibl, &ob, &obl); - n2 = mutt_iconv(cd, 0, 0, &ob, &obl); + n1 = my_iconv(cd, &ib, &ibl, &ob, &obl); + n2 = my_iconv(cd, 0, 0, &ob, &obl); assert (n1 >= 0 && n2 >= 0); - iconv_close(cd); + iconv_close (cd); return (*encoder)(s, buf1, ob - buf1, tocode); } else { return (*encoder)(s, d, dlen, tocode); diff --git a/lib-mx/hcache.c b/lib-mx/hcache.c index 01db5bd..a82921b 100644 --- a/lib-mx/hcache.c +++ b/lib-mx/hcache.c @@ -476,7 +476,7 @@ void mutt_hcache_delete(hcache_t *db, const char *filename, char path[_POSIX_PATH_MAX]; if (!db) - return; + return -1; snprintf(path, sizeof(path), "%s%s", db->folder, filename); diff --git a/sendlib.c b/sendlib.c index 5e5faf0..1f15e17 100644 --- a/sendlib.c +++ b/sendlib.c @@ -566,7 +566,7 @@ static ssize_t convert_file_to (FILE * file, const char *fromcode, /* Convert to UTF-8 */ ib = bufi; ob = bufu, obl = sizeof (bufu); - n = mutt_iconv(cd1, ibl ? &ib : 0, &ibl, &ob, &obl); + n = my_iconv(cd1, ibl ? &ib : 0, &ibl, &ob, &obl); if (n == -1 && ((errno != EINVAL && errno != E2BIG) || ib == bufi)) { ret = -1; break; @@ -578,7 +578,7 @@ static ssize_t convert_file_to (FILE * file, const char *fromcode, if (cd[i] != MUTT_ICONV_ERROR && score[i] != -1) { ub = bufu, ubl = ubl1; ob = bufo, obl = sizeof (bufo); - n = mutt_iconv(cd[i], (ibl || ubl) ? &ub : 0, &ubl, &ob, &obl); + n = my_iconv(cd[i], (ibl || ubl) ? &ub : 0, &ubl, &ob, &obl); if (n == -1) { score[i] = -1; } @@ -627,9 +627,9 @@ static ssize_t convert_file_to (FILE * file, const char *fromcode, for (i = 0; i < ncodes; i++) if (cd[i] != MUTT_ICONV_ERROR) - iconv_close(cd[i]); + iconv_close (cd[i]); - iconv_close(cd1); + iconv_close (cd1); p_delete(&cd); p_delete(&infos); p_delete(&score); diff --git a/state.c b/state.c index 12edf41..f21db7e 100644 --- a/state.c +++ b/state.c @@ -33,7 +33,7 @@ void mutt_convert_to_state (iconv_t cd, char *bufi, ssize_t * l, STATE * s) if (!bufi) { if (cd != MUTT_ICONV_ERROR) { ob = bufo, obl = sizeof (bufo); - mutt_iconv(cd, 0, 0, &ob, &obl); + my_iconv(cd, 0, 0, &ob, &obl); if (ob != bufo) state_prefix_put (bufo, ob - bufo, s); } @@ -51,7 +51,7 @@ void mutt_convert_to_state (iconv_t cd, char *bufi, ssize_t * l, STATE * s) ib = bufi, ibl = *l; for (;;) { ob = bufo, obl = sizeof (bufo); - mutt_iconv (cd, &ib, &ibl, &ob, &obl); + mutt_iconv (cd, &ib, &ibl, &ob, &obl, 0, "?"); if (ob == bufo) break; state_prefix_put (bufo, ob - bufo, s); -- 2.20.1