コード例 #1
0
ファイル: message-gen.c プロジェクト: karfai/portfolio
static void write_result(GMimeMessage* m, const char* fn)
{
    FILE* of = stdout;

    if ( fn ) {
        of = fopen(fn, "w");
    }

    GMimeStream* fst = g_mime_stream_file_new(of);
    GMimeFilter* flt = g_mime_filter_crlf_new(TRUE, FALSE);
    GMimeStream* st = g_mime_stream_filter_new(fst);
    time_t       dt;
    int          tz_off = 0;
    
    if ( !g_mime_message_get_message_id(m) ) {
        char* mid = g_mime_utils_generate_message_id("MG");
        g_mime_message_set_message_id(m, mid);
        g_free(mid);
    }
    g_mime_message_get_date(m, &dt, &tz_off);
    if ( !dt ) {
        g_mime_message_set_date(m, time(NULL), 0);
    }
    g_mime_stream_filter_add(GMIME_STREAM_FILTER(st), flt);
    g_mime_object_write_to_stream(GMIME_OBJECT(m), st);

    g_object_unref(st);
    g_object_unref(flt);
    g_object_unref(fst);
}
コード例 #2
0
ファイル: notmuch-reply.c プロジェクト: pazz/notmuch
static void
show_reply_headers (GMimeMessage *message)
{
    GMimeStream *stream_stdout = NULL;

    stream_stdout = g_mime_stream_file_new (stdout);
    if (stream_stdout) {
	g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE);
	/* Output RFC 2822 formatted (and RFC 2047 encoded) headers. */
	g_mime_object_write_to_stream (GMIME_OBJECT(message), stream_stdout);
	g_object_unref(stream_stdout);
    }
}
コード例 #3
0
ファイル: gmime-part.c プロジェクト: CMogilko/gmime
static void
mime_part_encode (GMimeObject *object, GMimeEncodingConstraint constraint)
{
	GMimePart *part = (GMimePart *) object;
	GMimeContentEncoding encoding;
	GMimeStream *stream, *null;
	GMimeFilter *filter;
	
	switch (part->encoding) {
	case GMIME_CONTENT_ENCODING_DEFAULT:
		/* Unspecified encoding, we need to figure out the
		 * best encoding no matter what */
		break;
	case GMIME_CONTENT_ENCODING_7BIT:
		/* This encoding is always safe. */
		return;
	case GMIME_CONTENT_ENCODING_8BIT:
		/* This encoding is safe unless the constraint is 7bit. */
		if (constraint != GMIME_ENCODING_CONSTRAINT_7BIT)
			return;
		break;
	case GMIME_CONTENT_ENCODING_BINARY:
		/* This encoding is only safe if the constraint is binary. */
		if (constraint == GMIME_ENCODING_CONSTRAINT_BINARY)
			return;
		break;
	case GMIME_CONTENT_ENCODING_BASE64:
	case GMIME_CONTENT_ENCODING_QUOTEDPRINTABLE:
	case GMIME_CONTENT_ENCODING_UUENCODE:
		/* These encodings are always safe. */
		return;
	}
	
	filter = g_mime_filter_best_new (GMIME_FILTER_BEST_ENCODING);
	
	null = g_mime_stream_null_new ();
	stream = g_mime_stream_filter_new (null);
	g_mime_stream_filter_add ((GMimeStreamFilter *) stream, filter);
	g_object_unref (null);
	
	g_mime_object_write_to_stream (object, stream);
	g_object_unref (stream);
	
	encoding = g_mime_filter_best_encoding ((GMimeFilterBest *) filter, constraint);
	g_mime_part_set_content_encoding (part, encoding);
	g_object_unref (filter);
}
コード例 #4
0
ファイル: notmuch-reply.c プロジェクト: chaoflow/notmuch
static void
show_reply_headers (GMimeMessage *message)
{
    GMimeStream *stream_stdout = NULL, *stream_filter = NULL;

    stream_stdout = g_mime_stream_file_new (stdout);
    if (stream_stdout) {
	g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE);
	stream_filter = g_mime_stream_filter_new(stream_stdout);
	if (stream_filter) {
		g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter),
					 g_mime_filter_headers_new());
		g_mime_object_write_to_stream(GMIME_OBJECT(message), stream_filter);
		g_object_unref(stream_filter);
	}
	g_object_unref(stream_stdout);
    }
}
コード例 #5
0
ファイル: main.c プロジェクト: jstedfast/spruce
static void
read_msg (SpruceFolder *folder, GPtrArray *uids, int cursor)
{
	GMimeMessage *message;
	GMimeStream *stream;
	GError *err = NULL;
	
	if (!(message = spruce_folder_get_message (folder, uids->pdata[cursor], &err))) {
		fprintf (stderr, "can't get message: %s\n", err ? err->message : "(null)");
		g_error_free (err);
		return;
	}
	
	stream = g_mime_stream_fs_new (dup (fileno (stdout)));
	g_mime_object_write_to_stream ((GMimeObject *) message, stream);
	g_mime_stream_write (stream, "\n", 1);
	g_mime_stream_flush (stream);
	g_object_unref (message);
	g_object_unref (stream);
	
	mark_msgs (folder, uids, NULL, cursor, SPRUCE_MESSAGE_SEEN, SPRUCE_MESSAGE_SEEN);
}
コード例 #6
0
ファイル: smtp_utils.c プロジェクト: eneq123/rspamd
gboolean
write_smtp_reply (struct smtp_session *session)
{
	gchar logbuf[1024], *new_subject;
	const gchar *old_subject;
	struct smtp_metric_callback_data cd;
	GMimeStream *stream;
	gint old_fd, sublen;

	/* Check metrics */
	cd.session = session;
	cd.action = METRIC_ACTION_NOACTION;
	cd.res = NULL;
	cd.log_buf = logbuf;
	cd.log_offset = rspamd_snprintf (logbuf,
			sizeof (logbuf),
			"id: <%s>, qid: <%s>, ",
			session->task->message_id,
			session->task->queue_id);
	cd.log_size = sizeof (logbuf);
	if (session->task->user) {
		cd.log_offset += rspamd_snprintf (logbuf + cd.log_offset,
				sizeof (logbuf) - cd.log_offset,
				"user: %s, ",
				session->task->user);
	}

	g_hash_table_foreach (session->task->results, smtp_metric_callback, &cd);

	msg_info ("%s", logbuf);

	if (cd.action <= METRIC_ACTION_REJECT) {
		if (!rspamd_dispatcher_write (session->dispatcher,
			session->ctx->reject_message, 0, FALSE, TRUE)) {
			return FALSE;
		}
		if (!rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) -
			1, FALSE, TRUE)) {
			return FALSE;
		}
		destroy_session (session->s);
		return FALSE;
	}
	else if (cd.action <= METRIC_ACTION_ADD_HEADER || cd.action <=
		METRIC_ACTION_REWRITE_SUBJECT) {
		old_fd = session->temp_fd;
		if (!make_smtp_tempfile (session)) {
			session->error = SMTP_ERROR_FILE;
			session->state = SMTP_STATE_CRITICAL_ERROR;
			rspamd_dispatcher_restore (session->dispatcher);
			if (!rspamd_dispatcher_write (session->dispatcher, session->error,
				0, FALSE, TRUE)) {
				goto err;
			}
			destroy_session (session->s);
			return FALSE;
		}

		if (cd.action <= METRIC_ACTION_REWRITE_SUBJECT) {
			/* XXX: add this action */
			old_subject = g_mime_message_get_subject (session->task->message);
			if (old_subject != NULL) {
				sublen = strlen (old_subject) + sizeof (SPAM_SUBJECT);
				new_subject = rspamd_mempool_alloc (session->pool, sublen);
				rspamd_snprintf (new_subject,
					sublen,
					"%s%s",
					SPAM_SUBJECT,
					old_subject);
			}
			else {
				new_subject = SPAM_SUBJECT;
			}
			g_mime_message_set_subject (session->task->message, new_subject);
		}
		else if (cd.action <= METRIC_ACTION_ADD_HEADER) {
#ifndef GMIME24
			g_mime_message_add_header (session->task->message, "X-Spam",
				"true");
#else
			g_mime_object_append_header (GMIME_OBJECT (
					session->task->message), "X-Spam", "true");
#endif
		}
		stream = g_mime_stream_fs_new (session->temp_fd);
		g_mime_stream_fs_set_owner (GMIME_STREAM_FS (stream), FALSE);
		close (old_fd);

		if (g_mime_object_write_to_stream (GMIME_OBJECT (session->task->message),
			stream) == -1) {
			msg_err ("cannot write MIME object to stream: %s",
				strerror (errno));
			session->error = SMTP_ERROR_FILE;
			session->state = SMTP_STATE_CRITICAL_ERROR;
			rspamd_dispatcher_restore (session->dispatcher);
			if (!rspamd_dispatcher_write (session->dispatcher, session->error,
				0, FALSE, TRUE)) {
				goto err;
			}
			destroy_session (session->s);
			return FALSE;
		}
		g_object_unref (stream);
	}
	/* XXX: Add other actions */
	return smtp_send_upstream_message (session);
