示例#1
0
文件: test4.c 项目: Pecisk/eds-gtasks
gint main (gint argc, gchar **argv)
{
	struct dirent *dent;
	DIR *dir;
	gint fd;

	camel_test_init (argc, argv);

	camel_test_start ("Message Test Suite");

	if (!(dir = opendir ("../data/messages")))
		return 77;

	while ((dent = readdir (dir)) != NULL) {
		CamelMimeMessage *message;
		CamelStream *stream;
		gchar *filename;
		struct stat st;

		if (dent->d_name[0] == '.')
			continue;

		filename = g_strdup_printf ("../data/messages/%s", dent->d_name);
		if (g_stat (filename, &st) == -1 || !S_ISREG (st.st_mode)) {
			g_free (filename);
			continue;
		}

		if ((fd = open (filename, O_RDONLY)) == -1) {
			g_free (filename);
			continue;
		}

		push ("testing message '%s'", filename);
		g_free (filename);

		stream = camel_stream_fs_new_with_fd (fd);
		message = camel_mime_message_new ();
		camel_data_wrapper_construct_from_stream_sync (
			CAMEL_DATA_WRAPPER (message), stream, NULL, NULL);
		g_seekable_seek (
			G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, NULL);

		/*dump_mime_struct ((CamelMimePart *) message, 0);*/
		test_message_compare (message);

		g_object_unref (message);
		g_object_unref (stream);

		pull ();
	}

	closedir (dir);

	camel_test_end ();

	return 0;
}
示例#2
0
gint
test_message_compare (CamelMimeMessage *msg)
{
    CamelMimeMessage *msg2;
    CamelStream *stream1;
    CamelStream *stream2;
    GByteArray *byte_array1;
    GByteArray *byte_array2;

    byte_array1 = g_byte_array_new ();
    stream1 = camel_stream_mem_new_with_byte_array (byte_array1);
    check_msg (camel_data_wrapper_write_to_stream_sync (
                   CAMEL_DATA_WRAPPER (msg), stream1, NULL, NULL) != -1,
               "write_to_stream 1 failed", NULL);
    g_seekable_seek (G_SEEKABLE (stream1), 0, G_SEEK_SET, NULL, NULL);

    msg2 = camel_mime_message_new ();
    check_msg (camel_data_wrapper_construct_from_stream_sync (
                   CAMEL_DATA_WRAPPER (msg2), stream1, NULL, NULL) != -1,
               "construct_from_stream 1 failed");
    g_seekable_seek (G_SEEKABLE (stream1), 0, G_SEEK_SET, NULL, NULL);

    byte_array2 = g_byte_array_new ();
    stream2 = camel_stream_mem_new_with_byte_array (byte_array2);
    check_msg (camel_data_wrapper_write_to_stream_sync (
                   CAMEL_DATA_WRAPPER (msg2), stream2, NULL, NULL) != -1,
               "write_to_stream 2 failed");
    g_seekable_seek (G_SEEKABLE (stream2), 0, G_SEEK_SET, NULL, NULL);

    if (byte_array1->len != byte_array2->len) {
        CamelDataWrapper *content;

        printf ("stream1 stream:\n%.*s\n", byte_array1->len, byte_array1->data);
        printf ("stream2 stream:\n%.*s\n\n", byte_array2->len, byte_array2->data);

        printf ("msg1:\n");
        test_message_dump_structure (msg);
        printf ("msg2:\n");
        test_message_dump_structure (msg2);

        content = camel_medium_get_content ((CamelMedium *) msg);
    }

    check_unref (msg2, 1);

    check_msg (
        byte_array1->len == byte_array2->len,
        "byte_array1->len = %d, byte_array2->len = %d",
        byte_array1->len, byte_array2->len);

    check_msg (memcmp (byte_array1->data, byte_array2->data, byte_array1->len) == 0, "msg/stream compare");

    g_object_unref (stream1);
    g_object_unref (stream2);

    return 0;
}
static gint
exchange_entry_play_append (CamelOfflineJournal *journal,
                            CamelExchangeJournalEntry *entry,
                            GCancellable *cancellable,
                            GError **error)
{
	CamelExchangeFolder *exchange_folder = (CamelExchangeFolder *) journal->folder;
	CamelFolder *folder = journal->folder;
	CamelMimeMessage *message;
	CamelMessageInfo *info, *real;
	CamelStream *stream;
	gchar *uid = NULL;

	/* if the message isn't in the cache, the user went behind our backs so "not our problem" */
	if (!exchange_folder->cache || !(stream = camel_data_cache_get (exchange_folder->cache, "cache", entry->uid, NULL)))
		goto done;

	message = camel_mime_message_new ();
	if (!camel_data_wrapper_construct_from_stream_sync (
		(CamelDataWrapper *) message, stream, cancellable, NULL)) {
		g_object_unref (message);
		g_object_unref (stream);
		goto done;
	}

	g_object_unref (stream);

	if (!(info = camel_folder_summary_get (folder->summary, entry->uid))) {
		/* Should have never happened, but create a new info to avoid further crashes */
		info = camel_message_info_new (NULL);
	}

	if (!camel_folder_append_message_sync (
		folder, message, info, &uid, cancellable, error))
		return -1;

	real = camel_folder_summary_info_new_from_message (folder->summary, message, NULL);
	g_object_unref (message);

	if (uid != NULL && real) {
		real->uid = camel_pstring_strdup (uid);
		exchange_message_info_dup_to ((CamelMessageInfoBase *) real, (CamelMessageInfoBase *) info);
		camel_folder_summary_add (folder->summary, real);
		/* FIXME: should a folder_changed event be triggered? */
	}
	camel_message_info_free (info);
	g_free (uid);

 done:

	camel_exchange_folder_remove_message (exchange_folder, entry->uid);

	return 0;
}
示例#4
0
void
test_message_set_content_simple (CamelMimePart *part,
                                 gint how,
                                 const gchar *type,
                                 const gchar *text,
                                 gint len)
{
	CamelStreamMem *content = NULL;
	CamelDataWrapper *dw;
	static GByteArray *ba;

	switch (how) {
	case 0:
		camel_mime_part_set_content (part, text, len, type);
		break;
	case 1:
		content = (CamelStreamMem *) camel_stream_mem_new_with_buffer (text, len);
		break;
	case 2:
		content = (CamelStreamMem *) camel_stream_mem_new ();
		camel_stream_mem_set_buffer (content, text, len);
		break;
	case 3:
		ba = g_byte_array_new ();
		g_byte_array_append (ba, (guint8 *) text, len);

		content = (CamelStreamMem *) camel_stream_mem_new_with_byte_array (ba);
		ba = NULL;
		break;
	case 4:
		ba = g_byte_array_new ();
		g_byte_array_append (ba, (guint8 *) text, len);

		content = (CamelStreamMem *) camel_stream_mem_new ();
		camel_stream_mem_set_byte_array (content, ba);

		g_object_weak_ref (
			G_OBJECT (content), (GWeakNotify)
			content_weak_notify, ba);
		break;
	}

	if (content != 0) {
		dw = camel_data_wrapper_new ();
		camel_data_wrapper_set_mime_type (dw, type);

		camel_data_wrapper_construct_from_stream_sync (
			dw, (CamelStream *) content, NULL, NULL);
		camel_medium_set_content ((CamelMedium *) part, dw);

		check_unref (content, 2);
		check_unref (dw, 2);
	}
}
static CamelMimeMessage *
maildir_folder_get_message_sync (CamelFolder *folder,
                                 const gchar *uid,
                                 GCancellable *cancellable,
                                 GError **error)
{
	CamelLocalFolder *lf = (CamelLocalFolder *)folder;
	CamelStream *message_stream = NULL;
	CamelMimeMessage *message = NULL;
	gchar *name = NULL;

	d(printf("getting message: %s\n", uid));

	if (camel_local_folder_lock (lf, CAMEL_LOCK_WRITE, error) == -1)
		return NULL;

	name = maildir_folder_get_filename (folder, uid, error);
	if (!name)
		goto fail;

	message_stream = camel_stream_fs_new_with_name (
		name, O_RDONLY, 0, error);
	if (message_stream == NULL) {
		g_prefix_error (
			error, _("Cannot get message %s from folder %s: "),
			uid, lf->folder_path);
		goto fail;
	}

	message = camel_mime_message_new ();
	if (!camel_data_wrapper_construct_from_stream_sync (
		(CamelDataWrapper *)message,
		message_stream, cancellable, error)) {
		g_prefix_error (
			error, _("Cannot get message %s from folder %s: "),
			uid, lf->folder_path);
		g_object_unref (message);
		message = NULL;

	}
	g_object_unref (message_stream);
 fail:
	g_free (name);

	camel_local_folder_unlock (lf);

	if (lf && camel_folder_change_info_changed (lf->changes)) {
		camel_folder_changed (folder, lf->changes);
		camel_folder_change_info_clear (lf->changes);
	}

	return message;
}
static void
data_wrapper_construct_from_stream_thread (GSimpleAsyncResult *simple,
                                           GObject *object,
                                           GCancellable *cancellable)
{
	AsyncContext *async_context;
	GError *error = NULL;

	async_context = g_simple_async_result_get_op_res_gpointer (simple);

	camel_data_wrapper_construct_from_stream_sync (
		CAMEL_DATA_WRAPPER (object), async_context->stream,
		cancellable, &error);

	if (error != NULL)
		g_simple_async_result_take_error (simple, error);
}
示例#7
0
CamelMimeMessage *
test_message_read_file (const gchar *name)
{
	CamelStream *stream;
	CamelMimeMessage *msg2;

	stream = camel_stream_fs_new_with_name (name, O_RDONLY, 0, NULL);
	msg2 = camel_mime_message_new ();

	camel_data_wrapper_construct_from_stream_sync (
		CAMEL_DATA_WRAPPER (msg2), stream, NULL, NULL);
	/* stream's refcount may be > 1 if the message is real big */
	check (G_OBJECT (stream)->ref_count >=1);
	g_object_unref (stream);

	return msg2;
}
static gint
exchange_entry_play_transfer (CamelOfflineJournal *journal,
                              CamelExchangeJournalEntry *entry,
                              GCancellable *cancellable,
                              GError **error)
{
	CamelExchangeFolder *exchange_folder = (CamelExchangeFolder *) journal->folder;
	CamelFolder *folder = journal->folder;
	CamelMessageInfo *info, *real;
	GPtrArray *xuids, *uids;
	CamelFolder *src;
	CamelExchangeStore *store;
	CamelStream *stream;
	CamelMimeMessage *message;
	CamelStore *parent_store;

	if (!exchange_folder->cache || !(stream = camel_data_cache_get (exchange_folder->cache, "cache", entry->uid, NULL)))
		goto done;

	message = camel_mime_message_new ();
	if (!camel_data_wrapper_construct_from_stream_sync (
		(CamelDataWrapper *) message, stream, cancellable, NULL)) {
		g_object_unref (message);
		g_object_unref (stream);
		goto done;
	}

	g_object_unref (stream);

	if (!(info = camel_folder_summary_get (folder->summary, entry->uid))) {
		/* Note: this should never happen, but rather than crash lets make a new info */
		info = camel_message_info_new (NULL);
	}

	if (!entry->folder_name) {
		g_set_error (
			error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
			_("No folder name found"));
		goto exception;
	}

	parent_store = camel_folder_get_parent_store (folder);
	store = CAMEL_EXCHANGE_STORE (parent_store);

	g_mutex_lock (store->folders_lock);
	src = (CamelFolder *) g_hash_table_lookup (store->folders, entry->folder_name);
	g_mutex_unlock (store->folders_lock);

	if (src) {
		gboolean success;
		uids = g_ptr_array_sized_new (1);
		g_ptr_array_add (uids, entry->original_uid);

		success = camel_folder_transfer_messages_to_sync (
			src, uids, folder, entry->delete_original,
			&xuids, cancellable, error);
		if (!success)
			goto exception;

		real = camel_folder_summary_info_new_from_message (
			folder->summary, message, NULL);
		g_object_unref (message);
		real->uid = camel_pstring_strdup (
			(gchar *) xuids->pdata[0]);
		/* Transfer flags */
		exchange_message_info_dup_to (
			(CamelMessageInfoBase *) real,
			(CamelMessageInfoBase *) info);
		camel_folder_summary_add (folder->summary, real);
		/* FIXME: should a folder_changed event be triggered? */

		g_ptr_array_free (xuids, TRUE);
		g_ptr_array_free (uids, TRUE);
		/* g_object_unref (src); FIXME: should we? */

	} else {
		g_set_error (
			error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
			_("Folder doesn't exist"));
		goto exception;
	}

	camel_message_info_free (info);
done:
	camel_exchange_folder_remove_message (exchange_folder, entry->uid);

	return 0;

exception:

	camel_message_info_free (info);

	return -1;
}
示例#9
0
static void
load_snapshot_loaded_cb (GFile *snapshot_file,
                         GAsyncResult *result,
                         GSimpleAsyncResult *simple)
{
	EShell *shell;
	GObject *object;
	LoadContext *context;
	EMsgComposer *composer;
	CamelMimeMessage *message;
	CamelStream *camel_stream;
	gchar *contents = NULL;
	gsize length;
	GError *local_error = NULL;

	context = g_simple_async_result_get_op_res_gpointer (simple);

	g_file_load_contents_finish (
		snapshot_file, result, &contents, &length, NULL, &local_error);

	if (local_error != NULL) {
		g_warn_if_fail (contents == NULL);
		g_simple_async_result_take_error (simple, local_error);
		g_simple_async_result_complete (simple);
		return;
	}

	/* Create an in-memory buffer for the MIME parser to read from.
	 * We have to do this because CamelStreams are syncrhonous-only,
	 * and feeding the parser a direct file stream would block. */
	message = camel_mime_message_new ();
	camel_stream = camel_stream_mem_new_with_buffer (contents, length);
	camel_data_wrapper_construct_from_stream_sync (
		CAMEL_DATA_WRAPPER (message), camel_stream, NULL, &local_error);
	g_object_unref (camel_stream);
	g_free (contents);

	if (local_error != NULL) {
		g_simple_async_result_take_error (simple, local_error);
		g_simple_async_result_complete (simple);
		g_object_unref (message);
		return;
	}

	/* g_async_result_get_source_object() returns a new reference. */
	object = g_async_result_get_source_object (G_ASYNC_RESULT (simple));

	/* Create a new composer window from the loaded message and
	 * restore its snapshot file so it continues auto-saving to
	 * the same file. */
	shell = E_SHELL (object);
	g_object_ref (snapshot_file);
	composer = e_msg_composer_new_with_message (shell, message, TRUE, NULL);
	g_object_set_data_full (
		G_OBJECT (composer),
		SNAPSHOT_FILE_KEY, snapshot_file,
		(GDestroyNotify) delete_snapshot_file);
	context->composer = g_object_ref_sink (composer);
	g_object_unref (message);

	g_object_unref (object);

	g_simple_async_result_complete (simple);
	g_object_unref (simple);
}
static CamelMimeMessage *
mail_attachment_handler_get_selected_message (EAttachmentHandler *handler)
{
	EAttachment *attachment;
	EAttachmentView *view;
	CamelMimePart *mime_part;
	CamelMimeMessage *message = NULL;
	CamelDataWrapper *outer_wrapper;
	CamelContentType *outer_content_type;
	CamelDataWrapper *inner_wrapper;
	CamelContentType *inner_content_type;
	GList *selected;
	gboolean inner_and_outer_content_types_match;

	view = e_attachment_handler_get_view (handler);

	selected = e_attachment_view_get_selected_attachments (view);
	g_return_val_if_fail (g_list_length (selected) == 1, NULL);

	attachment = E_ATTACHMENT (selected->data);
	mime_part = e_attachment_ref_mime_part (attachment);

	outer_wrapper =
		camel_medium_get_content (CAMEL_MEDIUM (mime_part));
	outer_content_type =
		camel_data_wrapper_get_mime_type_field (outer_wrapper);

	if (!camel_content_type_is (outer_content_type, "message", "rfc822"))
		goto exit;

	inner_wrapper =
		camel_medium_get_content (CAMEL_MEDIUM (outer_wrapper));
	inner_content_type =
		camel_data_wrapper_get_mime_type_field (inner_wrapper);

	inner_and_outer_content_types_match =
		camel_content_type_is (
			inner_content_type,
			outer_content_type->type,
			outer_content_type->subtype);

	if (!inner_and_outer_content_types_match) {
		CamelStream *mem;
		gboolean success;

		/* Create a message copy in case the inner content
		 * type doesn't match the mime_part's content type,
		 * which can happen for multipart/digest, where it
		 * confuses the formatter on reply, which skips all
		 * rfc822 subparts. */
		mem = camel_stream_mem_new ();
		camel_data_wrapper_write_to_stream_sync (
			CAMEL_DATA_WRAPPER (outer_wrapper), mem, NULL, NULL);

		g_seekable_seek (
			G_SEEKABLE (mem), 0, G_SEEK_SET, NULL, NULL);
		message = camel_mime_message_new ();
		success = camel_data_wrapper_construct_from_stream_sync (
			CAMEL_DATA_WRAPPER (message), mem, NULL, NULL);
		if (!success)
			g_clear_object (&message);

		g_object_unref (mem);
	}

exit:
	if (message == NULL)
		message = g_object_ref (outer_wrapper);

	g_clear_object (&mime_part);

	g_list_free_full (selected, (GDestroyNotify) g_object_unref);

	return message;
}
示例#11
0
static CamelMimePart *
multipart_signed_get_part (CamelMultipart *multipart,
                           guint index)
{
	CamelMultipartSigned *mps = (CamelMultipartSigned *) multipart;
	CamelDataWrapper *data_wrapper;
	CamelStream *stream;
	GByteArray *byte_array;

	data_wrapper = CAMEL_DATA_WRAPPER (multipart);
	byte_array = camel_data_wrapper_get_byte_array (data_wrapper);

	switch (index) {
	case CAMEL_MULTIPART_SIGNED_CONTENT:
		if (mps->content)
			return mps->content;
		if (mps->contentraw) {
			g_return_val_if_fail (
				G_IS_SEEKABLE (mps->contentraw), NULL);
			stream = g_object_ref (mps->contentraw);
		} else if (mps->start1 == -1
			   && multipart_signed_parse_content (mps) == -1
			   && byte_array->len == 0) {
			g_warning ("Trying to get content on an invalid multipart/signed");
			return NULL;
		} else if (byte_array->len == 0) {
			return NULL;
		} else if (mps->start1 == -1) {
			stream = camel_stream_mem_new ();
			camel_stream_mem_set_byte_array (
				CAMEL_STREAM_MEM (stream), byte_array);
		} else {
			stream = multipart_signed_clip_stream (
				mps, mps->start1, mps->end1);
		}
		g_seekable_seek (
			G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, NULL);
		mps->content = camel_mime_part_new ();
		camel_data_wrapper_construct_from_stream_sync (
			CAMEL_DATA_WRAPPER (mps->content), stream, NULL, NULL);
		g_object_unref (stream);
		return mps->content;
	case CAMEL_MULTIPART_SIGNED_SIGNATURE:
		if (mps->signature)
			return mps->signature;
		if (mps->start1 == -1
		    && multipart_signed_parse_content (mps) == -1) {
			g_warning ("Trying to get signature on invalid multipart/signed");
			return NULL;
		} else if (byte_array->len == 0) {
			return NULL;
		}
		stream = multipart_signed_clip_stream (
			mps, mps->start2, mps->end2);
		g_seekable_seek (
			G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, NULL);
		mps->signature = camel_mime_part_new ();
		camel_data_wrapper_construct_from_stream_sync (
			CAMEL_DATA_WRAPPER (mps->signature),
			stream, NULL, NULL);
		g_object_unref (stream);
		return mps->signature;
	default:
		g_warning ("trying to get object out of bounds for multipart");
	}

	return NULL;
}
static CamelMimeMessage *
mh_folder_get_message_sync (CamelFolder *folder,
                            const gchar *uid,
                            GCancellable *cancellable,
                            GError **error)
{
	CamelLocalFolder *lf = (CamelLocalFolder *) folder;
	CamelStream *message_stream = NULL;
	CamelMimeMessage *message = NULL;
	CamelMessageInfo *info;
	gchar *name = NULL;

	d(printf("getting message: %s\n", uid));

	if (!lf || camel_local_folder_lock (lf, CAMEL_LOCK_WRITE, error) == -1)
		return NULL;

	/* get the message summary info */
	if ((info = camel_folder_summary_get (folder->summary, uid)) == NULL) {
		set_cannot_get_message_ex (
			error, CAMEL_FOLDER_ERROR_INVALID_UID,
			uid, lf->folder_path, _("No such message"));
		goto fail;
	}

	/* we only need it to check the message exists */
	camel_message_info_free (info);

	name = g_strdup_printf("%s/%s", lf->folder_path, uid);
	message_stream = camel_stream_fs_new_with_name (
		name, O_RDONLY, 0, error);
	if (message_stream == NULL) {
		g_prefix_error (
			error, _("Cannot get message %s from folder %s: "),
			name, lf->folder_path);
		goto fail;
	}

	message = camel_mime_message_new ();
	if (!camel_data_wrapper_construct_from_stream_sync (
		(CamelDataWrapper *) message,
		message_stream, cancellable, error)) {
		g_prefix_error (
			error, _("Cannot get message %s from folder %s: "),
			name, lf->folder_path);
		g_object_unref (message);
		message = NULL;

	}
	g_object_unref (message_stream);

 fail:
	g_free (name);

	camel_local_folder_unlock (lf);

	if (camel_folder_change_info_changed (lf->changes)) {
		camel_folder_changed (folder, lf->changes);
		camel_folder_change_info_clear (lf->changes);
	}

	return message;
}
static CamelMimeMessage *
nntp_folder_get_message_sync (CamelFolder *folder,
                              const gchar *uid,
                              GCancellable *cancellable,
                              GError **error)
{
	CamelStore *parent_store;
	CamelMimeMessage *message = NULL;
	CamelDataCache *nntp_cache;
	CamelNNTPStore *nntp_store;
	CamelFolderChangeInfo *changes;
	CamelNNTPFolder *nntp_folder;
	CamelStream *stream = NULL;
	GIOStream *base_stream;
	gchar *article, *msgid;
	gsize article_len;

	parent_store = camel_folder_get_parent_store (folder);

	nntp_folder = CAMEL_NNTP_FOLDER (folder);
	nntp_store = CAMEL_NNTP_STORE (parent_store);

	article_len = strlen (uid) + 1;
	article = alloca (article_len);
	g_strlcpy (article, uid, article_len);
	msgid = strchr (article, ',');
	if (msgid == NULL) {
		g_set_error (
			error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
			_("Internal error: UID in invalid format: %s"), uid);
		return NULL;
	}
	*msgid++ = 0;

	/* Lookup in cache, NEWS is global messageid's so use a global cache path */
	nntp_cache = camel_nntp_store_ref_cache (nntp_store);
	base_stream = camel_data_cache_get (nntp_cache, "cache", msgid, NULL);
	g_clear_object (&nntp_cache);

	if (base_stream != NULL) {
		stream = camel_stream_new (base_stream);
		g_object_unref (base_stream);
	} else {
		CamelServiceConnectionStatus connection_status;

		connection_status = camel_service_get_connection_status (
			CAMEL_SERVICE (parent_store));

		if (connection_status != CAMEL_SERVICE_CONNECTED) {
			g_set_error (
				error, CAMEL_SERVICE_ERROR,
				CAMEL_SERVICE_ERROR_UNAVAILABLE,
				_("This message is not currently available"));
			goto fail;
		}

		stream = nntp_folder_download_message (nntp_folder, article, msgid, cancellable, error);
		if (stream == NULL)
			goto fail;
	}

	message = camel_mime_message_new ();
	if (!camel_data_wrapper_construct_from_stream_sync ((CamelDataWrapper *) message, stream, cancellable, error)) {
		g_prefix_error (error, _("Cannot get message %s: "), uid);
		g_object_unref (message);
		message = NULL;
	}

	g_object_unref (stream);
fail:
	if (camel_folder_change_info_changed (nntp_folder->changes)) {
		changes = nntp_folder->changes;
		nntp_folder->changes = camel_folder_change_info_new ();
	} else {
		changes = NULL;
	}

	if (changes) {
		camel_folder_changed (folder, changes);
		camel_folder_change_info_free (changes);
	}

	return message;
}
示例#14
0
static void
import_mbox_exec (struct _import_mbox_msg *m,
                  GCancellable *cancellable,
                  GError **error)
{
	CamelFolder *folder;
	CamelMimeParser *mp = NULL;
	struct stat st;
	gint fd;

	if (g_stat (m->path, &st) == -1) {
		g_warning (
			"cannot find source file to import '%s': %s",
			m->path, g_strerror (errno));
		return;
	}

	if (m->uri == NULL || m->uri[0] == 0)
		folder = e_mail_session_get_local_folder (
			m->session, E_MAIL_LOCAL_FOLDER_INBOX);
	else
		folder = e_mail_session_uri_to_folder_sync (
			m->session, m->uri, CAMEL_STORE_FOLDER_CREATE,
			cancellable, error);

	if (folder == NULL)
		return;

	if (S_ISREG (st.st_mode)) {
		gboolean any_read = FALSE;

		fd = g_open (m->path, O_RDONLY | O_BINARY, 0);
		if (fd == -1) {
			g_warning (
				"cannot find source file to import '%s': %s",
				m->path, g_strerror (errno));
			goto fail1;
		}

		mp = camel_mime_parser_new ();
		camel_mime_parser_scan_from (mp, TRUE);
		if (camel_mime_parser_init_with_fd (mp, fd) == -1) {
			/* will never happen - 0 is unconditionally returned */
			goto fail2;
		}

		camel_operation_push_message (
			cancellable, _("Importing '%s'"),
			camel_folder_get_display_name (folder));
		camel_folder_freeze (folder);
		while (camel_mime_parser_step (mp, NULL, NULL) == CAMEL_MIME_PARSER_STATE_FROM &&
		       !g_cancellable_is_cancelled (cancellable)) {

			CamelMimeMessage *msg;
			gint pc = 0;

			any_read = TRUE;

			if (st.st_size > 0)
				pc = (gint) (100.0 * ((gdouble)
					camel_mime_parser_tell (mp) /
					(gdouble) st.st_size));
			camel_operation_progress (cancellable, pc);

			msg = camel_mime_message_new ();
			if (!camel_mime_part_construct_from_parser_sync (
				(CamelMimePart *) msg, mp, NULL, NULL)) {
				/* set exception? */
				g_object_unref (msg);
				break;
			}

			import_mbox_add_message (folder, msg, cancellable, error);

			g_object_unref (msg);

			if (error && *error != NULL)
				break;

			camel_mime_parser_step (mp, NULL, NULL);
		}

		if (!any_read && !g_cancellable_is_cancelled (cancellable)) {
			CamelStream *stream;

			stream = camel_stream_fs_new_with_name (m->path, O_RDONLY, 0, NULL);
			if (stream) {
				CamelMimeMessage *msg;

				msg = camel_mime_message_new ();

				if (camel_data_wrapper_construct_from_stream_sync ((CamelDataWrapper *) msg, stream, NULL, NULL))
					import_mbox_add_message (folder, msg, cancellable, error);

				g_object_unref (msg);
				g_object_unref (stream);
			}
		}
		/* Not passing a GCancellable or GError here. */
		camel_folder_synchronize_sync (folder, FALSE, NULL, NULL);
		camel_folder_thaw (folder);
		camel_operation_pop_message (cancellable);
	fail2:
		g_object_unref (mp);
	}
fail1:
	/* Not passing a GCancellable or GError here. */
	camel_folder_synchronize_sync (folder, FALSE, NULL, NULL);
	g_object_unref (folder);
	/* 'fd' is freed together with 'mp' */
	/* coverity[leaked_handle] */
}
static gboolean
mbox_supported (EImport *ei,
                EImportTarget *target,
                EImportImporter *im)
{
	gchar signature[1024];
	gboolean ret = FALSE;
	gint fd, n;
	EImportTargetURI *s;
	gchar *filename;

	if (target->type != E_IMPORT_TARGET_URI)
		return FALSE;

	s = (EImportTargetURI *) target;
	if (s->uri_src == NULL)
		return TRUE;

	if (strncmp (s->uri_src, "file:///", strlen ("file:///")) != 0)
		return FALSE;

	filename = g_filename_from_uri (s->uri_src, NULL, NULL);
	fd = g_open (filename, O_RDONLY, 0);
	if (fd != -1) {
		n = read (fd, signature, 1024);
		ret = n >= 5 && memcmp (signature, "From ", 5) == 0;
		close (fd);

		/* An artificial number, at least 256 bytes message
		   to be able to try to import it as an MBOX */
		if (!ret && n >= 256) {
			gint ii;

			ret = (signature[0] >= 'a' && signature[0] <= 'z') ||
			      (signature[0] >= 'A' && signature[0] <= 'Z');

			for (ii = 0; ii < n && ret; ii++) {
				ret = signature[ii] == '-' ||
				      signature[ii] == ' ' ||
				      signature[ii] == '\t' ||
				     (signature[ii] >= 'a' && signature[ii] <= 'z') ||
				     (signature[ii] >= 'A' && signature[ii] <= 'Z') ||
				     (signature[ii] >= '0' && signature[ii] <= '9');
			}

			/* It's probably a header name which starts with ASCII letter and
			   contains only [a..z][A..Z][\t, ,-] and the read stopped on ':'. */
			if (ii > 0 && ii < n && !ret && signature[ii - 1] == ':') {
				CamelStream *stream;

				stream = camel_stream_fs_new_with_name (filename, O_RDONLY, 0, NULL);
				if (stream) {
					CamelMimeMessage *msg;

					msg = camel_mime_message_new ();

					/* Check whether the message can be parsed and whether
					   it contains any mandatory fields. */
					ret = camel_data_wrapper_construct_from_stream_sync ((CamelDataWrapper *) msg, stream, NULL, NULL) &&
					      camel_mime_message_get_message_id (msg) &&
					      camel_mime_message_get_subject (msg) &&
					      camel_mime_message_get_from (msg) &&
					      (camel_mime_message_get_recipients (msg, CAMEL_RECIPIENT_TYPE_TO) ||
					       camel_mime_message_get_recipients (msg, CAMEL_RECIPIENT_TYPE_RESENT_TO));

					g_object_unref (msg);
					g_object_unref (stream);
				}
			}
		}
	}

	g_free (filename);

	return ret;
}
static GtkWidget *
mbox_get_preview (EImport *ei,
                  EImportTarget *target,
                  EImportImporter *im)
{
	GtkWidget *preview = NULL;
	EImportTargetURI *s = (EImportTargetURI *) target;
	gchar *filename;
	gint fd;
	CamelMimeParser *mp;
	GtkListStore *store = NULL;
	GtkTreeIter iter;
	GtkWidget *preview_widget = NULL;
	gboolean any_read = FALSE;

	if (!create_preview_func || !fill_preview_func)
		return NULL;

	filename = g_filename_from_uri (s->uri_src, NULL, NULL);
	if (!filename) {
		g_message (G_STRLOC ": Couldn't get filename from URI '%s'", s->uri_src);
		return NULL;
	}

	fd = g_open (filename, O_RDONLY | O_BINARY, 0);
	if (fd == -1) {
		g_warning (
			"Cannot find source file to import '%s': %s",
			filename, g_strerror (errno));
		g_free (filename);
		return NULL;
	}

	mp = camel_mime_parser_new ();
	camel_mime_parser_scan_from (mp, TRUE);
	if (camel_mime_parser_init_with_fd (mp, fd) == -1) {
		goto cleanup;
	}

	while (camel_mime_parser_step (mp, NULL, NULL) == CAMEL_MIME_PARSER_STATE_FROM) {
		CamelMimeMessage *msg;

		any_read = TRUE;

		msg = camel_mime_message_new ();
		if (!camel_mime_part_construct_from_parser_sync (
			(CamelMimePart *) msg, mp, NULL, NULL)) {
			g_object_unref (msg);
			break;
		}

		mbox_preview_add_message (msg, &store);

		g_object_unref (msg);

		camel_mime_parser_step (mp, NULL, NULL);
	}

	if (!any_read) {
		CamelStream *stream;

		stream = camel_stream_fs_new_with_name (filename, O_RDONLY, 0, NULL);
		if (stream) {
			CamelMimeMessage *msg;

			msg = camel_mime_message_new ();

			if (camel_data_wrapper_construct_from_stream_sync ((CamelDataWrapper *) msg, stream, NULL, NULL))
				mbox_preview_add_message (msg, &store);

			g_object_unref (msg);
			g_object_unref (stream);
		}
	}

	if (store) {
		GtkTreeView *tree_view;
		GtkTreeSelection *selection;

		preview = e_web_view_preview_new ();
		gtk_widget_show (preview);

		tree_view = e_web_view_preview_get_tree_view (
			E_WEB_VIEW_PREVIEW (preview));
		if (!tree_view) {
			g_warn_if_reached ();
			gtk_widget_destroy (preview);
			preview = NULL;
			goto cleanup;
		}

		gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (store));
		g_object_unref (store);

		/* Translators: Column header for a message subject */
		gtk_tree_view_insert_column_with_attributes (
			tree_view, -1, C_("mboxImp", "Subject"),
			gtk_cell_renderer_text_new (), "text", 0, NULL);

		/* Translators: Column header for a message From address */
		gtk_tree_view_insert_column_with_attributes (
			tree_view, -1, C_("mboxImp", "From"),
			gtk_cell_renderer_text_new (), "text", 1, NULL);

		if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL) > 1)
			e_web_view_preview_show_tree_view (
				E_WEB_VIEW_PREVIEW (preview));

		create_preview_func (G_OBJECT (preview), &preview_widget);
		if (!preview_widget) {
			g_warn_if_reached ();
			goto cleanup;
		}

		e_web_view_preview_set_preview (
			E_WEB_VIEW_PREVIEW (preview), preview_widget);
		gtk_widget_show (preview_widget);

		selection = gtk_tree_view_get_selection (tree_view);
		if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) {
			g_warn_if_reached ();
			goto cleanup;
		}
		gtk_tree_selection_select_iter (selection, &iter);

		g_signal_connect (
			selection, "changed",
			G_CALLBACK (preview_selection_changed_cb), preview);

		preview_selection_changed_cb (
			selection, E_WEB_VIEW_PREVIEW (preview));
	}

 cleanup:
	g_object_unref (mp);
	g_free (filename);

	/* 'fd' is freed together with 'mp' */
	/* coverity[leaked_handle] */
	return preview;
}
static void
mail_attachment_handler_message_rfc822 (EAttachmentView *view,
                                        GdkDragContext *drag_context,
                                        gint x,
                                        gint y,
                                        GtkSelectionData *selection_data,
                                        guint info,
                                        guint time,
                                        EAttachmentHandler *handler)
{
	static GdkAtom atom = GDK_NONE;
	EAttachmentStore *store;
	EAttachment *attachment;
	CamelMimeMessage *message;
	CamelDataWrapper *wrapper;
	CamelStream *stream;
	const gchar *data;
	gboolean success = FALSE;
	gpointer parent;
	gint length;

	if (G_UNLIKELY (atom == GDK_NONE))
		atom = gdk_atom_intern_static_string ("message/rfc822");

	if (gtk_selection_data_get_target (selection_data) != atom)
		return;

	g_signal_stop_emission_by_name (view, "drag-data-received");

	data = (const gchar *) gtk_selection_data_get_data (selection_data);
	length = gtk_selection_data_get_length (selection_data);

	stream = camel_stream_mem_new ();
	camel_stream_write (stream, data, length, NULL, NULL);
	g_seekable_seek (G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, NULL);

	message = camel_mime_message_new ();
	wrapper = CAMEL_DATA_WRAPPER (message);

	if (!camel_data_wrapper_construct_from_stream_sync (
		wrapper, stream, NULL, NULL))
		goto exit;

	store = e_attachment_view_get_store (view);

	parent = gtk_widget_get_toplevel (GTK_WIDGET (view));
	parent = gtk_widget_is_toplevel (parent) ? parent : NULL;

	attachment = e_attachment_new_for_message (message);
	e_attachment_store_add_attachment (store, attachment);
	e_attachment_load_async (
		attachment, (GAsyncReadyCallback)
		call_attachment_load_handle_error, parent ? g_object_ref (parent) : NULL);
	g_object_unref (attachment);

	success = TRUE;

exit:
	g_object_unref (message);
	g_object_unref (stream);

	gtk_drag_finish (drag_context, success, FALSE, time);
}