2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999,2000 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);
356 codesets = &src_codeset;
359 codesets = jconv_info_get_pref_codesets(&n_codesets);
361 dest_codeset = conv_get_current_charset_str();
363 if (jconv_alloc_conv(inbuf, strlen(inbuf), &buf, &len,
364 codesets, n_codesets,
365 &actual_codeset, dest_codeset)
370 #else /* !HAVE_LIBJCONV */
372 if (!strcasecmp(src_codeset, CS_EUC_JP) ||
373 !strcasecmp(src_codeset, "EUCJP"))
374 src_charset = C_EUC_JP;
375 else if (!strcasecmp(src_codeset, CS_SHIFT_JIS) ||
376 !strcasecmp(src_codeset, "SHIFT-JIS") ||
377 !strcasecmp(src_codeset, "SJIS"))
378 src_charset = C_SHIFT_JIS;
379 if (dest_codeset && !strcasecmp(dest_codeset, CS_ISO_2022_JP))
380 dest_charset = C_ISO_2022_JP;
383 if ((src_charset == C_EUC_JP || src_charset == C_SHIFT_JIS) &&
384 dest_charset == C_ISO_2022_JP) {
385 len = (strlen(inbuf) + 1) * 3;
388 if (src_charset == C_EUC_JP)
389 conv_euctojis(buf, len, inbuf);
391 conv_anytojis(buf, len, inbuf);
392 buf = g_realloc(buf, strlen(buf) + 1);
395 buf = g_strdup(inbuf);
398 #endif /* !HAVE_LIBJCONV */
401 CodeConvFunc conv_get_code_conv_func(const gchar *charset)
403 CodeConvFunc code_conv;
406 if (conv_get_outgoing_charset() == C_ISO_2022_JP)
407 return conv_jistodisp;
412 if (!strcasecmp(charset, CS_ISO_2022_JP) ||
413 !strcasecmp(charset, CS_ISO_2022_JP_2))
414 code_conv = conv_jistodisp;
415 else if (!strcasecmp(charset, CS_US_ASCII))
416 code_conv = conv_ustodisp;
417 else if (!strncasecmp(charset, "ISO-8859-", 9))
418 code_conv = conv_latintodisp;
419 else if (!strcasecmp(charset, CS_SHIFT_JIS) ||
420 !strcasecmp(charset, "SHIFT-JIS") ||
421 !strcasecmp(charset, "SJIS") ||
422 !strcasecmp(charset, "X-SJIS"))
423 code_conv = conv_sjistodisp;
424 else if (!strcasecmp(charset, CS_EUC_JP) ||
425 !strcasecmp(charset, "EUCJP"))
426 code_conv = conv_euctodisp;
428 code_conv = conv_noconv;
433 static const struct {
437 {C_US_ASCII, CS_US_ASCII},
439 {C_ISO_8859_1, CS_ISO_8859_1},
440 {C_ISO_8859_2, CS_ISO_8859_2},
441 {C_ISO_8859_4, CS_ISO_8859_4},
442 {C_ISO_8859_5, CS_ISO_8859_5},
443 {C_ISO_8859_7, CS_ISO_8859_7},
444 {C_ISO_8859_8, CS_ISO_8859_8},
445 {C_ISO_8859_9, CS_ISO_8859_9},
446 {C_ISO_8859_13, CS_ISO_8859_13},
447 {C_ISO_8859_15, CS_ISO_8859_15},
448 {C_BALTIC, CS_BALTIC},
449 {C_CP1251, CS_CP1251},
450 {C_WINDOWS_1251, CS_WINDOWS_1251},
451 {C_KOI8_R, CS_KOI8_R},
452 {C_KOI8_U, CS_KOI8_U},
453 {C_ISO_2022_JP, CS_ISO_2022_JP},
454 {C_ISO_2022_JP_2, CS_ISO_2022_JP_2},
455 {C_EUC_JP, CS_EUC_JP},
456 {C_SHIFT_JIS, CS_SHIFT_JIS},
457 {C_ISO_2022_KR, CS_ISO_2022_KR},
458 {C_EUC_KR, CS_EUC_KR},
459 {C_ISO_2022_CN, CS_ISO_2022_CN},
460 {C_EUC_CN, CS_EUC_CN},
461 {C_GB2312, CS_GB2312},
462 {C_EUC_TW, CS_EUC_TW},
467 static const struct {
471 {"ja_JP.eucJP" , C_EUC_JP},
472 {"ja_JP.ujis" , C_EUC_JP},
473 {"ja_JP.EUC" , C_EUC_JP},
474 {"ja_JP.SJIS" , C_SHIFT_JIS},
475 {"ja_JP.JIS" , C_ISO_2022_JP},
476 {"ja_JP" , C_EUC_JP},
477 {"ko_KR" , C_EUC_KR},
478 {"zh_CN.GB2312" , C_GB2312},
479 {"zh_CN" , C_GB2312},
480 {"zh_TW.eucTW" , C_EUC_TW},
481 {"zh_TW.Big5" , C_BIG5},
484 {"ru_RU.KOI8-R" , C_KOI8_R},
485 {"ru_RU.CP1251" , C_CP1251},
487 {"en_US" , C_ISO_8859_1},
488 {"ca_ES" , C_ISO_8859_1},
489 {"da_DK" , C_ISO_8859_1},
490 {"de_DE" , C_ISO_8859_1},
491 {"nl_NL" , C_ISO_8859_1},
492 {"et_EE" , C_ISO_8859_1},
493 {"fi_FI" , C_ISO_8859_1},
494 {"fr_FR" , C_ISO_8859_1},
495 {"is_IS" , C_ISO_8859_1},
496 {"it_IT" , C_ISO_8859_1},
497 {"no_NO" , C_ISO_8859_1},
498 {"pt_PT" , C_ISO_8859_1},
499 {"pt_BR" , C_ISO_8859_1},
500 {"es_ES" , C_ISO_8859_1},
501 {"sv_SE" , C_ISO_8859_1},
503 {"hr_HR" , C_ISO_8859_2},
504 {"hu_HU" , C_ISO_8859_2},
505 {"pl_PL" , C_ISO_8859_2},
506 {"ro_RO" , C_ISO_8859_2},
507 {"sk_SK" , C_ISO_8859_2},
508 {"sl_SI" , C_ISO_8859_2},
509 {"ru_RU" , C_ISO_8859_5},
510 {"el_GR" , C_ISO_8859_7},
511 {"iw_IL" , C_ISO_8859_8},
512 {"tr_TR" , C_ISO_8859_9},
514 {"lt_LT.iso88594" , C_ISO_8859_4},
515 {"lt_LT.ISO8859-4" , C_ISO_8859_4},
516 {"lt_LT.ISO_8859-4" , C_ISO_8859_4},
517 {"lt_LT" , C_ISO_8859_13},
518 {"lv_LV" , C_ISO_8859_13},
521 {"POSIX" , C_US_ASCII},
523 #endif /* !HAVE_LIBJCONV */
525 const gchar *conv_get_charset_str(CharSet charset)
529 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
530 if (charsets[i].charset == charset)
531 return charsets[i].name;
537 CharSet conv_get_charset_from_str(const gchar *charset)
541 if (!charset) return C_AUTO;
543 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
544 if (!strcasecmp(charsets[i].name, charset))
545 return charsets[i].charset;
551 CharSet conv_get_current_charset(void)
553 static CharSet cur_charset = -1;
557 const gchar *cur_codeset;
559 const gchar *cur_locale;
562 if (cur_charset != -1)
566 cur_codeset = jconv_info_get_current_codeset();
567 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
568 if (!strcasecmp(cur_codeset, charsets[i].name)) {
569 cur_charset = charsets[i].charset;
574 cur_locale = g_getenv("LC_ALL");
575 if (!cur_locale) cur_locale = g_getenv("LC_CTYPE");
576 if (!cur_locale) cur_locale = g_getenv("LANG");
577 if (!cur_locale) cur_locale = setlocale(LC_CTYPE, NULL);
579 debug_print("current locale: %s\n",
580 cur_locale ? cur_locale : "(none)");
583 cur_charset = C_US_ASCII;
587 if (strcasestr(cur_locale, "UTF-8")) {
588 cur_charset = C_UTF_8;
592 for (i = 0; i < sizeof(locale_table) / sizeof(locale_table[0]); i++) {
595 /* "ja_JP.EUC" matches with "ja_JP.eucJP" and "ja_JP.EUC" */
596 /* "ja_JP" matches with "ja_JP.xxxx" and "ja" */
597 if (!strncasecmp(cur_locale, locale_table[i].locale,
598 strlen(locale_table[i].locale))) {
599 cur_charset = locale_table[i].charset;
601 } else if ((p = strchr(locale_table[i].locale, '_')) &&
602 !strchr(p + 1, '.')) {
603 if (strlen(cur_locale) == 2 &&
604 !strncasecmp(cur_locale, locale_table[i].locale, 2)) {
605 cur_charset = locale_table[i].charset;
612 cur_charset = C_AUTO;
616 const gchar *conv_get_current_charset_str(void)
619 return jconv_info_get_current_codeset();
621 static const gchar *codeset = NULL;
624 codeset = conv_get_charset_str(conv_get_current_charset());
626 return codeset ? codeset : "US-ASCII";
630 CharSet conv_get_outgoing_charset(void)
632 static CharSet out_charset = -1;
635 gint i, j, n_pref_codesets;
636 const gchar *const *pref_codesets;
641 if (out_charset != -1)
645 /* skip US-ASCII and UTF-8 */
646 pref_codesets = jconv_info_get_pref_codesets(&n_pref_codesets);
647 for (i = 0; i < n_pref_codesets; i++) {
648 for (j = 2; j < sizeof(charsets) / sizeof(charsets[0]); j++) {
649 if (!strcasecmp(pref_codesets[i], charsets[j].name)) {
650 out_charset = charsets[j].charset;
656 for (i = 0; i < n_pref_codesets; i++) {
657 if (!strcasecmp(pref_codesets[i], "UTF-8")) {
658 out_charset = C_UTF_8;
663 out_charset = C_AUTO;
665 cur_charset = conv_get_current_charset();
666 switch (cur_charset) {
669 out_charset = C_ISO_2022_JP;
672 out_charset = cur_charset;
679 const gchar *conv_get_outgoing_charset_str(void)
684 if (prefs_common.outgoing_charset) {
685 if (!isalpha(prefs_common.outgoing_charset[0])) {
686 g_free(prefs_common.outgoing_charset);
687 prefs_common.outgoing_charset = g_strdup(CS_AUTO);
688 } else if (strcmp(prefs_common.outgoing_charset, CS_AUTO) != 0)
689 return prefs_common.outgoing_charset;
692 out_charset = conv_get_outgoing_charset();
693 str = conv_get_charset_str(out_charset);
695 return str ? str : "US-ASCII";
698 void conv_unmime_header_overwrite(gchar *str)
704 cur_charset = conv_get_current_charset();
707 Xstrdup_a(buf, str, {return;});
708 outlen = strlen(str) + 1;
709 UnMimeHeaderConv(buf, str, outlen);
710 if (cur_charset == C_EUC_JP)
711 conv_unreadable_eucjp(str);
713 if (cur_charset == C_EUC_JP) {
717 Xstrdup_a(buf, str, {return;});
718 outlen = strlen(str) + 1;
720 len = strlen(buf) * 2 + 1;
721 Xalloca(tmp, len, {strncpy2(str, buf, outlen); return;});
722 conv_jistodisp(tmp, len, buf);
723 strncpy2(str, tmp, outlen);
729 void conv_unmime_header(gchar *outbuf, gint outlen, const gchar *str,
730 const gchar *charset)
735 Xstrdup_a(buf, str, {return;});
736 cur_charset = conv_get_current_charset();
739 UnMimeHeaderConv(buf, outbuf, outlen);
740 if (cur_charset == C_EUC_JP)
741 conv_unreadable_eucjp(outbuf);
744 if (cur_charset == C_EUC_JP) {
748 len = strlen(buf) * 2 + 1;
749 Xalloca(tmp, len, {strncpy2(outbuf, buf, outlen); return;});
750 conv_jistodisp(tmp, len, buf);
751 strncpy2(outbuf, tmp, outlen);
753 strncpy2(outbuf, buf, outlen);
757 #define MAX_ENCLEN 75
758 #define MAX_LINELEN 76
760 #define B64LEN(len) ((len) / 3 * 4 + ((len) % 3 ? 4 : 0))
763 void conv_encode_header(gchar *dest, gint len, const gchar *src,
769 size_t line_len, mimehdr_len, mimehdr_begin_len;
770 gchar *mimehdr_init = "=?";
771 gchar *mimehdr_end = "?=";
772 gchar *mimehdr_enctype = "?B?";
773 const gchar *mimehdr_charset;
775 //g_print("src = %s\n", src);
776 mimehdr_charset = conv_get_outgoing_charset_str();
778 /* convert to wide-character string */
779 wsrcp = wsrc = strdup_mbstowcs(src);
781 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
782 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
783 mimehdr_begin_len = strlen(mimehdr_init) +
784 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
786 line_len = header_len;
790 g_return_if_fail(wsrc != NULL);
793 wchar_t *wp, *wtmp, *wtmpp;
796 /* irresponsible buffer overrun check */
797 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
799 /* encode string including space
800 if non-ASCII string follows */
801 if (is_next_nonascii(wsrcp)) {
803 while ((wp = find_wspace(wp)) != NULL)
804 if (!is_next_nonascii(wp)) break;
806 wp = find_wspace(wsrcp);
809 wtmp = wcsndup(wsrcp, wp - wsrcp);
811 while (iswspace(wsrcp[nspc])) nspc++;
813 wtmp = wcsdup(wsrcp);
814 wsrcp += wcslen(wsrcp);
820 gint tlen = 0, str_ascii = 1;
821 gchar *tmp; /* internal codeset */
822 gchar *raw; /* converted, but not base64 encoded */
823 register gchar *tmpp;
826 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
831 while (*wtmpp != (wchar_t)0) {
834 gchar *raw_new = NULL;
836 const gchar *src_codeset;
838 if (*wtmpp < 32 || *wtmpp >= 127)
840 mbl = wctomb(tmpp, *wtmpp);
842 g_warning("invalid wide character\n");
847 src_codeset = conv_get_current_charset_str();
848 //printf ("tmp = %s, tlen = %d, mbl\n",
850 if (jconv_alloc_conv(tmp, tlen + mbl,
851 &raw_new, &raw_new_len,
853 &dummy, mimehdr_charset)
855 g_warning("can't convert\n");
860 gint dlen = mimehdr_len +
862 if ((line_len + dlen +
863 (*(wtmpp + 1) ? 0 : nspc) +
864 (line_len > 1 ? 1 : 0))
879 if ((line_len + tlen + mbl +
880 (*(wtmpp + 1) ? 0 : nspc) +
881 (line_len > 1 ? 1 : 0))
885 (*(wtmpp + 1) ? 0 : nspc)
904 raw_len = raw_new_len;
908 //g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
909 // tmp, tlen, mb_seqlen);
911 if (tlen == 0 || raw_len == 0) {
917 if (line_len > 1 && destp > dest) {
924 g_snprintf(destp, len - strlen(dest), "%s%s%s",
925 mimehdr_init, mimehdr_charset,
927 destp += mimehdr_begin_len;
928 line_len += mimehdr_begin_len;
930 to64frombits(destp, raw, raw_len);
931 line_len += strlen(destp);
932 destp += strlen(destp);
934 strcpy(destp, mimehdr_end);
935 destp += strlen(mimehdr_end);
936 line_len += strlen(mimehdr_end);
939 line_len += strlen(destp);
940 destp += strlen(destp);
945 //g_print("line_len = %d\n\n", line_len);
946 } while (*wtmpp != (wchar_t)0);
948 while (iswspace(*wsrcp)) {
951 mbl = wctomb(destp, *wsrcp++);
964 //g_print("dest = %s\n", dest);
966 #else /* !HAVE_LIBJCONV */
970 void conv_encode_header(gchar *dest, gint len, const gchar *src,
976 size_t line_len, mimehdr_len, mimehdr_begin_len;
977 gchar *mimehdr_init = "=?";
978 gchar *mimehdr_end = "?=";
979 gchar *mimehdr_enctype = "?B?";
980 const gchar *mimehdr_charset;
982 //g_print("src = %s\n", src);
983 mimehdr_charset = conv_get_outgoing_charset_str();
984 if (strcmp(mimehdr_charset, "ISO-2022-JP") != 0) {
985 /* currently only supports Japanese */
986 strncpy2(dest, src, len);
990 /* convert to wide-character string */
991 wsrcp = wsrc = strdup_mbstowcs(src);
993 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
994 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
995 mimehdr_begin_len = strlen(mimehdr_init) +
996 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
998 line_len = header_len;
1002 g_return_if_fail(wsrc != NULL);
1005 wchar_t *wp, *wtmp, *wtmpp;
1008 /* irresponsible buffer overrun check */
1009 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
1011 /* encode string including space
1012 if non-ASCII string follows */
1013 if (is_next_nonascii(wsrcp)) {
1015 while ((wp = find_wspace(wp)) != NULL)
1016 if (!is_next_nonascii(wp)) break;
1018 wp = find_wspace(wsrcp);
1021 wtmp = wcsndup(wsrcp, wp - wsrcp);
1023 while (iswspace(wsrcp[nspc])) nspc++;
1025 wtmp = wcsdup(wsrcp);
1026 wsrcp += wcslen(wsrcp);
1032 gint prev_mbl = 1, tlen = 0, mb_seqlen = 0;
1034 register gchar *tmpp;
1036 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
1039 while (*wtmpp != (wchar_t)0) {
1042 mbl = wctomb(tmpp, *wtmpp);
1044 g_warning("invalid wide character\n");
1049 /* length of KI + KO */
1050 if (prev_mbl == 1 && mbl == 2)
1051 mb_seqlen += JIS_SEQLEN * 2;
1054 gint dlen = mimehdr_len +
1055 B64LEN(tlen + mb_seqlen + mbl);
1057 if ((line_len + dlen +
1058 (*(wtmpp + 1) ? 0 : nspc) +
1059 (line_len > 1 ? 1 : 0))
1073 if ((line_len + tlen + mbl +
1074 (*(wtmpp + 1) ? 0 : nspc) +
1075 (line_len > 1 ? 1 : 0))
1077 if (1 + tlen + mbl +
1078 (*(wtmpp + 1) ? 0 : nspc)
1098 //g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
1099 // tmp, tlen, mb_seqlen);
1106 if (line_len > 1 && destp > dest) {
1115 tmp_jis = g_new(gchar, tlen + mb_seqlen + 1);
1116 conv_euctojis(tmp_jis,
1117 tlen + mb_seqlen + 1, tmp);
1118 g_snprintf(destp, len - strlen(dest), "%s%s%s",
1119 mimehdr_init, mimehdr_charset,
1121 destp += mimehdr_begin_len;
1122 line_len += mimehdr_begin_len;
1124 to64frombits(destp, tmp_jis, strlen(tmp_jis));
1125 line_len += strlen(destp);
1126 destp += strlen(destp);
1128 strcpy(destp, mimehdr_end);
1129 destp += strlen(mimehdr_end);
1130 line_len += strlen(mimehdr_end);
1135 line_len += strlen(destp);
1136 destp += strlen(destp);
1140 //g_print("line_len = %d\n\n", line_len);
1141 } while (*wtmpp != (wchar_t)0);
1143 while (iswspace(*wsrcp)) {
1146 mbl = wctomb(destp, *wsrcp++);
1159 //g_print("dest = %s\n", dest);
1161 #endif /* HAVE_LIBJCONV */