summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c
Unidiff
Diffstat (limited to 'libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c355
1 files changed, 355 insertions, 0 deletions
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c b/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c
new file mode 100644
index 0000000..4eed0db
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c
@@ -0,0 +1,355 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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 "pop3driver_cached_message.h"
37
38#include <string.h>
39#include <stdlib.h>
40
41#include "mail_cache_db.h"
42
43#include "mailmessage.h"
44#include "mailmessage_tools.h"
45#include "pop3driver.h"
46#include "pop3driver_tools.h"
47#include "pop3driver_cached.h"
48#include "pop3driver_message.h"
49#include "generic_cache.h"
50
51static int pop3_prefetch(mailmessage * msg_info);
52
53static void pop3_prefetch_free(struct generic_message_t * msg);
54
55static int pop3_initialize(mailmessage * msg_info);
56
57static void pop3_flush(mailmessage * msg_info);
58
59static void pop3_check(mailmessage * msg_info);
60
61static int pop3_fetch_header(mailmessage * msg_info,
62 char ** result,
63 size_t * result_len);
64
65static int pop3_fetch_size(mailmessage * msg_info,
66 size_t * result);
67
68static int pop3_get_flags(mailmessage * msg_info,
69 struct mail_flags ** result);
70
71static void pop3_uninitialize(mailmessage * msg_info);
72
73static mailmessage_driver local_pop3_cached_message_driver = {
74 .msg_name = "pop3-cached",
75
76 .msg_initialize = pop3_initialize,
77 .msg_uninitialize = pop3_uninitialize,
78
79 .msg_flush = pop3_flush,
80 .msg_check = pop3_check,
81
82 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
83
84 .msg_fetch = mailmessage_generic_fetch,
85 .msg_fetch_header = pop3_fetch_header,
86 .msg_fetch_body = mailmessage_generic_fetch_body,
87 .msg_fetch_size = pop3_fetch_size,
88 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
89 .msg_fetch_section = mailmessage_generic_fetch_section,
90 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
91 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
92 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
93 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
94
95 .msg_get_flags = pop3_get_flags,
96};
97
98mailmessage_driver * pop3_cached_message_driver =
99&local_pop3_cached_message_driver;
100
101
102static inline struct pop3_cached_session_state_data *
103get_cached_session_data(mailmessage * msg)
104{
105 return msg->msg_session->sess_data;
106}
107
108static inline mailsession * get_ancestor_session(mailmessage * msg)
109{
110 return get_cached_session_data(msg)->pop3_ancestor;
111}
112
113static inline struct pop3_session_state_data *
114get_ancestor_session_data(mailmessage * msg)
115{
116 return get_ancestor_session(msg)->sess_data;
117}
118
119static inline mailpop3 * get_pop3_session(mailmessage * msg)
120{
121 return get_ancestor_session_data(msg)->pop3_session;
122}
123
124
125static int pop3_prefetch(mailmessage * msg_info)
126{
127 char * msg_content;
128 size_t msg_length;
129 struct generic_message_t * msg;
130 int r;
131 struct pop3_cached_session_state_data * cached_data;
132 char filename[PATH_MAX];
133
134 /* we try the cached message */
135
136 cached_data = get_cached_session_data(msg_info);
137
138 snprintf(filename, PATH_MAX, "%s/%s",
139 cached_data->pop3_cache_directory, msg_info->msg_uid);
140
141 r = generic_cache_read(filename, &msg_content, &msg_length);
142 if (r == MAIL_NO_ERROR) {
143 msg = msg_info->msg_data;
144
145 msg->msg_message = msg_content;
146 msg->msg_length = msg_length;
147
148 return MAIL_NO_ERROR;
149 }
150
151 /* we get the message through the network */
152
153 r = pop3driver_retr(get_ancestor_session(msg_info), msg_info->msg_index,
154 &msg_content, &msg_length);
155 if (r != MAIL_NO_ERROR)
156 return r;
157
158 /* we write the message cache */
159
160 generic_cache_store(filename, msg_content, msg_length);
161
162 msg = msg_info->msg_data;
163
164 msg->msg_message = msg_content;
165 msg->msg_length = msg_length;
166
167 return MAIL_NO_ERROR;
168}
169
170static void pop3_prefetch_free(struct generic_message_t * msg)
171{
172 if (msg->msg_message != NULL) {
173 mmap_string_unref(msg->msg_message);
174 msg->msg_message = NULL;
175 }
176}
177
178static int pop3_initialize(mailmessage * msg_info)
179{
180 struct generic_message_t * msg;
181 int r;
182 char * uid;
183 struct mailpop3_msg_info * info;
184 mailpop3 * pop3;
185
186 pop3 = get_pop3_session(msg_info);
187
188 r = mailpop3_get_msg_info(pop3, msg_info->msg_index, &info);
189 switch (r) {
190 case MAILPOP3_NO_ERROR:
191 break;
192 default:
193 return pop3driver_pop3_error_to_mail_error(r);
194 }
195
196 uid = strdup(info->msg_uidl);
197 if (uid == NULL)
198 return MAIL_ERROR_MEMORY;
199
200 r = mailmessage_generic_initialize(msg_info);
201 if (r != MAIL_NO_ERROR) {
202 free(uid);
203 return r;
204 }
205
206 msg = msg_info->msg_data;
207 msg->msg_prefetch = pop3_prefetch;
208 msg->msg_prefetch_free = pop3_prefetch_free;
209 msg_info->msg_uid = uid;
210
211 return MAIL_NO_ERROR;
212}
213
214static void pop3_uninitialize(mailmessage * msg_info)
215{
216 mailmessage_generic_uninitialize(msg_info);
217}
218
219#define FLAGS_NAME "flags.db"
220
221static void pop3_flush(mailmessage * msg_info)
222{
223 mailmessage_generic_flush(msg_info);
224}
225
226static void pop3_check(mailmessage * msg_info)
227{
228 int r;
229
230 if (msg_info->msg_flags != NULL) {
231 r = mail_flags_store_set(get_cached_session_data(msg_info)->pop3_flags_store,
232 msg_info);
233 }
234}
235
236
237static int pop3_fetch_header(mailmessage * msg_info,
238 char ** result,
239 size_t * result_len)
240{
241 struct generic_message_t * msg;
242 char * headers;
243 size_t headers_length;
244 int r;
245 struct pop3_cached_session_state_data * cached_data;
246 char filename[PATH_MAX];
247
248 msg = msg_info->msg_data;
249
250 if (msg->msg_message != NULL)
251 return mailmessage_generic_fetch_header(msg_info,
252 result, result_len);
253
254 /* we try the cached message */
255
256 cached_data = get_cached_session_data(msg_info);
257
258 snprintf(filename, PATH_MAX, "%s/%s-header",
259 cached_data->pop3_cache_directory, msg_info->msg_uid);
260
261 r = generic_cache_read(filename, &headers, &headers_length);
262 if (r == MAIL_NO_ERROR) {
263 * result = headers;
264 * result_len = headers_length;
265
266 return MAIL_NO_ERROR;
267 }
268
269 /* we get the message trough the network */
270
271 r = pop3driver_header(get_ancestor_session(msg_info), msg_info->msg_index,
272 &headers, &headers_length);
273 if (r != MAIL_NO_ERROR)
274 return r;
275
276 generic_cache_store(filename, headers, headers_length);
277
278 * result = headers;
279 * result_len = headers_length;
280
281 return MAIL_NO_ERROR;
282}
283
284static int pop3_fetch_size(mailmessage * msg_info,
285 size_t * result)
286{
287 return pop3driver_size(get_ancestor_session(msg_info),
288 msg_info->msg_index, result);
289}
290
291static int pop3_get_flags(mailmessage * msg_info,
292 struct mail_flags ** result)
293{
294 int r;
295 struct mail_flags * flags;
296 struct mail_cache_db * cache_db_flags;
297 char filename_flags[PATH_MAX];
298 int res;
299 struct pop3_cached_session_state_data * cached_data;
300 MMAPString * mmapstr;
301
302 if (msg_info->msg_flags != NULL) {
303 * result = msg_info->msg_flags;
304
305 return MAIL_NO_ERROR;
306 }
307
308 cached_data = get_cached_session_data(msg_info);
309
310 flags = mail_flags_store_get(cached_data->pop3_flags_store,
311 msg_info->msg_index);
312
313 if (flags == NULL) {
314 snprintf(filename_flags, PATH_MAX, "%s/%s",
315 cached_data->pop3_flags_directory, FLAGS_NAME);
316
317 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
318 if (r < 0) {
319 res = MAIL_ERROR_MEMORY;
320 goto err;
321 }
322
323 mmapstr = mmap_string_new("");
324 if (mmapstr == NULL) {
325 res = MAIL_ERROR_MEMORY;
326 goto close_db_flags;
327 }
328
329 r = pop3driver_get_cached_flags(cache_db_flags, mmapstr,
330 msg_info->msg_session, msg_info->msg_index, &flags);
331 if (r != MAIL_NO_ERROR) {
332 flags = mail_flags_new_empty();
333 if (flags == NULL) {
334 res = MAIL_ERROR_MEMORY;
335 goto free_mmapstr;
336 }
337 }
338
339 mmap_string_free(mmapstr);
340 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
341 }
342
343 msg_info->msg_flags = flags;
344
345 * result = flags;
346
347 return MAIL_NO_ERROR;
348
349 free_mmapstr:
350 mmap_string_free(mmapstr);
351 close_db_flags:
352 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
353 err:
354 return res;
355}