3b22011d554fb7f85b23b9597ff1a684f58862a3
[platform/upstream/evolution-data-server.git] / camel / camel-folder.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* camelFolder.c : Abstract class for an email folder */
3
4 /* 
5  *
6  * Author : 
7  *  Bertrand Guiheneuf <bertrand@helixcode.com>
8  *
9  * Copyright 1999, 2000 HelixCode (http://www.helixcode.com) .
10  *
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.
15  *
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.
20  *
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
24  * USA
25  */
26 #include <config.h>
27 #include "camel-folder.h"
28 #include "camel-log.h"
29 #include "string-utils.h"
30
31 static GtkObjectClass *parent_class=NULL;
32
33 /* Returns the class for a CamelFolder */
34 #define CF_CLASS(so) CAMEL_FOLDER_CLASS (GTK_OBJECT(so)->klass)
35
36
37
38
39 static void _init_with_store (CamelFolder *folder, 
40                               CamelStore *parent_store, 
41                               CamelException *ex);
42 static void _finalize (GtkObject *object);
43
44
45 static void _open (CamelFolder *folder, 
46                    CamelFolderOpenMode mode, 
47                    CamelException *ex);
48 static void _close (CamelFolder *folder, 
49                     gboolean expunge, 
50                     CamelException *ex);
51
52 /* Async operations are not used for the moment */
53 static void _open_async (CamelFolder *folder, 
54                          CamelFolderOpenMode mode, 
55                          CamelFolderAsyncCallback callback, 
56                          gpointer user_data, 
57                          CamelException *ex);
58 static void _close_async (CamelFolder *folder, 
59                           gboolean expunge, 
60                           CamelFolderAsyncCallback callback, 
61                           gpointer user_data, 
62                           CamelException *ex);
63
64
65 static void _set_name (CamelFolder *folder, 
66                        const gchar *name, 
67                        CamelException *ex);
68 static const gchar *_get_name (CamelFolder *folder, 
69                                CamelException *ex);
70 static const gchar *_get_full_name (CamelFolder *folder, CamelException *ex);
71 /*  static void _set_full_name (CamelFolder *folder, const gchar *name); */
72
73
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);
80
81
82 static gboolean _create (CamelFolder *folder, CamelException *ex);
83 static gboolean _delete (CamelFolder *folder, gboolean recurse, CamelException *ex);
84
85
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);
91
92
93 static gboolean _has_message_number_capability (CamelFolder *folder, CamelException *ex);
94 static CamelMimeMessage *_get_message_by_number (CamelFolder *folder, 
95                                                  gint number, 
96                                                  CamelException *ex);
97 static gint _get_message_count        (CamelFolder *folder, 
98                                        CamelException *ex);
99
100
101 static gboolean _delete_messages (CamelFolder *folder, 
102                                   CamelException *ex);
103 static GList * _expunge         (CamelFolder *folder, 
104                               CamelException *ex);
105 static void _append_message  (CamelFolder *folder, 
106                               CamelMimeMessage *message, 
107                               CamelException *ex);
108 static void _copy_message_to (CamelFolder *folder, 
109                               CamelMimeMessage *message, 
110                               CamelFolder *dest_folder, 
111                               CamelException *ex);
112
113
114 static GList            *_get_uid_list       (CamelFolder *folder, CamelException *ex);
115 static const gchar      *_get_message_uid    (CamelFolder *folder, 
116                                               CamelMimeMessage *message, 
117                                               CamelException *ex);
118 static CamelMimeMessage *_get_message_by_uid (CamelFolder *folder, 
119                                               const gchar *uid, 
120                                               CamelException *ex);
121
122
123
124
125 static void
126 camel_folder_class_init (CamelFolderClass *camel_folder_class)
127 {
128         GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (camel_folder_class);
129         
130         parent_class = gtk_type_class (gtk_object_get_type ());
131         
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;
163
164         /* virtual method overload */
165         gtk_object_class->finalize = _finalize;
166 }
167
168
169
170
171
172
173
174 GtkType
175 camel_folder_get_type (void)
176 {
177         static GtkType camel_folder_type = 0;
178         
179         if (!camel_folder_type) {
180                 GtkTypeInfo camel_folder_info = 
181                 {
182                         "CamelFolder",
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,
190                 };
191                 
192                 camel_folder_type = gtk_type_unique (gtk_object_get_type (), &camel_folder_info);
193         }
194         
195         return camel_folder_type;
196 }
197
198
199 static void           
200 _finalize (GtkObject *object)
201 {
202         CamelFolder *camel_folder = CAMEL_FOLDER (object);
203         GList *message_node;
204
205         CAMEL_LOG_FULL_DEBUG ("Entering CamelFolder::finalize\n");
206
207         g_free (camel_folder->name);
208         g_free (camel_folder->full_name);
209         g_free (camel_folder->permanent_flags);
210
211         GTK_OBJECT_CLASS (parent_class)->finalize (object);
212         CAMEL_LOG_FULL_DEBUG ("Leaving CamelFolder::finalize\n");
213 }
214
215
216 /**
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
220  * 
221  * 
222  **/
223 static void 
224 _init_with_store (CamelFolder *folder, CamelStore *parent_store, CamelException *ex)
225 {
226         
227         if (!folder) {
228                 camel_exception_set (ex, 
229                                      CAMEL_EXCEPTION_FOLDER_NULL,
230                                      "folder object is NULL");
231                 return;
232         }
233
234         if (!parent_store) {
235                 camel_exception_set (ex, 
236                                      CAMEL_EXCEPTION_INVALID_PARAM,
237                                      "parent_store parameter is NULL");
238                 return;
239         }
240         
241         if (folder->parent_store) {
242                 camel_exception_set (ex, 
243                                      CAMEL_EXCEPTION_FOLDER_INVALID,
244                                      "folder already has a parent store");
245                 return;
246         }
247         
248         folder->parent_store = parent_store;
249         gtk_object_ref (GTK_OBJECT (parent_store));
250         
251         folder->open_mode = FOLDER_OPEN_UNKNOWN;
252         folder->open_state = FOLDER_CLOSE;
253         folder->name = NULL;
254         folder->full_name = NULL;
255 }
256
257
258
259
260
261 static void
262 _open (CamelFolder *folder, 
263        CamelFolderOpenMode mode, 
264        CamelException *ex)
265 {
266         if (!folder) {
267                 camel_exception_set (ex, 
268                                      CAMEL_EXCEPTION_FOLDER_NULL,
269                                      "folder object is NULL");
270                 return;
271         }
272
273         folder->open_state = FOLDER_OPEN;
274         folder->open_mode = mode;
275 }
276
277
278
279
280 /**
281  * camel_folder_open: Open a folder
282  * @folder: The folder object
283  * @mode: open mode (R/W/RW ?)
284  * @ex: exception object
285  *
286  * Open a folder in a given mode.
287  * 
288  **/
289 void 
290 camel_folder_open (CamelFolder *folder, 
291                    CamelFolderOpenMode mode, 
292                    CamelException *ex)
293 {       
294         if (!folder) {
295                 camel_exception_set (ex, 
296                                      CAMEL_EXCEPTION_FOLDER_NULL,
297                                      "folder object is NULL");
298                 return;
299         }
300         CF_CLASS(folder)->open (folder, mode, ex);
301 }
302
303
304
305
306
307
308 static void
309 _open_async (CamelFolder *folder, 
310              CamelFolderOpenMode mode, 
311              CamelFolderAsyncCallback callback, 
312              gpointer user_data, 
313              CamelException *ex)
314 {
315         CAMEL_LOG_WARNING ("Calling CamelFolder::open_async directly. "
316                            "Should be overloaded\n");
317 }
318
319
320
321 /**
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
328  *
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. 
332  * 
333  **/
334 void 
335 camel_folder_open_async (CamelFolder *folder, 
336                          CamelFolderOpenMode mode, 
337                          CamelFolderAsyncCallback callback, 
338                          gpointer user_data, 
339                          CamelException *ex)
340 {       
341         if (!folder) {
342                 camel_exception_set (ex, 
343                                      CAMEL_EXCEPTION_FOLDER_NULL,
344                                      "folder object is NULL");
345                 return;
346         }
347         CF_CLASS(folder)->open_async (folder, mode, callback, user_data, ex);
348 }
349
350
351
352
353
354
355 static void
356 _close (CamelFolder *folder, 
357         gboolean expunge, 
358         CamelException *ex)
359 {       
360         if (!folder) {
361                 camel_exception_set (ex, 
362                                      CAMEL_EXCEPTION_FOLDER_NULL,
363                                      "folder object is NULL");
364                 return;
365         }
366         folder->open_state = FOLDER_CLOSE;
367 }
368
369 /**
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
374  *
375  * Put a folder in its closed state, and possibly 
376  * expunge the flagged messages. 
377  * 
378  **/
379 void 
380 camel_folder_close (CamelFolder *folder, 
381                     gboolean expunge, 
382                     CamelException *ex)
383 {
384         if (!folder) {
385                 camel_exception_set (ex, 
386                                      CAMEL_EXCEPTION_FOLDER_NULL,
387                                      "folder object is NULL");
388                 return;
389         }
390         CF_CLASS(folder)->close (folder, expunge, ex);
391 }
392
393
394
395
396
397
398 static void
399 _close_async (CamelFolder *folder, 
400               gboolean expunge, 
401               CamelFolderAsyncCallback callback, 
402               gpointer user_data, 
403               CamelException *ex)
404 {       
405         if (!folder) {
406                 camel_exception_set (ex, 
407                                      CAMEL_EXCEPTION_FOLDER_NULL,
408                                      "folder object is NULL");
409                 return;
410         }
411         CAMEL_LOG_WARNING ("Calling CamelFolder::close_async directly. "
412                            "Should be overloaded\n");
413 }
414
415 /**
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
422  *
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. 
427  * 
428  **/
429 void 
430 camel_folder_close_async (CamelFolder *folder, 
431                           gboolean expunge, 
432                           CamelFolderAsyncCallback callback, 
433                           gpointer user_data, 
434                           CamelException *ex)
435 {
436         if (!folder) {
437                 camel_exception_set (ex, 
438                                      CAMEL_EXCEPTION_FOLDER_NULL,
439                                      "folder object is NULL");
440                 return;
441         }
442         CF_CLASS(folder)->close_async (folder, expunge, callback, user_data, ex);
443 }
444
445
446
447
448
449 static void
450 _set_name (CamelFolder *folder, 
451            const gchar *name, 
452            CamelException *ex)
453 {
454         gchar separator;
455         gchar *full_name;
456         const gchar *parent_full_name;
457         
458         if (!folder) {
459                 camel_exception_set (ex, 
460                                      CAMEL_EXCEPTION_FOLDER_NULL,
461                                      "folder object is NULL");
462                 return;
463         }
464
465         /* if the folder already has a name, free it */ 
466         g_free (folder->name);
467         g_free (folder->full_name);
468         
469         /* set those fields to NULL now, so that if an 
470            exception occurs, they will be set anyway */
471         folder->name = NULL;
472         folder->full_name = NULL;
473
474         if (!name) {
475                 camel_exception_set (ex, 
476                                      CAMEL_EXCEPTION_INVALID_PARAM,
477                                      "name parameter is NULL");
478                 return;
479         }       
480         
481         
482         if (!folder->parent_store) {
483                 camel_exception_set (ex, 
484                                      CAMEL_EXCEPTION_FOLDER_INVALID,
485                                      "folder has no parent store");
486                 return;
487         }
488
489         /* the set_name method is valid only only on 
490            close folders */
491
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");
496                 return;         
497         }
498                         
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;
504                 
505                 full_name = g_strdup_printf ("%s%d%s", parent_full_name, separator, name);              
506         } 
507         
508         folder->name = g_strdup (name);
509         folder->full_name = full_name;
510         
511 }
512
513
514 /**
515  * camel_folder_set_name:set the (short) name of the folder
516  * @folder: folder
517  * @name: new name of the folder
518  * @ex: exception object
519  **/
520 void
521 camel_folder_set_name (CamelFolder *folder, const gchar *name, CamelException *ex)
522 {
523         if (!folder) {
524                 camel_exception_set (ex, 
525                                      CAMEL_EXCEPTION_FOLDER_NULL,
526                                      "folder object is NULL");
527         }
528
529         CF_CLASS(folder)->set_name (folder, name, ex);
530 }
531
532
533
534
535
536 /* not used for the moment, I don't know if it it is
537    a good idea or not to use it */
538 #if 0
539 static void
540 _set_full_name (CamelFolder *folder, const gchar *name, CamelException *ex)
541 {
542         if (!folder) {
543                 camel_exception_set (ex, 
544                                      CAMEL_EXCEPTION_FOLDER_NULL,
545                                      "folder object is NULL");
546                 return;
547         }
548         g_free(folder->full_name);
549         folder->full_name = g_strdup (name);
550 }
551
552
553 /**
554  * camel_folder_set_full_name:set the (full) name of the folder
555  * @folder: folder
556  * @name: new name of the folder
557  * 
558  * set the name of the folder. 
559  * 
560  **/
561 void 
562 camel_folder_set_full_name (CamelFolder *folder, const gchar *name, CamelException *ex)
563 {
564         if (!folder) {
565                 camel_exception_set (ex, 
566                                      CAMEL_EXCEPTION_FOLDER_NULL,
567                                      "folder object is NULL");
568                 return;
569         }
570
571         CF_CLASS(folder)->set_full_name (folder, name, ex);
572 }
573 #endif
574
575
576
577
578 static const gchar *
579 _get_name (CamelFolder *folder, CamelException *ex)
580 {
581         if (!folder) {
582                 camel_exception_set (ex, 
583                                      CAMEL_EXCEPTION_FOLDER_NULL,
584                                      "folder object is NULL");
585                 return NULL;
586         }
587         return folder->name;
588 }
589
590
591 /**
592  * camel_folder_get_name: get the (short) name of the folder
593  * @folder: 
594  * 
595  * get the name of the folder. The fully qualified name
596  * can be obtained with the get_full_ame method (not implemented)
597  *
598  * Return value: name of the folder
599  **/
600 const gchar *
601 camel_folder_get_name (CamelFolder *folder, CamelException *ex)
602 {
603         if (!folder) {
604                 camel_exception_set (ex, 
605                                      CAMEL_EXCEPTION_FOLDER_NULL,
606                                      "folder object is NULL");
607                 return NULL;
608         }
609
610         return CF_CLASS(folder)->get_name (folder, ex);
611 }
612
613
614
615 static const gchar *
616 _get_full_name (CamelFolder *folder, CamelException *ex)
617 {
618         if (!folder) {
619                 camel_exception_set (ex, 
620                                      CAMEL_EXCEPTION_FOLDER_NULL,
621                                      "folder object is NULL");
622                 return NULL;
623         }
624
625         return folder->full_name;
626 }
627
628 /**
629  * camel_folder_get_full_name:get the (full) name of the folder
630  * @folder: folder to get the name 
631  * 
632  * get the name of the folder. 
633  * 
634  * Return value: full name of the folder
635  **/
636 const gchar *
637 camel_folder_get_full_name (CamelFolder *folder, CamelException *ex)
638 {
639         if (!folder) {
640                 camel_exception_set (ex, 
641                                      CAMEL_EXCEPTION_FOLDER_NULL,
642                                      "folder object is NULL");
643                 return NULL;
644         }
645
646         return CF_CLASS(folder)->get_full_name (folder, ex);
647 }
648
649
650 /**
651  * _can_hold_folders: tests if the folder can contain other folders
652  * @folder: The folder object 
653  * 
654  * Tests if a folder can contain other folder 
655  * (as for example MH folders)
656  * 
657  * Return value: 
658  **/
659 static gboolean
660 _can_hold_folders (CamelFolder *folder, CamelException *ex)
661 {
662         if (!folder) {
663                 camel_exception_set (ex, 
664                                      CAMEL_EXCEPTION_FOLDER_NULL,
665                                      "folder object is NULL");
666                 return FALSE;
667         }
668
669         return folder->can_hold_folders;
670 }
671
672
673
674
675 /**
676  * _can_hold_messages: tests if the folder can contain messages
677  * @folder: The folder object
678  * 
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).
682  * 
683  * Return value: true if it can contain messages false otherwise
684  **/
685 static gboolean
686 _can_hold_messages (CamelFolder *folder, CamelException *ex)
687 {
688         if (!folder) {
689                 camel_exception_set (ex, 
690                                      CAMEL_EXCEPTION_FOLDER_NULL,
691                                      "folder object is NULL");
692                 return FALSE;
693         }
694
695         return folder->can_hold_messages;
696 }
697
698
699
700 static gboolean
701 _exists (CamelFolder *folder, CamelException *ex)
702 {
703         if (!folder) {
704                 camel_exception_set (ex, 
705                                      CAMEL_EXCEPTION_FOLDER_NULL,
706                                      "folder object is NULL");
707                 return FALSE;
708         }
709
710         return FALSE;
711 }
712
713
714 /**
715  * _exists: tests if the folder object exists in its parent store.
716  * @folder: folder object
717  * 
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 
721  * 
722  * Return value: true if the folder exists on the store false otherwise 
723  **/
724 gboolean
725 camel_folder_exists (CamelFolder *folder, CamelException *ex)
726 {
727         if (!folder) {
728                 camel_exception_set (ex, 
729                                      CAMEL_EXCEPTION_FOLDER_NULL,
730                                      "folder object is NULL");
731                 return FALSE;
732         }
733
734         return (CF_CLASS(folder)->exists (folder, ex));
735 }
736
737
738
739 /**
740  * _is_open: test if the folder is open 
741  * @folder: The folder object
742  * 
743  * Tests if a folder is open. If not open it can be opened 
744  * CamelFolder::open
745  * 
746  * Return value: true if the folder exists, false otherwise
747  **/
748 static gboolean
749 _is_open (CamelFolder *folder, CamelException *ex)
750 {
751         if (!folder) {
752                 camel_exception_set (ex, 
753                                      CAMEL_EXCEPTION_FOLDER_NULL,
754                                      "folder object is NULL");
755                 return FALSE;
756         }
757
758         return (folder->open_state == FOLDER_OPEN);
759
760
761
762
763
764
765 static CamelFolder *
766 _get_subfolder (CamelFolder *folder, 
767                 const gchar *folder_name, 
768                 CamelException *ex)
769 {
770         CamelFolder *new_folder;
771         gchar *full_name;
772         const gchar *current_folder_full_name;
773         gchar separator;
774         
775         if (!folder) {
776                 camel_exception_set (ex, 
777                                      CAMEL_EXCEPTION_FOLDER_NULL,
778                                      "folder object is NULL");
779                 return NULL;
780         }
781
782         
783         if (!folder_name) {
784                 camel_exception_set (ex, 
785                                      CAMEL_EXCEPTION_INVALID_PARAM,
786                                      "folder_name parameter is NULL");
787                 return NULL;
788         }       
789         
790         if (!folder->parent_store) {
791                 camel_exception_set (ex, 
792                                      CAMEL_EXCEPTION_FOLDER_INVALID,
793                                      "folder has no parent store");
794                 return NULL;
795         }
796         
797         current_folder_full_name = camel_folder_get_full_name (folder, ex);
798         if (camel_exception_get_id (ex)) return NULL;
799
800
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);
803         
804         new_folder = camel_store_get_folder (folder->parent_store, full_name, ex);
805         return new_folder;
806 }
807
808
809
810 /**
811  * camel_folder_get_subfolder: return the (sub)folder object that is specified
812  * @folder: the folder
813  * @folder_name: subfolder path
814  * 
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.  
819  * 
820  * Return value: Required folder. NULL if the subfolder object  could not be obtained
821  **/
822 CamelFolder *
823 camel_folder_get_subfolder (CamelFolder *folder, gchar *folder_name, CamelException *ex)
824 {
825         if (!folder) {
826                 camel_exception_set (ex, 
827                                      CAMEL_EXCEPTION_FOLDER_NULL,
828                                      "folder object is NULL");
829                 return FALSE;
830         }
831
832         return (CF_CLASS(folder)->get_subfolder(folder,folder_name, ex));
833 }
834
835
836
837
838 /**
839  * _create: creates a folder on its store
840  * @folder: a CamelFolder object.
841  * 
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.
849  * 
850  * Return value: %TRUE if the folder exists, %FALSE otherwise 
851  **/
852 static gboolean
853 _create (CamelFolder *folder, CamelException *ex)
854 {
855         gchar *prefix;
856         gchar dich_result;
857         CamelFolder *parent;
858         gchar sep;
859         
860         g_assert (folder);
861         g_assert (folder->parent_store);
862         g_assert (folder->name);
863         
864         if (!folder) {
865                 camel_exception_set (ex, 
866                                      CAMEL_EXCEPTION_FOLDER_NULL,
867                                      "folder object is NULL");
868                 return FALSE;
869         }
870
871         
872         if (!folder->name) {
873                 camel_exception_set (ex, 
874                                      CAMEL_EXCEPTION_FOLDER_INVALID,
875                                      "folder has no name");
876                 return FALSE;
877         }       
878         
879         if (!folder->parent_store) {
880                 camel_exception_set (ex, 
881                                      CAMEL_EXCEPTION_FOLDER_INVALID,
882                                      "folder has no parent store");
883                 return FALSE;
884         }
885
886         /* if the folder already exists on the 
887            store, do nothing and return true */
888         if (CF_CLASS(folder)->exists (folder, ex))
889                 return TRUE;
890         
891         
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;
896         }
897         else {   
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"); 
904                                 return FALSE;
905                         } else {
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;
909                         }
910                 }
911         }       
912         return TRUE;
913 }
914
915
916 /**
917  * camel_folder_create: create the folder object on the physical store
918  * @folder: folder object to create
919  * 
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.
927  * 
928  * Return value: 
929  **/
930 gboolean
931 camel_folder_create (CamelFolder *folder, CamelException *ex)
932 {
933         if (!folder) {
934                 camel_exception_set (ex, 
935                                      CAMEL_EXCEPTION_FOLDER_NULL,
936                                      "folder object is NULL");
937                 return FALSE;
938         }
939
940         return (CF_CLASS(folder)->create(folder, ex));
941 }
942
943
944
945
946
947 /**
948  * _delete: delete folder 
949  * @folder: folder to delete
950  * @recurse: true is subfolders must also be deleted
951  * 
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
959  * 
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
967  * 
968  * Return value: true if the folder has been deleted
969  **/
970 static gboolean
971 _delete (CamelFolder *folder, gboolean recurse, CamelException *ex)
972 {
973         GList *subfolders=NULL;
974         GList *sf;
975         gboolean ok;
976         
977         g_assert(folder);
978         
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");
983                 return FALSE;
984         }
985         
986         /* delete all messages in the folder */
987         CF_CLASS(folder)->delete_messages(folder, ex);
988         if (camel_exception_get_id (ex)) return FALSE;
989
990         subfolders = CF_CLASS(folder)->list_subfolders(folder, ex); 
991         if (camel_exception_get_id (ex)) {
992                 if (subfolders) g_list_free (subfolders);
993                 return FALSE;
994         }
995         
996         ok = TRUE;
997         if (recurse) { /* delete subfolders */
998                 if (subfolders) {
999                         sf = subfolders;
1000                         do {
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));
1004                 }
1005         } else if (subfolders) {
1006                 camel_exception_set (ex, CAMEL_EXCEPTION_FOLDER_NON_EMPTY,
1007                                      "folder has subfolders");
1008                 ok = FALSE;
1009         }
1010         
1011         if (subfolders) g_list_free (subfolders);
1012
1013         return ok;
1014 }
1015
1016
1017
1018 /**
1019  * camel_folder_delete: delete a folder
1020  * @folder: folder to delete
1021  * @recurse: TRUE if subfolders must be deleted
1022  * 
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. 
1029  * 
1030  * Return value: TRUE if deletion was successful
1031  **/
1032 gboolean camel_folder_delete (CamelFolder *folder, gboolean recurse, CamelException *ex)
1033 {
1034         if (!folder) {
1035                 camel_exception_set (ex, 
1036                                      CAMEL_EXCEPTION_FOLDER_NULL,
1037                                      "folder object is NULL");
1038                 return FALSE;
1039         }
1040
1041         return CF_CLASS(folder)->delete(folder, recurse, ex);
1042 }
1043
1044
1045
1046
1047
1048 /**
1049  * _delete_messages: delete all messages in the folder
1050  * @folder: 
1051  * 
1052  * 
1053  * 
1054  * Return value: 
1055  **/
1056 static gboolean 
1057 _delete_messages (CamelFolder *folder, CamelException *ex)
1058 {
1059         if (!folder) {
1060                 camel_exception_set (ex, 
1061                                      CAMEL_EXCEPTION_FOLDER_NULL,
1062                                      "folder object is NULL");
1063                 return FALSE;
1064         }
1065
1066         CAMEL_LOG_WARNING ("Calling CamelFolder::delete_messages directly. "
1067                            "Should be overloaded\n");
1068         return FALSE;
1069 }
1070
1071
1072 /**
1073  * camel_folder_delete_messages: delete all messages in the folder
1074  * @folder: folder 
1075  * 
1076  * delete all messages stored in a folder
1077  * 
1078  * Return value: TRUE if the messages could be deleted
1079  **/
1080 gboolean
1081 camel_folder_delete_messages (CamelFolder *folder, CamelException *ex)
1082 {
1083         if (!folder) {
1084                 camel_exception_set (ex, 
1085                                      CAMEL_EXCEPTION_FOLDER_NULL,
1086                                      "folder object is NULL");
1087                 return FALSE;
1088         }
1089
1090         return CF_CLASS(folder)->delete_messages(folder, ex);
1091 }
1092
1093
1094
1095
1096
1097
1098 /**
1099  * _get_parent_folder: return parent folder
1100  * @folder: folder to get the parent
1101  * 
1102  * 
1103  * 
1104  * Return value: 
1105  **/
1106 static CamelFolder *
1107 _get_parent_folder (CamelFolder *folder, CamelException *ex)
1108 {
1109         if (!folder) {
1110                 camel_exception_set (ex, 
1111                                      CAMEL_EXCEPTION_FOLDER_NULL,
1112                                      "folder object is NULL");
1113                 return NULL;
1114         }
1115
1116         return folder->parent_folder;
1117 }
1118
1119
1120 /**
1121  * camel_folder_get_parent_folder:return parent folder
1122  * @folder: folder to get the parent
1123  * 
1124  * 
1125  * 
1126  * Return value: 
1127  **/
1128 CamelFolder *
1129 camel_folder_get_parent_folder (CamelFolder *folder, CamelException *ex)
1130 {
1131         if (!folder) {
1132                 camel_exception_set (ex, 
1133                                      CAMEL_EXCEPTION_FOLDER_NULL,
1134                                      "folder object is NULL");
1135                 return NULL;
1136         }
1137
1138         return CF_CLASS(folder)->get_parent_folder(folder, ex);
1139 }
1140
1141
1142 /**
1143  * _get_parent_store: return parent store
1144  * @folder: folder to get the parent
1145  * 
1146  * 
1147  * 
1148  * Return value: 
1149  **/
1150 static CamelStore *
1151 _get_parent_store (CamelFolder *folder, CamelException *ex)
1152 {
1153         if (!folder) {
1154                 camel_exception_set (ex, 
1155                                      CAMEL_EXCEPTION_FOLDER_NULL,
1156                                      "folder object is NULL");
1157                 return NULL;
1158         }
1159
1160         return folder->parent_store;
1161 }
1162
1163
1164 /**
1165  * camel_folder_get_parent_store: return parent store
1166  * @folder: folder to get the parent
1167  * 
1168  * Return the parent store of a folder
1169  * 
1170  * Return value: the parent store. 
1171  **/
1172 CamelStore *
1173 camel_folder_get_parent_store (CamelFolder *folder, CamelException *ex)
1174 {
1175         if (!folder) {
1176                 camel_exception_set (ex, 
1177                                      CAMEL_EXCEPTION_FOLDER_NULL,
1178                                      "folder object is NULL");
1179                 return NULL;
1180         }
1181
1182         return CF_CLASS(folder)->get_parent_store(folder, ex);
1183 }
1184
1185
1186
1187
1188 static CamelFolderOpenMode
1189 _get_mode (CamelFolder *folder, CamelException *ex)
1190 {
1191         if (!folder) {
1192                 camel_exception_set (ex, 
1193                                      CAMEL_EXCEPTION_FOLDER_NULL,
1194                                      "folder object is NULL");
1195                 return FOLDER_OPEN_UNKNOWN;
1196         }
1197
1198         return folder->open_mode;
1199 }
1200
1201
1202 /**
1203  * camel_folder_get_mode: return the open mode of a folder
1204  * @folder: 
1205  * 
1206  * 
1207  * 
1208  * Return value:  open mode of the folder
1209  **/
1210 CamelFolderOpenMode
1211 camel_folder_get_mode (CamelFolder *folder, CamelException *ex)
1212 {
1213         if (!folder) {
1214                 camel_exception_set (ex, 
1215                                      CAMEL_EXCEPTION_FOLDER_NULL,
1216                                      "folder object is NULL");
1217                 return FOLDER_OPEN_UNKNOWN;
1218         }
1219
1220         return CF_CLASS(folder)->get_mode(folder, ex);
1221 }
1222
1223
1224
1225
1226 static GList *
1227 _list_subfolders (CamelFolder *folder, CamelException *ex)
1228 {
1229         if (!folder) {
1230                 camel_exception_set (ex, 
1231                                      CAMEL_EXCEPTION_FOLDER_NULL,
1232                                      "folder object is NULL");
1233                 return NULL;
1234         }
1235
1236         CAMEL_LOG_WARNING ("Calling CamelFolder::list_subfolders directly. "
1237                            "Should be overloaded\n");
1238         return NULL;
1239 }
1240
1241
1242 /**
1243  * camel_folder_list_subfolders: list subfolders in a folder
1244  * @folder: the folder
1245  * 
1246  * List subfolders in a folder. 
1247  * 
1248  * Return value: list of subfolders
1249  **/
1250 GList *
1251 camel_folder_list_subfolders (CamelFolder *folder, CamelException *ex)
1252 {
1253         if (!folder) {
1254                 camel_exception_set (ex, 
1255                                      CAMEL_EXCEPTION_FOLDER_NULL,
1256                                      "folder object is NULL");
1257                 return NULL;
1258         }
1259
1260         return CF_CLASS(folder)->list_subfolders(folder, ex);
1261 }
1262
1263
1264
1265
1266 static GList *
1267 _expunge (CamelFolder *folder, CamelException *ex)
1268 {
1269         if (!folder) {
1270                 camel_exception_set (ex, 
1271                                      CAMEL_EXCEPTION_FOLDER_NULL,
1272                                      "folder object is NULL");
1273                 return NULL;
1274         }
1275
1276         CAMEL_LOG_WARNING ("Calling CamelFolder::expunge directly. "
1277                            "Should be overloaded\n");
1278         return NULL;
1279 }
1280
1281
1282 /**
1283  * camel_folder_expunge: physically delete messages marked as "DELETED"
1284  * @folder: the folder
1285  * 
1286  * Delete messages which have been marked as  "DELETED"
1287  * 
1288  * Return value: list of expunged messages 
1289  **/
1290 GList *
1291 camel_folder_expunge (CamelFolder *folder,  CamelException *ex)
1292 {
1293         if (!folder) {
1294                 camel_exception_set (ex, 
1295                                      CAMEL_EXCEPTION_FOLDER_NULL,
1296                                      "folder object is NULL");
1297                 return NULL;
1298         }
1299
1300         return CF_CLASS (folder)->expunge (folder, ex);
1301 }
1302
1303
1304 static gboolean 
1305 _has_message_number_capability (CamelFolder *folder, CamelException *ex)
1306 {
1307         if (!folder) {
1308                 camel_exception_set (ex, 
1309                                      CAMEL_EXCEPTION_FOLDER_NULL,
1310                                      "folder object is NULL");
1311                 return FALSE;
1312         }
1313
1314         CAMEL_LOG_WARNING ("Calling CamelFolder::has_message_number_capability directly. "
1315                            "Should be overloaded\n");
1316         return FALSE;
1317
1318 }
1319
1320
1321 /**
1322  * camel_folder_has_message_number_capability: tests if the message can be numbered within the folder
1323  * @folder: folder to test
1324  * 
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. 
1331  * 
1332  * Return value: TRUE if the folder supports message numbering, FALSE otherwise.
1333  **/
1334 gboolean 
1335 camel_folder_has_message_number_capability (CamelFolder *folder, CamelException *ex)
1336 {       
1337         if (!folder) {
1338                 camel_exception_set (ex, 
1339                                      CAMEL_EXCEPTION_FOLDER_NULL,
1340                                      "folder object is NULL");
1341                 return FALSE;
1342         }
1343
1344         return CF_CLASS(folder)->has_message_number_capability (folder, ex);
1345 }
1346
1347
1348
1349
1350 static CamelMimeMessage *
1351 _get_message_by_number (CamelFolder *folder, gint number, CamelException *ex)
1352 {
1353         if (!folder) {
1354                 camel_exception_set (ex, 
1355                                      CAMEL_EXCEPTION_FOLDER_NULL,
1356                                      "folder object is NULL");
1357                 return NULL;
1358         }
1359
1360         CAMEL_LOG_WARNING ("Calling CamelFolder::get_message_by_number directly. "
1361                            "Should be overloaded\n");
1362         return NULL;
1363 }
1364
1365
1366
1367
1368 /**
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.
1372  * 
1373  * Return the message corresponding to that number within the folder.
1374  * 
1375  * Return value: A pointer on the corresponding message or NULL if no corresponding message exists
1376  **/
1377 CamelMimeMessage *
1378 camel_folder_get_message_by_number (CamelFolder *folder, gint number, CamelException *ex)
1379 {
1380         if (!folder) {
1381                 camel_exception_set (ex, 
1382                                      CAMEL_EXCEPTION_FOLDER_NULL,
1383                                      "folder object is NULL");
1384                 return NULL;
1385         }
1386
1387         return CF_CLASS (folder)->get_message_by_number (folder, number, ex);
1388 }
1389
1390
1391 static gint
1392 _get_message_count (CamelFolder *folder, CamelException *ex)
1393 {
1394         CAMEL_LOG_WARNING ("Calling CamelFolder::get_message_count directly. "
1395                            "Should be overloaded\n");
1396         return -1;
1397 }
1398
1399
1400
1401 /**
1402  * camel_folder_get_message_count: get the number of messages in the folder
1403  * @folder: A CamelFolder object
1404  * 
1405  * Returns the number of messages in the folder.
1406  * 
1407  * Return value: the number of messages or -1 if unknown.
1408  **/
1409 gint
1410 camel_folder_get_message_count (CamelFolder *folder, CamelException *ex)
1411 {
1412         if (!folder) {
1413                 camel_exception_set (ex, 
1414                                      CAMEL_EXCEPTION_FOLDER_NULL,
1415                                      "folder object is NULL");
1416                 return -1;
1417         }
1418
1419         return CF_CLASS (folder)->get_message_count (folder, ex);
1420 }
1421
1422
1423 static void
1424 _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex)
1425 {
1426         if (!folder) {
1427                 camel_exception_set (ex, 
1428                                      CAMEL_EXCEPTION_FOLDER_NULL,
1429                                      "folder object is NULL");
1430                 return;
1431         }
1432
1433         CAMEL_LOG_WARNING ("Calling CamelFolder::append_message directly. "
1434                            "Should be overloaded\n");
1435         return;
1436
1437 }
1438
1439
1440 /**
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
1445  * 
1446  * Add a message to a folder.
1447  * 
1448  **/
1449 void 
1450 camel_folder_append_message (CamelFolder *folder, 
1451                              CamelMimeMessage *message, 
1452                              CamelException *ex)
1453 {       
1454         if (!folder) {
1455                 camel_exception_set (ex, 
1456                                      CAMEL_EXCEPTION_FOLDER_NULL,
1457                                      "folder object is NULL");
1458                 return;
1459         }
1460
1461         CF_CLASS (folder)->append_message (folder, message, ex);
1462 }
1463
1464
1465 static const GList *
1466 _list_permanent_flags (CamelFolder *folder, CamelException *ex)
1467 {
1468         if (!folder) {
1469                 camel_exception_set (ex, 
1470                                      CAMEL_EXCEPTION_FOLDER_NULL,
1471                                      "folder object is NULL");
1472                 return NULL;
1473         }
1474
1475         return folder->permanent_flags;
1476 }
1477
1478
1479 const GList *
1480 camel_folder_list_permanent_flags (CamelFolder *folder, CamelException *ex)
1481 {
1482         if (!folder) {
1483                 camel_exception_set (ex, 
1484                                      CAMEL_EXCEPTION_FOLDER_NULL,
1485                                      "folder object is NULL");
1486                 return NULL;
1487         }
1488
1489         return CF_CLASS (folder)->list_permanent_flags (folder, ex);
1490 }
1491
1492
1493
1494
1495 static void
1496 _copy_message_to (CamelFolder *folder, CamelMimeMessage *message, CamelFolder *dest_folder, CamelException *ex)
1497 {
1498         if (!folder) {
1499                 camel_exception_set (ex, 
1500                                      CAMEL_EXCEPTION_FOLDER_NULL,
1501                                      "folder object is NULL");
1502                 return;
1503         }
1504
1505         camel_folder_append_message (dest_folder, message, ex);
1506 }
1507
1508
1509 void
1510 camel_folder_copy_message_to (CamelFolder *folder, 
1511                               CamelMimeMessage *message, 
1512                               CamelFolder *dest_folder, 
1513                               CamelException *ex)
1514 {
1515         if (!folder) {
1516                 camel_exception_set (ex, 
1517                                      CAMEL_EXCEPTION_FOLDER_NULL,
1518                                      "folder object is NULL");
1519                 return;
1520         }
1521
1522         CF_CLASS (folder)->copy_message_to (folder, message, dest_folder, ex);;
1523 }
1524
1525
1526
1527
1528
1529 /* summary stuff */
1530
1531 gboolean
1532 camel_folder_has_summary_capability (CamelFolder *folder, 
1533                                      CamelException *ex)
1534 {
1535         if (!folder) {
1536                 camel_exception_set (ex, 
1537                                      CAMEL_EXCEPTION_FOLDER_NULL,
1538                                      "folder object is NULL");
1539                 return FALSE;
1540         }
1541
1542         return folder->has_summary_capability;
1543 }
1544
1545
1546 /**
1547  * camel_folder_get_summary: return the summary of a folder
1548  * @folder: folder object
1549  * @ex: exception object
1550  * 
1551  * Return a CamelFolderSummary object from 
1552  * which the main informations about a folder
1553  * can be retrieved.
1554  * 
1555  * Return value: the folder summary object.
1556  **/
1557 CamelFolderSummary *
1558 camel_folder_get_summary (CamelFolder *folder, 
1559                           CamelException *ex)
1560 {
1561         if (!folder) {
1562                 camel_exception_set (ex, 
1563                                      CAMEL_EXCEPTION_FOLDER_NULL,
1564                                      "folder object is NULL");
1565                 return NULL;
1566         }
1567
1568         return folder->summary;
1569 }
1570
1571
1572
1573
1574 /* UIDs stuff */
1575
1576 /**
1577  * camel_folder_has_uid_capability: detect if the folder support UIDs
1578  * @folder: Folder object
1579  * 
1580  * Detects if a folder supports UID operations, that is
1581  * reference messages by a Unique IDentifier instead
1582  * of by message number.  
1583  * 
1584  * Return value: TRUE if the folder supports UIDs 
1585  **/
1586 gboolean
1587 camel_folder_has_uid_capability (CamelFolder *folder, CamelException *ex)
1588 {
1589         if (!folder) {
1590                 camel_exception_set (ex, 
1591                                      CAMEL_EXCEPTION_FOLDER_NULL,
1592                                      "folder object is NULL");
1593                 return FALSE;
1594         }
1595
1596         return folder->has_uid_capability;
1597 }
1598
1599
1600
1601 static const gchar *
1602 _get_message_uid (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex)
1603 {
1604         CAMEL_LOG_WARNING ("Calling CamelFolder::get_message_uid directly. "
1605                            "Should be overloaded\n");
1606         return NULL;
1607 }
1608
1609 /**
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 
1613  * 
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
1617  * several folders. 
1618  * 
1619  * Return value: The UID of the message in the folder
1620  **/
1621 const gchar * 
1622 camel_folder_get_message_uid (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex)
1623 {
1624         if (!folder) {
1625                 camel_exception_set (ex, 
1626                                      CAMEL_EXCEPTION_FOLDER_NULL,
1627                                      "folder object is NULL");
1628                 return NULL;
1629         }
1630
1631         if (!folder->has_uid_capability) {
1632                 camel_exception_set (ex, 
1633                                      CAMEL_EXCEPTION_FOLDER_NON_UID,
1634                                      "folder is not UID capable");
1635                 return NULL;
1636         }
1637
1638         return CF_CLASS (folder)->get_message_uid (folder, message, ex);
1639 }
1640
1641
1642
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)
1646 {
1647         if (!folder) {
1648                 camel_exception_set (ex, 
1649                                      CAMEL_EXCEPTION_FOLDER_NULL,
1650                                      "folder object is NULL");
1651                 return NULL;
1652         }
1653
1654         CAMEL_LOG_WARNING ("Calling CamelFolder::get_message_uid_by_number directly. "
1655                            "Should be overloaded\n");
1656         return NULL;
1657 }
1658
1659 /**
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
1663  * 
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
1667  * not been used.
1668  * 
1669  * Return value: 
1670  **/
1671 const gchar * 
1672 camel_folder_get_message_uid_by_number (CamelFolder *folder, gint message_number, CamelException *ex)
1673 {
1674         if (!folder) {
1675                 camel_exception_set (ex, 
1676                                      CAMEL_EXCEPTION_FOLDER_NULL,
1677                                      "folder object is NULL");
1678                 return NULL;
1679         }
1680
1681         /*  if (!folder->has_uid_capability) return NULL; */
1682         /*  return CF_CLASS (folder)->get_message_uid_by_number (folder, message_number, ex); */
1683 }
1684
1685
1686 static CamelMimeMessage *
1687 _get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex)
1688 {
1689         CAMEL_LOG_WARNING ("Calling CamelFolder::get_message_by_uid directly. "
1690                            "Should be overloaded\n");
1691         return NULL;
1692 }
1693
1694
1695 /**
1696  * camel_folder_get_message_by_uid: Get a message by its UID in a folder
1697  * @folder: the folder object
1698  * @uid: the UID
1699  * 
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.
1703  * 
1704  * Return value: Message corresponding to the UID
1705  **/
1706 CamelMimeMessage *
1707 camel_folder_get_message_by_uid  (CamelFolder *folder, const gchar *uid, CamelException *ex)
1708 {
1709         if (!folder) {
1710                 camel_exception_set (ex, 
1711                                      CAMEL_EXCEPTION_FOLDER_NULL,
1712                                      "folder object is NULL");
1713                 return NULL;
1714         }
1715
1716         if (!folder->has_uid_capability) {
1717                 camel_exception_set (ex, 
1718                                      CAMEL_EXCEPTION_FOLDER_NON_UID,
1719                                      "folder is not UID capable");
1720                 return NULL;
1721         }
1722
1723         return CF_CLASS (folder)->get_message_by_uid (folder, uid, ex);
1724 }
1725
1726 static GList *
1727 _get_uid_list  (CamelFolder *folder, CamelException *ex)
1728 {
1729         if (!folder) {
1730                 camel_exception_set (ex, 
1731                                      CAMEL_EXCEPTION_FOLDER_NULL,
1732                                      "folder object is NULL");
1733                 return NULL;
1734         }
1735
1736         if (!folder->has_uid_capability) {
1737                 camel_exception_set (ex, 
1738                                      CAMEL_EXCEPTION_FOLDER_NON_UID,
1739                                      "folder is not UID capable");
1740                 return NULL;
1741         }
1742
1743         CAMEL_LOG_WARNING ("Calling CamelFolder::get_uid_list directly. "
1744                            "Should be overloaded\n");
1745         return NULL;
1746 }
1747
1748 /**
1749  * camel_folder_get_uid_list: get the list of UID in a folder
1750  * @folder: folder object
1751  * 
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.
1757  * 
1758  * Return value: Glist of UID correspondind to the messages available in the folder.
1759  **/
1760 GList *
1761 camel_folder_get_uid_list  (CamelFolder *folder, CamelException *ex)
1762 {
1763         if (!folder) {
1764                 camel_exception_set (ex, 
1765                                      CAMEL_EXCEPTION_FOLDER_NULL,
1766                                      "folder object is NULL");
1767                 return NULL;
1768         }
1769
1770         if (!folder->has_uid_capability) {
1771                 camel_exception_set (ex, 
1772                                      CAMEL_EXCEPTION_FOLDER_NON_UID,
1773                                      "folder is not UID capable");
1774                 return NULL;
1775         }
1776
1777         return CF_CLASS (folder)->get_uid_list (folder, ex);
1778 }
1779
1780
1781 /* **** */