summaryrefslogtreecommitdiffabout
path: root/kmicromail/libetpan/generic/mboxdriver_cached_message.c
Unidiff
Diffstat (limited to 'kmicromail/libetpan/generic/mboxdriver_cached_message.c') (more/less context) (ignore whitespace changes)
-rw-r--r--kmicromail/libetpan/generic/mboxdriver_cached_message.c360
1 files changed, 360 insertions, 0 deletions
diff --git a/kmicromail/libetpan/generic/mboxdriver_cached_message.c b/kmicromail/libetpan/generic/mboxdriver_cached_message.c
new file mode 100644
index 0000000..6d92b22
--- a/dev/null
+++ b/kmicromail/libetpan/generic/mboxdriver_cached_message.c
@@ -0,0 +1,360 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2002 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mboxdriver_cached_message.h"
37
38#include "mailmessage_tools.h"
39#include "mboxdriver_tools.h"
40#include "mboxdriver_cached.h"
41#include "mboxdriver.h"
42#include "mailmbox.h"
43#include "mail_cache_db.h"
44#include "generic_cache.h"
45
46#include <unistd.h>
47#include <sys/mman.h>
48#include <sys/types.h>
49#include <sys/stat.h>
50#include <fcntl.h>
51#include <string.h>
52#include <stdlib.h>
53
54static int mbox_prefetch(mailmessage * msg_info);
55
56static void mbox_prefetch_free(struct generic_message_t * msg);
57
58static int mbox_initialize(mailmessage * msg_info);
59
60static void mbox_uninitialize(mailmessage * msg_info);
61
62static void mbox_flush(mailmessage * msg_info);
63
64static void mbox_check(mailmessage * msg_info);
65
66static int mbox_fetch_size(mailmessage * msg_info,
67 size_t * result);
68
69static int mbox_get_flags(mailmessage * msg_info,
70 struct mail_flags ** result);
71
72static int mbox_fetch_header(mailmessage * msg_info,
73 char ** result,
74 size_t * result_len);
75
76static mailmessage_driver local_mbox_cached_message_driver = {
77 .msg_name = "mbox-cached",
78
79 .msg_initialize = mbox_initialize,
80 .msg_uninitialize = mbox_uninitialize,
81
82 .msg_flush = mbox_flush,
83 .msg_check = mbox_check,
84
85 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
86
87 .msg_fetch = mailmessage_generic_fetch,
88 .msg_fetch_header = mbox_fetch_header,
89 .msg_fetch_body = mailmessage_generic_fetch_body,
90 .msg_fetch_size = mbox_fetch_size,
91 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
92 .msg_fetch_section = mailmessage_generic_fetch_section,
93 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
94 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
95 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
96 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
97
98 .msg_get_flags = mbox_get_flags,
99};
100
101mailmessage_driver * mbox_cached_message_driver =
102&local_mbox_cached_message_driver;
103
104static inline struct mbox_cached_session_state_data *
105get_cached_session_data(mailmessage * msg)
106{
107 return msg->msg_session->sess_data;
108}
109
110static inline mailsession * get_ancestor_session(mailmessage * msg)
111{
112 return get_cached_session_data(msg)->mbox_ancestor;
113}
114
115static inline struct mbox_session_state_data *
116get_ancestor_session_data(mailmessage * msg)
117{
118 return get_ancestor_session(msg)->sess_data;
119}
120
121static inline struct mailmbox_folder *
122get_mbox_session(mailmessage * msg)
123{
124 return get_ancestor_session_data(msg)->mbox_folder;
125}
126
127static int mbox_prefetch(mailmessage * msg_info)
128{
129 struct generic_message_t * msg;
130 int r;
131 char * msg_content;
132 size_t msg_length;
133
134 r = mboxdriver_fetch_msg(get_ancestor_session(msg_info),
135 msg_info->msg_index,
136 &msg_content, &msg_length);
137 if (r != MAIL_NO_ERROR)
138 return r;
139
140 msg = msg_info->msg_data;
141
142 msg->msg_message = msg_content;
143 msg->msg_length = msg_length;
144
145 return MAIL_NO_ERROR;
146}
147
148static void mbox_prefetch_free(struct generic_message_t * msg)
149{
150 if (msg->msg_message != NULL) {
151 mmap_string_unref(msg->msg_message);
152 msg->msg_message = NULL;
153 }
154}
155
156static int mbox_initialize(mailmessage * msg_info)
157{
158 struct generic_message_t * msg;
159 int r;
160 char * uid;
161 char static_uid[PATH_MAX];
162 struct mailmbox_msg_info * info;
163 struct mailmbox_folder * folder;
164 int res;
165 chashdatum key;
166 chashdatum data;
167
168 folder = get_mbox_session(msg_info);
169 if (folder == NULL) {
170 res = MAIL_ERROR_BAD_STATE;
171 goto err;
172 }
173
174 key.data = (char *) &msg_info->msg_index;
175 key.len = sizeof(msg_info->msg_index);
176
177 r = chash_get(folder->mb_hash, &key, &data);
178 if (r < 0) {
179 res = MAIL_ERROR_MSG_NOT_FOUND;
180 goto err;
181 }
182
183 info = (struct mailmbox_msg_info *) data.data;
184
185 snprintf(static_uid, PATH_MAX, "%u-%u", msg_info->msg_index, info->msg_body_len);
186 uid = strdup(static_uid);
187 if (uid == NULL) {
188 res = MAIL_ERROR_MEMORY;
189 goto err;
190 }
191
192 r = mailmessage_generic_initialize(msg_info);
193 if (r != MAIL_NO_ERROR) {
194 free(uid);
195 res = r;
196 goto err;
197 }
198
199 msg = msg_info->msg_data;
200
201 msg->msg_prefetch = mbox_prefetch;
202 msg->msg_prefetch_free = mbox_prefetch_free;
203 msg_info->msg_uid = uid;
204
205 return MAIL_NO_ERROR;
206
207 err:
208 return res;
209}
210
211static void mbox_uninitialize(mailmessage * msg_info)
212{
213 mailmessage_generic_uninitialize(msg_info);
214}
215
216#define FLAGS_NAME "flags.db"
217
218static void mbox_flush(mailmessage * msg_info)
219{
220 mailmessage_generic_flush(msg_info);
221}
222
223static void mbox_check(mailmessage * msg_info)
224{
225 int r;
226
227 if (msg_info->msg_flags != NULL) {
228 r = mail_flags_store_set(get_cached_session_data(msg_info)->mbox_flags_store,
229 msg_info);
230 /* ignore errors */
231 }
232}
233
234
235static int mbox_fetch_size(mailmessage * msg_info,
236 size_t * result)
237{
238 int r;
239 size_t size;
240
241 r = mboxdriver_fetch_size(get_ancestor_session(msg_info),
242 msg_info->msg_index, &size);
243 if (r != MAIL_NO_ERROR)
244 return r;
245
246 * result = size;
247
248 return MAIL_NO_ERROR;
249}
250
251static int mbox_get_flags(mailmessage * msg_info,
252 struct mail_flags ** result)
253{
254 int r;
255 struct mail_flags * flags;
256 struct mail_cache_db * cache_db_flags;
257 char filename_flags[PATH_MAX];
258 int res;
259 struct mbox_cached_session_state_data * cached_data;
260 MMAPString * mmapstr;
261 struct mailmbox_folder * folder;
262
263 if (msg_info->msg_flags != NULL) {
264 * result = msg_info->msg_flags;
265
266 return MAIL_NO_ERROR;
267 }
268
269 flags = mail_flags_store_get(get_cached_session_data(msg_info)->mbox_flags_store,
270 msg_info->msg_index);
271
272 if (flags == NULL) {
273 folder = get_mbox_session(msg_info);
274 if (folder == NULL) {
275 res = MAIL_ERROR_BAD_STATE;
276 goto err;
277 }
278
279 cached_data = get_cached_session_data(msg_info);
280 if (cached_data->mbox_quoted_mb == NULL) {
281 res = MAIL_ERROR_BAD_STATE;
282 goto err;
283 }
284
285 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
286 cached_data->mbox_flags_directory,
287 cached_data->mbox_quoted_mb, FLAGS_NAME);
288
289 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
290 if (r < 0) {
291 res = MAIL_ERROR_MEMORY;
292 goto err;
293 }
294
295 mmapstr = mmap_string_new("");
296 if (mmapstr == NULL) {
297 res = MAIL_ERROR_MEMORY;
298 goto close_db_flags;
299 }
300
301 if (msg_info->msg_index > folder->mb_written_uid) {
302 flags = mail_flags_new_empty();
303 }
304 else {
305 r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr,
306 msg_info->msg_session,
307 msg_info->msg_index, &flags);
308 if (r != MAIL_NO_ERROR) {
309 flags = mail_flags_new_empty();
310 if (flags == NULL) {
311 res = MAIL_ERROR_MEMORY;
312 goto free_mmapstr;
313 }
314 }
315 }
316
317 mmap_string_free(mmapstr);
318 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
319 }
320
321 msg_info->msg_flags = flags;
322
323 * result = flags;
324
325 return MAIL_NO_ERROR;
326
327 free_mmapstr:
328 mmap_string_free(mmapstr);
329 close_db_flags:
330 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
331 err:
332 return res;
333}
334
335static int mbox_fetch_header(mailmessage * msg_info,
336 char ** result,
337 size_t * result_len)
338{
339 struct generic_message_t * msg;
340 int r;
341 char * msg_content;
342 size_t msg_length;
343
344 msg = msg_info->msg_data;
345 if (msg->msg_message != NULL) {
346 return mailmessage_generic_fetch_header(msg_info, result, result_len);
347 }
348 else {
349 r = mboxdriver_fetch_header(get_ancestor_session(msg_info),
350 msg_info->msg_index,
351 &msg_content, &msg_length);
352 if (r != MAIL_NO_ERROR)
353 return r;
354
355 * result = msg_content;
356 * result_len = msg_length;
357
358 return MAIL_NO_ERROR;
359 }
360}