예제 #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);
}
예제 #2
0
파일: mu-msg-part.c 프로젝트: otfrom/mu
/* call 'func' with information about this MIME-part */
static gboolean
handle_part (MuMsg *msg, GMimePart *part, GMimeObject *parent,
	     MuMsgOptions opts, unsigned index,
	     MuMsgPartForeachFunc func, gpointer user_data)
{
	GMimeContentType *ct;
	MuMsgPart msgpart;

	memset (&msgpart, 0, sizeof(MuMsgPart));

	msgpart.size        = get_part_size (part);
	msgpart.part_type   = MU_MSG_PART_TYPE_LEAF;
	msgpart.part_type |= get_disposition ((GMimeObject*)part);

	ct = g_mime_object_get_content_type ((GMimeObject*)part);
	if (GMIME_IS_CONTENT_TYPE(ct)) {
		msgpart.type    = g_mime_content_type_get_media_type (ct);
		msgpart.subtype = g_mime_content_type_get_media_subtype (ct);
		/* store as in the part_type as well, for quick
		 * checking */
		if (g_mime_content_type_is_type (ct, "text", "plain"))
			msgpart.part_type |= MU_MSG_PART_TYPE_TEXT_PLAIN;
		else if (g_mime_content_type_is_type (ct, "text", "html"))
			msgpart.part_type |= MU_MSG_PART_TYPE_TEXT_HTML;
	}

	msgpart.data    = (gpointer)part;
	msgpart.index   = index;

	func (msg, &msgpart, user_data);

	return TRUE;
}
예제 #3
0
const gchar *
libbalsa_message_body_charset(LibBalsaMessageBody * body)
{
    const gchar *charset;

    if (!body)
	return NULL;

    if (body->charset) /* This overrides all! Important for non
                        * us-ascii messages over IMAP. */
        return body->charset;

    if (GMIME_IS_PART(body->mime_part)) {
        GMimeContentType *type;

        type = g_mime_object_get_content_type(body->mime_part);
        return g_mime_content_type_get_parameter(type, "charset");
    }

    charset = libbalsa_message_body_charset(body->parts);
    if (charset)
        return charset;

    return libbalsa_message_body_charset(body->next);
}
예제 #4
0
static void
reply_part_content (GMimeObject *part)
{
    GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
    GMimeContentDisposition *disposition = g_mime_object_get_content_disposition (part);

    if (g_mime_content_type_is_type (content_type, "multipart", "*") ||
	g_mime_content_type_is_type (content_type, "message", "rfc822"))
    {
	/* Output nothing, since multipart subparts will be handled individually. */
    }
    else if (g_mime_content_type_is_type (content_type, "application", "pgp-encrypted") ||
	     g_mime_content_type_is_type (content_type, "application", "pgp-signature"))
    {
	/* Ignore PGP/MIME cruft parts */
    }
    else if (g_mime_content_type_is_type (content_type, "text", "*") &&
	!g_mime_content_type_is_type (content_type, "text", "html"))
    {
	GMimeStream *stream_stdout = NULL, *stream_filter = NULL;
	GMimeDataWrapper *wrapper;
	const char *charset;

	charset = g_mime_object_get_content_type_parameter (part, "charset");
	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 (charset) {
		g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter),
					 g_mime_filter_charset_new(charset, "UTF-8"));
	    }
	}
	g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter),
				 g_mime_filter_reply_new(TRUE));
	wrapper = g_mime_part_get_content_object (GMIME_PART (part));
	if (wrapper && stream_filter)
	    g_mime_data_wrapper_write_to_stream (wrapper, stream_filter);
	if (stream_filter)
	    g_object_unref(stream_filter);
	if (stream_stdout)
	    g_object_unref(stream_stdout);
    }
    else
    {
	if (disposition &&
	    strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 0)
	{
	    const char *filename = g_mime_part_get_filename (GMIME_PART (part));
	    printf ("Attachment: %s (%s)\n", filename,
		    g_mime_content_type_to_string (content_type));
	}
	else
	{
	    printf ("Non-text part: %s\n",
		    g_mime_content_type_to_string (content_type));
	}
    }
}
예제 #5
0
static void
format_part_reply (mime_node_t *node)
{
    int i;

    if (node->envelope_file) {
	printf ("On %s, %s wrote:\n",
		notmuch_message_get_header (node->envelope_file, "date"),
		notmuch_message_get_header (node->envelope_file, "from"));
    } else if (GMIME_IS_MESSAGE (node->part)) {
	GMimeMessage *message = GMIME_MESSAGE (node->part);
	InternetAddressList *recipients;
	const char *recipients_string;

	printf ("> From: %s\n", g_mime_message_get_sender (message));
	recipients = g_mime_message_get_recipients (message, GMIME_RECIPIENT_TYPE_TO);
	recipients_string = internet_address_list_to_string (recipients, 0);
	if (recipients_string)
	    printf ("> To: %s\n",
		    recipients_string);
	recipients = g_mime_message_get_recipients (message, GMIME_RECIPIENT_TYPE_CC);
	recipients_string = internet_address_list_to_string (recipients, 0);
	if (recipients_string)
	    printf ("> Cc: %s\n",
		    recipients_string);
	printf ("> Subject: %s\n", g_mime_message_get_subject (message));
	printf ("> Date: %s\n", g_mime_message_get_date_as_string (message));
	printf (">\n");
    } else if (GMIME_IS_PART (node->part)) {
	GMimeContentType *content_type = g_mime_object_get_content_type (node->part);
	GMimeContentDisposition *disposition = g_mime_object_get_content_disposition (node->part);

	if (g_mime_content_type_is_type (content_type, "application", "pgp-encrypted") ||
	    g_mime_content_type_is_type (content_type, "application", "pgp-signature")) {
	    /* Ignore PGP/MIME cruft parts */
	} else if (g_mime_content_type_is_type (content_type, "text", "*") &&
		   !g_mime_content_type_is_type (content_type, "text", "html")) {
	    GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);
	    g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE);
	    show_text_part_content (node->part, stream_stdout, NOTMUCH_SHOW_TEXT_PART_REPLY);
	    g_object_unref(stream_stdout);
	} else if (disposition &&
		   strcasecmp (g_mime_content_disposition_get_disposition (disposition),
			       GMIME_DISPOSITION_ATTACHMENT) == 0) {
	    const char *filename = g_mime_part_get_filename (GMIME_PART (node->part));
	    printf ("Attachment: %s (%s)\n", filename,
		    g_mime_content_type_to_string (content_type));
	} else {
	    printf ("Non-text part: %s\n",
		    g_mime_content_type_to_string (content_type));
	}
    }

    for (i = 0; i < node->nchildren; i++)
	format_part_reply (mime_node_child (node, i));
}
예제 #6
0
static gint
find_part_of_type(GMimeObject *part, GMimeContentType *fct)
{
	const GMimeContentType *ct;
	ct = g_mime_object_get_content_type(part);
	if (g_mime_content_type_is_type(ct, fct->type, fct->subtype)) {
		return 0;
	}
	return -1;
}
예제 #7
0
/* call 'func' with information about this MIME-part */
static gboolean
handle_part (MuMsg *msg, GMimePart *part, GMimeObject *parent,
	     MuMsgOptions opts, unsigned *index, gboolean decrypted,
	     MuMsgPartForeachFunc func, gpointer user_data)
{
	GMimeContentType *ct;
	MuMsgPart msgpart;

	memset (&msgpart, 0, sizeof(MuMsgPart));

	msgpart.size        = get_part_size (part);
	msgpart.part_type   = MU_MSG_PART_TYPE_LEAF;
	msgpart.part_type  |= get_disposition ((GMimeObject*)part);
	if (decrypted)
		msgpart.part_type |= MU_MSG_PART_TYPE_DECRYPTED;
	else if ((opts & MU_MSG_OPTION_DECRYPT) &&
	         GMIME_IS_MULTIPART_ENCRYPTED (parent))
		msgpart.part_type |= MU_MSG_PART_TYPE_ENCRYPTED;


	ct = g_mime_object_get_content_type ((GMimeObject*)part);
	if (GMIME_IS_CONTENT_TYPE(ct)) {
		msgpart.type    = g_mime_content_type_get_media_type (ct);
		msgpart.subtype = g_mime_content_type_get_media_subtype (ct);
		/* store as in the part_type as well, for quick
		 * checking */
		if (g_mime_content_type_is_type (ct, "text", "plain"))
			msgpart.part_type |= MU_MSG_PART_TYPE_TEXT_PLAIN;
		else if (g_mime_content_type_is_type (ct, "text", "html"))
			msgpart.part_type |= MU_MSG_PART_TYPE_TEXT_HTML;
	}

	/* put the verification info in the pgp-signature and every
	 * descendent of a pgp-encrypted part */
	msgpart.sig_status_report = NULL;
	if (g_ascii_strcasecmp (msgpart.subtype, "pgp-signature") == 0 ||
	    decrypted) {
		msgpart.sig_status_report =
			(MuMsgPartSigStatusReport*)
			g_object_get_data (G_OBJECT(parent),
					   SIG_STATUS_REPORT);

		if (msgpart.sig_status_report)
			msgpart.part_type |= MU_MSG_PART_TYPE_SIGNED;
	}

	msgpart.data    = (gpointer)part;
	msgpart.index   = (*index)++;

	func (msg, &msgpart, user_data);

	return TRUE;
}
예제 #8
0
파일: notmuch-show.c 프로젝트: dme/notmuch
static void
format_part_end_json (GMimeObject *part)
{
    GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));

    if (g_mime_content_type_is_type (content_type, "multipart", "*"))
	printf ("]");
    else if (g_mime_content_type_is_type (content_type, "message", "rfc822"))
	printf ("}]");

    printf ("}");
}
예제 #9
0
파일: gmime-part.c 프로젝트: CMogilko/gmime
/**
 * g_mime_part_set_content_md5:
 * @mime_part: a #GMimePart object
 * @content_md5: content md5 or %NULL to generate the md5 digest.
 *
 * Set the content md5 for the specified mime part.
 **/