err:
	session->error = SMTP_ERROR_FILE;
	session->state = SMTP_STATE_CRITICAL_ERROR;
	if (!rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE,
		TRUE)) {
		return FALSE;
	}
	destroy_session (session->s);
	return FALSE;
}
コード例 #7
0
ファイル: gmime-message-part.c プロジェクト: GNOME/gmime
static ssize_t
message_part_write_to_stream (GMimeObject *object, GMimeFormatOptions *options, gboolean content_only, GMimeStream *stream)
{
	GMimeMessagePart *part = (GMimeMessagePart *) object;
	GMimeMessage *message = part->message;
	ssize_t nwritten, total = 0;
	const char *newline, *eoln;
	gboolean match;
	size_t len;
	
	newline = g_mime_format_options_get_newline (options);
	
	if (!content_only) {
		/* write the content headers */
		if ((nwritten = g_mime_header_list_write_to_stream (object->headers, options, stream)) == -1)
			return -1;
		
		total += nwritten;
		
		/* terminate the headers */
		if ((nwritten = g_mime_stream_write_string (stream, newline)) == -1)
			return -1;
		
		total += nwritten;
	}
	
	/* write the message */
	if (message) {
		if (message->marker && (len = strlen (message->marker)) > 0) {
			if (*(eoln = message->marker + (len - 1)) == '\n') {
				if (eoln > message->marker && eoln[-1] == '\r')
					eoln--;
				
				/* check if newline sequences match... */
				if (!(match = !strcmp (eoln, newline))) {
					/* they don't match... trim off the eoln sequence */
					len = (size_t) (eoln - message->marker);
				}
			} else {
				match = FALSE;
			}
			
			if ((nwritten = g_mime_stream_write (stream, message->marker, len)) == -1)
				return -1;
			
			total += nwritten;
			
			if (!match) {
				if ((nwritten = g_mime_stream_write_string (stream, newline)) == -1)
					return -1;
				
				total += nwritten;
			}
		}
		
		if ((nwritten = g_mime_object_write_to_stream ((GMimeObject *) message, options, stream)) == -1)
			return -1;
		
		total += nwritten;
	}
	
	return total;
}
コード例 #8
0
static ssize_t
multipart_write_to_stream (GMimeObject *object, GMimeStream *stream)
{
	GMimeMultipart *multipart = (GMimeMultipart *) object;
	ssize_t nwritten, total = 0;
	const char *boundary;
	GMimeObject *part;
	guint i;
	
	/* make sure a boundary is set unless we are writing out a raw
	 * header (in which case it should already be set... or if
	 * not, then it's a broken multipart and so we don't want to
	 * alter it or we'll completely break the output) */
	boundary = g_mime_object_get_content_type_parameter (object, "boundary");
	if (!boundary && !g_mime_header_list_get_stream (object->headers)) {
		g_mime_multipart_set_boundary (multipart, NULL);
		boundary = g_mime_object_get_content_type_parameter (object, "boundary");
	}
	
	/* write the content headers */
	if ((nwritten = g_mime_header_list_write_to_stream (object->headers, stream)) == -1)
		return -1;
	
	total += nwritten;
	
	/* write the preface */
	if (multipart->preface) {
		/* terminate the headers */
		if (g_mime_stream_write (stream, "\n", 1) == -1)
			return -1;
		
		total++;
		
		if ((nwritten = g_mime_stream_write_string (stream, multipart->preface)) == -1)
			return -1;
		
		total += nwritten;
	}
	
	for (i = 0; i < multipart->children->len; i++) {
		part = multipart->children->pdata[i];
		
		/* write the boundary */
		if ((nwritten = g_mime_stream_printf (stream, "\n--%s\n", boundary)) == -1)
			return -1;
		
		total += nwritten;
		
		/* write this part out */
		if ((nwritten = g_mime_object_write_to_stream (part, stream)) == -1)
			return -1;
		
		total += nwritten;
	}
	
	/* write the end-boundary (but only if a boundary is set) */
	if (boundary) {
		if ((nwritten = g_mime_stream_printf (stream, "\n--%s--\n", boundary)) == -1)
			return -1;
		
		total += nwritten;
	}
	
	/* write the postface */
	if (multipart->postface) {
		if ((nwritten = g_mime_stream_write_string (stream, multipart->postface)) == -1)
			return -1;
		
		total += nwritten;
	}
	
	return total;
}
コード例 #9
0
ファイル: notmuch-show.c プロジェクト: briansniffen/notmuch
static notmuch_status_t
format_part_raw (unused (const void *ctx), mime_node_t *node,
                 unused (int indent),
                 unused (const notmuch_show_params_t *params))
{
    if (node->envelope_file) {
        /* Special case the entire message to avoid MIME parsing. */
        const char *filename;
        FILE *file;
        size_t size;
        char buf[4096];

        filename = notmuch_message_get_filename (node->envelope_file);
        if (filename == NULL) {
            fprintf (stderr, "Error: Cannot get message filename.\n");
            return NOTMUCH_STATUS_FILE_ERROR;
        }

        file = fopen (filename, "r");
        if (file == NULL) {
            fprintf (stderr, "Error: Cannot open file %s: %s\n", filename, strerror (errno));
            return NOTMUCH_STATUS_FILE_ERROR;
        }

        while (!feof (file)) {
            size = fread (buf, 1, sizeof (buf), file);
            if (ferror (file)) {
                fprintf (stderr, "Error: Read failed from %s\n", filename);
                fclose (file);
                return NOTMUCH_STATUS_FILE_ERROR;
            }

            if (fwrite (buf, size, 1, stdout) != 1) {
                fprintf (stderr, "Error: Write failed\n");
                fclose (file);
                return NOTMUCH_STATUS_FILE_ERROR;
            }
        }

        fclose (file);
        return NOTMUCH_STATUS_SUCCESS;
    }

    GMimeStream *stream_stdout;
    GMimeStream *stream_filter = NULL;

    stream_stdout = g_mime_stream_file_new (stdout);
    g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE);

    stream_filter = g_mime_stream_filter_new (stream_stdout);

    if (GMIME_IS_PART (node->part)) {
        /* For leaf parts, we emit only the transfer-decoded
         * body. */
        GMimeDataWrapper *wrapper;
        wrapper = g_mime_part_get_content_object (GMIME_PART (node->part));

        if (wrapper && stream_filter)
            g_mime_data_wrapper_write_to_stream (wrapper, stream_filter);
    } else {
        /* Write out the whole part.  For message parts (the root
         * part and embedded message parts), this will be the
         * message including its headers (but not the
         * encapsulating part's headers).  For multipart parts,
         * this will include the headers. */
        if (stream_filter)
            g_mime_object_write_to_stream (node->part, stream_filter);
    }

    if (stream_filter)
        g_object_unref (stream_filter);

    if (stream_stdout)
        g_object_unref(stream_stdout);

    return NOTMUCH_STATUS_SUCCESS;
}
コード例 #10
0
ファイル: test-mbox.c プロジェクト: GNOME/gmime
static void
test_parser (GMimeParser *parser, GMimeStream *mbox, GMimeStream *summary)
{
	gint64 message_begin, message_end, headers_begin, headers_end;
	GMimeFormatOptions *format = g_mime_format_options_get_default ();
	InternetAddressList *list;
	GMimeMessage *message;
	char *marker, *buf;
	const char *subject;
	GMimeObject *body;
	GDateTime *date;
	int nmsg = 0;
	
	while (!g_mime_parser_eos (parser)) {
		message_begin = g_mime_parser_tell (parser);
		if (!(message = g_mime_parser_construct_message (parser, NULL)))
			throw (exception_new ("failed to parse message #%d", nmsg));
		
		message_end = g_mime_parser_tell (parser);
		
		headers_begin = g_mime_parser_get_headers_begin (parser);
		headers_end = g_mime_parser_get_headers_end (parser);
		
		g_mime_stream_printf (summary, "message offsets: %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT "\n",
				      message_begin, message_end);
		g_mime_stream_printf (summary, "header offsets: %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT "\n",
				      headers_begin, headers_end);
		
		marker = g_mime_parser_get_mbox_marker (parser);
		g_mime_stream_printf (summary, "%s\n", marker);
		
		if ((list = g_mime_message_get_from (message)) != NULL &&
		    internet_address_list_length (list) > 0) {
			buf = internet_address_list_to_string (list, format, FALSE);
			g_mime_stream_printf (summary, "From: %s\n", buf);
			g_free (buf);
		}
		
		if ((list = g_mime_message_get_addresses (message, GMIME_ADDRESS_TYPE_TO)) != NULL &&
		    internet_address_list_length (list) > 0) {
			buf = internet_address_list_to_string (list, format, FALSE);
			g_mime_stream_printf (summary, "To: %s\n", buf);
			g_free (buf);
		}
		
		if (!(subject = g_mime_message_get_subject (message)))
			subject = "";
		g_mime_stream_printf (summary, "Subject: %s\n", subject);
		
		if (!(date = g_mime_message_get_date (message))) {
			date = g_date_time_new_from_unix_utc (0);
		} else {
			g_date_time_ref (date);
		}
		buf = g_mime_utils_header_format_date (date);
		g_mime_stream_printf (summary, "Date: %s\n", buf);
		g_date_time_unref (date);
		g_free (buf);
		
		body = g_mime_message_get_mime_part (message);
		print_mime_struct (summary, body, 0);
		g_mime_stream_write (summary, "\n", 1);
		
		if (mbox) {
			if (nmsg > 0)
				g_mime_stream_write (mbox, "\n", 1);
			
			g_mime_stream_printf (mbox, "%s\n", marker);
			g_mime_object_write_to_stream ((GMimeObject *) message, format, mbox);
		}
		
		g_object_unref (message);
		g_free (marker);
		nmsg++;
	}
}
コード例 #11
0
ファイル: gmime-multipart-crypt.c プロジェクト: GNOME/balsa
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;
}
コード例 #12
0
ファイル: gmime-multipart-crypt.c プロジェクト: GNOME/balsa
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;
}
コード例 #13
0
ファイル: gmime-multipart-crypt.c プロジェクト: GNOME/balsa
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;
}