X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=charset.c;h=8a1804f8d511ef17e4f0679e0fedd1fd4b4aa386;hp=9a80d319366dacc7f3a3795063a9449366096760;hb=2293e9bc5a94ef33dc596b064c607d6bed5ad1fd;hpb=fdb93a08e305b8755260144807e4d45106a9cb9f diff --git a/charset.c b/charset.c index 9a80d31..8a1804f 100644 --- a/charset.c +++ b/charset.c @@ -59,11 +59,16 @@ char *Charset; int Charset_is_utf8 = 0; wchar_t CharsetReplacement = '?'; + +/****************************************************************************/ +/* charset functions */ +/****************************************************************************/ + void charset_initialize(void) { #ifdef HAVE_LANGINFO_CODESET - char buff[LONG_STRING]; - char buff2[LONG_STRING]; + char buff[SHORT_STRING]; + char buff2[SHORT_STRING]; m_strcpy(buff, sizeof(buff), nl_langinfo(CODESET)); charset_canonicalize(buff2, sizeof(buff2), buff); @@ -89,7 +94,7 @@ void charset_initialize(void) void charset_canonicalize(char *dest, ssize_t dlen, const char *name) { const struct cset_pair *cp; - char scratch[LONG_STRING]; + char scratch[SHORT_STRING]; const char *p; int i = 0; @@ -110,9 +115,23 @@ void charset_canonicalize(char *dest, ssize_t dlen, const char *name) } } +/* XXX: MC: UGLY return of local static */ +const char *charset_getfirst(const char *charset) +{ + static char fcharset[SHORT_STRING]; + const char *p; + + if (m_strisempty(charset)) + return "us-ascii"; + + p = m_strchrnul(charset, ':'); + m_strncpy(fcharset, sizeof(fcharset), charset, p - charset); + return fcharset; +} + static int mutt_chscmp(const char *s, const char *chs) { - char buffer[STRING]; + char buffer[SHORT_STRING]; if (!s) return 0; @@ -132,361 +151,338 @@ int charset_is_us_ascii(const char *s) } -/* - * Like iconv_open, but canonicalises the charsets - */ +/****************************************************************************/ +/* iconv-line functions */ +/****************************************************************************/ -iconv_t mutt_iconv_open (const char *tocode, const char *fromcode, int flags) +/* Like iconv_open, but canonicalises the charsets */ +iconv_t mutt_iconv_open(const char *tocode, const char *fromcode, int flags) { - char tocode1[SHORT_STRING]; - char fromcode1[SHORT_STRING]; - char *tocode2, *fromcode2; - char *tmp; + char tocode1[SHORT_STRING]; + char fromcode1[SHORT_STRING]; + const char *tmp; - iconv_t cd; + iconv_t cd; - charset_canonicalize (tocode1, sizeof (tocode1), tocode); + if ((flags & M_ICONV_HOOK_TO) && (tmp = mutt_charset_hook(tocode1))) { + charset_canonicalize(tocode1, sizeof(tocode1), tmp); + } else { + charset_canonicalize(tocode1, sizeof(tocode1), tocode); + } -#ifdef M_ICONV_HOOK_TO - /* Not used. */ - if ((flags & M_ICONV_HOOK_TO) && (tmp = mutt_charset_hook (tocode1))) - charset_canonicalize (tocode1, sizeof (tocode1), tmp); -#endif + if ((flags & M_ICONV_HOOK_FROM) && (tmp = mutt_charset_hook(fromcode1))) { + charset_canonicalize(fromcode1, sizeof(fromcode1), tmp); + } else { + charset_canonicalize(fromcode1, sizeof(fromcode1), fromcode); + } - charset_canonicalize (fromcode1, sizeof (fromcode1), fromcode); - if ((flags & M_ICONV_HOOK_FROM) && (tmp = mutt_charset_hook (fromcode1))) - charset_canonicalize (fromcode1, sizeof (fromcode1), tmp); + cd = iconv_open(tocode1, fromcode1); + if (cd != MUTT_ICONV_ERROR) + return cd; - if ((cd = iconv_open (tocode1, fromcode1)) != (iconv_t) - 1) - return cd; - if ((tocode2 = mutt_iconv_hook (tocode1)) - && (fromcode2 = mutt_iconv_hook (fromcode1))) - return iconv_open (tocode2, fromcode2); + { + const char *to = mutt_iconv_hook(tocode1); + const char *from = mutt_iconv_hook(fromcode1); - return (iconv_t) - 1; + return to && from ? iconv_open(to, from) : 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. - */ - -ssize_t mutt_iconv(iconv_t cd, const char **inbuf, ssize_t *inbytesleft, +/* 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; + 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; + } } - 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; } - *inbuf = ib, *inbytesleft = ibl; - *outbuf = ob, *outbytesleft = obl; - return ret; - } } - -/* - * Convert a string - * Used in rfc2047.c and rfc2231.c - */ - -int mutt_convert_string (char **ps, const char *from, const char *to, - int flags) +/* 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 }; - char *s = *ps; + iconv_t cd; + const char *repls[] = { "\357\277\275", "?", 0 }; - if (!s || !*s) - return 0; + if (m_strisempty(*ps)) + return 0; - if (to && from && (cd = mutt_iconv_open (to, from, flags)) != (iconv_t) - 1) { - int len; - const char *ib; - char *buf, *ob; - ssize_t ibl, obl; - const char **inrepls = NULL; - const char *outrepl = NULL; - - if (charset_is_utf8 (to)) - outrepl = "\357\277\275"; - else if (charset_is_utf8 (from)) - inrepls = repls; - else - outrepl = "?"; - - len = m_strlen(s); - ib = s, ibl = len + 1; - obl = MB_LEN_MAX * ibl; - ob = buf = xmalloc(obl + 1); - - mutt_iconv (cd, &ib, &ibl, &ob, &obl, inrepls, outrepl); - iconv_close (cd); - - *ob = '\0'; - - p_delete(ps); - *ps = buf; - return 0; - } - else - return -1; -} + 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 = "?"; -/* - * FGETCONV stuff for converting a file while reading it - * Used in sendlib.c for converting from mutt's Charset - */ + ibl = m_strlen(*ps) + 1; + ib = *ps; -struct fgetconv_s { - FILE *file; - iconv_t cd; - char bufi[512]; - char bufo[512]; - char *p; - char *ob; - char *ib; - ssize_t ibl; - const char **inrepls; -}; + obl = MB_LEN_MAX * ibl; + ob = buf = p_new(char, obl + 1); -struct fgetconv_not { - FILE *file; - iconv_t cd; -}; + mutt_iconv(cd, &ib, &ibl, &ob, &obl, inrepls, outrepl); + iconv_close(cd); -FGETCONV *fgetconv_open (FILE * file, const char *from, const char *to, - int flags) -{ - struct fgetconv_s *fc; - iconv_t cd = (iconv_t) - 1; - static const char *repls[] = { "\357\277\275", "?", 0 }; + *ob = '\0'; - if (from && to) - cd = mutt_iconv_open (to, from, flags); + p_delete(ps); + *ps = buf; + return 0; + } - if (cd != (iconv_t) - 1) { - fc = p_new(struct fgetconv_s, 1); - fc->p = fc->ob = fc->bufo; - fc->ib = fc->bufi; - fc->ibl = 0; - fc->inrepls = charset_is_utf8 (to) ? repls : repls + 1; - } - else - fc = p_new(struct fgetconv_s, 1); - fc->file = file; - fc->cd = cd; - return (FGETCONV *) fc; + return -1; } -char *fgetconvs (char *buf, ssize_t l, FGETCONV * _fc) +static ssize_t convert_string(const char *f, ssize_t flen, + const char *from, const char *to, + char **t, ssize_t * tlen) { - int c; - ssize_t r; - - for (r = 0; r + 1 < l;) { - if ((c = fgetconv (_fc)) == EOF) - break; - buf[r++] = (char) c; - if (c == '\n') - break; - } - buf[r] = '\0'; - - if (r) - return buf; - else - return NULL; + iconv_t cd; + char *buf, *ob; + ssize_t obl; + ssize_t n; + int e; + + if ((cd = mutt_iconv_open(to, from, 0)) == MUTT_ICONV_ERROR) + 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; + *t = buf; + iconv_close(cd); + return n; } -int fgetconv (FGETCONV * _fc) +int mutt_convert_nonmime_string(char **ps) { - struct fgetconv_s *fc = (struct fgetconv_s *) _fc; + const char *p = AssumedCharset; + ssize_t ulen = m_strlen(*ps); + char *u = *ps; - if (!fc) - return EOF; - if (fc->cd == (iconv_t) - 1) - return fgetc (fc->file); - if (!fc->p) - return EOF; - if (fc->p < fc->ob) - return (unsigned char) *(fc->p)++; + while (*p) { + const char *q; + char fromcode[LONG_STRING], *s = NULL; + ssize_t slen; - /* Try to convert some more */ - fc->p = fc->ob = fc->bufo; - if (fc->ibl) { - ssize_t obl = ssizeof(fc->bufo); + if (!ulen) + return 0; - my_iconv(fc->cd, (const char **) &fc->ib, &fc->ibl, &fc->ob, &obl); - if (fc->p < fc->ob) - return (unsigned char) *(fc->p)++; - } + while (*p == ':') + *p++; - /* If we trusted iconv a bit more, we would at this point - * ask why it had stopped converting ... */ + q = m_strchrnul(p, ':'); + m_strncpy(fromcode, sizeof(fromcode), p, q - p); + p = q; - /* Try to read some more */ - if (fc->ibl == sizeof (fc->bufi) || - (fc->ibl && fc->ib + fc->ibl < fc->bufi + sizeof (fc->bufi))) { - fc->p = 0; - return EOF; - } - if (fc->ibl) - memcpy (fc->bufi, fc->ib, fc->ibl); - fc->ib = fc->bufi; - fc->ibl += - fread (fc->ib + fc->ibl, 1, sizeof (fc->bufi) - fc->ibl, fc->file); - - /* Try harder this time to convert some */ - if (fc->ibl) { - ssize_t obl = ssizeof(fc->bufo); - - 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)++; - } + if (convert_string(u, ulen, fromcode, Charset, &s, &slen) >= 0) { + p_delete(ps); + *ps = s; + return 0; + } + } - /* Either the file has finished or one of the buffers is too small */ - fc->p = 0; - return EOF; + return -1; } -void fgetconv_close (FGETCONV ** _fc) +/****************************************************************************/ +/* fgetconv functions */ +/****************************************************************************/ + +/* fgetconv_t stuff for converting a file while reading it + Used in sendlib.c for converting from mutt's Charset */ + +struct fgetconv_t { + FILE *file; + iconv_t cd; + char bufi[BUFSIZ]; + char bufo[BUFSIZ]; + char *p; + char *ob; + char *ib; + ssize_t ibl; + const char **inrepls; +}; + +fgetconv_t * +fgetconv_open(FILE *file, const char *from, const char *to, int flags) { - struct fgetconv_s *fc = (struct fgetconv_s *) *_fc; + static const char *repls[] = { "\357\277\275", "?", 0 }; + + struct fgetconv_t *fc = p_new(struct fgetconv_t, 1); - if (fc->cd != (iconv_t) - 1) - iconv_close (fc->cd); - p_delete(_fc); + fc->file = file; + if (from && to) + fc->cd = mutt_iconv_open(to, from, flags); + + if (fc->cd != MUTT_ICONV_ERROR) { + fc->p = fc->ob = fc->bufo; + fc->ib = fc->bufi; + fc->ibl = 0; + fc->inrepls = repls + charset_is_utf8(to); + } + return fc; } -const char *mutt_get_first_charset (const char *charset) +void fgetconv_close(fgetconv_t **fcp) { - static char fcharset[SHORT_STRING]; - const char *c, *c1; - - c = charset; - if (!m_strlen(c)) - return "us-ascii"; - if (!(c1 = strchr (c, ':'))) - return ((char*) charset); - m_strcpy(fcharset, c1 - c + 1, c); - return fcharset; + struct fgetconv_t *fc = *fcp; + + if (fc->cd != MUTT_ICONV_ERROR) + iconv_close (fc->cd); + p_delete(fcp); } -static ssize_t convert_string (const char *f, ssize_t flen, - const char *from, const char *to, - char **t, ssize_t * tlen) + +int fgetconv(fgetconv_t *fc) { - iconv_t cd; - char *buf, *ob; - ssize_t obl; - ssize_t n; - int e; - - cd = mutt_iconv_open (to, from, 0); - if (cd == (iconv_t) (-1)) - return -1; - obl = 4 * flen + 1; - ob = buf = xmalloc(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'; + if (!fc) + return EOF; - *tlen = ob - buf; + if (fc->cd == MUTT_ICONV_ERROR) + return fgetc(fc->file); - p_realloc(&buf, ob - buf + 1); - *t = buf; - iconv_close (cd); + if (!fc->p) + return EOF; + if (fc->p < fc->ob) + return (unsigned char)*(fc->p)++; + + /* Try to convert some more */ + fc->p = fc->ob = fc->bufo; + if (fc->ibl) { + ssize_t obl = ssizeof(fc->bufo); + + my_iconv(fc->cd, (const char **)&fc->ib, &fc->ibl, &fc->ob, &obl); + if (fc->p < fc->ob) + return (unsigned char)*(fc->p)++; + } + + /* If we trusted iconv a bit more, we would at this point + * ask why it had stopped converting ... */ + + /* Try to read some more */ + if (fc->ibl == sizeof(fc->bufi) + || (fc->ibl && fc->ib + fc->ibl < fc->bufi + sizeof(fc->bufi))) { + fc->p = NULL; + return EOF; + } + + if (fc->ibl) { + memcpy(fc->bufi, fc->ib, fc->ibl); + } + fc->ib = fc->bufi; + fc->ibl += fread(fc->ib + fc->ibl, 1, sizeof(fc->bufi) - fc->ibl, + fc->file); - return n; + /* Try harder this time to convert some */ + if (fc->ibl) { + ssize_t obl = ssizeof(fc->bufo); + + 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)++; + } + } + + /* Either the file has finished or one of the buffers is too small */ + fc->p = NULL; + return EOF; } -int mutt_convert_nonmime_string (char **ps) +char *fgetconvs(char *buf, ssize_t len, fgetconv_t *fc) { - const char *c, *c1; + ssize_t pos = 0; - for (c = AssumedCharset; c; c = c1 ? c1 + 1 : 0) { - char *u = *ps; - char *s = NULL; - char *fromcode; - ssize_t m, n; - ssize_t ulen = m_strlen(*ps); - ssize_t slen; - - if (!u || !*u) - return 0; - - c1 = strchr (c, ':'); - n = c1 ? c1 - c : m_strlen(c); - if (!n) - continue; - fromcode = p_dupstr(c, n); - m = convert_string (u, ulen, fromcode, Charset, &s, &slen); - p_delete(&fromcode); - if (m != -1) { - p_delete(ps); - *ps = s; - return 0; + while (pos < len - 1) { + int c = fgetconv(fc); + if (c == EOF) + break; + + buf[pos++] = c; + if (c == '\n') + break; } - } - return -1; + buf[pos] = '\0'; + + return pos ? buf : NULL; }