void
g_mime_part_set_content_md5 (GMimePart *mime_part, const char *content_md5)
{
	unsigned char digest[16], b64digest[32];
	GMimeStreamFilter *filtered_stream;
	GMimeContentType *content_type;
	GMimeFilter *md5_filter;
	GMimeStream *stream;
	guint32 save = 0;
	int state = 0;
	size_t len;
	
	g_return_if_fail (GMIME_IS_PART (mime_part));
	
	g_free (mime_part->content_md5);
	
	if (!content_md5) {
		/* compute a md5sum */
		stream = g_mime_stream_null_new ();
		filtered_stream = (GMimeStreamFilter *) g_mime_stream_filter_new (stream);
		g_object_unref (stream);
		
		content_type = g_mime_object_get_content_type ((GMimeObject *) mime_part);
		if (g_mime_content_type_is_type (content_type, "text", "*")) {
			GMimeFilter *crlf_filter;
			
			crlf_filter = g_mime_filter_crlf_new (TRUE, FALSE);
			g_mime_stream_filter_add (filtered_stream, crlf_filter);
			g_object_unref (crlf_filter);
		}
		
		md5_filter = g_mime_filter_md5_new ();
		g_mime_stream_filter_add (filtered_stream, md5_filter);
		
		stream = (GMimeStream *) filtered_stream;
		g_mime_data_wrapper_write_to_stream (mime_part->content, stream);
		g_object_unref (stream);
		
		memset (digest, 0, 16);
		g_mime_filter_md5_get_digest ((GMimeFilterMd5 *) md5_filter, digest);
		g_object_unref (md5_filter);
		
		len = g_mime_encoding_base64_encode_close (digest, 16, b64digest, &state, &save);
		b64digest[len] = '\0';
		g_strstrip ((char *) b64digest);
		
		content_md5 = (const char *) b64digest;
	}
	
	mime_part->content_md5 = g_strdup (content_md5);
	g_mime_header_list_set (GMIME_OBJECT (mime_part)->headers, "Content-Md5", content_md5);
}
예제 #10
0
파일: mime_tool.c 프로젝트: moisseev/rspamd
static void
mime_foreach_callback (GMimeObject * parent,
	GMimeObject * part,
	gpointer user_data)
{
	GMimeContentType *type;

	if (GMIME_IS_MESSAGE_PART (part)) {
		/* message/rfc822 or message/news */
		GMimeMessage *message;

		/* g_mime_message_foreach_part() won't descend into
			   child message parts, so if we want to count any
			   subparts of this child message, we'll have to call
			   g_mime_message_foreach_part() again here. */
		rspamd_printf ("got message part %p: parent: %p\n",
						part, parent);
		message = g_mime_message_part_get_message ((GMimeMessagePart *) part);
		g_mime_message_foreach (message, mime_foreach_callback, part);
	}
	else if (GMIME_IS_MULTIPART (part)) {
		type = (GMimeContentType *) g_mime_object_get_content_type (GMIME_OBJECT (
						part));
		rspamd_printf ("got multipart part %p, boundary: %s: parent: %p, type: %s/%s\n",
					part, g_mime_multipart_get_boundary (GMIME_MULTIPART(part)),
					parent,
					g_mime_content_type_get_media_type (type),
					g_mime_content_type_get_media_subtype (type));
	}
	else {
		type = (GMimeContentType *) g_mime_object_get_content_type (GMIME_OBJECT (
				part));
		rspamd_printf ("got normal part %p, parent: %p, type: %s/%s\n",
				part,
				parent,
				g_mime_content_type_get_media_type (type),
				g_mime_content_type_get_media_subtype (type));
	}
}
예제 #11
0
/* Write a MIME text part out to the given stream.
 *
 * If (flags & NOTMUCH_SHOW_TEXT_PART_REPLY), this prepends "> " to
 * each output line.
 *
 * Both line-ending conversion (CRLF->LF) and charset conversion ( ->
 * UTF-8) will be performed, so it is inappropriate to call this
 * function with a non-text part. Doing so will trigger an internal
 * error.
 */
