author | zautrix <zautrix> | 2005-03-18 20:17:03 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2005-03-18 20:17:03 (UTC) |
commit | 9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf (patch) (unidiff) | |
tree | 2528e6cc740225ca0f47d5ac8ff70f7d3bb10621 /libetpan/src/driver/implementation/imap/imapdriver_cached.c | |
parent | 9319998f20f03dcc217fbb39656755dc65226276 (diff) | |
download | kdepimpi-9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf.zip kdepimpi-9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf.tar.gz kdepimpi-9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf.tar.bz2 |
Initial revision
Diffstat (limited to 'libetpan/src/driver/implementation/imap/imapdriver_cached.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libetpan/src/driver/implementation/imap/imapdriver_cached.c | 1370 |
1 files changed, 1370 insertions, 0 deletions
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_cached.c b/libetpan/src/driver/implementation/imap/imapdriver_cached.c new file mode 100644 index 0000000..806b282 --- a/dev/null +++ b/libetpan/src/driver/implementation/imap/imapdriver_cached.c | |||
@@ -0,0 +1,1370 @@ | |||
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 "imapdriver_cached.h" | ||
37 | |||
38 | #include "libetpan-config.h" | ||
39 | |||
40 | #include <stdio.h> | ||
41 | #include <sys/types.h> | ||
42 | #include <sys/stat.h> | ||
43 | #include <fcntl.h> | ||
44 | #include <string.h> | ||
45 | #include <unistd.h> | ||
46 | #include <stdlib.h> | ||
47 | |||
48 | #include "mail.h" | ||
49 | #include "imapdriver_tools.h" | ||
50 | #include "mail_cache_db.h" | ||
51 | #include "mailmessage.h" | ||
52 | #include "imapdriver_cached_message.h" | ||
53 | #include "maildriver.h" | ||
54 | #include "imapdriver_types.h" | ||
55 | #include "generic_cache.h" | ||
56 | #include "imfcache.h" | ||
57 | #include "maildriver_tools.h" | ||
58 | #include "imapdriver.h" | ||
59 | |||
60 | static int imapdriver_cached_initialize(mailsession * session); | ||
61 | static void imapdriver_cached_uninitialize(mailsession * session); | ||
62 | |||
63 | static int imapdriver_cached_parameters(mailsession * session, | ||
64 | int id, void * value); | ||
65 | |||
66 | static int imapdriver_cached_connect_stream(mailsession * session, | ||
67 | mailstream * s); | ||
68 | |||
69 | static int imapdriver_cached_starttls(mailsession * session); | ||
70 | |||
71 | static int imapdriver_cached_login(mailsession * session, | ||
72 | char * userid, char * password); | ||
73 | static int imapdriver_cached_logout(mailsession * session); | ||
74 | static int imapdriver_cached_noop(mailsession * session); | ||
75 | static int imapdriver_cached_build_folder_name(mailsession * session, | ||
76 | char * mb, | ||
77 | char * name, char ** result); | ||
78 | static int imapdriver_cached_create_folder(mailsession * session, char * mb); | ||
79 | static int imapdriver_cached_delete_folder(mailsession * session, char * mb); | ||
80 | static int imapdriver_cached_rename_folder(mailsession * session, char * mb, | ||
81 | char * new_name); | ||
82 | static int imapdriver_cached_check_folder(mailsession * session); | ||
83 | static int imapdriver_cached_examine_folder(mailsession * session, | ||
84 | char * mb); | ||
85 | static int imapdriver_cached_select_folder(mailsession * session, char * mb); | ||
86 | static int imapdriver_cached_expunge_folder(mailsession * session); | ||
87 | static int imapdriver_cached_status_folder(mailsession * session, char * mb, | ||
88 | uint32_t * result_messages, | ||
89 | uint32_t * result_recent, | ||
90 | uint32_t * result_unseen); | ||
91 | static int imapdriver_cached_messages_number(mailsession * session, | ||
92 | char * mb, | ||
93 | uint32_t * result); | ||
94 | static int imapdriver_cached_recent_number(mailsession * session, char * mb, | ||
95 | uint32_t * result); | ||
96 | static int imapdriver_cached_unseen_number(mailsession * session, char * mb, | ||
97 | uint32_t * result); | ||
98 | static int imapdriver_cached_list_folders(mailsession * session, char * mb, | ||
99 | struct mail_list ** result); | ||
100 | static int imapdriver_cached_lsub_folders(mailsession * session, char * mb, | ||
101 | struct mail_list ** result); | ||
102 | static int imapdriver_cached_subscribe_folder(mailsession * session, | ||
103 | char * mb); | ||
104 | static int imapdriver_cached_unsubscribe_folder(mailsession * session, | ||
105 | char * mb); | ||
106 | static int imapdriver_cached_append_message(mailsession * session, | ||
107 | char * message, size_t size); | ||
108 | static int imapdriver_cached_append_message_flags(mailsession * session, | ||
109 | char * message, size_t size, struct mail_flags * flags); | ||
110 | static int imapdriver_cached_copy_message(mailsession * session, | ||
111 | uint32_t num, char * mb); | ||
112 | |||
113 | static int imapdriver_cached_get_messages_list(mailsession * session, | ||
114 | struct mailmessage_list ** | ||
115 | result); | ||
116 | static int | ||
117 | imapdriver_cached_get_envelopes_list(mailsession * session, | ||
118 | struct mailmessage_list * env_list); | ||
119 | static int imapdriver_cached_remove_message(mailsession * session, | ||
120 | uint32_t num); | ||
121 | |||
122 | #if 0 | ||
123 | static int imapdriver_cached_search_messages(mailsession * session, | ||
124 | char * charset, | ||
125 | struct mail_search_key * key, | ||
126 | struct mail_search_result ** | ||
127 | result); | ||
128 | #endif | ||
129 | |||
130 | static int imapdriver_cached_get_message(mailsession * session, | ||
131 | uint32_t num, mailmessage ** result); | ||
132 | |||
133 | static int imapdriver_cached_get_message_by_uid(mailsession * session, | ||
134 | const char * uid, | ||
135 | mailmessage ** result); | ||
136 | |||
137 | static mailsession_driver local_imap_cached_session_driver = { | ||
138 | .sess_name = "imap-cached", | ||
139 | |||
140 | .sess_initialize = imapdriver_cached_initialize, | ||
141 | .sess_uninitialize = imapdriver_cached_uninitialize, | ||
142 | |||
143 | .sess_parameters = imapdriver_cached_parameters, | ||
144 | |||
145 | .sess_connect_stream = imapdriver_cached_connect_stream, | ||
146 | .sess_connect_path = NULL, | ||
147 | .sess_starttls = imapdriver_cached_starttls, | ||
148 | .sess_login = imapdriver_cached_login, | ||
149 | .sess_logout = imapdriver_cached_logout, | ||
150 | .sess_noop = imapdriver_cached_noop, | ||
151 | |||
152 | .sess_build_folder_name = imapdriver_cached_build_folder_name, | ||
153 | .sess_create_folder = imapdriver_cached_create_folder, | ||
154 | .sess_delete_folder = imapdriver_cached_delete_folder, | ||
155 | .sess_rename_folder = imapdriver_cached_rename_folder, | ||
156 | .sess_check_folder = imapdriver_cached_check_folder, | ||
157 | .sess_examine_folder = imapdriver_cached_examine_folder, | ||
158 | .sess_select_folder = imapdriver_cached_select_folder, | ||
159 | .sess_expunge_folder = imapdriver_cached_expunge_folder, | ||
160 | .sess_status_folder = imapdriver_cached_status_folder, | ||
161 | .sess_messages_number = imapdriver_cached_messages_number, | ||
162 | .sess_recent_number = imapdriver_cached_recent_number, | ||
163 | .sess_unseen_number = imapdriver_cached_unseen_number, | ||
164 | .sess_list_folders = imapdriver_cached_list_folders, | ||
165 | .sess_lsub_folders = imapdriver_cached_lsub_folders, | ||
166 | .sess_subscribe_folder = imapdriver_cached_subscribe_folder, | ||
167 | .sess_unsubscribe_folder = imapdriver_cached_unsubscribe_folder, | ||
168 | |||
169 | .sess_append_message = imapdriver_cached_append_message, | ||
170 | .sess_append_message_flags = imapdriver_cached_append_message_flags, | ||
171 | .sess_copy_message = imapdriver_cached_copy_message, | ||
172 | .sess_move_message = NULL, | ||
173 | |||
174 | .sess_get_messages_list = imapdriver_cached_get_messages_list, | ||
175 | .sess_get_envelopes_list = imapdriver_cached_get_envelopes_list, | ||
176 | .sess_remove_message = imapdriver_cached_remove_message, | ||
177 | #if 0 | ||
178 | .sess_search_messages = imapdriver_cached_search_messages, | ||
179 | #endif | ||
180 | |||
181 | .sess_get_message = imapdriver_cached_get_message, | ||
182 | .sess_get_message_by_uid = imapdriver_cached_get_message_by_uid, | ||
183 | }; | ||
184 | |||
185 | mailsession_driver * imap_cached_session_driver = | ||
186 | &local_imap_cached_session_driver; | ||
187 | |||
188 | #define CACHE_MESSAGE_LIST | ||
189 | |||
190 | static inline struct imap_cached_session_state_data * | ||
191 | get_cached_data(mailsession * session) | ||
192 | { | ||
193 | return session->sess_data; | ||
194 | } | ||
195 | |||
196 | static inline mailsession * get_ancestor(mailsession * s) | ||
197 | { | ||
198 | return get_cached_data(s)->imap_ancestor; | ||
199 | } | ||
200 | |||
201 | static inline | ||
202 | struct imap_session_state_data * get_ancestor_data(mailsession * s) | ||
203 | { | ||
204 | return get_ancestor(s)->sess_data; | ||
205 | } | ||
206 | |||
207 | static inline mailimap * get_imap_session(mailsession * session) | ||
208 | { | ||
209 | return get_ancestor_data(session)->imap_session; | ||
210 | } | ||
211 | |||
212 | static int imapdriver_cached_initialize(mailsession * session) | ||
213 | { | ||
214 | struct imap_cached_session_state_data * data; | ||
215 | |||
216 | data = malloc(sizeof(* data)); | ||
217 | if (data == NULL) | ||
218 | goto err; | ||
219 | |||
220 | data->imap_ancestor = mailsession_new(imap_session_driver); | ||
221 | if (data->imap_ancestor == NULL) | ||
222 | goto free_data; | ||
223 | data->imap_quoted_mb = NULL; | ||
224 | data->imap_cache_directory[0] = '\0'; | ||
225 | data->imap_uid_list = carray_new(128); | ||
226 | if (data->imap_uid_list == NULL) | ||
227 | goto free_session; | ||
228 | |||
229 | session->sess_data = data; | ||
230 | |||
231 | return MAIL_NO_ERROR; | ||
232 | |||
233 | free_session: | ||
234 | mailsession_free(data->imap_ancestor); | ||
235 | free_data: | ||
236 | free(data); | ||
237 | err: | ||
238 | return MAIL_ERROR_MEMORY; | ||
239 | } | ||
240 | |||
241 | static void | ||
242 | free_quoted_mb(struct imap_cached_session_state_data * imap_cached_data) | ||
243 | { | ||
244 | if (imap_cached_data->imap_quoted_mb != NULL) { | ||
245 | free(imap_cached_data->imap_quoted_mb); | ||
246 | imap_cached_data->imap_quoted_mb = NULL; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | struct uid_cache_item { | ||
251 | uint32_t uid; | ||
252 | uint32_t size; | ||
253 | }; | ||
254 | |||
255 | static int update_uid_cache(mailsession * session, | ||
256 | struct mailmessage_list * env_list) | ||
257 | { | ||
258 | unsigned int i; | ||
259 | int r; | ||
260 | struct imap_cached_session_state_data * data; | ||
261 | int res; | ||
262 | |||
263 | data = get_cached_data(session); | ||
264 | |||
265 | /* free all UID cache */ | ||
266 | for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { | ||
267 | struct uid_cache_item * cache_item; | ||
268 | |||
269 | cache_item = carray_get(data->imap_uid_list, i); | ||
270 | free(cache_item); | ||
271 | } | ||
272 | |||
273 | /* build UID cache */ | ||
274 | r = carray_set_size(data->imap_uid_list, | ||
275 | carray_count(env_list->msg_tab)); | ||
276 | if (r < 0) { | ||
277 | res = MAIL_ERROR_MEMORY; | ||
278 | goto err; | ||
279 | } | ||
280 | |||
281 | for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { | ||
282 | struct uid_cache_item * cache_item; | ||
283 | mailmessage * msg; | ||
284 | |||
285 | cache_item = malloc(sizeof(* cache_item)); | ||
286 | if (cache_item == NULL) { | ||
287 | res = MAIL_ERROR_MEMORY; | ||
288 | goto err; | ||
289 | } | ||
290 | msg = carray_get(env_list->msg_tab, i); | ||
291 | cache_item->uid = msg->msg_index; | ||
292 | cache_item->size = msg->msg_size; | ||
293 | |||
294 | carray_set(data->imap_uid_list, i, cache_item); | ||
295 | } | ||
296 | |||
297 | return MAIL_NO_ERROR; | ||
298 | |||
299 | err: | ||
300 | return res; | ||
301 | } | ||
302 | |||
303 | static void check_for_uid_cache(mailsession * session) | ||
304 | { | ||
305 | #if 0 | ||
306 | mailsession * imap; | ||
307 | #endif | ||
308 | mailimap * imap; | ||
309 | #if 0 | ||
310 | struct imap_session_state_data * imap_data; | ||
311 | #endif | ||
312 | clist * list; | ||
313 | clistiter * cur; | ||
314 | struct imap_cached_session_state_data * data; | ||
315 | unsigned int i; | ||
316 | unsigned dest; | ||
317 | |||
318 | data = get_cached_data(session); | ||
319 | #if 0 | ||
320 | imap = get_ancestor(session); | ||
321 | |||
322 | imap_data = imap->data; | ||
323 | #endif | ||
324 | |||
325 | imap = get_imap_session(session); | ||
326 | |||
327 | if (imap->imap_response_info == NULL) | ||
328 | return; | ||
329 | |||
330 | list = imap->imap_response_info->rsp_expunged; | ||
331 | if (list == NULL) | ||
332 | return; | ||
333 | |||
334 | dest = 0; | ||
335 | i = 0; | ||
336 | /* remove expunged */ | ||
337 | for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { | ||
338 | uint32_t expunged; | ||
339 | |||
340 | expunged = * (uint32_t *) clist_content(cur); | ||
341 | |||
342 | while (i < carray_count(data->imap_uid_list)) { | ||
343 | struct uid_cache_item * cache_item; | ||
344 | |||
345 | if (dest + 1 == expunged) { | ||
346 | cache_item = carray_get(data->imap_uid_list, i); | ||
347 | free(cache_item); | ||
348 | i ++; | ||
349 | break; | ||
350 | } | ||
351 | else { | ||
352 | cache_item = carray_get(data->imap_uid_list, i); | ||
353 | carray_set(data->imap_uid_list, dest, cache_item); | ||
354 | i ++; | ||
355 | dest ++; | ||
356 | } | ||
357 | } | ||
358 | } | ||
359 | /* complete list */ | ||
360 | while (i < carray_count(data->imap_uid_list)) { | ||
361 | struct uid_cache_item * cache_item; | ||
362 | |||
363 | cache_item = carray_get(data->imap_uid_list, i); | ||
364 | carray_set(data->imap_uid_list, dest, cache_item); | ||
365 | i ++; | ||
366 | dest ++; | ||
367 | } | ||
368 | carray_set_size(data->imap_uid_list, dest); | ||
369 | } | ||
370 | |||
371 | static void imapdriver_cached_uninitialize(mailsession * session) | ||
372 | { | ||
373 | struct imap_cached_session_state_data * data; | ||
374 | unsigned int i; | ||
375 | |||
376 | data = get_cached_data(session); | ||
377 | |||
378 | for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { | ||
379 | struct uid_cache_item * cache_item; | ||
380 | |||
381 | cache_item = carray_get(data->imap_uid_list, i); | ||
382 | free(cache_item); | ||
383 | } | ||
384 | carray_free(data->imap_uid_list); | ||
385 | free_quoted_mb(data); | ||
386 | mailsession_free(data->imap_ancestor); | ||
387 | free(data); | ||
388 | |||
389 | session->sess_data = NULL; | ||
390 | } | ||
391 | |||
392 | |||
393 | static int imapdriver_cached_parameters(mailsession * session, | ||
394 | int id, void * value) | ||
395 | { | ||
396 | struct imap_cached_session_state_data * data; | ||
397 | int r; | ||
398 | |||
399 | data = get_cached_data(session); | ||
400 | |||
401 | switch (id) { | ||
402 | case IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY: | ||
403 | strncpy(data->imap_cache_directory, value, PATH_MAX); | ||
404 | data->imap_cache_directory[PATH_MAX - 1] = '\0'; | ||
405 | |||
406 | r = generic_cache_create_dir(data->imap_cache_directory); | ||
407 | if (r != MAIL_NO_ERROR) | ||
408 | return r; | ||
409 | |||
410 | return MAIL_NO_ERROR; | ||
411 | } | ||
412 | |||
413 | return MAIL_ERROR_INVAL; | ||
414 | } | ||
415 | |||
416 | |||
417 | static int imapdriver_cached_connect_stream(mailsession * session, | ||
418 | mailstream * s) | ||
419 | { | ||
420 | int r; | ||
421 | |||
422 | check_for_uid_cache(session); | ||
423 | |||
424 | r = mailsession_connect_stream(get_ancestor(session), s); | ||
425 | |||
426 | check_for_uid_cache(session); | ||
427 | |||
428 | return r; | ||
429 | } | ||
430 | |||
431 | static int imapdriver_cached_starttls(mailsession * session) | ||
432 | { | ||
433 | int r; | ||
434 | |||
435 | r = mailsession_starttls(get_ancestor(session)); | ||
436 | |||
437 | check_for_uid_cache(session); | ||
438 | |||
439 | return r; | ||
440 | } | ||
441 | |||
442 | static int imapdriver_cached_login(mailsession * session, | ||
443 | char * userid, char * password) | ||
444 | { | ||
445 | int r; | ||
446 | |||
447 | r = mailsession_login(get_ancestor(session), userid, password); | ||
448 | |||
449 | check_for_uid_cache(session); | ||
450 | |||
451 | return r; | ||
452 | } | ||
453 | |||
454 | static int imapdriver_cached_logout(mailsession * session) | ||
455 | { | ||
456 | int r; | ||
457 | |||
458 | r = mailsession_logout(get_ancestor(session)); | ||
459 | |||
460 | check_for_uid_cache(session); | ||
461 | |||
462 | if (r == MAIL_NO_ERROR) { | ||
463 | struct imap_cached_session_state_data * imap_cached_data; | ||
464 | |||
465 | imap_cached_data = get_cached_data(session); | ||
466 | |||
467 | free_quoted_mb(imap_cached_data); | ||
468 | } | ||
469 | |||
470 | return r; | ||
471 | } | ||
472 | |||
473 | static int imapdriver_cached_noop(mailsession * session) | ||
474 | { | ||
475 | int r; | ||
476 | |||
477 | r = mailsession_noop(get_ancestor(session)); | ||
478 | |||
479 | check_for_uid_cache(session); | ||
480 | |||
481 | return r; | ||
482 | } | ||
483 | |||
484 | static int imapdriver_cached_build_folder_name(mailsession * session, | ||
485 | char * mb, | ||
486 | char * name, char ** result) | ||
487 | { | ||
488 | int r; | ||
489 | |||
490 | r = mailsession_build_folder_name(get_ancestor(session), mb, | ||
491 | name, result); | ||
492 | |||
493 | check_for_uid_cache(session); | ||
494 | |||
495 | return r; | ||
496 | } | ||
497 | |||
498 | static int imapdriver_cached_create_folder(mailsession * session, char * mb) | ||
499 | { | ||
500 | int r; | ||
501 | |||
502 | r = mailsession_create_folder(get_ancestor(session), mb); | ||
503 | |||
504 | check_for_uid_cache(session); | ||
505 | |||
506 | return r; | ||
507 | } | ||
508 | |||
509 | static int imapdriver_cached_delete_folder(mailsession * session, char * mb) | ||
510 | { | ||
511 | int r; | ||
512 | |||
513 | r = mailsession_delete_folder(get_ancestor(session), mb); | ||
514 | |||
515 | check_for_uid_cache(session); | ||
516 | |||
517 | return r; | ||
518 | } | ||
519 | |||
520 | static int imapdriver_cached_rename_folder(mailsession * session, char * mb, | ||
521 | char * new_name) | ||
522 | { | ||
523 | int r; | ||
524 | |||
525 | r = mailsession_rename_folder(get_ancestor(session), mb, new_name); | ||
526 | |||
527 | check_for_uid_cache(session); | ||
528 | |||
529 | return r; | ||
530 | } | ||
531 | |||
532 | static int imapdriver_cached_check_folder(mailsession * session) | ||
533 | { | ||
534 | int r; | ||
535 | |||
536 | r = mailsession_check_folder(get_ancestor(session)); | ||
537 | |||
538 | check_for_uid_cache(session); | ||
539 | |||
540 | return r; | ||
541 | } | ||
542 | |||
543 | static int imapdriver_cached_examine_folder(mailsession * session, | ||
544 | char * mb) | ||
545 | { | ||
546 | int r; | ||
547 | |||
548 | r = mailsession_examine_folder(get_ancestor(session), mb); | ||
549 | |||
550 | check_for_uid_cache(session); | ||
551 | |||
552 | return r; | ||
553 | } | ||
554 | |||
555 | static int get_cache_folder(mailsession * session, char ** result) | ||
556 | { | ||
557 | #if 0 | ||
558 | mailsession * imap_session; | ||
559 | #endif | ||
560 | mailimap * imap; | ||
561 | char * mb; | ||
562 | char * cache_dir; | ||
563 | char * dirname; | ||
564 | char * quoted_mb; | ||
565 | int res; | ||
566 | int r; | ||
567 | char key[PATH_MAX]; | ||
568 | #if 0 | ||
569 | struct imap_session_state_data * imap_data; | ||
570 | struct imap_cached_session_state_data * cached_data; | ||
571 | #endif | ||
572 | |||
573 | #if 0 | ||
574 | imap_session = get_ancestor(session); | ||
575 | imap_data = imap_session->data; | ||
576 | imap = imap_data->session; | ||
577 | #endif | ||
578 | imap = get_imap_session(session); | ||
579 | |||
580 | mb = get_ancestor_data(session)->imap_mailbox; | ||
581 | |||
582 | cache_dir = get_cached_data(session)->imap_cache_directory; | ||
583 | |||
584 | if (imap->imap_state != MAILIMAP_STATE_SELECTED) | ||
585 | return MAIL_ERROR_BAD_STATE; | ||
586 | |||
587 | if (imap->imap_selection_info == NULL) | ||
588 | return MAIL_ERROR_BAD_STATE; | ||
589 | |||
590 | quoted_mb = maildriver_quote_mailbox(mb); | ||
591 | if (quoted_mb == NULL) { | ||
592 | res = MAIL_ERROR_MEMORY; | ||
593 | goto err; | ||
594 | } | ||
595 | |||
596 | snprintf(key, PATH_MAX, "%s/%s", cache_dir, quoted_mb); | ||
597 | |||
598 | dirname = strdup(key); | ||
599 | if (dirname == NULL) { | ||
600 | res = MAIL_ERROR_MEMORY; | ||
601 | goto free_mb; | ||
602 | } | ||
603 | |||
604 | r = generic_cache_create_dir(dirname); | ||
605 | if (r != MAIL_NO_ERROR) { | ||
606 | res = r; | ||
607 | goto free_dirname; | ||
608 | } | ||
609 | |||
610 | free(quoted_mb); | ||
611 | |||
612 | * result = dirname; | ||
613 | |||
614 | return MAIL_NO_ERROR; | ||
615 | |||
616 | free_dirname: | ||
617 | free(dirname); | ||
618 | free_mb: | ||
619 | free(quoted_mb); | ||
620 | err: | ||
621 | return res; | ||
622 | } | ||
623 | |||
624 | static int imapdriver_cached_select_folder(mailsession * session, char * mb) | ||
625 | { | ||
626 | int r; | ||
627 | char * quoted_mb; | ||
628 | struct imap_cached_session_state_data * data; | ||
629 | mailsession * imap; | ||
630 | char * old_mb; | ||
631 | |||
632 | imap = get_ancestor(session); | ||
633 | |||
634 | old_mb = get_ancestor_data(session)->imap_mailbox; | ||
635 | if (old_mb != NULL) | ||
636 | if (strcmp(mb, old_mb) == 0) | ||
637 | return MAIL_NO_ERROR; | ||
638 | |||
639 | r = mailsession_select_folder(get_ancestor(session), mb); | ||
640 | if (r != MAIL_NO_ERROR) | ||
641 | return r; | ||
642 | |||
643 | check_for_uid_cache(session); | ||
644 | |||
645 | r = get_cache_folder(session, "ed_mb); | ||
646 | if (r != MAIL_NO_ERROR) | ||
647 | return r; | ||
648 | |||
649 | data = get_cached_data(session); | ||
650 | if (data->imap_quoted_mb != NULL) | ||
651 | free(data->imap_quoted_mb); | ||
652 | data->imap_quoted_mb = quoted_mb; | ||
653 | |||
654 | /* clear UID cache */ | ||
655 | carray_set_size(data->imap_uid_list, 0); | ||
656 | |||
657 | return MAIL_NO_ERROR; | ||
658 | } | ||
659 | |||
660 | static int imapdriver_cached_expunge_folder(mailsession * session) | ||
661 | { | ||
662 | int r; | ||
663 | |||
664 | r = mailsession_expunge_folder(get_ancestor(session)); | ||
665 | |||
666 | check_for_uid_cache(session); | ||
667 | |||
668 | return r; | ||
669 | } | ||
670 | |||
671 | static int imapdriver_cached_status_folder(mailsession * session, char * mb, | ||
672 | uint32_t * result_messages, uint32_t * result_recent, | ||
673 | uint32_t * result_unseen) | ||
674 | { | ||
675 | int r; | ||
676 | |||
677 | r = mailsession_status_folder(get_ancestor(session), mb, result_messages, | ||
678 | result_recent, result_unseen); | ||
679 | |||
680 | check_for_uid_cache(session); | ||
681 | |||
682 | return r; | ||
683 | } | ||
684 | |||
685 | static int imapdriver_cached_messages_number(mailsession * session, | ||
686 | char * mb, | ||
687 | uint32_t * result) | ||
688 | { | ||
689 | int r; | ||
690 | |||
691 | r = mailsession_messages_number(get_ancestor(session), mb, result); | ||
692 | |||
693 | check_for_uid_cache(session); | ||
694 | |||
695 | return r; | ||
696 | } | ||
697 | |||
698 | static int imapdriver_cached_recent_number(mailsession * session, char * mb, | ||
699 | uint32_t * result) | ||
700 | { | ||
701 | int r; | ||
702 | |||
703 | r = mailsession_recent_number(get_ancestor(session), mb, result); | ||
704 | |||
705 | check_for_uid_cache(session); | ||
706 | |||
707 | return r; | ||
708 | } | ||
709 | |||
710 | static int imapdriver_cached_unseen_number(mailsession * session, char * mb, | ||
711 | uint32_t * result) | ||
712 | { | ||
713 | int r; | ||
714 | |||
715 | r = mailsession_unseen_number(get_ancestor(session), mb, result); | ||
716 | |||
717 | check_for_uid_cache(session); | ||
718 | |||
719 | return r; | ||
720 | } | ||
721 | |||
722 | static int imapdriver_cached_list_folders(mailsession * session, char * mb, | ||
723 | struct mail_list ** result) | ||
724 | { | ||
725 | int r; | ||
726 | |||
727 | r = mailsession_list_folders(get_ancestor(session), mb, result); | ||
728 | |||
729 | check_for_uid_cache(session); | ||
730 | |||
731 | return r; | ||
732 | } | ||
733 | |||
734 | static int imapdriver_cached_lsub_folders(mailsession * session, char * mb, | ||
735 | struct mail_list ** result) | ||
736 | { | ||
737 | int r; | ||
738 | |||
739 | r = mailsession_lsub_folders(get_ancestor(session), mb, result); | ||
740 | |||
741 | check_for_uid_cache(session); | ||
742 | |||
743 | return r; | ||
744 | } | ||
745 | |||
746 | static int imapdriver_cached_subscribe_folder(mailsession * session, | ||
747 | char * mb) | ||
748 | { | ||
749 | int r; | ||
750 | |||
751 | r = mailsession_subscribe_folder(get_ancestor(session), mb); | ||
752 | |||
753 | check_for_uid_cache(session); | ||
754 | |||
755 | return r; | ||
756 | } | ||
757 | |||
758 | static int imapdriver_cached_unsubscribe_folder(mailsession * session, | ||
759 | char * mb) | ||
760 | { | ||
761 | int r; | ||
762 | |||
763 | r = mailsession_unsubscribe_folder(get_ancestor(session), mb); | ||
764 | |||
765 | check_for_uid_cache(session); | ||
766 | |||
767 | return r; | ||
768 | } | ||
769 | |||
770 | static int imapdriver_cached_append_message(mailsession * session, | ||
771 | char * message, size_t size) | ||
772 | { | ||
773 | int r; | ||
774 | |||
775 | r = mailsession_append_message(get_ancestor(session), message, size); | ||
776 | |||
777 | check_for_uid_cache(session); | ||
778 | |||
779 | return r; | ||
780 | } | ||
781 | |||
782 | static int imapdriver_cached_append_message_flags(mailsession * session, | ||
783 | char * message, size_t size, struct mail_flags * flags) | ||
784 | { | ||
785 | int r; | ||
786 | |||
787 | r = mailsession_append_message_flags(get_ancestor(session), | ||
788 | message, size, flags); | ||
789 | |||
790 | check_for_uid_cache(session); | ||
791 | |||
792 | return r; | ||
793 | } | ||
794 | |||
795 | static int imapdriver_cached_copy_message(mailsession * session, | ||
796 | uint32_t num, char * mb) | ||
797 | { | ||
798 | int r; | ||
799 | |||
800 | r = mailsession_copy_message(get_ancestor(session), num, mb); | ||
801 | |||
802 | check_for_uid_cache(session); | ||
803 | |||
804 | return r; | ||
805 | } | ||
806 | |||
807 | static int cmp_uid(uint32_t ** pa, uint32_t ** pb) | ||
808 | { | ||
809 | uint32_t * a; | ||
810 | uint32_t * b; | ||
811 | |||
812 | a = * pa; | ||
813 | b = * pb; | ||
814 | |||
815 | return * a - * b; | ||
816 | } | ||
817 | |||
818 | |||
819 | static int imapdriver_cached_get_messages_list(mailsession * session, | ||
820 | struct mailmessage_list ** | ||
821 | result) | ||
822 | { | ||
823 | #if 0 | ||
824 | mailsession * imap_session; | ||
825 | #endif | ||
826 | mailimap * imap; | ||
827 | uint32_t uid_max; | ||
828 | struct imap_cached_session_state_data * data; | ||
829 | struct mailmessage_list * env_list; | ||
830 | unsigned i; | ||
831 | int r; | ||
832 | int res; | ||
833 | carray * tab; | ||
834 | |||
835 | #if 0 | ||
836 | data = session->data; | ||
837 | imap_session = get_ancestor(session); | ||
838 | imap = ((struct imap_session_state_data *) (imap_session->data))->session; | ||
839 | #endif | ||
840 | data = get_cached_data(session); | ||
841 | imap = get_imap_session(session); | ||
842 | |||
843 | uid_max = 0; | ||
844 | |||
845 | #ifdef CACHE_MESSAGE_LIST | ||
846 | /* get UID max */ | ||
847 | uid_max = 0; | ||
848 | for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { | ||
849 | struct uid_cache_item * cache_item; | ||
850 | |||
851 | cache_item = carray_get(data->imap_uid_list, i); | ||
852 | if (cache_item->uid > uid_max) | ||
853 | uid_max = cache_item->uid; | ||
854 | } | ||
855 | #endif | ||
856 | |||
857 | r = imap_get_messages_list(imap, session, imap_cached_message_driver, | ||
858 | uid_max + 1, &env_list); | ||
859 | |||
860 | check_for_uid_cache(session); | ||
861 | |||
862 | if (r != MAIL_NO_ERROR) { | ||
863 | res = r; | ||
864 | goto err; | ||
865 | } | ||
866 | |||
867 | #ifdef CACHE_MESSAGE_LIST | ||
868 | /* remove unsollicited message */ | ||
869 | i = 0; | ||
870 | while (i < carray_count(env_list->msg_tab)) { | ||
871 | mailmessage * msg; | ||
872 | |||
873 | msg = carray_get(env_list->msg_tab, i); | ||
874 | if (msg->msg_index < uid_max + 1) { | ||
875 | mailmessage * msg; | ||
876 | |||
877 | msg = carray_get(env_list->msg_tab, i); | ||
878 | mailmessage_free(msg); | ||
879 | carray_delete(env_list->msg_tab, i); | ||
880 | } | ||
881 | else { | ||
882 | i ++; | ||
883 | } | ||
884 | } | ||
885 | |||
886 | tab = carray_new(carray_count(env_list->msg_tab) + | ||
887 | carray_count(data->imap_uid_list)); | ||
888 | if (tab == NULL) { | ||
889 | res = MAIL_ERROR_MEMORY; | ||
890 | goto free; | ||
891 | } | ||
892 | carray_set_size(tab, | ||
893 | carray_count(env_list->msg_tab) + carray_count(data->imap_uid_list)); | ||
894 | |||
895 | /* sort cached data before adding them to the list */ | ||
896 | qsort(carray_data(data->imap_uid_list), carray_count(data->imap_uid_list), | ||
897 | sizeof(* carray_data(data->imap_uid_list)), | ||
898 | (int (*)(const void *, const void *)) cmp_uid); | ||
899 | |||
900 | /* adds cached UID */ | ||
901 | for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { | ||
902 | struct uid_cache_item * cache_item; | ||
903 | mailmessage * msg; | ||
904 | |||
905 | cache_item = carray_get(data->imap_uid_list, i); | ||
906 | |||
907 | msg = mailmessage_new(); | ||
908 | if (msg == NULL) { | ||
909 | res = MAIL_ERROR_MEMORY; | ||
910 | goto free; | ||
911 | } | ||
912 | |||
913 | r = mailmessage_init(msg, session, imap_cached_message_driver, | ||
914 | cache_item->uid, cache_item->size); | ||
915 | if (r != MAIL_NO_ERROR) { | ||
916 | mailmessage_free(msg); | ||
917 | res = r; | ||
918 | goto free; | ||
919 | } | ||
920 | |||
921 | carray_set(tab, i, msg); | ||
922 | } | ||
923 | |||
924 | /* adds new elements */ | ||
925 | for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { | ||
926 | mailmessage * msg; | ||
927 | |||
928 | msg = carray_get(env_list->msg_tab, i); | ||
929 | carray_set(tab, carray_count(data->imap_uid_list) + i, msg); | ||
930 | } | ||
931 | |||
932 | /* replace list of messages in env_list */ | ||
933 | carray_free(env_list->msg_tab); | ||
934 | env_list->msg_tab = tab; | ||
935 | |||
936 | r = update_uid_cache(session, env_list); | ||
937 | if (r != MAIL_NO_ERROR) { | ||
938 | res = r; | ||
939 | goto free; | ||
940 | } | ||
941 | #endif | ||
942 | |||
943 | * result = env_list; | ||
944 | |||
945 | return MAIL_NO_ERROR; | ||
946 | |||
947 | free: | ||
948 | mailmessage_list_free(env_list); | ||
949 | err: | ||
950 | return res; | ||
951 | } | ||
952 | |||
953 | #define IMAP_SET_MAX_COUNT 100 | ||
954 | |||
955 | static int get_flags_list(mailsession * session, | ||
956 | struct mailmessage_list * env_list) | ||
957 | { | ||
958 | struct mailimap_set * set; | ||
959 | struct mailimap_fetch_att * fetch_att; | ||
960 | struct mailimap_fetch_type * fetch_type; | ||
961 | int res; | ||
962 | clist * fetch_result; | ||
963 | int r; | ||
964 | clist * msg_list; | ||
965 | #if 0 | ||
966 | struct imap_session_state_data * data; | ||
967 | #endif | ||
968 | unsigned i; | ||
969 | unsigned dest; | ||
970 | clistiter * set_iter; | ||
971 | |||
972 | #if 0 | ||
973 | data = session->data; | ||
974 | #endif | ||
975 | |||
976 | fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); | ||
977 | if (fetch_type == NULL) { | ||
978 | res = MAIL_ERROR_MEMORY; | ||
979 | goto err; | ||
980 | } | ||
981 | |||
982 | fetch_att = mailimap_fetch_att_new_uid(); | ||
983 | if (fetch_att == NULL) { | ||
984 | res = MAIL_ERROR_MEMORY; | ||
985 | goto free_fetch_type; | ||
986 | } | ||
987 | |||
988 | r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); | ||
989 | if (r != MAILIMAP_NO_ERROR) { | ||
990 | mailimap_fetch_att_free(fetch_att); | ||
991 | res = MAIL_ERROR_MEMORY; | ||
992 | goto free_fetch_type; | ||
993 | } | ||
994 | |||
995 | fetch_att = mailimap_fetch_att_new_flags(); | ||
996 | if (fetch_att == NULL) { | ||
997 | res = MAIL_ERROR_MEMORY; | ||
998 | goto free_fetch_type; | ||
999 | } | ||
1000 | |||
1001 | r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); | ||
1002 | if (r != MAILIMAP_NO_ERROR) { | ||
1003 | mailimap_fetch_att_free(fetch_att); | ||
1004 | res = MAIL_ERROR_MEMORY; | ||
1005 | goto free_fetch_type; | ||
1006 | } | ||
1007 | |||
1008 | r = maildriver_env_list_to_msg_list_no_flags(env_list, &msg_list); | ||
1009 | if (r != MAIL_NO_ERROR) { | ||
1010 | res = MAIL_ERROR_MEMORY; | ||
1011 | goto free_fetch_type; | ||
1012 | } | ||
1013 | |||
1014 | if (clist_begin(msg_list) == NULL) { | ||
1015 | /* no need to fetch envelopes */ | ||
1016 | |||
1017 | clist_free(msg_list); | ||
1018 | mailimap_fetch_type_free(fetch_type); | ||
1019 | return MAIL_NO_ERROR; | ||
1020 | } | ||
1021 | |||
1022 | r = msg_list_to_imap_set(msg_list, &set); | ||
1023 | if (r != MAIL_NO_ERROR) { | ||
1024 | clist_foreach(msg_list, (clist_func) free, NULL); | ||
1025 | clist_free(msg_list); | ||
1026 | res = MAIL_ERROR_MEMORY; | ||
1027 | goto free_fetch_type; | ||
1028 | } | ||
1029 | clist_foreach(msg_list, (clist_func) free, NULL); | ||
1030 | clist_free(msg_list); | ||
1031 | |||
1032 | set_iter = clist_begin(set->set_list); | ||
1033 | while (set_iter != NULL) { | ||
1034 | struct mailimap_set * subset; | ||
1035 | unsigned int count; | ||
1036 | |||
1037 | subset = mailimap_set_new_empty(); | ||
1038 | if (subset == NULL) { | ||
1039 | res = MAIL_ERROR_MEMORY; | ||
1040 | mailimap_fetch_type_free(fetch_type); | ||
1041 | mailimap_set_free(set); | ||
1042 | res = MAIL_ERROR_MEMORY; | ||
1043 | goto err; | ||
1044 | } | ||
1045 | |||
1046 | count = 0; | ||
1047 | while (count < IMAP_SET_MAX_COUNT) { | ||
1048 | struct mailimap_set_item * item; | ||
1049 | |||
1050 | item = clist_content(set_iter); | ||
1051 | set_iter = clist_delete(set->set_list, set_iter); | ||
1052 | |||
1053 | r = mailimap_set_add(subset, item); | ||
1054 | if (r != MAILIMAP_NO_ERROR) { | ||
1055 | mailimap_set_item_free(item); | ||
1056 | mailimap_set_free(subset); | ||
1057 | mailimap_fetch_type_free(fetch_type); | ||
1058 | mailimap_set_free(set); | ||
1059 | res = MAIL_ERROR_MEMORY; | ||
1060 | goto err; | ||
1061 | } | ||
1062 | |||
1063 | count ++; | ||
1064 | |||
1065 | if (set_iter == NULL) | ||
1066 | break; | ||
1067 | } | ||
1068 | |||
1069 | r = mailimap_uid_fetch(get_imap_session(session), subset, | ||
1070 | fetch_type, &fetch_result); | ||
1071 | |||
1072 | mailimap_set_free(subset); | ||
1073 | |||
1074 | switch (r) { | ||
1075 | case MAILIMAP_NO_ERROR: | ||
1076 | break; | ||
1077 | default: | ||
1078 | mailimap_fetch_type_free(fetch_type); | ||
1079 | mailimap_set_free(set); | ||
1080 | return imap_error_to_mail_error(r); | ||
1081 | } | ||
1082 | |||
1083 | if (clist_begin(fetch_result) == NULL) { | ||
1084 | res = MAIL_ERROR_FETCH; | ||
1085 | goto err; | ||
1086 | } | ||
1087 | |||
1088 | r = imap_fetch_result_to_envelop_list(fetch_result, env_list); | ||
1089 | mailimap_fetch_list_free(fetch_result); | ||
1090 | |||
1091 | if (r != MAIL_NO_ERROR) { | ||
1092 | mailimap_fetch_type_free(fetch_type); | ||
1093 | mailimap_set_free(set); | ||
1094 | res = MAIL_ERROR_MEMORY; | ||
1095 | goto err; | ||
1096 | } | ||
1097 | } | ||
1098 | |||
1099 | #if 0 | ||
1100 | r = mailimap_uid_fetch(get_imap_session(session), set, | ||
1101 | fetch_type, &fetch_result); | ||
1102 | #endif | ||
1103 | |||
1104 | mailimap_fetch_type_free(fetch_type); | ||
1105 | mailimap_set_free(set); | ||
1106 | |||
1107 | #if 0 | ||
1108 | switch (r) { | ||
1109 | case MAILIMAP_NO_ERROR: | ||
1110 | break; | ||
1111 | default: | ||
1112 | return imap_error_to_mail_error(r); | ||
1113 | } | ||
1114 | |||
1115 | r = imap_fetch_result_to_envelop_list(fetch_result, env_list); | ||
1116 | mailimap_fetch_list_free(fetch_result); | ||
1117 | |||
1118 | if (r != MAIL_NO_ERROR) { | ||
1119 | res = MAIL_ERROR_MEMORY; | ||
1120 | goto err; | ||
1121 | } | ||
1122 | #endif | ||
1123 | |||
1124 | /* remove messages that don't have flags */ | ||
1125 | i = 0; | ||
1126 | dest = 0; | ||
1127 | while (i < carray_count(env_list->msg_tab)) { | ||
1128 | mailmessage * msg; | ||
1129 | |||
1130 | msg = carray_get(env_list->msg_tab, i); | ||
1131 | if (msg->msg_flags != NULL) { | ||
1132 | carray_set(env_list->msg_tab, dest, msg); | ||
1133 | dest ++; | ||
1134 | } | ||
1135 | else { | ||
1136 | mailmessage_free(msg); | ||
1137 | } | ||
1138 | i ++; | ||
1139 | } | ||
1140 | carray_set_size(env_list->msg_tab, dest); | ||
1141 | |||
1142 | return MAIL_NO_ERROR; | ||
1143 | |||
1144 | free_fetch_type: | ||
1145 | mailimap_fetch_type_free(fetch_type); | ||
1146 | err: | ||
1147 | return res; | ||
1148 | } | ||
1149 | |||
1150 | |||
1151 | #define ENV_NAME "env.db" | ||
1152 | |||
1153 | static void get_uid_from_filename(char * filename) | ||
1154 | { | ||
1155 | char * p; | ||
1156 | |||
1157 | p = strstr(filename, "-part"); | ||
1158 | if (p != NULL) | ||
1159 | * p = 0; | ||
1160 | p = strstr(filename, "-envelope"); | ||
1161 | if (p != NULL) | ||
1162 | * p = 0; | ||
1163 | p = strstr(filename, "-rfc822"); | ||
1164 | if (p != NULL) | ||
1165 | * p = 0; | ||
1166 | } | ||
1167 | |||
1168 | static int | ||
1169 | imapdriver_cached_get_envelopes_list(mailsession * session, | ||
1170 | struct mailmessage_list * env_list) | ||
1171 | { | ||
1172 | int r; | ||
1173 | int res; | ||
1174 | uint32_t i; | ||
1175 | struct imap_cached_session_state_data * data; | ||
1176 | MMAPString * mmapstr; | ||
1177 | struct mail_cache_db * cache_db; | ||
1178 | char filename[PATH_MAX]; | ||
1179 | |||
1180 | data = get_cached_data(session); | ||
1181 | if (data->imap_quoted_mb == NULL) { | ||
1182 | res = MAIL_ERROR_BAD_STATE; | ||
1183 | goto err; | ||
1184 | } | ||
1185 | |||
1186 | mmapstr = mmap_string_new(""); | ||
1187 | if (mmapstr == NULL) { | ||
1188 | res = MAIL_ERROR_MEMORY; | ||
1189 | goto err; | ||
1190 | } | ||
1191 | |||
1192 | snprintf(filename, PATH_MAX, "%s/%s", data->imap_quoted_mb, ENV_NAME); | ||
1193 | |||
1194 | r = mail_cache_db_open_lock(filename, &cache_db); | ||
1195 | if (r < 0) { | ||
1196 | res = MAIL_ERROR_MEMORY; | ||
1197 | goto free_mmapstr; | ||
1198 | } | ||
1199 | |||
1200 | /* fill with cached */ | ||
1201 | |||
1202 | for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { | ||
1203 | mailmessage * msg; | ||
1204 | struct mailimf_fields * fields; | ||
1205 | |||
1206 | msg = carray_get(env_list->msg_tab, i); | ||
1207 | |||
1208 | if (msg->msg_fields == NULL) { | ||
1209 | r = imapdriver_get_cached_envelope(cache_db, mmapstr, | ||
1210 | session, msg, &fields); | ||
1211 | if (r == MAIL_NO_ERROR) { | ||
1212 | msg->msg_cached = TRUE; | ||
1213 | msg->msg_fields = fields; | ||
1214 | } | ||
1215 | } | ||
1216 | } | ||
1217 | |||
1218 | mail_cache_db_close_unlock(filename, cache_db); | ||
1219 | |||
1220 | r = mailsession_get_envelopes_list(get_ancestor(session), env_list); | ||
1221 | |||
1222 | check_for_uid_cache(session); | ||
1223 | |||
1224 | if (r != MAIL_NO_ERROR) { | ||
1225 | res = r; | ||
1226 | goto free_mmapstr; | ||
1227 | } | ||
1228 | |||
1229 | r = get_flags_list(session, env_list); | ||
1230 | |||
1231 | if (r != MAIL_NO_ERROR) { | ||
1232 | res = r; | ||
1233 | goto free_mmapstr; | ||
1234 | } | ||
1235 | |||
1236 | #ifdef CACHE_MESSAGE_LIST | ||
1237 | r = update_uid_cache(session, env_list); | ||
1238 | if (r != MAIL_NO_ERROR) { | ||
1239 | res = r; | ||
1240 | goto free_mmapstr; | ||
1241 | } | ||
1242 | #endif | ||
1243 | |||
1244 | /* must write cache */ | ||
1245 | |||
1246 | r = mail_cache_db_open_lock(filename, &cache_db); | ||
1247 | if (r < 0) { | ||
1248 | res = MAIL_ERROR_MEMORY; | ||
1249 | goto free_mmapstr; | ||
1250 | } | ||
1251 | |||
1252 | for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { | ||
1253 | mailmessage * msg; | ||
1254 | |||
1255 | msg = carray_get(env_list->msg_tab, i); | ||
1256 | |||
1257 | if (msg->msg_fields != NULL) { | ||
1258 | if (!msg->msg_cached) { | ||
1259 | r = imapdriver_write_cached_envelope(cache_db, mmapstr, | ||
1260 | session, msg, msg->msg_fields); | ||
1261 | } | ||
1262 | } | ||
1263 | } | ||
1264 | |||
1265 | /* flush cache */ | ||
1266 | |||
1267 | maildriver_cache_clean_up(cache_db, NULL, env_list); | ||
1268 | |||
1269 | mail_cache_db_close_unlock(filename, cache_db); | ||
1270 | mmap_string_free(mmapstr); | ||
1271 | |||
1272 | /* remove cache files */ | ||
1273 | |||
1274 | maildriver_message_cache_clean_up(data->imap_quoted_mb, env_list, | ||
1275 | get_uid_from_filename); | ||
1276 | |||
1277 | return MAIL_NO_ERROR; | ||
1278 | |||
1279 | free_mmapstr: | ||
1280 | mmap_string_free(mmapstr); | ||
1281 | err: | ||
1282 | return res; | ||
1283 | } | ||
1284 | |||
1285 | static int imapdriver_cached_remove_message(mailsession * session, | ||
1286 | uint32_t num) | ||
1287 | { | ||
1288 | int r; | ||
1289 | |||
1290 | r = mailsession_remove_message(get_ancestor(session), num); | ||
1291 | |||
1292 | check_for_uid_cache(session); | ||
1293 | |||
1294 | return r; | ||
1295 | } | ||
1296 | |||
1297 | #if 0 | ||
1298 | static int imapdriver_cached_search_messages(mailsession * session, | ||
1299 | char * charset, | ||
1300 | struct mail_search_key * key, | ||
1301 | struct mail_search_result ** | ||
1302 | result) | ||
1303 | { | ||
1304 | int r; | ||
1305 | |||
1306 | r = mailsession_search_messages(get_ancestor(session), charset, key, result); | ||
1307 | |||
1308 | check_for_uid_cache(session); | ||
1309 | |||
1310 | return r; | ||
1311 | } | ||
1312 | #endif | ||
1313 | |||
1314 | static int imapdriver_cached_get_message(mailsession * session, | ||
1315 | uint32_t num, mailmessage ** result) | ||
1316 | { | ||
1317 | mailmessage * msg_info; | ||
1318 | int r; | ||
1319 | |||
1320 | msg_info = mailmessage_new(); | ||
1321 | if (msg_info == NULL) | ||
1322 | return MAIL_ERROR_MEMORY; | ||
1323 | |||
1324 | r = mailmessage_init(msg_info, session, imap_cached_message_driver, num, 0); | ||
1325 | if (r != MAIL_NO_ERROR) { | ||
1326 | mailmessage_free(msg_info); | ||
1327 | return r; | ||
1328 | } | ||
1329 | |||
1330 | * result = msg_info; | ||
1331 | |||
1332 | return MAIL_NO_ERROR; | ||
1333 | } | ||
1334 | |||
1335 | /* Retrieve a message by UID | ||
1336 | * libEtPan! uid format for IMAP is "UIDVALIDITY-UID" | ||
1337 | * where UIDVALIDITY and UID are decimal representation of | ||
1338 | * respectively uidvalidity and uid numbers. | ||
1339 | * Return value: | ||
1340 | * MAIL_ERROR_INVAL if uid is NULL or has an incorrect format. | ||
1341 | * MAIL_ERROR_MSG_NOT_FOUND if uidvalidity has changed or uid was not found | ||
1342 | * MAIL_NO_ERROR if message was found. Result is in result | ||
1343 | */ | ||
1344 | static int imapdriver_cached_get_message_by_uid(mailsession * session, | ||
1345 | const char * uid, | ||
1346 | mailmessage ** result) | ||
1347 | { | ||
1348 | uint32_t uidvalidity; | ||
1349 | uint32_t num; | ||
1350 | char * p1, * p2; | ||
1351 | mailimap *imap; | ||
1352 | |||
1353 | if (uid == NULL) | ||
1354 | return MAIL_ERROR_INVAL; | ||
1355 | |||
1356 | uidvalidity = strtoul(uid, &p1, 10); | ||
1357 | if (p1 == uid || * p1 != '-') | ||
1358 | return MAIL_ERROR_INVAL; | ||
1359 | |||
1360 | p1++; | ||
1361 | num = strtoul(p1, &p2, 10); | ||
1362 | if (p2 == p1 || * p2 != '\0') | ||
1363 | return MAIL_ERROR_INVAL; | ||
1364 | |||
1365 | imap = get_imap_session(session); | ||
1366 | if (imap->imap_selection_info->sel_uidvalidity != uidvalidity) | ||
1367 | return MAIL_ERROR_MSG_NOT_FOUND; | ||
1368 | |||
1369 | return imapdriver_cached_get_message(session, num, result); | ||
1370 | } | ||