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