summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/implementation/mh/mhdriver_tools.c
Unidiff
Diffstat (limited to 'libetpan/src/driver/implementation/mh/mhdriver_tools.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/implementation/mh/mhdriver_tools.c484
1 files changed, 484 insertions, 0 deletions
diff --git a/libetpan/src/driver/implementation/mh/mhdriver_tools.c b/libetpan/src/driver/implementation/mh/mhdriver_tools.c
new file mode 100644
index 0000000..b8bcf03
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mh/mhdriver_tools.c
@@ -0,0 +1,484 @@
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 "mhdriver_tools.h"
37
38#include "mailmessage.h"
39#include "mhdriver.h"
40#include "mhdriver_cached.h"
41#include "maildriver_types.h"
42#include "mailmh.h"
43#include "generic_cache.h"
44#include "imfcache.h"
45#include "mail_cache_db.h"
46
47#include <unistd.h>
48#include <sys/mman.h>
49#include <sys/types.h>
50#include <sys/stat.h>
51#include <fcntl.h>
52#include <string.h>
53#include <stdlib.h>
54
55int mhdriver_mh_error_to_mail_error(int error)
56{
57 switch (error) {
58 case MAILMH_NO_ERROR:
59 return MAIL_NO_ERROR;
60
61 case MAILMH_ERROR_FOLDER:
62 return MAIL_ERROR_FOLDER;
63
64 case MAILMH_ERROR_MEMORY:
65 return MAIL_ERROR_MEMORY;
66
67 case MAILMH_ERROR_FILE:
68 return MAIL_ERROR_FILE;
69
70 case MAILMH_ERROR_COULD_NOT_ALLOC_MSG:
71 return MAIL_ERROR_APPEND;
72
73 case MAILMH_ERROR_RENAME:
74 return MAIL_ERROR_RENAME;
75
76 case MAILMH_ERROR_MSG_NOT_FOUND:
77 return MAIL_ERROR_MSG_NOT_FOUND;
78
79 default:
80 return MAIL_ERROR_INVAL;
81 }
82}
83
84
85static inline struct mh_session_state_data * get_data(mailsession * session)
86{
87 return session->sess_data;
88}
89
90static inline struct mailmh_folder * get_mh_cur_folder(mailsession * session)
91{
92 return get_data(session)->mh_cur_folder;
93}
94
95static inline struct mh_cached_session_state_data *
96cached_get_data(mailsession * session)
97{
98 return session->sess_data;
99}
100
101
102static inline mailsession * cached_get_ancestor(mailsession * session)
103{
104 return cached_get_data(session)->mh_ancestor;
105}
106
107static inline struct mh_session_state_data *
108cached_get_ancestor_data(mailsession * session)
109{
110 return get_data(cached_get_ancestor(session));
111}
112
113static inline struct mailmh_folder *
114cached_get_mh_cur_folder(mailsession * session)
115{
116 return get_mh_cur_folder(cached_get_ancestor(session));
117}
118
119int mhdriver_fetch_message(mailsession * session, uint32_t index,
120 char ** result, size_t * result_len)
121{
122 size_t size;
123 size_t cur_token;
124 struct mailmh_folder * folder;
125 int fd;
126 MMAPString * mmapstr;
127 char * str;
128 int res;
129 int r;
130
131 folder = get_mh_cur_folder(session);
132 if (folder == NULL) {
133 res = MAIL_ERROR_BAD_STATE;
134 goto err;
135 }
136
137 r = mailmh_folder_get_message_fd(folder, index, O_RDONLY, &fd);
138
139 switch (r) {
140 case MAILMH_NO_ERROR:
141 break;
142
143 default:
144 res = mhdriver_mh_error_to_mail_error(r);
145 goto close;
146 }
147
148 r = mhdriver_fetch_size(session, index, &size);
149
150 switch (r) {
151 case MAILMH_NO_ERROR:
152 break;
153
154 default:
155 res = mhdriver_mh_error_to_mail_error(r);
156 goto close;
157 }
158
159 str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
160 if (str == MAP_FAILED) {
161 res = MAIL_ERROR_FETCH;
162 goto close;
163 }
164
165 /* strip "From " header for broken implementations */
166 /* XXX - called twice, make a function */
167 cur_token = 0;
168 if (strncmp("From ", str, 5) == 0) {
169 cur_token += 5;
170
171 while (1) {
172 if (str[cur_token] == '\n') {
173 cur_token ++;
174 break;
175 }
176 if (cur_token >= size)
177 break;
178 cur_token ++;
179 }
180 }
181
182 mmapstr = mmap_string_new_len(str + cur_token, size - cur_token);
183 if (mmapstr == NULL) {
184 res = MAIL_ERROR_MEMORY;
185 goto unmap;
186 }
187
188 if (mmap_string_ref(mmapstr) != 0) {
189 res = MAIL_ERROR_MEMORY;
190 goto free_str;
191 }
192
193 munmap(str, size);
194 close(fd);
195
196 * result = mmapstr->str;
197 * result_len = mmapstr->len;
198
199 return MAIL_NO_ERROR;
200
201 free_str:
202 mmap_string_free(mmapstr);
203 unmap:
204 munmap(str, size);
205 close:
206 close(fd);
207 err:
208 return res;
209}
210
211
212int mhdriver_fetch_header(mailsession * session, uint32_t index,
213 char ** result, size_t * result_len)
214{
215 size_t size;
216 size_t cur_token;
217 size_t begin;
218 struct mailmh_folder * folder;
219 int fd;
220 MMAPString * mmapstr;
221 char * str;
222 int res;
223 int r;
224
225 folder = get_mh_cur_folder(session);
226 if (folder == NULL) {
227 res = MAIL_ERROR_BAD_STATE;
228 goto err;
229 }
230
231 r = mailmh_folder_get_message_fd(folder, index, O_RDONLY, &fd);
232
233 switch (r) {
234 case MAILMH_NO_ERROR:
235 break;
236
237 default:
238 res = mhdriver_mh_error_to_mail_error(r);
239 goto close;
240 }
241
242 r = mhdriver_fetch_size(session, index, &size);
243
244 switch (r) {
245 case MAILMH_NO_ERROR:
246 break;
247
248 default:
249 res = mhdriver_mh_error_to_mail_error(r);
250 goto close;
251 }
252
253 str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
254 if (str == MAP_FAILED) {
255 res = MAIL_ERROR_FETCH;
256 goto close;
257 }
258
259 /* strip "From " header for broken implementations */
260 cur_token = 0;
261 if (size > 5) {
262 if (strncmp("From ", str, 5) == 0) {
263 cur_token += 5;
264
265 while (1) {
266 if (str[cur_token] == '\n') {
267 cur_token ++;
268 break;
269 }
270 if (cur_token >= size)
271 break;
272 cur_token ++;
273 }
274 }
275 }
276
277 begin = cur_token;
278
279 while (1) {
280 r = mailimf_ignore_field_parse(str, size, &cur_token);
281 if (r == MAILIMF_NO_ERROR) {
282 /* do nothing */
283 }
284 else
285 break;
286 }
287 mailimf_crlf_parse(str, size, &cur_token);
288
289 mmapstr = mmap_string_new_len(str + begin, cur_token - begin);
290 if (mmapstr == NULL) {
291 res = MAIL_ERROR_MEMORY;
292 goto unmap;
293 }
294
295 if (mmap_string_ref(mmapstr) != 0) {
296 res = MAIL_ERROR_MEMORY;
297 goto free_str;
298 }
299
300 munmap(str, size);
301 close(fd);
302
303 * result = mmapstr->str;
304 * result_len = mmapstr->len;
305
306 return MAIL_NO_ERROR;
307
308 free_str:
309 mmap_string_free(mmapstr);
310 unmap:
311 munmap(str, size);
312 close:
313 close(fd);
314 err:
315 return res;
316}
317
318
319int mhdriver_fetch_size(mailsession * session, uint32_t index,
320 size_t * result)
321{
322 struct mailmh_folder * folder;
323 int r;
324 struct stat buf;
325 char * name;
326
327 folder = get_mh_cur_folder(session);
328 if (folder == NULL)
329 return MAIL_ERROR_FETCH;
330
331 r = mailmh_folder_get_message_filename(folder, index, &name);
332
333 switch (r) {
334 case MAILMH_NO_ERROR:
335 break;
336
337 default:
338 return mhdriver_mh_error_to_mail_error(r);
339 }
340
341 r = stat(name, &buf);
342 free(name);
343 if (r == -1)
344 return MAIL_ERROR_FETCH;
345
346 * result = buf.st_size;
347
348 return MAIL_NO_ERROR;
349}
350
351int
352mhdriver_get_cached_flags(struct mail_cache_db * cache_db,
353 MMAPString * mmapstr,
354 mailsession * session,
355 uint32_t num,
356 struct mail_flags ** result)
357{
358 int r;
359 char keyname[PATH_MAX];
360 struct mail_flags * flags;
361 int res;
362 struct mailmh_msg_info * msg_info;
363 chashdatum key;
364 chashdatum data;
365 struct mailmh_folder * folder;
366
367 folder = cached_get_mh_cur_folder(session);
368#if 0
369 msg_info = cinthash_find(mh_data->cur_folder->fl_msgs_hash, num);
370 if (msg_info == NULL)
371 return MAIL_ERROR_CACHE_MISS;
372#endif
373 key.data = &num;
374 key.len = sizeof(num);
375 r = chash_get(folder->fl_msgs_hash, &key, &data);
376 if (r < 0)
377 return MAIL_ERROR_CACHE_MISS;
378 msg_info = data.data;
379
380 snprintf(keyname, PATH_MAX, "%u-%lu-%lu-flags",
381 num, (unsigned long) msg_info->msg_mtime,
382 (unsigned long) msg_info->msg_size);
383
384 r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
385 if (r != MAIL_NO_ERROR) {
386 res = r;
387 goto err;
388 }
389
390 * result = flags;
391
392 return MAIL_NO_ERROR;
393
394 err:
395 return res;
396}
397
398int
399mhdriver_write_cached_flags(struct mail_cache_db * cache_db,
400 MMAPString * mmapstr,
401 char * uid,
402 struct mail_flags * flags)
403{
404 int r;
405 char keyname[PATH_MAX];
406 int res;
407
408 snprintf(keyname, PATH_MAX, "%s-flags", uid);
409
410 r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
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
423int mh_get_messages_list(struct mailmh_folder * folder,
424 mailsession * session, mailmessage_driver * driver,
425 struct mailmessage_list ** result)
426{
427 unsigned int i;
428 struct mailmessage_list * env_list;
429 int r;
430 carray * tab;
431 int res;
432
433 tab = carray_new(128);
434 if (tab == NULL) {
435 res = MAIL_ERROR_MEMORY;
436 goto err;
437 }
438
439 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) {
440 struct mailmh_msg_info * mh_info;
441 mailmessage * msg;
442
443 mh_info = carray_get(folder->fl_msgs_tab, i);
444 if (mh_info == NULL)
445 continue;
446
447 msg = mailmessage_new();
448 if (msg == NULL) {
449 res = MAIL_ERROR_MEMORY;
450 goto free_list;
451 }
452
453 r = mailmessage_init(msg, session, driver,
454 mh_info->msg_index, mh_info->msg_size);
455 if (r != MAIL_NO_ERROR) {
456 res = r;
457 goto free_list;
458 }
459
460 r = carray_add(tab, msg, NULL);
461 if (r < 0) {
462 mailmessage_free(msg);
463 res = MAIL_ERROR_MEMORY;
464 goto free_list;
465 }
466 }
467
468 env_list = mailmessage_list_new(tab);
469 if (env_list == NULL) {
470 res = MAIL_ERROR_MEMORY;
471 goto free_list;
472 }
473
474 * result = env_list;
475
476 return MAIL_NO_ERROR;
477
478 free_list:
479 for(i = 0 ; i < carray_count(tab) ; i ++)
480 mailmessage_free(carray_get(tab, i));
481 carray_free(tab);
482 err:
483 return res;
484}