2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2001 Hiroyuki Yamamoto
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #if (HAVE_WCTYPE_H && HAVE_WCHAR_H)
49 #include "prefs_common.h"
52 (((c) & 0xff) >= 0xa1 && ((c) & 0xff) <= 0xfe)
54 (((c) & 0xff) == 0x8e || ((c) & 0xff) == 0x8f)
55 #define isunprintablekanji(c) \
56 (((c) & 0xff) >= 0xa9 && ((c) & 0xff) <= 0xaf)
58 void conv_jistoeuc(gchar *outbuf, gint outlen, const gchar *inbuf)
60 KCC_filter(outbuf, "EUC", (gchar *)inbuf, "JISBB", 0, 0, 0);
63 void conv_euctojis(gchar *outbuf, gint outlen, const gchar *inbuf)
67 inlen = strlen(inbuf);
68 if (iskanji(inbuf[inlen - 1]) || iseucss(inbuf[inlen - 1])) {
69 /* if tail end of the string is not ended with ascii,
70 add dummy return code. */
71 gchar *tmpin, *tmpout;
73 /* length of original string + '\n' + '\0' */
74 tmpin = alloca(inlen + 2);
76 g_warning(_("can't allocate memory\n"));
77 KCC_filter(outbuf, "JISBB", (gchar *)inbuf, "EUC",
83 tmpin[inlen + 1] = '\0';
85 tmpout = alloca(outlen + 1);
87 g_warning(_("can't allocate memory\n"));
88 KCC_filter(outbuf, "JISBB", (gchar *)inbuf, "EUC",
93 KCC_filter(tmpout, "JISBB", tmpin, "EUC", 0, 0, 0);
95 if (tmpout[len - 1] == '\n')
96 tmpout[len - 1] = '\0';
97 strncpy2(outbuf, tmpout, outlen);
99 KCC_filter(outbuf, "JISBB", (gchar *)inbuf, "EUC", 0, 0, 0);
102 void conv_sjistoeuc(gchar *outbuf, gint outlen, const gchar *inbuf)
104 KCC_filter(outbuf, "EUC", (gchar *)inbuf, "SJIS", 0, 0, 0);
107 void conv_anytoeuc(gchar *outbuf, gint outlen, const gchar *inbuf)
109 KCC_filter(outbuf, "EUC", (gchar *)inbuf, "AUTO", 0, 0, 0);
112 void conv_anytojis(gchar *outbuf, gint outlen, const gchar *inbuf)
114 KCC_filter(outbuf, "JISBB", (gchar *)inbuf, "AUTO", 0, 0, 0);
117 #define SUBST_CHAR '_'
119 void conv_unreadable_eucjp(gchar *str)
121 register guchar *p = str;
125 /* convert CR+LF -> LF */
126 if (*p == '\r' && *(p + 1) == '\n')
127 memmove(p, p + 1, strlen(p));
128 /* printable 7 bit code */
130 } else if (iskanji(*p)) {
131 if (iskanji(*(p + 1)) && !isunprintablekanji(*p))
132 /* printable euc-jp code */
135 /* substitute unprintable code */
144 } else if (iseucss(*p)) {
145 if ((*(p + 1) & 0x80) != 0)
146 /* euc-jp hankaku kana */
151 /* substitute unprintable 1 byte code */
156 void conv_unreadable_8bit(gchar *str)
158 register guchar *p = str;
161 /* convert CR+LF -> LF */
162 if (*p == '\r' && *(p + 1) == '\n')
163 memmove(p, p + 1, strlen(p));
164 else if (!isascii(*p)) *p = SUBST_CHAR;
169 void conv_unreadable_latin(gchar *str)
171 register guchar *p = str;
174 /* convert CR+LF -> LF */
175 if (*p == '\r' && *(p + 1) == '\n')
176 memmove(p, p + 1, strlen(p));
177 else if ((*p & 0xff) >= 0x80 && (*p & 0xff) <= 0x9f)
185 void conv_mb_alnum(gchar *str)
187 static guchar char_tbl[] = {
189 NCV, ' ', NCV, NCV, ',', '.', NCV, ':',
190 ';', '?', '!', NCV, NCV, NCV, NCV, NCV,
192 NCV, NCV, NCV, NCV, NCV, NCV, NCV, NCV,
193 NCV, NCV, NCV, NCV, NCV, NCV, NCV, NCV,
195 NCV, NCV, NCV, NCV, NCV, NCV, NCV, NCV,
196 NCV, NCV, '(', ')', NCV, NCV, '[', ']',
198 '{', '}', NCV, NCV, NCV, NCV, NCV, NCV,
199 NCV, NCV, NCV, NCV, '+', '-', NCV, NCV,
201 NCV, '=', NCV, '<', '>', NCV, NCV, NCV,
202 NCV, NCV, NCV, NCV, NCV, NCV, NCV, NCV
205 register guchar *p = str;
212 register guchar ch = *(p + 1);
214 if (ch >= 0xb0 && ch <= 0xfa) {
219 memmove(p, p + 1, len);
225 } else if (*p == 0xa1) {
226 register guchar ch = *(p + 1);
228 if (ch >= 0xa0 && ch <= 0xef &&
229 NCV != char_tbl[ch - 0xa0]) {
230 *p = char_tbl[ch - 0xa0];
233 memmove(p, p + 1, len);
239 } else if (iskanji(*p)) {
249 void conv_jistodisp(gchar *outbuf, gint outlen, const gchar *inbuf)
251 conv_jistoeuc(outbuf, outlen, inbuf);
252 conv_unreadable_eucjp(outbuf);
255 void conv_sjistodisp(gchar *outbuf, gint outlen, const gchar *inbuf)
257 conv_sjistoeuc(outbuf, outlen, inbuf);
258 conv_unreadable_eucjp(outbuf);
261 void conv_euctodisp(gchar *outbuf, gint outlen, const gchar *inbuf)
263 strncpy2(outbuf, inbuf, outlen);
264 conv_unreadable_eucjp(outbuf);
267 void conv_ustodisp(gchar *outbuf, gint outlen, const gchar *inbuf)
269 strncpy2(outbuf, inbuf, outlen);
270 conv_unreadable_8bit(outbuf);
273 void conv_latintodisp(gchar *outbuf, gint outlen, const gchar *inbuf)
275 strncpy2(outbuf, inbuf, outlen);
276 conv_unreadable_latin(outbuf);
279 void conv_noconv(gchar *outbuf, gint outlen, const gchar *inbuf)
281 strncpy2(outbuf, inbuf, outlen);
284 CodeConverter *conv_code_converter_new(const gchar *charset)
288 conv = g_new0(CodeConverter, 1);
290 conv->code_conv_func = conv_get_code_conv_func(charset);
292 conv->charset_str = g_strdup(charset);
293 conv->charset = conv_get_charset_from_str(charset);
298 void conv_code_converter_destroy(CodeConverter *conv)
300 g_free(conv->charset_str);
304 gint conv_convert(CodeConverter *conv, gchar *outbuf, gint outlen,
310 str = conv_codeset_strdup(inbuf, conv->charset_str, NULL);
314 strncpy2(outbuf, str, outlen);
317 #else /* !HAVE_LIBJCONV */
318 conv->code_conv_func(outbuf, outlen, inbuf);
324 gchar *conv_codeset_strdup(const gchar *inbuf,
325 const gchar *src_codeset, const gchar *dest_codeset)
331 const gchar *const *codesets;
333 #else /* !HAVE_LIBJCONV */
334 CharSet src_charset = C_AUTO, dest_charset = C_AUTO;
340 func = conv_get_code_conv_func(src_codeset);
341 if (func != conv_noconv) {
342 if (func == conv_jistodisp || func == conv_sjistodisp)
343 len = strlen(inbuf) * 2 + 1;
345 len = strlen(inbuf) + 1;
347 if (!buf) return NULL;
348 func(buf, len, inbuf);
349 buf = g_realloc(buf, strlen(buf) + 1);
354 /* don't convert if src and dest codeset are identical */
355 if (src_codeset && dest_codeset &&
356 !strcasecmp(src_codeset, dest_codeset))
357 return g_strdup(inbuf);
361 codesets = &src_codeset;
364 codesets = jconv_info_get_pref_codesets(&n_codesets);
366 dest_codeset = conv_get_current_charset_str();
367 /* don't convert if current codeset is US-ASCII */
368 if (!strcasecmp(dest_codeset, CS_US_ASCII))
369 return g_strdup(inbuf);
372 if (jconv_alloc_conv(inbuf, strlen(inbuf), &buf, &len,
373 codesets, n_codesets,
374 &actual_codeset, dest_codeset)
378 g_warning("code conversion from %s to %s failed\n",
379 codesets && codesets[0] ? codesets[0] : "(unknown)",
383 #else /* !HAVE_LIBJCONV */
385 if (!strcasecmp(src_codeset, CS_EUC_JP) ||
386 !strcasecmp(src_codeset, CS_EUCJP))
387 src_charset = C_EUC_JP;
388 else if (!strcasecmp(src_codeset, CS_SHIFT_JIS) ||
389 !strcasecmp(src_codeset, "SHIFT-JIS") ||
390 !strcasecmp(src_codeset, "SJIS"))
391 src_charset = C_SHIFT_JIS;
392 if (dest_codeset && !strcasecmp(dest_codeset, CS_ISO_2022_JP))
393 dest_charset = C_ISO_2022_JP;
396 if ((src_charset == C_EUC_JP || src_charset == C_SHIFT_JIS) &&
397 dest_charset == C_ISO_2022_JP) {
398 len = (strlen(inbuf) + 1) * 3;
401 if (src_charset == C_EUC_JP)
402 conv_euctojis(buf, len, inbuf);
404 conv_anytojis(buf, len, inbuf);
405 buf = g_realloc(buf, strlen(buf) + 1);
408 buf = g_strdup(inbuf);
411 #endif /* !HAVE_LIBJCONV */
414 CodeConvFunc conv_get_code_conv_func(const gchar *charset)
416 CodeConvFunc code_conv;
419 if (conv_get_outgoing_charset() == C_ISO_2022_JP)
420 return conv_jistodisp;
425 if (!strcasecmp(charset, CS_ISO_2022_JP) ||
426 !strcasecmp(charset, CS_ISO_2022_JP_2))
427 code_conv = conv_jistodisp;
428 else if (!strcasecmp(charset, CS_US_ASCII))
429 code_conv = conv_ustodisp;
430 else if (!strncasecmp(charset, CS_ISO_8859_1, 10))
431 code_conv = conv_latintodisp;
433 else if (!strncasecmp(charset, "ISO-8859-", 9))
434 code_conv = conv_latintodisp;
436 else if (!strcasecmp(charset, CS_SHIFT_JIS) ||
437 !strcasecmp(charset, "SHIFT-JIS") ||
438 !strcasecmp(charset, "SJIS") ||
439 !strcasecmp(charset, "X-SJIS"))
440 code_conv = conv_sjistodisp;
441 else if (!strcasecmp(charset, CS_EUC_JP) ||
442 !strcasecmp(charset, CS_EUCJP))
443 code_conv = conv_euctodisp;
445 code_conv = conv_noconv;
450 static const struct {
454 {C_US_ASCII, CS_US_ASCII},
455 {C_US_ASCII, CS_ANSI_X3_4_1968},
457 {C_ISO_8859_1, CS_ISO_8859_1},
458 {C_ISO_8859_2, CS_ISO_8859_2},
459 {C_ISO_8859_4, CS_ISO_8859_4},
460 {C_ISO_8859_5, CS_ISO_8859_5},
461 {C_ISO_8859_7, CS_ISO_8859_7},
462 {C_ISO_8859_8, CS_ISO_8859_8},
463 {C_ISO_8859_9, CS_ISO_8859_9},
464 {C_ISO_8859_11, CS_ISO_8859_11},
465 {C_ISO_8859_13, CS_ISO_8859_13},
466 {C_ISO_8859_15, CS_ISO_8859_15},
467 {C_BALTIC, CS_BALTIC},
468 {C_CP1251, CS_CP1251},
469 {C_WINDOWS_1251, CS_WINDOWS_1251},
470 {C_KOI8_R, CS_KOI8_R},
471 {C_KOI8_U, CS_KOI8_U},
472 {C_ISO_2022_JP, CS_ISO_2022_JP},
473 {C_ISO_2022_JP_2, CS_ISO_2022_JP_2},
474 {C_EUC_JP, CS_EUC_JP},
475 {C_EUC_JP, CS_EUCJP},
476 {C_SHIFT_JIS, CS_SHIFT_JIS},
477 {C_ISO_2022_KR, CS_ISO_2022_KR},
478 {C_EUC_KR, CS_EUC_KR},
479 {C_ISO_2022_CN, CS_ISO_2022_CN},
480 {C_EUC_CN, CS_EUC_CN},
481 {C_GB2312, CS_GB2312},
482 {C_EUC_TW, CS_EUC_TW},
484 {C_TIS_620, CS_TIS_620},
485 {C_WINDOWS_874, CS_WINDOWS_874},
489 static const struct {
493 {"ja_JP.eucJP" , C_EUC_JP},
494 {"ja_JP.ujis" , C_EUC_JP},
495 {"ja_JP.EUC" , C_EUC_JP},
496 {"ja_JP.SJIS" , C_SHIFT_JIS},
497 {"ja_JP.JIS" , C_ISO_2022_JP},
498 {"ja_JP" , C_EUC_JP},
499 {"ko_KR" , C_EUC_KR},
500 {"zh_CN.GB2312" , C_GB2312},
501 {"zh_CN" , C_GB2312},
502 {"zh_TW.eucTW" , C_EUC_TW},
503 {"zh_TW.Big5" , C_BIG5},
506 {"ru_RU.KOI8-R" , C_KOI8_R},
507 {"ru_RU.CP1251" , C_CP1251},
509 {"en_US" , C_ISO_8859_1},
510 {"ca_ES" , C_ISO_8859_1},
511 {"da_DK" , C_ISO_8859_1},
512 {"de_DE" , C_ISO_8859_1},
513 {"nl_NL" , C_ISO_8859_1},
514 {"et_EE" , C_ISO_8859_1},
515 {"fi_FI" , C_ISO_8859_1},
516 {"fr_FR" , C_ISO_8859_1},
517 {"is_IS" , C_ISO_8859_1},
518 {"it_IT" , C_ISO_8859_1},
519 {"no_NO" , C_ISO_8859_1},
520 {"pt_PT" , C_ISO_8859_1},
521 {"pt_BR" , C_ISO_8859_1},
522 {"es_ES" , C_ISO_8859_1},
523 {"sv_SE" , C_ISO_8859_1},
525 {"hr_HR" , C_ISO_8859_2},
526 {"hu_HU" , C_ISO_8859_2},
527 {"pl_PL" , C_ISO_8859_2},
528 {"ro_RO" , C_ISO_8859_2},
529 {"sk_SK" , C_ISO_8859_2},
530 {"sl_SI" , C_ISO_8859_2},
531 {"ru_RU" , C_ISO_8859_5},
532 {"el_GR" , C_ISO_8859_7},
533 {"iw_IL" , C_ISO_8859_8},
534 {"tr_TR" , C_ISO_8859_9},
536 {"th_TH" , C_TIS_620},
537 /* {"th_TH" , C_WINDOWS_874}, */
538 /* {"th_TH" , C_ISO_8859_11}, */
540 {"lt_LT.iso88594" , C_ISO_8859_4},
541 {"lt_LT.ISO8859-4" , C_ISO_8859_4},
542 {"lt_LT.ISO_8859-4" , C_ISO_8859_4},
543 {"lt_LT" , C_ISO_8859_13},
544 {"lv_LV" , C_ISO_8859_13},
547 {"POSIX" , C_US_ASCII},
548 {"ANSI_X3.4-1968" , C_US_ASCII},
550 #endif /* !HAVE_LIBJCONV */
552 const gchar *conv_get_charset_str(CharSet charset)
556 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
557 if (charsets[i].charset == charset)
558 return charsets[i].name;
564 CharSet conv_get_charset_from_str(const gchar *charset)
568 if (!charset) return C_AUTO;
570 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
571 if (!strcasecmp(charsets[i].name, charset))
572 return charsets[i].charset;
578 CharSet conv_get_current_charset(void)
580 static CharSet cur_charset = -1;
584 const gchar *cur_codeset;
586 const gchar *cur_locale;
589 if (cur_charset != -1)
593 cur_codeset = jconv_info_get_current_codeset();
594 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
595 if (!strcasecmp(cur_codeset, charsets[i].name)) {
596 cur_charset = charsets[i].charset;
601 cur_locale = g_getenv("LC_ALL");
602 if (!cur_locale) cur_locale = g_getenv("LC_CTYPE");
603 if (!cur_locale) cur_locale = g_getenv("LANG");
604 if (!cur_locale) cur_locale = setlocale(LC_CTYPE, NULL);
606 debug_print("current locale: %s\n",
607 cur_locale ? cur_locale : "(none)");
610 cur_charset = C_US_ASCII;
614 if (strcasestr(cur_locale, "UTF-8")) {
615 cur_charset = C_UTF_8;
619 for (i = 0; i < sizeof(locale_table) / sizeof(locale_table[0]); i++) {
622 /* "ja_JP.EUC" matches with "ja_JP.eucJP" and "ja_JP.EUC" */
623 /* "ja_JP" matches with "ja_JP.xxxx" and "ja" */
624 if (!strncasecmp(cur_locale, locale_table[i].locale,
625 strlen(locale_table[i].locale))) {
626 cur_charset = locale_table[i].charset;
628 } else if ((p = strchr(locale_table[i].locale, '_')) &&
629 !strchr(p + 1, '.')) {
630 if (strlen(cur_locale) == 2 &&
631 !strncasecmp(cur_locale, locale_table[i].locale, 2)) {
632 cur_charset = locale_table[i].charset;
639 cur_charset = C_AUTO;
643 const gchar *conv_get_current_charset_str(void)
645 static const gchar *codeset = NULL;
648 codeset = conv_get_charset_str(conv_get_current_charset());
650 return codeset ? codeset : "US-ASCII";
653 CharSet conv_get_outgoing_charset(void)
655 static CharSet out_charset = -1;
658 gint i, j, n_pref_codesets;
659 const gchar *const *pref_codesets;
664 if (out_charset != -1)
668 /* skip US-ASCII and UTF-8 */
669 pref_codesets = jconv_info_get_pref_codesets(&n_pref_codesets);
670 for (i = 0; i < n_pref_codesets; i++) {
671 for (j = 3; j < sizeof(charsets) / sizeof(charsets[0]); j++) {
672 if (!strcasecmp(pref_codesets[i], charsets[j].name)) {
673 out_charset = charsets[j].charset;
679 for (i = 0; i < n_pref_codesets; i++) {
680 if (!strcasecmp(pref_codesets[i], "UTF-8")) {
681 out_charset = C_UTF_8;
686 out_charset = C_AUTO;
688 cur_charset = conv_get_current_charset();
689 switch (cur_charset) {
692 out_charset = C_ISO_2022_JP;
695 out_charset = cur_charset;
702 const gchar *conv_get_outgoing_charset_str(void)
707 if (prefs_common.outgoing_charset) {
708 if (!isalpha(prefs_common.outgoing_charset[0])) {
709 g_free(prefs_common.outgoing_charset);
710 prefs_common.outgoing_charset = g_strdup(CS_AUTO);
711 } else if (strcmp(prefs_common.outgoing_charset, CS_AUTO) != 0)
712 return prefs_common.outgoing_charset;
715 out_charset = conv_get_outgoing_charset();
716 str = conv_get_charset_str(out_charset);
718 return str ? str : "US-ASCII";
721 const gchar *conv_get_current_locale(void)
725 cur_locale = g_getenv("LC_ALL");
726 if (!cur_locale) cur_locale = g_getenv("LANG");
727 if (!cur_locale) cur_locale = setlocale(LC_CTYPE, NULL);
729 debug_print("current locale: %s\n",
730 cur_locale ? cur_locale : "(none)");
735 void conv_unmime_header_overwrite(gchar *str)
741 cur_charset = conv_get_current_charset();
744 Xstrdup_a(buf, str, return);
745 outlen = strlen(str) + 1;
746 UnMimeHeaderConv(buf, str, outlen);
747 if (cur_charset == C_EUC_JP) {
751 len = strlen(str) * 2 + 1;
752 Xalloca(tmp, len, return);
753 conv_jistodisp(tmp, len, str);
754 strncpy2(str, tmp, outlen);
757 if (cur_charset == C_EUC_JP) {
761 Xstrdup_a(buf, str, return);
762 outlen = strlen(str) + 1;
764 len = strlen(buf) * 2 + 1;
765 Xalloca(tmp, len, {strncpy2(str, buf, outlen); return;});
766 conv_jistodisp(tmp, len, buf);
767 strncpy2(str, tmp, outlen);
773 void conv_unmime_header(gchar *outbuf, gint outlen, const gchar *str,
774 const gchar *charset)
779 cur_charset = conv_get_current_charset();
780 Xstrdup_a(buf, str, return);
783 UnMimeHeaderConv(buf, outbuf, outlen);
786 strncpy2(outbuf, buf, outlen);
788 if (cur_charset == C_EUC_JP) {
791 len = strlen(outbuf) * 2 + 1;
792 Xalloca(buf, len, return);
793 conv_jistodisp(buf, len, outbuf);
794 strncpy2(outbuf, buf, outlen);
798 #define MAX_ENCLEN 75
799 #define MAX_LINELEN 76
801 #define B64LEN(len) ((len) / 3 * 4 + ((len) % 3 ? 4 : 0))
804 void conv_encode_header(gchar *dest, gint len, const gchar *src,
810 size_t line_len, mimehdr_len, mimehdr_begin_len;
811 gchar *mimehdr_init = "=?";
812 gchar *mimehdr_end = "?=";
813 gchar *mimehdr_enctype = "?B?";
814 const gchar *mimehdr_charset;
816 /* g_print("src = %s\n", src); */
817 mimehdr_charset = conv_get_outgoing_charset_str();
819 /* convert to wide-character string */
820 wsrcp = wsrc = strdup_mbstowcs(src);
822 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
823 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
824 mimehdr_begin_len = strlen(mimehdr_init) +
825 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
826 line_len = header_len;
830 g_return_if_fail(wsrc != NULL);
833 wchar_t *wp, *wtmp, *wtmpp;
836 /* irresponsible buffer overrun check */
837 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
839 /* encode string including space
840 if non-ASCII string follows */
841 if (is_next_nonascii(wsrcp)) {
843 while ((wp = find_wspace(wp)) != NULL)
844 if (!is_next_nonascii(wp)) break;
846 wp = find_wspace(wsrcp);
849 wtmp = wcsndup(wsrcp, wp - wsrcp);
851 while (iswspace(wsrcp[nspc])) nspc++;
853 wtmp = wcsdup(wsrcp);
854 wsrcp += wcslen(wsrcp);
860 gint tlen = 0, str_ascii = 1;
861 gchar *tmp; /* internal codeset */
862 gchar *raw; /* converted, but not base64 encoded */
863 register gchar *tmpp;
866 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
871 while (*wtmpp != (wchar_t)0) {
874 gchar *raw_new = NULL;
876 const gchar *src_codeset;
878 if (*wtmpp < 32 || *wtmpp >= 127)
880 mbl = wctomb(tmpp, *wtmpp);
882 g_warning("invalid wide character\n");
887 src_codeset = conv_get_current_charset_str();
888 /* printf ("tmp = %s, tlen = %d, mbl\n",
890 if (jconv_alloc_conv(tmp, tlen + mbl,
891 &raw_new, &raw_new_len,
893 &dummy, mimehdr_charset)
895 g_warning("can't convert\n");
901 gint dlen = mimehdr_len +
903 if ((line_len + dlen +
904 (*(wtmpp + 1) ? 0 : nspc) +
905 (line_len > 1 ? 1 : 0))
919 } else if ((line_len + tlen + mbl +
920 (*(wtmpp + 1) ? 0 : nspc) +
921 (line_len > 1 ? 1 : 0))
925 (*(wtmpp + 1) ? 0 : nspc)
943 raw_len = raw_new_len;
947 /* g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
948 tmp, tlen, mb_seqlen); */
950 if (tlen == 0 || raw_len == 0) {
956 if (line_len > 1 && destp > dest) {
963 g_snprintf(destp, len - strlen(dest), "%s%s%s",
964 mimehdr_init, mimehdr_charset,
966 destp += mimehdr_begin_len;
967 line_len += mimehdr_begin_len;
969 to64frombits(destp, raw, raw_len);
970 line_len += strlen(destp);
971 destp += strlen(destp);
973 strcpy(destp, mimehdr_end);
974 destp += strlen(mimehdr_end);
975 line_len += strlen(mimehdr_end);
978 line_len += strlen(destp);
979 destp += strlen(destp);
984 /* g_print("line_len = %d\n\n", line_len); */
985 } while (*wtmpp != (wchar_t)0);
987 while (iswspace(*wsrcp)) {
990 mbl = wctomb(destp, *wsrcp++);
1003 /* g_print("dest = %s\n", dest); */
1005 #else /* !HAVE_LIBJCONV */
1007 #define JIS_SEQLEN 3
1009 void conv_encode_header(gchar *dest, gint len, const gchar *src,
1015 size_t line_len, mimehdr_len, mimehdr_begin_len;
1016 gchar *mimehdr_init = "=?";
1017 gchar *mimehdr_end = "?=";
1018 gchar *mimehdr_enctype = "?B?";
1019 const gchar *mimehdr_charset;
1021 /* g_print("src = %s\n", src); */
1022 mimehdr_charset = conv_get_outgoing_charset_str();
1023 if (strcmp(mimehdr_charset, "ISO-2022-JP") != 0) {
1024 /* currently only supports Japanese */
1025 strncpy2(dest, src, len);
1029 /* convert to wide-character string */
1030 wsrcp = wsrc = strdup_mbstowcs(src);
1032 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
1033 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
1034 mimehdr_begin_len = strlen(mimehdr_init) +
1035 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
1036 line_len = header_len;
1040 g_return_if_fail(wsrc != NULL);
1043 wchar_t *wp, *wtmp, *wtmpp;
1046 /* irresponsible buffer overrun check */
1047 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
1049 /* encode string including space
1050 if non-ASCII string follows */
1051 if (is_next_nonascii(wsrcp)) {
1053 while ((wp = find_wspace(wp)) != NULL)
1054 if (!is_next_nonascii(wp)) break;
1056 wp = find_wspace(wsrcp);
1059 wtmp = wcsndup(wsrcp, wp - wsrcp);
1061 while (iswspace(wsrcp[nspc])) nspc++;
1063 wtmp = wcsdup(wsrcp);
1064 wsrcp += wcslen(wsrcp);
1070 gint prev_mbl = 1, tlen = 0, mb_seqlen = 0;
1072 register gchar *tmpp;
1074 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
1077 while (*wtmpp != (wchar_t)0) {
1080 mbl = wctomb(tmpp, *wtmpp);
1082 g_warning("invalid wide character\n");
1087 /* length of KI + KO */
1088 if (prev_mbl == 1 && mbl == 2)
1089 mb_seqlen += JIS_SEQLEN * 2;
1092 gint dlen = mimehdr_len +
1093 B64LEN(tlen + mb_seqlen + mbl);
1095 if ((line_len + dlen +
1096 (*(wtmpp + 1) ? 0 : nspc) +
1097 (line_len > 1 ? 1 : 0))
1110 } else if ((line_len + tlen + mbl +
1111 (*(wtmpp + 1) ? 0 : nspc) +
1112 (line_len > 1 ? 1 : 0))
1114 if (1 + tlen + mbl +
1115 (*(wtmpp + 1) ? 0 : nspc)
1134 /* g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
1135 tmp, tlen, mb_seqlen); */
1142 if (line_len > 1 && destp > dest) {
1151 tmp_jis = g_new(gchar, tlen + mb_seqlen + 1);
1152 conv_euctojis(tmp_jis,
1153 tlen + mb_seqlen + 1, tmp);
1154 g_snprintf(destp, len - strlen(dest), "%s%s%s",
1155 mimehdr_init, mimehdr_charset,
1157 destp += mimehdr_begin_len;
1158 line_len += mimehdr_begin_len;
1160 to64frombits(destp, tmp_jis, strlen(tmp_jis));
1161 line_len += strlen(destp);
1162 destp += strlen(destp);
1164 strcpy(destp, mimehdr_end);
1165 destp += strlen(mimehdr_end);
1166 line_len += strlen(mimehdr_end);
1171 line_len += strlen(destp);
1172 destp += strlen(destp);
1176 /* g_print("line_len = %d\n\n", line_len); */
1177 } while (*wtmpp != (wchar_t)0);
1179 while (iswspace(*wsrcp)) {
1182 mbl = wctomb(destp, *wsrcp++);
1195 /* g_print("dest = %s\n", dest); */
1197 #endif /* HAVE_LIBJCONV */