Ejemplo n.º 1
0
END_TEST

START_TEST(test_store_empty_01)
{
    ip_map_t  map;
    ip_map_t  *read_map;

    ipmap_init(&map, 0);

    GOutputStream  *ostream =
        g_memory_output_stream_new(NULL, 0, g_realloc, g_free);
    GMemoryOutputStream  *mostream =
        G_MEMORY_OUTPUT_STREAM(ostream);

    fail_unless(ipmap_save(ostream, &map, NULL),
                "Could not save map");

    GInputStream  *istream =
        g_memory_input_stream_new_from_data
        (g_memory_output_stream_get_data(mostream),
         g_memory_output_stream_get_data_size(mostream),
         NULL);

    read_map = ipmap_load(istream, NULL);
    fail_if(read_map == NULL,
            "Could not read map");

    fail_unless(ipmap_is_equal(&map, read_map),
                "Map not same after saving/loading");

    g_object_unref(ostream);
    g_object_unref(istream);
    ipmap_done(&map);
    ipmap_free(read_map);
}
Ejemplo n.º 2
0
END_TEST

START_TEST(test_store_empty)
{
    ip_set_t  set;
    ip_set_t  *read_set;

    ipset_init(&set);

    GOutputStream  *ostream =
        g_memory_output_stream_new(NULL, 0, g_realloc, g_free);
    GMemoryOutputStream  *mostream =
        G_MEMORY_OUTPUT_STREAM(ostream);

    fail_unless(ipset_save(ostream, &set, NULL),
                "Could not save set");

    GInputStream  *istream =
        g_memory_input_stream_new_from_data
        (g_memory_output_stream_get_data(mostream),
         g_memory_output_stream_get_data_size(mostream),
         NULL);

    read_set = ipset_load(istream, NULL);
    fail_if(read_set == NULL,
            "Could not read set");

    fail_unless(ipset_is_equal(&set, read_set),
                "Set not same after saving/loading");

    g_object_unref(ostream);
    g_object_unref(istream);
    ipset_done(&set);
    ipset_free(read_set);
}
Ejemplo n.º 3
0
/**
 * Read all input from @src, allocating a new #GVariant from it into
 * output variable @out_variant.  @src will be closed as a result.
 *
 * Note the returned @out_variant is not floating.
 */
