author | zautrix <zautrix> | 2004-07-03 16:33:12 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-07-03 16:33:12 (UTC) |
commit | e3b89230f065c48c84b48c88edb6eb088374c487 (patch) (unidiff) | |
tree | 162ea2ef909a6f82ccfcedf45d80d6c821174912 /kmicromail/libetpan/generic/nntpdriver_cached.c | |
parent | 2dd6ac0b2d24c91d35ce674a6c26351352df2b15 (diff) | |
download | kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.zip kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.tar.gz kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.tar.bz2 |
Initial revision
Diffstat (limited to 'kmicromail/libetpan/generic/nntpdriver_cached.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | kmicromail/libetpan/generic/nntpdriver_cached.c | 1048 |
1 files changed, 1048 insertions, 0 deletions
diff --git a/kmicromail/libetpan/generic/nntpdriver_cached.c b/kmicromail/libetpan/generic/nntpdriver_cached.c new file mode 100644 index 0000000..1f8a8af --- a/dev/null +++ b/kmicromail/libetpan/generic/nntpdriver_cached.c | |||
@@ -0,0 +1,1048 @@ | |||
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 "nntpdriver_cached.h" | ||
37 | |||
38 | #include "libetpan-config.h" | ||
39 | |||
40 | #include <string.h> | ||
41 | #include <stdio.h> | ||
42 | #include <sys/types.h> | ||
43 | #include <sys/stat.h> | ||
44 | #include <fcntl.h> | ||
45 | #include <unistd.h> | ||
46 | #include <stdlib.h> | ||
47 | |||
48 | #include "mail_cache_db.h" | ||
49 | |||
50 | #include "mail.h" | ||
51 | #include "mailmessage.h" | ||
52 | #include "maildriver_tools.h" | ||
53 | #include "nntpdriver.h" | ||
54 | #include "maildriver.h" | ||
55 | #include "newsnntp.h" | ||
56 | #include "generic_cache.h" | ||
57 | #include "imfcache.h" | ||
58 | #include "maillock.h" | ||
59 | #include "nntpdriver_cached_message.h" | ||
60 | #include "nntpdriver_tools.h" | ||
61 | |||
62 | static int nntpdriver_cached_initialize(mailsession * session); | ||
63 | |||
64 | static void nntpdriver_cached_uninitialize(mailsession * session); | ||
65 | |||
66 | static int nntpdriver_cached_parameters(mailsession * session, | ||
67 | int id, void * value); | ||
68 | |||
69 | static int nntpdriver_cached_connect_stream(mailsession * session, | ||
70 | mailstream * s); | ||
71 | |||
72 | static int nntpdriver_cached_login(mailsession * session, | ||
73 | char * userid, char * password); | ||
74 | |||
75 | static int nntpdriver_cached_logout(mailsession * session); | ||
76 | |||
77 | static int nntpdriver_cached_check_folder(mailsession * session); | ||
78 | |||
79 | static int nntpdriver_cached_select_folder(mailsession * session, char * mb); | ||
80 | |||
81 | static int nntpdriver_cached_status_folder(mailsession * session, | ||
82 | char * mb, | ||
83 | uint32_t * result_messages, | ||
84 | uint32_t * result_recent, | ||
85 | uint32_t * result_unseen); | ||
86 | |||
87 | static int nntpdriver_cached_messages_number(mailsession * session, char * mb, | ||
88 | uint32_t * result); | ||
89 | |||
90 | static int nntpdriver_cached_recent_number(mailsession * session, char * mb, | ||
91 | uint32_t * result); | ||
92 | |||
93 | static int nntpdriver_cached_unseen_number(mailsession * session, char * mb, | ||
94 | uint32_t * result); | ||
95 | |||
96 | static int nntpdriver_cached_append_message(mailsession * session, | ||
97 | char * message, size_t size); | ||
98 | |||
99 | static int | ||
100 | nntpdriver_cached_get_envelopes_list(mailsession * session, | ||
101 | struct mailmessage_list * env_list); | ||
102 | |||
103 | |||
104 | static int | ||
105 | nntpdriver_cached_get_messages_list(mailsession * session, | ||
106 | struct mailmessage_list ** result); | ||
107 | |||
108 | static int nntpdriver_cached_list_folders(mailsession * session, char * mb, | ||
109 | struct mail_list ** result); | ||
110 | |||
111 | static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb, | ||
112 | struct mail_list ** result); | ||
113 | |||
114 | static int nntpdriver_cached_subscribe_folder(mailsession * session, | ||
115 | char * mb); | ||
116 | |||
117 | static int nntpdriver_cached_unsubscribe_folder(mailsession * session, | ||
118 | char * mb); | ||
119 | |||
120 | static int nntpdriver_cached_get_message(mailsession * session, | ||
121 | uint32_t num, mailmessage ** result); | ||
122 | |||
123 | static int nntpdriver_cached_noop(mailsession * session); | ||
124 | |||
125 | static int nntpdriver_cached_get_message_by_uid(mailsession * session, | ||
126 | const char * uid, | ||
127 | mailmessage ** result); | ||
128 | |||
129 | static mailsession_driver local_nntp_cached_session_driver = { | ||
130 | .sess_name = "nntp-cached", | ||
131 | |||
132 | .sess_initialize = nntpdriver_cached_initialize, | ||
133 | .sess_uninitialize = nntpdriver_cached_uninitialize, | ||
134 | |||
135 | .sess_parameters = nntpdriver_cached_parameters, | ||
136 | |||
137 | .sess_connect_stream = nntpdriver_cached_connect_stream, | ||
138 | .sess_connect_path = NULL, | ||
139 | .sess_starttls = NULL, | ||
140 | .sess_login = nntpdriver_cached_login, | ||
141 | .sess_logout = nntpdriver_cached_logout, | ||
142 | .sess_noop = nntpdriver_cached_noop, | ||
143 | |||
144 | .sess_build_folder_name = NULL, | ||
145 | .sess_create_folder = NULL, | ||
146 | .sess_delete_folder = NULL, | ||
147 | .sess_rename_folder = NULL, | ||
148 | .sess_check_folder = nntpdriver_cached_check_folder, | ||
149 | .sess_examine_folder = NULL, | ||
150 | .sess_select_folder = nntpdriver_cached_select_folder, | ||
151 | .sess_expunge_folder = NULL, | ||
152 | .sess_status_folder = nntpdriver_cached_status_folder, | ||
153 | .sess_messages_number = nntpdriver_cached_messages_number, | ||
154 | .sess_recent_number = nntpdriver_cached_recent_number, | ||
155 | .sess_unseen_number = nntpdriver_cached_unseen_number, | ||
156 | .sess_list_folders = nntpdriver_cached_list_folders, | ||
157 | .sess_lsub_folders = nntpdriver_cached_lsub_folders, | ||
158 | .sess_subscribe_folder = nntpdriver_cached_subscribe_folder, | ||
159 | .sess_unsubscribe_folder = nntpdriver_cached_unsubscribe_folder, | ||
160 | |||
161 | .sess_append_message = nntpdriver_cached_append_message, | ||
162 | .sess_copy_message = NULL, | ||
163 | .sess_move_message = NULL, | ||
164 | |||
165 | .sess_get_messages_list = nntpdriver_cached_get_messages_list, | ||
166 | .sess_get_envelopes_list = nntpdriver_cached_get_envelopes_list, | ||
167 | .sess_remove_message = NULL, | ||
168 | #if 0 | ||
169 | .sess_search_messages = maildriver_generic_search_messages, | ||
170 | #endif | ||
171 | |||
172 | .sess_get_message = nntpdriver_cached_get_message, | ||
173 | .sess_get_message_by_uid = nntpdriver_cached_get_message_by_uid, | ||
174 | }; | ||
175 | |||
176 | |||
177 | mailsession_driver * nntp_cached_session_driver = | ||
178 | &local_nntp_cached_session_driver; | ||
179 | |||
180 | #define ENV_NAME "env.db" | ||
181 | #define FLAGS_NAME "flags.db" | ||
182 | |||
183 | |||
184 | |||
185 | static void read_article_seq(mailsession * session, | ||
186 | uint32_t * pfirst, uint32_t * plast); | ||
187 | |||
188 | static void write_article_seq(mailsession * session, | ||
189 | uint32_t first, uint32_t last); | ||
190 | |||
191 | |||
192 | static inline struct nntp_cached_session_state_data * | ||
193 | get_cached_data(mailsession * session) | ||
194 | { | ||
195 | return session->sess_data; | ||
196 | } | ||
197 | |||
198 | static inline mailsession * get_ancestor(mailsession * session) | ||
199 | { | ||
200 | return get_cached_data(session)->nntp_ancestor; | ||
201 | } | ||
202 | |||
203 | static inline struct nntp_session_state_data * | ||
204 | get_ancestor_data(mailsession * session) | ||
205 | { | ||
206 | return get_ancestor(session)->sess_data; | ||
207 | } | ||
208 | |||
209 | static inline newsnntp * get_nntp_session(mailsession * session) | ||
210 | { | ||
211 | return get_ancestor_data(session)->nntp_session; | ||
212 | } | ||
213 | |||
214 | static int nntpdriver_cached_initialize(mailsession * session) | ||
215 | { | ||
216 | struct nntp_cached_session_state_data * data; | ||
217 | |||
218 | data = malloc(sizeof(* data)); | ||
219 | if (data == NULL) | ||
220 | goto err; | ||
221 | |||
222 | data->nntp_flags_store = mail_flags_store_new(); | ||
223 | if (data->nntp_flags_store == NULL) | ||
224 | goto free; | ||
225 | |||
226 | data->nntp_ancestor = mailsession_new(nntp_session_driver); | ||
227 | if (data->nntp_ancestor == NULL) | ||
228 | goto free_store; | ||
229 | |||
230 | session->sess_data = data; | ||
231 | |||
232 | return MAIL_NO_ERROR; | ||
233 | |||
234 | free_store: | ||
235 | mail_flags_store_free(data->nntp_flags_store); | ||
236 | free: | ||
237 | free(data); | ||
238 | err: | ||
239 | return MAIL_ERROR_MEMORY; | ||
240 | } | ||
241 | |||
242 | static int nntp_flags_store_process(char * flags_directory, char * group_name, | ||
243 | struct mail_flags_store * flags_store) | ||
244 | { | ||
245 | char filename_flags[PATH_MAX]; | ||
246 | struct mail_cache_db * cache_db_flags; | ||
247 | MMAPString * mmapstr; | ||
248 | unsigned int i; | ||
249 | int r; | ||
250 | int res; | ||
251 | |||
252 | if (carray_count(flags_store->fls_tab) == 0) | ||
253 | return MAIL_NO_ERROR; | ||
254 | |||
255 | if (group_name == NULL) | ||
256 | return MAIL_NO_ERROR; | ||
257 | |||
258 | snprintf(filename_flags, PATH_MAX, "%s/%s/%s", | ||
259 | flags_directory, group_name, FLAGS_NAME); | ||
260 | |||
261 | r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); | ||
262 | if (r < 0) { | ||
263 | res = MAIL_ERROR_FILE; | ||
264 | goto err; | ||
265 | } | ||
266 | |||
267 | mmapstr = mmap_string_new(""); | ||
268 | if (mmapstr == NULL) { | ||
269 | res = MAIL_ERROR_MEMORY; | ||
270 | goto close_db_flags; | ||
271 | } | ||
272 | |||
273 | for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { | ||
274 | mailmessage * msg; | ||
275 | |||
276 | msg = carray_get(flags_store->fls_tab, i); | ||
277 | |||
278 | r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr, | ||
279 | msg->msg_index, msg->msg_flags); | ||
280 | } | ||
281 | |||
282 | mmap_string_free(mmapstr); | ||
283 | mail_cache_db_close_unlock(filename_flags, cache_db_flags); | ||
284 | |||
285 | mail_flags_store_clear(flags_store); | ||
286 | |||
287 | return MAIL_NO_ERROR; | ||
288 | |||
289 | close_db_flags: | ||
290 | mail_cache_db_close_unlock(filename_flags, cache_db_flags); | ||
291 | err: | ||
292 | return res; | ||
293 | } | ||
294 | |||
295 | static void nntpdriver_cached_uninitialize(mailsession * session) | ||
296 | { | ||
297 | struct nntp_cached_session_state_data * cached_data; | ||
298 | struct nntp_session_state_data * ancestor_data; | ||
299 | |||
300 | cached_data = get_cached_data(session); | ||
301 | ancestor_data = get_ancestor_data(session); | ||
302 | |||
303 | nntp_flags_store_process(cached_data->nntp_flags_directory, | ||
304 | ancestor_data->nntp_group_name, | ||
305 | cached_data->nntp_flags_store); | ||
306 | |||
307 | mail_flags_store_free(cached_data->nntp_flags_store); | ||
308 | |||
309 | mailsession_free(cached_data->nntp_ancestor); | ||
310 | free(cached_data); | ||
311 | |||
312 | session->sess_data = NULL; | ||
313 | } | ||
314 | |||
315 | static int nntpdriver_cached_parameters(mailsession * session, | ||
316 | int id, void * value) | ||
317 | { | ||
318 | struct nntp_cached_session_state_data * cached_data; | ||
319 | int r; | ||
320 | |||
321 | cached_data = get_cached_data(session); | ||
322 | |||
323 | switch (id) { | ||
324 | case NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY: | ||
325 | strncpy(cached_data->nntp_cache_directory, value, PATH_MAX); | ||
326 | cached_data->nntp_cache_directory[PATH_MAX - 1] = '\0'; | ||
327 | |||
328 | r = generic_cache_create_dir(cached_data->nntp_cache_directory); | ||
329 | if (r != MAIL_NO_ERROR) | ||
330 | return r; | ||
331 | |||
332 | return MAIL_NO_ERROR; | ||
333 | |||
334 | case NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY: | ||
335 | strncpy(cached_data->nntp_flags_directory, value, PATH_MAX); | ||
336 | cached_data->nntp_flags_directory[PATH_MAX - 1] = '\0'; | ||
337 | |||
338 | r = generic_cache_create_dir(cached_data->nntp_flags_directory); | ||
339 | if (r != MAIL_NO_ERROR) | ||
340 | return r; | ||
341 | |||
342 | return MAIL_NO_ERROR; | ||
343 | |||
344 | default: | ||
345 | return mailsession_parameters(get_ancestor(session), id, value); | ||
346 | } | ||
347 | } | ||
348 | |||
349 | static int nntpdriver_cached_connect_stream(mailsession * session, | ||
350 | mailstream * s) | ||
351 | { | ||
352 | return mailsession_connect_stream(get_ancestor(session), s); | ||
353 | } | ||
354 | |||
355 | static int nntpdriver_cached_login(mailsession * session, | ||
356 | char * userid, char * password) | ||
357 | { | ||
358 | return mailsession_login(get_ancestor(session), userid, password); | ||
359 | } | ||
360 | |||
361 | static int nntpdriver_cached_logout(mailsession * session) | ||
362 | { | ||
363 | struct nntp_cached_session_state_data * cached_data; | ||
364 | struct nntp_session_state_data * ancestor_data; | ||
365 | |||
366 | cached_data = get_cached_data(session); | ||
367 | ancestor_data = get_ancestor_data(session); | ||
368 | |||
369 | nntp_flags_store_process(cached_data->nntp_flags_directory, | ||
370 | ancestor_data->nntp_group_name, | ||
371 | cached_data->nntp_flags_store); | ||
372 | |||
373 | return mailsession_logout(get_ancestor(session)); | ||
374 | } | ||
375 | |||
376 | static int nntpdriver_cached_select_folder(mailsession * session, char * mb) | ||
377 | { | ||
378 | int r; | ||
379 | struct nntp_session_state_data * ancestor_data; | ||
380 | struct nntp_cached_session_state_data * cached_data; | ||
381 | int res; | ||
382 | char key[PATH_MAX]; | ||
383 | |||
384 | cached_data = get_cached_data(session); | ||
385 | ancestor_data = get_ancestor_data(session); | ||
386 | |||
387 | nntp_flags_store_process(cached_data->nntp_flags_directory, | ||
388 | ancestor_data->nntp_group_name, | ||
389 | cached_data->nntp_flags_store); | ||
390 | |||
391 | r = mailsession_select_folder(get_ancestor(session), mb); | ||
392 | if (r != MAIL_NO_ERROR) | ||
393 | return r; | ||
394 | |||
395 | if (ancestor_data->nntp_group_name == NULL) | ||
396 | return MAIL_ERROR_BAD_STATE; | ||
397 | |||
398 | snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_cache_directory, | ||
399 | ancestor_data->nntp_group_name); | ||
400 | |||
401 | r = generic_cache_create_dir(key); | ||
402 | if (r != MAIL_NO_ERROR) { | ||
403 | res = r; | ||
404 | goto err; | ||
405 | } | ||
406 | |||
407 | snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_flags_directory, | ||
408 | ancestor_data->nntp_group_name); | ||
409 | |||
410 | r = generic_cache_create_dir(key); | ||
411 | if (r != MAIL_NO_ERROR) { | ||
412 | res = r; | ||
413 | goto err; | ||
414 | } | ||
415 | |||
416 | return MAIL_NO_ERROR; | ||
417 | |||
418 | err: | ||
419 | return res; | ||
420 | } | ||
421 | |||
422 | static int nntpdriver_cached_check_folder(mailsession * session) | ||
423 | { | ||
424 | struct nntp_session_state_data * ancestor_data; | ||
425 | struct nntp_cached_session_state_data * cached_data; | ||
426 | |||
427 | cached_data = get_cached_data(session); | ||
428 | ancestor_data = get_ancestor_data(session); | ||
429 | |||
430 | nntp_flags_store_process(cached_data->nntp_flags_directory, | ||
431 | ancestor_data->nntp_group_name, | ||
432 | cached_data->nntp_flags_store); | ||
433 | |||
434 | return MAIL_NO_ERROR; | ||
435 | } | ||
436 | |||
437 | |||
438 | static int nntpdriver_cached_status_folder(mailsession * session, | ||
439 | char * mb, uint32_t * result_messages, uint32_t * result_recent, | ||
440 | uint32_t * result_unseen) | ||
441 | { | ||
442 | int res; | ||
443 | struct nntp_cached_session_state_data * cached_data; | ||
444 | struct nntp_session_state_data * ancestor_data; | ||
445 | char filename_flags[PATH_MAX]; | ||
446 | struct mail_cache_db * cache_db_flags; | ||
447 | MMAPString * mmapstr; | ||
448 | uint32_t i; | ||
449 | int r; | ||
450 | uint32_t recent; | ||
451 | uint32_t unseen; | ||
452 | uint32_t first; | ||
453 | uint32_t last; | ||
454 | uint32_t count; | ||
455 | uint32_t additionnal; | ||
456 | |||
457 | r = nntpdriver_cached_select_folder(session, mb); | ||
458 | if (r != MAIL_NO_ERROR) { | ||
459 | res = r; | ||
460 | goto err; | ||
461 | } | ||
462 | |||
463 | read_article_seq(session, &first, &last); | ||
464 | |||
465 | count = 0; | ||
466 | recent = 0; | ||
467 | unseen = 0; | ||
468 | |||
469 | ancestor_data = get_ancestor_data(session); | ||
470 | cached_data = get_cached_data(session); | ||
471 | if (ancestor_data->nntp_group_name == NULL) { | ||
472 | res = MAIL_ERROR_BAD_STATE; | ||
473 | goto err; | ||
474 | } | ||
475 | |||
476 | if (ancestor_data->nntp_group_info->grp_first > first) | ||
477 | first = ancestor_data->nntp_group_info->grp_first; | ||
478 | if (last < first) | ||
479 | last = ancestor_data->nntp_group_info->grp_last; | ||
480 | |||
481 | snprintf(filename_flags, PATH_MAX, "%s/%s/%s", | ||
482 | cached_data->nntp_flags_directory, | ||
483 | ancestor_data->nntp_group_name, FLAGS_NAME); | ||
484 | |||
485 | r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); | ||
486 | if (r < 0) { | ||
487 | res = MAIL_ERROR_MEMORY; | ||
488 | goto err; | ||
489 | } | ||
490 | |||
491 | mmapstr = mmap_string_new(""); | ||
492 | if (mmapstr == NULL) { | ||
493 | res = MAIL_ERROR_MEMORY; | ||
494 | goto close_db_flags; | ||
495 | } | ||
496 | |||
497 | for(i = first ; i <= last ; i++) { | ||
498 | struct mail_flags * flags; | ||
499 | |||
500 | r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr, | ||
501 | i, &flags); | ||
502 | if (r == MAIL_NO_ERROR) { | ||
503 | if ((flags->fl_flags & MAIL_FLAG_CANCELLED) != 0) { | ||
504 | continue; | ||
505 | } | ||
506 | |||
507 | count ++; | ||
508 | if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { | ||
509 | recent ++; | ||
510 | } | ||
511 | if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { | ||
512 | unseen ++; | ||
513 | } | ||
514 | mail_flags_free(flags); | ||
515 | } | ||
516 | } | ||
517 | |||
518 | if ((count == 0) && (first != last)) { | ||
519 | count = last - first + 1; | ||
520 | recent = count; | ||
521 | unseen = count; | ||
522 | } | ||
523 | |||
524 | additionnal = ancestor_data->nntp_group_info->grp_last - last; | ||
525 | recent += additionnal; | ||
526 | unseen += additionnal; | ||
527 | |||
528 | mmap_string_free(mmapstr); | ||
529 | mail_cache_db_close_unlock(filename_flags, cache_db_flags); | ||
530 | |||
531 | * result_messages = count; | ||
532 | * result_recent = recent; | ||
533 | * result_unseen = unseen; | ||
534 | |||
535 | return MAIL_NO_ERROR; | ||
536 | |||
537 | close_db_flags: | ||
538 | mail_cache_db_close_unlock(filename_flags, cache_db_flags); | ||
539 | err: | ||
540 | return res; | ||
541 | } | ||
542 | |||
543 | static int nntpdriver_cached_messages_number(mailsession * session, | ||
544 | char * mb, | ||
545 | uint32_t * result) | ||
546 | { | ||
547 | uint32_t messages; | ||
548 | uint32_t recent; | ||
549 | uint32_t unseen; | ||
550 | int r; | ||
551 | |||
552 | r = nntpdriver_cached_status_folder(session, mb, | ||
553 | &messages, &recent, &unseen); | ||
554 | if (r != MAIL_NO_ERROR) | ||
555 | return r; | ||
556 | |||
557 | * result = messages; | ||
558 | |||
559 | return MAIL_NO_ERROR; | ||
560 | } | ||
561 | |||
562 | static int nntpdriver_cached_recent_number(mailsession * session, | ||
563 | char * mb, | ||
564 | uint32_t * result) | ||
565 | { | ||
566 | uint32_t messages; | ||
567 | uint32_t recent; | ||
568 | uint32_t unseen; | ||
569 | int r; | ||
570 | |||
571 | r = nntpdriver_cached_status_folder(session, mb, | ||
572 | &messages, &recent, &unseen); | ||
573 | if (r != MAIL_NO_ERROR) | ||
574 | return r; | ||
575 | |||
576 | * result = recent; | ||
577 | |||
578 | return MAIL_NO_ERROR; | ||
579 | } | ||
580 | |||
581 | static int nntpdriver_cached_unseen_number(mailsession * session, | ||
582 | char * mb, | ||
583 | uint32_t * result) | ||
584 | { | ||
585 | uint32_t messages; | ||
586 | uint32_t recent; | ||
587 | uint32_t unseen; | ||
588 | int r; | ||
589 | |||
590 | r = nntpdriver_cached_status_folder(session, mb, | ||
591 | &messages, &recent, &unseen); | ||
592 | if (r != MAIL_NO_ERROR) | ||
593 | return r; | ||
594 | |||
595 | * result = unseen; | ||
596 | |||
597 | return MAIL_NO_ERROR; | ||
598 | } | ||
599 | |||
600 | static int nntpdriver_cached_list_folders(mailsession * session, char * mb, | ||
601 | struct mail_list ** result) | ||
602 | { | ||
603 | return mailsession_list_folders(get_ancestor(session), mb, result); | ||
604 | } | ||
605 | |||
606 | static int nntpdriver_cached_lsub_folders(mailsession * session, char * mb, | ||
607 | struct mail_list ** result) | ||
608 | { | ||
609 | return mailsession_lsub_folders(get_ancestor(session), mb, result); | ||
610 | } | ||
611 | |||
612 | static int nntpdriver_cached_subscribe_folder(mailsession * session, | ||
613 | char * mb) | ||
614 | { | ||
615 | return mailsession_subscribe_folder(get_ancestor(session), mb); | ||
616 | } | ||
617 | |||
618 | static int nntpdriver_cached_unsubscribe_folder(mailsession * session, | ||
619 | char * mb) | ||
620 | { | ||
621 | return mailsession_unsubscribe_folder(get_ancestor(session), mb); | ||
622 | } | ||
623 | |||
624 | |||
625 | |||
626 | /* messages operations */ | ||
627 | |||
628 | static int nntpdriver_cached_append_message(mailsession * session, | ||
629 | char * message, size_t size) | ||
630 | { | ||
631 | return mailsession_append_message(get_ancestor(session), message, size); | ||
632 | } | ||
633 | |||
634 | |||
635 | |||
636 | static int | ||
637 | get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, | ||
638 | mailsession * session, uint32_t num, | ||
639 | struct mailimf_fields ** result) | ||
640 | { | ||
641 | char keyname[PATH_MAX]; | ||
642 | int r; | ||
643 | struct mailimf_fields * fields; | ||
644 | int res; | ||
645 | |||
646 | snprintf(keyname, PATH_MAX, "%i-envelope", num); | ||
647 | |||
648 | r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); | ||
649 | if (r != MAIL_NO_ERROR) { | ||
650 | res = r; | ||
651 | goto err; | ||
652 | } | ||
653 | |||
654 | * result = fields; | ||
655 | |||
656 | return MAIL_NO_ERROR; | ||
657 | |||
658 | err: | ||
659 | return res; | ||
660 | } | ||
661 | |||
662 | static int | ||
663 | write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, | ||
664 | mailsession * session, uint32_t num, | ||
665 | struct mailimf_fields * fields) | ||
666 | { | ||
667 | int r; | ||
668 | int res; | ||
669 | char keyname[PATH_MAX]; | ||
670 | |||
671 | snprintf(keyname, PATH_MAX, "%i-envelope", num); | ||
672 | |||
673 | r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); | ||
674 | if (r != MAIL_NO_ERROR) { | ||
675 | res = r; | ||
676 | goto err; | ||
677 | } | ||
678 | |||
679 | return MAIL_NO_ERROR; | ||
680 | |||
681 | err: | ||
682 | return res; | ||
683 | } | ||
684 | |||
685 | #define SEQ_FILENAME "articles-seq" | ||
686 | |||
687 | static void read_article_seq(mailsession * session, | ||
688 | uint32_t * pfirst, uint32_t * plast) | ||
689 | { | ||
690 | FILE * f; | ||
691 | struct nntp_session_state_data * ancestor_data; | ||
692 | uint32_t first; | ||
693 | uint32_t last; | ||
694 | char seq_filename[PATH_MAX]; | ||
695 | struct nntp_cached_session_state_data * cached_data; | ||
696 | int r; | ||
697 | |||
698 | first = 0; | ||
699 | last = 0; | ||
700 | |||
701 | cached_data = get_cached_data(session); | ||
702 | ancestor_data = get_ancestor_data(session); | ||
703 | |||
704 | if (ancestor_data->nntp_group_name == NULL) | ||
705 | return; | ||
706 | |||
707 | snprintf(seq_filename, PATH_MAX, "%s/%s/%s", | ||
708 | cached_data->nntp_cache_directory, | ||
709 | ancestor_data->nntp_group_name, SEQ_FILENAME); | ||
710 | f = fopen(seq_filename, "r"); | ||
711 | |||
712 | if (f != NULL) { | ||
713 | int fd; | ||
714 | |||
715 | fd = fileno(f); | ||
716 | |||
717 | r = maillock_read_lock(seq_filename, fd); | ||
718 | if (r == 0) { | ||
719 | MMAPString * mmapstr; | ||
720 | size_t cur_token; | ||
721 | char buf[sizeof(uint32_t) * 2]; | ||
722 | size_t read_size; | ||
723 | |||
724 | read_size = fread(buf, 1, sizeof(uint32_t) * 2, f); | ||
725 | mmapstr = mmap_string_new_len(buf, read_size); | ||
726 | if (mmapstr != NULL) { | ||
727 | cur_token = 0; | ||
728 | r = mailimf_cache_int_read(mmapstr, &cur_token, &first); | ||
729 | r = mailimf_cache_int_read(mmapstr, &cur_token, &last); | ||
730 | |||
731 | mmap_string_free(mmapstr); | ||
732 | } | ||
733 | |||
734 | maillock_read_unlock(seq_filename, fd); | ||
735 | } | ||
736 | fclose(f); | ||
737 | } | ||
738 | |||
739 | * pfirst = first; | ||
740 | * plast = last; | ||
741 | } | ||
742 | |||
743 | static void write_article_seq(mailsession * session, | ||
744 | uint32_t first, uint32_t last) | ||
745 | { | ||
746 | FILE * f; | ||
747 | struct nntp_session_state_data * ancestor_data; | ||
748 | char seq_filename[PATH_MAX]; | ||
749 | struct nntp_cached_session_state_data * cached_data; | ||
750 | int r; | ||
751 | int fd; | ||
752 | |||
753 | cached_data = get_cached_data(session); | ||
754 | ancestor_data = get_ancestor_data(session); | ||
755 | |||
756 | if (ancestor_data->nntp_group_name == NULL) | ||
757 | return; | ||
758 | |||
759 | snprintf(seq_filename, PATH_MAX, "%s/%s/%s", | ||
760 | cached_data->nntp_cache_directory, | ||
761 | ancestor_data->nntp_group_name, SEQ_FILENAME); | ||
762 | |||
763 | fd = creat(seq_filename, S_IRUSR | S_IWUSR); | ||
764 | if (fd < 0) | ||
765 | return; | ||
766 | |||
767 | f = fdopen(fd, "w"); | ||
768 | if (f != NULL) { | ||
769 | r = maillock_write_lock(seq_filename, fd); | ||
770 | if (r == 0) { | ||
771 | MMAPString * mmapstr; | ||
772 | size_t cur_token; | ||
773 | |||
774 | mmapstr = mmap_string_new(""); | ||
775 | if (mmapstr != NULL) { | ||
776 | r = mail_serialize_clear(mmapstr, &cur_token); | ||
777 | if (r == MAIL_NO_ERROR) { | ||
778 | r = mailimf_cache_int_write(mmapstr, &cur_token, first); | ||
779 | r = mailimf_cache_int_write(mmapstr, &cur_token, last); | ||
780 | |||
781 | fwrite(mmapstr->str, 1, mmapstr->len, f); | ||
782 | } | ||
783 | |||
784 | mmap_string_free(mmapstr); | ||
785 | } | ||
786 | |||
787 | maillock_write_unlock(seq_filename, fd); | ||
788 | } | ||
789 | fclose(f); | ||
790 | } | ||
791 | else | ||
792 | close(fd); | ||
793 | } | ||
794 | |||
795 | |||
796 | static void get_uid_from_filename(char * filename) | ||
797 | { | ||
798 | char * p; | ||
799 | |||
800 | if (strcmp(filename, SEQ_FILENAME) == 0) | ||
801 | * filename = 0; | ||
802 | |||
803 | p = strstr(filename, "-header"); | ||
804 | if (p != NULL) | ||
805 | * p = 0; | ||
806 | } | ||
807 | |||
808 | static int | ||
809 | nntpdriver_cached_get_envelopes_list(mailsession * session, | ||
810 | struct mailmessage_list * env_list) | ||
811 | { | ||
812 | int r; | ||
813 | unsigned int i; | ||
814 | struct nntp_cached_session_state_data * cached_data; | ||
815 | uint32_t first; | ||
816 | uint32_t last; | ||
817 | struct nntp_session_state_data * ancestor_data; | ||
818 | char filename_env[PATH_MAX]; | ||
819 | char filename_flags[PATH_MAX]; | ||
820 | struct mail_cache_db * cache_db_env; | ||
821 | struct mail_cache_db * cache_db_flags; | ||
822 | MMAPString * mmapstr; | ||
823 | int res; | ||
824 | char cache_dir[PATH_MAX]; | ||
825 | |||
826 | cached_data = get_cached_data(session); | ||
827 | ancestor_data = get_ancestor_data(session); | ||
828 | |||
829 | nntp_flags_store_process(cached_data->nntp_flags_directory, | ||
830 | ancestor_data->nntp_group_name, | ||
831 | cached_data->nntp_flags_store); | ||
832 | |||
833 | if (ancestor_data->nntp_group_name == NULL) { | ||
834 | res = MAIL_ERROR_BAD_STATE; | ||
835 | goto err; | ||
836 | } | ||
837 | |||
838 | /* read articles sequence */ | ||
839 | |||
840 | read_article_seq(session, &first, &last); | ||
841 | |||
842 | mmapstr = mmap_string_new(""); | ||
843 | if (mmapstr == NULL) { | ||
844 | res = MAIL_ERROR_MEMORY; | ||
845 | goto err; | ||
846 | } | ||
847 | |||
848 | snprintf(filename_env, PATH_MAX, "%s/%s/%s", | ||
849 | cached_data->nntp_cache_directory, | ||
850 | ancestor_data->nntp_group_name, ENV_NAME); | ||
851 | |||
852 | r = mail_cache_db_open_lock(filename_env, &cache_db_env); | ||
853 | if (r < 0) { | ||
854 | res = MAIL_ERROR_MEMORY; | ||
855 | goto free_mmapstr; | ||
856 | } | ||
857 | |||
858 | snprintf(filename_flags, PATH_MAX, "%s/%s/%s", | ||
859 | cached_data->nntp_flags_directory, | ||
860 | ancestor_data->nntp_group_name, FLAGS_NAME); | ||
861 | |||
862 | /* fill with cached */ | ||
863 | |||
864 | for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { | ||
865 | mailmessage * msg; | ||
866 | struct mailimf_fields * fields; | ||
867 | |||
868 | msg = carray_get(env_list->msg_tab, i); | ||
869 | |||
870 | if ((msg->msg_index < first) || (msg->msg_index > last)) | ||
871 | continue; | ||
872 | |||
873 | if (msg->msg_fields == NULL) { | ||
874 | r = get_cached_envelope(cache_db_env, mmapstr, | ||
875 | session, msg->msg_index, &fields); | ||
876 | if (r == MAIL_NO_ERROR) { | ||
877 | msg->msg_fields = fields; | ||
878 | msg->msg_cached = TRUE; | ||
879 | } | ||
880 | } | ||
881 | } | ||
882 | |||
883 | mail_cache_db_close_unlock(filename_env, cache_db_env); | ||
884 | |||
885 | r = mailsession_get_envelopes_list(get_ancestor(session), env_list); | ||
886 | |||
887 | if (r != MAIL_NO_ERROR) { | ||
888 | res = r; | ||
889 | goto free_mmapstr; | ||
890 | } | ||
891 | |||
892 | r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); | ||
893 | if (r < 0) { | ||
894 | res = MAIL_ERROR_MEMORY; | ||
895 | goto free_mmapstr; | ||
896 | } | ||
897 | |||
898 | /* add flags */ | ||
899 | |||
900 | for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { | ||
901 | mailmessage * msg; | ||
902 | |||
903 | msg = carray_get(env_list->msg_tab, i); | ||
904 | |||
905 | if (msg->msg_flags == NULL) { | ||
906 | struct mail_flags * flags; | ||
907 | |||
908 | r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr, | ||
909 | msg->msg_index, &flags); | ||
910 | if (r == MAIL_NO_ERROR) { | ||
911 | msg->msg_flags = flags; | ||
912 | } | ||
913 | else { | ||
914 | msg->msg_flags = mail_flags_new_empty(); | ||
915 | if (msg->msg_fields == NULL) { | ||
916 | msg->msg_flags->fl_flags |= MAIL_FLAG_CANCELLED; | ||
917 | mailmessage_check(msg); | ||
918 | } | ||
919 | } | ||
920 | } | ||
921 | } | ||
922 | |||
923 | mail_cache_db_close_unlock(filename_flags, cache_db_flags); | ||
924 | |||
925 | r = mail_cache_db_open_lock(filename_env, &cache_db_env); | ||
926 | if (r < 0) { | ||
927 | res = MAIL_ERROR_MEMORY; | ||
928 | goto free_mmapstr; | ||
929 | } | ||
930 | |||
931 | r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); | ||
932 | if (r < 0) { | ||
933 | res = MAIL_ERROR_MEMORY; | ||
934 | goto close_db_env; | ||
935 | } | ||
936 | |||
937 | /* must write cache */ | ||
938 | |||
939 | for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { | ||
940 | mailmessage * msg; | ||
941 | |||
942 | msg = carray_get(env_list->msg_tab, i); | ||
943 | |||
944 | if (msg->msg_fields != NULL) { | ||
945 | if (!msg->msg_cached) { | ||
946 | r = write_cached_envelope(cache_db_env, mmapstr, | ||
947 | session, msg->msg_index, msg->msg_fields); | ||
948 | } | ||
949 | } | ||
950 | |||
951 | if (msg->msg_flags != NULL) { | ||
952 | r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr, | ||
953 | msg->msg_index, msg->msg_flags); | ||
954 | } | ||
955 | } | ||
956 | |||
957 | first = 0; | ||
958 | last = 0; | ||
959 | if (carray_count(env_list->msg_tab) > 0) { | ||
960 | mailmessage * msg; | ||
961 | |||
962 | msg = carray_get(env_list->msg_tab, 0); | ||
963 | first = msg->msg_index; | ||
964 | |||
965 | msg = carray_get(env_list->msg_tab, carray_count(env_list->msg_tab) - 1); | ||
966 | last = msg->msg_index; | ||
967 | } | ||
968 | |||
969 | /* write articles sequence */ | ||
970 | |||
971 | write_article_seq(session, first, last); | ||
972 | |||
973 | /* flush cache */ | ||
974 | |||
975 | maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); | ||
976 | |||
977 | /* remove cache files */ | ||
978 | |||
979 | snprintf(cache_dir, PATH_MAX, "%s/%s", | ||
980 | cached_data->nntp_cache_directory, ancestor_data->nntp_group_name); | ||
981 | |||
982 | mail_cache_db_close_unlock(filename_flags, cache_db_flags); | ||
983 | mail_cache_db_close_unlock(filename_env, cache_db_env); | ||
984 | mmap_string_free(mmapstr); | ||
985 | |||
986 | maildriver_message_cache_clean_up(cache_dir, env_list, | ||
987 | get_uid_from_filename); | ||
988 | |||
989 | return MAIL_NO_ERROR; | ||
990 | |||
991 | close_db_env: | ||
992 | mail_cache_db_close_unlock(filename_env, cache_db_env); | ||
993 | free_mmapstr: | ||
994 | mmap_string_free(mmapstr); | ||
995 | err: | ||
996 | return res; | ||
997 | } | ||
998 | |||
999 | static int | ||
1000 | nntpdriver_cached_get_messages_list(mailsession * session, | ||
1001 | struct mailmessage_list ** result) | ||
1002 | { | ||
1003 | return nntp_get_messages_list(get_ancestor(session), session, | ||
1004 | nntp_cached_message_driver, result); | ||
1005 | } | ||
1006 | |||
1007 | static int nntpdriver_cached_get_message(mailsession * session, | ||
1008 | uint32_t num, mailmessage ** result) | ||
1009 | { | ||
1010 | mailmessage * msg_info; | ||
1011 | int r; | ||
1012 | |||
1013 | msg_info = mailmessage_new(); | ||
1014 | if (msg_info == NULL) | ||
1015 | return MAIL_ERROR_MEMORY; | ||
1016 | |||
1017 | r = mailmessage_init(msg_info, session, nntp_cached_message_driver, num, 0); | ||
1018 | if (r != MAIL_NO_ERROR) { | ||
1019 | mailmessage_free(msg_info); | ||
1020 | return r; | ||
1021 | } | ||
1022 | |||
1023 | * result = msg_info; | ||
1024 | |||
1025 | return MAIL_NO_ERROR; | ||
1026 | } | ||
1027 | |||
1028 | static int nntpdriver_cached_noop(mailsession * session) | ||
1029 | { | ||
1030 | return mailsession_noop(get_ancestor(session)); | ||
1031 | } | ||
1032 | |||
1033 | static int nntpdriver_cached_get_message_by_uid(mailsession * session, | ||
1034 | const char * uid, | ||
1035 | mailmessage ** result) | ||
1036 | { | ||
1037 | uint32_t num; | ||
1038 | char * p; | ||
1039 | |||
1040 | if (uid == NULL) | ||
1041 | return MAIL_ERROR_INVAL; | ||
1042 | |||
1043 | num = strtoul(uid, &p, 10); | ||
1044 | if ((p == uid) || (* p != '\0')) | ||
1045 | return MAIL_ERROR_INVAL; | ||
1046 | |||
1047 | return nntpdriver_cached_get_message(session, num, result); | ||
1048 | } | ||