Ejemplo n.º 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;
}
/**
 * g_mime_header_list_write_to_stream:
 * @headers: a #GMimeHeaderList
 * @stream: output stream
 *
 * Write the headers to a stream.
 *
 * Returns: the number of bytes written or %-1 on fail.
 **/
ssize_t
g_mime_header_list_write_to_stream (const GMimeHeaderList *headers, GMimeStream *stream)
{
	ssize_t nwritten, total = 0;
	GMimeHeaderWriter writer;
	GHashTable *writers;
	GMimeHeader *header;
	
	g_return_val_if_fail (headers != NULL, -1);
	g_return_val_if_fail (stream != NULL, -1);
	
	if (headers->stream) {
		g_mime_stream_reset (headers->stream);
		return g_mime_stream_write_to_stream (headers->stream, stream);
	}
	
	header = (GMimeHeader *) headers->list.head;
	writers = headers->writers;
	
	while (header->next) {
		if (header->value) {
			if (!(writer = g_hash_table_lookup (writers, header->name)))
				writer = default_writer;
			
			if ((nwritten = writer (stream, header->name, header->value)) == -1)
				return -1;
			
			total += nwritten;
		}
		
		header = header->next;
	}
	
	return total;
}
Ejemplo n.º 3
0
static void
test_cat_read (GMimeStream *whole, struct _StreamPart *parts, int bounded)
{
	struct _StreamPart *part = parts;
	GMimeStream *stream, *cat;
	Exception *ex;
	int fd;
	
	cat = g_mime_stream_cat_new ();
	
	while (part != NULL) {
		d(fprintf (stderr, "adding %s start=%lld, end=%lld...\n",
			   part->filename, part->pstart, part->pend));
		
		if ((fd = open (part->filename, O_RDONLY, 0)) == -1) {
			ex = exception_new ("could not open `%s': %s", part->filename, g_strerror (errno));
			g_object_unref (cat);
			throw (ex);
		}
		
		stream = g_mime_stream_fs_new_with_bounds (fd, part->pstart, bounded ? part->pend : -1);
		g_mime_stream_cat_add_source ((GMimeStreamCat *) cat, stream);
		g_object_unref (stream);
		
		part = part->next;
	}
	
	g_mime_stream_reset (whole);
	if (check_streams_match (whole, cat, "stream.part*", TRUE) == -1) {
		ex = exception_new ("streams do not match");
		g_object_unref (cat);
		throw (ex);
	}
}
/**
 * g_mime_header_list_to_string:
 * @headers: a #GMimeHeaderList
 *
 * Allocates a string buffer containing the raw rfc822 headers
 * contained in @headers.
 *
 * Returns: a string containing the header block.
 **/
