aboutsummaryrefslogtreecommitdiff
path: root/libsylph
diff options
context:
space:
mode:
authorhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2006-03-17 04:48:28 +0000
committerhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2006-03-17 04:48:28 +0000
commit5d5b413e4b4213e72f51d6393d4f42ba96936ea2 (patch)
tree470154d84b34f340f90ceefb0ccbc936869002a7 /libsylph
parent0758434f9b288d0c05d7df2147a24c0ca9af0492 (diff)
implemented RFC 2231 filename encoding on send.
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@1052 ee746299-78ed-0310-b773-934348b2243d
Diffstat (limited to 'libsylph')
-rw-r--r--libsylph/codeconv.c111
-rw-r--r--libsylph/codeconv.h5
-rw-r--r--libsylph/prefs_common.c2
-rw-r--r--libsylph/prefs_common.h7
-rw-r--r--libsylph/procmime.c4
-rw-r--r--libsylph/utils.c24
-rw-r--r--libsylph/utils.h2
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,