void
show_text_part_content (GMimeObject *part, GMimeStream *stream_out,
                        notmuch_show_text_part_flags flags)
{
    GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
    GMimeStream *stream_filter = NULL;
    GMimeDataWrapper *wrapper;
    const char *charset;

    if (! g_mime_content_type_is_type (content_type, "text", "*"))
        INTERNAL_ERROR ("Illegal request to format non-text part (%s) as text.",
                        g_mime_content_type_to_string (content_type));

    if (stream_out == NULL)
        return;

    stream_filter = g_mime_stream_filter_new (stream_out);
    g_mime_stream_filter_add(GMIME_STREAM_FILTER (stream_filter),
                             g_mime_filter_crlf_new (FALSE, FALSE));

    charset = g_mime_object_get_content_type_parameter (part, "charset");
    if (charset) {
        GMimeFilter *charset_filter;
        charset_filter = g_mime_filter_charset_new (charset, "UTF-8");
        /* This result can be NULL for things like "unknown-8bit".
         * Don't set a NULL filter as that makes GMime print
         * annoying assertion-failure messages on stderr. */
        if (charset_filter) {
            g_mime_stream_filter_add (GMIME_STREAM_FILTER (stream_filter),
                                      charset_filter);
            g_object_unref (charset_filter);
        }

    }

    if (flags & NOTMUCH_SHOW_TEXT_PART_REPLY) {
        GMimeFilter *reply_filter;
        reply_filter = g_mime_filter_reply_new (TRUE);
        if (reply_filter) {
            g_mime_stream_filter_add (GMIME_STREAM_FILTER (stream_filter),
                                      reply_filter);
            g_object_unref (reply_filter);
        }
    }

    wrapper = g_mime_part_get_content_object (GMIME_PART (part));
    if (wrapper && stream_filter)
        g_mime_data_wrapper_write_to_stream (wrapper, stream_filter);
    if (stream_filter)
        g_object_unref(stream_filter);
}
예제 #12
0
파일: mu-msg-part.c 프로젝트: Chris00/mu
/*
 * when a part doesn't have a filename, it can be useful to 'guess' one based on
 * its mime-type, which allows other tools to handle them correctly, e.g. from
 * mu4e.
 *
 * For now, we only handle calendar invitations in that way, but others may
 * follow.
 */
static char*
guess_file_name (GMimeObject *mobj, unsigned index)
{
	GMimeContentType *ctype;

	ctype = g_mime_object_get_content_type (mobj);

	/* special case for calendars; map to '.vcs' */
	if (g_mime_content_type_is_type (ctype, "text", "calendar"))
		return g_strdup_printf ("vcal-%u.vcs", index);

	/* fallback */
	return g_strdup_printf ("%u.msgpart", index);
}
예제 #13
0
static void
reply_part_content (GMimeObject *part)
{
    GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
    GMimeContentDisposition *disposition = g_mime_object_get_content_disposition (part);

    if (g_mime_content_type_is_type (content_type, "text", "*") &&
	!g_mime_content_type_is_type (content_type, "text", "html"))
    {
	GMimeStream *stream_stdout = NULL, *stream_filter = NULL;
	GMimeDataWrapper *wrapper;
	const char *charset;

	charset = g_mime_object_get_content_type_parameter (part, "charset");
	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 (charset) {
		g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter),
					 g_mime_filter_charset_new(charset, "UTF-8"));
	    }
	}
	g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter),
				 g_mime_filter_reply_new(TRUE));
	wrapper = g_mime_part_get_content_object (GMIME_PART (part));
	if (wrapper && stream_filter)
	    g_mime_data_wrapper_write_to_stream (wrapper, stream_filter);
	if (stream_filter)
	    g_object_unref(stream_filter);
	if (stream_stdout)
	    g_object_unref(stream_stdout);
    }
    else
    {
	if (disposition &&
	    strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 0)
	{
	    const char *filename = g_mime_part_get_filename (GMIME_PART (part));
	    printf ("Attachment: %s (%s)\n", filename,
		    g_mime_content_type_to_string (content_type));
	}
	else
	{
	    printf ("Non-text part: %s\n",
		    g_mime_content_type_to_string (content_type));
	}
    }
}
예제 #14
0
파일: mu-msg-part.c 프로젝트: otfrom/mu
static void
accumulate_text_part (MuMsg *msg, MuMsgPart *part, GString **gstrp)
{
	GMimeContentType *ctype;
	gboolean err;
	char *txt;
	ctype = g_mime_object_get_content_type ((GMimeObject*)part->data);
	if (!g_mime_content_type_is_type (ctype, "text", "plain"))
		return; /* not plain text */
	txt = mu_msg_mime_part_to_string
		((GMimePart*)part->data, &err);
	if (txt)
		g_string_append (*gstrp, txt);
	g_free (txt);
}
예제 #15
0
파일: gmime-part.c 프로젝트: CMogilko/gmime
/**
 * g_mime_part_verify_content_md5:
 * @mime_part: a #GMimePart object
 *
 * Verify the content md5 for the specified mime part.
 *
 * Returns: %TRUE if the md5 is valid or %FALSE otherwise. Note: will
 * return %FALSE if the mime part does not contain a Content-MD5.
 **/
