diff options
Diffstat (limited to 'libsylph')
-rw-r--r-- | libsylph/codeconv.c | 111 | ||||
-rw-r--r-- | libsylph/codeconv.h | 5 | ||||
-rw-r--r-- | libsylph/prefs_common.c | 2 | ||||
-rw-r--r-- | libsylph/prefs_common.h | 7 | ||||
-rw-r--r-- | libsylph/procmime.c | 4 | ||||
-rw-r--r-- | libsylph/utils.c | 24 | ||||
-rw-r--r-- | libsylph/utils.h | 2 |
7 files changed, 150 insertions, 5 deletions
diff --git a/libsylph/codeconv.c b/libsylph/codeconv.c index 6cf3de66..76d75336 100644 --- a/libsylph/codeconv.c +++ b/libsylph/codeconv.c @@ -2271,6 +2271,117 @@ void conv_encode_header(gchar *dest, gint len, const gchar *src, #undef LBREAK_IF_REQUIRED +#define INT_TO_HEX_UPPER(outp, val) \ +{ \ + if ((val) < 10) \ + *outp = '0' + (val); \ + else \ + *outp = 'A' + (val) - 10; \ +} + +#define IS_ESCAPE_CHAR(c) \ + (c < 0x20 || c > 0x7f || \ + strchr("\t \r\n*'%!#$&~`,{}|()<>@,;:\\\"/[]?=", c)) + +static gchar *encode_rfc2231_filename(const gchar *str) +{ + const gchar *p; + gchar *out; + gchar *outp; + + outp = out = g_malloc(strlen(str) * 3 + 1); + + for (p = str; *p != '\0'; ++p) { + guchar ch = *(guchar *)p; + + if (IS_ESCAPE_CHAR(ch)) { + *outp++ = '%'; + INT_TO_HEX_UPPER(outp, ch >> 4); + ++outp; + INT_TO_HEX_UPPER(outp, ch & 0x0f); + ++outp; + } else + *outp++ = ch; + } + + *outp = '\0'; + return out; +} + +gchar *conv_encode_filename(const gchar *src, const gchar *param_name, + const gchar *out_encoding) +{ + gint name_len, max_linelen; + gchar *out_str, *enc_str; + gchar cur_param[80]; + GString *string; + gint count = 0; + gint cur_left_len; + gchar *p; + + g_return_val_if_fail(src != NULL, NULL); + g_return_val_if_fail(param_name != NULL, NULL); + + if (is_ascii_str(src)) + return g_strdup_printf(" %s=\"%s\"", param_name, src); + + name_len = strlen(param_name); + max_linelen = MAX_LINELEN - name_len - 3; + + if (!out_encoding) + out_encoding = conv_get_outgoing_charset_str(); + if (!strcmp(out_encoding, CS_US_ASCII)) + out_encoding = CS_ISO_8859_1; + + out_str = conv_codeset_strdup(src, CS_INTERNAL, out_encoding); + if (!out_str) + return NULL; + enc_str = encode_rfc2231_filename(out_str); + g_free(out_str); + + if (strlen(enc_str) <= max_linelen) { + gchar *ret; + ret = g_strdup_printf(" %s*=%s''%s", + param_name, out_encoding, enc_str); + g_free(enc_str); + return ret; + } + + string = g_string_new(NULL); + g_string_printf(string, " %s*0*=%s''", param_name, out_encoding); + cur_left_len = MAX_LINELEN - string->len; + + p = enc_str; + + while (*p != '\0') { + if ((*p == '%' && cur_left_len < 4) || + (*p != '%' && cur_left_len < 2)) { + gint len; + + g_string_append(string, ";\n"); + ++count; + len = g_snprintf(cur_param, sizeof(cur_param), + " %s*%d*=", param_name, count); + g_string_append(string, cur_param); + cur_left_len = MAX_LINELEN - len; + } + + if (*p == '%') { + g_string_append_len(string, p, 3); + p += 3; + cur_left_len -= 3; + } else { + g_string_append_c(string, *p); + ++p; + --cur_left_len; + } + } + + g_free(enc_str); + + return g_string_free(string, FALSE); +} + gint conv_copy_file(const gchar *src, const gchar *dest, const gchar *encoding) { FILE *src_fp, *dest_fp; diff --git a/libsylph/codeconv.h b/libsylph/codeconv.h index 1920c8f0..700e83b0 100644 --- a/libsylph/codeconv.h +++ b/libsylph/codeconv.h @@ -1,6 +1,6 @@ /* * LibSylph -- E-Mail client library - * Copyright (C) 1999-2005 Hiroyuki Yamamoto + * Copyright (C) 1999-2006 Hiroyuki Yamamoto * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -230,6 +230,9 @@ void conv_encode_header (gchar *dest, gint header_len, gboolean addr_field, const gchar *out_encoding); +gchar *conv_encode_filename (const gchar *src, + const gchar *param_name, + const gchar *out_encoding); gint conv_copy_file (const gchar *src, const gchar *dest, diff --git a/libsylph/prefs_common.c b/libsylph/prefs_common.c index 8360d0ce..5c4bfca5 100644 --- a/libsylph/prefs_common.c +++ b/libsylph/prefs_common.c @@ -57,6 +57,8 @@ static PrefParam param[] = { {"filter_sent_message", "FALSE", &prefs_common.filter_sent, P_BOOL}, {"encoding_method", "0", &prefs_common.encoding_method, P_ENUM}, + {"mime_filename_encoding_method", "0", + &prefs_common.mime_fencoding_method, P_ENUM}, {"allow_jisx0201_kana", "FALSE", &prefs_common.allow_jisx0201_kana, P_BOOL}, diff --git a/libsylph/prefs_common.h b/libsylph/prefs_common.h index de3a53c8..6f12e877 100644 --- a/libsylph/prefs_common.h +++ b/libsylph/prefs_common.h @@ -44,6 +44,12 @@ typedef enum { CTE_8BIT } TransferEncodingMethod; +typedef enum { + FENC_MIME, + FENC_RFC2231, + FENC_NONE +} MIMEFilenameEncodingMethod; + struct _PrefsCommon { /* Receive */ @@ -62,6 +68,7 @@ struct _PrefsCommon gboolean savemsg; gboolean filter_sent; TransferEncodingMethod encoding_method; + MIMEFilenameEncodingMethod mime_fencoding_method; gboolean allow_jisx0201_kana; diff --git a/libsylph/procmime.c b/libsylph/procmime.c index c79a2e59..28bb9d1f 100644 --- a/libsylph/procmime.c +++ b/libsylph/procmime.c @@ -576,7 +576,7 @@ static MimeParams *procmime_parse_mime_parameter(const gchar *str) if (encoded) { dec_value = g_malloc(strlen(begin) + 1); - decode_uri(dec_value, begin); + decode_xdigit_encoded_str(dec_value, begin); CONCAT_CONT_VALUE(dec_value); g_free(dec_value); } else { @@ -602,7 +602,7 @@ static MimeParams *procmime_parse_mime_parameter(const gchar *str) mparam->name = name; if (encoded) { dec_value = g_malloc(strlen(begin) + 1); - decode_uri(dec_value, begin); + decode_xdigit_encoded_str(dec_value, begin); mparam->value = procmime_convert_value (dec_value, charset); g_free(dec_value); diff --git a/libsylph/utils.c b/libsylph/utils.c index a2c3bd3e..914fd007 100644 --- a/libsylph/utils.c +++ b/libsylph/utils.c @@ -1629,8 +1629,8 @@ void decode_uri(gchar *decoded_uri, const gchar *encoded_uri) while (*enc) { if (*enc == '%') { enc++; - if (isxdigit((guchar)enc[0]) && - isxdigit((guchar)enc[1])) { + if (g_ascii_isxdigit((guchar)enc[0]) && + g_ascii_isxdigit((guchar)enc[1])) { *dec = axtoi(enc); dec++; enc += 2; @@ -1648,6 +1648,26 @@ void decode_uri(gchar *decoded_uri, const gchar *encoded_uri) *dec = '\0'; } +void decode_xdigit_encoded_str(gchar *decoded, const gchar *encoded) +{ + gchar *dec = decoded; + const gchar *enc = encoded; + + while (*enc) { + if (*enc == '%') { + enc++; + if (g_ascii_isxdigit((guchar)enc[0]) && + g_ascii_isxdigit((guchar)enc[1])) { + *dec++ = axtoi(enc); + enc += 2; + } + } else + *dec++ = *enc++; + } + + *dec = '\0'; +} + gchar *encode_uri(const gchar *filename) { gchar *uri; diff --git a/libsylph/utils.h b/libsylph/utils.h index 43372bb0..63bb7861 100644 --- a/libsylph/utils.h +++ b/libsylph/utils.h @@ -348,6 +348,8 @@ gchar *get_uri_path (const gchar *uri); gint get_uri_len (const gchar *str); void decode_uri (gchar *decoded_uri, const gchar *encoded_uri); +void decode_xdigit_encoded_str (gchar *decoded, + const gchar *encoded); gchar *encode_uri (const gchar *filename); gchar *uriencode_for_filename (const gchar *filename); gint scan_mailto_url (const gchar *mailto, |