1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* camel-imap-folder.c : class for a imap folder */
4 * Authors: Michael Zucchi <notzed@ximian.com>
6 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
8 * This library is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation.
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, see <http://www.gnu.org/licenses/>.
26 #include <glib/gi18n-lib.h>
28 #include "camel-imapx-folder.h"
29 #include "camel-imapx-search.h"
30 #include "camel-imapx-server.h"
31 #include "camel-imapx-settings.h"
32 #include "camel-imapx-store.h"
33 #include "camel-imapx-summary.h"
34 #include "camel-imapx-utils.h"
39 #define d(...) camel_imapx_debug(debug, '?', __VA_ARGS__)
41 #define CAMEL_IMAPX_FOLDER_GET_PRIVATE(obj) \
42 (G_TYPE_INSTANCE_GET_PRIVATE \
43 ((obj), CAMEL_TYPE_IMAPX_FOLDER, CamelIMAPXFolderPrivate))
45 struct _CamelIMAPXFolderPrivate {
49 GMutex move_to_hash_table_lock;
50 GHashTable *move_to_real_junk_uids;
51 GHashTable *move_to_real_trash_uids;
54 /* The custom property ID is a CamelArg artifact.
55 * It still identifies the property in state files. */
59 PROP_APPLY_FILTERS = 0x2501
62 G_DEFINE_TYPE (CamelIMAPXFolder, camel_imapx_folder, CAMEL_TYPE_OFFLINE_FOLDER)
64 static gboolean imapx_folder_get_apply_filters (CamelIMAPXFolder *folder);
67 imapx_folder_claim_move_to_real_junk_uids (CamelIMAPXFolder *folder,
68 GPtrArray *out_uids_to_copy)
72 g_mutex_lock (&folder->priv->move_to_hash_table_lock);
74 keys = g_hash_table_get_keys (folder->priv->move_to_real_junk_uids);
75 g_hash_table_steal_all (folder->priv->move_to_real_junk_uids);
77 g_mutex_unlock (&folder->priv->move_to_hash_table_lock);
79 while (keys != NULL) {
80 g_ptr_array_add (out_uids_to_copy, keys->data);
81 keys = g_list_delete_link (keys, keys);
86 imapx_folder_claim_move_to_real_trash_uids (CamelIMAPXFolder *folder,
87 GPtrArray *out_uids_to_copy)
91 g_mutex_lock (&folder->priv->move_to_hash_table_lock);
93 keys = g_hash_table_get_keys (folder->priv->move_to_real_trash_uids);
94 g_hash_table_steal_all (folder->priv->move_to_real_trash_uids);
96 g_mutex_unlock (&folder->priv->move_to_hash_table_lock);
98 while (keys != NULL) {
99 g_ptr_array_add (out_uids_to_copy, keys->data);
100 keys = g_list_delete_link (keys, keys);
105 imapx_folder_get_apply_filters (CamelIMAPXFolder *folder)
107 g_return_val_if_fail (folder != NULL, FALSE);
108 g_return_val_if_fail (CAMEL_IS_IMAPX_FOLDER (folder), FALSE);
110 return folder->apply_filters;
114 imapx_folder_set_apply_filters (CamelIMAPXFolder *folder,
115 gboolean apply_filters)
117 g_return_if_fail (folder != NULL);
118 g_return_if_fail (CAMEL_IS_IMAPX_FOLDER (folder));
120 if (folder->apply_filters == apply_filters)
123 folder->apply_filters = apply_filters;
125 g_object_notify (G_OBJECT (folder), "apply-filters");
129 imapx_folder_set_property (GObject *object,
134 switch (property_id) {
135 case PROP_APPLY_FILTERS:
136 imapx_folder_set_apply_filters (
137 CAMEL_IMAPX_FOLDER (object),
138 g_value_get_boolean (value));
142 camel_imapx_folder_set_mailbox (
143 CAMEL_IMAPX_FOLDER (object),
144 g_value_get_object (value));
148 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
152 imapx_folder_get_property (GObject *object,
157 switch (property_id) {
158 case PROP_APPLY_FILTERS:
159 g_value_set_boolean (
161 imapx_folder_get_apply_filters (
162 CAMEL_IMAPX_FOLDER (object)));
166 g_value_take_object (
168 camel_imapx_folder_ref_mailbox (
169 CAMEL_IMAPX_FOLDER (object)));
173 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
177 imapx_folder_dispose (GObject *object)
179 CamelIMAPXFolder *folder = CAMEL_IMAPX_FOLDER (object);
182 if (folder->cache != NULL) {
183 g_object_unref (folder->cache);
184 folder->cache = NULL;
187 if (folder->search != NULL) {
188 g_object_unref (folder->search);
189 folder->search = NULL;
192 store = camel_folder_get_parent_store (CAMEL_FOLDER (folder));
194 camel_store_summary_disconnect_folder_summary (
195 CAMEL_IMAPX_STORE (store)->summary,
196 CAMEL_FOLDER (folder)->summary);
199 g_weak_ref_set (&folder->priv->mailbox, NULL);
201 /* Chain up to parent's dispose() method. */
202 G_OBJECT_CLASS (camel_imapx_folder_parent_class)->dispose (object);
206 imapx_folder_finalize (GObject *object)
208 CamelIMAPXFolder *folder = CAMEL_IMAPX_FOLDER (object);
210 g_mutex_clear (&folder->search_lock);
211 g_mutex_clear (&folder->stream_lock);
213 g_mutex_clear (&folder->priv->property_lock);
215 g_mutex_clear (&folder->priv->move_to_hash_table_lock);
216 g_hash_table_destroy (folder->priv->move_to_real_junk_uids);
217 g_hash_table_destroy (folder->priv->move_to_real_trash_uids);
219 /* Chain up to parent's finalize() method. */
220 G_OBJECT_CLASS (camel_imapx_folder_parent_class)->finalize (object);
223 /* Algorithm for selecting a folder:
225 * - If uidvalidity == old uidvalidity
226 * and exsists == old exists
227 * and recent == old recent
228 * and unseen == old unseen
229 * Assume our summary is correct
230 * for each summary item
231 * mark the summary item as 'old/not updated'
233 * fetch flags from 1:*
234 * for each fetch response
235 * info = summary[index]
237 * info = summary_by_uid[uid]
240 * create new info @ index
246 * update based on header
249 * update based on imap body
253 * Async fetch response:
254 * info = summary[index]
257 * force resync/select?
258 * info = empty @ index
259 * else if uid && info.uid != uid
272 * info.state - 2 bit field in flags
273 * 0 = empty, nothing set
274 * 1 = uid & flags set
275 * 2 = update required
280 imapx_search_free (CamelFolder *folder,
283 CamelIMAPXFolder *imapx_folder;
285 imapx_folder = CAMEL_IMAPX_FOLDER (folder);
287 g_return_if_fail (imapx_folder->search);
289 g_mutex_lock (&imapx_folder->search_lock);
291 camel_folder_search_free_result (imapx_folder->search, uids);
293 g_mutex_unlock (&imapx_folder->search_lock);
297 imapx_search_by_uids (CamelFolder *folder,
298 const gchar *expression,
300 GCancellable *cancellable,
303 CamelIMAPXStore *imapx_store;
304 CamelIMAPXFolder *imapx_folder;
305 CamelIMAPXSearch *imapx_search;
306 CamelIMAPXServer *imapx_server = NULL;
307 const gchar *folder_name;
312 return g_ptr_array_new ();
314 imapx_folder = CAMEL_IMAPX_FOLDER (folder);
315 store = camel_folder_get_parent_store (folder);
316 folder_name = camel_folder_get_full_name (folder);
318 imapx_store = CAMEL_IMAPX_STORE (store);
319 if (camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store)))
320 imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, NULL);
322 g_mutex_lock (&imapx_folder->search_lock);
324 imapx_search = CAMEL_IMAPX_SEARCH (imapx_folder->search);
325 camel_imapx_search_set_server (imapx_search, imapx_server);
327 camel_folder_search_set_folder (imapx_folder->search, folder);
329 matches = camel_folder_search_search (
330 imapx_folder->search, expression, uids, cancellable, error);
332 camel_imapx_search_set_server (imapx_search, NULL);
335 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
337 g_mutex_unlock (&imapx_folder->search_lock);
339 g_clear_object (&imapx_server);
345 imapx_count_by_expression (CamelFolder *folder,
346 const gchar *expression,
347 GCancellable *cancellable,
350 CamelIMAPXStore *imapx_store;
351 CamelIMAPXFolder *imapx_folder;
352 CamelIMAPXSearch *imapx_search;
353 CamelIMAPXServer *imapx_server = NULL;
354 const gchar *folder_name;
358 imapx_folder = CAMEL_IMAPX_FOLDER (folder);
359 store = camel_folder_get_parent_store (folder);
360 folder_name = camel_folder_get_full_name (folder);
362 imapx_store = CAMEL_IMAPX_STORE (store);
363 if (camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store)))
364 imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, NULL);
366 g_mutex_lock (&imapx_folder->search_lock);
368 imapx_search = CAMEL_IMAPX_SEARCH (imapx_folder->search);
369 camel_imapx_search_set_server (imapx_search, imapx_server);
371 camel_folder_search_set_folder (imapx_folder->search, folder);
373 matches = camel_folder_search_count (
374 imapx_folder->search, expression, cancellable, error);
376 camel_imapx_search_set_server (imapx_search, NULL);
379 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
381 g_mutex_unlock (&imapx_folder->search_lock);
383 g_clear_object (&imapx_server);
389 imapx_search_by_expression (CamelFolder *folder,
390 const gchar *expression,
391 GCancellable *cancellable,
394 CamelIMAPXStore *imapx_store;
395 CamelIMAPXFolder *imapx_folder;
396 CamelIMAPXSearch *imapx_search;
397 CamelIMAPXServer *imapx_server = NULL;
398 const gchar *folder_name;
402 imapx_folder = CAMEL_IMAPX_FOLDER (folder);
403 store = camel_folder_get_parent_store (folder);
404 folder_name = camel_folder_get_full_name (folder);
406 imapx_store = CAMEL_IMAPX_STORE (store);
407 if (camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store)))
408 imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, NULL);
410 g_mutex_lock (&imapx_folder->search_lock);
412 imapx_search = CAMEL_IMAPX_SEARCH (imapx_folder->search);
413 camel_imapx_search_set_server (imapx_search, imapx_server);
415 camel_folder_search_set_folder (imapx_folder->search, folder);
417 matches = camel_folder_search_search (
418 imapx_folder->search, expression, NULL, cancellable, error);
420 camel_imapx_search_set_server (imapx_search, NULL);
423 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
425 g_mutex_unlock (&imapx_folder->search_lock);
427 g_clear_object (&imapx_server);
433 imapx_get_filename (CamelFolder *folder,
437 CamelIMAPXFolder *imapx_folder;
439 imapx_folder = CAMEL_IMAPX_FOLDER (folder);
441 return camel_data_cache_get_filename (
442 imapx_folder->cache, "cache", uid);
446 imapx_append_message_sync (CamelFolder *folder,
447 CamelMimeMessage *message,
448 CamelMessageInfo *info,
449 gchar **appended_uid,
450 GCancellable *cancellable,
454 CamelIMAPXStore *imapx_store;
455 CamelIMAPXServer *imapx_server;
456 CamelIMAPXMailbox *mailbox = NULL;
457 const gchar *folder_name;
458 gboolean success = FALSE;
460 if (appended_uid != NULL)
461 *appended_uid = NULL;
463 store = camel_folder_get_parent_store (folder);
464 folder_name = camel_folder_get_full_name (folder);
466 imapx_store = CAMEL_IMAPX_STORE (store);
467 imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, error);
469 if (imapx_server == NULL)
472 mailbox = camel_imapx_folder_list_mailbox (
473 CAMEL_IMAPX_FOLDER (folder), cancellable, error);
475 if (mailbox == NULL) {
476 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
480 success = camel_imapx_server_append_message (
481 imapx_server, mailbox, folder->summary,
482 CAMEL_IMAPX_FOLDER (folder)->cache, message,
483 info, appended_uid, cancellable, error);
485 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
488 g_clear_object (&mailbox);
489 g_clear_object (&imapx_server);
495 imapx_expunge_sync (CamelFolder *folder,
496 GCancellable *cancellable,
500 CamelIMAPXStore *imapx_store;
501 CamelIMAPXServer *imapx_server;
502 CamelIMAPXMailbox *mailbox = NULL;
503 const gchar *folder_name;
504 gboolean success = FALSE;
506 store = camel_folder_get_parent_store (folder);
507 folder_name = camel_folder_get_full_name (folder);
509 imapx_store = CAMEL_IMAPX_STORE (store);
510 imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, error);
512 if (imapx_server == NULL)
515 mailbox = camel_imapx_folder_list_mailbox (
516 CAMEL_IMAPX_FOLDER (folder), cancellable, error);
518 if (mailbox == NULL) {
519 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
523 if ((store->flags & CAMEL_STORE_VTRASH) == 0) {
525 const gchar *full_name;
526 GError *local_error = NULL;
528 full_name = camel_folder_get_full_name (folder);
530 trash = camel_store_get_trash_folder_sync (store, cancellable, &local_error);
532 if (local_error == NULL && trash && (folder == trash || g_ascii_strcasecmp (full_name, camel_folder_get_full_name (trash)) == 0)) {
533 CamelMessageInfo *info;
534 GPtrArray *known_uids;
537 camel_folder_summary_prepare_fetch_all (folder->summary, NULL);
538 known_uids = camel_folder_summary_get_array (folder->summary);
540 /* it's a real trash folder, thus delete all mails from there */
541 for (ii = 0; known_uids && ii < known_uids->len; ii++) {
542 info = camel_folder_summary_get (folder->summary, g_ptr_array_index (known_uids, ii));
544 camel_message_info_set_flags (info, CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_DELETED);
545 camel_message_info_unref (info);
549 camel_folder_summary_free_array (known_uids);
552 g_clear_object (&trash);
553 g_clear_error (&local_error);
556 success = camel_imapx_server_expunge (
557 imapx_server, mailbox, cancellable, error);
559 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
562 g_clear_object (&mailbox);
563 g_clear_object (&imapx_server);
568 static CamelMimeMessage *
569 imapx_get_message_cached (CamelFolder *folder,
570 const gchar *message_uid,
571 GCancellable *cancellable)
573 CamelIMAPXFolder *imapx_folder;
574 CamelMimeMessage *msg = NULL;
575 CamelStream *stream = NULL;
576 GIOStream *base_stream;
578 g_return_val_if_fail (CAMEL_IS_IMAPX_FOLDER (folder), NULL);
579 g_return_val_if_fail (message_uid != NULL, NULL);
581 imapx_folder = CAMEL_IMAPX_FOLDER (folder);
583 base_stream = camel_data_cache_get (imapx_folder->cache, "cur", message_uid, NULL);
584 if (base_stream != NULL) {
585 stream = camel_stream_new (base_stream);
586 g_object_unref (base_stream);
589 if (stream != NULL) {
592 msg = camel_mime_message_new ();
594 g_mutex_lock (&imapx_folder->stream_lock);
595 success = camel_data_wrapper_construct_from_stream_sync (
596 CAMEL_DATA_WRAPPER (msg), stream, cancellable, NULL);
598 g_object_unref (msg);
601 g_mutex_unlock (&imapx_folder->stream_lock);
602 g_object_unref (stream);
608 static CamelMimeMessage *
609 imapx_get_message_sync (CamelFolder *folder,
611 GCancellable *cancellable,
614 CamelMimeMessage *msg = NULL;
617 CamelIMAPXFolder *imapx_folder;
618 GIOStream *base_stream;
619 const gchar *path = NULL;
620 gboolean offline_message = FALSE;
622 imapx_folder = CAMEL_IMAPX_FOLDER (folder);
623 store = camel_folder_get_parent_store (folder);
625 if (!strchr (uid, '-'))
629 offline_message = TRUE;
632 base_stream = camel_data_cache_get (
633 imapx_folder->cache, path, uid, NULL);
634 if (base_stream != NULL) {
635 stream = camel_stream_new (base_stream);
636 g_object_unref (base_stream);
638 CamelIMAPXServer *imapx_server;
639 CamelIMAPXMailbox *mailbox;
640 const gchar *folder_name;
642 if (offline_message) {
644 error, CAMEL_FOLDER_ERROR,
645 CAMEL_FOLDER_ERROR_INVALID_UID,
646 "Offline message vanished from disk: %s", uid);
650 folder_name = camel_folder_get_full_name (folder);
651 imapx_server = camel_imapx_store_ref_server (
652 CAMEL_IMAPX_STORE (store), folder_name, FALSE, cancellable, error);
654 if (imapx_server == NULL)
657 mailbox = camel_imapx_folder_list_mailbox (
658 CAMEL_IMAPX_FOLDER (folder), cancellable, error);
660 if (mailbox == NULL) {
661 camel_imapx_store_folder_op_done (CAMEL_IMAPX_STORE (store), imapx_server, folder_name);
662 g_object_unref (imapx_server);
666 stream = camel_imapx_server_get_message (
667 imapx_server, mailbox, folder->summary,
668 CAMEL_IMAPX_FOLDER (folder)->cache, uid,
671 camel_imapx_store_folder_op_done (CAMEL_IMAPX_STORE (store), imapx_server, folder_name);
673 g_clear_object (&mailbox);
674 g_clear_object (&imapx_server);
677 if (stream != NULL) {
680 msg = camel_mime_message_new ();
682 g_mutex_lock (&imapx_folder->stream_lock);
683 success = camel_data_wrapper_construct_from_stream_sync (
684 CAMEL_DATA_WRAPPER (msg), stream, cancellable, error);
686 g_object_unref (msg);
689 g_mutex_unlock (&imapx_folder->stream_lock);
690 g_object_unref (stream);
694 CamelMessageInfo *mi;
696 mi = camel_folder_summary_get (folder->summary, uid);
698 CamelMessageFlags flags;
699 gboolean has_attachment;
701 flags = camel_message_info_flags (mi);
702 has_attachment = camel_mime_message_has_attachment (msg);
703 if (((flags & CAMEL_MESSAGE_ATTACHMENTS) && !has_attachment) ||
704 ((flags & CAMEL_MESSAGE_ATTACHMENTS) == 0 && has_attachment)) {
705 camel_message_info_set_flags (
706 mi, CAMEL_MESSAGE_ATTACHMENTS,
707 has_attachment ? CAMEL_MESSAGE_ATTACHMENTS : 0);
710 camel_message_info_unref (mi);
717 static CamelFolderQuotaInfo *
718 imapx_get_quota_info_sync (CamelFolder *folder,
719 GCancellable *cancellable,
723 CamelIMAPXStore *imapx_store;
724 CamelIMAPXServer *imapx_server;
725 CamelIMAPXMailbox *mailbox = NULL;
726 CamelFolderQuotaInfo *quota_info = NULL;
727 const gchar *folder_name;
729 gboolean success = FALSE;
731 store = camel_folder_get_parent_store (folder);
732 folder_name = camel_folder_get_full_name (folder);
734 imapx_store = CAMEL_IMAPX_STORE (store);
735 imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, error);
737 if (imapx_server == NULL)
740 mailbox = camel_imapx_folder_list_mailbox (
741 CAMEL_IMAPX_FOLDER (folder), cancellable, error);
742 if (mailbox == NULL) {
743 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
747 success = camel_imapx_server_update_quota_info (
748 imapx_server, mailbox, cancellable, error);
750 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
755 quota_roots = camel_imapx_mailbox_dup_quota_roots (mailbox);
757 /* XXX Just return info for the first quota root, I guess. */
758 if (quota_roots != NULL && quota_roots[0] != NULL) {
759 quota_info = camel_imapx_store_dup_quota_info (
760 CAMEL_IMAPX_STORE (store), quota_roots[0]);
763 g_strfreev (quota_roots);
765 if (quota_info == NULL)
767 error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
768 _("No quota information available for folder '%s'"),
769 camel_folder_get_full_name (folder));
772 g_clear_object (&mailbox);
773 g_clear_object (&imapx_server);
779 imapx_purge_message_cache_sync (CamelFolder *folder,
782 GCancellable *cancellable,
785 /* Not Implemented for now. */
790 imapx_refresh_info_sync (CamelFolder *folder,
791 GCancellable *cancellable,
795 CamelIMAPXStore *imapx_store;
796 CamelIMAPXServer *imapx_server;
797 CamelIMAPXMailbox *mailbox = NULL;
798 CamelFolderChangeInfo *changes;
799 const gchar *folder_name;
800 gboolean success = FALSE;
802 store = camel_folder_get_parent_store (folder);
803 folder_name = camel_folder_get_full_name (folder);
805 imapx_store = CAMEL_IMAPX_STORE (store);
806 imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, TRUE, cancellable, error);
808 if (imapx_server == NULL)
811 mailbox = camel_imapx_folder_list_mailbox (
812 CAMEL_IMAPX_FOLDER (folder), cancellable, error);
814 if (mailbox == NULL) {
815 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
819 changes = camel_imapx_server_refresh_info (
820 imapx_server, mailbox, cancellable, error);
822 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
824 if (changes != NULL) {
825 if (camel_folder_change_info_changed (changes))
826 camel_folder_changed (folder, changes);
827 camel_folder_change_info_free (changes);
832 g_clear_object (&mailbox);
833 g_clear_object (&imapx_server);
838 /* Helper for imapx_synchronize_sync() */
840 imapx_move_to_real_junk (CamelIMAPXServer *imapx_server,
842 GCancellable *cancellable,
843 gboolean *out_need_to_expunge,
846 CamelIMAPXFolder *imapx_folder;
847 CamelIMAPXMailbox *mailbox;
848 CamelIMAPXSettings *settings;
849 GPtrArray *uids_to_copy;
850 gchar *real_junk_path = NULL;
851 gboolean success = TRUE;
853 *out_need_to_expunge = FALSE;
855 /* Caller already obtained the mailbox from the folder,
856 * so the folder should still have it readily available. */
857 imapx_folder = CAMEL_IMAPX_FOLDER (folder);
858 mailbox = camel_imapx_folder_ref_mailbox (imapx_folder);
859 g_return_val_if_fail (mailbox != NULL, FALSE);
861 uids_to_copy = g_ptr_array_new_with_free_func (
862 (GDestroyNotify) camel_pstring_free);
864 settings = camel_imapx_server_ref_settings (imapx_server);
865 if (camel_imapx_settings_get_use_real_junk_path (settings)) {
867 camel_imapx_settings_dup_real_junk_path (settings);
868 imapx_folder_claim_move_to_real_junk_uids (
869 imapx_folder, uids_to_copy);
871 g_object_unref (settings);
873 if (uids_to_copy->len > 0) {
874 CamelIMAPXStore *imapx_store;
875 CamelIMAPXMailbox *destination = NULL;
877 imapx_store = camel_imapx_server_ref_store (imapx_server);
879 if (real_junk_path != NULL) {
880 folder = camel_store_get_folder_sync (
881 CAMEL_STORE (imapx_store),
886 error, CAMEL_FOLDER_ERROR,
887 CAMEL_FOLDER_ERROR_INVALID_PATH,
888 _("No destination folder specified"));
892 if (folder != NULL) {
893 destination = camel_imapx_folder_list_mailbox (
894 CAMEL_IMAPX_FOLDER (folder),
896 g_object_unref (folder);
899 /* Avoid duplicating messages in the Junk folder. */
900 if (destination == mailbox) {
902 } else if (destination != NULL) {
903 success = camel_imapx_server_copy_message (
905 mailbox, destination,
908 *out_need_to_expunge = success;
916 _("Unable to move junk messages"));
919 g_clear_object (&destination);
920 g_clear_object (&imapx_store);
923 g_ptr_array_unref (uids_to_copy);
924 g_free (real_junk_path);
926 g_clear_object (&mailbox);
931 /* Helper for imapx_synchronize_sync() */
933 imapx_move_to_real_trash (CamelIMAPXServer *imapx_server,
935 GCancellable *cancellable,
936 gboolean *out_need_to_expunge,
939 CamelIMAPXFolder *imapx_folder;
940 CamelIMAPXMailbox *mailbox;
941 CamelIMAPXSettings *settings;
942 GPtrArray *uids_to_copy;
943 gchar *real_trash_path = NULL;
944 gboolean success = TRUE;
946 *out_need_to_expunge = FALSE;
948 /* Caller already obtained the mailbox from the folder,
949 * so the folder should still have it readily available. */
950 imapx_folder = CAMEL_IMAPX_FOLDER (folder);
951 mailbox = camel_imapx_folder_ref_mailbox (imapx_folder);
952 g_return_val_if_fail (mailbox != NULL, FALSE);
954 uids_to_copy = g_ptr_array_new_with_free_func (
955 (GDestroyNotify) camel_pstring_free);
957 settings = camel_imapx_server_ref_settings (imapx_server);
958 if (camel_imapx_settings_get_use_real_trash_path (settings)) {
960 camel_imapx_settings_dup_real_trash_path (settings);
961 imapx_folder_claim_move_to_real_trash_uids (
962 CAMEL_IMAPX_FOLDER (folder), uids_to_copy);
964 g_object_unref (settings);
966 if (uids_to_copy->len > 0) {
967 CamelIMAPXStore *imapx_store;
968 CamelIMAPXMailbox *destination = NULL;
970 imapx_store = camel_imapx_server_ref_store (imapx_server);
972 if (real_trash_path != NULL) {
973 folder = camel_store_get_folder_sync (
974 CAMEL_STORE (imapx_store),
979 error, CAMEL_FOLDER_ERROR,
980 CAMEL_FOLDER_ERROR_INVALID_PATH,
981 _("No destination folder specified"));
985 if (folder != NULL) {
986 destination = camel_imapx_folder_list_mailbox (
987 CAMEL_IMAPX_FOLDER (folder),
989 g_object_unref (folder);
992 /* Avoid duplicating messages in the Trash folder. */
993 if (destination == mailbox) {
995 } else if (destination != NULL) {
996 success = camel_imapx_server_copy_message (
998 mailbox, destination,
1000 cancellable, error);
1001 *out_need_to_expunge = success;
1009 _("Unable to move deleted messages"));
1012 g_clear_object (&destination);
1013 g_clear_object (&imapx_store);
1016 g_ptr_array_unref (uids_to_copy);
1017 g_free (real_trash_path);
1019 g_clear_object (&mailbox);
1025 imapx_synchronize_sync (CamelFolder *folder,
1027 GCancellable *cancellable,
1031 CamelIMAPXStore *imapx_store;
1032 CamelIMAPXServer *imapx_server;
1033 CamelIMAPXMailbox *mailbox = NULL;
1034 const gchar *folder_name;
1035 gboolean need_to_expunge;
1036 gboolean success = FALSE;
1038 store = camel_folder_get_parent_store (folder);
1039 folder_name = camel_folder_get_full_name (folder);
1041 imapx_store = CAMEL_IMAPX_STORE (store);
1042 /* while it can be expensive job, do not treat it as such, to avoid a blockage
1043 by really expensive jobs */
1044 imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, error);
1046 if (imapx_server == NULL)
1049 mailbox = camel_imapx_folder_list_mailbox (
1050 CAMEL_IMAPX_FOLDER (folder), cancellable, error);
1051 if (mailbox == NULL) {
1052 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
1056 success = camel_imapx_server_sync_changes (
1057 imapx_server, mailbox, cancellable, error);
1060 success = imapx_move_to_real_junk (
1061 imapx_server, folder, cancellable,
1062 &need_to_expunge, error);
1063 expunge |= need_to_expunge;
1067 success = imapx_move_to_real_trash (
1068 imapx_server, folder, cancellable,
1069 &need_to_expunge, error);
1070 expunge |= need_to_expunge;
1073 /* Sync twice - make sure deleted flags are written out,
1074 * then sync again incase expunge changed anything */
1076 if (success && expunge) {
1077 success = camel_imapx_server_expunge (
1078 imapx_server, mailbox, cancellable, error);
1081 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
1084 g_clear_object (&mailbox);
1085 g_clear_object (&imapx_server);
1091 imapx_synchronize_message_sync (CamelFolder *folder,
1093 GCancellable *cancellable,
1097 CamelIMAPXStore *imapx_store;
1098 CamelIMAPXServer *imapx_server;
1099 CamelIMAPXMailbox *mailbox = NULL;
1100 const gchar *folder_name;
1101 gboolean success = FALSE;
1103 store = camel_folder_get_parent_store (folder);
1104 folder_name = camel_folder_get_full_name (folder);
1106 imapx_store = CAMEL_IMAPX_STORE (store);
1107 imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, error);
1109 if (imapx_server == NULL)
1112 mailbox = camel_imapx_folder_list_mailbox (
1113 CAMEL_IMAPX_FOLDER (folder), cancellable, error);
1115 if (mailbox == NULL) {
1116 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
1120 success = camel_imapx_server_sync_message (
1121 imapx_server, mailbox, folder->summary,
1122 CAMEL_IMAPX_FOLDER (folder)->cache, uid,
1123 cancellable, error);
1125 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
1128 g_clear_object (&mailbox);
1129 g_clear_object (&imapx_server);
1135 imapx_transfer_messages_to_sync (CamelFolder *source,
1138 gboolean delete_originals,
1139 GPtrArray **transferred_uids,
1140 GCancellable *cancellable,
1144 CamelIMAPXStore *imapx_store;
1145 CamelIMAPXServer *imapx_server;
1146 CamelIMAPXMailbox *src_mailbox = NULL;
1147 CamelIMAPXMailbox *dst_mailbox = NULL;
1148 const gchar *folder_name;
1149 gboolean success = FALSE;
1151 store = camel_folder_get_parent_store (source);
1152 folder_name = camel_folder_get_full_name (source);
1154 imapx_store = CAMEL_IMAPX_STORE (store);
1155 imapx_server = camel_imapx_store_ref_server (imapx_store, folder_name, FALSE, cancellable, error);
1157 if (imapx_server == NULL)
1160 src_mailbox = camel_imapx_folder_list_mailbox (
1161 CAMEL_IMAPX_FOLDER (source), cancellable, error);
1163 if (src_mailbox == NULL) {
1164 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
1168 dst_mailbox = camel_imapx_folder_list_mailbox (
1169 CAMEL_IMAPX_FOLDER (dest), cancellable, error);
1171 if (dst_mailbox == NULL) {
1172 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
1176 success = camel_imapx_server_copy_message (
1177 imapx_server, src_mailbox, dst_mailbox, uids,
1178 delete_originals, cancellable, error);
1180 camel_imapx_store_folder_op_done (imapx_store, imapx_server, folder_name);
1182 /* Update destination folder only if it's not frozen,
1183 * to avoid updating for each "move" action on a single
1184 * message while filtering. */
1185 if (!camel_folder_is_frozen (dest))
1186 imapx_refresh_info_sync (dest, cancellable, NULL);
1189 g_clear_object (&src_mailbox);
1190 g_clear_object (&dst_mailbox);
1191 g_clear_object (&imapx_server);
1197 imapx_rename (CamelFolder *folder,
1198 const gchar *new_name)
1201 CamelIMAPXStore *imapx_store;
1202 const gchar *folder_name;
1204 store = camel_folder_get_parent_store (folder);
1205 imapx_store = CAMEL_IMAPX_STORE (store);
1207 camel_store_summary_disconnect_folder_summary (
1208 imapx_store->summary, folder->summary);
1210 /* Chain up to parent's rename() method. */
1211 CAMEL_FOLDER_CLASS (camel_imapx_folder_parent_class)->
1212 rename (folder, new_name);
1214 folder_name = camel_folder_get_full_name (folder);
1216 camel_store_summary_connect_folder_summary (
1217 imapx_store->summary, folder_name, folder->summary);
1221 camel_imapx_folder_class_init (CamelIMAPXFolderClass *class)
1223 GObjectClass *object_class;
1224 CamelFolderClass *folder_class;
1226 g_type_class_add_private (class, sizeof (CamelIMAPXFolderPrivate));
1228 object_class = G_OBJECT_CLASS (class);
1229 object_class->set_property = imapx_folder_set_property;
1230 object_class->get_property = imapx_folder_get_property;
1231 object_class->dispose = imapx_folder_dispose;
1232 object_class->finalize = imapx_folder_finalize;
1234 folder_class = CAMEL_FOLDER_CLASS (class);
1235 folder_class->rename = imapx_rename;
1236 folder_class->search_by_expression = imapx_search_by_expression;
1237 folder_class->search_by_uids = imapx_search_by_uids;
1238 folder_class->count_by_expression = imapx_count_by_expression;
1239 folder_class->search_free = imapx_search_free;
1240 folder_class->get_filename = imapx_get_filename;
1241 folder_class->append_message_sync = imapx_append_message_sync;
1242 folder_class->expunge_sync = imapx_expunge_sync;
1243 folder_class->get_message_cached = imapx_get_message_cached;
1244 folder_class->get_message_sync = imapx_get_message_sync;
1245 folder_class->get_quota_info_sync = imapx_get_quota_info_sync;
1246 folder_class->purge_message_cache_sync = imapx_purge_message_cache_sync;
1247 folder_class->refresh_info_sync = imapx_refresh_info_sync;
1248 folder_class->synchronize_sync = imapx_synchronize_sync;
1249 folder_class->synchronize_message_sync = imapx_synchronize_message_sync;
1250 folder_class->transfer_messages_to_sync = imapx_transfer_messages_to_sync;
1252 g_object_class_install_property (
1255 g_param_spec_boolean (
1258 _("Apply message _filters to this folder"),
1261 CAMEL_PARAM_PERSISTENT));
1263 g_object_class_install_property (
1266 g_param_spec_object (
1269 "IMAP mailbox for this folder",
1270 CAMEL_TYPE_IMAPX_MAILBOX,
1272 G_PARAM_STATIC_STRINGS));
1276 camel_imapx_folder_init (CamelIMAPXFolder *imapx_folder)
1278 CamelFolder *folder = CAMEL_FOLDER (imapx_folder);
1279 GHashTable *move_to_real_junk_uids;
1280 GHashTable *move_to_real_trash_uids;
1282 move_to_real_junk_uids = g_hash_table_new_full (
1283 (GHashFunc) g_direct_hash,
1284 (GEqualFunc) g_direct_equal,
1285 (GDestroyNotify) camel_pstring_free,
1286 (GDestroyNotify) NULL);
1288 move_to_real_trash_uids = g_hash_table_new_full (
1289 (GHashFunc) g_direct_hash,
1290 (GEqualFunc) g_direct_equal,
1291 (GDestroyNotify) camel_pstring_free,
1292 (GDestroyNotify) NULL);
1294 imapx_folder->priv = CAMEL_IMAPX_FOLDER_GET_PRIVATE (imapx_folder);
1296 folder->folder_flags |= CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY;
1298 folder->permanent_flags =
1299 CAMEL_MESSAGE_ANSWERED |
1300 CAMEL_MESSAGE_DELETED |
1301 CAMEL_MESSAGE_DRAFT |
1302 CAMEL_MESSAGE_FLAGGED |
1303 CAMEL_MESSAGE_SEEN |
1306 camel_folder_set_lock_async (folder, TRUE);
1308 g_mutex_init (&imapx_folder->priv->property_lock);
1310 g_mutex_init (&imapx_folder->priv->move_to_hash_table_lock);
1311 imapx_folder->priv->move_to_real_junk_uids = move_to_real_junk_uids;
1312 imapx_folder->priv->move_to_real_trash_uids = move_to_real_trash_uids;
1316 camel_imapx_folder_new (CamelStore *store,
1317 const gchar *folder_dir,
1318 const gchar *folder_name,
1321 CamelFolder *folder;
1322 CamelService *service;
1323 CamelSettings *settings;
1324 CamelIMAPXFolder *imapx_folder;
1325 const gchar *short_name;
1327 gboolean filter_all;
1328 gboolean filter_inbox;
1329 gboolean filter_junk;
1330 gboolean filter_junk_inbox;
1332 d ("opening imap folder '%s'\n", folder_dir);
1334 service = CAMEL_SERVICE (store);
1336 settings = camel_service_ref_settings (service);
1340 "filter-all", &filter_all,
1341 "filter-inbox", &filter_inbox,
1342 "filter-junk", &filter_junk,
1343 "filter-junk-inbox", &filter_junk_inbox,
1346 g_object_unref (settings);
1348 short_name = strrchr (folder_name, '/');
1352 short_name = folder_name;
1354 folder = g_object_new (
1355 CAMEL_TYPE_IMAPX_FOLDER,
1356 "display-name", short_name,
1357 "full_name", folder_name,
1358 "parent-store", store, NULL);
1360 folder->summary = camel_imapx_summary_new (folder);
1361 if (folder->summary == NULL) {
1363 error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
1364 _("Could not create folder summary for %s"),
1369 imapx_folder = CAMEL_IMAPX_FOLDER (folder);
1370 imapx_folder->cache = camel_data_cache_new (folder_dir, error);
1371 if (imapx_folder->cache == NULL) {
1373 error, _("Could not create cache for %s: "),
1378 state_file = g_build_filename (folder_dir, "cmeta", NULL);
1379 camel_object_set_state_filename (CAMEL_OBJECT (folder), state_file);
1380 g_free (state_file);
1381 camel_object_state_read (CAMEL_OBJECT (folder));
1383 imapx_folder->search = camel_imapx_search_new ();
1384 g_mutex_init (&imapx_folder->search_lock);
1385 g_mutex_init (&imapx_folder->stream_lock);
1388 folder->folder_flags |= CAMEL_FOLDER_FILTER_RECENT;
1390 if (camel_imapx_mailbox_is_inbox (folder_name)) {
1392 folder->folder_flags |= CAMEL_FOLDER_FILTER_RECENT;
1395 folder->folder_flags |= CAMEL_FOLDER_FILTER_JUNK;
1397 if (filter_junk && !filter_junk_inbox)
1398 folder->folder_flags |= CAMEL_FOLDER_FILTER_JUNK;
1400 if (imapx_folder_get_apply_filters (imapx_folder))
1401 folder->folder_flags |= CAMEL_FOLDER_FILTER_RECENT;
1404 camel_store_summary_connect_folder_summary (
1405 CAMEL_IMAPX_STORE (store)->summary,
1406 folder_name, folder->summary);
1412 * camel_imapx_folder_ref_mailbox:
1413 * @folder: a #CamelIMAPXFolder
1415 * Returns the #CamelIMAPXMailbox for @folder from the current IMAP server
1416 * connection, or %NULL if @folder's #CamelFolder:parent-store is disconnected
1417 * from the IMAP server.
1419 * The returned #CamelIMAPXMailbox is referenced for thread-safety and
1420 * should be unreferenced with g_object_unref() when finished with it.
1422 * Returns: a #CamelIMAPXMailbox, or %NULL
1427 camel_imapx_folder_ref_mailbox (CamelIMAPXFolder *folder)
1429 g_return_val_if_fail (CAMEL_IS_IMAPX_FOLDER (folder), NULL);
1431 return g_weak_ref_get (&folder->priv->mailbox);
1435 * camel_imapx_folder_set_mailbox:
1436 * @folder: a #CamelIMAPXFolder
1437 * @mailbox: a #CamelIMAPXMailbox
1439 * Sets the #CamelIMAPXMailbox for @folder from the current IMAP server
1440 * connection. Note that #CamelIMAPXFolder only holds a weak reference
1441 * on its #CamelIMAPXMailbox so that when the IMAP server connection is
1442 * lost, all mailbox instances are automatically destroyed.
1447 camel_imapx_folder_set_mailbox (CamelIMAPXFolder *folder,
1448 CamelIMAPXMailbox *mailbox)
1450 g_return_if_fail (CAMEL_IS_IMAPX_FOLDER (folder));
1451 g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
1453 g_weak_ref_set (&folder->priv->mailbox, mailbox);
1455 g_object_notify (G_OBJECT (folder), "mailbox");
1459 * camel_imapx_folder_list_mailbox:
1460 * @folder: a #CamelIMAPXFolder
1461 * @cancellable: optional #GCancellable object, or %NULL
1462 * @error: return location for a #GError, or %NULL
1464 * Ensures that @folder's #CamelIMAPXFolder:mailbox property is set,
1465 * going so far as to issue a LIST command if necessary (but should
1466 * be a rarely needed last resort).
1468 * If @folder's #CamelFolder:parent-store is disconnected from the IMAP
1469 * server or an error occurs during the LIST command, the function sets
1470 * @error and returns %NULL.
1472 * The returned #CamelIMAPXMailbox is referenced for thread-safety and
1473 * should be unreferenced with g_object_unref() when finished with it.
1475 * Returns: a #CamelIMAPXMailbox, or %NULL
1480 camel_imapx_folder_list_mailbox (CamelIMAPXFolder *folder,
1481 GCancellable *cancellable,
1484 CamelIMAPXStore *imapx_store;
1485 CamelIMAPXServer *server = NULL;
1486 CamelIMAPXMailbox *mailbox;
1487 CamelStore *parent_store;
1488 CamelStoreInfo *store_info;
1489 CamelIMAPXStoreInfo *imapx_store_info;
1490 gchar *folder_path = NULL;
1491 gchar *mailbox_name = NULL;
1495 g_return_val_if_fail (CAMEL_IS_IMAPX_FOLDER (folder), FALSE);
1497 /* First check if we already have a mailbox. */
1499 mailbox = camel_imapx_folder_ref_mailbox (folder);
1500 if (mailbox != NULL)
1503 /* Obtain the mailbox name from the store summary. */
1505 folder_path = camel_folder_dup_full_name (CAMEL_FOLDER (folder));
1506 parent_store = camel_folder_get_parent_store (CAMEL_FOLDER (folder));
1508 imapx_store = CAMEL_IMAPX_STORE (parent_store);
1510 store_info = camel_store_summary_path (
1511 imapx_store->summary, folder_path);
1513 /* This should never fail. We needed the CamelStoreInfo
1514 * to instantiate the CamelIMAPXFolder in the first place. */
1515 g_return_val_if_fail (store_info != NULL, FALSE);
1517 imapx_store_info = (CamelIMAPXStoreInfo *) store_info;
1518 mailbox_name = g_strdup (imapx_store_info->mailbox_name);
1520 camel_store_summary_info_unref (imapx_store->summary, store_info);
1522 /* See if the CamelIMAPXServer already has the mailbox. */
1524 server = camel_imapx_store_ref_server (imapx_store, NULL, FALSE, cancellable, error);
1529 mailbox = camel_imapx_server_ref_mailbox (server, mailbox_name);
1530 if (mailbox != NULL) {
1531 camel_imapx_folder_set_mailbox (folder, mailbox);
1535 /* Last resort is to issue a LIST command. Maintainer should
1536 * monitor IMAP logs to make sure this is rarely if ever used. */
1538 pattern = camel_utf8_utf7 (mailbox_name);
1540 /* This creates a mailbox instance from the LIST response. */
1541 success = camel_imapx_server_list (
1542 server, pattern, 0, cancellable, error);
1549 /* This might still return NULL if the mailbox has a
1550 * /NonExistent attribute. Otherwise this should work. */
1551 mailbox = camel_imapx_server_ref_mailbox (server, mailbox_name);
1552 if (mailbox != NULL) {
1553 camel_imapx_folder_set_mailbox (folder, mailbox);
1556 error, CAMEL_FOLDER_ERROR,
1557 CAMEL_FOLDER_ERROR_INVALID_STATE,
1558 _("No IMAP mailbox available for folder '%s'"),
1559 camel_folder_get_display_name (CAMEL_FOLDER (folder)));
1563 g_clear_object (&server);
1565 g_free (folder_path);
1566 g_free (mailbox_name);
1572 * camel_imapx_folder_copy_message_map:
1573 * @folder: a #CamelIMAPXFolder
1575 * Returns a #GSequence of 32-bit integers representing the locally cached
1576 * mapping of message sequence numbers to unique identifiers.
1578 * Free the returns #GSequence with g_sequence_free().
1580 * Returns: a #GSequence
1585 camel_imapx_folder_copy_message_map (CamelIMAPXFolder *folder)
1587 CamelFolderSummary *summary;
1588 GSequence *message_map;
1592 g_return_val_if_fail (CAMEL_IS_IMAPX_FOLDER (folder), NULL);
1594 summary = CAMEL_FOLDER (folder)->summary;
1595 array = camel_folder_summary_get_array (summary);
1596 camel_folder_sort_uids (CAMEL_FOLDER (folder), array);
1598 message_map = g_sequence_new (NULL);
1600 for (ii = 0; ii < array->len; ii++) {
1601 guint32 uid = strtoul (array->pdata[ii], NULL, 10);
1602 g_sequence_append (message_map, GUINT_TO_POINTER (uid));
1605 camel_folder_summary_free_array (array);
1611 * camel_imapx_folder_add_move_to_real_junk:
1612 * @folder: a #CamelIMAPXFolder
1613 * @message_uid: a message UID
1615 * Adds @message_uid to a pool of messages to be moved to a real junk
1616 * folder the next time @folder is explicitly synchronized by way of
1617 * camel_folder_synchronize() or camel_folder_synchronize_sync().
1619 * This only applies when using a real folder to track junk messages,
1620 * as specified by the #CamelIMAPXSettings:use-real-junk-path setting.
1625 camel_imapx_folder_add_move_to_real_junk (CamelIMAPXFolder *folder,
1626 const gchar *message_uid)
1628 g_return_if_fail (CAMEL_IS_IMAPX_FOLDER (folder));
1629 g_return_if_fail (message_uid != NULL);
1631 g_mutex_lock (&folder->priv->move_to_hash_table_lock);
1634 folder->priv->move_to_real_junk_uids,
1635 (gpointer) camel_pstring_strdup (message_uid));
1637 g_mutex_unlock (&folder->priv->move_to_hash_table_lock);
1641 * camel_imapx_folder_add_move_to_real_trash:
1642 * @folder: a #CamelIMAPXFolder
1643 * @message_uid: a message UID
1645 * Adds @message_uid to a pool of messages to be moved to a real trash
1646 * folder the next time @folder is explicitly synchronized by way of
1647 * camel_folder_synchronize() or camel_folder_synchronize_sync().
1649 * This only applies when using a real folder to track deleted messages,
1650 * as specified by the #CamelIMAPXSettings:use-real-trash-path setting.
1655 camel_imapx_folder_add_move_to_real_trash (CamelIMAPXFolder *folder,
1656 const gchar *message_uid)
1658 g_return_if_fail (CAMEL_IS_IMAPX_FOLDER (folder));
1659 g_return_if_fail (message_uid != NULL);
1661 g_mutex_lock (&folder->priv->move_to_hash_table_lock);
1664 folder->priv->move_to_real_trash_uids,
1665 (gpointer) camel_pstring_strdup (message_uid));
1667 g_mutex_unlock (&folder->priv->move_to_hash_table_lock);
1671 * camel_imapx_folder_invalidate_local_cache:
1672 * @folder: a #CamelIMAPXFolder
1673 * @new_uidvalidity: the new UIDVALIDITY value
1675 * Call this function when the IMAP server reports a different UIDVALIDITY
1676 * value than what is presently cached. This means all cached message UIDs
1677 * are now invalid and must be discarded.
1679 * The local cache for @folder is reset and the @new_uidvalidity value is
1680 * recorded in the newly-reset cache.
1685 camel_imapx_folder_invalidate_local_cache (CamelIMAPXFolder *folder,
1686 guint64 new_uidvalidity)
1688 CamelFolderSummary *summary;
1689 CamelFolderChangeInfo *changes;
1693 g_return_if_fail (CAMEL_IS_IMAPX_FOLDER (folder));
1694 g_return_if_fail (new_uidvalidity > 0);
1696 summary = CAMEL_FOLDER (folder)->summary;
1698 changes = camel_folder_change_info_new ();
1699 array = camel_folder_summary_get_array (summary);
1701 for (ii = 0; ii < array->len; ii++) {
1702 const gchar *uid = array->pdata[ii];
1703 camel_folder_change_info_change_uid (changes, uid);
1706 CAMEL_IMAPX_SUMMARY (summary)->validity = new_uidvalidity;
1707 camel_folder_summary_touch (summary);
1708 camel_folder_summary_save_to_db (summary, NULL);
1710 camel_data_cache_clear (folder->cache, "cache");
1711 camel_data_cache_clear (folder->cache, "cur");
1713 camel_folder_changed (CAMEL_FOLDER (folder), changes);
1715 camel_folder_change_info_free (changes);
1716 camel_folder_summary_free_array (array);