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