Exemplo n.º 1
0
QNetworkReply*
MailNetworkManager::makeReply(const QNetworkRequest& req, GMimeObject* content)
{
    auto ctype = g_mime_object_get_content_type(content);
    char *mtstr = g_mime_content_type_to_string(ctype);
    QString mediaType = QString::fromUtf8(mtstr);
    g_free(mtstr);
    const char *enc = g_mime_content_type_get_parameter(ctype, "charset");
    if (enc != NULL) {
        mediaType += "; charset=\"";
        mediaType += QString::fromUtf8(enc);
        mediaType += "\"";
    }

    g_return_val_if_fail(GMIME_IS_PART(content), NULL);

    GMimeStream *stream = g_mime_stream_mem_new();
    GMimeDataWrapper *wrapper = g_mime_part_get_content_object(GMIME_PART(content));
    g_mime_data_wrapper_write_to_stream(wrapper, stream);
    GByteArray *bytes = g_mime_stream_mem_get_byte_array(GMIME_STREAM_MEM(stream));

    QByteArray buffer((const char*) bytes->data, bytes->len);
    g_object_unref(stream);

    qDebug() <<"making reply of length" <<buffer.size() <<"and type" <<mediaType;

    return StaticHTTPReply::ok(req, buffer, mediaType);
}
/**
 * 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;
}
Exemplo n.º 3
0
static void
test_decrypt (GMimeCryptoContext *ctx, gboolean sign, GMimeStream *cleartext, GMimeStream *ciphertext)
{
	GMimeSignatureList *signatures;
	GMimeSignatureStatus status;
	GMimeDecryptResult *result;
	Exception *ex = NULL;
	GMimeStream *stream;
	GError *err = NULL;
	GByteArray *buf[2];
	
	stream = g_mime_stream_mem_new ();
	
	if (!(result = g_mime_crypto_context_decrypt (ctx, 0, NULL, ciphertext, stream, &err))) {
		g_object_unref (stream);
		ex = exception_new ("%s", err->message);
		g_error_free (err);
		throw (ex);
	}
	
	signatures = g_mime_decrypt_result_get_signatures (result);
	
	if (sign) {
		if (signatures != NULL) {
			status = get_sig_status (signatures);
			
			if ((status & GMIME_SIGNATURE_STATUS_RED) != 0)
				ex = exception_new ("expected GOOD signature");
		} else {
			ex = exception_new ("Failed to get signatures");
		}
	} else {
		if (signatures != NULL)
			ex = exception_new ("unexpected signature");
	}
	
	/* Did not ask for session_key -- it should not be present.
	   We test asking for session_key over in test-pgpmime.c */
	if (ex == NULL && result->session_key)
		ex = exception_new ("got session_key when not requested");
	
	g_object_unref (result);
	
	if (ex != NULL) {
		g_object_unref (stream);
		throw (ex);
	}
	
	buf[0] = g_mime_stream_mem_get_byte_array ((GMimeStreamMem *) cleartext);
	buf[1] = g_mime_stream_mem_get_byte_array ((GMimeStreamMem *) stream);
	
	if (buf[0]->len != buf[1]->len || memcmp (buf[0]->data, buf[1]->data, buf[0]->len) != 0)
		ex = exception_new ("decrypted data does not match original cleartext");
	
	g_object_unref (stream);
	
	if (ex != NULL)
		throw (ex);
}
Exemplo n.º 4
0
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);
}
Exemplo n.º 5
0
static void
test_verify (GMimeCryptoContext *ctx, GMimeStream *cleartext, GMimeStream *ciphertext)
{
	GMimeSignatureList *signatures;
	GMimeSignatureStatus status;
	Exception *ex = NULL;
	GMimeStream *stream;
	GError *err = NULL;
	GByteArray *buf[2];
	
	stream = g_mime_stream_mem_new ();
	
	signatures = g_mime_crypto_context_verify (ctx, 0, ciphertext, NULL, stream, &err);
	
	if (signatures == NULL) {
		ex = exception_new ("%s", err->message);
		g_object_unref (stream);
		g_error_free (err);
		throw (ex);
	}
	
	status = get_sig_status (signatures);
	
	if ((status & GMIME_SIGNATURE_STATUS_RED) != 0) {
		g_object_unref (signatures);
		g_object_unref (stream);
		
		throw (exception_new ("signature BAD"));
	}
	
	g_object_unref (signatures);
	
	buf[0] = GMIME_STREAM_MEM (cleartext)->buffer;
	buf[1] = GMIME_STREAM_MEM (stream)->buffer;
	
	if (buf[0]->len != buf[1]->len || memcmp (buf[0]->data, buf[1]->data, buf[0]->len) != 0)
		ex = exception_new ("extracted data does not match original cleartext");
	
	g_object_unref (stream);
	
	if (ex != NULL)
		throw (ex);
}
Exemplo n.º 6
0
static void
format_part_content_json (GMimeObject *part)
{
    GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
    GMimeStream *stream_memory = g_mime_stream_mem_new ();
    const char *cid = g_mime_object_get_content_id (part);
    void *ctx = talloc_new (NULL);
    GByteArray *part_content;

    printf (", \"content-type\": %s",
	    json_quote_str (ctx, g_mime_content_type_to_string (content_type)));

    if (cid != NULL)
	    printf(", \"content-id\": %s", json_quote_str (ctx, cid));

    if (GMIME_IS_PART (part))
    {
	const char *filename = g_mime_part_get_filename (GMIME_PART (part));
	if (filename)
	    printf (", \"filename\": %s", json_quote_str (ctx, filename));
    }

    if (g_mime_content_type_is_type (content_type, "text", "*") &&
	!g_mime_content_type_is_type (content_type, "text", "html"))
    {
	show_text_part_content (part, stream_memory);
	part_content = g_mime_stream_mem_get_byte_array (GMIME_STREAM_MEM (stream_memory));

	printf (", \"content\": %s", json_quote_chararray (ctx, (char *) part_content->data, part_content->len));
    }
    else if (g_mime_content_type_is_type (content_type, "multipart", "*"))
    {
	printf (", \"content\": [");
    }
    else if (g_mime_content_type_is_type (content_type, "message", "rfc822"))
    {
	printf (", \"content\": [{");
    }

    talloc_free (ctx);
    if (stream_memory)
	g_object_unref (stream_memory);
}
Exemplo n.º 7
0
static void
test_stream_mem (const char *filename)
{
	/* Note: this also tests g_mime_stream_write_to_stream */
	GMimeStream *stream, *fstream;
	int fd;
	
	if ((fd = open (filename, O_RDONLY, 0)) == -1) {
		v(fprintf (stderr, "failed to open %s: %s\n", filename, g_strerror (errno)));
		return;
	}
	
	testsuite_start ("GMimeStreamMem");
	
	fstream = g_mime_stream_fs_new (fd);
	stream = g_mime_stream_mem_new ();
	
	testsuite_check ("GMimeStreamMem::read()");
	try {
		if (g_mime_stream_write_to_stream (fstream, stream) == -1)
			throw (exception_new ("g_mime_stream_write_to_stream() failed"));
		
		if (g_mime_stream_length (stream) != g_mime_stream_length (fstream))
			throw (exception_new ("stream lengths didn't match"));
		
		test_stream_read (stream, filename);
		
		testsuite_check_passed ();
	} catch (ex) {
		testsuite_check_failed ("GMimeStreamMem::read() failed: %s",
					ex->message);
	} finally;
	
	g_object_unref (fstream);
	g_object_unref (stream);
	
	testsuite_end ();
}
Exemplo n.º 8
0
static void
lsv_escape_change_state(GSimpleAction * action,
                        GVariant      * state,
                        gpointer        user_data)
{
    LibBalsaSourceViewerInfo *lsvi =
        g_object_get_data(G_OBJECT(user_data), "lsvi");
    LibBalsaMessage *msg = lsvi->msg;
    GMimeStream *msg_stream;
    GMimeStream *mem_stream;
    char *raw_message;

    if (!msg->mailbox) {
	libbalsa_information(LIBBALSA_INFORMATION_WARNING,
			     _("Mailbox closed"));
	return;
    }
    msg_stream = libbalsa_mailbox_get_message_stream(msg->mailbox, msg->msgno,
						     TRUE);
    if (msg_stream == NULL)
	return;

    mem_stream = g_mime_stream_mem_new();
    libbalsa_mailbox_lock_store(msg->mailbox);
    g_mime_stream_write_to_stream(msg_stream, mem_stream);
    libbalsa_mailbox_unlock_store(msg->mailbox);
    g_mime_stream_write(mem_stream, "", 1); /* close string */
    raw_message = (char *) GMIME_STREAM_MEM(mem_stream)->buffer->data;

    *(lsvi->escape_specials) = g_variant_get_boolean(state);
    lsv_show_message(raw_message, lsvi, *(lsvi->escape_specials));

    g_object_unref(msg_stream);
    g_object_unref(mem_stream);

    g_simple_action_set_state(action, state);
}
Exemplo n.º 9
0
void
format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first)
{
    /* Any changes to the JSON format should be reflected in the file
     * devel/schemata. */

    if (node->envelope_file) {
        printf ("{");
        format_message_json (ctx, node->envelope_file);

        printf ("\"headers\": ");
        format_headers_json (ctx, GMIME_MESSAGE (node->part), FALSE);

        printf (", \"body\": [");
        format_part_json (ctx, mime_node_child (node, 0), first);

        printf ("]}");
        return;
    }

    void *local = talloc_new (ctx);
    /* The disposition and content-type metadata are associated with
     * the envelope for message parts */
    GMimeObject *meta = node->envelope_part ?
                        GMIME_OBJECT (node->envelope_part) : node->part;
    GMimeContentType *content_type = g_mime_object_get_content_type (meta);
    const char *cid = g_mime_object_get_content_id (meta);
    const char *filename = GMIME_IS_PART (node->part) ?
                           g_mime_part_get_filename (GMIME_PART (node->part)) : NULL;
    const char *terminator = "";
    int i;

    if (!first)
        printf (", ");

    printf ("{\"id\": %d", node->part_num);

    if (node->decrypt_attempted)
        printf (", \"encstatus\": [{\"status\": \"%s\"}]",
                node->decrypt_success ? "good" : "bad");

    if (node->verify_attempted) {
        printf (", \"sigstatus\": ");
        format_part_sigstatus_json (node);
    }

    printf (", \"content-type\": %s",
            json_quote_str (local, g_mime_content_type_to_string (content_type)));

    if (cid)
        printf (", \"content-id\": %s", json_quote_str (local, cid));

    if (filename)
        printf (", \"filename\": %s", json_quote_str (local, filename));

    if (GMIME_IS_PART (node->part)) {
        /* For non-HTML text parts, we include the content in the
         * JSON. Since JSON must be Unicode, we handle charset
         * decoding here and do not report a charset to the caller.
         * For text/html parts, we do not include the content. If a
         * caller is interested in text/html parts, it should retrieve
         * them separately and they will not be decoded. Since this
         * makes charset decoding the responsibility on the caller, we
         * report the charset for text/html parts.
         */
        if (g_mime_content_type_is_type (content_type, "text", "html")) {
            const char *content_charset = g_mime_object_get_content_type_parameter (meta, "charset");

            if (content_charset != NULL)
                printf (", \"content-charset\": %s", json_quote_str (local, content_charset));
        } else if (g_mime_content_type_is_type (content_type, "text", "*")) {
            GMimeStream *stream_memory = g_mime_stream_mem_new ();
            GByteArray *part_content;
            show_text_part_content (node->part, stream_memory, 0);
            part_content = g_mime_stream_mem_get_byte_array (GMIME_STREAM_MEM (stream_memory));

            printf (", \"content\": %s", json_quote_chararray (local, (char *) part_content->data, part_content->len));
            g_object_unref (stream_memory);
        }
    } else if (GMIME_IS_MULTIPART (node->part)) {
        printf (", \"content\": [");
        terminator = "]";
    } else if (GMIME_IS_MESSAGE (node->part)) {
        printf (", \"content\": [{");
        printf ("\"headers\": ");
        format_headers_json (local, GMIME_MESSAGE (node->part), FALSE);

        printf (", \"body\": [");
        terminator = "]}]";
    }

    talloc_free (local);

    for (i = 0; i < node->nchildren; i++)
        format_part_json (ctx, mime_node_child (node, i), i == 0);

    printf ("%s}", terminator);
}
Exemplo n.º 10
0
void
format_part_sprinter (const void *ctx, sprinter_t *sp, mime_node_t *node,
		      notmuch_bool_t first, notmuch_bool_t output_body,
		      notmuch_bool_t include_html)
{
    /* Any changes to the JSON or S-Expression format should be
     * reflected in the file devel/schemata. */

    if (node->envelope_file) {
	sp->begin_map (sp);
	format_message_sprinter (sp, node->envelope_file);

	sp->map_key (sp, "headers");
	format_headers_sprinter (sp, GMIME_MESSAGE (node->part), FALSE);

	if (output_body) {
	    sp->map_key (sp, "body");
	    sp->begin_list (sp);
	    format_part_sprinter (ctx, sp, mime_node_child (node, 0), first, TRUE, include_html);
	    sp->end (sp);
	}
	sp->end (sp);
	return;
    }

    /* The disposition and content-type metadata are associated with
     * the envelope for message parts */
    GMimeObject *meta = node->envelope_part ?
	GMIME_OBJECT (node->envelope_part) : node->part;
    GMimeContentType *content_type = g_mime_object_get_content_type (meta);
    const char *cid = g_mime_object_get_content_id (meta);
    const char *filename = GMIME_IS_PART (node->part) ?
	g_mime_part_get_filename (GMIME_PART (node->part)) : NULL;
    int nclose = 0;
    int i;

    sp->begin_map (sp);

    sp->map_key (sp, "id");
    sp->integer (sp, node->part_num);

    if (node->decrypt_attempted) {
	sp->map_key (sp, "encstatus");
	sp->begin_list (sp);
	sp->begin_map (sp);
	sp->map_key (sp, "status");
	sp->string (sp, node->decrypt_success ? "good" : "bad");
	sp->end (sp);
	sp->end (sp);
    }

    if (node->verify_attempted) {
	sp->map_key (sp, "sigstatus");
	format_part_sigstatus_sprinter (sp, node);
    }

    sp->map_key (sp, "content-type");
    sp->string (sp, g_mime_content_type_to_string (content_type));

    if (cid) {
	sp->map_key (sp, "content-id");
	sp->string (sp, cid);
    }

    if (filename) {
	sp->map_key (sp, "filename");
	sp->string (sp, filename);
    }

    if (GMIME_IS_PART (node->part)) {
	/* For non-HTML text parts, we include the content in the
	 * JSON. Since JSON must be Unicode, we handle charset
	 * decoding here and do not report a charset to the caller.
	 * For text/html parts, we do not include the content unless
	 * the --include-html option has been passed. If a html part
	 * is not included, it can be requested directly. This makes
	 * charset decoding the responsibility on the caller so we
	 * report the charset for text/html parts.
	 */
	if (g_mime_content_type_is_type (content_type, "text", "*") &&
	    (include_html ||
	     ! g_mime_content_type_is_type (content_type, "text", "html")))
	{
	    GMimeStream *stream_memory = g_mime_stream_mem_new ();
	    GByteArray *part_content;
	    show_text_part_content (node->part, stream_memory, 0);
	    part_content = g_mime_stream_mem_get_byte_array (GMIME_STREAM_MEM (stream_memory));
	    sp->map_key (sp, "content");
	    sp->string_len (sp, (char *) part_content->data, part_content->len);
	    g_object_unref (stream_memory);
	} else {
	    format_omitted_part_meta_sprinter (sp, meta, GMIME_PART (node->part));
	}
    } else if (GMIME_IS_MULTIPART (node->part)) {
	sp->map_key (sp, "content");
	sp->begin_list (sp);
	nclose = 1;
    } else if (GMIME_IS_MESSAGE (node->part)) {
	sp->map_key (sp, "content");
	sp->begin_list (sp);
	sp->begin_map (sp);

	sp->map_key (sp, "headers");
	format_headers_sprinter (sp, GMIME_MESSAGE (node->part), FALSE);

	sp->map_key (sp, "body");
	sp->begin_list (sp);
	nclose = 3;
    }

    for (i = 0; i < node->nchildren; i++)
	format_part_sprinter (ctx, sp, mime_node_child (node, i), i == 0, TRUE, include_html);

    /* Close content structures */
    for (i = 0; i < nclose; i++)
	sp->end (sp);
    /* Close part map */
    sp->end (sp);
}
Exemplo n.º 11
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);
}
Exemplo 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
}
Exemplo n.º 13
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;
}
Exemplo n.º 14
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);
}
Exemplo n.º 15
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;
}
Exemplo n.º 16
0
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);
    }

  }
}
Exemplo n.º 17
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;
}
Exemplo n.º 18
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 ();
}
Exemplo n.º 19
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;
}