gboolean
g_mime_part_verify_content_md5 (GMimePart *mime_part)
{
	unsigned char digest[16], b64digest[32];
	GMimeStreamFilter *filtered_stream;
	GMimeContentType *content_type;
	GMimeFilter *md5_filter;
	GMimeStream *stream;
	guint32 save = 0;
	int state = 0;
	size_t len;
	
	g_return_val_if_fail (GMIME_IS_PART (mime_part), FALSE);
	g_return_val_if_fail (mime_part->content != NULL, FALSE);
	
	if (!mime_part->content_md5)
		return FALSE;
	
	stream = g_mime_stream_null_new ();
	filtered_stream = (GMimeStreamFilter *) g_mime_stream_filter_new (stream);
	g_object_unref (stream);
	
	content_type = g_mime_object_get_content_type ((GMimeObject *) mime_part);
	if (g_mime_content_type_is_type (content_type, "text", "*")) {
		GMimeFilter *crlf_filter;
		
		crlf_filter = g_mime_filter_crlf_new (TRUE, FALSE);
		g_mime_stream_filter_add (filtered_stream, crlf_filter);
		g_object_unref (crlf_filter);
	}
	
	md5_filter = g_mime_filter_md5_new ();
	g_mime_stream_filter_add (filtered_stream, md5_filter);
	
	stream = (GMimeStream *) filtered_stream;
	g_mime_data_wrapper_write_to_stream (mime_part->content, stream);
	g_object_unref (stream);
	
	memset (digest, 0, 16);
	g_mime_filter_md5_get_digest ((GMimeFilterMd5 *) md5_filter, digest);
	g_object_unref (md5_filter);
	
	len = g_mime_encoding_base64_encode_close (digest, 16, b64digest, &state, &save);
	b64digest[len] = '\0';
	g_strstrip ((char *) b64digest);
	
	return !strcmp ((char *) b64digest, mime_part->content_md5);
}
예제 #16
0
파일: notmuch-show.c 프로젝트: dme/notmuch
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);
}
예제 #17
0
파일: mux-message-part.c 프로젝트: djcb/mux
MuxMessagePart*
mux_message_part_new (const char *path, GMimeObject *mobj)
{
        MuxMessagePart *self;

	g_return_val_if_fail (path, NULL);
	g_return_val_if_fail (GMIME_IS_OBJECT(mobj), NULL);

        self = MUX_MESSAGE_PART(g_object_new(MUX_TYPE_MESSAGE_PART, NULL));

	self->path		  = ext_path (path);
	self->content_type	  = g_mime_object_get_content_type (mobj);
	self->content_id	  = g_mime_object_get_content_id (mobj);
	self->content_disposition = g_mime_object_get_content_disposition (mobj);
	
	if (GMIME_IS_PART (mobj))
		self->file_name = g_mime_part_get_filename ((GMimePart*)mobj);

	self->mime_object = g_object_ref (mobj);

	return self;
}
예제 #18
0
파일: notmuch-show.c 프로젝트: dme/notmuch
static void
format_part_content_text (GMimeObject *part)
{
    const char *cid = g_mime_object_get_content_id (part);
    GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));

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

    if (cid)
	printf (", Content-id: %s", cid);

    printf (", Content-type: %s\n", g_mime_content_type_to_string (content_type));

    if (g_mime_content_type_is_type (content_type, "text", "*") &&
	!g_mime_content_type_is_type (content_type, "text", "html"))
    {
	GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);
	g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE);
	show_text_part_content (part, stream_stdout);
	g_object_unref(stream_stdout);
    }
    else if (g_mime_content_type_is_type (content_type, "multipart", "*") ||
	     g_mime_content_type_is_type (content_type, "message", "rfc822"))
    {
	/* Do nothing for multipart since its content will be printed
	 * when recursing. */
    }
    else
    {
	printf ("Non-text part: %s\n",
		g_mime_content_type_to_string (content_type));
    }
}
예제 #19
0
파일: test-mbox.c 프로젝트: GNOME/gmime
static void
print_mime_struct (GMimeStream *stream, GMimeObject *part, int depth)
{
	GMimeMultipart *multipart;
	GMimeMessagePart *mpart;
	GMimeContentType *type;
	GMimeObject *subpart;
	GMimeObject *body;
	GMimeMessage *msg;
	int i, n;
	
	print_depth (stream, depth);
	
	type = g_mime_object_get_content_type (part);
	
	g_mime_stream_printf (stream, "Content-Type: %s/%s\n",
			      g_mime_content_type_get_media_type (type),
			      g_mime_content_type_get_media_subtype (type));
	
	if (GMIME_IS_MULTIPART (part)) {
		multipart = (GMimeMultipart *) part;
		
		n = g_mime_multipart_get_count (multipart);
		for (i = 0; i < n; i++) {
			subpart = g_mime_multipart_get_part (multipart, i);
			print_mime_struct (stream, subpart, depth + 1);
		}
	} else if (GMIME_IS_MESSAGE_PART (part)) {
		mpart = (GMimeMessagePart *) part;
		msg = g_mime_message_part_get_message (mpart);
		
		if (msg != NULL) {
			body = g_mime_message_get_mime_part (msg);
			
			print_mime_struct (stream, body, depth + 1);
		}
	}
}
예제 #20
0
static void
write_part(GMimeObject *part)
{
	GList *l;
	const GMimeContentType *ct;
	ct = g_mime_object_get_content_type(GMIME_OBJECT(part));
	
	if (GMIME_IS_MULTIPART(part)) {
		if (g_mime_content_type_is_type(ct, "multipart", "alternative")) {
			choose_alternative(part);
			level += g_list_length(GMIME_MULTIPART(part)->subparts);
		} else {
			l = GMIME_MULTIPART(part)->subparts;
			while (l != NULL) {
				write_part(l->data);
				l = l->next;
				level++;
			}
		}
	} else if (GMIME_IS_MESSAGE_PART(part)) {
	} else if (GMIME_IS_PART(part)) {
		display_part(part, ct);
	}
}
예제 #21
0
void AnalyseMessageParse(GMimePart * mime_part)
{
    int ichar=0,iencode =0;

    if( NULL==mime_part )
    {
        printf("empty part\n");
        return ;
    }

    GMimeContentEncoding ReEncoding = g_mime_part_get_content_encoding(mime_part);

    char* szCharset = (char*)g_mime_object_get_content_type_parameter((GMimeObject*)mime_part,"charset");
    printf("charset %s\n",szCharset);

    {
        char* szCharset = (char*)g_mime_object_get_content_type_parameter((GMimeObject*)mime_part,"name");
        printf("name %s\n",szCharset);
        GMimeContentType* pContentType = g_mime_object_get_content_type((GMimeObject*)mime_part) ;
        printf("The content type is: (%s/%s)\n",pContentType->type,pContentType->subtype);
        const char *  ppp= g_mime_object_get_disposition((GMimeObject*)mime_part);
        if(!ppp)
        {
            goto exits;
        }
        const char * qqq=g_mime_object_get_content_disposition_parameter((GMimeObject*)mime_part,"filename");
        printf("get disposition\t%s\n%s\n",ppp,qqq);
        if(qqq)
        {
            FILE * ps=fopen(qqq,"w+b");
            printf("\n=======write to file================\n" );
            GMimeStream *stream = g_mime_stream_file_new (ps);
            GMimeDataWrapper * content=g_mime_part_get_content_object(mime_part);
            g_mime_data_wrapper_write_to_stream(content,stream);
            fclose(ps);
            printf("finish writing\n");
            getchar();
            return ;
        }
    }

exits:{}
    /*decode for text/plain or html*/
    GMimeDataWrapper *dataWrap = g_mime_part_get_content_object(mime_part);
    if(!dataWrap)
        printf("error in dataWrap\n" );

    GMimeStream * gmime_stream= g_mime_data_wrapper_get_stream(dataWrap);
    //encoding转码
    GMimeFilter * pAttFilter =  g_mime_filter_basic_new(ReEncoding,FALSE);
    GMimeStream* pFilterStream =  g_mime_stream_filter_new(gmime_stream);

    iencode = g_mime_stream_filter_add (GMIME_STREAM_FILTER (pFilterStream), pAttFilter);

    /*create a filter convert the charset into local type*/
    GMimeFilter * secondPtr =  g_mime_filter_charset_new(szCharset,g_mime_charset_locale_name());
    ichar = g_mime_stream_filter_add (GMIME_STREAM_FILTER (pFilterStream), secondPtr);

    /*convert stream into stdout*/
    GMimeStream *stream = g_mime_stream_file_new (stdout);
    g_mime_stream_write_to_stream(pFilterStream,stream);
#if 0
    /*get data from stream load into char* */
    char pp[10000]= {0};
    int tt=g_mime_stream_read(pFilterStream,pp,10000);

    printf("%d\t%s\n",tt,pp);
#endif

    g_object_unref ( pAttFilter );
    g_object_unref ( secondPtr );


    g_mime_stream_filter_remove((GMimeStreamFilter*)pFilterStream,ichar);
    g_mime_stream_filter_remove((GMimeStreamFilter*)pFilterStream,iencode);
    g_object_unref (pFilterStream);
    //g_object_unref (gmime_stream);
    //g_object_unref (stream);

    //if(NULL==szCharset)
    {
        printf("\n====>>>>====>>>>====>>>>Finish decoding this part<<<<====<<<<====<<<<====\n");
        getchar();
        //return ;
    }
    return ;
}
예제 #22
0
/**
 * Output a list of the parts included in the current message.
 */
