Ejemplo n.º 1
0
/* check a message is present */
void
test_folder_message (CamelFolder *folder, const gchar *uid)
{
	CamelMimeMessage *msg;
	CamelMessageInfo *info;
	GPtrArray *s;
	gint i;
	gint found;
	GError *error = NULL;

	push ("uid %s is in folder", uid);

	/* first try getting info */
	info = camel_folder_get_message_info (folder, uid);
	check (info != NULL);
	check (strcmp (camel_message_info_uid (info), uid) == 0);
	camel_folder_free_message_info (folder, info);

	/* then, getting message */
	msg = camel_folder_get_message_sync (folder, uid, NULL, &error);
	check_msg (error == NULL, "%s", error->message);
	check (msg != NULL);

	/* cross check with info */
	test_message_info (msg, info);

	g_object_unref (msg);

	/* see if it is in the summary (only once) */
	s = camel_folder_get_summary (folder);
	check (s != NULL);
	found = 0;
	for (i=0;i<s->len;i++) {
		info = s->pdata[i];
		if (strcmp (camel_message_info_uid (info), uid) == 0)
			found++;
	}
	check (found == 1);
	camel_folder_free_summary (folder, s);

	/* check it is in the uid list */
	s = camel_folder_get_uids (folder);
	check (s != NULL);
	found = 0;
	for (i=0;i<s->len;i++) {
		if (strcmp (s->pdata[i], uid) == 0)
			found++;
	}
	check (found == 1);
	camel_folder_free_uids (folder, s);

	g_clear_error (&error);

	pull ();
}
Ejemplo n.º 2
0
static void
imap4_fetch_all_add (struct imap4_fetch_all_t *fetch)
{
	CamelFolderChangeInfo *changes = NULL;
	struct imap4_envelope_t *envelope;
	CamelMessageInfo *info;
	int i;

	changes = fetch->changes;

	for (i = 0; i < fetch->added->len; i++) {
		if (!(envelope = fetch->added->pdata[i])) {
			courier_imap_is_a_piece_of_shit (fetch->summary, i + fetch->first);
			break;
		}

		if (envelope->changed != IMAP4_FETCH_ALL) {
			d(fprintf (stderr, "Hmmm, IMAP4 server didn't give us everything for message %d\n", i + 1));
			camel_message_info_free (envelope->info);
			g_free (envelope);
			continue;
		}

		if ((info = camel_folder_summary_uid (fetch->summary, camel_message_info_uid (envelope->info)))) {
			camel_message_info_free (envelope->info);
			camel_message_info_free (info);
			g_free (envelope);
			continue;
		}

		camel_folder_change_info_add_uid (changes, camel_message_info_uid (envelope->info));

		if ((((CamelMessageInfoBase *) envelope->info)->flags & CAMEL_IMAP4_MESSAGE_RECENT))
			camel_folder_change_info_recent_uid (changes, camel_message_info_uid (envelope->info));

		camel_folder_summary_add (fetch->summary, envelope->info);
		g_free (envelope);
	}

	g_ptr_array_free (fetch->added, TRUE);
	g_hash_table_destroy (fetch->uid_hash);

	if (camel_folder_change_info_changed (changes))
		camel_object_trigger_event (fetch->summary->folder, "folder_changed", changes);
	camel_folder_change_info_free (changes);

	g_free (fetch);
}
void
groupwise_summary_clear (CamelFolderSummary *summary, gboolean uncache)
{
	CamelFolderChangeInfo *changes;
	CamelMessageInfo *info;
	int i, count;
	const char *uid;

	changes = camel_folder_change_info_new ();
	count = camel_folder_summary_count (summary);
	for (i = 0; i < count; i++) {
		if (!(info = camel_folder_summary_index (summary, i)))
			continue;

		uid = camel_message_info_uid (info);
		camel_folder_change_info_remove_uid (changes, uid);
		camel_folder_summary_remove_uid (summary, uid);
		camel_message_info_free(info);
	}

	camel_folder_summary_clear (summary);
	camel_folder_summary_save (summary);

	if (uncache)
		camel_data_cache_clear (((CamelGroupwiseFolder *) summary->folder)->cache, "cache", NULL);

	if (camel_folder_change_info_changed (changes))
		camel_object_trigger_event (summary->folder, "folder_changed", changes);
	camel_folder_change_info_free (changes);
}
Ejemplo n.º 4
0
/* check message not present */
void
test_folder_not_message (CamelFolder *folder, const gchar *uid)
{
	CamelMimeMessage *msg;
	CamelMessageInfo *info;
	GPtrArray *s;
	gint i;
	gint found;
	GError *error = NULL;

	push ("uid '%s' is not in folder", uid);

	/* first try getting info */
	push ("no message info");
	info = camel_folder_get_message_info (folder, uid);
	check (info == NULL);
	pull ();

	/* then, getting message */
	push ("no message");
	msg = camel_folder_get_message_sync (folder, uid, NULL, &error);
	check (error != NULL);
	check (msg == NULL);
	g_clear_error (&error);
	pull ();

	/* see if it is not in the summary (only once) */
	push ("not in summary list");
	s = camel_folder_get_summary (folder);
	check (s != NULL);
	found = 0;
	for (i=0;i<s->len;i++) {
		info = s->pdata[i];
		if (strcmp (camel_message_info_uid (info), uid) == 0)
			found++;
	}
	check (found == 0);
	camel_folder_free_summary (folder, s);
	pull ();

	/* check it is not in the uid list */
	push ("not in uid list");
	s = camel_folder_get_uids (folder);
	check (s != NULL);
	found = 0;
	for (i=0;i<s->len;i++) {
		if (strcmp (s->pdata[i], uid) == 0)
			found++;
	}
	check (found == 0);
	camel_folder_free_uids (folder, s);
	pull ();

	g_clear_error (&error);

	pull ();
}
static gboolean
gw_info_set_flags (CamelMessageInfo *info, guint32 flags, guint32 set)
{
	guint32 old;
	CamelMessageInfoBase *mi = (CamelMessageInfoBase *)info;

	/* TODO: locking? */

	old = mi->flags;
	/* we don't set flags which aren't appropriate for the folder*/
	if ((set == (CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_JUNK_LEARN|CAMEL_MESSAGE_SEEN)) && (old & CAMEL_GW_MESSAGE_JUNK))
		return FALSE;

	mi->flags = (old & ~flags) | (set & flags);
	if (old != mi->flags) {
		mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED;
		if (mi->summary)
			camel_folder_summary_touch(mi->summary);
	}
	/* This is a hack, we are using CAMEL_MESSAGE_JUNK justo to hide the item
	 * we make sure this doesn't have any side effects*/

	if ((set == CAMEL_MESSAGE_JUNK_LEARN) && (old & CAMEL_GW_MESSAGE_JUNK)) {
		mi->flags |= CAMEL_GW_MESSAGE_NOJUNK | CAMEL_MESSAGE_JUNK;

		/* This has ugly side-effects. Evo will never learn unjunk.

		   We need to create one CAMEL_MESSAGE_HIDDEN flag which must be used for all hiding operations. We must also get rid of the seperate file that is maintained somewhere in evolution/mail/em-folder-browser.c for hidden messages
		 */

		if (mi->summary) {
			camel_folder_summary_touch(mi->summary);
		}

	} else	if ((old & ~CAMEL_MESSAGE_SYSTEM_MASK) == (mi->flags & ~CAMEL_MESSAGE_SYSTEM_MASK))
		return FALSE;

	if (mi->summary && mi->summary->folder && mi->uid) {
		CamelFolderChangeInfo *changes = camel_folder_change_info_new();

		camel_folder_change_info_change_uid(changes, camel_message_info_uid(info));
		camel_object_trigger_event(mi->summary->folder, "folder_changed", changes);
		camel_folder_change_info_free(changes);
	}

	return TRUE;

}
Ejemplo n.º 6
0
static guint32
imap4_fetch_all_update (struct imap4_fetch_all_t *fetch)
{
	CamelIMAP4MessageInfo *iinfo, *new_iinfo;
	CamelFolderChangeInfo *changes = NULL;
	struct imap4_envelope_t *envelope;
	CamelMessageInfo *info;
	guint32 first = 0;
	guint32 flags;
	int total, i;

	changes = fetch->changes;

	total = camel_folder_summary_count (fetch->summary);
	for (i = 0; i < total; i++) {
		info = camel_folder_summary_index (fetch->summary, i);
		if (!(envelope = g_hash_table_lookup (fetch->uid_hash, camel_message_info_uid (info)))) {
			/* remove it */
			camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info));
			camel_folder_summary_remove (fetch->summary, info);
			total--;
			i--;
		} else if (envelope->changed & IMAP4_FETCH_FLAGS) {
			/* update it with the new flags */
			new_iinfo = (CamelIMAP4MessageInfo *) envelope->info;
			iinfo = (CamelIMAP4MessageInfo *) info;

			flags = iinfo->info.flags;
			iinfo->info.flags = camel_imap4_merge_flags (iinfo->server_flags, iinfo->info.flags, new_iinfo->server_flags);
			iinfo->server_flags = new_iinfo->server_flags;
			if (iinfo->info.flags != flags)
				camel_folder_change_info_change_uid (changes, camel_message_info_uid (info));
		}

		camel_message_info_free (info);
	}

	for (i = 0; i < fetch->added->len; i++) {
		if (!(envelope = fetch->added->pdata[i])) {
			courier_imap_is_a_piece_of_shit (fetch->summary, i + fetch->first);
			break;
		}

		info = envelope->info;
		if (!first && camel_message_info_uid (info)) {
			if ((info = camel_folder_summary_uid (fetch->summary, camel_message_info_uid (info)))) {
				camel_message_info_free(info);
			} else {
				first = i + fetch->first;
			}
		}

		camel_message_info_free(envelope->info);
		g_free (envelope);
	}

	g_ptr_array_free (fetch->added, TRUE);
	g_hash_table_destroy (fetch->uid_hash);

	if (camel_folder_change_info_changed (changes))
		camel_object_trigger_event (fetch->summary->folder, "folder_changed", changes);
	camel_folder_change_info_free (changes);

	g_free (fetch);

	return first;
}
static gboolean
maildir_folder_append_message_sync (CamelFolder *folder,
                                    CamelMimeMessage *message,
                                    CamelMessageInfo *info,
                                    gchar **appended_uid,
                                    GCancellable *cancellable,
                                    GError **error)
{
	CamelLocalFolder *lf = (CamelLocalFolder *)folder;
	CamelStream *output_stream;
	CamelMessageInfo *mi;
	CamelMaildirMessageInfo *mdi;
	gchar *name, *dest = NULL;
	gboolean success = TRUE;

	d(printf("Appending message\n"));

	/* If we can't lock, don't do anything */
	if (camel_local_folder_lock (lf, CAMEL_LOCK_WRITE, error) == -1)
		return FALSE;

	/* add it to the summary/assign the uid, etc */
	mi = camel_local_summary_add (
		CAMEL_LOCAL_SUMMARY (folder->summary),
		message, info, lf->changes, error);
	if (mi == NULL)
		goto check_changed;

	if ((camel_message_info_flags (mi) & CAMEL_MESSAGE_ATTACHMENTS) && !camel_mime_message_has_attachment (message))
		camel_message_info_set_flags (mi, CAMEL_MESSAGE_ATTACHMENTS, 0);

	mdi = (CamelMaildirMessageInfo *)mi;

	d(printf("Appending message: uid is %s filename is %s\n", camel_message_info_uid(mi), mdi->filename));

	/* write it out to tmp, use the uid we got from the summary */
	name = g_strdup_printf ("%s/tmp/%s", lf->folder_path, camel_message_info_uid(mi));
	output_stream = camel_stream_fs_new_with_name (
		name, O_WRONLY|O_CREAT, 0600, error);
	if (output_stream == NULL)
		goto fail_write;

	if (camel_data_wrapper_write_to_stream_sync (
		(CamelDataWrapper *)message, output_stream, cancellable, error) == -1
	    || camel_stream_close (output_stream, cancellable, error) == -1)
		goto fail_write;

	/* now move from tmp to cur (bypass new, does it matter?) */
	dest = g_strdup_printf("%s/cur/%s", lf->folder_path, camel_maildir_info_filename (mdi));
	if (g_rename (name, dest) == -1) {
		g_set_error (
			error, G_IO_ERROR,
			g_io_error_from_errno (errno),
			"%s", g_strerror (errno));
		goto fail_write;
	}

	g_free (dest);
	g_free (name);

	if (appended_uid)
		*appended_uid = g_strdup(camel_message_info_uid(mi));

	if (output_stream)
		g_object_unref (output_stream);

	goto check_changed;

 fail_write:

	/* remove the summary info so we are not out-of-sync with the mh folder */
	camel_folder_summary_remove_uid (CAMEL_FOLDER_SUMMARY (folder->summary),
					 camel_message_info_uid (mi));

	g_prefix_error (
		error, _("Cannot append message to maildir folder: %s: "),
		name);

	if (output_stream) {
		g_object_unref (CAMEL_OBJECT (output_stream));
		unlink (name);
	}

	g_free (name);
	g_free (dest);

	success = FALSE;

 check_changed:
	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 success;
}
static gboolean
mh_folder_append_message_sync (CamelFolder *folder,
                               CamelMimeMessage *message,
                               CamelMessageInfo *info,
                               gchar **appended_uid,
                               GCancellable *cancellable,
                               GError **error)
{
	CamelLocalFolder *lf = (CamelLocalFolder *) folder;
	CamelStream *output_stream;
	CamelMessageInfo *mi;
	gchar *name;
	gboolean has_attachment;

	/* FIXME: probably needs additional locking (although mh doesn't appear do do it) */

	d(printf("Appending message\n"));

	/* If we can't lock, don't do anything */
	if (!lf || camel_local_folder_lock (lf, CAMEL_LOCK_WRITE, error) == -1)
		return FALSE;

	/* add it to the summary/assign the uid, etc */
	mi = camel_local_summary_add ((CamelLocalSummary *) folder->summary, message, info, lf->changes, error);
	if (mi == NULL)
		goto check_changed;

	has_attachment = camel_mime_message_has_attachment (message);
	if (((camel_message_info_flags (mi) & CAMEL_MESSAGE_ATTACHMENTS) && !has_attachment) ||
	    ((camel_message_info_flags (mi) & CAMEL_MESSAGE_ATTACHMENTS) == 0 && has_attachment)) {
		camel_message_info_set_flags (mi, CAMEL_MESSAGE_ATTACHMENTS, has_attachment ? CAMEL_MESSAGE_ATTACHMENTS : 0);
	}

	d(printf("Appending message: uid is %s\n", camel_message_info_uid(mi)));

	/* write it out, use the uid we got from the summary */
	name = g_strdup_printf("%s/%s", lf->folder_path, camel_message_info_uid(mi));
	output_stream = camel_stream_fs_new_with_name (
		name, O_WRONLY | O_CREAT, 0600, error);
	if (output_stream == NULL)
		goto fail_write;

	if (camel_data_wrapper_write_to_stream_sync (
		(CamelDataWrapper *) message, output_stream, cancellable, error) == -1
	    || camel_stream_close (output_stream, cancellable, error) == -1)
		goto fail_write;

	/* close this? */
	g_object_unref (output_stream);

	g_free (name);

	if (appended_uid)
		*appended_uid = g_strdup(camel_message_info_uid(mi));

	goto check_changed;

 fail_write:

	/* remove the summary info so we are not out-of-sync with the mh folder */
	camel_folder_summary_remove_uid (CAMEL_FOLDER_SUMMARY (folder->summary),
					 camel_message_info_uid (mi));

	g_prefix_error (
		error, _("Cannot append message to mh folder: %s: "), name);

	if (output_stream) {
		g_object_unref (output_stream);
		unlink (name);
	}

	g_free (name);

 check_changed:
	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 TRUE;
}
static gboolean
mbox_folder_append_message_sync (CamelFolder *folder,
                                 CamelMimeMessage *message,
                                 CamelMessageInfo *info,
                                 gchar **appended_uid,
                                 GCancellable *cancellable,
                                 GError **error)
{
	CamelLocalFolder *lf = (CamelLocalFolder *) folder;
	CamelStream *output_stream = NULL, *filter_stream = NULL;
	CamelMimeFilter *filter_from;
	CamelMboxSummary *mbs = (CamelMboxSummary *) folder->summary;
	CamelMessageInfo *mi;
	gchar *fromline = NULL;
	struct stat st;
	gint retval;
	gboolean has_attachment;
#if 0
	gchar *xev;
#endif
	/* If we can't lock, dont do anything */
	if (camel_local_folder_lock (lf, CAMEL_LOCK_WRITE, error) == -1)
		return FALSE;

	d (printf ("Appending message\n"));

	/* first, check the summary is correct (updates folder_size too) */
	retval = camel_local_summary_check ((CamelLocalSummary *) folder->summary, lf->changes, cancellable, error);
	if (retval == -1)
		goto fail;

	/* add it to the summary/assign the uid, etc */
	mi = camel_local_summary_add ((CamelLocalSummary *) folder->summary, message, info, lf->changes, error);
	if (mi == NULL)
		goto fail;

	d (printf ("Appending message: uid is %s\n", camel_message_info_uid (mi)));

	has_attachment = camel_mime_message_has_attachment (message);
	if (((camel_message_info_flags (mi) & CAMEL_MESSAGE_ATTACHMENTS) && !has_attachment) ||
	    ((camel_message_info_flags (mi) & CAMEL_MESSAGE_ATTACHMENTS) == 0 && has_attachment)) {
		camel_message_info_set_flags (mi, CAMEL_MESSAGE_ATTACHMENTS, has_attachment ? CAMEL_MESSAGE_ATTACHMENTS : 0);
	}

	output_stream = camel_stream_fs_new_with_name (
		lf->folder_path, O_WRONLY | O_APPEND |
		O_LARGEFILE, 0666, error);
	if (output_stream == NULL) {
		g_prefix_error (
			error, _("Cannot open mailbox: %s: "),
			lf->folder_path);
		goto fail;
	}

	/* and we need to set the frompos/XEV explicitly */
	((CamelMboxMessageInfo *) mi)->frompos = mbs->folder_size;
#if 0
	xev = camel_local_summary_encode_x_evolution ((CamelLocalSummary *) folder->summary, mi);
	if (xev) {
		/* the x-ev header should match the 'current' flags, no problem, so store as much */
		camel_medium_set_header ((CamelMedium *) message, "X-Evolution", xev);
		mi->flags &= ~ CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_FLAGGED;
		g_free (xev);
	}
#endif

	/* we must write this to the non-filtered stream ... */
	fromline = camel_mime_message_build_mbox_from (message);
	if (camel_stream_write (output_stream, fromline, strlen (fromline), cancellable, error) == -1)
		goto fail_write;

	/* and write the content to the filtering stream, that translates '\nFrom' into '\n>From' */
	filter_stream = camel_stream_filter_new (output_stream);
	filter_from = camel_mime_filter_from_new ();
	camel_stream_filter_add ((CamelStreamFilter *) filter_stream, filter_from);
	g_object_unref (filter_from);

	if (camel_data_wrapper_write_to_stream_sync (
		(CamelDataWrapper *) message, filter_stream, cancellable, error) == -1 ||
	    camel_stream_write (filter_stream, "\n", 1, cancellable, error) == -1 ||
	    camel_stream_flush (filter_stream, cancellable, error) == -1)
		goto fail_write;

	/* filter stream ref's the output stream itself, so we need to unref it too */
	g_object_unref (filter_stream);
	g_object_unref (output_stream);
	g_free (fromline);

	if (!((CamelMessageInfoBase *) mi)->preview && camel_folder_summary_get_need_preview (folder->summary)) {
		if (camel_mime_message_build_preview ((CamelMimePart *) message, mi) && ((CamelMessageInfoBase *) mi)->preview)
			camel_folder_summary_add_preview (folder->summary, mi);
	}

	/* now we 'fudge' the summary  to tell it its uptodate, because its idea of uptodate has just changed */
	/* the stat really shouldn't fail, we just wrote to it */
	if (g_stat (lf->folder_path, &st) == 0) {
		((CamelFolderSummary *) mbs)->time = st.st_mtime;
		mbs->folder_size = st.st_size;
	}

	/* unlock as soon as we can */
	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);
	}

	if (appended_uid)
		*appended_uid = g_strdup(camel_message_info_uid(mi));

	return TRUE;

