summaryrefslogtreecommitdiffabout
path: root/kmicromail/libetpan/generic/mhdriver_tools.c
Unidiff
Diffstat (limited to 'kmicromail/libetpan/generic/mhdriver_tools.c') (more/less context) (ignore whitespace changes)
-rw-r--r--kmicromail/libetpan/generic/mhdriver_tools.c475
1 files changed, 475 insertions, 0 deletions
diff --git a/kmicromail/libetpan/generic/mhdriver_tools.c b/kmicromail/libetpan/generic/mhdriver_tools.c
new file mode 100644
index 0000000..cb863fa
--- a/dev/null
+++ b/kmicromail/libetpan/generic/mhdriver_tools.c
@@ -0,0 +1,475 @@
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 "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_NO_ERROR;
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, size) == 0) {
169 cur_token += 5;
170
171 while (str[cur_token] != '\n') {
172 if (cur_token >= size)
173 break;
174 cur_token ++;
175 }
176 }
177
178 mmapstr = mmap_string_new_len(str + cur_token, size - cur_token);
179 if (mmapstr == NULL) {
180 res = MAIL_ERROR_MEMORY;
181 goto unmap;
182 }
183
184 if (mmap_string_ref(mmapstr) != 0) {
185 res = MAIL_ERROR_MEMORY;
186 goto free_str;
187 }
188
189 munmap(str, size);
190 close(fd);
191
192 * result = mmapstr->str;
193 * result_len = mmapstr->len;
194
195 return MAIL_NO_ERROR;
196
197 free_str:
198 mmap_string_free(mmapstr);
199 unmap:
200 munmap(str, size);
201 close:
202 close(fd);
203 err:
204 return res;
205}
206
207
208int mhdriver_fetch_header(mailsession * session, uint32_t index,
209 char ** result, size_t * result_len)
210{
211 size_t size;
212 size_t cur_token;
213 size_t begin;
214 struct mailmh_folder * folder;
215 int fd;
216 MMAPString * mmapstr;
217 char * str;
218 int res;
219 int r;
220
221 folder = get_mh_cur_folder(session);
222 if (folder == NULL) {
223 res = MAIL_ERROR_BAD_STATE;
224 goto err;
225 }
226
227 r = mailmh_folder_get_message_fd(folder, index, O_RDONLY, &fd);
228
229 switch (r) {
230 case MAILMH_NO_ERROR:
231 break;
232
233 default:
234 res = mhdriver_mh_error_to_mail_error(r);
235 goto close;
236 }
237
238 r = mhdriver_fetch_size(session, index, &size);
239
240 switch (r) {
241 case MAILMH_NO_ERROR:
242 break;
243
244 default:
245 res = mhdriver_mh_error_to_mail_error(r);
246 goto close;
247 }
248
249 str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
250 if (str == MAP_FAILED) {
251 res = MAIL_ERROR_FETCH;
252 goto close;
253 }
254
255 /* strip "From " header for broken implementations */
256 cur_token = 0;
257 if (size > 5) {
258 if (strncmp("From ", str, size) == 0) {
259 cur_token += 5;
260
261 while (str[cur_token] != '\n') {
262 if (cur_token >= size)
263 break;
264 cur_token ++;
265 }
266 }
267 }
268
269 begin = cur_token;
270
271 while (1) {
272 r = mailimf_ignore_field_parse(str, size, &cur_token);
273 if (r == MAILIMF_NO_ERROR) {
274 /* do nothing */
275 }
276 else
277 break;
278 }
279 mailimf_crlf_parse(str, size, &cur_token);
280
281 mmapstr = mmap_string_new_len(str + begin, cur_token - begin);
282 if (mmapstr == NULL) {
283 res = MAIL_ERROR_MEMORY;
284 goto unmap;
285 }
286
287 if (mmap_string_ref(mmapstr) != 0) {
288 res = MAIL_ERROR_MEMORY;
289 goto free_str;
290 }
291
292 munmap(str, size);
293 close(fd);
294
295 * result = mmapstr->str;
296 * result_len = mmapstr->len;
297
298 return MAIL_NO_ERROR;
299
300 free_str:
301 mmap_string_free(mmapstr);
302 unmap:
303 munmap(str, size);
304 close:
305 close(fd);
306 err:
307 return res;
308}
309
310
311int mhdriver_fetch_size(mailsession * session, uint32_t index,
312 size_t * result)
313{
314 struct mailmh_folder * folder;
315 int r;
316 struct stat buf;
317 char * name;
318
319 folder = get_mh_cur_folder(session);
320 if (folder == NULL)
321 return MAIL_ERROR_FETCH;
322
323 r = mailmh_folder_get_message_filename(folder, index, &name);
324
325 switch (r) {
326 case MAILMH_NO_ERROR:
327 break;
328
329 default:
330 return mhdriver_mh_error_to_mail_error(r);
331 }
332
333 r = stat(name, &buf);
334 free(name);
335 if (r == -1)
336 return MAIL_ERROR_FETCH;
337
338 * result = buf.st_size;
339
340 return MAIL_NO_ERROR;
341}
342
343int
344mhdriver_get_cached_flags(struct mail_cache_db * cache_db,
345 MMAPString * mmapstr,
346 mailsession * session,
347 uint32_t num,
348 struct mail_flags ** result)
349{
350 int r;
351 char keyname[PATH_MAX];
352 struct mail_flags * flags;
353 int res;
354 struct mailmh_msg_info * msg_info;
355 chashdatum key;
356 chashdatum data;
357 struct mailmh_folder * folder;
358
359 folder = cached_get_mh_cur_folder(session);
360#if 0
361 msg_info = cinthash_find(mh_data->cur_folder->fl_msgs_hash, num);
362 if (msg_info == NULL)
363 return MAIL_ERROR_CACHE_MISS;
364#endif
365 key.data = &num;
366 key.len = sizeof(num);
367 r = chash_get(folder->fl_msgs_hash, &key, &data);
368 if (r < 0)
369 return MAIL_ERROR_CACHE_MISS;
370 msg_info = data.data;
371
372 snprintf(keyname, PATH_MAX, "%u-%u-%u-flags",
373 num, (uint32_t) msg_info->msg_mtime, msg_info->msg_size);
374
375 r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
376 if (r != MAIL_NO_ERROR) {
377 res = r;
378 goto err;
379 }
380
381 * result = flags;
382
383 return MAIL_NO_ERROR;
384
385 err:
386 return res;
387}
388
389int
390mhdriver_write_cached_flags(struct mail_cache_db * cache_db,
391 MMAPString * mmapstr,
392 char * uid,
393 struct mail_flags * flags)
394{
395 int r;
396 char keyname[PATH_MAX];
397 int res;
398
399 snprintf(keyname, PATH_MAX, "%s-flags", uid);
400
401 r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
402 if (r != MAIL_NO_ERROR) {
403 res = r;
404 goto err;
405 }
406
407 return MAIL_NO_ERROR;
408
409 err:
410 return res;
411}
412
413
414int mh_get_messages_list(struct mailmh_folder * folder,
415 mailsession * session, mailmessage_driver * driver,
416 struct mailmessage_list ** result)
417{
418 unsigned int i;
419 struct mailmessage_list * env_list;
420 int r;
421 carray * tab;
422 int res;
423
424 tab = carray_new(128);
425 if (tab == NULL) {
426 res = MAIL_ERROR_MEMORY;
427 goto err;
428 }
429
430 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) {
431 struct mailmh_msg_info * mh_info;
432 mailmessage * msg;
433
434 mh_info = carray_get(folder->fl_msgs_tab, i);
435 if (mh_info == NULL)
436 continue;
437
438 msg = mailmessage_new();
439 if (msg == NULL) {
440 res = MAIL_ERROR_MEMORY;
441 goto free_list;
442 }
443
444 r = mailmessage_init(msg, session, driver,
445 mh_info->msg_index, mh_info->msg_size);
446 if (r != MAIL_NO_ERROR) {
447 res = r;
448 goto free_list;
449 }
450
451 r = carray_add(tab, msg, NULL);
452 if (r < 0) {
453 mailmessage_free(msg);
454 res = MAIL_ERROR_MEMORY;
455 goto free_list;
456 }
457 }
458
459 env_list = mailmessage_list_new(tab);
460 if (env_list == NULL) {
461 res = MAIL_ERROR_MEMORY;
462 goto free_list;
463 }
464
465 * result = env_list;
466
467 return MAIL_NO_ERROR;
468
469 free_list:
470 for(i = 0 ; i < carray_count(tab) ; i ++)
471 mailmessage_free(carray_get(tab, i));
472 carray_free(tab);
473 err:
474 return res;
475}