char *
g_mime_header_list_to_string (const GMimeHeaderList *headers)
{
	GMimeStream *stream;
	GByteArray *array;
	char *str;
	
	g_return_val_if_fail (headers != NULL, NULL);
	
	array = g_byte_array_new ();
	stream = g_mime_stream_mem_new ();
	g_mime_stream_mem_set_byte_array (GMIME_STREAM_MEM (stream), array);
	
	if (headers->stream) {
		g_mime_stream_reset (headers->stream);
		g_mime_stream_write_to_stream (headers->stream, stream);
	} else {
		g_mime_header_list_write_to_stream (headers, stream);
	}
	
	g_object_unref (stream);
	
	g_byte_array_append (array, (unsigned char *) "", 1);
	str = (char *) array->data;
	g_byte_array_free (array, FALSE);
	
	return str;
}
Ejemplo n.º 5
0
static GMimeStream *
g_mime_data_wrapper_get_decoded_stream(GMimeDataWrapper * wrapper)
{
    GMimeStream *decoded_stream;
    GMimeFilter *decoder;

    g_mime_stream_reset(wrapper->stream);

    switch (wrapper->encoding) {
    case GMIME_CONTENT_ENCODING_BASE64:
    case GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE:
    case GMIME_CONTENT_ENCODING_UUENCODE:
	decoder = g_mime_filter_basic_new(wrapper->encoding, FALSE);
	decoded_stream = g_mime_stream_filter_new(wrapper->stream);
	g_mime_stream_filter_add(GMIME_STREAM_FILTER(decoded_stream),
				 decoder);
	g_object_unref(decoder);
	break;
    default:
	decoded_stream = wrapper->stream;
	g_object_ref(wrapper->stream);
	break;
    }

    return decoded_stream;
}
Ejemplo n.º 6
0
static void
test_stream_buffer_gets (const char *filename)
{
	GMimeStream *stream, *buffered = NULL;
	int fd;
	
	if ((fd = open (filename, O_RDONLY, 0)) == -1) {
		v(fprintf (stderr, "failed to open %s", filename));
		return;
	}
	
	stream = g_mime_stream_fs_new (fd);
	
	testsuite_check ("GMimeStreamBuffer::block gets");
	try {
		g_mime_stream_reset (stream);
		buffered = g_mime_stream_buffer_new (stream, GMIME_STREAM_BUFFER_BLOCK_READ);
		test_stream_gets (buffered, filename);
		testsuite_check_passed ();
	} catch (ex) {
		testsuite_check_failed ("GMimeStreamBuffer::block gets() failed: %s",
					ex->message);
	} finally {
		g_object_unref (buffered);
	}
	
	testsuite_check ("GMimeStreamBuffer::cache gets");
	try {
		g_mime_stream_reset (stream);
		buffered = g_mime_stream_buffer_new (stream, GMIME_STREAM_BUFFER_CACHE_READ);
		test_stream_gets (buffered, filename);
		testsuite_check_passed ();
	} catch (ex) {
		testsuite_check_failed ("GMimeStreamBuffer::block gets() failed: %s",
					ex->message);
	} finally {
		g_object_unref (buffered);
	}
	
	g_object_unref (stream);
}
Ejemplo n.º 7
0
static GMimeStream *
random_whole_stream (const char *datadir, char **filename)
{
	size_t nwritten, buflen, total = 0, size, i;
	GMimeStream *stream;
	char buf[4096];
	ssize_t n;
	int fd;
	
	/* read between 4k and 14k bytes */
	size = 4096 + (size_t) (10240.0 * (rand () / (RAND_MAX + 1.0)));
	v(fprintf (stdout, "Generating %zu bytes of random data... ", size));
	v(fflush (stdout));
	
	g_mkdir_with_parents (datadir, 0755);
	
	g_snprintf (buf, sizeof (buf), "%s%cstream.%u", datadir, G_DIR_SEPARATOR, getpid ());
	if ((fd = open (buf, O_CREAT | O_TRUNC | O_RDWR, 0666)) == -1) {
		fprintf (stderr, "Error: Cannot create `%s': %s\n", buf, g_strerror (errno));
		exit (EXIT_FAILURE);
	}
	
	*filename = g_strdup (buf);
	
	stream = g_mime_stream_fs_new (fd);
	
	while (total < size) {
		buflen = size - total > sizeof (buf) ? sizeof (buf) : size - total;
		for (i = 0; i < buflen; i++)
			buf[i] = (char) (255 * (rand () / (RAND_MAX + 1.0)));
		
		nwritten = 0;
		do {
			if ((n = g_mime_stream_write (stream, buf + nwritten, buflen - nwritten)) <= 0)
				break;
			nwritten += n;
			total += n;
		} while (nwritten < buflen);
		
		if (nwritten < buflen)
			break;
	}
	
	g_mime_stream_flush (stream);
	g_mime_stream_reset (stream);
	
	v(fputs ("done\n", stdout));
	
	return stream;
}
Ejemplo n.º 8
0
static size_t
gen_random_stream (GMimeStream *stream)
{
	size_t nwritten, buflen, total = 0, size, i;
	char buf[4096];
	ssize_t n;
	
	/* read between 4k and 14k bytes */
	size = 4096 + (size_t) (10240.0 * (rand () / (RAND_MAX + 1.0)));
	v(fprintf (stdout, "Generating %" G_GSIZE_FORMAT " bytes of random data... ", size));
	v(fflush (stdout));
	
	while (total < size) {
		buflen = size - total > sizeof (buf) ? sizeof (buf) : size - total;
		for (i = 0; i < buflen; i++)
			buf[i] = (char) (255 * (rand () / (RAND_MAX + 1.0)));
		
		nwritten = 0;
		do {
			if ((n = g_mime_stream_write (stream, buf + nwritten, buflen - nwritten)) <= 0)
				break;
			nwritten += n;
			total += n;
		} while (nwritten < buflen);
		
		if (nwritten < buflen)
			break;
	}
	
	g_mime_stream_flush (stream);
	g_mime_stream_reset (stream);
	
	v(fputs ("done\n", stdout));

	return size;
}
Ejemplo n.º 9
0
static void
test_openpgp_filter (GMimeFilterOpenPGP *filter, const char *path, GMimeOpenPGPData data_type, gint64 begin, gint64 end)
{
	GMimeStream *filtered, *stream, *expected, *ostream;
	GMimeFilter *dos2unix;
	GMimeOpenPGPData type;
	Exception *ex = NULL;
	GByteArray *buf[2];
	char *filename;
	struct stat st;
	gint64 offset;
	
	ostream = g_mime_stream_mem_new ();
	
	pump_data_through_filter ((GMimeFilter *) filter, path, ostream);
	
	if ((type = g_mime_filter_openpgp_get_data_type (filter)) != data_type) {
		g_object_unref (ostream);
		throw (exception_new ("Incorrect OpenPGP data type detected: %s", openpgp_data_types[type]));
	}
	
	if ((offset = g_mime_filter_openpgp_get_begin_offset (filter)) != begin) {
		g_object_unref (ostream);
		throw (exception_new ("Incorrect begin offset: %ld", (long) offset));
	}
	
	if ((offset = g_mime_filter_openpgp_get_end_offset (filter)) != end) {
		g_object_unref (ostream);
		throw (exception_new ("Incorrect end offset: %ld", (long) offset));
	}
	
	filename = g_strdup_printf ("%s.openpgp-block", path);
	if (stat (filename, &st) == -1) {
		stream = g_mime_stream_fs_open (filename, O_RDWR | O_CREAT, 0644, NULL);
		g_mime_stream_reset (ostream);
		g_mime_stream_write_to_stream (ostream, stream);
		g_mime_stream_flush (stream);
		g_mime_stream_reset (stream);
	} else {
		stream = g_mime_stream_fs_open (filename, O_RDONLY, 0644, NULL);
	}
	g_free (filename);
	
	/* make sure the data is in UNIX format before comparing (might be running tests on Windows) */
	expected = g_mime_stream_mem_new ();
	filtered = g_mime_stream_filter_new (expected);
	dos2unix = g_mime_filter_dos2unix_new (FALSE);
	g_mime_stream_filter_add ((GMimeStreamFilter *) filtered, dos2unix);
	g_object_unref (dos2unix);
	
	g_mime_stream_write_to_stream (stream, filtered);
	g_mime_stream_flush (filtered);
	g_object_unref (filtered);
	g_object_unref (stream);
	
	buf[0] = GMIME_STREAM_MEM (expected)->buffer;
	buf[1] = GMIME_STREAM_MEM (ostream)->buffer;
	
	if (buf[0]->len != buf[1]->len || memcmp (buf[0]->data, buf[1]->data, buf[0]->len) != 0)
		ex = exception_new ("filtered data does not match the expected result");
	
	g_object_unref (expected);
	g_object_unref (ostream);
	
	if (ex != NULL)
		throw (ex);
}
Ejemplo n.º 10
0
static void
test_cat_write (GMimeStream *whole, struct _StreamPart *parts, int bounded)
{
	struct _StreamPart *part = parts;
	GMimeStream *stream, *sub, *cat;
	Exception *ex;
	int fd;
	
	cat = g_mime_stream_cat_new ();
	
	while (part != NULL) {
		d(fprintf (stderr, "adding %s start=%lld, end=%lld...\n",
			   part->filename, part->pstart, part->pend));
		
		if ((fd = open (part->filename, O_CREAT | O_TRUNC | O_WRONLY, 0666)) == -1) {
			ex = exception_new ("could not create `%s': %s", part->filename, g_strerror (errno));
			throw (ex);
		}
		
		stream = g_mime_stream_fs_new_with_bounds (fd, part->pstart, part->pend);
		g_mime_stream_cat_add_source ((GMimeStreamCat *) cat, stream);
		g_object_unref (stream);
		
		part = part->next;
	}
	
	g_mime_stream_reset (whole);
	if (g_mime_stream_write_to_stream (whole, (GMimeStream *) cat) == -1) {
		ex = exception_new ("%s", g_strerror (errno));
		g_object_unref (cat);
		throw (ex);
	}
	
	g_object_unref (cat);
	
	/* now lets check that the content matches */
	d(fprintf (stderr, "checking all part streams have correct data...\n"));
	part = parts;
	while (part != NULL) {
		d(fprintf (stderr, "checking substream %s\n", part->filename));
		if ((fd = open (part->filename, O_RDONLY, 0)) == -1) {
			ex = exception_new ("could not open `%s': %s", part->filename, g_strerror (errno));
			throw (ex);
		}
		
		if (!(sub = g_mime_stream_substream (whole, part->wstart, part->wend))) {
			ex = exception_new ("could not substream original stream");
			close (fd);
			throw (ex);
		}
		
		if (!(stream = g_mime_stream_fs_new_with_bounds (fd, part->pstart, -1))) {
			ex = exception_new ("could not instantiate stream for `%s'", part->filename);
			close (fd);
			throw (ex);
		}
		
		d(fprintf (stderr, "checking substream %s matches...\n", part->filename));
		if (check_streams_match (sub, stream, part->filename, TRUE) == -1) {
			ex = exception_new ("streams did not match");
			g_object_unref (stream);
			g_object_unref (sub);
			throw (ex);
		}
		
		g_object_unref (stream);
		g_object_unref (sub);
		
		part = part->next;
	}
}
Ejemplo n.º 11
0
static ssize_t
write_content (GMimePart *part, GMimeStream *stream)
{
	ssize_t nwritten, total = 0;
	
	if (!part->content)
		return 0;
	
	/* Evil Genius's "slight" optimization: Since GMimeDataWrapper::write_to_stream()
	 * decodes its content stream to the raw format, we can cheat by requesting its
	 * content stream and not doing any encoding on the data if the source and
	 * destination encodings are identical.
	 */
	
	if (part->encoding != g_mime_data_wrapper_get_encoding (part->content)) {
		GMimeStream *filtered_stream;
		const char *filename;
		GMimeFilter *filter;
		
		switch (part->encoding) {
		case GMIME_CONTENT_ENCODING_UUENCODE:
			filename = g_mime_part_get_filename (part);
			nwritten = g_mime_stream_printf (stream, "begin 0644 %s\n",
							 filename ? filename : "unknown");
			if (nwritten == -1)
				return -1;
			
			total += nwritten;
			
			/* fall thru... */
		case GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE:
		case GMIME_CONTENT_ENCODING_BASE64:
			filtered_stream = g_mime_stream_filter_new (stream);
			filter = g_mime_filter_basic_new (part->encoding, TRUE);
			g_mime_stream_filter_add (GMIME_STREAM_FILTER (filtered_stream), filter);
			g_object_unref (filter);
			break;
		default:
			filtered_stream = stream;
			g_object_ref (stream);
			break;
		}
		
		nwritten = g_mime_data_wrapper_write_to_stream (part->content, filtered_stream);
		g_mime_stream_flush (filtered_stream);
		g_object_unref (filtered_stream);
		
		if (nwritten == -1)
			return -1;
		
		total += nwritten;
		
		if (part->encoding == GMIME_CONTENT_ENCODING_UUENCODE) {
			/* FIXME: get rid of this special-case x-uuencode crap */
			nwritten = g_mime_stream_write (stream, "end\n", 4);
			if (nwritten == -1)
				return -1;
			
			total += nwritten;
		}
	} else {
		GMimeStream *content_stream;
		
		content_stream = g_mime_data_wrapper_get_stream (part->content);
		g_mime_stream_reset (content_stream);
		nwritten = g_mime_stream_write_to_stream (content_stream, stream);
		g_mime_stream_reset (content_stream);
		
		if (nwritten == -1)
			return -1;
		
		total += nwritten;
	}
	
	return total;
}
Ejemplo n.º 12
0
int main (int argc, char **argv)
{
#ifdef ENABLE_CRYPTO
	const char *datadir = "data/pgp";
	GMimeStream *istream, *ostream;
	GMimeFilterOpenPGP *filter;
	GMimeCryptoContext *ctx;
	const char *what;
	char *gpg, *key;
	struct stat st;
	int i;
	
	g_mime_init ();
	
	testsuite_init (argc, argv);
	
	if (!(gpg = g_find_program_in_path ("gpg2")))
		if (!(gpg = g_find_program_in_path ("gpg")))
			return EXIT_FAILURE;
	
	if (testsuite_setup_gpghome (gpg) != 0)
		return EXIT_FAILURE;
	
	g_free (gpg);
	
	for (i = 1; i < argc; i++) {
		if (argv[i][0] != '-') {
			datadir = argv[i];
			break;
		}
	}
	
	if (i < argc && (stat (datadir, &st) == -1 || !S_ISDIR (st.st_mode)))
		return 0;
	
	testsuite_start ("GnuPG crypto context");
	
	ctx = g_mime_gpg_context_new ();
	g_mime_crypto_context_set_request_password (ctx, request_passwd);
	
	testsuite_check ("GMimeGpgContext::import");
	try {
		key = g_build_filename (datadir, "gmime.gpg.pub", NULL);
		import_key (ctx, key);
		g_free (key);
		
		key = g_build_filename (datadir, "gmime.gpg.sec", NULL);
		import_key (ctx, key);
		g_free (key);
		
		testsuite_check_passed ();
	} catch (ex) {
		testsuite_check_failed ("GMimeGpgContext::import failed: %s", ex->message);
		return EXIT_FAILURE;
	} finally;
	
	key = g_build_filename (datadir, "gmime.gpg.pub", NULL);
	testsuite_check ("GMimeGpgContext::export");
	try {
		test_export (ctx, key);
		testsuite_check_passed ();
	} catch (ex) {
		testsuite_check_failed ("GMimeGpgContext::export failed: %s", ex->message);
	} finally;
	
	g_free (key);
	
	istream = g_mime_stream_mem_new ();
	ostream = g_mime_stream_mem_new ();
	
	g_mime_stream_write_string (istream, "this is some cleartext\r\n");
	g_mime_stream_reset (istream);
	
	what = "GMimeGpgContext::sign";
	testsuite_check ("%s", what);
	try {
		test_sign (ctx, FALSE, istream, ostream);
		testsuite_check_passed ();
		
		what = "GMimeGpgContext::verify";
		testsuite_check ("%s", what);
		g_mime_stream_reset (istream);
		g_mime_stream_reset (ostream);
		test_verify (ctx, istream, ostream);
		testsuite_check_passed ();
	} catch (ex) {
		testsuite_check_failed ("%s failed: %s", what, ex->message);
	} finally;
	
	g_object_unref (ostream);
	g_mime_stream_reset (istream);
	ostream = g_mime_stream_mem_new ();
	
	what = "GMimeGpgContext::sign (detached)";
	testsuite_check ("%s", what);
	try {
		test_sign (ctx, TRUE, istream, ostream);
		testsuite_check_passed ();
		
		what = "GMimeGpgContext::verify (detached)";
		testsuite_check ("%s", what);
		g_mime_stream_reset (istream);
		g_mime_stream_reset (ostream);
		test_verify_detached (ctx, istream, ostream);
		testsuite_check_passed ();
	} catch (ex) {
		testsuite_check_failed ("%s failed: %s", what, ex->message);
	} finally;
	
	g_object_unref (ostream);
	g_mime_stream_reset (istream);
	ostream = g_mime_stream_mem_new ();
	
	what = "GMimeGpgContext::encrypt";
	testsuite_check ("%s", what);
	try {
		test_encrypt (ctx, FALSE, istream, ostream);
		testsuite_check_passed ();
		
		what = "GMimeGpgContext::decrypt";
		testsuite_check ("%s", what);
		g_mime_stream_reset (istream);
		g_mime_stream_reset (ostream);
		test_decrypt (ctx, FALSE, istream, ostream);
		testsuite_check_passed ();
	} catch (ex) {
		testsuite_check_failed ("%s failed: %s", what, ex->message);
	} finally;
	
	g_object_unref (ostream);
	g_mime_stream_reset (istream);
	ostream = g_mime_stream_mem_new ();
	
	what = "GMimeGpgContext::encrypt+sign";
	testsuite_check ("%s", what);
	try {
		test_encrypt (ctx, TRUE, istream, ostream);
		testsuite_check_passed ();
		
		what = "GMimeGpgContext::decrypt+verify";
		testsuite_check ("%s", what);
		g_mime_stream_reset (istream);
		g_mime_stream_reset (ostream);
		test_decrypt (ctx, TRUE, istream, ostream);
		testsuite_check_passed ();
	} catch (ex) {
		testsuite_check_failed ("%s failed: %s", what, ex->message);
	} finally;
	
	g_object_unref (istream);
	g_object_unref (ostream);
	g_object_unref (ctx);

	filter = (GMimeFilterOpenPGP *) g_mime_filter_openpgp_new ();
	
	what = "GMimeFilterOpenPGP::public key block";
	testsuite_check ("%s", what);
	try {
		key = g_build_filename (datadir, "gmime.gpg.pub", NULL);
		test_openpgp_filter (filter, key, GMIME_OPENPGP_DATA_PUBLIC_KEY, 0, 1720);
		g_free (key);
		
		testsuite_check_passed ();
	} catch (ex) {
		testsuite_check_failed ("%s failed: %s", what, ex->message);
	} finally;
	
	g_mime_filter_reset ((GMimeFilter *) filter);
	
	what = "GMimeFilterOpenPGP::private key block";
	testsuite_check ("%s", what);
	try {
		key = g_build_filename (datadir, "gmime.gpg.sec", NULL);
		test_openpgp_filter (filter, key, GMIME_OPENPGP_DATA_PRIVATE_KEY, 0, 1928);
		g_free (key);
		
		testsuite_check_passed ();
	} catch (ex) {
		testsuite_check_failed ("%s failed: %s", what, ex->message);
	} finally;
	
	g_mime_filter_reset ((GMimeFilter *) filter);
	
	what = "GMimeFilterOpenPGP::signed message block";
	testsuite_check ("%s", what);
	try {
		key = g_build_filename (datadir, "signed-message.txt", NULL);
		test_openpgp_filter (filter, key, GMIME_OPENPGP_DATA_SIGNED, 162, 440);
		g_free (key);
		
		testsuite_check_passed ();
	} catch (ex) {
		testsuite_check_failed ("%s failed: %s", what, ex->message);
	} finally;
	
	g_mime_filter_reset ((GMimeFilter *) filter);
	
	what = "GMimeFilterOpenPGP::encrypted message block";
	testsuite_check ("%s", what);
	try {
		key = g_build_filename (datadir, "encrypted-message.txt", NULL);
		test_openpgp_filter (filter, key, GMIME_OPENPGP_DATA_ENCRYPTED, 165, 1084);
		g_free (key);
		
		testsuite_check_passed ();
	} catch (ex) {
		testsuite_check_failed ("%s failed: %s", what, ex->message);
	} finally;
	
	g_object_unref (filter);
	
	testsuite_end ();
	
	g_mime_shutdown ();
	
	if (testsuite_destroy_gpghome () != 0)
		return EXIT_FAILURE;
	
	return testsuite_exit ();
#else
	fprintf (stderr, "PGP support not enabled in this build.\n");
	return EXIT_SUCCESS;
#endif
}
Ejemplo n.º 13
0
static void
test_export (GMimeCryptoContext *ctx, const char *path)
{
	GMimeStream *istream, *ostream;
	register const char *inptr;
	const char *inbuf, *outbuf;
	size_t inlen, outlen;
	Exception *ex = NULL;
	const char *keys[2];
	GError *err = NULL;
	int fd;
	
	if ((fd = open (path, O_RDONLY, 0)) == -1)
		throw (exception_new ("open() failed: %s", g_strerror (errno)));
	
	ostream = g_mime_stream_fs_new (fd);
	istream = g_mime_stream_mem_new ();
	g_mime_stream_write_to_stream (ostream, istream);
	g_mime_stream_reset (istream);
	g_object_unref (ostream);
	
	keys[0] = "*****@*****.**";
	keys[1] = NULL;
	
	ostream = g_mime_stream_mem_new ();
	
	g_mime_crypto_context_export_keys (ctx, keys, ostream, &err);
	
	if (err != NULL) {
		ex = exception_new ("%s", err->message);
		g_object_unref (istream);
		g_object_unref (ostream);
		g_error_free (err);
		throw (ex);
	}
	
	inbuf = (const char *) GMIME_STREAM_MEM (istream)->buffer->data;
	inlen = GMIME_STREAM_MEM (istream)->buffer->len;
	if ((inptr = strstr (inbuf, "\n\n"))) {
		/* skip past the headers which may have different version numbers */
		inptr += 2;
		inlen -= (inptr - inbuf);
		inbuf = inptr;
	}
	
	outbuf = (const char *) GMIME_STREAM_MEM (ostream)->buffer->data;
	outlen = GMIME_STREAM_MEM (ostream)->buffer->len;
	if ((inptr = strstr (outbuf, "\n\n"))) {
		/* skip past the headers which may have different version numbers */
		inptr += 2;
		outlen -= (inptr - outbuf);
		outbuf = inptr;
	}
	
	if (outlen != inlen || memcmp (outbuf, inbuf, inlen) != 0)
		ex = exception_new ("exported key does not match original key");
	
	g_object_unref (istream);
	g_object_unref (ostream);
	
	if (ex != NULL)
		throw (ex);
}
Ejemplo n.º 14
0
int main (int argc, char **argv)
{
	const char *datadir = "data/mbox";
	char input[256], output[256], *tmp, *p, *q;
	GMimeStream *istream, *ostream, *mstream, *pstream;
	GMimeParser *parser;
	const char *dent;
	const char *path;
	struct stat st;
	GDir *dir;
	int i;
#ifdef ENABLE_MBOX_MATCH
	int fd;

	if (mkdir ("./tmp", 0755) == -1 && errno != EEXIST)
		return 0;
#endif
	
	g_mime_init ();
	
	testsuite_init (argc, argv);
	
	path = datadir;
	for (i = 1; i < argc; i++) {
		if (argv[i][0] != '-') {
			path = argv[i];
			break;
		}
	}
	
	testsuite_start ("Mbox parser");
	
	if (stat (path, &st) == -1)
		goto exit;
	
	if (S_ISDIR (st.st_mode)) {
		/* automated testsuite */
		p = g_stpcpy (input, path);
		*p++ = G_DIR_SEPARATOR;
		p = g_stpcpy (p, "input");
		
		if (!(dir = g_dir_open (input, 0, NULL)))
			goto exit;
		
		*p++ = G_DIR_SEPARATOR;
		*p = '\0';
		
		q = g_stpcpy (output, path);
		*q++ = G_DIR_SEPARATOR;
		q = g_stpcpy (q, "output");
		*q++ = G_DIR_SEPARATOR;
		*q = '\0';
		
		while ((dent = g_dir_read_name (dir))) {
			if (!g_str_has_suffix (dent, ".mbox"))
				continue;
			
			strcpy (p, dent);
			strcpy (q, dent);
			
			tmp = NULL;
			parser = NULL;
			istream = NULL;
			ostream = NULL;
			mstream = NULL;
			pstream = NULL;
			
			testsuite_check ("%s", dent);
			try {
				if (!(istream = g_mime_stream_fs_open (input, O_RDONLY, 0, NULL))) {
					throw (exception_new ("could not open `%s': %s",
							      input, g_strerror (errno)));
				}
				
				if (!(ostream = g_mime_stream_fs_open (output, O_RDONLY, 0, NULL))) {
					throw (exception_new ("could not open `%s': %s",
							      output, g_strerror (errno)));
				}
				
#ifdef ENABLE_MBOX_MATCH
				tmp = g_strdup_printf ("./tmp/%s", dent);
				if ((fd = open (tmp, O_CREAT | O_RDWR | O_TRUNC, 0644)) == -1) {
					throw (exception_new ("could not open `%s': %s",
							      tmp, g_strerror (errno)));
				}
				
				mstream = g_mime_stream_fs_new (fd);
#endif
				
				parser = g_mime_parser_new_with_stream (istream);
				g_mime_parser_set_persist_stream (parser, TRUE);
				g_mime_parser_set_format (parser, GMIME_FORMAT_MBOX);
				
				if (!g_mime_parser_get_persist_stream (parser))
					throw (exception_new ("persist stream check failed"));
				
				if (g_mime_parser_get_format (parser) != GMIME_FORMAT_MBOX)
					throw (exception_new ("format check failed"));
				
				if (strstr (dent, "content-length") != NULL) {
					g_mime_parser_set_respect_content_length (parser, TRUE);
					
					if (!g_mime_parser_get_respect_content_length (parser))
						throw (exception_new ("respect content-length check failed"));
				} else {
					g_mime_parser_set_respect_content_length (parser, FALSE);
					
					if (g_mime_parser_get_respect_content_length (parser))
						throw (exception_new ("respect content-length check failed"));
				}
				
				g_mime_parser_set_header_regex (parser, "^X-Evolution", xevcb, NULL);
				
				pstream = g_mime_stream_mem_new ();
				test_parser (parser, mstream, pstream);
				
#ifdef ENABLE_MBOX_MATCH
				g_mime_stream_flush (mstream);
				g_mime_stream_reset (istream);
				g_mime_stream_reset (mstream);
				if (!streams_match (istream, mstream))
					throw (exception_new ("mboxes do not match for `%s'", dent));
#endif
				
				g_mime_stream_reset (ostream);
				g_mime_stream_reset (pstream);
				if (!streams_match (ostream, pstream))
					throw (exception_new ("summaries do not match for `%s'", dent));
				
				testsuite_check_passed ();
				
#ifdef ENABLE_MBOX_MATCH
				unlink (tmp);
#endif
			} catch (ex) {
				if (parser != NULL)
					testsuite_check_failed ("%s: %s", dent, ex->message);
				else
					testsuite_check_warn ("%s: %s", dent, ex->message);
			} finally;
			
			if (mstream != NULL)
				g_object_unref (mstream);
			
			if (pstream != NULL)
				g_object_unref (pstream);
			
			if (istream != NULL)
				g_object_unref (istream);
			
			if (ostream != NULL)
				g_object_unref (ostream);
			
			if (parser != NULL)
				g_object_unref (parser);
			
			g_free (tmp);
		}
		
		g_dir_close (dir);
	} else if (S_ISREG (st.st_mode)) {
		/* manually run test on a single file */
		if (!(istream = g_mime_stream_fs_open (path, O_RDONLY, 0, NULL)))
			goto exit;
		
		parser = g_mime_parser_new_with_stream (istream);
		g_mime_parser_set_format (parser, GMIME_FORMAT_MBOX);
		
#ifdef ENABLE_MBOX_MATCH
		tmp = g_strdup ("./tmp/mbox-test.XXXXXX");
		if ((fd = g_mkstemp (tmp)) == -1) {
			g_object_unref (istream);
			g_object_unref (parser);
			g_free (tmp);
			goto exit;
		}
		
		mstream = g_mime_stream_fs_new (fd);
#else
		mstream = NULL;
#endif
		
		ostream = g_mime_stream_file_new (stdout);
		g_mime_stream_file_set_owner ((GMimeStreamFile *) ostream, FALSE);
		
		testsuite_check ("user-input mbox: `%s'", path);
		try {
			test_parser (parser, mstream, ostream);
			
#ifdef ENABLE_MBOX_MATCH
			g_mime_stream_reset (istream);
			g_mime_stream_reset (mstream);
			if (!streams_match (istream, mstream))
				throw (exception_new ("`%s' does not match `%s'", tmp, path));
			
			unlink (tmp);
#endif
			
			testsuite_check_passed ();
		} catch (ex) {
			testsuite_check_failed ("user-input mbox `%s': %s", path, ex->message);
		} finally;
		
		g_object_unref (istream);
		g_object_unref (ostream);
		g_object_unref (parser);
		
#ifdef ENABLE_MBOX_MATCH
		g_object_unref (mstream);
		g_free (tmp);
#endif
	} else {
		goto exit;
	}
	
 exit:
	
#ifdef ENABLE_MBOX_MATCH
	//if ((dir = g_dir_open ("./tmp", 0, NULL))) {
	//	p = g_stpcpy (input, "./tmp");
	//	*p++ = G_DIR_SEPARATOR;
	//	
	//	while ((dent = g_dir_read_name (dir))) {
	//		strcpy (p, dent);
	//		unlink (input);
	//	}
	//	
	//	g_dir_close (dir);
	//}
	
	//rmdir ("./tmp");
#endif
	
	testsuite_end ();
	
	g_mime_shutdown ();
	
	return testsuite_exit ();
}
Ejemplo n.º 15
0
gboolean
g_mime_gpgme_mps_sign(GMimeMultipartSigned * mps, GMimeObject * content,
		      const gchar * userid, gpgme_protocol_t protocol,
		      GtkWindow * parent, GError ** err)
{
    GMimeStream *stream;
    GMimeStream *filtered;
    GMimeStream *sigstream;
    GMimeFilter *filter;
    GMimeContentType *content_type;
    GMimeDataWrapper *wrapper;
    GMimeParser *parser;
    GMimePart *signature;
    gchar *micalg;
    const gchar *proto_type;
    const gchar *sig_subtype;
    gpgme_hash_algo_t hash_algo;

    g_return_val_if_fail(GMIME_IS_MULTIPART_SIGNED(mps), FALSE);
    g_return_val_if_fail(GMIME_IS_OBJECT(content), FALSE);

    /* Prepare all the parts for signing... */
    sign_prepare(content);

    /* get the cleartext */
    stream = g_mime_stream_mem_new();
    filtered = g_mime_stream_filter_new(stream);

    /* Note: see rfc3156, section 3 - second note */
    filter = g_mime_filter_from_new(GMIME_FILTER_FROM_MODE_ARMOR);
    g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered), filter);
    g_object_unref(filter);

    /* Note: see rfc3156, section 5.4 (this is the main difference between rfc2015 and rfc3156) */
    filter = g_mime_filter_strip_new();
    g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered), filter);
    g_object_unref(filter);

    g_mime_object_write_to_stream(content, filtered);
    g_mime_stream_flush(filtered);
    g_object_unref(filtered);
    g_mime_stream_reset(stream);

    /* Note: see rfc2015 or rfc3156, section 5.1 */
    filtered = g_mime_stream_filter_new(stream);
    filter = g_mime_filter_crlf_new(TRUE, FALSE);
    g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered), filter);
    g_object_unref(filter);

    /* construct the signature stream */
    sigstream = g_mime_stream_mem_new();

    /* sign the content stream */
    hash_algo =
	libbalsa_gpgme_sign(userid, filtered, sigstream, protocol, FALSE,
			    parent, err);
    g_object_unref(filtered);
    if (hash_algo == GPGME_MD_NONE) {
	g_object_unref(sigstream);
	g_object_unref(stream);
	return FALSE;
    }

    g_mime_stream_reset(sigstream);
    g_mime_stream_reset(stream);

    /* set the multipart/signed protocol and micalg */
    content_type = g_mime_object_get_content_type(GMIME_OBJECT(mps));
    if (protocol == GPGME_PROTOCOL_OpenPGP) {
	micalg =
	    g_strdup_printf("PGP-%s", gpgme_hash_algo_name(hash_algo));
	proto_type = "application/pgp-signature";
	sig_subtype = "pgp-signature";
    } else {
	micalg = g_strdup(gpgme_hash_algo_name(hash_algo));
	proto_type = "application/pkcs7-signature";
	sig_subtype = "pkcs7-signature";
    }
    g_mime_content_type_set_parameter(content_type, "micalg", micalg);
    g_free(micalg);
    g_mime_content_type_set_parameter(content_type, "protocol", proto_type);
    g_mime_multipart_set_boundary(GMIME_MULTIPART(mps), NULL);

    /* construct the content part */
    parser = g_mime_parser_new_with_stream(stream);
    content = g_mime_parser_construct_part(parser);
    g_object_unref(stream);
    g_object_unref(parser);

    /* construct the signature part */
    signature = g_mime_part_new_with_type("application", sig_subtype);

    wrapper = g_mime_data_wrapper_new();
    g_mime_data_wrapper_set_stream(wrapper, sigstream);
    g_mime_part_set_content_object(signature, wrapper);
    g_object_unref(sigstream);
    g_object_unref(wrapper);

    /* FIXME: temporary hack, this info should probably be set in
     * the CipherContext class - maybe ::sign can take/output a
     * GMimePart instead. */
    if (protocol == GPGME_PROTOCOL_CMS) {
	g_mime_part_set_content_encoding(signature,
					 GMIME_CONTENT_ENCODING_BASE64);
	g_mime_part_set_filename(signature, "smime.p7m");
    }

    /* save the content and signature parts */
    /* FIXME: make sure there aren't any other parts?? */
    g_mime_multipart_add(GMIME_MULTIPART(mps), content);
    g_mime_multipart_add(GMIME_MULTIPART(mps), (GMimeObject *) signature);
    g_object_unref(signature);
    g_object_unref(content);

    return TRUE;
}
Ejemplo n.º 16
0
GMimeObject *
g_mime_gpgme_mpe_decrypt(GMimeMultipartEncrypted * mpe,
			 GMimeGpgmeSigstat ** signature,
			 GtkWindow * parent, GError ** err)
{
    GMimeObject *decrypted, *version, *encrypted;
    GMimeStream *stream, *ciphertext;
    GMimeStream *filtered_stream;
    GMimeContentType *mime_type;
    GMimeGpgmeSigstat *sigstat;
    GMimeDataWrapper *wrapper;
    GMimeFilter *crlf_filter;
    GMimeParser *parser;
    const char *protocol;
    char *content_type;

    g_return_val_if_fail(GMIME_IS_MULTIPART_ENCRYPTED(mpe), NULL);

    if (signature && *signature) {
	g_object_unref(G_OBJECT(*signature));
	*signature = NULL;
    }

    protocol =
	g_mime_object_get_content_type_parameter(GMIME_OBJECT(mpe),
						 "protocol");

    /* make sure the protocol is present and matches the cipher encrypt protocol */
    if (!protocol
	|| g_ascii_strcasecmp("application/pgp-encrypted",
			      protocol) != 0) {
	g_set_error(err, GMIME_ERROR, GMIME_ERROR_PROTOCOL_ERROR,
		    _
		    ("Cannot decrypt multipart/encrypted part: unsupported encryption protocol “%s”."),
		    protocol ? protocol : _("(none)"));
	return NULL;
    }

    version =
	g_mime_multipart_get_part(GMIME_MULTIPART(mpe),
				  GMIME_MULTIPART_ENCRYPTED_VERSION);

    /* make sure the protocol matches the version part's content-type */
    content_type = g_mime_content_type_to_string(version->content_type);
    if (g_ascii_strcasecmp(content_type, protocol) != 0) {
	g_set_error(err, GMIME_ERROR, GMIME_ERROR_PROTOCOL_ERROR, "%s",
		    _
		    ("Cannot decrypt multipart/encrypted part: content-type does not match protocol."));
	g_free(content_type);
	return NULL;
    }
    g_free(content_type);

    /* get the encrypted part and check that it is of type application/octet-stream */
    encrypted =
	g_mime_multipart_get_part(GMIME_MULTIPART(mpe),
				  GMIME_MULTIPART_ENCRYPTED_CONTENT);
    mime_type = g_mime_object_get_content_type(encrypted);
    if (!g_mime_content_type_is_type
	(mime_type, "application", "octet-stream")) {
	g_set_error(err, GMIME_ERROR, GMIME_ERROR_PROTOCOL_ERROR, "%s",
		    _
		    ("Cannot decrypt multipart/encrypted part: unexpected content type"));
	return NULL;
    }

    /* get the ciphertext stream */
    wrapper = g_mime_part_get_content_object(GMIME_PART(encrypted));
    ciphertext = g_mime_data_wrapper_get_decoded_stream(wrapper);
    g_mime_stream_reset(ciphertext);

    stream = g_mime_stream_mem_new();
    filtered_stream = g_mime_stream_filter_new(stream);
    crlf_filter = g_mime_filter_crlf_new(FALSE, FALSE);
    g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_stream),
			     crlf_filter);
    g_object_unref(crlf_filter);

    /* get the cleartext */
    sigstat =
	libbalsa_gpgme_decrypt(ciphertext, filtered_stream,
			       GPGME_PROTOCOL_OpenPGP, parent, err);
    if (!sigstat) {
	g_object_unref(filtered_stream);
	g_object_unref(ciphertext);
	g_object_unref(stream);
	return NULL;
    }

    g_mime_stream_flush(filtered_stream);
    g_object_unref(filtered_stream);
    g_object_unref(ciphertext);

    g_mime_stream_reset(stream);
    parser = g_mime_parser_new();
    g_mime_parser_init_with_stream(parser, stream);
    g_object_unref(stream);

    decrypted = g_mime_parser_construct_part(parser);
    g_object_unref(parser);

    if (!decrypted) {
	g_set_error(err, GMIME_ERROR, GMIME_ERROR_PARSE_ERROR, "%s",
		    _
		    ("Cannot decrypt multipart/encrypted part: failed to parse decrypted content"));
	g_object_unref(G_OBJECT(sigstat));
	return NULL;
    }


    /* cache the decrypted part */
    if (signature) {
	if (sigstat->status != GPG_ERR_NOT_SIGNED)
	    *signature = sigstat;
	else
	    g_object_unref(G_OBJECT(sigstat));
    }

    return decrypted;
}
Ejemplo n.º 17
0
gboolean
g_mime_gpgme_mpe_encrypt(GMimeMultipartEncrypted * mpe,
			 GMimeObject * content, GPtrArray * recipients,
			 gboolean trust_all, GtkWindow * parent,
			 GError ** err)
{
    GMimeStream *filtered_stream;
    GMimeStream *ciphertext;
    GMimeStream *stream;
    GMimePart *version_part;
    GMimePart *encrypted_part;
    GMimeDataWrapper *wrapper;
    GMimeFilter *crlf_filter;

    g_return_val_if_fail(GMIME_IS_MULTIPART_ENCRYPTED(mpe), FALSE);
    g_return_val_if_fail(GMIME_IS_OBJECT(content), FALSE);

    /* get the cleartext */
    stream = g_mime_stream_mem_new();
    filtered_stream = g_mime_stream_filter_new(stream);

    crlf_filter = g_mime_filter_crlf_new(TRUE, FALSE);
    g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_stream),
			     crlf_filter);
    g_object_unref(crlf_filter);

    g_mime_object_write_to_stream(content, filtered_stream);
    g_mime_stream_flush(filtered_stream);
    g_object_unref(filtered_stream);

    /* reset the content stream */
    g_mime_stream_reset(stream);

    /* encrypt the content stream */
    ciphertext = g_mime_stream_mem_new();
    if (!libbalsa_gpgme_encrypt
	(recipients, NULL, stream, ciphertext, GPGME_PROTOCOL_OpenPGP,
	 FALSE, trust_all, parent, err)) {
	g_object_unref(ciphertext);
	g_object_unref(stream);
	return FALSE;
    }

    g_object_unref(stream);
    g_mime_stream_reset(ciphertext);

    /* construct the version part */
    version_part =
	g_mime_part_new_with_type("application", "pgp-encrypted");
    g_mime_part_set_content_encoding(version_part,
				     GMIME_CONTENT_ENCODING_7BIT);
    stream =
	g_mime_stream_mem_new_with_buffer("Version: 1\n",
					  strlen("Version: 1\n"));
    wrapper =
	g_mime_data_wrapper_new_with_stream(stream,
					    GMIME_CONTENT_ENCODING_7BIT);
    g_mime_part_set_content_object(version_part, wrapper);
    g_object_unref(wrapper);
    g_object_unref(stream);

    /* construct the encrypted mime part */
    encrypted_part =
	g_mime_part_new_with_type("application", "octet-stream");
    g_mime_part_set_content_encoding(encrypted_part,
				     GMIME_CONTENT_ENCODING_7BIT);
    wrapper =
	g_mime_data_wrapper_new_with_stream(ciphertext,
					    GMIME_CONTENT_ENCODING_7BIT);
    g_mime_part_set_content_object(encrypted_part, wrapper);
    g_object_unref(ciphertext);
    g_object_unref(wrapper);

    /* save the version and encrypted parts */
    /* FIXME: make sure there aren't any other parts?? */
    g_mime_multipart_add(GMIME_MULTIPART(mpe), GMIME_OBJECT(version_part));
    g_mime_multipart_add(GMIME_MULTIPART(mpe),
			 GMIME_OBJECT(encrypted_part));
    g_object_unref(encrypted_part);
    g_object_unref(version_part);

    /* set the content-type params for this multipart/encrypted part */
    g_mime_object_set_content_type_parameter(GMIME_OBJECT(mpe), "protocol",
					     "application/pgp-encrypted");
    g_mime_multipart_set_boundary(GMIME_MULTIPART(mpe), NULL);

    return TRUE;
}
Ejemplo n.º 18
0
GMimeGpgmeSigstat *
g_mime_gpgme_mps_verify(GMimeMultipartSigned * mps, GError ** error)
{
    const gchar *protocol;
    gpgme_protocol_t crypto_prot;
    gchar *content_type;
    GMimeObject *content;
    GMimeObject *signature;
    GMimeStream *stream;
    GMimeStream *filtered_stream;
    GMimeFilter *crlf_filter;
    GMimeDataWrapper *wrapper;
    GMimeStream *sigstream;
    GMimeGpgmeSigstat *result;

    g_return_val_if_fail(GMIME_IS_MULTIPART_SIGNED(mps), NULL);

    if (g_mime_multipart_get_count(GMIME_MULTIPART(mps)) < 2) {
	g_set_error(error, GMIME_ERROR, GMIME_ERROR_PARSE_ERROR, "%s",
		    _
		    ("Cannot verify multipart/signed part due to missing subparts."));
	return NULL;
    }

    /* grab the protocol so we can configure the GpgME context */
    protocol =
	g_mime_object_get_content_type_parameter(GMIME_OBJECT(mps),
						 "protocol");
    if (protocol) {
	if (g_ascii_strcasecmp("application/pgp-signature", protocol) == 0)
	    crypto_prot = GPGME_PROTOCOL_OpenPGP;
	else if (g_ascii_strcasecmp
		 ("application/pkcs7-signature", protocol) == 0
		 || g_ascii_strcasecmp("application/x-pkcs7-signature",
				       protocol) == 0)
	    crypto_prot = GPGME_PROTOCOL_CMS;
	else
	    crypto_prot = GPGME_PROTOCOL_UNKNOWN;
    } else
	crypto_prot = GPGME_PROTOCOL_UNKNOWN;

    /* eject on unknown protocols */
    if (crypto_prot == GPGME_PROTOCOL_UNKNOWN) {
	g_set_error(error, GPGME_ERROR_QUARK, GPG_ERR_INV_VALUE,
		    _("unsupported protocol “%s”"), protocol);
	return NULL;
    }

    signature =
	g_mime_multipart_get_part(GMIME_MULTIPART(mps),
				  GMIME_MULTIPART_SIGNED_SIGNATURE);

    /* make sure the protocol matches the signature content-type */
    content_type = g_mime_content_type_to_string(signature->content_type);
    if (g_ascii_strcasecmp(content_type, protocol) != 0) {
	g_set_error(error, GMIME_ERROR, GMIME_ERROR_PARSE_ERROR, "%s",
		    _
		    ("Cannot verify multipart/signed part: signature content-type does not match protocol."));
	g_free(content_type);
	return NULL;
    }
    g_free(content_type);

    content =
	g_mime_multipart_get_part(GMIME_MULTIPART(mps),
				  GMIME_MULTIPART_SIGNED_CONTENT);

    /* get the content stream */
    stream = g_mime_stream_mem_new();
    filtered_stream = g_mime_stream_filter_new(stream);

    /* Note: see rfc2015 or rfc3156, section 5.1 */
    crlf_filter = g_mime_filter_crlf_new(TRUE, FALSE);
    g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_stream),
			     crlf_filter);
    g_object_unref(crlf_filter);

    g_mime_object_write_to_stream(content, filtered_stream);
    g_mime_stream_flush(filtered_stream);
    g_object_unref(filtered_stream);
    g_mime_stream_reset(stream);

    /* get the signature stream */
    wrapper = g_mime_part_get_content_object(GMIME_PART(signature));

    /* a s/mime signature is always encoded, a pgp signature shouldn't,
     * but there exist implementations which encode it... */
	sigstream = g_mime_stream_mem_new();
	g_mime_data_wrapper_write_to_stream(wrapper, sigstream);
    g_mime_stream_reset(sigstream);

    /* verify the signature */
    result =
	libbalsa_gpgme_verify(stream, sigstream, crypto_prot, FALSE,
			      error);
    g_object_unref(stream);
    g_object_unref(sigstream);

    return result;
}