sync with 0.8.6cvs17
authorPaul Mangan <paul@claws-mail.org>
Fri, 13 Dec 2002 09:22:05 +0000 (09:22 +0000)
committerPaul Mangan <paul@claws-mail.org>
Fri, 13 Dec 2002 09:22:05 +0000 (09:22 +0000)
12 files changed:
ChangeLog
ChangeLog.claws
ChangeLog.jp
configure.in
src/codeconv.c
src/common/Makefile.am
src/common/quoted-printable.c [new file with mode: 0644]
src/common/quoted-printable.h [new file with mode: 0644]
src/common/utils.c
src/common/utils.h
src/procmime.c
src/unmime.c

index fc2f3848871739c7300f2f320fb73971d3e29a76..d4fda65c56a0121cc085f9b64283fcc72a471a7f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2002-12-13
+
+       * src/codeconv.c: conv_encode_header(): reimplemented the routine
+         of MIME header encoding. And use Q-encoding method if the current
+         locale is single-byte one.
+       * src/utils.[ch]: is_next_nonascii(): take multi-byte string instead
+         of wide-character string. Consider control codes as non-ASCII.
+         get_next_word_len(): new. It returns the length of next word.
+         is_next_mbs(), find_wspace(): removed.
+       * src/quoted-printable.[ch]: new.
+         qp_decode_line(): decodes one QP line.
+         qp_decode_q_encoding(): decodes Q-encoded string in MIME header.
+         qp_get_q_encoding_len(): returns the length when a string is
+         Q-encoded.
+         qp_q_encode(): Q-encode a string (RFC 2047).
+       * src/unmime.c: moved the functions for quoted-printable to
+         quoted-printable.c.
+
 2002-12-05
 
        * src/send.c: send_message_local(): escape line that only have one
index 185a1690936191f7bce3890b74216247ce1c8226..85adef3898e630a14c7260440957a8d8829b08de 100644 (file)
@@ -1,3 +1,8 @@
+2002-12-13 [paul]      0.8.6claws103
+
+       * sync with 0.8.6cvs17
+               see ChangeLog 2002-12-13
+
 2002-12-13 [paul]      0.8.6claws102
 
        * po/es.po
index 3d5bdb5b133a9bda08d25859bb06380258f47db7..ace5026d7157df1acbc36afe59247911f51dd9d9 100644 (file)
@@ -1,3 +1,22 @@
+2002-12-13
+
+       * src/codeconv.c: conv_encode_header(): MIME ¥Ø¥Ã¥À¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°
+         ¤Î¥ë¡¼¥Á¥ó¤òºÆ¼ÂÁõ¡£¸½ºß¤Î locale ¤¬¥·¥ó¥°¥ë¥Ð¥¤¥È¤Ç¤¢¤ì¤Ð
+         Q Éä¹æ²½¤ò»ÈÍѤ¹¤ë¤è¤¦¤Ë¤·¤¿¡£
+       * src/utils.[ch]: is_next_nonascii(): ¥ï¥¤¥É¥­¥ã¥é¥¯¥¿Ê¸»úÎó¤ÎÂå¤ï¤ê
+         ¤Ë¥Þ¥ë¥Á¥Ð¥¤¥Èʸ»úÎó¤ò¤È¤ë¤è¤¦¤Ë¤·¤¿¡£¥³¥ó¥È¥í¡¼¥ë¥³¡¼¥É¤òÈó
+         ASCII ¤È¤ß¤Ê¤¹¤è¤¦¤Ë¤·¤¿¡£
+         get_next_word_len(): ¿·µ¬¡£¼¡¤Îñ¸ì¤ÎŤµ¤òÊÖ¤¹¡£
+         is_next_mbs(), find_wspace(): ºï½ü¡£
+       * src/quoted-printable.[ch]: ¿·µ¬¡£
+         qp_decode_line(): QP ¹Ô¤ò1¹Ô¥Ç¥³¡¼¥É¤¹¤ë¡£
+         qp_decode_q_encoding(): MIME ¥Ø¥Ã¥ÀÃæ¤Î Q Éä¹æ²½¤µ¤ì¤¿Ê¸»úÎó¤ò
+         ¥Ç¥³¡¼¥É¤¹¤ë¡£
+         qp_get_q_encoding_len(): Ê¸»úÎó¤ò Q Éä¹æ²½¤·¤¿¤È¤­¤ÎŤµ¤òÊÖ¤¹¡£
+         qp_q_encode(): Ê¸»úÎó¤ò Q Éä¹æ²½¤¹¤ë(RFC 2047)¡£
+       * src/unmime.c: quoted-printable ´ØÏ¢¤Î´Ø¿ô¤ò quoted-printable.c
+         ¤Ë°ÜÆ°¡£
+
 2002-12-05
 
        * src/send.c: send_message_local(): ¥É¥Ã¥È1ʸ»ú¤À¤±¤Î¹Ô¤ò¥¨¥¹¥±¡¼¥×
