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)
379 #else /* !HAVE_LIBJCONV */
381 if (!strcasecmp(src_codeset, CS_EUC_JP) ||
382 !strcasecmp(src_codeset, "EUCJP"))
383 src_charset = C_EUC_JP;
384 else if (!strcasecmp(src_codeset, CS_SHIFT_JIS) ||
385 !strcasecmp(src_codeset, "SHIFT-JIS") ||
386 !strcasecmp(src_codeset, "SJIS"))
387 src_charset = C_SHIFT_JIS;
388 if (dest_codeset && !strcasecmp(dest_codeset, CS_ISO_2022_JP))
389 dest_charset = C_ISO_2022_JP;
392 if ((src_charset == C_EUC_JP || src_charset == C_SHIFT_JIS) &&
393 dest_charset == C_ISO_2022_JP) {
394 len = (strlen(inbuf) + 1) * 3;
397 if (src_charset == C_EUC_JP)
398 conv_euctojis(buf, len, inbuf);
400 conv_anytojis(buf, len, inbuf);
401 buf = g_realloc(buf, strlen(buf) + 1);
404 buf = g_strdup(inbuf);
407 #endif /* !HAVE_LIBJCONV */
410 CodeConvFunc conv_get_code_conv_func(const gchar *charset)
412 CodeConvFunc code_conv;
415 if (conv_get_outgoing_charset() == C_ISO_2022_JP)
416 return conv_jistodisp;
421 if (!strcasecmp(charset, CS_ISO_2022_JP) ||
422 !strcasecmp(charset, CS_ISO_2022_JP_2))
423 code_conv = conv_jistodisp;
424 else if (!strcasecmp(charset, CS_US_ASCII))
425 code_conv = conv_ustodisp;
426 else if (!strncasecmp(charset, CS_ISO_8859_1, 10))
427 code_conv = conv_latintodisp;
429 else if (!strncasecmp(charset, "ISO-8859-", 9))
430 code_conv = conv_latintodisp;
432 else if (!strcasecmp(charset, CS_SHIFT_JIS) ||
433 !strcasecmp(charset, "SHIFT-JIS") ||
434 !strcasecmp(charset, "SJIS") ||
435 !strcasecmp(charset, "X-SJIS"))
436 code_conv = conv_sjistodisp;
437 else if (!strcasecmp(charset, CS_EUC_JP) ||
438 !strcasecmp(charset, "EUCJP"))
439 code_conv = conv_euctodisp;
441 code_conv = conv_noconv;
446 static const struct {
450 {C_US_ASCII, CS_US_ASCII},
451 {C_US_ASCII, CS_ANSI_X3_4_1968},
453 {C_ISO_8859_1, CS_ISO_8859_1},
454 {C_ISO_8859_2, CS_ISO_8859_2},
455 {C_ISO_8859_4, CS_ISO_8859_4},
456 {C_ISO_8859_5, CS_ISO_8859_5},
457 {C_ISO_8859_7, CS_ISO_8859_7},
458 {C_ISO_8859_8, CS_ISO_8859_8},
459 {C_ISO_8859_9, CS_ISO_8859_9},
460 {C_ISO_8859_13, CS_ISO_8859_13},
461 {C_ISO_8859_15, CS_ISO_8859_15},
462 {C_BALTIC, CS_BALTIC},
463 {C_CP1251, CS_CP1251},
464 {C_WINDOWS_1251, CS_WINDOWS_1251},
465 {C_KOI8_R, CS_KOI8_R},
466 {C_KOI8_U, CS_KOI8_U},
467 {C_ISO_2022_JP, CS_ISO_2022_JP},
468 {C_ISO_2022_JP_2, CS_ISO_2022_JP_2},
469 {C_EUC_JP, CS_EUC_JP},
470 {C_SHIFT_JIS, CS_SHIFT_JIS},
471 {C_ISO_2022_KR, CS_ISO_2022_KR},
472 {C_EUC_KR, CS_EUC_KR},
473 {C_ISO_2022_CN, CS_ISO_2022_CN},
474 {C_EUC_CN, CS_EUC_CN},
475 {C_GB2312, CS_GB2312},
476 {C_EUC_TW, CS_EUC_TW},
481 static const struct {
485 {"ja_JP.eucJP" , C_EUC_JP},
486 {"ja_JP.ujis" , C_EUC_JP},
487 {"ja_JP.EUC" , C_EUC_JP},
488 {"ja_JP.SJIS" , C_SHIFT_JIS},
489 {"ja_JP.JIS" , C_ISO_2022_JP},
490 {"ja_JP" , C_EUC_JP},
491 {"ko_KR" , C_EUC_KR},
492 {"zh_CN.GB2312" , C_GB2312},
493 {"zh_CN" , C_GB2312},
494 {"zh_TW.eucTW" , C_EUC_TW},
495 {"zh_TW.Big5" , C_BIG5},
498 {"ru_RU.KOI8-R" , C_KOI8_R},
499 {"ru_RU.CP1251" , C_CP1251},
501 {"en_US" , C_ISO_8859_1},
502 {"ca_ES" , C_ISO_8859_1},
503 {"da_DK" , C_ISO_8859_1},
504 {"de_DE" , C_ISO_8859_1},
505 {"nl_NL" , C_ISO_8859_1},
506 {"et_EE" , C_ISO_8859_1},
507 {"fi_FI" , C_ISO_8859_1},
508 {"fr_FR" , C_ISO_8859_1},
509 {"is_IS" , C_ISO_8859_1},
510 {"it_IT" , C_ISO_8859_1},
511 {"no_NO" , C_ISO_8859_1},
512 {"pt_PT" , C_ISO_8859_1},
513 {"pt_BR" , C_ISO_8859_1},
514 {"es_ES" , C_ISO_8859_1},
515 {"sv_SE" , C_ISO_8859_1},
517 {"hr_HR" , C_ISO_8859_2},
518 {"hu_HU" , C_ISO_8859_2},
519 {"pl_PL" , C_ISO_8859_2},
520 {"ro_RO" , C_ISO_8859_2},
521 {"sk_SK" , C_ISO_8859_2},
522 {"sl_SI" , C_ISO_8859_2},
523 {"ru_RU" , C_ISO_8859_5},
524 {"el_GR" , C_ISO_8859_7},
525 {"iw_IL" , C_ISO_8859_8},
526 {"tr_TR" , C_ISO_8859_9},
528 {"lt_LT.iso88594" , C_ISO_8859_4},
529 {"lt_LT.ISO8859-4" , C_ISO_8859_4},
530 {"lt_LT.ISO_8859-4" , C_ISO_8859_4},
531 {"lt_LT" , C_ISO_8859_13},
532 {"lv_LV" , C_ISO_8859_13},
535 {"POSIX" , C_US_ASCII},
536 {"ANSI_X3.4-1968" , C_US_ASCII},
538 #endif /* !HAVE_LIBJCONV */
540 const gchar *conv_get_charset_str(CharSet charset)
544 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
545 if (charsets[i].charset == charset)
546 return charsets[i].name;
552 CharSet conv_get_charset_from_str(const gchar *charset)
556 if (!charset) return C_AUTO;
558 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
559 if (!strcasecmp(charsets[i].name, charset))
560 return charsets[i].charset;
566 CharSet conv_get_current_charset(void)
568 static CharSet cur_charset = -1;
572 const gchar *cur_codeset;
574 const gchar *cur_locale;
577 if (cur_charset != -1)
581 cur_codeset = jconv_info_get_current_codeset();
582 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
583 if (!strcasecmp(cur_codeset, charsets[i].name)) {
584 cur_charset = charsets[i].charset;
589 cur_locale = g_getenv("LC_ALL");
590 if (!cur_locale) cur_locale = g_getenv("LC_CTYPE");
591 if (!cur_locale) cur_locale = g_getenv("LANG");
592 if (!cur_locale) cur_locale = setlocale(LC_CTYPE, NULL);
594 debug_print("current locale: %s\n",
595 cur_locale ? cur_locale : "(none)");
598 cur_charset = C_US_ASCII;
602 if (strcasestr(cur_locale, "UTF-8")) {
603 cur_charset = C_UTF_8;
607 for (i = 0; i < sizeof(locale_table) / sizeof(locale_table[0]); i++) {
610 /* "ja_JP.EUC" matches with "ja_JP.eucJP" and "ja_JP.EUC" */
611 /* "ja_JP" matches with "ja_JP.xxxx" and "ja" */
612 if (!strncasecmp(cur_locale, locale_table[i].locale,
613 strlen(locale_table[i].locale))) {
614 cur_charset = locale_table[i].charset;
616 } else if ((p = strchr(locale_table[i].locale, '_')) &&
617 !strchr(p + 1, '.')) {
618 if (strlen(cur_locale) == 2 &&
619 !strncasecmp(cur_locale, locale_table[i].locale, 2)) {
620 cur_charset = locale_table[i].charset;
627 cur_charset = C_AUTO;
631 const gchar *conv_get_current_charset_str(void)
633 static const gchar *codeset = NULL;
636 codeset = conv_get_charset_str(conv_get_current_charset());
638 return codeset ? codeset : "US-ASCII";
641 CharSet conv_get_outgoing_charset(void)
643 static CharSet out_charset = -1;
646 gint i, j, n_pref_codesets;
647 const gchar *const *pref_codesets;
652 if (out_charset != -1)
656 /* skip US-ASCII and UTF-8 */
657 pref_codesets = jconv_info_get_pref_codesets(&n_pref_codesets);
658 for (i = 0; i < n_pref_codesets; i++) {
659 for (j = 3; j < sizeof(charsets) / sizeof(charsets[0]); j++) {
660 if (!strcasecmp(pref_codesets[i], charsets[j].name)) {
661 out_charset = charsets[j].charset;
667 for (i = 0; i < n_pref_codesets; i++) {
668 if (!strcasecmp(pref_codesets[i], "UTF-8")) {
669 out_charset = C_UTF_8;
674 out_charset = C_AUTO;
676 cur_charset = conv_get_current_charset();
677 switch (cur_charset) {
680 out_charset = C_ISO_2022_JP;
683 out_charset = cur_charset;
690 const gchar *conv_get_outgoing_charset_str(void)
695 if (prefs_common.outgoing_charset) {
696 if (!isalpha(prefs_common.outgoing_charset[0])) {
697 g_free(prefs_common.outgoing_charset);
698 prefs_common.outgoing_charset = g_strdup(CS_AUTO);
699 } else if (strcmp(prefs_common.outgoing_charset, CS_AUTO) != 0)
700 return prefs_common.outgoing_charset;
703 out_charset = conv_get_outgoing_charset();
704 str = conv_get_charset_str(out_charset);
706 return str ? str : "US-ASCII";
709 const gchar *conv_get_current_locale(void)
713 cur_locale = g_getenv("LC_ALL");
714 if (!cur_locale) cur_locale = g_getenv("LANG");
715 if (!cur_locale) cur_locale = setlocale(LC_CTYPE, NULL);
717 debug_print("current locale: %s\n",
718 cur_locale ? cur_locale : "(none)");
723 void conv_unmime_header_overwrite(gchar *str)
729 cur_charset = conv_get_current_charset();
732 Xstrdup_a(buf, str, return);
733 outlen = strlen(str) + 1;
734 UnMimeHeaderConv(buf, str, outlen);
735 if (cur_charset == C_EUC_JP) {
739 len = strlen(str) * 2 + 1;
740 Xalloca(tmp, len, return);
741 conv_jistodisp(tmp, len, str);
742 strncpy2(str, tmp, outlen);
745 if (cur_charset == C_EUC_JP) {
749 Xstrdup_a(buf, str, return);
750 outlen = strlen(str) + 1;
752 len = strlen(buf) * 2 + 1;
753 Xalloca(tmp, len, {strncpy2(str, buf, outlen); return;});
754 conv_jistodisp(tmp, len, buf);
755 strncpy2(str, tmp, outlen);
761 void conv_unmime_header(gchar *outbuf, gint outlen, const gchar *str,
762 const gchar *charset)
767 cur_charset = conv_get_current_charset();
768 Xstrdup_a(buf, str, return);
771 UnMimeHeaderConv(buf, outbuf, outlen);
774 strncpy2(outbuf, buf, outlen);
776 if (cur_charset == C_EUC_JP) {
779 len = strlen(outbuf) * 2 + 1;
780 Xalloca(buf, len, return);
781 conv_jistodisp(buf, len, outbuf);
782 strncpy2(outbuf, buf, outlen);
786 #define MAX_ENCLEN 75
787 #define MAX_LINELEN 76
789 #define B64LEN(len) ((len) / 3 * 4 + ((len) % 3 ? 4 : 0))
792 void conv_encode_header(gchar *dest, gint len, const gchar *src,
798 size_t line_len, mimehdr_len, mimehdr_begin_len;
799 gchar *mimehdr_init = "=?";
800 gchar *mimehdr_end = "?=";
801 gchar *mimehdr_enctype = "?B?";
802 const gchar *mimehdr_charset;
804 /* g_print("src = %s\n", src); */
805 mimehdr_charset = conv_get_outgoing_charset_str();
807 /* convert to wide-character string */
808 wsrcp = wsrc = strdup_mbstowcs(src);
810 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
811 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
812 mimehdr_begin_len = strlen(mimehdr_init) +
813 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
815 line_len = header_len;
819 g_return_if_fail(wsrc != NULL);
822 wchar_t *wp, *wtmp, *wtmpp;
825 /* irresponsible buffer overrun check */
826 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
828 /* encode string including space
829 if non-ASCII string follows */
830 if (is_next_nonascii(wsrcp)) {
832 while ((wp = find_wspace(wp)) != NULL)
833 if (!is_next_nonascii(wp)) break;
835 wp = find_wspace(wsrcp);
838 wtmp = wcsndup(wsrcp, wp - wsrcp);
840 while (iswspace(wsrcp[nspc])) nspc++;
842 wtmp = wcsdup(wsrcp);
843 wsrcp += wcslen(wsrcp);
849 gint tlen = 0, str_ascii = 1;
850 gchar *tmp; /* internal codeset */
851 gchar *raw; /* converted, but not base64 encoded */
852 register gchar *tmpp;
855 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
860 while (*wtmpp != (wchar_t)0) {
863 gchar *raw_new = NULL;
865 const gchar *src_codeset;
867 if (*wtmpp < 32 || *wtmpp >= 127)
869 mbl = wctomb(tmpp, *wtmpp);
871 g_warning("invalid wide character\n");
876 src_codeset = conv_get_current_charset_str();
877 /* printf ("tmp = %s, tlen = %d, mbl\n",
879 if (jconv_alloc_conv(tmp, tlen + mbl,
880 &raw_new, &raw_new_len,
882 &dummy, mimehdr_charset)
884 g_warning("can't convert\n");
889 gint dlen = mimehdr_len +
891 if ((line_len + dlen +
892 (*(wtmpp + 1) ? 0 : nspc) +
893 (line_len > 1 ? 1 : 0))
907 } else if ((line_len + tlen + mbl +
908 (*(wtmpp + 1) ? 0 : nspc) +
909 (line_len > 1 ? 1 : 0))
913 (*(wtmpp + 1) ? 0 : nspc)
931 raw_len = raw_new_len;
936 g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
937 tmp, tlen, mb_seqlen);
940 if (tlen == 0 || raw_len == 0) {
946 if (line_len > 1 && destp > dest) {
953 g_snprintf(destp, len - strlen(dest), "%s%s%s",
954 mimehdr_init, mimehdr_charset,
956 destp += mimehdr_begin_len;
957 line_len += mimehdr_begin_len;
959 to64frombits(destp, raw, raw_len);
960 line_len += strlen(destp);
961 destp += strlen(destp);
963 strcpy(destp, mimehdr_end);
964 destp += strlen(mimehdr_end);
965 line_len += strlen(mimehdr_end);
968 line_len += strlen(destp);
969 destp += strlen(destp);
974 /* g_print("line_len = %d\n\n", line_len); */
975 } while (*wtmpp != (wchar_t)0);
977 while (iswspace(*wsrcp)) {
980 mbl = wctomb(destp, *wsrcp++);
993 /* g_print("dest = %s\n", dest); */
995 #else /* !HAVE_LIBJCONV */
999 void conv_encode_header(gchar *dest, gint len, const gchar *src,
1005 size_t line_len, mimehdr_len, mimehdr_begin_len;
1006 gchar *mimehdr_init = "=?";
1007 gchar *mimehdr_end = "?=";
1008 gchar *mimehdr_enctype = "?B?";
1009 const gchar *mimehdr_charset;
1011 /* g_print("src = %s\n", src); */
1012 mimehdr_charset = conv_get_outgoing_charset_str();
1013 if (strcmp(mimehdr_charset, "ISO-2022-JP") != 0) {
1014 /* currently only supports Japanese */
1015 strncpy2(dest, src, len);
1019 /* convert to wide-character string */
1020 wsrcp = wsrc = strdup_mbstowcs(src);
1022 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
1023 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
1024 mimehdr_begin_len = strlen(mimehdr_init) +
1025 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
1027 line_len = header_len;
1031 g_return_if_fail(wsrc != NULL);
1034 wchar_t *wp, *wtmp, *wtmpp;
1037 /* irresponsible buffer overrun check */
1038 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
1040 /* encode string including space
1041 if non-ASCII string follows */
1042 if (is_next_nonascii(wsrcp)) {
1044 while ((wp = find_wspace(wp)) != NULL)
1045 if (!is_next_nonascii(wp)) break;
1047 wp = find_wspace(wsrcp);
1050 wtmp = wcsndup(wsrcp, wp - wsrcp);
1052 while (iswspace(wsrcp[nspc])) nspc++;
1054 wtmp = wcsdup(wsrcp);
1055 wsrcp += wcslen(wsrcp);
1061 gint prev_mbl = 1, tlen = 0, mb_seqlen = 0;
1063 register gchar *tmpp;
1065 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
1068 while (*wtmpp != (wchar_t)0) {
1071 mbl = wctomb(tmpp, *wtmpp);
1073 g_warning("invalid wide character\n");
1078 /* length of KI + KO */
1079 if (prev_mbl == 1 && mbl == 2)
1080 mb_seqlen += JIS_SEQLEN * 2;
1083 gint dlen = mimehdr_len +
1084 B64LEN(tlen + mb_seqlen + mbl);
1086 if ((line_len + dlen +
1087 (*(wtmpp + 1) ? 0 : nspc) +
1088 (line_len > 1 ? 1 : 0))
1101 } else if ((line_len + tlen + mbl +
1102 (*(wtmpp + 1) ? 0 : nspc) +
1103 (line_len > 1 ? 1 : 0))
1105 if (1 + tlen + mbl +
1106 (*(wtmpp + 1) ? 0 : nspc)
1125 /* g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
1126 tmp, tlen, mb_seqlen);
1134 if (line_len > 1 && destp > dest) {
1143 tmp_jis = g_new(gchar, tlen + mb_seqlen + 1);
1144 conv_euctojis(tmp_jis,
1145 tlen + mb_seqlen + 1, tmp);
1146 g_snprintf(destp, len - strlen(dest), "%s%s%s",
1147 mimehdr_init, mimehdr_charset,
1149 destp += mimehdr_begin_len;
1150 line_len += mimehdr_begin_len;
1152 to64frombits(destp, tmp_jis, strlen(tmp_jis));
1153 line_len += strlen(destp);
1154 destp += strlen(destp);
1156 strcpy(destp, mimehdr_end);
1157 destp += strlen(mimehdr_end);
1158 line_len += strlen(mimehdr_end);
1163 line_len += strlen(destp);
1164 destp += strlen(destp);
1168 /* g_print("line_len = %d\n\n", line_len); */
1169 } while (*wtmpp != (wchar_t)0);
1171 while (iswspace(*wsrcp)) {
1174 mbl = wctomb(destp, *wsrcp++);
1187 /* g_print("dest = %s\n", dest); */
1189 #endif /* HAVE_LIBJCONV */