示例#1
0
static GMimeStream*
get_mime_stream (GMimeObject *obj, GError **err)
{
	GMimeStream		*mstream;
	GMimeDataWrapper	*wrapper;

	if (!GMIME_IS_PART(obj)) {
		char		*str;
		GByteArray	*ar;

		str = g_mime_object_to_string (obj);
		ar  = g_byte_array_new_take ((guchar*)str, strlen(str));
		
		mstream = g_mime_stream_mem_new_with_byte_array (ar);
		g_mime_stream_mem_set_owner (
			GMIME_STREAM_MEM(mstream), TRUE);

		return mstream;
	}

	wrapper = get_data_wrapper (obj, err);
	if (!wrapper)
		return NULL;

	mstream = g_mime_data_wrapper_get_stream (wrapper);
	if (!mstream || g_mime_stream_reset (mstream) != 0) {
		g_set_error (err, G_IO_ERROR, G_IO_ERROR_FAILED,
			     "invalid mime-stream");
		return NULL;
	}

	return mstream;
}
示例#2
0
static GByteArray *
read_all_bytes (const char *path, gboolean is_text)
{
	GMimeStream *filtered, *stream, *mem;
	GMimeFilter *filter;
	GByteArray *buffer;
	
	buffer = g_byte_array_new ();
	stream = g_mime_stream_fs_open (path, O_RDONLY, 0644, NULL);
	mem = g_mime_stream_mem_new_with_byte_array (buffer);
	g_mime_stream_mem_set_owner ((GMimeStreamMem *) mem, FALSE);
	
	if (is_text) {
		filtered = g_mime_stream_filter_new (mem);
		filter = g_mime_filter_dos2unix_new (FALSE);
		g_mime_stream_filter_add ((GMimeStreamFilter *) filtered, filter);
		g_object_unref (filter);
		g_object_unref (mem);
	} else {
		filtered = mem;
	}
	
	g_mime_stream_write_to_stream (stream, filtered);
	g_mime_stream_flush (filtered);
	g_object_unref (filtered);
	g_object_unref (stream);
	
	return buffer;
}
示例#3
0
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);
}
示例#4
0
文件: gmimex.c 项目: swerter/gmimex
static void extract_part(GMimeObject *part, PartExtractorData *a_data) {
  GMimeDataWrapper *attachment_wrapper = g_mime_part_get_content_object(GMIME_PART(part));
  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(attachment_wrapper, attachment_mem_stream);
  g_mime_stream_flush(attachment_mem_stream);
  a_data->content = g_mime_stream_mem_get_byte_array(GMIME_STREAM_MEM(attachment_mem_stream));
  g_object_unref(attachment_mem_stream);
}
示例#5
0
static void
test_gzip (const char *datadir, const char *filename)
{
	char *name = g_strdup_printf ("%s.gz", filename);
	char *path = g_build_filename (datadir, filename, NULL);
	const char *what = "GMimeFilterGzip::zip";
	GByteArray *actual, *expected;
	GMimeStream *stream;
	GMimeFilter *filter;
	
	testsuite_check ("%s", what);
	
	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_gzip_new (GMIME_FILTER_GZIP_MODE_ZIP, 9);
	g_mime_filter_gzip_set_filename ((GMimeFilterGZip *) filter, filename);
	g_mime_filter_gzip_set_comment ((GMimeFilterGZip *) filter, "This is a comment.");
	
	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, name, NULL);
	expected = read_all_bytes (path, FALSE);
	g_free (name);
	g_free (path);
	
	if (actual->len != 1233 && (actual->len != expected->len || memcmp (actual->data, expected->data, actual->len) != 0)) {
		if (actual->len != expected->len)
			testsuite_check_failed ("%s failed: streams are not the same length: %u", what, actual->len);
		else
			testsuite_check_failed ("%s failed: streams do not match", what);
		
		name = g_strdup_printf ("%s.1.gz", filename);
		path = g_build_filename (datadir, name, NULL);
		g_free (name);
		
		stream = g_mime_stream_fs_open (path, O_WRONLY | O_CREAT | O_TRUNC, 0644, NULL);
		g_free (path);
		
		g_mime_stream_write (stream, (const char *) actual->data, actual->len);
		g_mime_stream_flush (stream);
		g_object_unref (stream);
	} else {
		testsuite_check_passed ();
	}
	
	g_byte_array_free (expected, TRUE);
	g_byte_array_free (actual, TRUE);
}
示例#6
0
static void
test_charset_conversion (const char *datadir, const char *base, const char *from, const char *to)
{
	const char *what = "GMimeFilterCharset";
	GByteArray *actual, *expected;
	GMimeStream *stream;
	GMimeFilter *filter;
	char *path, *name;
	
	testsuite_check ("%s (%s %s -> %s)", what, base, from, to);
	
	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_charset_new (from, to);
	
	name = g_strdup_printf ("%s.%s.txt", base, from);
	path = g_build_filename (datadir, name, 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);
	g_free (name);
	
	name = g_strdup_printf ("%s.%s.txt", base, to);
	path = g_build_filename (datadir, name, NULL);
	expected = read_all_bytes (path, TRUE);
	g_free (path);
	g_free (name);
	
	if (actual->len != expected->len) {
		testsuite_check_failed ("%s failed: stream lengths do not match: expected=%u; actual=%u",
					what, expected->len, actual->len);
		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);
}
示例#7
0
static void
test_enriched (const char *datadir, const char *input, const char *output)
{
	const char *what = "GMimeFilterEnriched";
	GByteArray *actual, *expected;
	GMimeStream *stream;
	GMimeFilter *filter;
	char *path;
	
	testsuite_check ("%s (%s)", what, input);
	
	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_enriched_new (0);
	
	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);
		printf ("enriched: -->%.*s<--\n", (int) actual->len, (char *) actual->data);
		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);
}
示例#8
0
static void
test_gunzip (const char *datadir, const char *filename)
{
	char *name = g_strdup_printf ("%s.gz", filename);
	char *path = g_build_filename (datadir, name, NULL);
	const char *what = "GMimeFilterGzip::unzip";
	GByteArray *actual, *expected;
	GMimeStream *stream;
	GMimeFilter *filter;
	const char *value;
	
	testsuite_check ("%s", what);
	
	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_gzip_new (GMIME_FILTER_GZIP_MODE_UNZIP, 9);
	
	pump_data_through_filter (filter, path, stream, FALSE, TRUE);
	g_object_unref (stream);
	g_free (path);
	g_free (name);
	
	path = g_build_filename (datadir, filename, 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);
		goto error;
	}
	
	if (memcmp (actual->data, expected->data, actual->len) != 0) {
		testsuite_check_failed ("%s failed: stream contents do not match", what);
		goto error;
	}
	
	value = g_mime_filter_gzip_get_filename ((GMimeFilterGZip *) filter);
	if (!value || strcmp (value, filename) != 0) {
		testsuite_check_failed ("%s failed: filename does not match: %s", what, value);
		goto error;
	}
	
	value = g_mime_filter_gzip_get_comment ((GMimeFilterGZip *) filter);
	if (!value || strcmp (value, "This is a comment.") != 0) {
		testsuite_check_failed ("%s failed: comment does not match: %s", what, value);
		goto error;
	}
	
	testsuite_check_passed ();
	
