1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* camelFolder.c : Abstract class for an email folder */
7 * Bertrand Guiheneuf <bertrand@helixcode.com>
9 * Copyright 1999, 2000 HelixCode (http://www.helixcode.com) .
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of the
14 * License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 #include "camel-folder.h"
28 #include "camel-log.h"
29 #include "string-utils.h"
31 static GtkObjectClass *parent_class=NULL;
33 /* Returns the class for a CamelFolder */
34 #define CF_CLASS(so) CAMEL_FOLDER_CLASS (GTK_OBJECT(so)->klass)
39 static void _init_with_store (CamelFolder *folder,
40 CamelStore *parent_store,
42 static void _finalize (GtkObject *object);
45 static void _open (CamelFolder *folder,
46 CamelFolderOpenMode mode,
48 static void _close (CamelFolder *folder,
52 /* Async operations are not used for the moment */
53 static void _open_async (CamelFolder *folder,
54 CamelFolderOpenMode mode,
55 CamelFolderAsyncCallback callback,
58 static void _close_async (CamelFolder *folder,
60 CamelFolderAsyncCallback callback,
65 static void _set_name (CamelFolder *folder,
68 static const gchar *_get_name (CamelFolder *folder,
70 static const gchar *_get_full_name (CamelFolder *folder, CamelException *ex);
71 /* static void _set_full_name (CamelFolder *folder, const gchar *name); */
74 static gboolean _can_hold_folders (CamelFolder *folder, CamelException *ex);
75 static gboolean _can_hold_messages (CamelFolder *folder, CamelException *ex);
76 static gboolean _exists (CamelFolder *folder, CamelException *ex);
77 static gboolean _is_open (CamelFolder *folder, CamelException *ex);
78 static const GList *_list_permanent_flags (CamelFolder *folder, CamelException *ex);
79 static CamelFolderOpenMode _get_mode (CamelFolder *folder, CamelException *ex);
82 static gboolean _create (CamelFolder *folder, CamelException *ex);
83 static gboolean _delete (CamelFolder *folder, gboolean recurse, CamelException *ex);
86 static GList *_list_subfolders (CamelFolder *folder, CamelException *ex);
87 static CamelFolder *_get_subfolder (CamelFolder *folder,
88 const gchar *folder_name, CamelException *ex);
89 static CamelFolder *_get_parent_folder (CamelFolder *folder, CamelException *ex);
90 static CamelStore * _get_parent_store (CamelFolder *folder, CamelException *ex);
93 static gboolean _has_message_number_capability (CamelFolder *folder, CamelException *ex);
94 static CamelMimeMessage *_get_message_by_number (CamelFolder *folder,
97 static gint _get_message_count (CamelFolder *folder,
101 static gboolean _delete_messages (CamelFolder *folder,
103 static GList * _expunge (CamelFolder *folder,
105 static void _append_message (CamelFolder *folder,
106 CamelMimeMessage *message,
108 static void _copy_message_to (CamelFolder *folder,
109 CamelMimeMessage *message,
110 CamelFolder *dest_folder,
114 static GList *_get_uid_list (CamelFolder *folder, CamelException *ex);
115 static const gchar *_get_message_uid (CamelFolder *folder,
116 CamelMimeMessage *message,
118 static CamelMimeMessage *_get_message_by_uid (CamelFolder *folder,
126 camel_folder_class_init (CamelFolderClass *camel_folder_class)
128 GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (camel_folder_class);
130 parent_class = gtk_type_class (gtk_object_get_type ());
132 /* virtual method definition */
133 camel_folder_class->init_with_store = _init_with_store;
134 camel_folder_class->open = _open;
135 camel_folder_class->open_async = _open_async;
136 camel_folder_class->close = _close;
137 camel_folder_class->close_async = _close_async;
138 camel_folder_class->set_name = _set_name;
139 camel_folder_class->get_name = _get_name;
140 camel_folder_class->get_full_name = _get_full_name;
141 camel_folder_class->can_hold_folders = _can_hold_folders;
142 camel_folder_class->can_hold_messages = _can_hold_messages;
143 camel_folder_class->exists = _exists;
144 camel_folder_class->is_open = _is_open;
145 camel_folder_class->get_subfolder = _get_subfolder;
146 camel_folder_class->create = _create;
147 camel_folder_class->delete = _delete;
148 camel_folder_class->delete_messages = _delete_messages;
149 camel_folder_class->get_parent_folder = _get_parent_folder;
150 camel_folder_class->get_parent_store = _get_parent_store;
151 camel_folder_class->get_mode = _get_mode;
152 camel_folder_class->list_subfolders = _list_subfolders;
153 camel_folder_class->expunge = _expunge;
154 camel_folder_class->has_message_number_capability = _has_message_number_capability;
155 camel_folder_class->get_message_by_number = _get_message_by_number;
156 camel_folder_class->get_message_count = _get_message_count;
157 camel_folder_class->append_message = _append_message;
158 camel_folder_class->list_permanent_flags = _list_permanent_flags;
159 camel_folder_class->copy_message_to = _copy_message_to;
160 camel_folder_class->get_message_uid = _get_message_uid;
161 camel_folder_class->get_message_by_uid = _get_message_by_uid;
162 camel_folder_class->get_uid_list = _get_uid_list;
164 /* virtual method overload */
165 gtk_object_class->finalize = _finalize;
175 camel_folder_get_type (void)
177 static GtkType camel_folder_type = 0;
179 if (!camel_folder_type) {
180 GtkTypeInfo camel_folder_info =
183 sizeof (CamelFolder),
184 sizeof (CamelFolderClass),
185 (GtkClassInitFunc) camel_folder_class_init,
186 (GtkObjectInitFunc) NULL,
187 /* reserved_1 */ NULL,
188 /* reserved_2 */ NULL,
189 (GtkClassInitFunc) NULL,
192 camel_folder_type = gtk_type_unique (gtk_object_get_type (), &camel_folder_info);
195 return camel_folder_type;
200 _finalize (GtkObject *object)
202 CamelFolder *camel_folder = CAMEL_FOLDER (object);
205 CAMEL_LOG_FULL_DEBUG ("Entering CamelFolder::finalize\n");
207 g_free (camel_folder->name);
208 g_free (camel_folder->full_name);
209 g_free (camel_folder->permanent_flags);
211 GTK_OBJECT_CLASS (parent_class)->finalize (object);
212 CAMEL_LOG_FULL_DEBUG ("Leaving CamelFolder::finalize\n");
217 * _init_with_store: init the folder by setting its parent store.
218 * @folder: folder object to initialize
219 * @parent_store: parent store object of the folder
224 _init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException *ex)
228 camel_exception_set (ex,
229 CAMEL_EXCEPTION_FOLDER_NULL,
230 "folder object is NULL");
235 camel_exception_set (ex,
236 CAMEL_EXCEPTION_INVALID_PARAM,
237 "parent_store parameter is NULL");
241 if (folder->parent_store) {
242 camel_exception_set (ex,
243 CAMEL_EXCEPTION_FOLDER_INVALID,
244 "folder already has a parent store");
248 folder->parent_store = parent_store;
249 gtk_object_ref (GTK_OBJECT (parent_store));
251 folder->open_mode = FOLDER_OPEN_UNKNOWN;
252 folder->open_state = FOLDER_CLOSE;
254 folder->full_name = NULL;
262 _open (CamelFolder *folder,
263 CamelFolderOpenMode mode,
267 camel_exception_set (ex,
268 CAMEL_EXCEPTION_FOLDER_NULL,
269 "folder object is NULL");
273 folder->open_state = FOLDER_OPEN;
274 folder->open_mode = mode;
281 * camel_folder_open: Open a folder
282 * @folder: The folder object
283 * @mode: open mode (R/W/RW ?)
284 * @ex: exception object
286 * Open a folder in a given mode.
290 camel_folder_open (CamelFolder *folder,
291 CamelFolderOpenMode mode,
295 camel_exception_set (ex,
296 CAMEL_EXCEPTION_FOLDER_NULL,
297 "folder object is NULL");
300 CF_CLASS(folder)->open (folder, mode, ex);
309 _open_async (CamelFolder *folder,
310 CamelFolderOpenMode mode,
311 CamelFolderAsyncCallback callback,
315 CAMEL_LOG_WARNING ("Calling CamelFolder::open_async directly. "
316 "Should be overloaded\n");
322 * camel_folder_open: Open a folder
323 * @folder: The folder object
324 * @mode: open mode (R/W/RW ?)
325 * @callback: function to call when the operation is over
326 * @user_data: data to pass to the callback
327 * @ex: exception object
329 * Open a folder in a given mode. When the operation is over
330 * the callback is called and the client program can determine
331 * if the operation suceeded by examining the exception.
335 camel_folder_open_async (CamelFolder *folder,
336 CamelFolderOpenMode mode,
337 CamelFolderAsyncCallback callback,
342 camel_exception_set (ex,
343 CAMEL_EXCEPTION_FOLDER_NULL,
344 "folder object is NULL");
347 CF_CLASS(folder)->open_async (folder, mode, callback, user_data, ex);
356 _close (CamelFolder *folder,
361 camel_exception_set (ex,
362 CAMEL_EXCEPTION_FOLDER_NULL,
363 "folder object is NULL");
366 folder->open_state = FOLDER_CLOSE;
370 * camel_folder_close: Close a folder.
371 * @folder: The folder object
372 * @expunge: if TRUE, the flagged message are deleted.
373 * @ex: exception object
375 * Put a folder in its closed state, and possibly
376 * expunge the flagged messages.
380 camel_folder_close (CamelFolder *folder,
385 camel_exception_set (ex,
386 CAMEL_EXCEPTION_FOLDER_NULL,
387 "folder object is NULL");
390 CF_CLASS(folder)->close (folder, expunge, ex);
399 _close_async (CamelFolder *folder,
401 CamelFolderAsyncCallback callback,
406 camel_exception_set (ex,
407 CAMEL_EXCEPTION_FOLDER_NULL,
408 "folder object is NULL");
411 CAMEL_LOG_WARNING ("Calling CamelFolder::close_async directly. "
412 "Should be overloaded\n");
416 * camel_folder_close_async: Close a folder.
417 * @folder: The folder object
418 * @expunge: if TRUE, the flagged message are deleted.
419 * @callback: function to call when the operation is over
420 * @user_data: data to pass to the callback
421 * @ex: exception object
423 * Put a folder in its closed state, and possibly
424 * expunge the flagged messages. The callback is called
425 * when the operation is over and the client program can determine
426 * if the operation suceeded by examining the exception.
430 camel_folder_close_async (CamelFolder *folder,
432 CamelFolderAsyncCallback callback,
437 camel_exception_set (ex,
438 CAMEL_EXCEPTION_FOLDER_NULL,
439 "folder object is NULL");
442 CF_CLASS(folder)->close_async (folder, expunge, callback, user_data, ex);
450 _set_name (CamelFolder *folder,
456 const gchar *parent_full_name;
459 camel_exception_set (ex,
460 CAMEL_EXCEPTION_FOLDER_NULL,
461 "folder object is NULL");
465 /* if the folder already has a name, free it */
466 g_free (folder->name);
467 g_free (folder->full_name);
469 /* set those fields to NULL now, so that if an
470 exception occurs, they will be set anyway */
472 folder->full_name = NULL;
475 camel_exception_set (ex,
476 CAMEL_EXCEPTION_INVALID_PARAM,
477 "name parameter is NULL");
482 if (!folder->parent_store) {
483 camel_exception_set (ex,
484 CAMEL_EXCEPTION_FOLDER_INVALID,
485 "folder has no parent store");
489 /* the set_name method is valid only only on
492 if (camel_folder_get_mode (folder, ex) != FOLDER_CLOSE) {
493 camel_exception_set (ex,
494 CAMEL_EXCEPTION_FOLDER_INVALID,
495 "CamelFolder::set_name is valid only on closed folders");
499 separator = camel_store_get_separator (folder->parent_store, ex);
500 camel_exception_clear (ex);
501 if (folder->parent_folder) {
502 parent_full_name = camel_folder_get_full_name (folder->parent_folder, ex);
503 if (camel_exception_get_id (ex)) return;
505 full_name = g_strdup_printf ("%s%d%s", parent_full_name, separator, name);
508 folder->name = g_strdup (name);
509 folder->full_name = full_name;
515 * camel_folder_set_name:set the (short) name of the folder
517 * @name: new name of the folder
518 * @ex: exception object
521 camel_folder_set_name (CamelFolder *folder, const gchar *name, CamelException *ex)
524 camel_exception_set (ex,
525 CAMEL_EXCEPTION_FOLDER_NULL,
526 "folder object is NULL");
529 CF_CLASS(folder)->set_name (folder, name, ex);
536 /* not used for the moment, I don't know if it it is
537 a good idea or not to use it */
540 _set_full_name (CamelFolder *folder, const gchar *name, CamelException *ex)
543 camel_exception_set (ex,
544 CAMEL_EXCEPTION_FOLDER_NULL,
545 "folder object is NULL");
548 g_free(folder->full_name);
549 folder->full_name = g_strdup (name);
554 * camel_folder_set_full_name:set the (full) name of the folder
556 * @name: new name of the folder
558 * set the name of the folder.
562 camel_folder_set_full_name (CamelFolder *folder, const gchar *name, CamelException *ex)
565 camel_exception_set (ex,
566 CAMEL_EXCEPTION_FOLDER_NULL,
567 "folder object is NULL");
571 CF_CLASS(folder)->set_full_name (folder, name, ex);
579 _get_name (CamelFolder *folder, CamelException *ex)
582 camel_exception_set (ex,
583 CAMEL_EXCEPTION_FOLDER_NULL,
584 "folder object is NULL");
592 * camel_folder_get_name: get the (short) name of the folder
595 * get the name of the folder. The fully qualified name
596 * can be obtained with the get_full_ame method (not implemented)
598 * Return value: name of the folder
601 camel_folder_get_name (CamelFolder *folder, CamelException *ex)
604 camel_exception_set (ex,
605 CAMEL_EXCEPTION_FOLDER_NULL,
606 "folder object is NULL");
610 return CF_CLASS(folder)->get_name (folder, ex);
616 _get_full_name (CamelFolder *folder, CamelException *ex)
619 camel_exception_set (ex,
620 CAMEL_EXCEPTION_FOLDER_NULL,
621 "folder object is NULL");
625 return folder->full_name;
629 * camel_folder_get_full_name:get the (full) name of the folder
630 * @folder: folder to get the name
632 * get the name of the folder.
634 * Return value: full name of the folder
637 camel_folder_get_full_name (CamelFolder *folder, CamelException *ex)
640 camel_exception_set (ex,
641 CAMEL_EXCEPTION_FOLDER_NULL,
642 "folder object is NULL");
646 return CF_CLASS(folder)->get_full_name (folder, ex);
651 * _can_hold_folders: tests if the folder can contain other folders
652 * @folder: The folder object
654 * Tests if a folder can contain other folder
655 * (as for example MH folders)
660 _can_hold_folders (CamelFolder *folder, CamelException *ex)
663 camel_exception_set (ex,
664 CAMEL_EXCEPTION_FOLDER_NULL,
665 "folder object is NULL");
669 return folder->can_hold_folders;
676 * _can_hold_messages: tests if the folder can contain messages
677 * @folder: The folder object
679 * Tests if a folder object can contain messages.
680 * In the case it can not, it most surely can only
681 * contain folders (rare).
683 * Return value: true if it can contain messages false otherwise
686 _can_hold_messages (CamelFolder *folder, CamelException *ex)
689 camel_exception_set (ex,
690 CAMEL_EXCEPTION_FOLDER_NULL,
691 "folder object is NULL");
695 return folder->can_hold_messages;
701 _exists (CamelFolder *folder, CamelException *ex)
704 camel_exception_set (ex,
705 CAMEL_EXCEPTION_FOLDER_NULL,
706 "folder object is NULL");
715 * _exists: tests if the folder object exists in its parent store.
716 * @folder: folder object
718 * Test if a folder exists on a store. A folder can be
719 * created without physically on a store. In that case,
720 * use CamelFolder::create to create it
722 * Return value: true if the folder exists on the store false otherwise
725 camel_folder_exists (CamelFolder *folder, CamelException *ex)
728 camel_exception_set (ex,
729 CAMEL_EXCEPTION_FOLDER_NULL,
730 "folder object is NULL");
734 return (CF_CLASS(folder)->exists (folder, ex));
740 * _is_open: test if the folder is open
741 * @folder: The folder object
743 * Tests if a folder is open. If not open it can be opened
746 * Return value: true if the folder exists, false otherwise
749 _is_open (CamelFolder *folder, CamelException *ex)
752 camel_exception_set (ex,
753 CAMEL_EXCEPTION_FOLDER_NULL,
754 "folder object is NULL");
758 return (folder->open_state == FOLDER_OPEN);
766 _get_subfolder (CamelFolder *folder,
767 const gchar *folder_name,
770 CamelFolder *new_folder;
772 const gchar *current_folder_full_name;
776 camel_exception_set (ex,
777 CAMEL_EXCEPTION_FOLDER_NULL,
778 "folder object is NULL");
784 camel_exception_set (ex,
785 CAMEL_EXCEPTION_INVALID_PARAM,
786 "folder_name parameter is NULL");
790 if (!folder->parent_store) {
791 camel_exception_set (ex,
792 CAMEL_EXCEPTION_FOLDER_INVALID,
793 "folder has no parent store");
797 current_folder_full_name = camel_folder_get_full_name (folder, ex);
798 if (camel_exception_get_id (ex)) return NULL;
801 separator = camel_store_get_separator (folder->parent_store, ex);
802 full_name = g_strdup_printf ("%s%d%s", current_folder_full_name, separator, folder_name);
804 new_folder = camel_store_get_folder (folder->parent_store, full_name, ex);
811 * camel_folder_get_subfolder: return the (sub)folder object that is specified
812 * @folder: the folder
813 * @folder_name: subfolder path
815 * This method returns a folder objects. This folder
816 * is necessarily a subfolder of the current folder.
817 * It is an error to ask a folder begining with the
818 * folder separator character.
820 * Return value: Required folder. NULL if the subfolder object could not be obtained
823 camel_folder_get_subfolder (CamelFolder *folder, gchar *folder_name, CamelException *ex)
826 camel_exception_set (ex,
827 CAMEL_EXCEPTION_FOLDER_NULL,
828 "folder object is NULL");
832 return (CF_CLASS(folder)->get_subfolder(folder,folder_name, ex));
839 * _create: creates a folder on its store
840 * @folder: a CamelFolder object.
842 * this routine handles the recursion mechanism.
843 * Children classes have to implement the actual
844 * creation mechanism. They must call this method
845 * before physically creating the folder in order
846 * to be sure the parent folder exists.
847 * Calling this routine on an existing folder is
848 * not an error, and returns %TRUE.
850 * Return value: %TRUE if the folder exists, %FALSE otherwise
853 _create (CamelFolder *folder, CamelException *ex)
861 g_assert (folder->parent_store);
862 g_assert (folder->name);
865 camel_exception_set (ex,
866 CAMEL_EXCEPTION_FOLDER_NULL,
867 "folder object is NULL");
873 camel_exception_set (ex,
874 CAMEL_EXCEPTION_FOLDER_INVALID,
875 "folder has no name");
879 if (!folder->parent_store) {
880 camel_exception_set (ex,
881 CAMEL_EXCEPTION_FOLDER_INVALID,
882 "folder has no parent store");
886 /* if the folder already exists on the
887 store, do nothing and return true */
888 if (CF_CLASS(folder)->exists (folder, ex))
892 sep = camel_store_get_separator (folder->parent_store, ex);
893 if (folder->parent_folder) {
894 camel_folder_create (folder->parent_folder, ex);
895 if (camel_exception_get_id (ex)) return FALSE;
898 if (folder->full_name) {
899 dich_result = string_dichotomy (
900 folder->full_name, sep, &prefix, NULL,
901 STRING_DICHOTOMY_STRIP_TRAILING | STRING_DICHOTOMY_RIGHT_DIR);
902 if (dich_result!='o') {
903 g_warning("have to handle the case where the path is not OK\n");
906 parent = camel_store_get_folder (folder->parent_store, prefix, ex);
907 camel_folder_create (parent, ex);
908 if (camel_exception_get_id (ex)) return FALSE;
917 * camel_folder_create: create the folder object on the physical store
918 * @folder: folder object to create
920 * This routine physically creates the folder object on
921 * the store. Having created the object does not
922 * mean the folder physically exists. If it does not
923 * exists, this routine will create it.
924 * if the folder full name contains more than one level
925 * of hierarchy, all folders between the current folder
926 * and the last folder name will be created if not existing.
931 camel_folder_create (CamelFolder *folder, CamelException *ex)
934 camel_exception_set (ex,
935 CAMEL_EXCEPTION_FOLDER_NULL,
936 "folder object is NULL");
940 return (CF_CLASS(folder)->create(folder, ex));
948 * _delete: delete folder
949 * @folder: folder to delete
950 * @recurse: true is subfolders must also be deleted
952 * Delete a folder and its subfolders (if recurse is TRUE).
953 * The scheme is the following:
954 * 1) delete all messages in the folder
955 * 2) if recurse is FALSE, and if there are subfolders
956 * return FALSE, else delete current folder and retuen TRUE
957 * if recurse is TRUE, delete subfolders, delete
958 * current folder and return TRUE
960 * subclasses implementing a protocol with a different
961 * deletion behaviour must emulate this one or implement
962 * empty folders deletion and call this routine which
963 * will do all the works for them.
964 * Opertions must be done in the folllowing order:
965 * - call this routine
966 * - delete empty folder
968 * Return value: true if the folder has been deleted
971 _delete (CamelFolder *folder, gboolean recurse, CamelException *ex)
973 GList *subfolders=NULL;
979 /* method valid only on closed folders */
980 if (folder->open_state != FOLDER_CLOSE) {
981 camel_exception_set (ex, CAMEL_EXCEPTION_FOLDER_INVALID_STATE,
982 "Delete operation invalid on opened folders");
986 /* delete all messages in the folder */
987 CF_CLASS(folder)->delete_messages(folder, ex);
988 if (camel_exception_get_id (ex)) return FALSE;
990 subfolders = CF_CLASS(folder)->list_subfolders(folder, ex);
991 if (camel_exception_get_id (ex)) {
992 if (subfolders) g_list_free (subfolders);
997 if (recurse) { /* delete subfolders */
1001 CF_CLASS(sf->data)->delete(CAMEL_FOLDER(sf->data), TRUE, ex);
1002 if (camel_exception_get_id (ex)) ok = FALSE;
1003 } while (ok && (sf = sf->next));
1005 } else if (subfolders) {
1006 camel_exception_set (ex, CAMEL_EXCEPTION_FOLDER_NON_EMPTY,
1007 "folder has subfolders");
1011 if (subfolders) g_list_free (subfolders);
1019 * camel_folder_delete: delete a folder
1020 * @folder: folder to delete
1021 * @recurse: TRUE if subfolders must be deleted
1023 * Delete a folder. All messages in the folder
1024 * are deleted before the folder is deleted.
1025 * When recurse is true, all subfolders are
1026 * deleted too. When recurse is FALSE and folder
1027 * contains subfolders, all messages are deleted,
1028 * but folder deletion fails.
1030 * Return value: TRUE if deletion was successful
1032 gboolean camel_folder_delete (CamelFolder *folder, gboolean recurse, CamelException *ex)
1035 camel_exception_set (ex,
1036 CAMEL_EXCEPTION_FOLDER_NULL,
1037 "folder object is NULL");
1041 return CF_CLASS(folder)->delete(folder, recurse, ex);
1049 * _delete_messages: delete all messages in the folder
1057 _delete_messages (CamelFolder *folder, CamelException *ex)
1060 camel_exception_set (ex,
1061 CAMEL_EXCEPTION_FOLDER_NULL,
1062 "folder object is NULL");
1066 CAMEL_LOG_WARNING ("Calling CamelFolder::delete_messages directly. "
1067 "Should be overloaded\n");
1073 * camel_folder_delete_messages: delete all messages in the folder
1076 * delete all messages stored in a folder
1078 * Return value: TRUE if the messages could be deleted
1081 camel_folder_delete_messages (CamelFolder *folder, CamelException *ex)
1084 camel_exception_set (ex,
1085 CAMEL_EXCEPTION_FOLDER_NULL,
1086 "folder object is NULL");
1090 return CF_CLASS(folder)->delete_messages(folder, ex);
1099 * _get_parent_folder: return parent folder
1100 * @folder: folder to get the parent
1106 static CamelFolder *
1107 _get_parent_folder (CamelFolder *folder, CamelException *ex)
1110 camel_exception_set (ex,
1111 CAMEL_EXCEPTION_FOLDER_NULL,
1112 "folder object is NULL");
1116 return folder->parent_folder;
1121 * camel_folder_get_parent_folder:return parent folder
1122 * @folder: folder to get the parent
1129 camel_folder_get_parent_folder (CamelFolder *folder, CamelException *ex)
1132 camel_exception_set (ex,
1133 CAMEL_EXCEPTION_FOLDER_NULL,
1134 "folder object is NULL");
1138 return CF_CLASS(folder)->get_parent_folder(folder, ex);
1143 * _get_parent_store: return parent store
1144 * @folder: folder to get the parent
1151 _get_parent_store (CamelFolder *folder, CamelException *ex)
1154 camel_exception_set (ex,
1155 CAMEL_EXCEPTION_FOLDER_NULL,
1156 "folder object is NULL");
1160 return folder->parent_store;
1165 * camel_folder_get_parent_store: return parent store
1166 * @folder: folder to get the parent
1168 * Return the parent store of a folder
1170 * Return value: the parent store.
1173 camel_folder_get_parent_store (CamelFolder *folder, CamelException *ex)
1176 camel_exception_set (ex,
1177 CAMEL_EXCEPTION_FOLDER_NULL,
1178 "folder object is NULL");
1182 return CF_CLASS(folder)->get_parent_store(folder, ex);
1188 static CamelFolderOpenMode
1189 _get_mode (CamelFolder *folder, CamelException *ex)
1192 camel_exception_set (ex,
1193 CAMEL_EXCEPTION_FOLDER_NULL,
1194 "folder object is NULL");
1195 return FOLDER_OPEN_UNKNOWN;
1198 return folder->open_mode;
1203 * camel_folder_get_mode: return the open mode of a folder
1208 * Return value: open mode of the folder
1211 camel_folder_get_mode (CamelFolder *folder, CamelException *ex)
1214 camel_exception_set (ex,
1215 CAMEL_EXCEPTION_FOLDER_NULL,
1216 "folder object is NULL");
1217 return FOLDER_OPEN_UNKNOWN;
1220 return CF_CLASS(folder)->get_mode(folder, ex);
1227 _list_subfolders (CamelFolder *folder, CamelException *ex)
1230 camel_exception_set (ex,
1231 CAMEL_EXCEPTION_FOLDER_NULL,
1232 "folder object is NULL");
1236 CAMEL_LOG_WARNING ("Calling CamelFolder::list_subfolders directly. "
1237 "Should be overloaded\n");
1243 * camel_folder_list_subfolders: list subfolders in a folder
1244 * @folder: the folder
1246 * List subfolders in a folder.
1248 * Return value: list of subfolders
1251 camel_folder_list_subfolders (CamelFolder *folder, CamelException *ex)
1254 camel_exception_set (ex,
1255 CAMEL_EXCEPTION_FOLDER_NULL,
1256 "folder object is NULL");
1260 return CF_CLASS(folder)->list_subfolders(folder, ex);
1267 _expunge (CamelFolder *folder, CamelException *ex)
1270 camel_exception_set (ex,
1271 CAMEL_EXCEPTION_FOLDER_NULL,
1272 "folder object is NULL");
1276 CAMEL_LOG_WARNING ("Calling CamelFolder::expunge directly. "
1277 "Should be overloaded\n");
1283 * camel_folder_expunge: physically delete messages marked as "DELETED"
1284 * @folder: the folder
1286 * Delete messages which have been marked as "DELETED"
1288 * Return value: list of expunged messages
1291 camel_folder_expunge (CamelFolder *folder, CamelException *ex)
1294 camel_exception_set (ex,
1295 CAMEL_EXCEPTION_FOLDER_NULL,
1296 "folder object is NULL");
1300 return CF_CLASS (folder)->expunge (folder, ex);
1305 _has_message_number_capability (CamelFolder *folder, CamelException *ex)
1308 camel_exception_set (ex,
1309 CAMEL_EXCEPTION_FOLDER_NULL,
1310 "folder object is NULL");
1314 CAMEL_LOG_WARNING ("Calling CamelFolder::has_message_number_capability directly. "
1315 "Should be overloaded\n");
1322 * camel_folder_has_message_number_capability: tests if the message can be numbered within the folder
1323 * @folder: folder to test
1325 * Test if the message in this folder can be
1326 * obtained via the get_by_number method.
1327 * Usually, when the folder has the UID
1328 * capability, messages should be referred to
1329 * by their UID rather than by their number
1330 * as the UID is more reliable.
1332 * Return value: TRUE if the folder supports message numbering, FALSE otherwise.
1335 camel_folder_has_message_number_capability (CamelFolder *folder, CamelException *ex)
1338 camel_exception_set (ex,
1339 CAMEL_EXCEPTION_FOLDER_NULL,
1340 "folder object is NULL");
1344 return CF_CLASS(folder)->has_message_number_capability (folder, ex);
1350 static CamelMimeMessage *
1351 _get_message_by_number (CamelFolder *folder, gint number, CamelException *ex)
1354 camel_exception_set (ex,
1355 CAMEL_EXCEPTION_FOLDER_NULL,
1356 "folder object is NULL");
1360 CAMEL_LOG_WARNING ("Calling CamelFolder::get_message_by_number directly. "
1361 "Should be overloaded\n");
1369 * camel_folder_get_message_by_number: return the message corresponding to that number in the folder
1370 * @folder: a CamelFolder object
1371 * @number: the number of the message within the folder.
1373 * Return the message corresponding to that number within the folder.
1375 * Return value: A pointer on the corresponding message or NULL if no corresponding message exists
1378 camel_folder_get_message_by_number (CamelFolder *folder, gint number, CamelException *ex)
1381 camel_exception_set (ex,
1382 CAMEL_EXCEPTION_FOLDER_NULL,
1383 "folder object is NULL");
1387 return CF_CLASS (folder)->get_message_by_number (folder, number, ex);
1392 _get_message_count (CamelFolder *folder, CamelException *ex)
1394 CAMEL_LOG_WARNING ("Calling CamelFolder::get_message_count directly. "
1395 "Should be overloaded\n");
1402 * camel_folder_get_message_count: get the number of messages in the folder
1403 * @folder: A CamelFolder object
1405 * Returns the number of messages in the folder.
1407 * Return value: the number of messages or -1 if unknown.
1410 camel_folder_get_message_count (CamelFolder *folder, CamelException *ex)
1413 camel_exception_set (ex,
1414 CAMEL_EXCEPTION_FOLDER_NULL,
1415 "folder object is NULL");
1419 return CF_CLASS (folder)->get_message_count (folder, ex);
1424 _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex)
1427 camel_exception_set (ex,
1428 CAMEL_EXCEPTION_FOLDER_NULL,
1429 "folder object is NULL");
1433 CAMEL_LOG_WARNING ("Calling CamelFolder::append_message directly. "
1434 "Should be overloaded\n");
1441 * camel_folder_append_message: add a message to a folder
1442 * @folder: folder object to add the message to
1443 * @message: message object
1444 * @ex: exception object
1446 * Add a message to a folder.
1450 camel_folder_append_message (CamelFolder *folder,
1451 CamelMimeMessage *message,
1455 camel_exception_set (ex,
1456 CAMEL_EXCEPTION_FOLDER_NULL,
1457 "folder object is NULL");
1461 CF_CLASS (folder)->append_message (folder, message, ex);
1465 static const GList *
1466 _list_permanent_flags (CamelFolder *folder, CamelException *ex)
1469 camel_exception_set (ex,
1470 CAMEL_EXCEPTION_FOLDER_NULL,
1471 "folder object is NULL");
1475 return folder->permanent_flags;
1480 camel_folder_list_permanent_flags (CamelFolder *folder, CamelException *ex)
1483 camel_exception_set (ex,
1484 CAMEL_EXCEPTION_FOLDER_NULL,
1485 "folder object is NULL");
1489 return CF_CLASS (folder)->list_permanent_flags (folder, ex);
1496 _copy_message_to (CamelFolder *folder, CamelMimeMessage *message, CamelFolder *dest_folder, CamelException *ex)
1499 camel_exception_set (ex,
1500 CAMEL_EXCEPTION_FOLDER_NULL,
1501 "folder object is NULL");
1505 camel_folder_append_message (dest_folder, message, ex);
1510 camel_folder_copy_message_to (CamelFolder *folder,
1511 CamelMimeMessage *message,
1512 CamelFolder *dest_folder,
1516 camel_exception_set (ex,
1517 CAMEL_EXCEPTION_FOLDER_NULL,
1518 "folder object is NULL");
1522 CF_CLASS (folder)->copy_message_to (folder, message, dest_folder, ex);;
1532 camel_folder_has_summary_capability (CamelFolder *folder,
1536 camel_exception_set (ex,
1537 CAMEL_EXCEPTION_FOLDER_NULL,
1538 "folder object is NULL");
1542 return folder->has_summary_capability;
1547 * camel_folder_get_summary: return the summary of a folder
1548 * @folder: folder object
1549 * @ex: exception object
1551 * Return a CamelFolderSummary object from
1552 * which the main informations about a folder
1555 * Return value: the folder summary object.
1557 CamelFolderSummary *
1558 camel_folder_get_summary (CamelFolder *folder,
1562 camel_exception_set (ex,
1563 CAMEL_EXCEPTION_FOLDER_NULL,
1564 "folder object is NULL");
1568 return folder->summary;
1577 * camel_folder_has_uid_capability: detect if the folder support UIDs
1578 * @folder: Folder object
1580 * Detects if a folder supports UID operations, that is
1581 * reference messages by a Unique IDentifier instead
1582 * of by message number.
1584 * Return value: TRUE if the folder supports UIDs
1587 camel_folder_has_uid_capability (CamelFolder *folder, CamelException *ex)
1590 camel_exception_set (ex,
1591 CAMEL_EXCEPTION_FOLDER_NULL,
1592 "folder object is NULL");
1596 return folder->has_uid_capability;
1601 static const gchar *
1602 _get_message_uid (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex)
1604 CAMEL_LOG_WARNING ("Calling CamelFolder::get_message_uid directly. "
1605 "Should be overloaded\n");
1610 * camel_folder_get_message_uid: get the UID of a message in a folder
1611 * @folder: Folder in which the UID must refer to
1612 * @message: Message object
1614 * Return the UID of a message relatively to a folder.
1615 * A message can have different UID, each one corresponding
1616 * to a different folder, if the message is referenced in
1619 * Return value: The UID of the message in the folder
1622 camel_folder_get_message_uid (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex)
1625 camel_exception_set (ex,
1626 CAMEL_EXCEPTION_FOLDER_NULL,
1627 "folder object is NULL");
1631 if (!folder->has_uid_capability) {
1632 camel_exception_set (ex,
1633 CAMEL_EXCEPTION_FOLDER_NON_UID,
1634 "folder is not UID capable");
1638 return CF_CLASS (folder)->get_message_uid (folder, message, ex);
1643 /* the next two func are left there temporarily */
1644 static const gchar *
1645 _get_message_uid_by_number (CamelFolder *folder, gint message_number, CamelException *ex)
1648 camel_exception_set (ex,
1649 CAMEL_EXCEPTION_FOLDER_NULL,
1650 "folder object is NULL");
1654 CAMEL_LOG_WARNING ("Calling CamelFolder::get_message_uid_by_number directly. "
1655 "Should be overloaded\n");
1660 * camel_folder_get_message_uid_by_number: get the UID corresponding to a message number
1661 * @folder: Folder object
1662 * @message_number: Message number
1664 * get the UID corresponding to a message number.
1665 * Use of this routine should be avoiding, as on
1666 * folders supporting UIDs, message numbers should
1672 camel_folder_get_message_uid_by_number (CamelFolder *folder, gint message_number, CamelException *ex)
1675 camel_exception_set (ex,
1676 CAMEL_EXCEPTION_FOLDER_NULL,
1677 "folder object is NULL");
1681 /* if (!folder->has_uid_capability) return NULL; */
1682 /* return CF_CLASS (folder)->get_message_uid_by_number (folder, message_number, ex); */
1686 static CamelMimeMessage *
1687 _get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex)
1689 CAMEL_LOG_WARNING ("Calling CamelFolder::get_message_by_uid directly. "
1690 "Should be overloaded\n");
1696 * camel_folder_get_message_by_uid: Get a message by its UID in a folder
1697 * @folder: the folder object
1700 * Get a message from its UID in the folder. Messages
1701 * are cached within a folder, that is, asking twice
1702 * for the same UID returns the same message object.
1704 * Return value: Message corresponding to the UID
1707 camel_folder_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex)
1710 camel_exception_set (ex,
1711 CAMEL_EXCEPTION_FOLDER_NULL,
1712 "folder object is NULL");
1716 if (!folder->has_uid_capability) {
1717 camel_exception_set (ex,
1718 CAMEL_EXCEPTION_FOLDER_NON_UID,
1719 "folder is not UID capable");
1723 return CF_CLASS (folder)->get_message_by_uid (folder, uid, ex);
1727 _get_uid_list (CamelFolder *folder, CamelException *ex)
1730 camel_exception_set (ex,
1731 CAMEL_EXCEPTION_FOLDER_NULL,
1732 "folder object is NULL");
1736 if (!folder->has_uid_capability) {
1737 camel_exception_set (ex,
1738 CAMEL_EXCEPTION_FOLDER_NON_UID,
1739 "folder is not UID capable");
1743 CAMEL_LOG_WARNING ("Calling CamelFolder::get_uid_list directly. "
1744 "Should be overloaded\n");
1749 * camel_folder_get_uid_list: get the list of UID in a folder
1750 * @folder: folder object
1752 * get the list of UID available in a folder. This
1753 * routine is usefull to know what messages are
1754 * available when the folder does not support
1755 * summaries. The UIDs in the list must not be freed,
1756 * the folder object caches them.
1758 * Return value: Glist of UID correspondind to the messages available in the folder.
1761 camel_folder_get_uid_list (CamelFolder *folder, CamelException *ex)
1764 camel_exception_set (ex,
1765 CAMEL_EXCEPTION_FOLDER_NULL,
1766 "folder object is NULL");
1770 if (!folder->has_uid_capability) {
1771 camel_exception_set (ex,
1772 CAMEL_EXCEPTION_FOLDER_NON_UID,
1773 "folder is not UID capable");
1777 return CF_CLASS (folder)->get_uid_list (folder, ex);