index 31868a995ca2ce024ef624330b39d5aef89f8723..db4d72f4a0e7efc8e8b7a10e892cee0c98952bd7 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=8
 MICRO_VERSION=6
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=claws102
+EXTRA_VERSION=claws103
 VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION$EXTRA_VERSION
 
 dnl set $target
index 1be0ffc89de013b42db64e5f0e948a0d0fb65786..b11aed446c5a0cdb760c8ac13f2877f4d92719d6 100644 (file)
 
 #include "intl.h"
 #include "codeconv.h"
+#include "unmime.h"
 #include "base64.h"
+#include "quoted-printable.h"
 #include "utils.h"
 #include "prefs_common.h"
-#include "unmime.h"
 
 typedef enum
 {
@@ -1049,417 +1050,168 @@ void conv_unmime_header(gchar *outbuf, gint outlen, const gchar *str,
                unmime_header(outbuf, str);
 }
 
-#define MAX_ENCLEN     75
 #define MAX_LINELEN    76
+#define MIMESEP_BEGIN  "=?"
+#define MIMESEP_END    "?="
 
 #define B64LEN(len)    ((len) / 3 * 4 + ((len) % 3 ? 4 : 0))
 
-#if HAVE_LIBJCONV
+#define LBREAK_IF_REQUIRED(cond)                               \
+{                                                              \
+       if (len - (destp - dest) < MAX_LINELEN) {               \
+               *destp = '\0';                                  \
+               return;                                         \
+       }                                                       \
+                                                               \
+       if (cond) {                                             \
+               if (destp > dest && isspace(*(destp - 1)))      \
+                       destp--;                                \
+               *destp++ = '\n';                                \
+               *destp++ = ' ';                                 \
+               left = MAX_LINELEN - 1;                         \
+       }                                                       \
+}
+
 void conv_encode_header(gchar *dest, gint len, const gchar *src,
                        gint header_len)
 {
-       wchar_t *wsrc;
-       wchar_t *wsrcp;
-       gchar *destp;
-       size_t line_len, mimehdr_len, mimehdr_begin_len;
-       gchar *mimehdr_init = "=?";
-       gchar *mimehdr_end = "?=";
-       gchar *mimehdr_enctype = "?B?";
-       const gchar *mimehdr_charset;
-
-       /* g_print("src = %s\n", src); */
-       mimehdr_charset = conv_get_outgoing_charset_str();
-
-       /* convert to wide-character string */
-       wsrcp = wsrc = strdup_mbstowcs(src);
-       if (!wsrc) {
-               g_warning("Can't convert string to wide characters.\n");
-               strncpy2(dest, src, len);
-               return;
+       const gchar *cur_encoding;
+       const gchar *out_encoding;
+       gint mimestr_len;
+       gchar *mimesep_enc;
+       gint left;
+       const gchar *srcp = src;
+       gchar *destp = dest;
+       gboolean use_base64;
+
+       if (MB_CUR_MAX > 1) {
+               use_base64 = TRUE;
+               mimesep_enc = "?B?";
+       } else {
+               use_base64 = FALSE;
+               mimesep_enc = "?Q?";
        }
 
-       mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
-               strlen(mimehdr_charset) + strlen(mimehdr_enctype);
-       mimehdr_begin_len = strlen(mimehdr_init) +
-               strlen(mimehdr_charset) + strlen(mimehdr_enctype);
-       line_len = header_len;
-       destp = dest;
-       *dest = '\0';
-
-       while (*wsrcp) {
-               wchar_t *wp, *wtmp, *wtmpp;
-               gint nspc = 0;
-               gboolean str_is_non_ascii;
-
-               /* irresponsible buffer overrun check */
-               if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
-
-               /* encode string including space
-                  if non-ASCII string follows */
-               if (is_next_nonascii(wsrcp)) {
-                       wp = wsrcp;
-                       while ((wp = find_wspace(wp)) != NULL)
-                               if (!is_next_nonascii(wp)) break;
-                       str_is_non_ascii = TRUE;
-               } else {
-                       wp = find_wspace(wsrcp);
-                       str_is_non_ascii = FALSE;
-               }
-
-               if (wp != NULL) {
-                       wtmp = wcsndup(wsrcp, wp - wsrcp);
-                       wsrcp = wp + 1;
-                       while (iswspace(wsrcp[nspc])) nspc++;
-               } else {
-                       wtmp = wcsdup(wsrcp);
-                       wsrcp += wcslen(wsrcp);
-               }
-
-               wtmpp = wtmp;
-
-               do {
-                       gint tlen = 0;
-                       gchar *tmp; /* internal codeset */
-                       gchar *raw; /* converted, but not base64 encoded */
-                       register gchar *tmpp;
-                       gint raw_len;
-
-                       tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
-                       *tmp = '\0';
-                       raw = g_strdup("");
-                       raw_len = 0;
-
-                       while (*wtmpp != (wchar_t)0) {
-                               gint mbl;
-                               gint dummy;
-                               gchar *raw_new = NULL;
-                               int raw_new_len = 0;
-                               const gchar *src_codeset;
-
-                               mbl = wctomb(tmpp, *wtmpp);
-                               if (mbl == -1) {
-                                       g_warning("invalid wide character\n");
-                                       wtmpp++;
-                                       continue;
-                               }
-                               /* g_free(raw); */
-                               src_codeset = conv_get_current_charset_str();
-                               /* printf ("tmp = %s, tlen = %d, mbl\n",
-                                       tmp, tlen, mbl); */
-                               if (jconv_alloc_conv(tmp, tlen + mbl,
-                                                    &raw_new, &raw_new_len,
-                                                    &src_codeset, 1,
-                                                    &dummy, mimehdr_charset)
-                                   != 0) {
-                                       g_warning("can't convert\n");
-                                       tmpp[0] = '\0';
-                                       wtmpp++;
-                                       continue;
-                               }
-                               if (str_is_non_ascii) {
-                                       gint dlen = mimehdr_len +
-                                               B64LEN(raw_len);
-                                       if ((line_len + dlen +
-                                            (*(wtmpp + 1) ? 0 : nspc) +
-                                            (line_len > 1 ? 1 : 0))
-                                           > MAX_LINELEN) {
-                                               g_free(raw_new);
-                                               if (tlen == 0) {
-                                                       *destp++ = '\n';
-                                                       *destp++ = ' ';
-                                                       line_len = 1;
-                                                       continue;
-                                               } else {
-                                                       *tmpp = '\0';
-                                                       break;
-                                               }
-                                       }
-                               } else if ((line_len + tlen + mbl +
-                                           (*(wtmpp + 1) ? 0 : nspc) +
-                                           (line_len > 1 ? 1 : 0))
-                                          > MAX_LINELEN) {
-                                       g_free(raw_new);
-                                       if (1 + tlen + mbl +
-                                           (*(wtmpp + 1) ? 0 : nspc)
-                                           >= MAX_LINELEN) {
-                                               *tmpp = '\0';
-                                               break;
-                                       }
-                                       *destp++ = '\n';
-                                       *destp++ = ' ';
-                                       line_len = 1;
-                                       continue;
-                               }
-
-                               tmpp += mbl;
-                               *tmpp = '\0';
-
-                               tlen += mbl;
-
-                               g_free(raw);
-                               raw = raw_new;
-                               raw_len = raw_new_len;
-
-                               wtmpp++;
-                       }
-                       /* g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
-                               tmp, tlen, mb_seqlen); */
-
-                       if (tlen == 0 || raw_len == 0) {
-                               g_free(tmp);
-                               g_free(raw);
-                               continue;
-                       }
-
-                       if (line_len > 1 && destp > dest) {
-                               *destp++ = ' ';
-                               *destp = '\0';
-                               line_len++;
-                       }
-
-                       if (str_is_non_ascii) {
-                               g_snprintf(destp, len - strlen(dest), "%s%s%s",
-                                          mimehdr_init, mimehdr_charset,
-                                          mimehdr_enctype);
-                               destp += mimehdr_begin_len;
-                               line_len += mimehdr_begin_len;
+       cur_encoding = conv_get_current_charset_str();
+       out_encoding = conv_get_outgoing_charset_str();
+       if (!strcmp(out_encoding, "US-ASCII"))
+               out_encoding = "ISO-8859-1";
 
-                               base64_encode(destp, raw, raw_len);
-                               line_len += strlen(destp);
-                               destp += strlen(destp);
+       mimestr_len = strlen(MIMESEP_BEGIN) + strlen(out_encoding) +
+               strlen(mimesep_enc) + strlen(MIMESEP_END);
 
-                               strcpy(destp, mimehdr_end);
-                               destp += strlen(mimehdr_end);
-                               line_len += strlen(mimehdr_end);
-                       } else {
-                               strcpy(destp, tmp);
-                               line_len += strlen(destp);
-                               destp += strlen(destp);
-                       }
+       left = MAX_LINELEN - header_len;
 
-                       g_free(tmp);
-                       g_free(raw);
-                       /* g_print("line_len = %d\n\n", line_len); */
-               } while (*wtmpp != (wchar_t)0);
+       while (*srcp) {
+               LBREAK_IF_REQUIRED(left <= 0);
 
-               while (iswspace(*wsrcp)) {
-                       gint mbl;
-
-                       mbl = wctomb(destp, *wsrcp++);
-                       if (mbl != -1) {
-                               destp += mbl;
-                               line_len += mbl;
-                       }
+               while (isspace(*srcp)) {
+                       *destp++ = *srcp++;
+                       left--;
+                       LBREAK_IF_REQUIRED(left <= 0);
                }
-               *destp = '\0';
-
-               g_free(wtmp);
-       }
 
-       g_free(wsrc);
+               /* output as it is if the next word is ASCII string */
+               if (!is_next_nonascii(srcp)) {
+                       gint word_len;
 
-       /* g_print("dest = %s\n", dest); */
-}
-#else /* !HAVE_LIBJCONV */
-
-#define JIS_SEQLEN     3
-
-void conv_encode_header(gchar *dest, gint len, const gchar *src,
-                       gint header_len)
-{
-       wchar_t *wsrc;
-       wchar_t *wsrcp;
-       gchar *destp;
-       size_t line_len, mimehdr_len, mimehdr_begin_len;
-       gchar *mimehdr_init = "=?";
-       gchar *mimehdr_end = "?=";
-       gchar *mimehdr_enctype = "?B?";
-       const gchar *mimehdr_charset;
-       gboolean do_conv = FALSE;
-
-       /* g_print("src = %s\n", src); */
-       mimehdr_charset = conv_get_outgoing_charset_str();
-       if (strcmp(mimehdr_charset, "ISO-2022-JP") == 0)
-               do_conv = TRUE;
-       else if (strcmp(mimehdr_charset, "US-ASCII") == 0)
-               mimehdr_charset = "ISO-8859-1";
-
-       /* convert to wide-character string */
-       wsrcp = wsrc = strdup_mbstowcs(src);
-       if (!wsrc) {
-               g_warning("Can't convert string to wide characters.\n");
-               strncpy2(dest, src, len);
-               return;
-       }
-
-       mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
-                     strlen(mimehdr_charset) + strlen(mimehdr_enctype);
-       mimehdr_begin_len = strlen(mimehdr_init) +
-                           strlen(mimehdr_charset) + strlen(mimehdr_enctype);
-       line_len = header_len;
-       destp = dest;
-       *dest = '\0';
-
-       while (*wsrcp) {
-               wchar_t *wp, *wtmp, *wtmpp;
-               gint nspc = 0;
-               gboolean str_is_non_ascii;
-
-               /* irresponsible buffer overrun check */
-               if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
-
-               /* encode string including space
-                  if non-ASCII string follows */
-               if (is_next_nonascii(wsrcp)) {
-                       wp = wsrcp;
-                       while ((wp = find_wspace(wp)) != NULL)
-                               if (!is_next_nonascii(wp)) break;
-                       str_is_non_ascii = TRUE;
-               } else {
-                       wp = find_wspace(wsrcp);
-                       str_is_non_ascii = FALSE;
-               }
+                       word_len = get_next_word_len(srcp);
+                       LBREAK_IF_REQUIRED(left < word_len);
+                       while(*srcp && !isspace(*srcp)) {
+                               *destp++ = *srcp++;
+                               left--;
+                               LBREAK_IF_REQUIRED(left <= 0);
+                       }
 
-               if (wp != NULL) {
-                       wtmp = wcsndup(wsrcp, wp - wsrcp);
-                       wsrcp = wp + 1;
-                       while (iswspace(wsrcp[nspc])) nspc++;
-               } else {
-                       wtmp = wcsdup(wsrcp);
-                       wsrcp += wcslen(wsrcp);
+                       continue;
                }
 
-               wtmpp = wtmp;
-
-               do {
-                       gint prev_mbl = 1, tlen = 0, mb_seqlen = 0;
-                       gchar *tmp;
-                       register gchar *tmpp;
+               while (1) {
+                       gint mb_len = 0;
+                       gint cur_len = 0;
+                       gchar *part_str;
+                       gchar *out_str;
+                       gchar *enc_str;
+                       const gchar *p = srcp;
+                       gint out_str_len;
+                       gint out_enc_str_len;
+                       gint mime_block_len;
+                       gboolean cont = FALSE;
+
+                       while (*p != '\0') {
+                               if (isspace(*p) && !is_next_nonascii(p + 1))
+                                       break;
+
+                               mb_len = mblen(p, MB_CUR_MAX);
+                               if (mb_len < 0) {
+                                       g_warning("invalid multibyte character encountered\n");
+                                       break;
+                               }
 
-                       tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
-                       *tmp = '\0';
+                               Xstrndup_a(part_str, srcp, cur_len + mb_len, );
+                               out_str = conv_codeset_strdup
+                                       (part_str, cur_encoding, out_encoding);
+                               out_str_len = strlen(out_str);
 
-                       while (*wtmpp != (wchar_t)0) {
-                               gint mbl;
+                               if (use_base64)
+                                       out_enc_str_len = B64LEN(out_str_len);
+                               else
+                                       out_enc_str_len =
+                                               qp_get_q_encoding_len(out_str);
 
-                               mbl = wctomb(tmpp, *wtmpp);
-                               if (mbl == -1) {
-                                       g_warning("invalid wide character\n");
-                                       wtmpp++;
-                                       continue;
-                               }
+                               g_free(out_str);
 
-                               /* length of KI + KO */
-                               if (do_conv && prev_mbl == 1 && mbl == 2)
-                                       mb_seqlen += JIS_SEQLEN * 2;
-
-                               if (str_is_non_ascii) {
-                                       gint dlen = mimehdr_len +
-                                               B64LEN(tlen + mb_seqlen + mbl);
-
-                                       if ((line_len + dlen +
-                                            (*(wtmpp + 1) ? 0 : nspc) +
-                                            (line_len > 1 ? 1 : 0))
-                                           > MAX_LINELEN) {
-                                               if (tlen == 0) {
-                                                       *destp++ = '\n';
-                                                       *destp++ = ' ';
-                                                       line_len = 1;
-                                                       mb_seqlen = 0;
-                                                       continue;
-                                               } else {
-                                                       *tmpp = '\0';
-                                                       break;
-                                               }
-                                       }
-                               } else if ((line_len + tlen + mbl +
-                                           (*(wtmpp + 1) ? 0 : nspc) +
-                                           (line_len > 1 ? 1 : 0))
-                                          > MAX_LINELEN) {
-                                       if (1 + tlen + mbl +
-                                           (*(wtmpp + 1) ? 0 : nspc)
-                                           >= MAX_LINELEN) {
-                                               *tmpp = '\0';
-                                               break;
-                                       }
-                                       *destp++ = '\n';
-                                       *destp++ = ' ';
-                                       line_len = 1;
+                               if (mimestr_len + out_enc_str_len <= left) {
+                                       cur_len += mb_len;
+                                       p += mb_len;
+                               } else if (cur_len == 0) {
+                                       LBREAK_IF_REQUIRED(1);
                                        continue;
+                               } else {
+                                       cont = TRUE;
+                                       break;
                                }
-
-                               tmpp += mbl;
-                               *tmpp = '\0';
-
-                               tlen += mbl;
-                               prev_mbl = mbl;
-
-                               wtmpp++;
-                       }
-                       /* g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
-                               tmp, tlen, mb_seqlen); */
-
-                       if (tlen == 0) {
-                               g_free(tmp);
-                               continue;
                        }
 
-                       if (line_len > 1 && destp > dest) {
-                               *destp++ = ' ';
-                               *destp = '\0';
-                               line_len++;
-                       }
+                       if (cur_len > 0) {
+                               Xstrndup_a(part_str, srcp, cur_len, );
+                               out_str = conv_codeset_strdup
+                                       (part_str, cur_encoding, out_encoding);
+                               out_str_len = strlen(out_str);
 
-                       if (str_is_non_ascii) {
-                               gchar *raw;
+                               if (use_base64)
+                                       out_enc_str_len = B64LEN(out_str_len);
+                               else
+                                       out_enc_str_len =
+                                               qp_get_q_encoding_len(out_str);
 
-                               raw = g_new(gchar, tlen + mb_seqlen + 1);
-                               if (do_conv)
-                                       conv_euctojis(raw, tlen + mb_seqlen + 1,
-                                                     tmp);
+                               Xalloca(enc_str, out_enc_str_len + 1, );
+                               if (use_base64)
+                                       base64_encode(enc_str, out_str, out_str_len);
                                else
-                                       strcpy(raw, tmp);
-                               g_snprintf(destp, len - strlen(dest), "%s%s%s",
-                                          mimehdr_init, mimehdr_charset,
-                                          mimehdr_enctype);
-                               destp += mimehdr_begin_len;
-                               line_len += mimehdr_begin_len;
-
-                               base64_encode(destp, raw, strlen(raw));
-                               line_len += strlen(destp);
-                               destp += strlen(destp);
-
-                               strcpy(destp, mimehdr_end);
-                               destp += strlen(mimehdr_end);
-                               line_len += strlen(mimehdr_end);
-
-                               g_free(raw);
-                       } else {
-                               strcpy(destp, tmp);
-                               line_len += strlen(destp);
-                               destp += strlen(destp);
-                       }
+                                       qp_q_encode(enc_str, out_str);
 
-                       g_free(tmp);
-                       /* g_print("line_len = %d\n\n", line_len); */
-               } while (*wtmpp != (wchar_t)0);
+                               g_free(out_str);
 
-               while (iswspace(*wsrcp)) {
-                       gint mbl;
+                               /* output MIME-encoded string block */
+                               mime_block_len = mimestr_len + strlen(enc_str);
+                               g_snprintf(destp, mime_block_len + 1,
+                                          MIMESEP_BEGIN "%s%s%s" MIMESEP_END,
+                                          out_encoding, mimesep_enc, enc_str);
+                               destp += mime_block_len;
+                               srcp += cur_len;
 
-                       mbl = wctomb(destp, *wsrcp++);
-                       if (mbl != -1) {
-                               destp += mbl;
-                               line_len += mbl;
+                               left -= mime_block_len;
                        }
-               }
-               *destp = '\0';
 
-               g_free(wtmp);
-       }
+                       LBREAK_IF_REQUIRED(cont);
 
-       g_free(wsrc);
+                       if (cur_len == 0)
+                               break;
+               }
+       }
 
-       /* g_print("dest = %s\n", dest); */
+       *destp = '\0';
 }
-#endif /* HAVE_LIBJCONV */
+
+#undef LBREAK_IF_REQUIRED
index 6a9d3250c8f13e866b10706aab605391c645e4d7..86a03cda52222ad5b64f4f785abaeb6a2b22d29d 100644 (file)
@@ -6,6 +6,7 @@ libsylpheedcommon_la_SOURCES = \
        log.c log.h \
        md5.c md5.h \
        nntp.c nntp.h \
+       quoted-printable.c quoted-printable.h \
        session.c session.h \
        smtp.c smtp.h \
        socket.c socket.h \
diff --git a/src/common/quoted-printable.c b/src/common/quoted-printable.c
new file mode 100644 (file)
index 0000000..df6cca4
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2002 Hiroyuki Yamamoto
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <glib.h>
+#include <ctype.h>
+
+static gboolean get_hex_value(guchar *out, gchar c1, gchar c2);
+static void get_hex_str(gchar *out, guchar ch);
+
+gint qp_decode_line(gchar *str)
+{
+       gchar *inp = str, *outp = str;
+
+       while (*inp != '\0') {
+               if (*inp == '=') {
+                       if (inp[1] && inp[2] &&
+                           get_hex_value(outp, inp[1], inp[2]) == TRUE) {
+                               inp += 3;
+                       } else if (inp[1] == '\0' || isspace(inp[1])) {
+                               /* soft line break */
+                               break;
+                       } else {
+                               /* broken QP string */
+                               *outp = *inp++;
+                       }
+               } else {
+                       *outp = *inp++;
+               }
+               outp++;
+       }
+
+       *outp = '\0';
+
+       return outp - str;
+}
+
+gint qp_decode_q_encoding(guchar *out, const gchar *in, gint inlen)
+{
+       const gchar *inp = in;
+       guchar *outp = out;
+
+       if (inlen < 0)
+               inlen = G_MAXINT;
+
+       while (inp - in < inlen && *inp != '\0') {
+               if (*inp == '=' && inp + 3 - in <= inlen) {
+                       if (get_hex_value(outp, inp[1], inp[2]) == TRUE) {
+                               inp += 3;
+                       } else {
+                               *outp = *inp++;
+                       }
+               } else if (*inp == '_') {
+                       *outp = ' ';
+                       inp++;
+               } else {
+                       *outp = *inp++;
+               }
+               outp++;
+       }
+
+       *outp = '\0';
+
+       return outp - out;
+}
+
+gint qp_get_q_encoding_len(const guchar *str)
+{
+       const guchar *inp = str;
+       gint len = 0;
+
+       while (*inp != '\0') {
+               if (*inp == 0x20)
+                       len++;
+               else if (*inp == '=' || *inp == '?' || *inp == '_' ||
+                        *inp < 32 || *inp > 127 || isspace(*inp))
+                       len += 3;
+               else
+                       len++;
+
+               inp++;
+       }
+
+       return len;
+}
+
+void qp_q_encode(gchar *out, const guchar *in)
+{
+       const guchar *inp = in;
+       gchar *outp = out;
+
+       while (*inp != '\0') {
+               if (*inp == 0x20)
+                       *outp++ = '_';
+               else if (*inp == '=' || *inp == '?' || *inp == '_' ||
+                        *inp < 32 || *inp > 127 || isspace(*inp)) {
+                       *outp++ = '=';
+                       get_hex_str(outp, *inp);
+                       outp += 2;
+               } else
+                       *outp++ = *inp;
+
+               inp++;
+       }
+
+       *outp = '\0';
+}
+
+#define HEX_TO_INT(val, hex)                   \
+{                                              \
+       gchar c = hex;                          \
+                                               \
+       if ('0' <= c && c <= '9') {             \
+               val = c - '0';                  \
+       } else if ('a' <= c && c <= 'f') {      \
+               val = c - 'a' + 10;             \
+       } else if ('A' <= c && c <= 'F') {      \
+               val = c - 'A' + 10;             \
+       } else {                                \
+               val = -1;                       \
+       }                                       \
+}
+
+static gboolean get_hex_value(guchar *out, gchar c1, gchar c2)
+{
+       gint hi, lo;
+
+       HEX_TO_INT(hi, c1);
+       HEX_TO_INT(lo, c2);
+
+       if (hi == -1 || lo == -1)
+               return FALSE;
+
+       *out = (hi << 4) + lo;
+       return TRUE;
+}
+
+#define INT_TO_HEX(hex, val)           \
+{                                      \
+       if ((val) < 10)                 \
+               hex = '0' + (val);      \
+       else                            \
+               hex = 'A' + (val) - 10; \
+}
+
+static void get_hex_str(gchar *out, guchar ch)
+{
+       gchar hex;
+
+       INT_TO_HEX(hex, ch >> 4);
+       *out++ = hex;
+       INT_TO_HEX(hex, ch & 0x0f);
+       *out++ = hex;
+}
diff --git a/src/common/quoted-printable.h b/src/common/quoted-printable.h
new file mode 100644 (file)
index 0000000..8e31a6a
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2002 Hiroyuki Yamamoto
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __QUOTED_PRINTABLE_H__
+#define __QUOTED_PRINTABLE_H__
+
+#include <glib.h>
+
+gint qp_decode_line            (gchar          *str);
+gint qp_decode_q_encoding      (guchar         *out,
+                                const gchar    *in,
+                                gint            inlen);
+gint qp_get_q_encoding_len     (const guchar   *str);
+void qp_q_encode               (gchar          *out,
+                                const guchar   *in);
+
+#endif /* __UNMIME_H__ */
index 7c2873680ed4a979bcf3b1c182f52039d9464ab4..d655e7e03c22f6b67c5e688ab6f364d04d7d44b8 100644 (file)
@@ -470,52 +470,29 @@ wchar_t *wcscasestr(const wchar_t *haystack, const wchar_t *needle)
 }
 
 /* Examine if next block is non-ASCII string */
-gboolean is_next_nonascii(const wchar_t *s)
+gboolean is_next_nonascii(const guchar *s)
 {
-       const wchar_t *wp;
+       const guchar *p;
 
        /* skip head space */
-       for (wp = s; *wp != (wchar_t)0 && iswspace(*wp); wp++)
+       for (p = s; *p != '\0' && isspace(*p); p++)
                ;
-       for (; *wp != (wchar_t)0 && !iswspace(*wp); wp++) {
-               if (*wp > 127)
+       for (; *p != '\0' && !isspace(*p); p++) {
+               if (*p > 127 || *p < 32)
                        return TRUE;
        }
 
        return FALSE;
 }
 
-/* Examine if next block is multi-byte string */
-gboolean is_next_mbs(const wchar_t *s)
+gint get_next_word_len(const gchar *s)
 {
-       gint mbl;
-       const wchar_t *wp;
-       gchar tmp[MB_LEN_MAX];
+       gint len = 0;
 
-       /* skip head space */
-       for (wp = s; *wp != (wchar_t)0 && iswspace(*wp); wp++)
+       for (; *s != '\0' && !isspace(*s); s++, len++)
                ;
-       for (; *wp != (wchar_t)0 && !iswspace(*wp); wp++) {
-               mbl = wctomb(tmp, *wp);
-               if (mbl > 1)
-                       return TRUE;
-       }
 
-       return FALSE;
-}
-
-wchar_t *find_wspace(const wchar_t *s)
-{
-       const wchar_t *wp;
-
-       for (wp = s; *wp != (wchar_t)0 && iswspace(*wp); wp++)
-               ;
-       for (; *wp != (wchar_t)0; wp++) {
-               if (iswspace(*wp))
-                       return (wchar_t *)wp;
-       }
-
-       return NULL;
+       return len;
 }
 
 /* compare subjects */
index c33f201a5d3a99f8befd400ce9205ae4364712f0..d02b2be6f2bbc622da1c82c1bfda2e0a8d674b4f 100644 (file)
@@ -213,9 +213,8 @@ gint wcsncasecmp            (const wchar_t *s1,
 wchar_t *wcscasestr            (const wchar_t *haystack,
                                 const wchar_t *needle);
 
-gboolean is_next_nonascii      (const wchar_t *s);
-gboolean is_next_mbs           (const wchar_t *s);
-wchar_t *find_wspace           (const wchar_t *s);
+gboolean is_next_nonascii      (const guchar *s);
+gint get_next_word_len         (const gchar *s);
 
 /* functions for string parsing */
 gint subject_compare                   (const gchar    *s1,
index f6fdb696ce80a57299da2fd05c71d10ba0e9900a..e481db574a0f85985b49bc1938c60ca670182a14 100644 (file)
@@ -33,6 +33,7 @@
 #include "procmime.h"
 #include "procheader.h"
 #include "base64.h"
+#include "quoted-printable.h"
 #include "uuencode.h"
 #include "unmime.h"
 #include "html.h"
@@ -611,7 +612,7 @@ FILE *procmime_decode_content(FILE *outfp, FILE *infp, MimeInfo *mimeinfo)
                       (!boundary ||
                        !IS_BOUNDARY(buf, boundary, boundary_len))) {
                        gint len;
-                       len = unmime_quoted_printable_line(buf);
+                       len = qp_decode_line(buf);
                        fwrite(buf, len, 1, outfp);
                }
        } else if (mimeinfo->encoding_type == ENC_BASE64) {
index 1ba54c1f20c1f018bea5c8d0e2452bda4e542205..8649f473249712932ae61bcf7185a2df6e285a62 100644 (file)
 
 #include "codeconv.h"
 #include "base64.h"
+#include "quoted-printable.h"
 
 #define ENCODED_WORD_BEGIN     "=?"
 #define ENCODED_WORD_END       "?="
 
-static gboolean get_hex_value(gchar *out, gchar c1, gchar c2);
-
 /* Decodes headers based on RFC2045 and RFC2047. */
 
 void unmime_header(gchar *out, const gchar *str)
@@ -100,29 +99,11 @@ void unmime_header(gchar *out, const gchar *str)
                                            eword_end_p - (text_begin_p + 1));
                        decoded_text[len] = '\0';
                } else if (encoding == 'Q') {
-                       const gchar *ep = text_begin_p + 1;
-                       gchar *dp;
-
-                       dp = decoded_text = g_malloc(eword_end_p - ep + 1);
-
-                       while (ep < eword_end_p) {
-                               if (*ep == '=' && ep + 3 <= eword_end_p) {
-                                       if (get_hex_value(dp, ep[1], ep[2])
-                                           == TRUE) {
-                                               ep += 3;
-                                       } else {
-                                               *dp = *ep++;
-                                       }
-                               } else if (*ep == '_') {
-                                       *dp = ' ';
-                                       ep++;
-                               } else {
-                                       *dp = *ep++;
-                               }
-                               dp++;
-                       }
-
-                       *dp = '\0';
+                       decoded_text = g_malloc
+                               (eword_end_p - (text_begin_p + 1) + 1);
+                       len = qp_decode_q_encoding
+                               (decoded_text, text_begin_p + 1,
+                                eword_end_p - (text_begin_p + 1));
                } else {
                        memcpy(outp, p, eword_end_p + 2 - p);
                        outp += eword_end_p + 2 - p;
@@ -149,59 +130,3 @@ void unmime_header(gchar *out, const gchar *str)
 
        *outp = '\0';
 }
-
-gint unmime_quoted_printable_line(gchar *str)
-{
-       gchar *inp = str, *outp = str;
-
-       while (*inp != '\0') {
-               if (*inp == '=') {
-                       if (inp[1] && inp[2] &&
-                           get_hex_value(outp, inp[1], inp[2]) == TRUE) {
-                               inp += 3;
-                       } else if (inp[1] == '\0' || isspace(inp[1])) {
-                               /* soft line break */
-                               break;
-                       } else {
-                               /* broken QP string */
-                               *outp = *inp++;
-                       }
-               } else {
-                       *outp = *inp++;
-               }
-               outp++;
-       }
-
-       *outp = '\0';
-
-       return outp - str;
-}
-
-#define HEX_TO_INT(val, hex)                   \
-{                                              \
-       gchar c = hex;                          \
-                                               \
-       if ('0' <= c && c <= '9') {             \
-               val = c - '0';                  \
-       } else if ('a' <= c && c <= 'f') {      \
-               val = c - 'a' + 10;             \
-       } else if ('A' <= c && c <= 'F') {      \
-               val = c - 'A' + 10;             \
-       } else {                                \
-               val = -1;                       \
-       }                                       \
-}
-
-static gboolean get_hex_value(gchar *out, gchar c1, gchar c2)
-{
-       gint hi, lo;
-
-       HEX_TO_INT(hi, c1);
-       HEX_TO_INT(lo, c2);
-
-       if (hi == -1 || lo == -1)
-               return FALSE;
-
-       *out = (hi << 4) + lo;
-       return TRUE;
-}