fail_write:
	g_prefix_error (
		error, _("Cannot append message to mbox file: %s: "),
		lf->folder_path);

	if (output_stream) {
		gint fd;

		fd = camel_stream_fs_get_fd (CAMEL_STREAM_FS (output_stream));
		if (fd != -1) {
			/* reset the file to original size */
			do {
				retval = ftruncate (fd, mbs->folder_size);
			} while (retval == -1 && errno == EINTR);
		}

		g_object_unref (output_stream);
	}

	if (filter_stream)
		g_object_unref (filter_stream);

	g_free (fromline);

	/* remove the summary info so we are not out-of-sync with the mbox */
	camel_folder_summary_remove (CAMEL_FOLDER_SUMMARY (mbs), mi);

	/* and tell the summary it's up-to-date */
	if (g_stat (lf->folder_path, &st) == 0) {
		((CamelFolderSummary *) mbs)->time = st.st_mtime;
		mbs->folder_size = st.st_size;
	}

fail:
	/* make sure we unlock the folder - before we start triggering events into appland */
	camel_local_folder_unlock (lf);

	/* cascade the changes through, anyway, if there are any outstanding */
	if (camel_folder_change_info_changed (lf->changes)) {
		camel_folder_changed (folder, lf->changes);
		camel_folder_change_info_clear (lf->changes);
	}

	return FALSE;
}