From f51b9d1be995123da43512ea06674045c2e4e5071b9b97918cf35785bc59708c Mon Sep 17 00:00:00 2001 From: "Dr. Werner Fink" Date: Fri, 23 Mar 2012 14:09:16 +0000 Subject: [PATCH 1/3] . OBS-URL: https://build.opensuse.org/package/show/server:mail/mailx?expand=0&rev=19 --- mailx-12.5-mime.dif | 243 +++++++++++++++++++++++++++++++++++--------- mailx.changes | 5 + mailx.spec | 16 +-- 3 files changed, 207 insertions(+), 57 deletions(-) diff --git a/mailx-12.5-mime.dif b/mailx-12.5-mime.dif index db4e731..8730dd4 100644 --- a/mailx-12.5-mime.dif +++ b/mailx-12.5-mime.dif @@ -1,42 +1,120 @@ --- def.h -+++ def.h 2011-05-13 11:04:51.779926337 +0000 -@@ -142,7 +142,8 @@ enum mimeclean { ++++ def.h 2012-03-23 13:57:44.000000000 +0000 +@@ -142,7 +142,9 @@ enum mimeclean { MIME_LONGLINES = 002, /* has lines too long for RFC 2822 */ MIME_CTRLCHAR = 004, /* contains control characters */ MIME_HASNUL = 010, /* contains \0 characters */ - MIME_NOTERMNL = 020 /* lacks a terminating newline */ + MIME_NOTERMNL = 020, /* lacks a terminating newline */ -+ MIME_UTF8 = 040 /* UTF-8 high bit characters */ ++ MIME_UTF8 = 040, /* UTF-8 high bit multi byte characters */ ++ MIME_LATIN = 0100 /* Latin high bit single byte characters */ }; enum tdflags { --- mime.c -+++ mime.c 2011-05-13 11:04:51.779926337 +0000 -@@ -258,8 +258,11 @@ getcharset(int isclean) - if (isclean & (MIME_CTRLCHAR|MIME_HASNUL)) - charset = NULL; - else if (isclean & MIME_HIGHBIT) { -- charset = (wantcharset && wantcharset != (char *)-1) ? -- wantcharset : value("charset"); -+ if (isclean & MIME_UTF8) -+ charset = defcharset; -+ if (charset == NULL) -+ charset = (wantcharset && wantcharset != (char *)-1) ? -+ wantcharset : value("charset"); - if (charset == NULL) { - char *t = value("ttycharset"); - if (t == NULL || (ascncasecmp("ANSI_X3.4", t, 9) == 0)) -@@ -737,6 +740,7 @@ mime_isclean(FILE *f) - lastc = c; - c = getc(f); - curlen++; -+ check: - if (c == '\n' || c == EOF) { - /* - * RFC 821 imposes a maximum line length of 1000 -@@ -749,10 +753,38 @@ mime_isclean(FILE *f) ++++ mime.c 2012-03-23 13:50:06.000000000 +0000 +@@ -302,13 +302,78 @@ gettcharset(void) + return t; + } + ++#define F 0 /* character never appears in mail text */ ++#define T 1 /* character appears in plain ASCII text */ ++#define I 2 /* character appears in ISO-8859 text */ ++#define X 3 /* character appears in non-ISO extended ASCII (Mac, IBM PC) */ ++ ++static char text_chars[256] = { ++ /* NUL BEL BS HT LF FF CR */ ++ F, F, F, F, F, F, F, F, T, T, T, F, F, T, F, F, /* 0x0X */ ++ /* ESC */ ++ F, F, F, F, F, F, F, F, F, F, F, T, F, F, F, F, /* 0x1X */ ++ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x2X */ ++ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x3X */ ++ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x4X */ ++ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x5X */ ++ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x6X */ ++ T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F, /* 0x7X */ ++ /* NEL */ ++ X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, /* 0x8X */ ++ X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, /* 0x9X */ ++ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xaX */ ++ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xbX */ ++ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xcX */ ++ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xdX */ ++ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xeX */ ++ I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I /* 0xfX */ ++}; ++ ++static int encflags; ++static void ++test_enc(const char *s) ++{ ++ int c = *s; ++ if (c & 0100) { ++ int n, follow; ++ ++ if ((c & 040) == 0) /* 110xxxxx */ ++ follow = 1; ++ else if ((c & 020) == 0) /* 1110xxxx */ ++ follow = 2; ++ else if ((c & 010) == 0) /* 11110xxx */ ++ follow = 3; ++ else if ((c & 004) == 0) /* 111110xx */ ++ follow = 4; ++ else if ((c & 002) == 0) /* 1111110x */ ++ follow = 5; ++ else ++ return; ++ ++ for (n = 1; n <= follow; n++) { ++ if ((c = *(s+n)) == '\0') ++ goto latin; ++ if ((c & 0200) == 0 || (c & 0100)) ++ goto latin; ++ } ++ encflags = MIME_UTF8; ++ return; ++ } ++latin: ++ c = *s; ++ if (text_chars[c & 0377] == I) ++ encflags = MIME_LATIN; ++} ++ + static int + has_highbit(const char *s) + { + if (s) { + do +- if (*s & 0200) ++ if (*s & 0200) { ++ test_enc(s); + return 1; ++ } + while (*s++ != '\0'); + } + return 0; +@@ -328,6 +393,7 @@ name_highbit(struct name *np) + char * + need_hdrconv(struct header *hp, enum gfield w) + { ++ encflags = 0; + if (w & GIDENT) { + if (hp->h_from && name_highbit(hp->h_from)) + goto needs; +@@ -355,7 +421,7 @@ need_hdrconv(struct header *hp, enum gfi + if (w & GSUBJECT && has_highbit(hp->h_subject)) + goto needs; + return NULL; +-needs: return getcharset(MIME_HIGHBIT); ++needs: return getcharset(MIME_HIGHBIT|encflags); + } + + #ifdef HAVE_ICONV +@@ -748,11 +814,54 @@ mime_isclean(FILE *f) + maxlen = curlen; curlen = 1; } else if (c & 0200) { ++ int i = c; isclean |= MIME_HIGHBIT; + if (c & 0100) { + int n, follow; @@ -57,24 +135,38 @@ + for (n = 0; n < follow; n++) { + lastc = c; + c = getc(f); ++ curlen++; + -+ if ((c & 0200) == 0 || (c & 0100) || -+ (c == '\0') || (c == '\n') || (c == EOF)) { -+ curlen += n; -+ goto check; ++ if (c == '\0') { ++ isclean |= MIME_HASNUL; ++ goto latin; ++ } ++ if ((c & 0200) == 0 || (c & 0100)) ++ goto latin; ++ if ((c == '\n') || (c == EOF)) { ++ if (curlen > maxlen) ++ maxlen = curlen; ++ curlen = 1; ++ goto latin; + } + } + isclean |= MIME_UTF8; ++ continue; + } ++ latin: ++ if (text_chars[i & 0377] == I) ++ isclean |= MIME_LATIN; ++ if (text_chars[i & 0377] == X) ++ isclean |= MIME_CTRLCHAR; } else if (c == '\0') { isclean |= MIME_HASNUL; break; - } else if ((c < 040 && (c != '\t' && c != '\f')) || c == 0177) { -+ } else if ((c < 040 && (c != '\t' && c != '\f' && c != '\b')) || c == 0177) { ++ } else if (text_chars[c & 0377] == F) { isclean |= MIME_CTRLCHAR; } } while (c != EOF); -@@ -826,12 +858,15 @@ get_mime_convert(FILE *fp, char **conten +@@ -826,11 +935,16 @@ get_mime_convert(FILE *fp, char **conten * ^I or ^L in text/plain bodies. However, some * obscure character sets actually contain these * characters, so the content type can be set. @@ -85,32 +177,85 @@ *contenttype = "application/octet-stream"; } else if (*contenttype == NULL) *contenttype = "text/plain"; -- } + } else if (ascncasecmp(*contenttype, "text/", 5) == 0) ++ { + *charset = getcharset(*isclean); + } return convert; } - --- sendout.c -+++ sendout.c 2011-05-13 11:07:31.623926237 +0000 -@@ -230,6 +230,11 @@ attach_file1(struct attachment *ap, FILE ++++ sendout.c 2012-03-23 13:46:32.000000000 +0000 +@@ -226,6 +226,23 @@ attach_file1(struct attachment *ap, FILE + charset = ap->a_charset; + convert = get_mime_convert(fi, &contenttype, &charset, &isclean, + dosign); ++#ifdef HAVE_ICONV ++ tcs = gettcharset(); ++ if (isclean & MIME_UTF8) ++ { ++ tcs = "utf-8"; ++ } ++ if (isclean & MIME_LATIN) { ++ tcs = value("charset"); ++ if (tcs == NULL && wantcharset && wantcharset != (char *)-1) ++ tcs = wantcharset; ++ } ++ if (tcs == NULL) { ++ contenttype = "application/octet-stream"; ++ charset = NULL; ++ convert = CONV_TOB64; ++ } ++#endif + fprintf(fo, "\n--%s\n" "Content-Type: %s", - send_boundary, contenttype); -+ tcs = gettcharset(); -+#ifdef HAVE_ICONV -+ if (wantcharset && ascncasecmp(wantcharset, "ANSI_X3.4", 9)) -+ charset = wantcharset; -+#endif - if (charset == NULL) - putc('\n', fo); - else -@@ -259,7 +264,7 @@ attach_file1(struct attachment *ap, FILE +@@ -255,11 +272,10 @@ attach_file1(struct attachment *ap, FILE + iconv_close(iconvd); + iconvd = (iconv_t)-1; + } +- tcs = gettcharset(); if ((isclean & (MIME_HASNUL|MIME_CTRLCHAR)) == 0 && ascncasecmp(contenttype, "text/", 5) == 0 && - isclean & MIME_HIGHBIT && +- isclean & MIME_HIGHBIT && - charset != NULL) { -+ charset != NULL && tcs != NULL && asccasecmp(charset, tcs)) { ++ (isclean & MIME_HIGHBIT) && ++ charset != NULL && tcs != NULL) { if ((iconvd = iconv_open_ft(charset, tcs)) == (iconv_t)-1 && errno != 0) { if (errno == EINVAL) +@@ -467,11 +483,12 @@ infix(struct header *hp, FILE *fi, int d + } + rm(tempMail); + Ftfree(&tempMail); +- convert = get_mime_convert(fi, &contenttype, &charset, +- &isclean, dosign); ++ convert = get_mime_convert(fi, &contenttype, &charset, &isclean, ++ dosign); + #ifdef HAVE_ICONV + tcs = gettcharset(); +- if ((convhdr = need_hdrconv(hp, GTO|GSUBJECT|GCC|GBCC|GIDENT)) != 0) { ++ if ((convhdr = need_hdrconv(hp, GTO|GSUBJECT|GCC|GBCC|GIDENT)) != 0 && ++ convhdr != NULL && tcs != NULL) { + if (iconvd != (iconv_t)-1) + iconv_close(iconvd); + if ((iconvd = iconv_open_ft(convhdr, tcs)) == (iconv_t)-1 +@@ -505,10 +522,17 @@ infix(struct header *hp, FILE *fi, int d + iconv_close(iconvd); + iconvd = (iconv_t)-1; + } ++ if (isclean & MIME_UTF8) ++ tcs = "utf-8"; ++ if (isclean & MIME_LATIN) { ++ tcs = value("charset"); ++ if (tcs == NULL && wantcharset && wantcharset != (char *)-1) ++ tcs = wantcharset; ++ } + if ((isclean & (MIME_HASNUL|MIME_CTRLCHAR)) == 0 && + ascncasecmp(contenttype, "text/", 5) == 0 && +- isclean & MIME_HIGHBIT && +- charset != NULL) { ++ (isclean & MIME_HIGHBIT) && ++ charset != NULL && tcs != NULL) { + if (iconvd != (iconv_t)-1) + iconv_close(iconvd); + if ((iconvd = iconv_open_ft(charset, tcs)) == (iconv_t)-1 diff --git a/mailx.changes b/mailx.changes index 9aaf931..fb708f2 100644 --- a/mailx.changes +++ b/mailx.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Fri Mar 23 14:01:02 UTC 2012 - werner@suse.de + +- Try to support not only UTF-8 but also latin text encodings (bnc#753340) + ------------------------------------------------------------------- Fri May 13 13:29:52 CEST 2011 - werner@suse.de diff --git a/mailx.spec b/mailx.spec index 2576a71..618a08a 100644 --- a/mailx.spec +++ b/mailx.spec @@ -1,7 +1,7 @@ # # spec file for package mailx # -# Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -15,20 +15,20 @@ # Please submit bugfixes or comments via http://bugs.opensuse.org/ # -# norootforbuild - Name: mailx -BuildRequires: krb5-devel openssl-devel pcre postfix +BuildRequires: krb5-devel +BuildRequires: openssl-devel +BuildRequires: pcre +BuildRequires: postfix Url: http://heirloom.sourceforge.net/mailx.html -License: BSD3c(or similar) -Group: Productivity/Networking/Email/Utilities Provides: mail Recommends: smtp_daemon -AutoReqProv: on Version: 12.5 -Release: 1 +Release: 0 Summary: A MIME-Capable Implementation of the mailx Command +License: BSD-3-Clause +Group: Productivity/Networking/Email/Utilities Source: mailx-%{version}.tar.bz2 Patch: mailx-%{version}.dif Patch1: nail-11.25-path.dif From ca7abefa3b4f96f4e7a62065cea4a18572db87688840ad25a6ebe7eb85eb7320 Mon Sep 17 00:00:00 2001 From: "Dr. Werner Fink" Date: Fri, 23 Mar 2012 18:41:10 +0000 Subject: [PATCH 2/3] . OBS-URL: https://build.opensuse.org/package/show/server:mail/mailx?expand=0&rev=20 --- mailx-12.5-mime.dif | 65 ++++++++++++++++++++++++++++++++++++++++++--- mailx.changes | 6 +++++ 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/mailx-12.5-mime.dif b/mailx-12.5-mime.dif index 8730dd4..70aeb13 100644 --- a/mailx-12.5-mime.dif +++ b/mailx-12.5-mime.dif @@ -12,7 +12,7 @@ enum tdflags { --- mime.c -+++ mime.c 2012-03-23 13:50:06.000000000 +0000 ++++ mime.c 2012-03-23 18:36:39.777934029 +0000 @@ -302,13 +302,78 @@ gettcharset(void) return t; } @@ -110,6 +110,24 @@ } #ifdef HAVE_ICONV +@@ -441,7 +507,7 @@ iconv_open_ft(const char *tocode, const + * be used to check the validity of the input even with + * identical encoding names. + */ +- if (strcmp(t, f) == 0) ++ if (asccasecmp(t, f) == 0) + errno = 0; + return (iconv_t)-1; + } +@@ -665,7 +731,7 @@ mime_tline(char *x, char *l) + l++; + if (*l != '\0') + *l++ = '\0'; +- if (strcmp(x, n) == 0) { ++ if (asccasecmp(x, n) == 0) { + match = 1; + break; + } @@ -748,11 +814,54 @@ mime_isclean(FILE *f) maxlen = curlen; curlen = 1; @@ -183,8 +201,49 @@ } return convert; } +@@ -989,8 +1103,12 @@ mime_fromhdr(struct str *in, struct str + #ifdef HAVE_ICONV + iconv_t fhicd = (iconv_t)-1; + #endif ++ encflags = 0; + + tcs = gettcharset(); ++ if (has_highbit(in->s)) ++ encflags |= MIME_HIGHBIT; ++ + maxstor = in->l; + out->s = smalloc(maxstor + 1); + out->l = 0; +@@ -1010,7 +1128,7 @@ mime_fromhdr(struct str *in, struct str + #ifdef HAVE_ICONV + if (fhicd != (iconv_t)-1) + iconv_close(fhicd); +- if (strcmp(cs, tcs)) ++ if (asccasecmp(cs, tcs)) + fhicd = iconv_open_ft(tcs, cs); + else + fhicd = (iconv_t)-1; +@@ -1105,12 +1223,17 @@ notmime: + } + fromhdr_end: + *q = '\0'; +- if (flags & TD_ISPR) { ++ if ((flags & TD_ISPR) && (encflags & MIME_HIGHBIT)) { + struct str new; ++ if ((encflags & MIME_UTF8) && asccasecmp("utf-8", tcs) == 0) ++ goto skip; ++ if ((encflags & MIME_LATIN) && ascncasecmp("iso-8859-", tcs, 9) == 0) ++ goto skip; + makeprint(out, &new); + free(out->s); + *out = new; + } ++skip: + if (flags & TD_DELCTRL) + out->l = delctrl(out->s, out->l); + #ifdef HAVE_ICONV --- sendout.c -+++ sendout.c 2012-03-23 13:46:32.000000000 +0000 ++++ sendout.c 2012-03-23 18:30:50.949933289 +0000 @@ -226,6 +226,23 @@ attach_file1(struct attachment *ap, FILE charset = ap->a_charset; convert = get_mime_convert(fi, &contenttype, &charset, &isclean, @@ -235,7 +294,7 @@ tcs = gettcharset(); - if ((convhdr = need_hdrconv(hp, GTO|GSUBJECT|GCC|GBCC|GIDENT)) != 0) { + if ((convhdr = need_hdrconv(hp, GTO|GSUBJECT|GCC|GBCC|GIDENT)) != 0 && -+ convhdr != NULL && tcs != NULL) { ++ tcs != NULL) { if (iconvd != (iconv_t)-1) iconv_close(iconvd); if ((iconvd = iconv_open_ft(convhdr, tcs)) == (iconv_t)-1 diff --git a/mailx.changes b/mailx.changes index fb708f2..0fc4109 100644 --- a/mailx.changes +++ b/mailx.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Mar 23 18:39:38 UTC 2012 - werner@suse.de + +- Avoid header rewrite in case of specified ttycharset in wrong + locale but subject in ttycharset (bnc#753340) + ------------------------------------------------------------------- Fri Mar 23 14:01:02 UTC 2012 - werner@suse.de From ba0f793ca4317657ef42ae8f76b2bfd33e7d14a78612e1a5b34c5939ec7bbbfa Mon Sep 17 00:00:00 2001 From: "Dr. Werner Fink" Date: Fri, 30 Mar 2012 14:52:32 +0000 Subject: [PATCH 3/3] . OBS-URL: https://build.opensuse.org/package/show/server:mail/mailx?expand=0&rev=21 --- mailx-12.5-mime.dif | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/mailx-12.5-mime.dif b/mailx-12.5-mime.dif index 70aeb13..cdb17fc 100644 --- a/mailx-12.5-mime.dif +++ b/mailx-12.5-mime.dif @@ -12,7 +12,7 @@ enum tdflags { --- mime.c -+++ mime.c 2012-03-23 18:36:39.777934029 +0000 ++++ mime.c 2012-03-30 14:50:10.318065066 +0000 @@ -302,13 +302,78 @@ gettcharset(void) return t; } @@ -201,20 +201,22 @@ } return convert; } -@@ -989,8 +1103,12 @@ mime_fromhdr(struct str *in, struct str +@@ -989,8 +1103,14 @@ mime_fromhdr(struct str *in, struct str #ifdef HAVE_ICONV iconv_t fhicd = (iconv_t)-1; #endif -+ encflags = 0; ++ enum mimeclean isclean = 0; tcs = gettcharset(); ++ ++ encflags = 0; + if (has_highbit(in->s)) -+ encflags |= MIME_HIGHBIT; ++ isclean |= (MIME_HIGHBIT|encflags); + maxstor = in->l; out->s = smalloc(maxstor + 1); out->l = 0; -@@ -1010,7 +1128,7 @@ mime_fromhdr(struct str *in, struct str +@@ -1010,7 +1130,7 @@ mime_fromhdr(struct str *in, struct str #ifdef HAVE_ICONV if (fhicd != (iconv_t)-1) iconv_close(fhicd); @@ -223,16 +225,16 @@ fhicd = iconv_open_ft(tcs, cs); else fhicd = (iconv_t)-1; -@@ -1105,12 +1223,17 @@ notmime: +@@ -1105,12 +1225,17 @@ notmime: } fromhdr_end: *q = '\0'; - if (flags & TD_ISPR) { -+ if ((flags & TD_ISPR) && (encflags & MIME_HIGHBIT)) { ++ if ((flags & TD_ISPR) && (isclean & MIME_HIGHBIT)) { struct str new; -+ if ((encflags & MIME_UTF8) && asccasecmp("utf-8", tcs) == 0) ++ if ((isclean & MIME_UTF8) && asccasecmp("utf-8", tcs) == 0) + goto skip; -+ if ((encflags & MIME_LATIN) && ascncasecmp("iso-8859-", tcs, 9) == 0) ++ if ((isclean & MIME_LATIN) && ascncasecmp("iso-8859-", tcs, 9) == 0) + goto skip; makeprint(out, &new); free(out->s);