static void test_html (const char *datadir, const char *input, const char *output, guint32 citation) { guint32 flags = GMIME_FILTER_HTML_CONVERT_NL | GMIME_FILTER_HTML_CONVERT_SPACES | GMIME_FILTER_HTML_CONVERT_URLS | GMIME_FILTER_HTML_CONVERT_ADDRESSES; const char *what = "GMimeFilterHtml", *mode; GByteArray *expected, *actual; GMimeStream *stream; GMimeFilter *filter; char *path; switch (citation) { case GMIME_FILTER_HTML_BLOCKQUOTE_CITATION: mode = "blockquote"; break; case GMIME_FILTER_HTML_MARK_CITATION: mode = "mark"; break; case GMIME_FILTER_HTML_CITE: mode = "cite"; break; default: mode = "none"; break; } testsuite_check ("%s (%s %s)", what, input, mode); actual = g_byte_array_new (); stream = g_mime_stream_mem_new_with_byte_array (actual); g_mime_stream_mem_set_owner ((GMimeStreamMem *) stream, FALSE); filter = g_mime_filter_html_new (flags | citation, 0x008888); path = g_build_filename (datadir, input, NULL); pump_data_through_filter (filter, path, stream, TRUE, TRUE); g_mime_filter_reset (filter); g_object_unref (stream); g_object_unref (filter); g_free (path); path = g_build_filename (datadir, output, NULL); expected = read_all_bytes (path, TRUE); g_free (path); if (actual->len != expected->len) { testsuite_check_failed ("%s failed: stream lengths do not match: expected=%u; actual=%u", what, expected->len, actual->len); stream = g_mime_stream_fs_open (output, O_WRONLY | O_CREAT, 0644, NULL); g_mime_stream_write (stream, (const char *) actual->data, actual->len); g_mime_stream_flush (stream); g_object_unref (stream); goto error; } if (memcmp (actual->data, expected->data, actual->len) != 0) { testsuite_check_failed ("%s failed: stream contents do not match", what); goto error; } testsuite_check_passed (); error: g_byte_array_free (expected, TRUE); g_byte_array_free (actual, TRUE); }
static void display_part(GMimeObject *part, const GMimeContentType *ct) { GMimeStream *ostream, *fstream; GMimeFilter *basic; GMimeDataWrapper *content; GMimeFilter *charset, *html; GMimePartEncodingType encoding; encoding = g_mime_part_get_encoding(GMIME_PART(part)); fstream = g_mime_stream_file_new(stdout); ostream = g_mime_stream_filter_new_with_stream(fstream); g_mime_stream_unref(fstream); /* Encoding filter, always on */ if (charset = g_mime_filter_charset_new(g_mime_content_type_get_parameter(ct, "charset"), "utf-8")) { g_mime_stream_filter_add(GMIME_STREAM_FILTER(ostream), charset); g_object_unref(charset); } if (g_mime_content_type_is_type(ct, "text", "plain")) { if (text_only == 0) { html = g_mime_filter_html_new ( GMIME_FILTER_HTML_CONVERT_SPACES | GMIME_FILTER_HTML_CONVERT_URLS | GMIME_FILTER_HTML_MARK_CITATION | GMIME_FILTER_HTML_CITE, 0); g_mime_stream_filter_add(GMIME_STREAM_FILTER(ostream), html); g_object_unref(html); } content = g_mime_part_get_content_object(GMIME_PART(part)); g_mime_data_wrapper_write_to_stream(content, ostream); g_mime_stream_flush(ostream); g_object_unref(content); // GMimeFilterBasic (base64, quopri) // GMimeFilterCharset // GMimeFilterHTML // GMimeFilterEnriched (text/enriched, text/rtf) } else if (g_mime_content_type_is_type(ct, "text", "html")) { content = g_mime_part_get_content_object(GMIME_PART(part)); g_mime_data_wrapper_write_to_stream(content, ostream); g_mime_stream_flush(ostream); g_object_unref(content); } else if (strcmp(ct->type, "image") == 0) { display_image(part); } }
static void collect_part(GMimeObject *part, PartCollectorData *fdata, gboolean multipart_parent) { GMimeContentType *content_type = g_mime_object_get_content_type(part); GMimeContentDisposition *disposition = g_mime_object_get_content_disposition(part); if (!content_type) return; GMimeDataWrapper *wrapper = g_mime_part_get_content_object(GMIME_PART(part)); if (!wrapper) return; // All the information will be collected in the CollectedPart CollectedPart *c_part = new_collected_part(fdata->part_id); gboolean is_attachment = FALSE; if (disposition) { c_part->disposition = g_ascii_strdown(disposition->disposition, -1); is_attachment = !g_ascii_strcasecmp(disposition->disposition, GMIME_DISPOSITION_ATTACHMENT); } // If a filename is given, collect it always const gchar *filename = g_mime_part_get_filename(GMIME_PART(part)); if (filename) c_part->filename = g_strdup(filename); // If a contentID is given, collect it always const char* content_id = g_mime_part_get_content_id (GMIME_PART(part)); if (content_id) c_part->content_id = g_strdup(content_id); // Get the contentType in lowercase gchar *content_type_str = g_mime_content_type_to_string(content_type); c_part->content_type = g_ascii_strdown(content_type_str, -1); g_free(content_type_str); // To qualify as a message body, a MIME entity MUST NOT have a Content-Disposition header with the value "attachment". if (!is_attachment && g_mime_content_type_is_type(content_type, "text", "*")) { gboolean is_text_plain = g_mime_content_type_is_type(content_type, "text", "plain"); gboolean is_text_html = g_mime_content_type_is_type(content_type, "text", "html"); gboolean is_text_rtf = g_mime_content_type_is_type(content_type, "text", "rtf"); gboolean is_text_enriched = g_mime_content_type_is_type(content_type, "text", "enriched"); gboolean is_new_text = !fdata->text_part && is_text_plain; gboolean is_new_html = !fdata->html_part && (is_text_html || is_text_enriched || is_text_rtf); GMimeStream *mem_stream = g_mime_stream_mem_new(); g_mime_stream_mem_set_owner(GMIME_STREAM_MEM(mem_stream), FALSE); GMimeStream *filtered_mem_stream = g_mime_stream_filter_new(mem_stream); const gchar *charset = g_mime_object_get_content_type_parameter(part, "charset"); if (charset && g_ascii_strcasecmp(charset, UTF8_CHARSET)) { GMimeFilter *utf8_charset_filter = g_mime_filter_charset_new(charset, UTF8_CHARSET); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_mem_stream), utf8_charset_filter); g_object_unref(utf8_charset_filter); } if (!fdata->raw && is_new_text) { GMimeFilter *strip_filter = g_mime_filter_strip_new(); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_mem_stream), strip_filter); g_object_unref(strip_filter); GMimeFilter *crlf_filter = g_mime_filter_crlf_new(FALSE, FALSE); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_mem_stream), crlf_filter); g_object_unref(crlf_filter); GMimeFilter *html_filter = g_mime_filter_html_new( GMIME_FILTER_HTML_CONVERT_NL | GMIME_FILTER_HTML_CONVERT_SPACES | GMIME_FILTER_HTML_CONVERT_URLS | GMIME_FILTER_HTML_MARK_CITATION | GMIME_FILTER_HTML_CONVERT_ADDRESSES | GMIME_FILTER_HTML_CITE, CITATION_COLOUR); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_mem_stream), html_filter); g_object_unref(html_filter); } if (!fdata->raw && (is_new_text || is_new_html)) { GMimeFilter *from_filter = g_mime_filter_from_new(GMIME_FILTER_FROM_MODE_ESCAPE); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_mem_stream), from_filter); g_object_unref(from_filter); } // Add Enriched/RTF filter for this content if (!fdata->raw && (is_new_html && (is_text_enriched || is_text_rtf))) { guint flags = 0; if (is_text_rtf) flags = GMIME_FILTER_ENRICHED_IS_RICHTEXT; GMimeFilter *enriched_filter = g_mime_filter_enriched_new(flags); g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_mem_stream), enriched_filter); g_object_unref(enriched_filter); } g_mime_data_wrapper_write_to_stream(wrapper, filtered_mem_stream); // Very important! Flush the the stream and get all content through. g_mime_stream_flush(filtered_mem_stream); // Freed by the mem_stream on its own (owner) [transfer none] c_part->content = g_mime_stream_mem_get_byte_array(GMIME_STREAM_MEM(mem_stream)); // After we unref the mem_stream, part_content is NOT available anymore g_object_unref(filtered_mem_stream); g_object_unref(mem_stream); // Without content, the collected body part is of no use, so we ignore it. if (c_part->content->len == 0) { free_collected_part(c_part); return; } // We accept only the first text and first html content, everything // else is considered an alternative body if (is_new_text) { fdata->text_part = c_part; } else if (is_new_html) { fdata->html_part = c_part; } else { g_ptr_array_add(fdata->alternative_bodies, c_part); } } else { GMimeStream *attachment_mem_stream = g_mime_stream_mem_new(); g_mime_stream_mem_set_owner (GMIME_STREAM_MEM(attachment_mem_stream), FALSE); g_mime_data_wrapper_write_to_stream(wrapper, attachment_mem_stream); g_mime_stream_flush(attachment_mem_stream); c_part->content = g_mime_stream_mem_get_byte_array(GMIME_STREAM_MEM(attachment_mem_stream)); g_object_unref(attachment_mem_stream); // Some content may not have disposition defined so we need to determine better what it is if ((disposition && !g_ascii_strcasecmp(disposition->disposition, GMIME_DISPOSITION_INLINE)) || g_mime_part_get_content_id(GMIME_PART(part))) { g_ptr_array_add(fdata->inlines, c_part); } else { // All other disposition should be kept within attachments g_ptr_array_add(fdata->attachments, c_part); } } }