void dump_mail( char *filename )
{
    std::string result;

    GMimeMessage *m_message;
    GMimeParser *parser;
    GMimeStream *stream;
    int fd;

    std::cout << "File: " << filename << std::endl;

    if ((fd = open( filename, O_RDONLY, 0)) == -1)
    {
        std::cout << "Opening failed ..." << std::endl;
        return;
    }

    stream = g_mime_stream_fs_new (fd);

    parser = g_mime_parser_new_with_stream (stream);
    g_object_unref (stream);

    m_message = g_mime_parser_construct_message (parser);
    g_object_unref (parser);

    /**
     * Create an iterator
     */
    GMimePartIter *iter =  g_mime_part_iter_new ((GMimeObject *) m_message);
    int count = 1;

    /**
     * Iterate over the message.
     */
    do
    {
        GMimeObject *part  = g_mime_part_iter_get_current (iter);

        if ( ( GMIME_IS_OBJECT( part ) ) &&
             ( GMIME_IS_PART(part) ) )
        {
            /**
             * Get the content-type
             */
            GMimeContentType *content_type = g_mime_object_get_content_type (part);
            const char *filename = g_mime_object_get_content_disposition_parameter(part, "filename");
            gchar *type = g_mime_content_type_to_string ( content_type );
            std::cout << count << " " << type << std::endl;
            if ( filename )
                std::cout << "\t[This is an attachment with file-name " << filename << "]" << std::endl;
        }


        /**
         * Highlight inline parts - which are not attachments.
         */
        GMimeContentDisposition *disp = g_mime_object_get_content_disposition(part);
        if ( disp != NULL )
        {
            const char *str = g_mime_content_disposition_get_disposition (disp);
            std::cout << "\tNOTE: Content-Disposition: " << str << std::endl;

        }

       count += 1;
    }
    while (g_mime_part_iter_next (iter));

    g_mime_part_iter_free (iter);
    g_object_unref(m_message);
}
예제 #23
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;
}
예제 #24
0
파일: crypto.c 프로젝트: notmuch/notmuch
notmuch_status_t
_notmuch_message_crypto_potential_payload (_notmuch_message_crypto_t *msg_crypto, GMimeObject *payload, GMimeObject *parent, int childnum)
{
    const char *protected_headers = NULL;
    const char *forwarded = NULL;
    const char *subject = NULL;

    if (!msg_crypto || !payload)
	return NOTMUCH_STATUS_NULL_POINTER;

    /* only fire on the first payload part encountered */
    if (msg_crypto->payload_encountered)
	return NOTMUCH_STATUS_SUCCESS;

    /* the first child of multipart/encrypted that matches the
     * encryption protocol should be "control information" metadata,
     * not payload.  So we skip it. (see
     * https://tools.ietf.org/html/rfc1847#page-8) */
    if (parent && GMIME_IS_MULTIPART_ENCRYPTED (parent) && childnum == GMIME_MULTIPART_ENCRYPTED_VERSION) {
	const char *enc_type = g_mime_object_get_content_type_parameter (parent, "protocol");
	GMimeContentType *ct = g_mime_object_get_content_type (payload);
	if (ct && enc_type) {
	    const char *part_type = g_mime_content_type_get_mime_type (ct);
	    if (part_type && strcmp (part_type, enc_type) == 0)
		return NOTMUCH_STATUS_SUCCESS;
	}
    }

    msg_crypto->payload_encountered = true;

    /* don't bother recording anything if there is no cryptographic
     * envelope: */
    if ((msg_crypto->decryption_status != NOTMUCH_MESSAGE_DECRYPTED_FULL) &&
	(msg_crypto->sig_list == NULL))
	return NOTMUCH_STATUS_SUCCESS;

    /* Verify that this payload has headers that are intended to be
     * exported to the larger message: */

    /* Consider a payload that uses Alexei Melinkov's forwarded="no" for
     * message/global or message/rfc822:
     * https://tools.ietf.org/html/draft-melnikov-smime-header-signing-05#section-4 */
    forwarded = g_mime_object_get_content_type_parameter (payload, "forwarded");
    if (GMIME_IS_MESSAGE_PART (payload) && forwarded && strcmp (forwarded, "no") == 0) {
	GMimeMessage *message = g_mime_message_part_get_message (GMIME_MESSAGE_PART (payload));
	subject = g_mime_message_get_subject (message);
	/* FIXME: handle more than just Subject: at some point */
    } else {
	/* Consider "memoryhole"-style protected headers as practiced by Enigmail and K-9 */
	protected_headers = g_mime_object_get_content_type_parameter (payload, "protected-headers");
	if (protected_headers && strcasecmp("v1", protected_headers) == 0)
	    subject = g_mime_object_get_header (payload, "Subject");
	/* FIXME: handle more than just Subject: at some point */
    }

    if (subject) {
	if (msg_crypto->payload_subject)
	    talloc_free (msg_crypto->payload_subject);
	msg_crypto->payload_subject = talloc_strdup (msg_crypto, subject);
    }

    return NOTMUCH_STATUS_SUCCESS;
}
예제 #25
0
파일: test-headers.c 프로젝트: GNOME/gmime
static void
test_content_type_sync (void)
{
	const char *raw_value, *value;
	GMimeHeaderList *headers;
	GMimeContentType *type;
	GMimeParamList *params;
	GMimeObject *object;
	GMimeHeader *header;
	GMimePart *part;
	
	object = (GMimeObject *) (part = g_mime_part_new ());
	headers = g_mime_object_get_header_list (object);
	
	testsuite_check ("content-type synchronization");
	try {
		/* first, check that the current Content-Type header
		 * value is "application/octet-stream" as expected */
		if (!(value = g_mime_object_get_header (object, "Content-Type")))
			throw (exception_new ("initial content-type header was unexpectedly null"));
		
		if (strcmp ("application/octet-stream", value) != 0)
			throw (exception_new ("initial content-type header had unexpected value: %s", value));
		
		/* now change the content-type's media type... */
		type = g_mime_object_get_content_type (object);
		g_mime_content_type_set_media_type (type, "text");
		if (!(value = g_mime_object_get_header (object, "Content-Type")))
			throw (exception_new ("content-type header was unexpectedly null after changing type"));
		if (strcmp ("text/octet-stream", value) != 0)
			throw (exception_new ("content-type header had unexpected value after changing type"));
		header = g_mime_header_list_get_header (headers, "Content-Type");
		if (!(raw_value = g_mime_header_get_raw_value (header)))
			throw (exception_new ("content-type raw_value was unexpectedly null after changing type"));
		if (strcmp (" text/octet-stream\n", raw_value) != 0)
			throw (exception_new ("content-type raw_value had unexpected value after changing type"));
		
		/* now change the content-type's media subtype... */
		g_mime_content_type_set_media_subtype (type, "plain");
		if (!(value = g_mime_object_get_header (object, "Content-Type")))
			throw (exception_new ("content-type header was unexpectedly null after changing subtype"));
		if (strcmp ("text/plain", value) != 0)
			throw (exception_new ("content-type header had unexpected value after changing subtype"));
		header = g_mime_header_list_get_header (headers, "Content-Type");
		if (!(raw_value = g_mime_header_get_raw_value (header)))
			throw (exception_new ("content-type raw_value was unexpectedly null after changing subtype"));
		if (strcmp (" text/plain\n", raw_value) != 0)
			throw (exception_new ("content-type raw_value had unexpected value after changing subtype"));
		
		/* now change the content-type's parameters by setting a param */
		g_mime_content_type_set_parameter (type, "format", "flowed");
		if (!(value = g_mime_object_get_header (object, "Content-Type")))
			throw (exception_new ("content-type header was unexpectedly null after setting a param"));
		if (strcmp ("text/plain; format=flowed", value) != 0)
			throw (exception_new ("content-type header had unexpected value after setting a param"));
		header = g_mime_header_list_get_header (headers, "Content-Type");
		if (!(raw_value = g_mime_header_get_raw_value (header)))
			throw (exception_new ("content-type raw_value was unexpectedly null after setting a param"));
		if (strcmp (" text/plain; format=flowed\n", raw_value) != 0)
			throw (exception_new ("content-type raw_value had unexpected value after setting a param"));
		
		/* now change the content-type's parameters by clearing the params */
		params = g_mime_content_type_get_parameters (type);
		g_mime_param_list_clear (params);
		if (!(value = g_mime_object_get_header (object, "Content-Type")))
			throw (exception_new ("content-type header was unexpectedly null after clearing params"));
		if (strcmp ("text/plain", value) != 0)
			throw (exception_new ("content-type header had unexpected value after clearing params"));
		header = g_mime_header_list_get_header (headers, "Content-Type");
		if (!(raw_value = g_mime_header_get_raw_value (header)))
			throw (exception_new ("content-type raw_value was unexpectedly null after clearing params"));
		if (strcmp (" text/plain\n", raw_value) != 0)
			throw (exception_new ("content-type raw_value had unexpected value after clearing params"));
		
		/* let's try this in reverse... set the header value and make sure GMimeContentType gets updated */
		header = g_mime_header_list_get_header_at (headers, 0);
		g_mime_header_set_value (header, NULL, "text/html; charset=utf-8", NULL);
		type = g_mime_object_get_content_type (object);
		if (!g_mime_content_type_is_type (type, "text", "html"))
			throw (exception_new ("GMimeContentType object was not updated"));
		header = g_mime_header_list_get_header (headers, "Content-Type");
		if (!(raw_value = g_mime_header_get_raw_value (header)))
			throw (exception_new ("content-type raw_value was unexpectedly null after setting value"));
		if (strcmp (" text/html; charset=utf-8\n", raw_value) != 0)
			throw (exception_new ("content-type raw_value had unexpected value after setting value"));
		
		testsuite_check_passed ();
	} catch (ex) {
		testsuite_check_failed ("content-type header not synchronized: %s", ex->message);
	} finally;
	
	g_object_unref (part);
}
예제 #26
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;
}
예제 #27
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);
}
예제 #28
0
static notmuch_status_t
format_part_text (const void *ctx, mime_node_t *node,
                  int indent, const notmuch_show_params_t *params)
{
    /* 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 notmuch_bool_t leaf = GMIME_IS_PART (node->part);
    const char *part_type;
    int i;

    if (node->envelope_file) {
        notmuch_message_t *message = node->envelope_file;

        part_type = "message";
        printf ("\f%s{ id:%s depth:%d match:%d excluded:%d filename:%s\n",
                part_type,
                notmuch_message_get_message_id (message),
                indent,
                notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_MATCH) ? 1 : 0,
                notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_EXCLUDED) ? 1 : 0,
                notmuch_message_get_filename (message));
    } else {
        GMimeContentDisposition *disposition = g_mime_object_get_content_disposition (meta);
        const char *cid = g_mime_object_get_content_id (meta);
        const char *filename = leaf ?
                               g_mime_part_get_filename (GMIME_PART (node->part)) : NULL;

        if (disposition &&
                strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 0)
            part_type = "attachment";
        else
            part_type = "part";

        printf ("\f%s{ ID: %d", part_type, node->part_num);
        if (filename)
            printf (", Filename: %s", filename);
        if (cid)
            printf (", Content-id: %s", cid);
        printf (", Content-type: %s\n", g_mime_content_type_to_string (content_type));
    }

    if (GMIME_IS_MESSAGE (node->part)) {
        GMimeMessage *message = GMIME_MESSAGE (node->part);
        InternetAddressList *recipients;
        const char *recipients_string;

        printf ("\fheader{\n");
        if (node->envelope_file)
            printf ("%s\n", _get_one_line_summary (ctx, node->envelope_file));
        printf ("Subject: %s\n", g_mime_message_get_subject (message));
        printf ("From: %s\n", g_mime_message_get_sender (message));
        recipients = g_mime_message_get_recipients (message, GMIME_RECIPIENT_TYPE_TO);
        recipients_string = internet_address_list_to_string (recipients, 0);
        if (recipients_string)
            printf ("To: %s\n", recipients_string);
        recipients = g_mime_message_get_recipients (message, GMIME_RECIPIENT_TYPE_CC);
        recipients_string = internet_address_list_to_string (recipients, 0);
        if (recipients_string)
            printf ("Cc: %s\n", recipients_string);
        printf ("Date: %s\n", g_mime_message_get_date_as_string (message));
        printf ("\fheader}\n");

        printf ("\fbody{\n");
    }

    if (leaf) {
        if (g_mime_content_type_is_type (content_type, "text", "*") &&
                !g_mime_content_type_is_type (content_type, "text", "html"))
        {
            GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);
            g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE);
            show_text_part_content (node->part, stream_stdout, 0);
            g_object_unref(stream_stdout);
        } else {
            printf ("Non-text part: %s\n",
                    g_mime_content_type_to_string (content_type));
        }
    }

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

    if (GMIME_IS_MESSAGE (node->part))
        printf ("\fbody}\n");

    printf ("\f%s}\n", part_type);

    return NOTMUCH_STATUS_SUCCESS;
}
예제 #29
0
파일: gmimex.c 프로젝트: swerter/gmimex
static void collect_part(GMimeObject *part, PartCollectorData *fdata, gboolean multipart_parent) {
  GMimeContentType        *content_type = g_mime_object_get_content_type(part);
  GMimeContentDisposition *disposition  = g_mime_object_get_content_disposition(part);

  if (!content_type)
    return;

  GMimeDataWrapper *wrapper = g_mime_part_get_content_object(GMIME_PART(part));
  if (!wrapper)
    return;

  // All the information will be collected in the CollectedPart
  CollectedPart *c_part = new_collected_part(fdata->part_id);

  gboolean is_attachment = FALSE;
  if (disposition) {
    c_part->disposition = g_ascii_strdown(disposition->disposition, -1);
    is_attachment = !g_ascii_strcasecmp(disposition->disposition, GMIME_DISPOSITION_ATTACHMENT);
  }

  // If a filename is given, collect it always
  const gchar *filename = g_mime_part_get_filename(GMIME_PART(part));
  if (filename)
    c_part->filename = g_strdup(filename);

  // If a contentID is given, collect it always
  const char* content_id = g_mime_part_get_content_id (GMIME_PART(part));
  if (content_id)
    c_part->content_id = g_strdup(content_id);

  // Get the contentType in lowercase
  gchar *content_type_str = g_mime_content_type_to_string(content_type);
  c_part->content_type = g_ascii_strdown(content_type_str, -1);
  g_free(content_type_str);

  // To qualify as a message body, a MIME entity MUST NOT have a Content-Disposition header with the value "attachment".
  if (!is_attachment && g_mime_content_type_is_type(content_type, "text", "*")) {
    gboolean is_text_plain    = g_mime_content_type_is_type(content_type, "text", "plain");
    gboolean is_text_html     = g_mime_content_type_is_type(content_type, "text", "html");
    gboolean is_text_rtf      = g_mime_content_type_is_type(content_type, "text", "rtf");
    gboolean is_text_enriched = g_mime_content_type_is_type(content_type, "text", "enriched");

    gboolean is_new_text = !fdata->text_part && is_text_plain;
    gboolean is_new_html = !fdata->html_part && (is_text_html || is_text_enriched || is_text_rtf);

    GMimeStream *mem_stream = g_mime_stream_mem_new();
    g_mime_stream_mem_set_owner(GMIME_STREAM_MEM(mem_stream), FALSE);
    GMimeStream *filtered_mem_stream = g_mime_stream_filter_new(mem_stream);

    const gchar *charset = g_mime_object_get_content_type_parameter(part, "charset");
    if (charset && g_ascii_strcasecmp(charset, UTF8_CHARSET)) {
      GMimeFilter *utf8_charset_filter = g_mime_filter_charset_new(charset, UTF8_CHARSET);
      g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_mem_stream), utf8_charset_filter);
      g_object_unref(utf8_charset_filter);
    }

    if (!fdata->raw && is_new_text) {
      GMimeFilter *strip_filter = g_mime_filter_strip_new();
      g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_mem_stream), strip_filter);
      g_object_unref(strip_filter);

      GMimeFilter *crlf_filter = g_mime_filter_crlf_new(FALSE, FALSE);
      g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_mem_stream), crlf_filter);
      g_object_unref(crlf_filter);

      GMimeFilter *html_filter = g_mime_filter_html_new(
         GMIME_FILTER_HTML_CONVERT_NL        |
         GMIME_FILTER_HTML_CONVERT_SPACES    |
         GMIME_FILTER_HTML_CONVERT_URLS      |
         GMIME_FILTER_HTML_MARK_CITATION     |
         GMIME_FILTER_HTML_CONVERT_ADDRESSES |
         GMIME_FILTER_HTML_CITE, CITATION_COLOUR);
      g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_mem_stream), html_filter);
      g_object_unref(html_filter);
    }

    if (!fdata->raw && (is_new_text || is_new_html)) {
      GMimeFilter *from_filter = g_mime_filter_from_new(GMIME_FILTER_FROM_MODE_ESCAPE);
      g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_mem_stream), from_filter);
      g_object_unref(from_filter);
    }

    // Add Enriched/RTF filter for this content
    if (!fdata->raw && (is_new_html && (is_text_enriched || is_text_rtf))) {
      guint flags = 0;
      if (is_text_rtf)
        flags = GMIME_FILTER_ENRICHED_IS_RICHTEXT;

      GMimeFilter *enriched_filter = g_mime_filter_enriched_new(flags);
      g_mime_stream_filter_add(GMIME_STREAM_FILTER(filtered_mem_stream), enriched_filter);
      g_object_unref(enriched_filter);
    }
    g_mime_data_wrapper_write_to_stream(wrapper, filtered_mem_stream);

    // Very important! Flush the the stream and get all content through.
    g_mime_stream_flush(filtered_mem_stream);

    // Freed by the mem_stream on its own (owner) [transfer none]
    c_part->content = g_mime_stream_mem_get_byte_array(GMIME_STREAM_MEM(mem_stream));

    // After we unref the mem_stream, part_content is NOT available anymore
    g_object_unref(filtered_mem_stream);
    g_object_unref(mem_stream);

    // Without content, the collected body part is of no use, so we ignore it.
    if (c_part->content->len == 0) {
      free_collected_part(c_part);
      return;
    }

    // We accept only the first text and first html content, everything
    // else is considered an alternative body
    if (is_new_text) {
      fdata->text_part = c_part;
    } else if (is_new_html) {
      fdata->html_part = c_part;
    } else {
      g_ptr_array_add(fdata->alternative_bodies, c_part);
    }

  } else {
    GMimeStream *attachment_mem_stream = g_mime_stream_mem_new();
    g_mime_stream_mem_set_owner (GMIME_STREAM_MEM(attachment_mem_stream), FALSE);
    g_mime_data_wrapper_write_to_stream(wrapper, attachment_mem_stream);
    g_mime_stream_flush(attachment_mem_stream);

    c_part->content = g_mime_stream_mem_get_byte_array(GMIME_STREAM_MEM(attachment_mem_stream));
    g_object_unref(attachment_mem_stream);

    // Some content may not have disposition defined so we need to determine better what it is
    if ((disposition && !g_ascii_strcasecmp(disposition->disposition, GMIME_DISPOSITION_INLINE)) ||
        g_mime_part_get_content_id(GMIME_PART(part))) {
      g_ptr_array_add(fdata->inlines, c_part);
    } else {
      // All other disposition should be kept within attachments
      g_ptr_array_add(fdata->attachments, c_part);
    }

  }
}
예제 #30
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);
}