aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-mime-message.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/camel-mime-message.c')
-rw-r--r--camel/camel-mime-message.c171
1 files changed, 170 insertions, 1 deletions
diff --git a/camel/camel-mime-message.c b/camel/camel-mime-message.c
index b6bd93864e..2cb6fed5a7 100644
--- a/camel/camel-mime-message.c
+++ b/camel/camel-mime-message.c
@@ -25,11 +25,14 @@
*/
#include <config.h>
+
#include "camel-mime-message.h"
-#include <stdio.h>
+#include "camel-multipart.h"
#include "gmime-content-field.h"
+#include "camel-stream-mem.h"
#include "string-utils.h"
#include "hash-table-utils.h"
+#include <stdio.h>
#define d(x)
@@ -548,3 +551,169 @@ remove_header(CamelMedium *medium, const char *header_name)
process_header(medium, header_name, NULL);
parent_class->parent_class.remove_header (medium, header_name);
}
+
+static gboolean
+multipart_has_8bit_parts (CamelMultipart *multipart)
+{
+ gboolean has_8bit = FALSE;
+ int i, nparts;
+
+ nparts = camel_multipart_get_number (multipart);
+
+ for (i = 0; i < nparts && !has_8bit; i++) {
+ GMimeContentField *content;
+ CamelMimePart *mime_part;
+
+ mime_part = camel_multipart_get_part (multipart, i);
+ content = camel_mime_part_get_content_type (mime_part);
+
+ if (gmime_content_field_is_type (content, "multipart", "*")) {
+ CamelDataWrapper *wrapper;
+ CamelMultipart *mpart;
+
+ wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
+ mpart = CAMEL_MULTIPART (wrapper);
+
+ has_8bit = multipart_has_8bit_parts (mpart);
+ } else {
+ /* see if this part is 8bit */
+ has_8bit = camel_mime_part_get_encoding (mime_part) == CAMEL_MIME_PART_ENCODING_8BIT;
+ }
+ }
+
+ return has_8bit;
+}
+
+gboolean
+camel_mime_message_has_8bit_parts (CamelMimeMessage *mime_message)
+{
+ GMimeContentField *content;
+ gboolean has_8bit = FALSE;
+
+ content = camel_mime_part_get_content_type (CAMEL_MIME_PART (mime_message));
+
+ if (gmime_content_field_is_type (content, "multipart", "*")) {
+ CamelDataWrapper *wrapper;
+ CamelMultipart *multipart;
+
+ wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (CAMEL_MIME_PART (mime_message)));
+ multipart = CAMEL_MULTIPART (wrapper);
+
+ has_8bit = multipart_has_8bit_parts (multipart);
+ } else {
+ /* single-part message so just check this part */
+ has_8bit = camel_mime_part_get_encoding (CAMEL_MIME_PART (mime_message)) == CAMEL_MIME_PART_ENCODING_8BIT;
+ }
+
+ return has_8bit;
+}
+
+static int
+best_encoding (const guchar *text)
+{
+ guchar *ch;
+ int count = 0;
+ int total;
+
+ for (ch = (guchar *) text; *ch; ch++)
+ if (*ch > (guchar) 127)
+ count++;
+
+ total = (int) (ch - text);
+
+ if ((float) count <= total * 0.17)
+ return CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE;
+ else
+ return CAMEL_MIME_PART_ENCODING_BASE64;
+}
+
+static void
+multipart_encode_8bit_parts (CamelMultipart *multipart)
+{
+ int i, nparts;
+
+ nparts = camel_multipart_get_number (multipart);
+
+ for (i = 0; i < nparts; i++) {
+ GMimeContentField *content;
+ CamelMimePart *mime_part;
+
+ mime_part = camel_multipart_get_part (multipart, i);
+ content = camel_mime_part_get_content_type (mime_part);
+
+ if (gmime_content_field_is_type (content, "multipart", "*")) {
+ /* ...and the search for Spock continues */
+ CamelDataWrapper *wrapper;
+ CamelMultipart *mpart;
+
+ wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
+ mpart = CAMEL_MULTIPART (wrapper);
+
+ multipart_encode_8bit_parts (mpart);
+ } else {
+ /* re-encode this if necessary */
+ gboolean is_8bit;
+
+ is_8bit = camel_mime_part_get_encoding (mime_part) == CAMEL_MIME_PART_ENCODING_8BIT;
+ if (is_8bit) {
+ CamelStream *stream;
+ GByteArray *array;
+ guchar *content;
+
+ array = g_byte_array_new ();
+ stream = camel_stream_mem_new_with_byte_array (array);
+ camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (mime_part), stream);
+ g_byte_array_append (array, "", 1);
+
+ content = array->data;
+ g_byte_array_free (array, FALSE);
+
+ camel_mime_part_set_encoding (mime_part, best_encoding (content));
+ g_free (content);
+ camel_object_unref (CAMEL_OBJECT (stream));
+ }
+ }
+ }
+}
+
+void
+camel_mime_message_encode_8bit_parts (CamelMimeMessage *mime_message)
+{
+ GMimeContentField *content;
+
+ content = camel_mime_part_get_content_type (CAMEL_MIME_PART (mime_message));
+
+ if (gmime_content_field_is_type (content, "multipart", "*")) {
+ /* search for Spock */
+ CamelDataWrapper *wrapper;
+ CamelMultipart *multipart;
+
+ wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (CAMEL_MIME_PART (mime_message)));
+ multipart = CAMEL_MULTIPART (wrapper);
+
+ multipart_encode_8bit_parts (multipart);
+ } else {
+ /* re-encode if we need to */
+ gboolean is_8bit;
+
+ is_8bit = camel_mime_part_get_encoding (CAMEL_MIME_PART (mime_message)) == CAMEL_MIME_PART_ENCODING_8BIT;
+ if (is_8bit) {
+ /* FIXME: is there a better way of doing this? */
+ CamelStream *stream;
+ GByteArray *array;
+ guchar *content;
+
+ array = g_byte_array_new ();
+ stream = camel_stream_mem_new_with_byte_array (array);
+ camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (CAMEL_MIME_PART (mime_message)), stream);
+ g_byte_array_append (array, "", 1);
+
+ content = array->data;
+ g_byte_array_free (array, FALSE);
+
+ camel_mime_part_set_encoding (CAMEL_MIME_PART (mime_message), best_encoding (content));
+ g_free (content);
+ camel_object_unref (CAMEL_OBJECT (stream));
+ }
+ }
+}