gboolean
ot_util_variant_from_stream (GInputStream         *src,
                             const GVariantType   *type,
                             gboolean              trusted,
                             GVariant            **out_variant,
                             GCancellable         *cancellable,
                             GError              **error)
{
  gboolean ret = FALSE;
  gs_unref_object GMemoryOutputStream *data_stream = NULL;
  gs_unref_variant GVariant *ret_variant = NULL;

  data_stream = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0, g_realloc, g_free);

  if (g_output_stream_splice ((GOutputStream*)data_stream, src,
                              G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
                              cancellable, error) < 0)
    goto out;

  ret_variant = g_variant_new_from_data (type, g_memory_output_stream_get_data (data_stream),
                                         g_memory_output_stream_get_data_size (data_stream),
                                         trusted, (GDestroyNotify) g_object_unref, data_stream);
  data_stream = NULL; /* Transfer ownership */
  g_variant_ref_sink (ret_variant);

  ret = TRUE;
  ot_transfer_out_value (out_variant, &ret_variant);
 out:
  return ret;
}
Ejemplo n.º 4
0
char *
g_vfs_afp_command_get_data (GVfsAfpCommand *comm)
{
  GMemoryOutputStream *mem_stream;

  mem_stream =
    G_MEMORY_OUTPUT_STREAM (g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (comm)));

  return g_memory_output_stream_get_data (mem_stream);
}
Ejemplo n.º 5
0
static void
user_style_sheet_output_stream_splice_cb (GOutputStream *output_stream,
                                          GAsyncResult  *result,
                                          gpointer       user_data)
{
  gssize bytes;

  bytes = g_output_stream_splice_finish (output_stream, result, NULL);
  if (bytes > 0) {
    WebKitUserStyleSheet *style_sheet;

    style_sheet = webkit_user_style_sheet_new (g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (output_stream)),
                                               WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_STYLE_LEVEL_USER,
                                               NULL, NULL);
    webkit_user_content_manager_add_style_sheet (WEBKIT_USER_CONTENT_MANAGER (ephy_embed_shell_get_user_content_manager (ephy_embed_shell_get_default ())),
                                                 style_sheet);
    webkit_user_style_sheet_unref (style_sheet);
  }
}
Ejemplo n.º 6
0
static void ekg_gnutls_flush(struct ekg_connection *c) {
	struct ekg_gnutls_connection *gc = c->master->priv_data;
	GMemoryOutputStream *dos = gc->outstream;
	ssize_t ret;
	gconstpointer bufp;
	gsize bufleft;

		/* GMemoryOutputStream is not supposed to fail */
	g_assert(g_output_stream_flush(
			G_OUTPUT_STREAM(c->outstream),
			NULL,
			NULL));

		/* now pass the written data to gnutls */
	bufp = g_memory_output_stream_get_data(dos);
	bufleft = g_memory_output_stream_get_data_size(dos);
	do {
		ret = gnutls_record_send(gc->session, bufp, bufleft);

		if (ret > 0) {
			g_assert(ret <= bufleft);
			bufp += ret;
			bufleft -= ret;
		} else if (ret != GNUTLS_E_INTERRUPTED && ret != GNUTLS_E_AGAIN) {
			debug_error("gnutls_flush(), write failed: %s\n",
					gnutls_strerror(ret));
			/* XXX */
			failed_write(c);
		}
	} while (bufleft > 0);

	{
		GSeekable *sos = G_SEEKABLE(dos);
		g_assert(g_seekable_seek(sos, 0, G_SEEK_SET, NULL, NULL));
		g_assert(g_seekable_truncate(sos, 0, NULL, NULL));
	}
}
Ejemplo n.º 7
0
GDataInputStream *
http_data_input_stream(GInputStream * stream,gsize * length,GCancellable * cancellable,GError ** error)
{
	GMemoryOutputStream
	* out = G_MEMORY_OUTPUT_STREAM(g_memory_output_stream_new_resizable());
	gchar * content = NULL;
	guint8 byte = 0;
	while(g_input_stream_read(stream,&byte,1,cancellable,error))
	{
		if(g_memory_output_stream_get_data_size(out) > 2048)
		{
			g_output_stream_close(G_OUTPUT_STREAM(out),NULL,NULL);
			g_free(g_memory_output_stream_steal_data(out));
			g_object_unref(out);
			return NULL;
		}
		g_output_stream_write_all(G_OUTPUT_STREAM(out),&byte,1,NULL,NULL,NULL);
		if(g_memory_output_stream_get_data_size(out) >= 4)
		{
			content = g_memory_output_stream_get_data(out);
			if(strncmp((content + g_memory_output_stream_get_data_size(out) - 4),"\r\n\r\n",4) == 0)
				break;
		}
	}
	g_output_stream_close(G_OUTPUT_STREAM(out),NULL,NULL);
	GMemoryInputStream
	* result = G_MEMORY_INPUT_STREAM(g_memory_input_stream_new_from_data(
				g_memory_output_stream_steal_data(out),
				g_memory_output_stream_get_data_size(out),
				g_free
			));
	g_object_unref(out);
	GDataInputStream
	* dis = g_data_input_stream_new(G_INPUT_STREAM(result));
	g_data_input_stream_set_newline_type(dis,G_DATA_STREAM_NEWLINE_TYPE_CR_LF);
	return dis;
}
Ejemplo n.º 8
0
static void run_test (gconstpointer data)
{
    GFileInputStream *stream;
    gchar contents[1024];
    gsize bytes;
    gchar *curi, *newline;
    gchar **uriv;
    GFile *file = G_FILE (data);
    YelpUri *uri;
    GOutputStream *outstream;
    gchar *out;

    stream = g_file_read (file, NULL, NULL);
    g_assert (g_input_stream_read_all (G_INPUT_STREAM (stream),
                                       contents, 1024, &bytes,
                                       NULL, NULL));
    newline = strchr (contents, '\n');
    curi = g_strndup (contents, newline - contents);
    uriv = g_strsplit (curi, " ", 2);
    uri = yelp_uri_new (uriv[0]);
    if (uriv[1] != NULL)
        uri = yelp_uri_new_relative (uri, uriv[1]);
    g_strfreev (uriv);

    yelp_uri_resolve (uri);

    while (!yelp_uri_is_resolved (uri))
        while (g_main_context_pending (NULL))
            g_main_context_iteration (NULL, FALSE);

    outstream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
    print_uri (curi, uri, outstream);
    out = (gchar *) g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (outstream));
    g_free (curi);
    g_assert (!strncmp (out, contents, bytes));
}
Ejemplo n.º 9
0
/**
 * as_get_yml_data_origin:
 *
 * Extract the data origin from the AppStream YAML file.
 * We don't use the #AsYAMLData loader, because it is much
 * slower than just loading the initial parts of the file and
 * extracting the origin manually.
 */
