[evolution-data-server] CamelIMAPXJob: Protect the CamelFolder.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] CamelIMAPXJob: Protect the CamelFolder.
- Date: Sun, 23 Dec 2012 18:04:48 +0000 (UTC)
commit 5759770438f0fc0af5f6cf1007160e90808457c7
Author: Matthew Barnes <mbarnes redhat com>
Date: Sun Dec 23 10:54:04 2012 -0500
CamelIMAPXJob: Protect the CamelFolder.
Move the CamelFolder pointer to CamelIMAPXJob's private section to
ensure thread-safety and consistent reference counting.
Had a crash just now in camel_imapx_server_get_job_queue_info() due to
a dangling CamelFolder pointer. Further investigation found that some
methods assign "job->folder" a new reference (but in some cases never
unref it!) and other methods just do a straight assignment.
Technically this is an API/ABI break, but not bumping Camel's soname
because it does not affect evolution-kolab, the only known 3rd party
consumer of IMAPX APIs.
camel/camel-imapx-job.c | 77 +++++-
camel/camel-imapx-job.h | 7 +-
camel/camel-imapx-server.c | 516 +++++++++++++++++++++----------
docs/reference/camel/camel-sections.txt | 3 +
4 files changed, 436 insertions(+), 167 deletions(-)
---
diff --git a/camel/camel-imapx-job.c b/camel/camel-imapx-job.c
index 03e8ef5..244afcd 100644
--- a/camel/camel-imapx-job.c
+++ b/camel/camel-imapx-job.c
@@ -38,6 +38,9 @@ struct _CamelIMAPXRealJob {
/* Extra job-specific data. */
gpointer data;
GDestroyNotify destroy_data;
+
+ CamelFolder *folder;
+ GMutex folder_lock;
};
static void
@@ -68,6 +71,8 @@ camel_imapx_job_new (GCancellable *cancellable)
g_object_ref (cancellable);
real_job->cancellable = cancellable;
+ g_mutex_init (&real_job->folder_lock);
+
return (CamelIMAPXJob *) real_job;
}
@@ -101,17 +106,21 @@ camel_imapx_job_unref (CamelIMAPXJob *job)
if (real_job->public.pop_operation_msg)
camel_operation_pop_message (real_job->cancellable);
+ /* Free the private stuff. */
+
if (real_job->cancellable != NULL)
g_object_unref (real_job->cancellable);
- /* Free the private stuff. */
-
g_cond_clear (&real_job->done_cond);
g_mutex_clear (&real_job->done_mutex);
if (real_job->destroy_data != NULL)
real_job->destroy_data (real_job->data);
+ if (real_job->folder != NULL)
+ g_object_unref (real_job->folder);
+ g_mutex_clear (&real_job->folder_lock);
+
/* Fill the memory with a bit pattern before releasing
* it back to the slab allocator, so we can more easily
* identify dangling CamelIMAPXJob pointers. */
@@ -264,3 +273,67 @@ camel_imapx_job_set_data (CamelIMAPXJob *job,
real_job->destroy_data = destroy_data;
}
+gboolean
+camel_imapx_job_has_folder (CamelIMAPXJob *job,
+ CamelFolder *folder)
+{
+ CamelIMAPXRealJob *real_job;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_JOB (job), FALSE);
+
+ if (folder != NULL)
+ g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
+
+ real_job = (CamelIMAPXRealJob *) job;
+
+ /* Not necessary to lock the mutex since
+ * we're just comparing memory addresses. */
+
+ return (folder == real_job->folder);
+}
+
+CamelFolder *
+camel_imapx_job_ref_folder (CamelIMAPXJob *job)
+{
+ CamelIMAPXRealJob *real_job;
+ CamelFolder *folder = NULL;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_JOB (job), NULL);
+
+ real_job = (CamelIMAPXRealJob *) job;
+
+ g_mutex_lock (&real_job->folder_lock);
+
+ if (real_job->folder != NULL)
+ folder = g_object_ref (real_job->folder);
+
+ g_mutex_unlock (&real_job->folder_lock);
+
+ return folder;
+}
+
+void
+camel_imapx_job_set_folder (CamelIMAPXJob *job,
+ CamelFolder *folder)
+{
+ CamelIMAPXRealJob *real_job;
+
+ g_return_if_fail (CAMEL_IS_IMAPX_JOB (job));
+
+ real_job = (CamelIMAPXRealJob *) job;
+
+ if (folder != NULL) {
+ g_return_if_fail (CAMEL_IS_FOLDER (folder));
+ g_object_ref (folder);
+ }
+
+ g_mutex_lock (&real_job->folder_lock);
+
+ if (real_job->folder != NULL)
+ g_object_unref (real_job->folder);
+
+ real_job->folder = folder;
+
+ g_mutex_unlock (&real_job->folder_lock);
+}
+
diff --git a/camel/camel-imapx-job.h b/camel/camel-imapx-job.h
index 160eac2..9b12fdb 100644
--- a/camel/camel-imapx-job.h
+++ b/camel/camel-imapx-job.h
@@ -56,8 +56,6 @@ struct _CamelIMAPXJob {
guint32 type; /* operation type */
gint pri; /* the command priority */
gshort commands; /* counts how many commands are outstanding */
-
- CamelFolder *folder;
};
CamelIMAPXJob * camel_imapx_job_new (GCancellable *cancellable);
@@ -77,6 +75,11 @@ gpointer camel_imapx_job_get_data (CamelIMAPXJob *job);
void camel_imapx_job_set_data (CamelIMAPXJob *job,
gpointer data,
GDestroyNotify destroy_data);
+gboolean camel_imapx_job_has_folder (CamelIMAPXJob *job,
+ CamelFolder *folder);
+CamelFolder * camel_imapx_job_ref_folder (CamelIMAPXJob *job);
+void camel_imapx_job_set_folder (CamelIMAPXJob *job,
+ CamelFolder *folder);
G_END_DECLS
diff --git a/camel/camel-imapx-server.c b/camel/camel-imapx-server.c
index 3e223c6..9919714 100644
--- a/camel/camel-imapx-server.c
+++ b/camel/camel-imapx-server.c
@@ -1666,19 +1666,26 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
}
if ((finfo->got & (FETCH_BODY | FETCH_UID)) == (FETCH_BODY | FETCH_UID)) {
- CamelIMAPXJob *job = imapx_match_active_job (is, IMAPX_JOB_GET_MESSAGE, finfo->uid);
+ CamelIMAPXJob *job;
GetMessageData *data;
+ job = imapx_match_active_job (
+ is, IMAPX_JOB_GET_MESSAGE, finfo->uid);
+ g_return_val_if_fail (job != NULL, FALSE);
+
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
- /* This must've been a get-message request, fill out the body stream,
- * in the right spot */
+ /* This must've been a get-message request,
+ * fill out the body stream, in the right spot. */
if (job != NULL) {
if (data->use_multi_fetch) {
data->body_offset = finfo->offset;
- g_seekable_seek (G_SEEKABLE (data->stream), finfo->offset, G_SEEK_SET, NULL, NULL);
+ g_seekable_seek (
+ G_SEEKABLE (data->stream),
+ finfo->offset, G_SEEK_SET,
+ NULL, NULL);
}
data->body_len = camel_stream_write_to_stream (
@@ -1693,17 +1700,22 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
}
if ((finfo->got & FETCH_FLAGS) && !(finfo->got & FETCH_HEADER)) {
- CamelIMAPXJob *job = imapx_match_active_job (is, IMAPX_JOB_FETCH_NEW_MESSAGES | IMAPX_JOB_REFRESH_INFO | IMAPX_JOB_FETCH_MESSAGES, NULL);
+ CamelIMAPXJob *job;
RefreshInfoData *data = NULL;
- if (job) {
+ job = imapx_match_active_job (
+ is, IMAPX_JOB_FETCH_NEW_MESSAGES |
+ IMAPX_JOB_REFRESH_INFO |
+ IMAPX_JOB_FETCH_MESSAGES, NULL);
+
+ if (job != NULL) {
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
}
- /* This is either a refresh_info job, check to see if it is and update
- * if so, otherwise it must've been an unsolicited response, so update
- * the summary to match */
+ /* This is either a refresh_info job, check to see if it is
+ * and update if so, otherwise it must've been an unsolicited
+ * response, so update the summary to match. */
if (data && (finfo->got & FETCH_UID) && data->scan_changes) {
struct _refresh_info r;
@@ -1768,23 +1780,32 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
}
if ((finfo->got & (FETCH_HEADER | FETCH_UID)) == (FETCH_HEADER | FETCH_UID)) {
- CamelIMAPXJob *job = imapx_match_active_job (is, IMAPX_JOB_FETCH_NEW_MESSAGES | IMAPX_JOB_REFRESH_INFO | IMAPX_JOB_FETCH_MESSAGES, NULL);
+ CamelIMAPXJob *job;
+
+ /* This must be a refresh info job as well, but it has
+ * asked for new messages to be added to the index. */
- /* This must be a refresh info job as well, but it has asked for
- * new messages to be added to the index */
+ job = imapx_match_active_job (
+ is, IMAPX_JOB_FETCH_NEW_MESSAGES |
+ IMAPX_JOB_REFRESH_INFO |
+ IMAPX_JOB_FETCH_MESSAGES, NULL);
- if (job) {
+ if (job != NULL) {
+ CamelFolder *folder;
CamelMimeParser *mp;
CamelMessageInfo *mi;
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
/* Do we want to save these headers for later too? Do we care? */
mp = camel_mime_parser_new ();
camel_mime_parser_init_with_stream (mp, finfo->header, NULL);
- mi = camel_folder_summary_info_new_from_parser (job->folder->summary, mp);
+ mi = camel_folder_summary_info_new_from_parser (folder->summary, mp);
g_object_unref (mp);
- if (mi) {
+ if (mi != NULL) {
guint32 server_flags;
CamelFlag *server_user_flags;
CamelMessageInfoBase *binfo;
@@ -1840,12 +1861,12 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
* command completion, but update UNREAD count now according to the
* message SEEN flag */
if (!(server_flags & CAMEL_MESSAGE_SEEN)) {
- CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) job->folder;
+ CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) folder;
guint64 uidl = strtoull (mi->uid, NULL, 10);
if (uidl >= ifolder->uidnext_on_server) {
c (is->tagprefix, "Updating unread count for new message %s\n", mi->uid);
- ((CamelIMAPXFolder *) job->folder)->unread_on_server++;
+ ((CamelIMAPXFolder *) folder)->unread_on_server++;
} else {
c (is->tagprefix, "Not updating unread count for new message %s\n", mi->uid);
}
@@ -1854,16 +1875,16 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
binfo = (CamelMessageInfoBase *) mi;
binfo->size = finfo->size;
- if (!camel_folder_summary_check_uid (job->folder->summary, mi->uid)) {
+ if (!camel_folder_summary_check_uid (folder->summary, mi->uid)) {
RefreshInfoData *data;
- CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) job->folder;
+ CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) folder;
gint cnt;
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
- imapx_set_message_info_flags_for_new_message (mi, server_flags, server_user_flags, job->folder);
- camel_folder_summary_add (job->folder->summary, mi);
+ imapx_set_message_info_flags_for_new_message (mi, server_flags, server_user_flags, folder);
+ camel_folder_summary_add (folder->summary, mi);
camel_folder_change_info_add_uid (data->changes, mi->uid);
if (!g_hash_table_lookup (ifolder->ignore_recent, mi->uid)) {
@@ -1871,7 +1892,7 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
g_hash_table_remove (ifolder->ignore_recent, mi->uid);
}
- cnt = (camel_folder_summary_count (job->folder->summary) * 100 ) / ifolder->exists_on_server;
+ cnt = (camel_folder_summary_count (folder->summary) * 100 ) / ifolder->exists_on_server;
camel_operation_progress (cancellable, cnt ? cnt : 1);
} else {
camel_message_info_free (mi);
@@ -1881,6 +1902,8 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
camel_flag_list_free (&server_user_flags);
}
+
+ g_object_unref (folder);
}
}
@@ -2877,12 +2900,16 @@ imapx_job_idle_start (CamelIMAPXJob *job,
GCancellable *cancellable,
GError **error)
{
+ CamelFolder *folder;
CamelIMAPXCommand *ic;
CamelIMAPXCommandPart *cp;
gboolean success = TRUE;
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
ic = camel_imapx_command_new (
- is, "IDLE", job->folder, "IDLE");
+ is, "IDLE", folder, "IDLE");
camel_imapx_command_set_job (ic, job);
ic->pri = job->pri;
ic->complete = imapx_command_idle_done;
@@ -2904,6 +2931,8 @@ imapx_job_idle_start (CamelIMAPXJob *job,
IDLE_UNLOCK (is->idle);
QUEUE_UNLOCK (is);
+ g_object_unref (folder);
+
return success;
}
@@ -2919,7 +2948,8 @@ camel_imapx_server_idle (CamelIMAPXServer *is,
job = camel_imapx_job_new (cancellable);
job->type = IMAPX_JOB_IDLE;
job->start = imapx_job_idle_start;
- job->folder = folder;
+
+ camel_imapx_job_set_folder (job, folder);
success = imapx_submit_job (is, job, error);
@@ -2933,7 +2963,7 @@ imapx_job_fetch_new_messages_matches (CamelIMAPXJob *job,
CamelFolder *folder,
const gchar *uid)
{
- return (folder == job->folder);
+ return camel_imapx_job_has_folder (job, folder);
}
static gboolean
@@ -2957,9 +2987,10 @@ imapx_server_fetch_new_messages (CamelIMAPXServer *is,
job->type = IMAPX_JOB_FETCH_NEW_MESSAGES;
job->start = imapx_job_fetch_new_messages_start;
job->matches = imapx_job_fetch_new_messages_matches;
- job->folder = folder;
job->noreply = async;
+ camel_imapx_job_set_folder (job, folder);
+
camel_imapx_job_set_data (
job, data, (GDestroyNotify) refresh_info_data_free);
@@ -4095,6 +4126,7 @@ imapx_command_fetch_message_done (CamelIMAPXServer *is,
GError **error)
{
CamelIMAPXJob *job;
+ CamelFolder *folder;
GetMessageData *data;
CamelIMAPXFolder *ifolder;
gboolean success = TRUE;
@@ -4106,6 +4138,9 @@ imapx_command_fetch_message_done (CamelIMAPXServer *is,
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
/* We either have more to fetch (partial mode?), we are complete,
* or we failed. Failure is handled in the fetch code, so
* we just return the job, or keep it alive with more requests */
@@ -4127,14 +4162,13 @@ imapx_command_fetch_message_done (CamelIMAPXServer *is,
if (data->fetch_offset < data->size ||
data->fetch_offset == really_fetched) {
CamelIMAPXCommand *new_ic;
- gboolean success;
camel_operation_progress (
cancellable,
(data->fetch_offset *100) / data->size);
new_ic = camel_imapx_command_new (
- is, "FETCH", job->folder,
+ is, "FETCH", folder,
"UID FETCH %t (BODY.PEEK[]",
data->uid);
camel_imapx_command_add (new_ic, "<%u.%u>", data->fetch_offset, MULTI_SIZE);
@@ -4148,9 +4182,7 @@ imapx_command_fetch_message_done (CamelIMAPXServer *is,
success = imapx_command_queue (
is, new_ic, cancellable, error);
- camel_imapx_command_unref (ic);
-
- return success;
+ goto exit;
}
}
@@ -4160,7 +4192,7 @@ imapx_command_fetch_message_done (CamelIMAPXServer *is,
/* No more messages to fetch, let's wrap things up. */
- ifolder = CAMEL_IMAPX_FOLDER (job->folder);
+ ifolder = CAMEL_IMAPX_FOLDER (folder);
/* return the exception from last command */
if (local_error != NULL) {
@@ -4222,6 +4254,8 @@ imapx_command_fetch_message_done (CamelIMAPXServer *is,
imapx_unregister_job (is, job);
exit:
+ g_object_unref (folder);
+
camel_imapx_command_unref (ic);
g_clear_error (&local_error);
@@ -4235,6 +4269,7 @@ imapx_job_get_message_start (CamelIMAPXJob *job,
GCancellable *cancellable,
GError **error)
{
+ CamelFolder *folder;
CamelIMAPXCommand *ic;
GetMessageData *data;
gint i;
@@ -4243,10 +4278,13 @@ imapx_job_get_message_start (CamelIMAPXJob *job,
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
if (data->use_multi_fetch) {
for (i = 0; i < 3 && data->fetch_offset < data->size; i++) {
ic = camel_imapx_command_new (
- is, "FETCH", job->folder,
+ is, "FETCH", folder,
"UID FETCH %t (BODY.PEEK[]",
data->uid);
camel_imapx_command_add (ic, "<%u.%u>", data->fetch_offset, MULTI_SIZE);
@@ -4264,7 +4302,7 @@ imapx_job_get_message_start (CamelIMAPXJob *job,
}
} else {
ic = camel_imapx_command_new (
- is, "FETCH", job->folder,
+ is, "FETCH", folder,
"UID FETCH %t (BODY.PEEK[])",
data->uid);
ic->complete = imapx_command_fetch_message_done;
@@ -4275,6 +4313,8 @@ imapx_job_get_message_start (CamelIMAPXJob *job,
success = imapx_command_queue (is, ic, cancellable, error);
}
+ g_object_unref (folder);
+
return success;
}
@@ -4288,7 +4328,7 @@ imapx_job_get_message_matches (CamelIMAPXJob *job,
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
- if (folder != job->folder)
+ if (!camel_imapx_job_has_folder (job, folder))
return FALSE;
if (g_strcmp0 (uid, data->uid) != 0)
@@ -4306,6 +4346,7 @@ imapx_command_copy_messages_step_done (CamelIMAPXServer *is,
GError **error)
{
CamelIMAPXJob *job;
+ CamelFolder *folder;
CopyMessagesData *data;
GPtrArray *uids;
gint i;
@@ -4317,6 +4358,9 @@ imapx_command_copy_messages_step_done (CamelIMAPXServer *is,
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
uids = data->uids;
i = data->index;
@@ -4325,17 +4369,19 @@ imapx_command_copy_messages_step_done (CamelIMAPXServer *is,
error, "%s: ",
_("Error copying messages"));
success = FALSE;
- goto cleanup;
+ goto exit;
}
if (data->delete_originals) {
gint j;
for (j = data->last_index; j < i; j++)
- camel_folder_delete_message (job->folder, uids->pdata[j]);
+ camel_folder_delete_message (folder, uids->pdata[j]);
}
- /* TODO copy the summary and cached messages to the new folder. We might need a sorted insert to avoid refreshing the dest folder */
+ /* TODO Copy the summary and cached messages to the new folder.
+ * We might need a sorted insert to avoid refreshing the dest
+ * folder. */
if (ic->status && ic->status->condition == IMAPX_COPYUID) {
gint i;
@@ -4350,14 +4396,16 @@ imapx_command_copy_messages_step_done (CamelIMAPXServer *is,
}
if (i < uids->len) {
+ g_object_unref (folder);
+
camel_imapx_command_unref (ic);
return imapx_command_copy_messages_step_start (
is, job, i, cancellable, error);
}
-cleanup:
- g_object_unref (job->folder);
+exit:
+ g_object_unref (folder);
imapx_unregister_job (is, job);
camel_imapx_command_unref (ic);
@@ -4372,6 +4420,7 @@ imapx_command_copy_messages_step_start (CamelIMAPXServer *is,
GCancellable *cancellable,
GError **error)
{
+ CamelFolder *folder;
CamelIMAPXCommand *ic;
CopyMessagesData *data;
GPtrArray *uids;
@@ -4380,15 +4429,19 @@ imapx_command_copy_messages_step_start (CamelIMAPXServer *is,
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
uids = data->uids;
- ic = camel_imapx_command_new (
- is, "COPY", job->folder, "UID COPY ");
+ ic = camel_imapx_command_new (is, "COPY", folder, "UID COPY ");
ic->complete = imapx_command_copy_messages_step_done;
camel_imapx_command_set_job (ic, job);
ic->pri = job->pri;
data->last_index = i;
+ g_object_unref (folder);
+
for (; i < uids->len; i++) {
gint res;
const gchar *uid = (gchar *) g_ptr_array_index (uids, i);
@@ -4416,14 +4469,18 @@ imapx_job_copy_messages_start (CamelIMAPXJob *job,
GCancellable *cancellable,
GError **error)
{
+ CamelFolder *folder;
CopyMessagesData *data;
gboolean success;
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
success = imapx_server_sync_changes (
- is, job->folder, job->type, job->pri, cancellable, error);
+ is, folder, job->type, job->pri, cancellable, error);
if (!success)
imapx_unregister_job (is, job);
@@ -4431,6 +4488,8 @@ imapx_job_copy_messages_start (CamelIMAPXJob *job,
g_ptr_array_sort (data->uids, (GCompareFunc) imapx_uids_array_cmp);
imapx_uidset_init (&data->uidset, 0, MAX_COMMAND_LEN);
+ g_object_unref (folder);
+
return imapx_command_copy_messages_step_start (
is, job, 0, cancellable, error);
}
@@ -4445,6 +4504,7 @@ imapx_command_append_message_done (CamelIMAPXServer *is,
{
CamelIMAPXJob *job;
CamelIMAPXFolder *ifolder;
+ CamelFolder *folder;
CamelMessageInfo *mi;
AppendMessageData *data;
gchar *cur, *old_uid;
@@ -4456,12 +4516,16 @@ imapx_command_append_message_done (CamelIMAPXServer *is,
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
- ifolder = (CamelIMAPXFolder *) job->folder;
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
- /* Append done. If we the server supports UIDPLUS we will get an APPENDUID response
- * with the new uid. This lets us move the message we have directly to the cache
- * and also create a correctly numbered MessageInfo, without losing any information.
- * Otherwise we have to wait for the server to less us know it was appended. */
+ ifolder = CAMEL_IMAPX_FOLDER (folder);
+
+ /* Append done. If we the server supports UIDPLUS we will get
+ * an APPENDUID response with the new uid. This lets us move the
+ * message we have directly to the cache and also create a correctly
+ * numbered MessageInfo, without losing any information. Otherwise
+ * we have to wait for the server to let us know it was appended. */
mi = camel_message_info_clone (data->info);
old_uid = g_strdup (data->info->uid);
@@ -4484,14 +4548,15 @@ imapx_command_append_message_done (CamelIMAPXServer *is,
g_rename (data->path, cur);
/* should we update the message count ? */
- imapx_set_message_info_flags_for_new_message (mi,
- ((CamelMessageInfoBase *) data->info)->flags,
- ((CamelMessageInfoBase *) data->info)->user_flags,
- job->folder);
- camel_folder_summary_add (job->folder->summary, mi);
+ imapx_set_message_info_flags_for_new_message (
+ mi,
+ ((CamelMessageInfoBase *) data->info)->flags,
+ ((CamelMessageInfoBase *) data->info)->user_flags,
+ folder);
+ camel_folder_summary_add (folder->summary, mi);
changes = camel_folder_change_info_new ();
camel_folder_change_info_add_uid (changes, mi->uid);
- camel_folder_changed (job->folder, changes);
+ camel_folder_changed (folder, changes);
camel_folder_change_info_free (changes);
g_free (cur);
@@ -4502,7 +4567,8 @@ imapx_command_append_message_done (CamelIMAPXServer *is,
camel_data_cache_remove (ifolder->cache, "new", old_uid, NULL);
g_free (old_uid);
- g_object_unref (job->folder);
+
+ g_object_unref (folder);
imapx_unregister_job (is, job);
camel_imapx_command_unref (ic);
@@ -4516,16 +4582,20 @@ imapx_job_append_message_start (CamelIMAPXJob *job,
GCancellable *cancellable,
GError **error)
{
+ CamelFolder *folder;
CamelIMAPXCommand *ic;
AppendMessageData *data;
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
/* TODO: we could supply the original append date from the file timestamp */
ic = camel_imapx_command_new (
is, "APPEND", NULL,
- "APPEND %f %F %P", job->folder,
+ "APPEND %f %F %P", folder,
((CamelMessageInfoBase *) data->info)->flags,
((CamelMessageInfoBase *) data->info)->user_flags,
data->path);
@@ -4534,6 +4604,8 @@ imapx_job_append_message_start (CamelIMAPXJob *job,
ic->pri = job->pri;
job->commands++;
+ g_object_unref (folder);
+
return imapx_command_queue (is, ic, cancellable, error);
}
@@ -4627,6 +4699,7 @@ imapx_command_step_fetch_done (CamelIMAPXServer *is,
CamelIMAPXFolder *ifolder;
CamelIMAPXSummary *isum;
CamelIMAPXJob *job;
+ CamelFolder *folder;
RefreshInfoData *data;
gint i;
gboolean success = TRUE;
@@ -4640,10 +4713,13 @@ imapx_command_step_fetch_done (CamelIMAPXServer *is,
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
data->scan_changes = FALSE;
- ifolder = (CamelIMAPXFolder *) job->folder;
- isum = (CamelIMAPXSummary *) job->folder->summary;
+ ifolder = CAMEL_IMAPX_FOLDER (folder);
+ isum = CAMEL_IMAPX_SUMMARY (folder->summary);
settings = camel_imapx_server_ref_settings (is);
batch_count = camel_imapx_settings_get_batch_fetch_count (settings);
@@ -4652,31 +4728,31 @@ imapx_command_step_fetch_done (CamelIMAPXServer *is,
i = data->index;
- //printf ("%s: Mobile mode: %d Fetch Count %d\n", camel_folder_get_display_name (job->folder), mobile_mode, batch_count);
+ //printf ("%s: Mobile mode: %d Fetch Count %d\n", camel_folder_get_display_name (folder), mobile_mode, batch_count);
if (camel_imapx_command_set_error_if_failed (ic, error)) {
g_prefix_error (
error, "%s: ",
_("Error fetching message headers"));
success = FALSE;
- goto cleanup;
+ goto exit;
}
if (camel_folder_change_info_changed (data->changes)) {
- imapx_update_store_summary (job->folder);
- camel_folder_summary_save_to_db (job->folder->summary, NULL);
- camel_folder_changed (job->folder, data->changes);
+ imapx_update_store_summary (folder);
+ camel_folder_summary_save_to_db (folder->summary, NULL);
+ camel_folder_changed (folder, data->changes);
}
camel_folder_change_info_clear (data->changes);
if (i < data->infos->len) {
- gint total = camel_folder_summary_count (job->folder->summary);
+ gint total = camel_folder_summary_count (folder->summary);
gint fetch_limit = data->fetch_msg_limit;
camel_imapx_command_unref (ic);
ic = camel_imapx_command_new (
- is, "FETCH", job->folder, "UID FETCH ");
+ is, "FETCH", folder, "UID FETCH ");
ic->complete = imapx_command_step_fetch_done;
camel_imapx_command_set_job (ic, job);
ic->pri = job->pri - 1;
@@ -4698,24 +4774,28 @@ imapx_command_step_fetch_done (CamelIMAPXServer *is,
camel_imapx_command_add (ic, " (RFC822.SIZE RFC822.HEADER)");
data->index = i + 1;
+ g_object_unref (folder);
+
return imapx_command_queue (is, ic, cancellable, error);
}
}
}
- //printf ("Existing : %d Gonna fetch in %s for %d/%d\n", total, camel_folder_get_full_name (job->folder), i, data->infos->len);
+ //printf ("Existing : %d Gonna fetch in %s for %d/%d\n", total, camel_folder_get_full_name (folder), i, data->infos->len);
data->index = data->infos->len;
if (imapx_uidset_done (&data->uidset, ic)) {
camel_imapx_command_add (ic, " (RFC822.SIZE RFC822.HEADER)");
+ g_object_unref (folder);
+
return imapx_command_queue (is, ic, cancellable, error);
}
}
- if (camel_folder_summary_count (job->folder->summary)) {
+ if (camel_folder_summary_count (folder->summary)) {
gchar *uid = imapx_get_uid_from_index (
- job->folder->summary,
- camel_folder_summary_count (job->folder->summary) - 1);
+ folder->summary,
+ camel_folder_summary_count (folder->summary) - 1);
guint64 uidl = strtoull (uid, NULL, 10);
g_free (uid);
@@ -4724,15 +4804,17 @@ imapx_command_step_fetch_done (CamelIMAPXServer *is,
if (uidl > ifolder->uidnext_on_server) {
c (
is->tagprefix, "Updating uidnext_on_server for '%s' to %" G_GUINT64_FORMAT "\n",
- camel_folder_get_full_name (job->folder), uidl);
+ camel_folder_get_full_name (folder), uidl);
ifolder->uidnext_on_server = uidl;
}
}
isum->uidnext = ifolder->uidnext_on_server;
- cleanup:
+exit:
refresh_info_data_infos_free (data);
+ g_object_unref (folder);
+
imapx_unregister_job (is, job);
camel_imapx_command_unref (ic);
@@ -4772,6 +4854,7 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is,
{
CamelIMAPXJob *job;
CamelIMAPXSettings *settings;
+ CamelFolder *folder;
RefreshInfoData *data;
guint uidset_size;
gboolean success = TRUE;
@@ -4783,6 +4866,9 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is,
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
data->scan_changes = FALSE;
settings = camel_imapx_server_ref_settings (is);
@@ -4800,14 +4886,16 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is,
GCompareDataFunc uid_cmp = imapx_uid_cmp;
CamelMessageInfo *s_minfo = NULL;
CamelIMAPXMessageInfo *info;
- CamelFolderSummary *s = job->folder->summary;
- CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) job->folder;
+ CamelFolderSummary *s = folder->summary;
+ CamelIMAPXFolder *ifolder;
GList *removed = NULL, *l;
gboolean fetch_new = FALSE;
gint i;
guint j = 0;
GPtrArray *uids;
+ ifolder = CAMEL_IMAPX_FOLDER (folder);
+
/* Actually we wanted to do this after the SELECT but before the
* FETCH command was issued. But this should suffice. */
((CamelIMAPXSummary *) s)->uidnext = ifolder->uidnext_on_server;
@@ -4851,7 +4939,7 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is,
if (s_minfo && uid_cmp (s_minfo->uid, r->uid, s) == 0) {
info = (CamelIMAPXMessageInfo *) s_minfo;
- if (imapx_update_message_info_flags ((CamelMessageInfo *) info, r->server_flags, r->server_user_flags, is->permanentflags, job->folder, FALSE))
+ if (imapx_update_message_info_flags ((CamelMessageInfo *) info, r->server_flags, r->server_user_flags, is->permanentflags, folder, FALSE))
camel_folder_change_info_change_uid (data->changes, camel_message_info_uid (s_minfo));
r->exists = TRUE;
} else
@@ -4901,10 +4989,10 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is,
}
camel_folder_summary_save_to_db (s, NULL);
- imapx_update_store_summary (job->folder);
+ imapx_update_store_summary (folder);
if (camel_folder_change_info_changed (data->changes))
- camel_folder_changed (job->folder, data->changes);
+ camel_folder_changed (folder, data->changes);
camel_folder_change_info_clear (data->changes);
camel_folder_summary_free_array (uids);
@@ -4916,13 +5004,15 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is,
camel_operation_push_message (
cancellable,
_("Fetching summary information for new messages in '%s'"),
- camel_folder_get_display_name (job->folder));
+ camel_folder_get_display_name (folder));
imapx_uidset_init (&data->uidset, uidset_size, 0);
/* These are new messages which arrived since we last knew the unseen count;
* update it as they arrive. */
data->update_unseen = TRUE;
+ g_object_unref (folder);
+
return imapx_command_step_fetch_done (
is, ic, cancellable, error);
}
@@ -4936,7 +5026,10 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is,
* with a STATUS command.
**/
if (!mobile_mode)
- ((CamelIMAPXFolder *) job->folder)->unread_on_server = camel_folder_summary_get_unread_count (job->folder->summary);
+ ((CamelIMAPXFolder *) folder)->unread_on_server =
+ camel_folder_summary_get_unread_count (folder->summary);
+
+ g_object_unref (folder);
imapx_unregister_job (is, job);
camel_imapx_command_unref (ic);
@@ -4950,35 +5043,39 @@ imapx_job_scan_changes_start (CamelIMAPXJob *job,
GCancellable *cancellable,
GError **error)
{
+ CamelFolder *folder;
CamelIMAPXCommand *ic;
RefreshInfoData *data;
CamelIMAPXSettings *settings;
gboolean mobile_mode;
gchar *uid = NULL;
+ data = camel_imapx_job_get_data (job);
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
settings = camel_imapx_server_ref_settings (is);
mobile_mode = camel_imapx_settings_get_mobile_mode (settings);
g_object_unref (settings);
if (mobile_mode)
- uid = imapx_get_uid_from_index (job->folder->summary, 0);
-
- data = camel_imapx_job_get_data (job);
- g_return_val_if_fail (data != NULL, FALSE);
+ uid = imapx_get_uid_from_index (folder->summary, 0);
job->pop_operation_msg = TRUE;
camel_operation_push_message (
cancellable,
_("Scanning for changed messages in '%s'"),
- camel_folder_get_display_name (job->folder));
+ camel_folder_get_display_name (folder));
e (
'E', "Scanning from %s in %s\n", uid ? uid : "start",
- camel_folder_get_full_name (job->folder));
+ camel_folder_get_full_name (folder));
ic = camel_imapx_command_new (
- is, "FETCH", job->folder,
+ is, "FETCH", folder,
"UID FETCH %s:* (UID FLAGS)", uid ? uid : "1");
camel_imapx_command_set_job (ic, job);
ic->complete = imapx_job_scan_changes_done;
@@ -4990,6 +5087,8 @@ imapx_job_scan_changes_start (CamelIMAPXJob *job,
g_free (uid);
+ g_object_unref (folder);
+
return imapx_command_queue (is, ic, cancellable, error);
}
@@ -5002,6 +5101,7 @@ imapx_command_fetch_new_messages_done (CamelIMAPXServer *is,
CamelIMAPXJob *job;
CamelIMAPXSummary *isum;
CamelIMAPXFolder *ifolder;
+ CamelFolder *folder;
RefreshInfoData *data;
gboolean success = TRUE;
@@ -5011,28 +5111,31 @@ imapx_command_fetch_new_messages_done (CamelIMAPXServer *is,
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
- ifolder = (CamelIMAPXFolder *) job->folder;
- isum = (CamelIMAPXSummary *) job->folder->summary;
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
+ ifolder = CAMEL_IMAPX_FOLDER (folder);
+ isum = CAMEL_IMAPX_SUMMARY (folder->summary);
if (camel_imapx_command_set_error_if_failed (ic, error)) {
g_prefix_error (
error, "%s: ",
_("Error fetching new messages"));
success = FALSE;
- goto exception;
+ goto exit;
}
if (camel_folder_change_info_changed (data->changes)) {
- camel_folder_summary_save_to_db (job->folder->summary, NULL);
- imapx_update_store_summary (job->folder);
- camel_folder_changed (job->folder, data->changes);
+ camel_folder_summary_save_to_db (folder->summary, NULL);
+ imapx_update_store_summary (folder);
+ camel_folder_changed (folder, data->changes);
camel_folder_change_info_clear (data->changes);
}
- if (camel_folder_summary_count (job->folder->summary)) {
+ if (camel_folder_summary_count (folder->summary)) {
gchar *uid = imapx_get_uid_from_index (
- job->folder->summary,
- camel_folder_summary_count (job->folder->summary) - 1);
+ folder->summary,
+ camel_folder_summary_count (folder->summary) - 1);
guint64 uidl = strtoull (uid, NULL, 10);
g_free (uid);
@@ -5041,14 +5144,16 @@ imapx_command_fetch_new_messages_done (CamelIMAPXServer *is,
if (uidl > ifolder->uidnext_on_server) {
c (
is->tagprefix, "Updating uidnext_on_server for '%s' to %" G_GUINT64_FORMAT "\n",
- camel_folder_get_full_name (job->folder), uidl);
+ camel_folder_get_full_name (folder), uidl);
ifolder->uidnext_on_server = uidl;
}
}
isum->uidnext = ifolder->uidnext_on_server;
-exception:
+exit:
+ g_object_unref (folder);
+
imapx_unregister_job (is, job);
camel_imapx_command_unref (ic);
@@ -5088,8 +5193,8 @@ imapx_job_fetch_new_messages_start (CamelIMAPXJob *job,
GError **error)
{
CamelIMAPXCommand *ic;
- CamelFolder *folder = job->folder;
- CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) folder;
+ CamelFolder *folder;
+ CamelIMAPXFolder *ifolder;
CamelIMAPXSettings *settings;
CamelSortType fetch_order;
RefreshInfoData *data;
@@ -5100,11 +5205,16 @@ imapx_job_fetch_new_messages_start (CamelIMAPXJob *job,
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
settings = camel_imapx_server_ref_settings (is);
fetch_order = camel_imapx_settings_get_fetch_order (settings);
uidset_size = camel_imapx_settings_get_batch_fetch_count (settings);
g_object_unref (settings);
+ ifolder = CAMEL_IMAPX_FOLDER (folder);
+
total = camel_folder_summary_count (folder->summary);
diff = ifolder->exists_on_server - total;
@@ -5127,7 +5237,7 @@ imapx_job_fetch_new_messages_start (CamelIMAPXJob *job,
//printf ("Fetch order: %d/%d\n", fetch_order, CAMEL_SORT_DESCENDING);
if (diff > uidset_size || fetch_order == CAMEL_SORT_DESCENDING) {
ic = camel_imapx_command_new (
- is, "FETCH", job->folder,
+ is, "FETCH", folder,
"UID FETCH %s:* (UID FLAGS)", uid);
imapx_uidset_init (&data->uidset, uidset_size, 0);
refresh_info_data_infos_free (data);
@@ -5142,7 +5252,7 @@ imapx_job_fetch_new_messages_start (CamelIMAPXJob *job,
ic->complete = imapx_command_step_fetch_done;
} else {
ic = camel_imapx_command_new (
- is, "FETCH", job->folder,
+ is, "FETCH", folder,
"UID FETCH %s:* (RFC822.SIZE RFC822.HEADER FLAGS)", uid);
ic->pri = job->pri;
ic->complete = imapx_command_fetch_new_messages_done;
@@ -5152,6 +5262,8 @@ imapx_job_fetch_new_messages_start (CamelIMAPXJob *job,
camel_imapx_command_set_job (ic, job);
+ g_object_unref (folder);
+
return imapx_command_queue (is, ic, cancellable, error);
}
@@ -5162,7 +5274,7 @@ imapx_job_fetch_messages_start (CamelIMAPXJob *job,
GError **error)
{
CamelIMAPXCommand *ic;
- CamelFolder *folder = job->folder;
+ CamelFolder *folder;
guint32 total;
gchar *start_uid = NULL, *end_uid = NULL;
CamelFetchType ftype;
@@ -5175,6 +5287,9 @@ imapx_job_fetch_messages_start (CamelIMAPXJob *job,
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
settings = camel_imapx_server_ref_settings (is);
fetch_order = camel_imapx_settings_get_fetch_order (settings);
uidset_size = camel_imapx_settings_get_batch_fetch_count (settings);
@@ -5219,6 +5334,7 @@ imapx_job_fetch_messages_start (CamelIMAPXJob *job,
g_prefix_error (
error, "%s: ",
_("Error while fetching messages"));
+ g_object_unref (folder);
return FALSE;
}
}
@@ -5233,7 +5349,7 @@ imapx_job_fetch_messages_start (CamelIMAPXJob *job,
/* New account and fetching old messages, we would return just the limited number of newest messages */
ic = camel_imapx_command_new (
- is, "FETCH", job->folder,
+ is, "FETCH", folder,
"UID FETCH %s:* (UID FLAGS)", uid);
imapx_uidset_init (&data->uidset, uidset_size, 0);
@@ -5265,7 +5381,7 @@ imapx_job_fetch_messages_start (CamelIMAPXJob *job,
camel_folder_get_display_name (folder));
ic = camel_imapx_command_new (
- is, "FETCH", job->folder,
+ is, "FETCH", folder,
"UID FETCH %s:%s (RFC822.SIZE RFC822.HEADER FLAGS)", start_uid, end_uid);
ic->pri = job->pri;
ic->complete = imapx_command_fetch_new_messages_done;
@@ -5279,6 +5395,8 @@ imapx_job_fetch_messages_start (CamelIMAPXJob *job,
camel_imapx_command_set_job (ic, job);
+ g_object_unref (folder);
+
return imapx_command_queue (is, ic, cancellable, error);
}
@@ -5288,22 +5406,28 @@ imapx_job_refresh_info_start (CamelIMAPXJob *job,
GCancellable *cancellable,
GError **error)
{
- guint32 total;
- CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) job->folder;
- CamelIMAPXSummary *isum = (CamelIMAPXSummary *) job->folder->summary;
- CamelFolder *folder = job->folder;
+ CamelIMAPXFolder *ifolder;
+ CamelIMAPXSettings *settings;
+ CamelIMAPXSummary *isum;
+ CamelFolder *folder;
const gchar *full_name;
gboolean need_rescan = FALSE;
gboolean is_selected = FALSE;
gboolean can_qresync = FALSE;
- CamelIMAPXSettings *settings;
gboolean mobile_mode;
gboolean success;
+ guint32 total;
+
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
settings = camel_imapx_server_ref_settings (is);
mobile_mode = camel_imapx_settings_get_mobile_mode (settings);
g_object_unref (settings);
+ ifolder = CAMEL_IMAPX_FOLDER (folder);
+ isum = CAMEL_IMAPX_SUMMARY (folder->summary);
+
full_name = camel_folder_get_full_name (folder);
/* Sync changes first, else unread count will not
@@ -5460,7 +5584,7 @@ imapx_job_refresh_info_start (CamelIMAPXJob *job,
goto done;
qresync_done:
isum->modseq = ifolder->modseq_on_server;
- total = camel_folder_summary_count (job->folder->summary);
+ total = camel_folder_summary_count (folder->summary);
if (total != ifolder->exists_on_server ||
camel_folder_summary_get_unread_count (folder->summary) != ifolder->unread_on_server ||
(isum->modseq != ifolder->modseq_on_server)) {
@@ -5479,9 +5603,13 @@ imapx_job_refresh_info_start (CamelIMAPXJob *job,
}
}
+ g_object_unref (folder);
+
return imapx_job_scan_changes_start (job, is, cancellable, error);
done:
+ g_object_unref (folder);
+
imapx_unregister_job (is, job);
return success;
@@ -5492,7 +5620,7 @@ imapx_job_refresh_info_matches (CamelIMAPXJob *job,
CamelFolder *folder,
const gchar *uid)
{
- return (folder == job->folder);
+ return camel_imapx_job_has_folder (job, folder);
}
/* ********************************************************************** */
@@ -5504,11 +5632,15 @@ imapx_command_expunge_done (CamelIMAPXServer *is,
GError **error)
{
CamelIMAPXJob *job;
+ CamelFolder *folder;
gboolean success = TRUE;
job = camel_imapx_command_get_job (ic);
g_return_val_if_fail (CAMEL_IS_IMAPX_JOB (job), FALSE);
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
if (camel_imapx_command_set_error_if_failed (ic, error)) {
g_prefix_error (
error, "%s: ",
@@ -5517,7 +5649,6 @@ imapx_command_expunge_done (CamelIMAPXServer *is,
} else {
GPtrArray *uids;
- CamelFolder *folder = job->folder;
CamelStore *parent_store;
const gchar *full_name;
@@ -5559,6 +5690,8 @@ imapx_command_expunge_done (CamelIMAPXServer *is,
}
}
+ g_object_unref (folder);
+
imapx_unregister_job (is, job);
camel_imapx_command_unref (ic);
@@ -5572,15 +5705,19 @@ imapx_job_expunge_start (CamelIMAPXJob *job,
GError **error)
{
CamelIMAPXCommand *ic;
+ CamelFolder *folder;
gboolean success;
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
success = imapx_server_sync_changes (
- is, job->folder, job->type, job->pri, cancellable, error);
+ is, folder, job->type, job->pri, cancellable, error);
if (success) {
/* TODO handle UIDPLUS capability */
ic = camel_imapx_command_new (
- is, "EXPUNGE", job->folder, "EXPUNGE");
+ is, "EXPUNGE", folder, "EXPUNGE");
camel_imapx_command_set_job (ic, job);
ic->pri = job->pri;
ic->complete = imapx_command_expunge_done;
@@ -5588,6 +5725,8 @@ imapx_job_expunge_start (CamelIMAPXJob *job,
success = imapx_command_queue (is, ic, cancellable, error);
}
+ g_object_unref (folder);
+
return success;
}
@@ -5596,7 +5735,7 @@ imapx_job_expunge_matches (CamelIMAPXJob *job,
CamelFolder *folder,
const gchar *uid)
{
- return (folder == job->folder);
+ return camel_imapx_job_has_folder (job, folder);
}
/* ********************************************************************** */
@@ -5835,6 +5974,7 @@ imapx_job_delete_folder_start (CamelIMAPXJob *job,
{
CamelIMAPXCommand *ic;
CamelIMAPXStore *store;
+ CamelFolder *folder;
DeleteFolderData *data;
gchar *encoded_fname = NULL;
gboolean success = FALSE;
@@ -5846,20 +5986,24 @@ imapx_job_delete_folder_start (CamelIMAPXJob *job,
encoded_fname = imapx_encode_folder_name (store, data->folder_name);
- job->folder = camel_store_get_folder_sync (
+ folder = camel_store_get_folder_sync (
CAMEL_STORE (store), "INBOX", 0, cancellable, error);
- if (job->folder != NULL) {
+ if (folder != NULL) {
+ camel_imapx_job_set_folder (job, folder);
+
/* Make sure the to-be-deleted folder is not
* selected by selecting INBOX for this operation. */
ic = camel_imapx_command_new (
- is, "DELETE", job->folder,
+ is, "DELETE", folder,
"DELETE %s", encoded_fname);
ic->pri = job->pri;
camel_imapx_command_set_job (ic, job);
ic->complete = imapx_command_delete_folder_done;
success = imapx_command_queue (is, ic, cancellable, error);
+
+ g_object_unref (folder);
}
g_free (encoded_fname);
@@ -5905,7 +6049,9 @@ imapx_job_rename_folder_start (CamelIMAPXJob *job,
CamelIMAPXCommand *ic;
CamelIMAPXStore *store;
RenameFolderData *data;
- gchar *en_ofname = NULL, *en_nfname = NULL;
+ CamelFolder *folder;
+ gchar *en_ofname = NULL;
+ gchar *en_nfname = NULL;
gboolean success = FALSE;
data = camel_imapx_job_get_data (job);
@@ -5916,18 +6062,22 @@ imapx_job_rename_folder_start (CamelIMAPXJob *job,
en_ofname = imapx_encode_folder_name (store, data->old_folder_name);
en_nfname = imapx_encode_folder_name (store, data->new_folder_name);
- job->folder = camel_store_get_folder_sync (
+ folder = camel_store_get_folder_sync (
CAMEL_STORE (store), "INBOX", 0, cancellable, error);
- if (job->folder != NULL) {
+ if (folder != NULL) {
+ camel_imapx_job_set_folder (job, folder);
+
ic = camel_imapx_command_new (
- is, "RENAME", job->folder,
+ is, "RENAME", folder,
"RENAME %s %s", en_ofname, en_nfname);
ic->pri = job->pri;
camel_imapx_command_set_job (ic, job);
ic->complete = imapx_command_rename_folder_done;
success = imapx_command_queue (is, ic, cancellable, error);
+
+ g_object_unref (folder);
}
g_free (en_ofname);
@@ -6035,16 +6185,21 @@ imapx_job_noop_start (CamelIMAPXJob *job,
GError **error)
{
CamelIMAPXCommand *ic;
+ CamelFolder *folder;
+
+ folder = camel_imapx_job_ref_folder (job);
ic = camel_imapx_command_new (
- is, "NOOP", job->folder, "NOOP");
+ is, "NOOP", folder, "NOOP");
camel_imapx_command_set_job (ic, job);
ic->complete = imapx_command_noop_done;
- if (job->folder)
+ if (folder != NULL) {
ic->pri = IMAPX_PRIORITY_REFRESH_INFO;
- else
+ g_object_unref (folder);
+ } else {
ic->pri = IMAPX_PRIORITY_NOOP;
+ }
return imapx_command_queue (is, ic, cancellable, error);
}
@@ -6083,6 +6238,7 @@ imapx_command_sync_changes_done (CamelIMAPXServer *is,
GError **error)
{
CamelIMAPXJob *job;
+ CamelFolder *folder;
CamelStore *parent_store;
SyncChangesData *data;
const gchar *full_name;
@@ -6096,14 +6252,17 @@ imapx_command_sync_changes_done (CamelIMAPXServer *is,
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
settings = camel_imapx_server_ref_settings (is);
mobile_mode = camel_imapx_settings_get_mobile_mode (settings);
g_object_unref (settings);
job->commands--;
- full_name = camel_folder_get_full_name (job->folder);
- parent_store = camel_folder_get_parent_store (job->folder);
+ full_name = camel_folder_get_full_name (folder);
+ parent_store = camel_folder_get_parent_store (folder);
/* If this worked, we should really just update the changes that we
* sucessfully stored, so we dont have to worry about sending them
@@ -6126,7 +6285,7 @@ imapx_command_sync_changes_done (CamelIMAPXServer *is,
gint i;
for (i = 0; i < data->changed_uids->len; i++) {
- CamelIMAPXMessageInfo *xinfo = (CamelIMAPXMessageInfo *) camel_folder_summary_get (job->folder->summary,
+ CamelIMAPXMessageInfo *xinfo = (CamelIMAPXMessageInfo *) camel_folder_summary_get (folder->summary,
data->changed_uids->pdata[i]);
if (!xinfo)
@@ -6139,26 +6298,26 @@ imapx_command_sync_changes_done (CamelIMAPXServer *is,
xinfo->info.dirty = TRUE;
camel_flag_list_copy (&xinfo->server_user_flags, &xinfo->info.user_flags);
- camel_folder_summary_touch (job->folder->summary);
+ camel_folder_summary_touch (folder->summary);
camel_message_info_free (xinfo);
}
/* Apply the changes to server-side unread count; it won't tell
* us of these changes, of course. */
- ((CamelIMAPXFolder *) job->folder)->unread_on_server += data->unread_change;
+ ((CamelIMAPXFolder *) folder)->unread_on_server += data->unread_change;
}
if (job->commands == 0) {
- if (job->folder->summary && (job->folder->summary->flags & CAMEL_FOLDER_SUMMARY_DIRTY) != 0) {
+ if (folder->summary && (folder->summary->flags & CAMEL_FOLDER_SUMMARY_DIRTY) != 0) {
CamelStoreInfo *si;
/* ... and store's summary when folder's summary is dirty */
si = camel_store_summary_path ((CamelStoreSummary *)((CamelIMAPXStore *) parent_store)->summary, full_name);
if (si) {
- if (si->total != camel_folder_summary_get_saved_count (job->folder->summary) ||
- si->unread != camel_folder_summary_get_unread_count (job->folder->summary)) {
- si->total = camel_folder_summary_get_saved_count (job->folder->summary);
+ if (si->total != camel_folder_summary_get_saved_count (folder->summary) ||
+ si->unread != camel_folder_summary_get_unread_count (folder->summary)) {
+ si->total = camel_folder_summary_get_saved_count (folder->summary);
if (!mobile_mode) /* Don't mess with server's unread count in mobile mode, as what we have downloaded is little */
- si->unread = camel_folder_summary_get_unread_count (job->folder->summary);
+ si->unread = camel_folder_summary_get_unread_count (folder->summary);
camel_store_summary_touch ((CamelStoreSummary *)((CamelIMAPXStore *) parent_store)->summary);
}
@@ -6166,12 +6325,14 @@ imapx_command_sync_changes_done (CamelIMAPXServer *is,
}
}
- camel_folder_summary_save_to_db (job->folder->summary, error);
+ camel_folder_summary_save_to_db (folder->summary, error);
camel_store_summary_save ((CamelStoreSummary *)((CamelIMAPXStore *) parent_store)->summary);
imapx_unregister_job (is, job);
}
+ g_object_unref (folder);
+
camel_imapx_command_unref (ic);
return success;
@@ -6184,6 +6345,7 @@ imapx_job_sync_changes_start (CamelIMAPXJob *job,
GError **error)
{
SyncChangesData *data;
+ CamelFolder *folder;
guint32 i, j;
struct _uidset_state ss;
GPtrArray *uids;
@@ -6192,6 +6354,9 @@ imapx_job_sync_changes_start (CamelIMAPXJob *job,
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
+ folder = camel_imapx_job_ref_folder (job);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
uids = data->changed_uids;
for (on = 0; on < 2; on++) {
@@ -6216,7 +6381,7 @@ imapx_job_sync_changes_start (CamelIMAPXJob *job,
info = (CamelIMAPXMessageInfo *)
camel_folder_summary_get (
- job->folder->summary,
+ folder->summary,
uids->pdata[i]);
if (info == NULL)
@@ -6241,7 +6406,7 @@ imapx_job_sync_changes_start (CamelIMAPXJob *job,
|| (!on && (((flags ^ sflags) & ~flags) & flag))) {
if (ic == NULL) {
ic = camel_imapx_command_new (
- is, "STORE", job->folder,
+ is, "STORE", folder,
"UID STORE ");
ic->complete = imapx_command_sync_changes_done;
camel_imapx_command_set_job (ic, job);
@@ -6282,7 +6447,7 @@ imapx_job_sync_changes_start (CamelIMAPXJob *job,
if (ic == NULL) {
ic = camel_imapx_command_new (
- is, "STORE", job->folder,
+ is, "STORE", folder,
"UID STORE ");
ic->complete = imapx_command_sync_changes_done;
camel_imapx_command_set_job (ic, job);
@@ -6303,12 +6468,13 @@ imapx_job_sync_changes_start (CamelIMAPXJob *job,
}
exit:
+ g_object_unref (folder);
+
/* Since this may start in another thread ... we need to
* lock the commands count, ho hum */
- if (job->commands == 0) {
+ if (job->commands == 0)
imapx_unregister_job (is, job);
- }
return TRUE;
}
@@ -6318,7 +6484,7 @@ imapx_job_sync_changes_matches (CamelIMAPXJob *job,
CamelFolder *folder,
const gchar *uid)
{
- return (folder == job->folder);
+ return camel_imapx_job_has_folder (job, folder);
}
/* we cancel all the commands and their jobs, so associated jobs will be notified */
@@ -6933,7 +7099,8 @@ imapx_server_get_message (CamelIMAPXServer *is,
job->type = IMAPX_JOB_GET_MESSAGE;
job->start = imapx_job_get_message_start;
job->matches = imapx_job_get_message_matches;
- job->folder = folder;
+
+ camel_imapx_job_set_folder (job, folder);
camel_imapx_job_set_data (
job, data, (GDestroyNotify) get_message_data_free);
@@ -7035,7 +7202,8 @@ camel_imapx_server_copy_message (CamelIMAPXServer *is,
job->pri = IMAPX_PRIORITY_APPEND_MESSAGE;
job->type = IMAPX_JOB_COPY_MESSAGE;
job->start = imapx_job_copy_messages_start;
- job->folder = g_object_ref (source);
+
+ camel_imapx_job_set_folder (job, source);
camel_imapx_job_set_data (
job, data, (GDestroyNotify) copy_messages_data_free);
@@ -7062,10 +7230,11 @@ camel_imapx_server_append_message (CamelIMAPXServer *is,
gint res;
gboolean success;
- /* Append just assumes we have no/a dodgy connection. We dump stuff into the 'new'
- * directory, and let the summary know it's there. Then we fire off a no-reply
- * job which will asynchronously upload the message at some point in the future,
- * and fix up the summary to match */
+ /* Append just assumes we have no/a dodgy connection. We dump
+ * stuff into the 'new' directory, and let the summary know it's
+ * there. Then we fire off a no-reply job which will asynchronously
+ * upload the message at some point in the future, and fix up the
+ * summary to match */
/* chen cleanup this later */
uid = imapx_get_temp_uid ();
@@ -7137,15 +7306,16 @@ camel_imapx_server_append_message (CamelIMAPXServer *is,
job->pri = IMAPX_PRIORITY_APPEND_MESSAGE;
job->type = IMAPX_JOB_APPEND_MESSAGE;
job->start = imapx_job_append_message_start;
- job->folder = g_object_ref (folder);
job->noreply = FALSE;
+ camel_imapx_job_set_folder (job, folder);
+
camel_imapx_job_set_data (
job, data, (GDestroyNotify) append_message_data_free);
success = imapx_submit_job (is, job, error);
- if (appended_uid) {
+ if (appended_uid != NULL) {
*appended_uid = data->appended_uid;
data->appended_uid = NULL;
}
@@ -7167,9 +7337,10 @@ camel_imapx_server_noop (CamelIMAPXServer *is,
job = camel_imapx_job_new (cancellable);
job->type = IMAPX_JOB_NOOP;
job->start = imapx_job_noop_start;
- job->folder = folder;
job->pri = IMAPX_PRIORITY_NOOP;
+ camel_imapx_job_set_folder (job, folder);
+
success = imapx_submit_job (is, job, error);
camel_imapx_job_unref (job);
@@ -7207,9 +7378,10 @@ camel_imapx_server_refresh_info (CamelIMAPXServer *is,
job->type = IMAPX_JOB_REFRESH_INFO;
job->start = imapx_job_refresh_info_start;
job->matches = imapx_job_refresh_info_matches;
- job->folder = folder;
job->pri = IMAPX_PRIORITY_REFRESH_INFO;
+ camel_imapx_job_set_folder (job, folder);
+
if (g_ascii_strcasecmp (full_name, "INBOX") == 0)
job->pri += 10;
@@ -7449,7 +7621,8 @@ imapx_server_sync_changes (CamelIMAPXServer *is,
job->start = imapx_job_sync_changes_start;
job->matches = imapx_job_sync_changes_matches;
job->pri = pri;
- job->folder = folder;
+
+ camel_imapx_job_set_folder (job, folder);
camel_imapx_job_set_data (
job, data, (GDestroyNotify) sync_changes_data_free);
@@ -7502,7 +7675,8 @@ camel_imapx_server_expunge (CamelIMAPXServer *is,
job->start = imapx_job_expunge_start;
job->matches = imapx_job_expunge_matches;
job->pri = IMAPX_PRIORITY_EXPUNGE;
- job->folder = folder;
+
+ camel_imapx_job_set_folder (job, folder);
registered = imapx_register_job (is, job, error);
@@ -7695,10 +7869,10 @@ camel_imapx_server_delete_folder (CamelIMAPXServer *is,
static gboolean
imapx_job_fetch_messages_matches (CamelIMAPXJob *job,
- CamelFolder *folder,
- const gchar *uid)
+ CamelFolder *folder,
+ const gchar *uid)
{
- return (folder == job->folder);
+ return camel_imapx_job_has_folder (job, folder);
}
gboolean
@@ -7741,9 +7915,10 @@ camel_imapx_server_fetch_messages (CamelIMAPXServer *is,
job->type = IMAPX_JOB_FETCH_MESSAGES;
job->start = imapx_job_fetch_messages_start;
job->matches = imapx_job_fetch_messages_matches;
- job->folder = folder;
job->pri = IMAPX_PRIORITY_NEW_MESSAGES;
+ camel_imapx_job_set_folder (job, folder);
+
full_name = camel_folder_get_full_name (folder);
if (g_ascii_strcasecmp (full_name, "INBOX") == 0)
@@ -7854,21 +8029,36 @@ camel_imapx_server_get_job_queue_info (CamelIMAPXServer *is)
QUEUE_LOCK (is);
jinfo->queue_len = g_queue_get_length (&is->jobs);
- jinfo->folders = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
+ jinfo->folders = g_hash_table_new_full (
+ (GHashFunc) g_str_hash,
+ (GEqualFunc) g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) NULL);
head = g_queue_peek_head_link (&is->jobs);
for (link = head; link != NULL; link = g_list_next (link)) {
+ CamelFolder *folder;
+
job = (CamelIMAPXJob *) link->data;
+ folder = camel_imapx_job_ref_folder (job);
+
+ if (folder != NULL) {
+ gchar *folder_name;
+
+ folder_name = camel_folder_dup_full_name (folder);
+ g_hash_table_add (jinfo->folders, folder_name);
- if (job->folder) {
- const gchar *full_name = camel_folder_get_full_name (job->folder);
- g_hash_table_insert (jinfo->folders, g_strdup (full_name), GINT_TO_POINTER (1));
+ g_object_unref (folder);
}
}
- if (is->select_folder)
- g_hash_table_insert (jinfo->folders, g_strdup (camel_folder_get_full_name (is->select_folder)), GINT_TO_POINTER (1));
+ if (is->select_folder != NULL) {
+ gchar *folder_name;
+
+ folder_name = camel_folder_dup_full_name (is->select_folder);
+ g_hash_table_add (jinfo->folders, folder_name);
+ }
QUEUE_UNLOCK (is);
diff --git a/docs/reference/camel/camel-sections.txt b/docs/reference/camel/camel-sections.txt
index dceb598..26083c9 100644
--- a/docs/reference/camel/camel-sections.txt
+++ b/docs/reference/camel/camel-sections.txt
@@ -830,6 +830,9 @@ camel_imapx_job_run
camel_imapx_job_matches
camel_imapx_job_get_data
camel_imapx_job_set_data
+camel_imapx_job_has_folder
+camel_imapx_job_ref_folder
+camel_imapx_job_set_folder
<SUBSECTION Private>
uidset_state
</SECTION>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]