summaryrefslogtreecommitdiffabout
path: root/kmicromail/libetpan/generic/mime_message_driver.c
Unidiff
Diffstat (limited to 'kmicromail/libetpan/generic/mime_message_driver.c') (more/less context) (show whitespace changes)
-rw-r--r--kmicromail/libetpan/generic/mime_message_driver.c689
1 files changed, 689 insertions, 0 deletions
diff --git a/kmicromail/libetpan/generic/mime_message_driver.c b/kmicromail/libetpan/generic/mime_message_driver.c
new file mode 100644
index 0000000..273875e
--- a/dev/null
+++ b/kmicromail/libetpan/generic/mime_message_driver.c
@@ -0,0 +1,689 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001 - 2003 - 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 "mime_message_driver.h"
37
38#include "libetpan-config.h"
39
40#include <sys/stat.h>
41#include <sys/types.h>
42#include <unistd.h>
43#include <sys/mman.h>
44#include <stdlib.h>
45#include <string.h>
46
47#include "mailmessage.h"
48#include "mailmessage_tools.h"
49#include "maildriver_tools.h"
50
51static FILE * get_mime_tmp_file(mailmessage * msg,
52 char * filename, size_t size)
53{
54 int fd;
55 mode_t old_mask;
56 FILE * f;
57
58 if (msg->msg_data == NULL)
59 return NULL;
60
61 snprintf(filename, size, "%s/libetpan-mime-XXXXXX",
62 (char *) msg->msg_data);
63
64 old_mask = umask(0077);
65 fd = mkstemp(filename);
66 umask(old_mask);
67 if (fd == -1)
68 return NULL;
69
70 f = fdopen(fd, "r+");
71 if (f == NULL) {
72 close(fd);
73 unlink(filename);
74 }
75
76 return f;
77}
78
79int mime_message_set_tmpdir(mailmessage * msg, char * tmpdir)
80{
81 if (msg->msg_data != NULL)
82 free(msg->msg_data);
83
84 msg->msg_data = strdup(tmpdir);
85 if (msg->msg_data == NULL)
86 return MAIL_ERROR_MEMORY;
87
88 return MAIL_NO_ERROR;
89}
90
91void mime_message_detach_mime(mailmessage * msg)
92{
93 msg->msg_mime = NULL;
94}
95
96mailmessage * mime_message_init(struct mailmime * mime)
97{
98 mailmessage * msg;
99 int r;
100
101 msg = mailmessage_new();
102 if (msg == NULL)
103 goto err;
104
105 r = mailmessage_init(msg, NULL, mime_message_driver, 0, 0);
106 if (r != MAIL_NO_ERROR)
107 goto free;
108
109 if (mime != NULL) {
110 mailmime_free(msg->msg_mime);
111 msg->msg_mime = mime;
112 }
113
114 return msg;
115
116 free:
117 mailmessage_free(msg);
118 err:
119 return NULL;
120}
121
122static int initialize(mailmessage * msg)
123{
124 struct mailmime * mime;
125 int res;
126
127 mime = mailmime_new_message_data(NULL);
128 if (mime == NULL) {
129 res = MAIL_ERROR_MEMORY;
130 goto err;
131 }
132
133 msg->msg_mime = mime;
134
135 return MAIL_NO_ERROR;
136
137 err:
138 return res;
139}
140
141static void uninitialize(mailmessage * msg)
142{
143 /* tmp dir name */
144 if (msg->msg_data != NULL)
145 free(msg->msg_data);
146
147 if (msg->msg_mime != NULL)
148 mailmime_free(msg->msg_mime);
149 msg->msg_mime = NULL;
150}
151
152static void flush(mailmessage * msg)
153{
154 /* do nothing */
155}
156
157static void check(mailmessage * msg)
158{
159 /* do nothing */
160}
161
162static void fetch_result_free(mailmessage * msg_info, char * content)
163{
164 mmap_string_unref(content);
165}
166
167static int file_to_mmapstr(FILE * f,
168 char ** result, size_t * result_len)
169{
170 int fd;
171 char * data;
172 struct stat buf;
173 MMAPString * mmapstr;
174 int res;
175 int r;
176
177 fd = fileno(f);
178 if (fd == -1) {
179 res = MAIL_ERROR_FILE;
180
181 goto err;
182 }
183
184 fflush(f);
185 r = fstat(fd, &buf);
186 if (r == -1) {
187 res = MAIL_ERROR_FILE;
188
189 goto err;
190 }
191
192 data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
193 if (data == MAP_FAILED) {
194 res = MAIL_ERROR_FILE;
195
196 goto err;
197 }
198
199 mmapstr = mmap_string_new_len(data, buf.st_size);
200 if (mmapstr == NULL) {
201 res = MAIL_ERROR_MEMORY;
202
203 goto unmap;
204 }
205
206 munmap(data, buf.st_size);
207
208 r = mmap_string_ref(mmapstr);
209 if (r != 0) {
210 res = MAIL_ERROR_MEMORY;
211
212 goto err;
213 }
214
215 * result = mmapstr->str;
216 * result_len = mmapstr->len;
217
218 return MAIL_NO_ERROR;
219
220 unmap:
221 munmap(data, buf.st_size);
222 err:
223 return res;
224}
225
226
227static int file_body_to_mmapstr(FILE * f,
228 char ** result, size_t * result_len)
229{
230 int fd;
231 char * data;
232 struct stat buf;
233 MMAPString * mmapstr;
234 size_t cur_token;
235 int res;
236 int r;
237
238 fd = fileno(f);
239 if (fd == -1) {
240 res = MAIL_ERROR_FILE;
241
242 goto err;
243 }
244
245 fflush(f);
246 r = fstat(fd, &buf);
247 if (r == -1) {
248 res = MAIL_ERROR_FILE;
249
250 goto err;
251 }
252
253 data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
254 if (data == MAP_FAILED) {
255 res = MAIL_ERROR_FILE;
256
257 goto err;
258 }
259
260 cur_token = 0;
261
262 /* skip header */
263
264 while (1) {
265 r = mailimf_ignore_field_parse(data,
266 buf.st_size, &cur_token);
267 if (r == MAILIMF_NO_ERROR) {
268 /* do nothing */
269 }
270 else
271 break;
272 }
273
274 r = mailimf_crlf_parse(data, buf.st_size, &cur_token);
275 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
276 res = maildriver_imf_error_to_mail_error(r);
277 goto unmap;
278 }
279
280 mmapstr = mmap_string_new_len(data + cur_token, buf.st_size - cur_token);
281 if (mmapstr == NULL) {
282 res = MAIL_ERROR_MEMORY;
283
284 goto unmap;
285 }
286
287 munmap(data, buf.st_size);
288
289 r = mmap_string_ref(mmapstr);
290 if (r != 0) {
291 res = MAIL_ERROR_MEMORY;
292
293 goto err;
294 }
295
296 * result = mmapstr->str;
297 * result_len = mmapstr->len;
298
299 return MAIL_NO_ERROR;
300
301 unmap:
302 munmap(data, buf.st_size);
303 err:
304 return res;
305}
306
307static int file_body_body_to_mmapstr(FILE * f,
308 char ** result, size_t * result_len)
309{
310 int fd;
311 char * data;
312 struct stat buf;
313 MMAPString * mmapstr;
314 size_t cur_token;
315 int res;
316 int r;
317
318 fd = fileno(f);
319 if (fd == -1) {
320 res = MAIL_ERROR_FILE;
321
322 goto err;
323 }
324
325 fflush(f);
326 r = fstat(fd, &buf);
327 if (r == -1) {
328 res = MAIL_ERROR_FILE;
329
330 goto err;
331 }
332
333 data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
334 if (data == MAP_FAILED) {
335 res = MAIL_ERROR_FILE;
336
337 goto err;
338 }
339
340 cur_token = 0;
341
342 /* skip header */
343
344 /* MIME header */
345
346 while (1) {
347 r = mailimf_ignore_field_parse(data,
348 buf.st_size, &cur_token);
349 if (r == MAILIMF_NO_ERROR) {
350 /* do nothing */
351 }
352 else
353 break;
354 }
355
356 r = mailimf_crlf_parse(data, buf.st_size, &cur_token);
357 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
358 res = maildriver_imf_error_to_mail_error(r);
359 goto unmap;
360 }
361
362 /* headers */
363
364 while (1) {
365 r = mailimf_ignore_field_parse(data,
366 buf.st_size, &cur_token);
367 if (r == MAILIMF_NO_ERROR) {
368 /* do nothing */
369 }
370 else
371 break;
372 }
373
374 r = mailimf_crlf_parse(data, buf.st_size, &cur_token);
375 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
376 res = maildriver_imf_error_to_mail_error(r);
377 goto unmap;
378 }
379
380 mmapstr = mmap_string_new_len(data + cur_token, buf.st_size - cur_token);
381 if (mmapstr == NULL) {
382 res = MAIL_ERROR_MEMORY;
383
384 goto unmap;
385 }
386
387 munmap(data, buf.st_size);
388
389 r = mmap_string_ref(mmapstr);
390 if (r != 0) {
391 res = MAIL_ERROR_MEMORY;
392
393 goto err;
394 }
395
396 * result = mmapstr->str;
397 * result_len = mmapstr->len;
398
399 return MAIL_NO_ERROR;
400
401 unmap:
402 munmap(data, buf.st_size);
403 err:
404 return res;
405}
406
407
408
409static int fetch_section(mailmessage * msg_info,
410 struct mailmime * mime,
411 char ** result, size_t * result_len)
412{
413 int r;
414 FILE * f;
415 int res;
416 int col;
417 char filename[PATH_MAX];
418
419 if (msg_info->msg_mime == NULL)
420 return MAIL_ERROR_INVAL;
421
422 f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
423 if (f == NULL) {
424 res = MAIL_ERROR_FILE;
425 goto err;
426 }
427
428 col = 0;
429 r = mailmime_write(f, &col, mime);
430 if (r != MAILIMF_NO_ERROR) {
431 res = maildriver_imf_error_to_mail_error(r);
432 goto close;
433 }
434
435 if (mime->mm_parent == NULL)
436 r = file_to_mmapstr(f, result, result_len);
437 else
438 r = file_body_to_mmapstr(f, result, result_len);
439
440 if (r != MAIL_NO_ERROR) {
441 res = r;
442 goto close;
443 }
444
445 fclose(f);
446 unlink(filename);
447
448 return MAIL_NO_ERROR;
449
450 close:
451 fclose(f);
452 unlink(filename);
453 err:
454 return res;
455}
456
457
458static int fetch_section_header(mailmessage * msg_info,
459 struct mailmime * mime,
460 char ** result, size_t * result_len)
461{
462 int r;
463 FILE * f;
464 int res;
465 int col;
466 char filename[PATH_MAX];
467
468 if (msg_info->msg_mime == NULL)
469 return MAIL_ERROR_INVAL;
470
471 f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
472 if (f == NULL) {
473 res = MAIL_ERROR_FILE;
474 goto err;
475 }
476
477 col = 0;
478 if (mime->mm_type == MAILMIME_MESSAGE) {
479 if (mime->mm_data.mm_message.mm_fields != NULL) {
480 r = mailimf_fields_write(f, &col, mime->mm_data.mm_message.mm_fields);
481 if (r != MAILIMF_NO_ERROR) {
482 res = maildriver_imf_error_to_mail_error(r);
483 goto close;
484 }
485 mailimf_string_write(f, &col, "\r\n", 2);
486 }
487 }
488
489 r = file_to_mmapstr(f, result, result_len);
490 if (r != MAIL_NO_ERROR) {
491 res = r;
492 goto close;
493 }
494
495 fclose(f);
496 unlink(filename);
497
498 return MAIL_NO_ERROR;
499
500 close:
501 fclose(f);
502 unlink(filename);
503 err:
504 return res;
505}
506
507
508static int fetch_section_mime(mailmessage * msg_info,
509 struct mailmime * mime,
510 char ** result, size_t * result_len)
511{
512 int r;
513 FILE * f;
514 int res;
515 int col;
516 char filename[PATH_MAX];
517
518 if (msg_info->msg_mime == NULL)
519 return MAIL_ERROR_INVAL;
520
521 f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
522 if (f == NULL) {
523 res = MAIL_ERROR_FILE;
524 goto err;
525 }
526
527 col = 0;
528 if (mime->mm_content_type != NULL) {
529 r = mailmime_content_write(f, &col, mime->mm_content_type);
530 if (r != MAILIMF_NO_ERROR) {
531 res = maildriver_imf_error_to_mail_error(r);
532 goto close;
533 }
534 }
535 if (mime->mm_mime_fields != NULL) {
536 r = mailmime_fields_write(f, &col, mime->mm_mime_fields);
537 if (r != MAILIMF_NO_ERROR) {
538 res = maildriver_imf_error_to_mail_error(r);
539 goto close;
540 }
541 }
542 mailimf_string_write(f, &col, "\r\n", 2);
543
544 r = file_to_mmapstr(f, result, result_len);
545 if (r != MAIL_NO_ERROR) {
546 res = r;
547 goto close;
548 }
549
550 fclose(f);
551 unlink(filename);
552
553 return MAIL_NO_ERROR;
554
555 close:
556 fclose(f);
557 unlink(filename);
558 err:
559 return res;
560}
561
562
563
564static int fetch_section_body(mailmessage * msg_info,
565 struct mailmime * mime,
566 char ** result, size_t * result_len)
567{
568 int r;
569 FILE * f;
570 int res;
571 int col;
572 char filename[PATH_MAX];
573
574 if (msg_info->msg_mime == NULL)
575 return MAIL_ERROR_INVAL;
576
577 f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
578 if (f == NULL) {
579 res = MAIL_ERROR_FILE;
580 goto err;
581 }
582
583 col = 0;
584 if (mime->mm_mime_fields != NULL) {
585 r = mailmime_write(f, &col, mime);
586 if (r != MAILIMF_NO_ERROR) {
587 res = maildriver_imf_error_to_mail_error(r);
588 goto close;
589 }
590 }
591
592 if (mime->mm_type == MAILMIME_MESSAGE)
593 r = file_body_body_to_mmapstr(f, result, result_len);
594 else
595 r = file_body_to_mmapstr(f, result, result_len);
596
597 if (r != MAIL_NO_ERROR) {
598 res = r;
599 goto close;
600 }
601
602 fclose(f);
603 unlink(filename);
604
605 return MAIL_NO_ERROR;
606
607 close:
608 fclose(f);
609 unlink(filename);
610 err:
611 return res;
612}
613
614
615static int get_bodystructure(mailmessage * msg_info,
616 struct mailmime ** result)
617{
618 if (msg_info->msg_mime == NULL)
619 return MAIL_ERROR_INVAL;
620
621 * result = msg_info->msg_mime;
622
623 return MAIL_NO_ERROR;
624}
625
626
627static int fetch(mailmessage * msg_info,
628 char ** result, size_t * result_len)
629{
630 return fetch_section(msg_info, msg_info->msg_mime, result, result_len);
631}
632
633static int fetch_header(mailmessage * msg_info,
634 char ** result, size_t * result_len)
635{
636 return fetch_section_header(msg_info,
637 msg_info->msg_mime, result, result_len);
638}
639
640static int fetch_body(mailmessage * msg_info,
641 char ** result, size_t * result_len)
642{
643 return fetch_section_body(msg_info, msg_info->msg_mime, result, result_len);
644}
645
646
647static int fetch_size(mailmessage * msg_info,
648 size_t * result)
649{
650 char * msg;
651 int r;
652
653 r = fetch(msg_info, &msg, result);
654 if (r != MAIL_NO_ERROR) {
655 return r;
656 }
657
658 fetch_result_free(msg_info, msg);
659
660 return MAIL_NO_ERROR;
661}
662
663
664static mailmessage_driver local_mime_message_driver = {
665 .msg_name = "mime",
666
667 .msg_initialize = initialize,
668 .msg_uninitialize = uninitialize,
669
670 .msg_flush = flush,
671 .msg_check = check,
672
673 .msg_fetch_result_free = fetch_result_free,
674
675 .msg_fetch = fetch,
676 .msg_fetch_header = fetch_header,
677 .msg_fetch_body = fetch_body,
678 .msg_fetch_size = fetch_size,
679 .msg_get_bodystructure = get_bodystructure,
680 .msg_fetch_section = fetch_section,
681 .msg_fetch_section_header = fetch_section_header,
682 .msg_fetch_section_mime = fetch_section_mime,
683 .msg_fetch_section_body = fetch_section_body,
684 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
685
686 .msg_get_flags = NULL,
687};
688
689mailmessage_driver * mime_message_driver = &local_mime_message_driver;