static gchar*
as_get_yml_data_origin (const gchar *fname)
{
	const gchar *data;
	GZlibDecompressor *zdecomp;
	g_autoptr(GFileInputStream) fistream = NULL;
	g_autoptr(GMemoryOutputStream) mem_os = NULL;
	g_autoptr(GInputStream) conv_stream = NULL;
	g_autoptr(GFile) file = NULL;
	g_autofree gchar *str = NULL;
	g_auto(GStrv) strv = NULL;
	GError *err;
	guint i;
	gchar *start, *end;
	gchar *origin = NULL;

	file = g_file_new_for_path (fname);
	fistream = g_file_read (file, NULL, &err);

	if (!fistream) {
		g_critical ("Unable to open file '%s' for reading: %s, skipping.", fname, err->message);
		g_error_free (err);
		return NULL;
	}

	mem_os = (GMemoryOutputStream*) g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
	zdecomp = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
	conv_stream = g_converter_input_stream_new (G_INPUT_STREAM (fistream), G_CONVERTER (zdecomp));
	g_object_unref (zdecomp);

	g_output_stream_splice (G_OUTPUT_STREAM (mem_os), conv_stream, 0, NULL, NULL);
	data = (const gchar*) g_memory_output_stream_get_data (mem_os);

	/* faster than a regular expression?
	 * Get the first YAML document, then extract the origin string.
	 */
	if (data == NULL)
		return NULL;
	/* start points to the start of the document, i.e. "File:" normally */
	start = g_strstr_len (data, 400, YAML_SEPARATOR) + YAML_SEPARATOR_LEN;
	if (start == NULL)
		return NULL;
	/* Find the end of the first document - can be NULL if there is only one,
	 * for example if we're given YAML for an empty archive */
	end = g_strstr_len (start, -1, YAML_SEPARATOR);
	str = g_strndup (start, strlen(start) - (end ? strlen(end) : 0));

	strv = g_strsplit (str, "\n", -1);
	for (i = 0; strv[i] != NULL; i++) {
		g_auto(GStrv) strv2 = NULL;
		if (!g_str_has_prefix (strv[i], "Origin:"))
			continue;

		strv2 = g_strsplit (strv[i], ":", 2);
		g_strstrip (strv2[1]);
		origin = g_strdup (strv2[1]);

		/* remove quotes, in case the string is quoted */
		if ((g_str_has_prefix (origin, "\"")) && (g_str_has_suffix (origin, "\""))) {
			g_autofree gchar *tmp = NULL;

			tmp = origin;
			origin = g_strndup (tmp + 1, strlen (tmp) - 2);
		}

		break;
	}

	return origin;
}
static gboolean
emfe_attachment_format (EMailFormatterExtension *extension,
                        EMailFormatter *formatter,
                        EMailFormatterContext *context,
                        EMailPart *part,
                        GOutputStream *stream,
                        GCancellable *cancellable)
{
	gchar *text, *html;
	gchar *button_id;
	EAttachmentStore *store;
	EMailExtensionRegistry *registry;
	GQueue *extensions;
	EMailPartAttachment *empa;
	CamelMimePart *mime_part;
	CamelMimeFilterToHTMLFlags flags;
	GString *buffer;
	const gchar *attachment_part_id;
	const gchar *part_id;

	g_return_val_if_fail (E_IS_MAIL_PART_ATTACHMENT (part), FALSE);

	empa = (EMailPartAttachment *) part;
	part_id = e_mail_part_get_id (part);

	if ((context->mode == E_MAIL_FORMATTER_MODE_NORMAL) ||
	    (context->mode == E_MAIL_FORMATTER_MODE_PRINTING) ||
	    (context->mode == E_MAIL_FORMATTER_MODE_ALL_HEADERS)) {
		EAttachment *attachment;
		GList *head, *link;

		attachment = e_mail_part_attachment_ref_attachment (
			E_MAIL_PART_ATTACHMENT (part));

		head = g_queue_peek_head_link (&part->validities);

		for (link = head; link != NULL; link = g_list_next (link)) {
			EMailPartValidityPair *pair = link->data;

			if (pair == NULL)
				continue;

			if ((pair->validity_type & E_MAIL_PART_VALIDITY_SIGNED) != 0)
				e_attachment_set_signed (
					attachment,
					pair->validity->sign.status);

			if ((pair->validity_type & E_MAIL_PART_VALIDITY_ENCRYPTED) != 0)
				e_attachment_set_encrypted (
					attachment,
					pair->validity->encrypt.status);
		}

		store = find_attachment_store (context->part_list, part);
		if (store) {
			GList *attachments = e_attachment_store_get_attachments (store);
			if (!g_list_find (attachments, attachment)) {
				e_attachment_store_add_attachment (
					store, attachment);
			}
			g_list_free (attachments);
		} else {
			g_warning ("Failed to locate attachment-bar for %s", part_id);
		}

		g_object_unref (attachment);
	}

	registry = e_mail_formatter_get_extension_registry (formatter);

	extensions = e_mail_extension_registry_get_for_mime_type (
		registry, empa->snoop_mime_type);
	if (extensions == NULL)
		extensions = e_mail_extension_registry_get_fallback (
			registry, empa->snoop_mime_type);

	/* If the attachment is requested as RAW, then call the
	 * handler directly and do not append any other code. */
	if ((context->mode == E_MAIL_FORMATTER_MODE_RAW) ||
	    (context->mode == E_MAIL_FORMATTER_MODE_PRINTING)) {
		GList *head, *link;
		gboolean success = FALSE;

		if (extensions == NULL)
			return FALSE;

		if (context->mode == E_MAIL_FORMATTER_MODE_PRINTING) {
			gchar *name;
			EAttachment *attachment;
			GFileInfo *file_info;
			const gchar *display_name;
			gchar *description;

			attachment = e_mail_part_attachment_ref_attachment (
				E_MAIL_PART_ATTACHMENT (part));

			file_info = e_attachment_ref_file_info (attachment);
			display_name = g_file_info_get_display_name (file_info);

			description = e_attachment_dup_description (attachment);
			if (description != NULL && *description != '\0') {
				name = g_strdup_printf (
					"<h2>Attachment: %s (%s)</h2>\n",
					description, display_name);
			} else {
				name = g_strdup_printf (
					"<h2>Attachment: %s</h2>\n",
					display_name);
			}

			g_output_stream_write_all (
				stream, name, strlen (name),
				NULL, cancellable, NULL);

			g_free (description);
			g_free (name);

			g_object_unref (attachment);
			g_object_unref (file_info);
		}

		head = g_queue_peek_head_link (extensions);

		for (link = head; link != NULL; link = g_list_next (link)) {
			success = e_mail_formatter_extension_format (
				E_MAIL_FORMATTER_EXTENSION (link->data),
				formatter, context, part, stream, cancellable);
			if (success)
				break;
		}

		return success;
	}

	/* E_MAIL_FORMATTER_MODE_NORMAL: */

	mime_part = e_mail_part_ref_mime_part (part);
	text = e_mail_part_describe (mime_part, empa->snoop_mime_type);
	flags = e_mail_formatter_get_text_format_flags (formatter);
	html = camel_text_to_html (
		text, flags & CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0);
	g_free (text);
	g_object_unref (mime_part);

	if (empa->attachment_view_part_id)
		attachment_part_id = empa->attachment_view_part_id;
	else
		attachment_part_id = part_id;

	button_id = g_strconcat (attachment_part_id, ".attachment_button", NULL);

	/* XXX Wild guess at the initial size. */
	buffer = g_string_sized_new (8192);

	g_string_append_printf (
		buffer,
		"<div class=\"attachment\">"
		"<table width=\"100%%\" border=\"0\">"
		"<tr valign=\"middle\">"
		"<td align=\"left\" width=\"100\">"
		"<object type=\"application/vnd.evolution.widget.attachment-button\" "
		"height=\"20\" width=\"100\" data=\"%s\" id=\"%s\"></object>"
		"</td>"
		"<td align=\"left\">%s</td>"
		"</tr>", part_id, button_id, html);

	g_free (button_id);
	g_free (html);

	if (extensions != NULL) {
		GOutputStream *content_stream;
		gboolean success = FALSE;

		content_stream = g_memory_output_stream_new_resizable ();

		if (empa->attachment_view_part_id != NULL) {
			EMailPart *attachment_view_part;

			attachment_view_part = e_mail_part_list_ref_part (
				context->part_list,
				empa->attachment_view_part_id);

			/* Avoid recursion. */
			if (attachment_view_part == part)
				g_clear_object (&attachment_view_part);

			if (attachment_view_part != NULL) {
				success = e_mail_formatter_format_as (
					formatter, context,
					attachment_view_part,
					content_stream, NULL,
					cancellable);
				g_object_unref (attachment_view_part);
			}

		} else {
			GList *head, *link;

			head = g_queue_peek_head_link (extensions);

			for (link = head; link != NULL; link = g_list_next (link)) {
				success = e_mail_formatter_extension_format (
					E_MAIL_FORMATTER_EXTENSION (link->data),
					formatter, context,
					part, content_stream,
					cancellable);
				if (success)
					break;
			}
		}

		if (success) {
			gchar *wrapper_element_id;
			gconstpointer data;
			gsize size;

			wrapper_element_id = g_strconcat (
				attachment_part_id, ".wrapper", NULL);

			data = g_memory_output_stream_get_data (
				G_MEMORY_OUTPUT_STREAM (content_stream));
			size = g_memory_output_stream_get_data_size (
				G_MEMORY_OUTPUT_STREAM (content_stream));

			g_string_append_printf (
				buffer,
				"<tr><td colspan=\"2\">"
				"<div class=\"attachment-wrapper\" id=\"%s\">",
				wrapper_element_id);

			g_string_append_len (buffer, data, size);

			g_string_append (buffer, "</div></td></tr>");

			g_free (wrapper_element_id);
		}

		g_object_unref (content_stream);
	}

	g_string_append (buffer, "</table></div>");

	g_output_stream_write_all (
		stream, buffer->str, buffer->len, NULL, cancellable, NULL);

	g_string_free (buffer, TRUE);

	return TRUE;
}
Ejemplo n.º 11
0
char *
gvfs_file_info_marshal (GFileInfo *info,
			gsize     *size)
{
  GOutputStream *memstream;
  GDataOutputStream *out;
  GFileAttributeType type;
  GFileAttributeStatus status;
  GObject *obj;
  char **attrs, *attr;
  char *data;
  int i;

  memstream = g_memory_output_stream_new (NULL, 0, g_realloc, NULL);

  out = g_data_output_stream_new (memstream);
  g_object_unref (memstream);

  attrs = g_file_info_list_attributes (info, NULL);

  g_data_output_stream_put_uint32 (out,
				   g_strv_length (attrs),
				   NULL, NULL);

  for (i = 0; attrs[i] != NULL; i++)
    {
      attr = attrs[i];

      type = g_file_info_get_attribute_type  (info, attr);
      status = g_file_info_get_attribute_status  (info, attr);
      
      put_string (out, attr);
      g_data_output_stream_put_byte (out, type, 
				     NULL, NULL);
      g_data_output_stream_put_byte (out, status, 
				     NULL, NULL);

      switch (type)
	{
	case G_FILE_ATTRIBUTE_TYPE_STRING:
	  put_string (out, g_file_info_get_attribute_string (info, attr));
	  break;
	case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
	  put_string (out, g_file_info_get_attribute_byte_string (info, attr));
	  break;
	case G_FILE_ATTRIBUTE_TYPE_STRINGV:
	  put_stringv (out, g_file_info_get_attribute_stringv (info, attr));
	  break;
	case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
	  g_data_output_stream_put_byte (out,
					 g_file_info_get_attribute_boolean (info, attr),
					 NULL, NULL);
	  break;
	case G_FILE_ATTRIBUTE_TYPE_UINT32:
	  g_data_output_stream_put_uint32 (out,
					   g_file_info_get_attribute_uint32 (info, attr),
					  NULL, NULL);
	  break;
	case G_FILE_ATTRIBUTE_TYPE_INT32:
	  g_data_output_stream_put_int32 (out,
					  g_file_info_get_attribute_int32 (info, attr),
					  NULL, NULL);
	  break;
	case G_FILE_ATTRIBUTE_TYPE_UINT64:
	  g_data_output_stream_put_uint64 (out,
					   g_file_info_get_attribute_uint64 (info, attr),
					  NULL, NULL);
	  break;
	case G_FILE_ATTRIBUTE_TYPE_INT64:
	  g_data_output_stream_put_int64 (out,
					  g_file_info_get_attribute_int64 (info, attr),
					  NULL, NULL);
	  break;
	case G_FILE_ATTRIBUTE_TYPE_OBJECT:
          obj = g_file_info_get_attribute_object (info, attr);
	  if (obj == NULL)
	    {
	      g_data_output_stream_put_byte (out, 0,
					     NULL, NULL);
	    }
	  else if (G_IS_ICON (obj))
	    {
	      char *icon_str;

	      icon_str = g_icon_to_string (G_ICON (obj));
	      g_data_output_stream_put_byte (out, 1,
					     NULL, NULL);
	      put_string (out, icon_str);
	      g_free (icon_str);
	    }
	  else
	    {
	      g_warning ("Unsupported GFileInfo object type %s\n",
			 g_type_name_from_instance ((GTypeInstance *)obj));
	      g_data_output_stream_put_byte (out, 0,
					     NULL, NULL);
	    }
	  break;
	case G_FILE_ATTRIBUTE_TYPE_INVALID:
	default:
	  break;
	}
    }

  data = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (memstream));
  *size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (memstream));
  g_object_unref (out);
  g_strfreev (attrs);
  return data;
}
Ejemplo n.º 12
0
static gboolean
emfe_text_html_format (EMailFormatterExtension *extension,
                       EMailFormatter *formatter,
                       EMailFormatterContext *context,
                       EMailPart *part,
                       GOutputStream *stream,
                       GCancellable *cancellable)
{
	if (g_cancellable_is_cancelled (cancellable))
		return FALSE;

	if (context->mode == E_MAIL_FORMATTER_MODE_RAW) {
		e_mail_formatter_format_text (
			formatter, part, stream, cancellable);

	} else if (context->mode == E_MAIL_FORMATTER_MODE_PRINTING) {
		GOutputStream *decoded_stream;
		GString *string;
		gchar *pos;
		GList *tags, *iter;
		gboolean valid;
		gchar *tag;
		const gchar *document_end;
		gpointer data;
		gsize length;
		gint i;

		decoded_stream = g_memory_output_stream_new_resizable ();

		/* FORMATTER FIXME: See above */
		e_mail_formatter_format_text (
			formatter, part, decoded_stream, cancellable);

		data = g_memory_output_stream_get_data (
			G_MEMORY_OUTPUT_STREAM (decoded_stream));
		length = g_memory_output_stream_get_data_size (
			G_MEMORY_OUTPUT_STREAM (decoded_stream));

		string = g_string_new_len ((gchar *) data, length);

		g_object_unref (decoded_stream);

		if (!g_utf8_validate (string->str, -1, NULL)) {
			gchar *valid_utf8;

			valid_utf8 = e_util_utf8_make_valid (string->str);
			g_string_free (string, TRUE);
			string = g_string_new (valid_utf8);
			g_free (valid_utf8);
		}

		tags = NULL;
		pos = string->str;
		valid = FALSE;

		do {
			gchar *tmp;
			gchar *closing;
			gchar *opening;

			tmp = g_utf8_find_next_char (pos, NULL);
			pos = g_utf8_strchr (tmp, -1, '<');
			if (!pos)
				break;

			opening = pos;
			closing = g_utf8_strchr (pos, -1, '>');

			/* Find where the actual tag name begins */
			while (tag = g_utf8_find_next_char (pos, NULL), tag != NULL) {
				gunichar c = g_utf8_get_char (tag);
				if (!g_unichar_isspace (c))
					break;
			}

			if (g_ascii_strncasecmp (tag, "style", 5) == 0) {
				tags = g_list_append (
					tags,
					get_tag (string->str, "style", opening, closing));
			} else if (g_ascii_strncasecmp (tag, "script", 6) == 0) {
				tags = g_list_append (
					tags,
					get_tag (string->str, "script", opening, closing));
			} else if (g_ascii_strncasecmp (tag, "link", 4) == 0) {
				tags = g_list_append (
					tags,
					get_tag (string->str, "link", opening, closing));
			} else if (g_ascii_strncasecmp (tag, "body", 4) == 0) {
				valid = TRUE;
				break;
			}

		} while (pos);

		/* Something's wrong, let's write the entire HTML and hope
		 * that WebKit can handle it */
		if (!valid) {
			EMailFormatterContext c = {
				.part_list = context->part_list,
				.flags = context->flags,
				.mode = E_MAIL_FORMATTER_MODE_RAW,
			};

			emfe_text_html_format (
				extension, formatter, &c,
				part, stream, cancellable);
			return FALSE;
		}

		/*	       include the "body" as well -----v */
		g_string_erase (string, 0, tag - string->str + 4);
		g_string_prepend (string, "<div ");

		for (iter = tags; iter; iter = iter->next) {
			if (iter->data)
				g_string_prepend (string, iter->data);
		}

		g_list_free_full (tags, g_free);

		document_end = NULL;
		/* We can probably use ASCII functions here */
		if (g_strrstr (string->str, "</body>")) {
			document_end = ">ydob/<";
		}

		if (g_strrstr (string->str, "</html>")) {
			if (document_end) {
				document_end = ">lmth/<>ydob/<";
			} else {
				document_end = ">lmth/<";
			}
		}

		if (document_end) {
			length = strlen (document_end);
			tag = string->str + string->len - 1;
			i = 0;
			valid = FALSE;
			while (i < length - 1) {
				gunichar c;

				c = g_utf8_get_char (tag);
				if (g_unichar_isspace (c)) {
					tag = g_utf8_find_prev_char (string->str, tag);
					continue;
				}

				c = g_unichar_tolower (c);

				if (c == document_end[i]) {
					tag = g_utf8_find_prev_char (string->str, tag);
					i++;
					valid = TRUE;
					continue;
				}

				tag = g_utf8_find_prev_char (string->str, tag);
				valid = FALSE;
			}
		} else {
			/* do not cut, if there is no end tag */
			valid = FALSE;
		}

		if (valid)
			g_string_truncate (string, tag - string->str);

		g_output_stream_write_all (
			stream, string->str, string->len,
			NULL, cancellable, NULL);

		g_string_free (string, TRUE);
	} else {