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();
368 if (jconv_alloc_conv(inbuf, strlen(inbuf), &buf, &len,
369 codesets, n_codesets,
370 &actual_codeset, dest_codeset)
375 #else /* !HAVE_LIBJCONV */
377 if (!strcasecmp(src_codeset, CS_EUC_JP) ||
378 !strcasecmp(src_codeset, "EUCJP"))
379 src_charset = C_EUC_JP;
380 else if (!strcasecmp(src_codeset, CS_SHIFT_JIS) ||
381 !strcasecmp(src_codeset, "SHIFT-JIS") ||
382 !strcasecmp(src_codeset, "SJIS"))
383 src_charset = C_SHIFT_JIS;
384 if (dest_codeset && !strcasecmp(dest_codeset, CS_ISO_2022_JP))
385 dest_charset = C_ISO_2022_JP;
388 if ((src_charset == C_EUC_JP || src_charset == C_SHIFT_JIS) &&
389 dest_charset == C_ISO_2022_JP) {
390 len = (strlen(inbuf) + 1) * 3;
393 if (src_charset == C_EUC_JP)
394 conv_euctojis(buf, len, inbuf);
396 conv_anytojis(buf, len, inbuf);
397 buf = g_realloc(buf, strlen(buf) + 1);
400 buf = g_strdup(inbuf);
403 #endif /* !HAVE_LIBJCONV */
406 CodeConvFunc conv_get_code_conv_func(const gchar *charset)
408 CodeConvFunc code_conv;
411 if (conv_get_outgoing_charset() == C_ISO_2022_JP)
412 return conv_jistodisp;
417 if (!strcasecmp(charset, CS_ISO_2022_JP) ||
418 !strcasecmp(charset, CS_ISO_2022_JP_2))
419 code_conv = conv_jistodisp;
420 else if (!strcasecmp(charset, CS_US_ASCII))
421 code_conv = conv_ustodisp;
422 else if (!strncasecmp(charset, CS_ISO_8859_1, 10))
423 code_conv = conv_latintodisp;
425 else if (!strncasecmp(charset, "ISO-8859-", 9))
426 code_conv = conv_latintodisp;
428 else if (!strcasecmp(charset, CS_SHIFT_JIS) ||
429 !strcasecmp(charset, "SHIFT-JIS") ||
430 !strcasecmp(charset, "SJIS") ||
431 !strcasecmp(charset, "X-SJIS"))
432 code_conv = conv_sjistodisp;
433 else if (!strcasecmp(charset, CS_EUC_JP) ||
434 !strcasecmp(charset, "EUCJP"))
435 code_conv = conv_euctodisp;
437 code_conv = conv_noconv;
442 static const struct {
446 {C_US_ASCII, CS_US_ASCII},
447 {C_US_ASCII, CS_ANSI_X3_4_1968},
449 {C_ISO_8859_1, CS_ISO_8859_1},
450 {C_ISO_8859_2, CS_ISO_8859_2},
451 {C_ISO_8859_4, CS_ISO_8859_4},
452 {C_ISO_8859_5, CS_ISO_8859_5},
453 {C_ISO_8859_7, CS_ISO_8859_7},
454 {C_ISO_8859_8, CS_ISO_8859_8},
455 {C_ISO_8859_9, CS_ISO_8859_9},
456 {C_ISO_8859_13, CS_ISO_8859_13},
457 {C_ISO_8859_15, CS_ISO_8859_15},
458 {C_BALTIC, CS_BALTIC},
459 {C_CP1251, CS_CP1251},
460 {C_WINDOWS_1251, CS_WINDOWS_1251},
461 {C_KOI8_R, CS_KOI8_R},
462 {C_KOI8_U, CS_KOI8_U},
463 {C_ISO_2022_JP, CS_ISO_2022_JP},
464 {C_ISO_2022_JP_2, CS_ISO_2022_JP_2},
465 {C_EUC_JP, CS_EUC_JP},
466 {C_SHIFT_JIS, CS_SHIFT_JIS},
467 {C_ISO_2022_KR, CS_ISO_2022_KR},
468 {C_EUC_KR, CS_EUC_KR},
469 {C_ISO_2022_CN, CS_ISO_2022_CN},
470 {C_EUC_CN, CS_EUC_CN},
471 {C_GB2312, CS_GB2312},
472 {C_EUC_TW, CS_EUC_TW},
477 static const struct {
481 {"ja_JP.eucJP" , C_EUC_JP},
482 {"ja_JP.ujis" , C_EUC_JP},
483 {"ja_JP.EUC" , C_EUC_JP},
484 {"ja_JP.SJIS" , C_SHIFT_JIS},
485 {"ja_JP.JIS" , C_ISO_2022_JP},
486 {"ja_JP" , C_EUC_JP},
487 {"ko_KR" , C_EUC_KR},
488 {"zh_CN.GB2312" , C_GB2312},
489 {"zh_CN" , C_GB2312},
490 {"zh_TW.eucTW" , C_EUC_TW},
491 {"zh_TW.Big5" , C_BIG5},
494 {"ru_RU.KOI8-R" , C_KOI8_R},
495 {"ru_RU.CP1251" , C_CP1251},
497 {"en_US" , C_ISO_8859_1},
498 {"ca_ES" , C_ISO_8859_1},
499 {"da_DK" , C_ISO_8859_1},
500 {"de_DE" , C_ISO_8859_1},
501 {"nl_NL" , C_ISO_8859_1},
502 {"et_EE" , C_ISO_8859_1},
503 {"fi_FI" , C_ISO_8859_1},
504 {"fr_FR" , C_ISO_8859_1},
505 {"is_IS" , C_ISO_8859_1},
506 {"it_IT" , C_ISO_8859_1},
507 {"no_NO" , C_ISO_8859_1},
508 {"pt_PT" , C_ISO_8859_1},
509 {"pt_BR" , C_ISO_8859_1},
510 {"es_ES" , C_ISO_8859_1},
511 {"sv_SE" , C_ISO_8859_1},
513 {"hr_HR" , C_ISO_8859_2},
514 {"hu_HU" , C_ISO_8859_2},
515 {"pl_PL" , C_ISO_8859_2},
516 {"ro_RO" , C_ISO_8859_2},
517 {"sk_SK" , C_ISO_8859_2},
518 {"sl_SI" , C_ISO_8859_2},
519 {"ru_RU" , C_ISO_8859_5},
520 {"el_GR" , C_ISO_8859_7},
521 {"iw_IL" , C_ISO_8859_8},
522 {"tr_TR" , C_ISO_8859_9},
524 {"lt_LT.iso88594" , C_ISO_8859_4},
525 {"lt_LT.ISO8859-4" , C_ISO_8859_4},
526 {"lt_LT.ISO_8859-4" , C_ISO_8859_4},
527 {"lt_LT" , C_ISO_8859_13},
528 {"lv_LV" , C_ISO_8859_13},
531 {"POSIX" , C_US_ASCII},
533 #endif /* !HAVE_LIBJCONV */
535 const gchar *conv_get_charset_str(CharSet charset)
539 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
540 if (charsets[i].charset == charset)
541 return charsets[i].name;
547 CharSet conv_get_charset_from_str(const gchar *charset)
551 if (!charset) return C_AUTO;
553 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
554 if (!strcasecmp(charsets[i].name, charset))
555 return charsets[i].charset;
561 CharSet conv_get_current_charset(void)
563 static CharSet cur_charset = -1;
567 const gchar *cur_codeset;
569 const gchar *cur_locale;
572 if (cur_charset != -1)
576 cur_codeset = jconv_info_get_current_codeset();
577 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
578 if (!strcasecmp(cur_codeset, charsets[i].name)) {
579 cur_charset = charsets[i].charset;
584 cur_locale = g_getenv("LC_ALL");
585 if (!cur_locale) cur_locale = g_getenv("LC_CTYPE");
586 if (!cur_locale) cur_locale = g_getenv("LANG");
587 if (!cur_locale) cur_locale = setlocale(LC_CTYPE, NULL);
589 debug_print("current locale: %s\n",
590 cur_locale ? cur_locale : "(none)");
593 cur_charset = C_US_ASCII;
597 if (strcasestr(cur_locale, "UTF-8")) {
598 cur_charset = C_UTF_8;
602 for (i = 0; i < sizeof(locale_table) / sizeof(locale_table[0]); i++) {
605 /* "ja_JP.EUC" matches with "ja_JP.eucJP" and "ja_JP.EUC" */
606 /* "ja_JP" matches with "ja_JP.xxxx" and "ja" */
607 if (!strncasecmp(cur_locale, locale_table[i].locale,
608 strlen(locale_table[i].locale))) {
609 cur_charset = locale_table[i].charset;
611 } else if ((p = strchr(locale_table[i].locale, '_')) &&
612 !strchr(p + 1, '.')) {
613 if (strlen(cur_locale) == 2 &&
614 !strncasecmp(cur_locale, locale_table[i].locale, 2)) {
615 cur_charset = locale_table[i].charset;
622 cur_charset = C_AUTO;
626 const gchar *conv_get_current_charset_str(void)
628 static const gchar *codeset = NULL;
631 codeset = conv_get_charset_str(conv_get_current_charset());
633 return codeset ? codeset : "US-ASCII";
636 CharSet conv_get_outgoing_charset(void)
638 static CharSet out_charset = -1;
641 gint i, j, n_pref_codesets;
642 const gchar *const *pref_codesets;
647 if (out_charset != -1)
651 /* skip US-ASCII and UTF-8 */
652 pref_codesets = jconv_info_get_pref_codesets(&n_pref_codesets);
653 for (i = 0; i < n_pref_codesets; i++) {
654 for (j = 2; j < sizeof(charsets) / sizeof(charsets[0]); j++) {
655 if (!strcasecmp(pref_codesets[i], charsets[j].name)) {
656 out_charset = charsets[j].charset;
662 for (i = 0; i < n_pref_codesets; i++) {
663 if (!strcasecmp(pref_codesets[i], "UTF-8")) {
664 out_charset = C_UTF_8;
669 out_charset = C_AUTO;
671 cur_charset = conv_get_current_charset();
672 switch (cur_charset) {
675 out_charset = C_ISO_2022_JP;
678 out_charset = cur_charset;
685 const gchar *conv_get_outgoing_charset_str(void)
690 if (prefs_common.outgoing_charset) {
691 if (!isalpha(prefs_common.outgoing_charset[0])) {
692 g_free(prefs_common.outgoing_charset);
693 prefs_common.outgoing_charset = g_strdup(CS_AUTO);
694 } else if (strcmp(prefs_common.outgoing_charset, CS_AUTO) != 0)
695 return prefs_common.outgoing_charset;
698 out_charset = conv_get_outgoing_charset();
699 str = conv_get_charset_str(out_charset);
701 return str ? str : "US-ASCII";
704 const gchar *conv_get_current_locale(void)
708 cur_locale = g_getenv("LC_ALL");
709 if (!cur_locale) cur_locale = g_getenv("LANG");
710 if (!cur_locale) cur_locale = setlocale(LC_CTYPE, NULL);
712 debug_print("current locale: %s\n",
713 cur_locale ? cur_locale : "(none)");
718 void conv_unmime_header_overwrite(gchar *str)
724 cur_charset = conv_get_current_charset();
727 Xstrdup_a(buf, str, return);
728 outlen = strlen(str) + 1;
729 UnMimeHeaderConv(buf, str, outlen);
730 if (cur_charset == C_EUC_JP) {
734 len = strlen(str) * 2 + 1;
735 Xalloca(tmp, len, return);
736 conv_jistodisp(tmp, len, str);
737 strncpy2(str, tmp, outlen);
740 if (cur_charset == C_EUC_JP) {
744 Xstrdup_a(buf, str, return);
745 outlen = strlen(str) + 1;
747 len = strlen(buf) * 2 + 1;
748 Xalloca(tmp, len, {strncpy2(str, buf, outlen); return;});
749 conv_jistodisp(tmp, len, buf);
750 strncpy2(str, tmp, outlen);
756 void conv_unmime_header(gchar *outbuf, gint outlen, const gchar *str,
757 const gchar *charset)
762 cur_charset = conv_get_current_charset();
763 Xstrdup_a(buf, str, return);
766 UnMimeHeaderConv(buf, outbuf, outlen);
769 strncpy2(outbuf, buf, outlen);
771 if (cur_charset == C_EUC_JP) {
774 len = strlen(outbuf) * 2 + 1;
775 Xalloca(buf, len, return);
776 conv_jistodisp(buf, len, outbuf);
777 strncpy2(outbuf, buf, outlen);
781 #define MAX_ENCLEN 75
782 #define MAX_LINELEN 76
784 #define B64LEN(len) ((len) / 3 * 4 + ((len) % 3 ? 4 : 0))
787 void conv_encode_header(gchar *dest, gint len, const gchar *src,
793 size_t line_len, mimehdr_len, mimehdr_begin_len;
794 gchar *mimehdr_init = "=?";
795 gchar *mimehdr_end = "?=";
796 gchar *mimehdr_enctype = "?B?";
797 const gchar *mimehdr_charset;
799 /* g_print("src = %s\n", src); */
800 mimehdr_charset = conv_get_outgoing_charset_str();
802 /* convert to wide-character string */
803 wsrcp = wsrc = strdup_mbstowcs(src);
805 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
806 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
807 mimehdr_begin_len = strlen(mimehdr_init) +
808 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
810 line_len = header_len;
814 g_return_if_fail(wsrc != NULL);
817 wchar_t *wp, *wtmp, *wtmpp;
820 /* irresponsible buffer overrun check */
821 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
823 /* encode string including space
824 if non-ASCII string follows */
825 if (is_next_nonascii(wsrcp)) {
827 while ((wp = find_wspace(wp)) != NULL)
828 if (!is_next_nonascii(wp)) break;
830 wp = find_wspace(wsrcp);
833 wtmp = wcsndup(wsrcp, wp - wsrcp);
835 while (iswspace(wsrcp[nspc])) nspc++;
837 wtmp = wcsdup(wsrcp);
838 wsrcp += wcslen(wsrcp);
844 gint tlen = 0, str_ascii = 1;
845 gchar *tmp; /* internal codeset */
846 gchar *raw; /* converted, but not base64 encoded */
847 register gchar *tmpp;
850 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
855 while (*wtmpp != (wchar_t)0) {
858 gchar *raw_new = NULL;
860 const gchar *src_codeset;
862 if (*wtmpp < 32 || *wtmpp >= 127)
864 mbl = wctomb(tmpp, *wtmpp);
866 g_warning("invalid wide character\n");
871 src_codeset = conv_get_current_charset_str();
872 /* printf ("tmp = %s, tlen = %d, mbl\n",
874 if (jconv_alloc_conv(tmp, tlen + mbl,
875 &raw_new, &raw_new_len,
877 &dummy, mimehdr_charset)
879 g_warning("can't convert\n");
884 gint dlen = mimehdr_len +
886 if ((line_len + dlen +
887 (*(wtmpp + 1) ? 0 : nspc) +
888 (line_len > 1 ? 1 : 0))
902 } else if ((line_len + tlen + mbl +
903 (*(wtmpp + 1) ? 0 : nspc) +
904 (line_len > 1 ? 1 : 0))
908 (*(wtmpp + 1) ? 0 : nspc)
926 raw_len = raw_new_len;
931 g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
932 tmp, tlen, mb_seqlen);
935 if (tlen == 0 || raw_len == 0) {
941 if (line_len > 1 && destp > dest) {
948 g_snprintf(destp, len - strlen(dest), "%s%s%s",
949 mimehdr_init, mimehdr_charset,
951 destp += mimehdr_begin_len;
952 line_len += mimehdr_begin_len;
954 to64frombits(destp, raw, raw_len);
955 line_len += strlen(destp);
956 destp += strlen(destp);
958 strcpy(destp, mimehdr_end);
959 destp += strlen(mimehdr_end);
960 line_len += strlen(mimehdr_end);
963 line_len += strlen(destp);
964 destp += strlen(destp);
969 /* g_print("line_len = %d\n\n", line_len); */
970 } while (*wtmpp != (wchar_t)0);
972 while (iswspace(*wsrcp)) {
975 mbl = wctomb(destp, *wsrcp++);
988 /* g_print("dest = %s\n", dest); */
990 #else /* !HAVE_LIBJCONV */
994 void conv_encode_header(gchar *dest, gint len, const gchar *src,
1000 size_t line_len, mimehdr_len, mimehdr_begin_len;
1001 gchar *mimehdr_init = "=?";
1002 gchar *mimehdr_end = "?=";
1003 gchar *mimehdr_enctype = "?B?";
1004 const gchar *mimehdr_charset;
1006 /* g_print("src = %s\n", src); */
1007 mimehdr_charset = conv_get_outgoing_charset_str();
1008 if (strcmp(mimehdr_charset, "ISO-2022-JP") != 0) {
1009 /* currently only supports Japanese */
1010 strncpy2(dest, src, len);
1014 /* convert to wide-character string */
1015 wsrcp = wsrc = strdup_mbstowcs(src);
1017 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
1018 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
1019 mimehdr_begin_len = strlen(mimehdr_init) +
1020 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
1022 line_len = header_len;
1026 g_return_if_fail(wsrc != NULL);
1029 wchar_t *wp, *wtmp, *wtmpp;
1032 /* irresponsible buffer overrun check */
1033 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
1035 /* encode string including space
1036 if non-ASCII string follows */
1037 if (is_next_nonascii(wsrcp)) {
1039 while ((wp = find_wspace(wp)) != NULL)
1040 if (!is_next_nonascii(wp)) break;
1042 wp = find_wspace(wsrcp);
1045 wtmp = wcsndup(wsrcp, wp - wsrcp);
1047 while (iswspace(wsrcp[nspc])) nspc++;
1049 wtmp = wcsdup(wsrcp);
1050 wsrcp += wcslen(wsrcp);
1056 gint prev_mbl = 1, tlen = 0, mb_seqlen = 0;
1058 register gchar *tmpp;
1060 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
1063 while (*wtmpp != (wchar_t)0) {
1066 mbl = wctomb(tmpp, *wtmpp);
1068 g_warning("invalid wide character\n");
1073 /* length of KI + KO */
1074 if (prev_mbl == 1 && mbl == 2)
1075 mb_seqlen += JIS_SEQLEN * 2;
1078 gint dlen = mimehdr_len +
1079 B64LEN(tlen + mb_seqlen + mbl);
1081 if ((line_len + dlen +
1082 (*(wtmpp + 1) ? 0 : nspc) +
1083 (line_len > 1 ? 1 : 0))
1096 } else if ((line_len + tlen + mbl +
1097 (*(wtmpp + 1) ? 0 : nspc) +
1098 (line_len > 1 ? 1 : 0))
1100 if (1 + tlen + mbl +
1101 (*(wtmpp + 1) ? 0 : nspc)
1120 /* g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
1121 tmp, tlen, mb_seqlen);
1129 if (line_len > 1 && destp > dest) {
1138 tmp_jis = g_new(gchar, tlen + mb_seqlen + 1);
1139 conv_euctojis(tmp_jis,
1140 tlen + mb_seqlen + 1, tmp);
1141 g_snprintf(destp, len - strlen(dest), "%s%s%s",
1142 mimehdr_init, mimehdr_charset,
1144 destp += mimehdr_begin_len;
1145 line_len += mimehdr_begin_len;
1147 to64frombits(destp, tmp_jis, strlen(tmp_jis));
1148 line_len += strlen(destp);
1149 destp += strlen(destp);
1151 strcpy(destp, mimehdr_end);
1152 destp += strlen(mimehdr_end);
1153 line_len += strlen(mimehdr_end);
1158 line_len += strlen(destp);
1159 destp += strlen(destp);
1163 /* g_print("line_len = %d\n\n", line_len); */
1164 } while (*wtmpp != (wchar_t)0);
1166 while (iswspace(*wsrcp)) {
1169 mbl = wctomb(destp, *wsrcp++);
1182 /* g_print("dest = %s\n", dest); */
1184 #endif /* HAVE_LIBJCONV */