1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* camel-imap-folder.c : class for a imap folder */
5 * Authors: Michael Zucchi <notzed@ximian.com>
7 * Copyright (C) 2002 Ximian, Inc. (www.ximian.com)
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of version 2 of the GNU Lesser General Public
11 * License as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
32 #include <libedataserver/md5-utils.h>
33 #include <libedataserver/e-data-server-util.h>
35 #include "camel-data-cache.h"
36 #include "camel-exception.h"
37 #include "camel-file-utils.h"
38 #include "camel-mime-message.h"
39 #include "camel-operation.h"
40 #include "camel-session.h"
41 #include "camel-stream-filter.h"
42 #include "camel-stream-mem.h"
44 #include "camel-imapp-exception.h"
45 #include "camel-imapp-folder.h"
46 #include "camel-imapp-store.h"
47 #include "camel-imapp-summary.h"
51 #define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(o)))
52 static CamelFolderClass *parent_class;
54 static void imap_finalize (CamelObject *object);
55 static void imap_refresh_info (CamelFolder *folder, CamelException *ex);
56 static void imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex);
57 static CamelMimeMessage *imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex);
60 imap_folder_class_init (CamelIMAPPFolderClass *camel_imapp_folder_class)
62 CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_imapp_folder_class);
64 parent_class = CAMEL_FOLDER_CLASS(camel_folder_get_type());
66 /* virtual method overload */
67 camel_folder_class->refresh_info = imap_refresh_info;
68 camel_folder_class->sync = imap_sync;
70 camel_folder_class->get_message = imap_get_message;
74 imap_folder_init(CamelObject *o, CamelObjectClass *klass)
76 CamelFolder *folder = (CamelFolder *)o;
77 CamelIMAPPFolder *ifolder = (CamelIMAPPFolder *)o;
79 folder->folder_flags |= (CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY |
80 CAMEL_FOLDER_HAS_SEARCH_CAPABILITY);
82 folder->permanent_flags = CAMEL_MESSAGE_ANSWERED |
83 CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_DRAFT |
84 CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_USER;
86 /* FIXME: this is just a skeleton */
88 ifolder->changes = camel_folder_change_info_new();
92 camel_imapp_folder_get_type (void)
94 static CamelType camel_imapp_folder_type = CAMEL_INVALID_TYPE;
96 if (!camel_imapp_folder_type) {
97 camel_imapp_folder_type = camel_type_register (CAMEL_FOLDER_TYPE, "CamelIMAPPFolder",
98 sizeof (CamelIMAPPFolder),
99 sizeof (CamelIMAPPFolderClass),
100 (CamelObjectClassInitFunc) imap_folder_class_init,
103 (CamelObjectFinalizeFunc) imap_finalize);
106 return camel_imapp_folder_type;
110 imap_finalize (CamelObject *object)
112 CamelIMAPPFolder *folder = (CamelIMAPPFolder *)object;
114 camel_folder_change_info_free(folder->changes);
118 camel_imapp_folder_new(CamelStore *store, const char *path)
123 d(printf("opening imap folder '%s'\n", path));
125 folder = CAMEL_FOLDER (camel_object_new (CAMEL_IMAPP_FOLDER_TYPE));
126 camel_folder_construct(folder, store, path, path);
128 ((CamelIMAPPFolder *)folder)->raw_name = g_strdup(path);
130 folder->summary = camel_imapp_summary_new();
132 root = camel_session_get_storage_path(((CamelService *)store)->session, (CamelService *)store, NULL);
134 char *base = g_build_filename(root, path, NULL);
135 char *file = g_build_filename(base, ".ev-summary", NULL);
137 g_mkdir_with_parents (base, 0777);
140 camel_folder_summary_set_filename(folder->summary, file);
141 printf("loading summary from '%s' (root=%s)\n", file, root);
143 camel_folder_summary_load(folder->summary);
151 /* experimental interfaces */
153 camel_imapp_folder_open(CamelIMAPPFolder *folder, CamelException *ex)
159 camel_imapp_folder_delete(CamelIMAPPFolder *folder, CamelException *ex)
164 camel_imapp_folder_rename(CamelIMAPPFolder *folder, const char *new, CamelException *ex)
169 camel_imapp_folder_close(CamelIMAPPFolder *folder, CamelException *ex)
175 imap_refresh_info (CamelFolder *folder, CamelException *ex)
177 printf("imapp refresh info?\n");
181 imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
183 camel_imapp_driver_sync(((CamelIMAPPStore *)(folder->parent_store))->driver, expunge, (CamelIMAPPFolder *) folder);
186 static CamelMimeMessage *
187 imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex)
189 CamelMimeMessage * volatile msg = NULL;
190 CamelStream * volatile stream = NULL;
192 printf("get message '%s'\n", uid);
195 /* simple implementation, just get whole message in 1 go */
196 stream = camel_imapp_driver_fetch(((CamelIMAPPStore *)(folder->parent_store))->driver, (CamelIMAPPFolder *)folder, uid, "");
197 camel_stream_reset(stream);
198 msg = camel_mime_message_new();
199 if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)msg, stream) != -1) {
204 camel_object_unref(msg);
206 camel_exception_xfer(ex, e);
210 camel_object_unref(stream);
216 /* Algorithm for selecting a folder:
218 - If uidvalidity == old uidvalidity
219 and exsists == old exists
220 and recent == old recent
221 and unseen == old unseen
222 Assume our summary is correct
223 for each summary item
224 mark the summary item as 'old/not updated'
227 for each fetch response
228 info = summary[index]
230 info = summary_by_uid[uid]
233 create new info @ index
239 update based on header
242 update based on imap body
246 Async fetch response:
247 info = summary[index]
252 else if uid && info.uid != uid
265 info.state - 2 bit field in flags
266 0 = empty, nothing set