diff -up evolution-3.10.4/modules/text-highlight/e-mail-formatter-text-highlight.c.large-message-render-hung evolution-3.10.4/modules/text-highlight/e-mail-formatter-text-highlight.c --- evolution-3.10.4/modules/text-highlight/e-mail-formatter-text-highlight.c.large-message-render-hung 2013-12-07 15:14:12.000000000 +0100 +++ evolution-3.10.4/modules/text-highlight/e-mail-formatter-text-highlight.c 2014-09-12 08:24:26.418217142 +0200 @@ -41,6 +41,15 @@ typedef EMailFormatterExtensionClass EMa typedef EExtension EMailFormatterTextHighlightLoader; typedef EExtensionClass EMailFormatterTextHighlightLoaderClass; +typedef struct _TextHighlightClosure TextHighlightClosure; + +struct _TextHighlightClosure { + CamelStream *read_stream; + CamelStream *output_stream; + GCancellable *cancellable; + GError *error; +}; + GType e_mail_formatter_text_highlight_get_type (void); G_DEFINE_DYNAMIC_TYPE ( @@ -110,6 +119,103 @@ get_syntax (EMailPart *part, return syntax; } +static gpointer +text_hightlight_read_data_thread (gpointer user_data) +{ + TextHighlightClosure *closure = user_data; + gchar buffer[10240]; + + g_return_val_if_fail (closure != NULL, NULL); + + while (!camel_stream_eos (closure->read_stream) && + !g_cancellable_set_error_if_cancelled (closure->cancellable, &closure->error)) { + gssize read; + gsize wrote = 0; + + read = camel_stream_read (closure->read_stream, buffer, 10240, closure->cancellable, &closure->error); + if (read < 0 || closure->error) + break; + + wrote = camel_stream_write (closure->output_stream, buffer, read, closure->cancellable, &closure->error); + if (wrote == -1 || (gssize) wrote != read || closure->error) + break; + } + + return NULL; +} + +static gboolean +text_highlight_feed_data (CamelStream *output_stream, + CamelDataWrapper *data_wrapper, + gint pipe_stdin, + gint pipe_stdout, + GCancellable *cancellable, + GError **error) +{ + TextHighlightClosure closure; + CamelContentType *content_type; + CamelStream *write_stream; + gboolean success = TRUE; + GThread *thread; + + closure.read_stream = camel_stream_fs_new_with_fd (pipe_stdout); + closure.output_stream = output_stream; + closure.cancellable = cancellable; + closure.error = NULL; + + write_stream = camel_stream_fs_new_with_fd (pipe_stdin); + + thread = g_thread_new (NULL, text_hightlight_read_data_thread, &closure); + + content_type = camel_data_wrapper_get_mime_type_field (data_wrapper); + if (content_type) { + const gchar *charset = camel_content_type_param (content_type, "charset"); + + /* Convert to UTF-8 charset, if needed, which the 'highlight' expects; + it can cope with non-UTF-8 letters, thus no need for a content UTF-8-validation */ + if (charset && g_ascii_strcasecmp (charset, "utf-8") != 0) { + CamelMimeFilter *filter; + + filter = camel_mime_filter_charset_new (charset, "UTF-8"); + if (filter != NULL) { + CamelStream *filtered = camel_stream_filter_new (write_stream); + + if (filtered) { + camel_stream_filter_add (CAMEL_STREAM_FILTER (filtered), filter); + g_object_unref (write_stream); + write_stream = filtered; + } + + g_object_unref (filter); + } + } + } + + if (camel_data_wrapper_decode_to_stream_sync (data_wrapper, write_stream, cancellable, error) < 0) { + g_cancellable_cancel (cancellable); + success = FALSE; + } else { + /* Close the stream, thus the highlight knows no more data will come */ + g_clear_object (&write_stream); + } + + g_thread_join (thread); + + g_clear_object (&closure.read_stream); + g_clear_object (&write_stream); + + if (closure.error) { + if (error && !*error) + g_propagate_error (error, closure.error); + else + g_clear_error (&closure.error); + + return FALSE; + } + + return success; +} + static gboolean emfe_text_highlight_format (EMailFormatterExtension *extension, EMailFormatter *formatter, @@ -213,35 +319,27 @@ emfe_text_highlight_format (EMailFormatt &pid, &pipe_stdin, &pipe_stdout, NULL, NULL); if (success) { - CamelStream *read; - CamelStream *write; - CamelStream *utf8; - GByteArray *ba; - gchar *tmp; - - write = camel_stream_fs_new_with_fd (pipe_stdin); - read = camel_stream_fs_new_with_fd (pipe_stdout); - - /* Decode the content of mime part to the 'utf8' stream */ - utf8 = camel_stream_mem_new (); - camel_data_wrapper_decode_to_stream_sync ( - dw, utf8, cancellable, NULL); - - /* Convert the binary data do someting displayable */ - ba = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (utf8)); - tmp = e_util_utf8_data_make_valid ((gchar *) ba->data, ba->len); - - /* Send the sanitized data to the highlighter */ - camel_stream_write_string (write, tmp, cancellable, NULL); - g_free (tmp); - g_object_unref (utf8); - g_object_unref (write); + GError *local_error = NULL; - g_spawn_close_pid (pid); + success = text_highlight_feed_data ( + stream, dw, + pipe_stdin, pipe_stdout, + cancellable, &local_error); + + if (g_error_matches ( + local_error, G_IO_ERROR, + G_IO_ERROR_CANCELLED)) { + /* Do nothing. */ + + } else if (local_error != NULL) { + g_warning ( + "%s: %s", G_STRFUNC, + local_error->message); + } + + g_clear_error (&local_error); - g_seekable_seek (G_SEEKABLE (read), 0, G_SEEK_SET, cancellable, NULL); - camel_stream_write_to_stream (read, stream, cancellable, NULL); - g_object_unref (read); + g_spawn_close_pid (pid); } else { /* We can't call e_mail_formatter_format_as on text/plain, * because text-highlight is registered as an handler for