error:
	
	g_byte_array_free (expected, TRUE);
	g_byte_array_free (actual, TRUE);
	
	g_mime_filter_reset (filter);
	g_object_unref (filter);
}
示例#9
0
文件: gmimex.c 项目: swerter/gmimex
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);
    }

  }
}
示例#10
0
static void
rspamd_process_file (struct rspamd_config *cfg, const gchar *fname, gint mode)
{
	struct rspamd_task *task;
	gint fd;
	gpointer map;
	struct stat st;
	GError *err = NULL;
#if 0
	GMimeMessage *message;
	GMimeParser *parser;
	GMimeStream *stream;
	GByteArray tmp;
#endif
	struct rspamd_mime_part *part;
	guint i;
	gdouble ts1, ts2;

	fd = open (fname, O_RDONLY);

	if (fd == -1) {
		rspamd_fprintf (stderr, "cannot open %s: %s\n", fname, strerror (errno));
		exit (EXIT_FAILURE);
	}

	if (fstat (fd, &st) == -1) {
		rspamd_fprintf (stderr, "cannot stat %s: %s\n", fname, strerror (errno));
		exit (EXIT_FAILURE);
	}

	map = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
	close (fd);

	if (map == MAP_FAILED) {
		rspamd_fprintf (stderr, "cannot mmap %s: %s\n", fname, strerror (errno));
		exit (EXIT_FAILURE);
	}

	task = rspamd_task_new (NULL, cfg);
	task->msg.begin = map;
	task->msg.len = st.st_size;

	ts1 = rspamd_get_ticks ();

	if (mode == MODE_NORMAL) {
		if (!rspamd_mime_parse_task (task, &err)) {
			rspamd_fprintf (stderr, "cannot parse %s: %e\n", fname, err);
			g_error_free (err);
		}
	}
#if 0
	else if (mode == MODE_GMIME) {
		tmp.data = map;
		tmp.len = st.st_size;
		stream = g_mime_stream_mem_new_with_byte_array (&tmp);
		g_mime_stream_mem_set_owner (GMIME_STREAM_MEM (stream), FALSE);
		parser = g_mime_parser_new_with_stream (stream);
		message = g_mime_parser_construct_message (parser);
	}
#endif
	ts2 = rspamd_get_ticks ();
	total_time += ts2 - ts1;

	if (mode == MODE_NORMAL) {
		for (i = 0; i < task->parts->len; i ++) {
			part = g_ptr_array_index (task->parts, i);

			if (part->ct->flags & RSPAMD_CONTENT_TYPE_MULTIPART) {
				rspamd_show_multipart (part);
			}
			else if (part->ct->flags & RSPAMD_CONTENT_TYPE_MESSAGE) {
				rspamd_show_message (part);
			}
			else {
				rspamd_show_normal (part);
			}
		}
	}
#if 0
	else if (mode == MODE_GMIME) {
		g_mime_message_foreach (message, mime_foreach_callback, NULL);
	}
#endif

	rspamd_task_free (task);
	munmap (map, st.st_size);
#if 0
	if (mode == MODE_GMIME) {
		g_object_unref (message);
	}
#endif
}