summaryrefslogtreecommitdiffabout
path: root/libetpan/src/low-level/imf/mailimf_write_generic.c
Unidiff
Diffstat (limited to 'libetpan/src/low-level/imf/mailimf_write_generic.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_generic.c2028
1 files changed, 2028 insertions, 0 deletions
diff --git a/libetpan/src/low-level/imf/mailimf_write_generic.c b/libetpan/src/low-level/imf/mailimf_write_generic.c
new file mode 100644
index 0000000..74c1d43
--- a/dev/null
+++ b/libetpan/src/low-level/imf/mailimf_write_generic.c
@@ -0,0 +1,2028 @@
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 "mailimf_write_generic.h"
37
38#include <time.h>
39#include <string.h>
40#include <ctype.h>
41
42#define MAX_MAIL_COL 72
43
44#ifndef TRUE
45#define TRUE 1
46#endif
47
48#ifndef FALSE
49#define FALSE 0
50#endif
51
52#define MAX_VALID_IMF_LINE 998
53
54static int mailimf_orig_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data,
55 int * col,
56 struct mailimf_orig_date * date);
57static int mailimf_date_time_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
58 struct mailimf_date_time * date_time);
59static int mailimf_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
60 struct mailimf_from * from);
61static int mailimf_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
62 struct mailimf_sender * sender);
63static int mailimf_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
64 struct mailimf_reply_to * reply_to);
65static int mailimf_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
66 struct mailimf_to * to);
67static int mailimf_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
68 struct mailimf_cc * to);
69static int mailimf_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
70 struct mailimf_bcc * to);
71static int mailimf_message_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
72 struct mailimf_message_id * message_id);
73static int mailimf_msg_id_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
74 clist * list);
75static int mailimf_in_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
76 struct mailimf_in_reply_to *
77 in_reply_to);
78static int mailimf_references_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
79 struct mailimf_references * references);
80static int mailimf_subject_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
81 struct mailimf_subject * subject);
82
83static int mailimf_address_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
84 struct mailimf_address * addr);
85static int mailimf_group_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
86 struct mailimf_group * group);
87
88static int mailimf_mailbox_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
89 struct mailimf_mailbox * mb);
90
91static int mailimf_comments_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
92 struct mailimf_comments * comments);
93
94static int mailimf_optional_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
95 struct mailimf_optional_field * field);
96
97static int mailimf_keywords_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
98 struct mailimf_keywords * keywords);
99
100static int mailimf_return_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
101 struct mailimf_return * return_path);
102
103static int mailimf_path_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
104 struct mailimf_path * path);
105
106static int mailimf_resent_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
107 struct mailimf_orig_date * date);
108
109static int mailimf_resent_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
110 struct mailimf_from * from);
111
112static int mailimf_resent_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
113 struct mailimf_sender * sender);
114
115static int mailimf_resent_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
116 struct mailimf_to * to);
117
118static int mailimf_resent_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
119 struct mailimf_cc * cc);
120
121static int mailimf_resent_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
122 struct mailimf_bcc * bcc);
123
124static int
125mailimf_resent_msg_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
126 struct mailimf_message_id * message_id);
127
128
129
130/* ************************ */
131
132#if 0
133int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
134 char * str, size_t length)
135{
136 int r;
137
138 if (length != 0) {
139 r = fwrite(str, sizeof(char), length, f);
140 if (r < 0)
141 return MAILIMF_ERROR_FILE;
142 * col += length;
143 }
144
145 return MAILIMF_NO_ERROR;
146}
147#endif
148
149#define CRLF "\r\n"
150#define HEADER_FOLD "\r\n "
151
152static inline int flush_buf(int (* do_write)(void *, const char *, size_t), void * data, const char * str, size_t length)
153{
154 if (length != 0) {
155 int r;
156
157 if (length > 0) {
158 r = do_write(data, str, length);
159 if (r == 0)
160 return MAILIMF_ERROR_FILE;
161 }
162 }
163 return MAILIMF_NO_ERROR;
164}
165
166#define CUT_AT_MAX_VALID_IMF_LINE
167
168int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
169 const char * str, size_t length)
170{
171 int r;
172 size_t count;
173 const char * block_begin;
174 const char * p;
175 int done;
176
177 p = str;
178 block_begin = str;
179 count = 0;
180
181 while (length > 0) {
182#ifdef CUT_AT_MAX_VALID_IMF_LINE
183 if (count >= 998) {
184 /*
185 cut lines at maximum valid length for internet message
186 format standard (currently RFC 2822)
187
188 This should not happen.
189 In case there are some lines larger than 998 in body,
190 the encoding must be changed into base64 or quoted-printable
191 so that wrapping to 72 columns is done.
192 */
193
194 r = flush_buf(do_write, data, block_begin, count);
195 if (r != MAILIMF_NO_ERROR)
196 return r;
197
198 r = do_write(data, CRLF, sizeof(CRLF) - 1);
199 if (r == 0)
200 return MAILIMF_ERROR_FILE;
201
202 count = 0;
203 block_begin = p;
204
205 * col = 0;
206 }
207#endif
208 switch (* p) {
209 case '\n':
210 r = flush_buf(do_write, data, block_begin, count);
211 if (r != MAILIMF_NO_ERROR)
212 return r;
213
214 r = do_write(data, CRLF, sizeof(CRLF) - 1);
215 if (r == 0)
216 return MAILIMF_ERROR_FILE;
217
218 p ++;
219 length --;
220 count = 0;
221 block_begin = p;
222
223 * col = 0;
224 break;
225
226 case '\r':
227 done = 0;
228 if (length >= 2) {
229 if (* (p + 1) == '\n') {
230 r = flush_buf(do_write, data, block_begin, count);
231 if (r != MAILIMF_NO_ERROR)
232 return r;
233
234 r = do_write(data, CRLF, sizeof(CRLF) - 1);
235 if (r == 0)
236 return MAILIMF_ERROR_FILE;
237
238 p += 2;
239 length -= 2;
240 count = 0;
241 block_begin = p;
242
243 * col = 0;
244
245 done = 1;
246 }
247 }
248 if (!done) {
249 r = flush_buf(do_write, data, block_begin, count);
250 if (r != MAILIMF_NO_ERROR)
251 return r;
252
253 r = do_write(data, CRLF, sizeof(CRLF) - 1);
254 if (r == 0)
255 return MAILIMF_ERROR_FILE;
256
257 p ++;
258 length --;
259 count = 0;
260 block_begin = p;
261
262 * col = 0;
263 }
264 break;
265
266 default:
267 p ++;
268 count ++;
269 length --;
270 break;
271 }
272 }
273
274 r = flush_buf(do_write, data, block_begin, count);
275 if (r != MAILIMF_NO_ERROR)
276 return r;
277 * col += count;
278
279 return MAILIMF_NO_ERROR;
280}
281
282#if 0
283int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
284 char * str, size_t length)
285{
286 char * p;
287 char * block_begin;
288 int current_col;
289 char * last_cut;
290 int r;
291 int first;
292
293 if (* col + length < MAX_MAIL_COL)
294 return mailimf_string_write_driver(do_write, data, col, str, length);
295
296 first = 1;
297 p = str;
298 block_begin = p;
299 last_cut = block_begin;
300 current_col = * col;
301
302 while (1) {
303 if (current_col >= MAX_MAIL_COL) {
304 /* if we reach the maximum recommanded size of line */
305 if (last_cut == block_begin) {
306 /* if we could not find any place to cut */
307 if (first) {
308 /* fold the header */
309 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
310 sizeof(HEADER_FOLD) - 1);
311 if (r != MAILIMF_NO_ERROR)
312 return r;
313 current_col = * col + p - block_begin;
314 first = 0;
315 }
316 else {
317 /* cut the header */
318 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
319 if (r != MAILIMF_NO_ERROR)
320 return r;
321 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
322 sizeof(HEADER_FOLD) - 1);
323 if (r != MAILIMF_NO_ERROR)
324 return r;
325 first = 0;
326 block_begin = p;
327 last_cut = block_begin;
328 current_col = * col + p - block_begin;
329 }
330 }
331 else {
332 /* if we found a place to cut */
333 r = mailimf_string_write_driver(do_write, data, col, block_begin, last_cut - block_begin);
334 if (r != MAILIMF_NO_ERROR)
335 return r;
336 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
337 sizeof(HEADER_FOLD) - 1);
338 if (r != MAILIMF_NO_ERROR)
339 return r;
340 first = 0;
341 block_begin = last_cut;
342 last_cut = block_begin;
343 current_col = * col + p - block_begin;
344 continue;
345 }
346 }
347 else {
348 if (length == 0)
349 break;
350
351 switch (* p) {
352 case ' ':
353 case '\t':
354 last_cut = p;
355 current_col ++;
356 break;
357
358 case '\r':
359 case '\n':
360 current_col = 0;
361 break;
362
363 default:
364 current_col ++;
365 break;
366 }
367
368 p ++;
369 length --;
370 }
371 }
372
373 return mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
374}
375#endif
376
377#if 0
378enum {
379 STATE_LOWER_72,
380 STATE_LOWER_72_CUT,
381 STATE_EQUAL_72,
382 STATE_LOWER_998,
383 STATE_EQUAL_998,
384};
385
386int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
387 const char * str, size_t length)
388{
389 int state;
390 const char * p;
391 const char * block_begin;
392 size_t size;
393 const char * cut;
394 int r;
395
396 if (* col < MAX_MAIL_COL)
397 state = STATE_LOWER_72_CUT;
398 else if (* col == MAX_MAIL_COL)
399 state = STATE_EQUAL_72;
400 else if (* col < MAX_VALID_IMF_LINE)
401 state = STATE_LOWER_998;
402 else
403 state = STATE_EQUAL_998;
404
405 p = str;
406 block_begin = p;
407 size = * col;
408 cut = p;
409
410 while (length > 0) {
411 switch (state) {
412 case STATE_LOWER_72:
413 switch (* p) {
414 case '\r':
415 case '\n':
416 p ++;
417 length --;
418 size = 0;
419 break;
420
421 case ' ':
422 case '\t':
423 cut = p;
424 p ++;
425 length --;
426 size ++;
427 state = STATE_LOWER_72_CUT;
428 break;
429
430 default:
431 if (size < MAX_MAIL_COL - 1) {
432 p ++;
433 length --;
434 size ++;
435 }
436 else {
437 state = STATE_EQUAL_72;
438 p ++;
439 length --;
440 size ++;
441 }
442 break;
443 }
444 break; /* end of STATE_LOWER_72 */
445
446 case STATE_LOWER_72_CUT:
447 switch (* p) {
448 case '\r':
449 case '\n':
450 p ++;
451 length --;
452 size = 0;
453 state = STATE_LOWER_72;
454 break;
455
456 case ' ':
457 case '\t':
458 cut = p;
459 p ++;
460 length --;
461 size ++;
462 break;
463
464 default:
465 if (size < MAX_MAIL_COL) {
466 p ++;
467 length --;
468 size ++;
469 }
470 else {
471 r = mailimf_string_write_driver(do_write, data, col, block_begin, cut - block_begin);
472 if (r != MAILIMF_NO_ERROR)
473 return r;
474 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
475 sizeof(HEADER_FOLD) - 1);
476 if (r != MAILIMF_NO_ERROR)
477 return r;
478 p ++;
479 length --;
480 block_begin = cut;
481 if ((* block_begin == ' ') || (* block_begin == '\t'))
482 block_begin ++;
483 size = p - block_begin + * col;
484 state = STATE_LOWER_72;
485 }
486 break;
487 }
488 break; /* end of STATE_LOWER_72_CUT */
489
490 case STATE_EQUAL_72:
491 switch (* p) {
492 case '\r':
493 case '\n':
494 p ++;
495 length --;
496 size = 0;
497 state = STATE_LOWER_72;
498 break;
499
500 case ' ':
501 case '\t':
502 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
503 if (r != MAILIMF_NO_ERROR)
504 return r;
505 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
506 sizeof(HEADER_FOLD) - 1);
507 if (r != MAILIMF_NO_ERROR)
508 return r;
509 p ++;
510 length --;
511 block_begin = p;
512 size = p - block_begin + * col;
513 state = STATE_LOWER_72;
514 break;
515
516 default:
517 p ++;
518 length --;
519 size ++;
520 state = STATE_LOWER_998;
521 break;
522 }
523 break; /* end of STATE_EQUAL_72 */
524
525 case STATE_LOWER_998:
526 switch (* p) {
527 case '\r':
528 case '\n':
529 p ++;
530 length --;
531 size = 0;
532 state = STATE_LOWER_72;
533 break;
534
535 case ' ':
536 case '\t':
537 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
538 if (r != MAILIMF_NO_ERROR)
539 return r;
540 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
541 sizeof(HEADER_FOLD) - 1);
542 if (r != MAILIMF_NO_ERROR)
543 return r;
544 p ++;
545 length --;
546 block_begin = p;
547 size = p - block_begin + * col;
548 state = STATE_LOWER_72;
549 break;
550
551 default:
552 if (size < MAX_VALID_IMF_LINE - 1) {
553 p ++;
554 length --;
555 size ++;
556 }
557 else {
558 p ++;
559 length --;
560 size = 0;
561 state = STATE_EQUAL_998;
562 }
563 break;
564 }
565 break; /* end of STATE_LOWER_998 */
566
567 case STATE_EQUAL_998:
568 switch (* p) {
569 case '\r':
570 case '\n':
571 p ++;
572 length --;
573 size = 0;
574 state = STATE_LOWER_72;
575 break;
576
577 case ' ':
578 case '\t':
579 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
580 if (r != MAILIMF_NO_ERROR)
581 return r;
582 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
583 sizeof(HEADER_FOLD) - 1);
584 if (r != MAILIMF_NO_ERROR)
585 return r;
586 p ++;
587 length --;
588 block_begin = p;
589 size = p - block_begin + * col;
590 state = STATE_LOWER_72;
591 break;
592
593 default:
594#ifdef CUT_AT_MAX_VALID_IMF_LINE
595 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
596 if (r != MAILIMF_NO_ERROR)
597 return r;
598 r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
599 sizeof(HEADER_FOLD) - 1);
600 if (r != MAILIMF_NO_ERROR)
601 return r;
602 p ++;
603 length --;
604 block_begin = p;
605 size = p - block_begin + * col;
606 state = STATE_LOWER_72;
607#else
608 p ++;
609 length --;
610 size ++;
611#endif
612 break;
613 }
614 break; /* end of STATE_EQUAL_998 */
615 }
616 }
617
618 r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin);
619 if (r != MAILIMF_NO_ERROR)
620 return r;
621
622 return MAILIMF_NO_ERROR;
623}
624#endif
625
626enum {
627 STATE_BEGIN,
628 STATE_WORD,
629 STATE_SPACE,
630};
631
632int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
633 const char * str, size_t length)
634{
635 int state;
636 const char * p;
637 const char * word_begin;
638 const char * word_end;
639 const char * next_word;
640 int first;
641
642 state = STATE_BEGIN;
643
644 p = str;
645 word_begin = p;
646 word_end = p;
647 next_word = p;
648 first = 1;
649
650 while (length > 0) {
651 switch (state) {
652 case STATE_BEGIN:
653 switch (* p) {
654 case '\r':
655 case '\n':
656 case ' ':
657 case '\t':
658 p ++;
659 length --;
660 break;
661
662 default:
663 word_begin = p;
664 state = STATE_WORD;
665 break;
666 }
667 break;
668
669 case STATE_SPACE:
670 switch (* p) {
671 case '\r':
672 case '\n':
673 case ' ':
674 case '\t':
675 p ++;
676 length --;
677 break;
678
679 default:
680 word_begin = p;
681 state = STATE_WORD;
682 break;
683 }
684 break;
685
686 case STATE_WORD:
687 switch (* p) {
688 case '\r':
689 case '\n':
690 case ' ':
691 case '\t':
692 if (p - word_begin + (* col) + 1 > MAX_MAIL_COL)
693 mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
694 sizeof(HEADER_FOLD) - 1);
695 else {
696 if (!first)
697 mailimf_string_write_driver(do_write, data, col, " ", 1);
698 }
699 first = 0;
700 mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin);
701 state = STATE_SPACE;
702 break;
703
704 default:
705 if (p - word_begin + (* col) >= MAX_VALID_IMF_LINE) {
706 mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin);
707 mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
708 sizeof(HEADER_FOLD) - 1);
709 word_begin = p;
710 }
711 p ++;
712 length --;
713 break;
714 }
715 break;
716 }
717 }
718
719 if (state == STATE_WORD) {
720 if (p - word_begin + (* col) >= MAX_MAIL_COL)
721 mailimf_string_write_driver(do_write, data, col, HEADER_FOLD,
722 sizeof(HEADER_FOLD) - 1);
723 else {
724 if (!first)
725 mailimf_string_write_driver(do_write, data, col, " ", 1);
726 }
727 first = 0;
728 mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin);
729 }
730
731 return MAILIMF_NO_ERROR;
732}
733
734int mailimf_envelope_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
735 struct mailimf_fields * fields)
736{
737 clistiter * cur;
738
739 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
740 cur = clist_next(cur)) {
741 int r;
742 struct mailimf_field * field;
743
744 field = clist_content(cur);
745 if (field->fld_type != MAILIMF_FIELD_OPTIONAL_FIELD) {
746 r = mailimf_field_write_driver(do_write, data, col, field);
747 if (r != MAILIMF_NO_ERROR)
748 return r;
749 }
750 }
751
752 return MAILIMF_NO_ERROR;
753}
754
755int mailimf_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
756 struct mailimf_fields * fields)
757{
758 clistiter * cur;
759
760 for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
761 cur = clist_next(cur)) {
762 int r;
763
764 r = mailimf_field_write_driver(do_write, data, col, clist_content(cur));
765 if (r != MAILIMF_NO_ERROR)
766 return r;
767 }
768
769 return MAILIMF_NO_ERROR;
770}
771
772#if 0
773int mailimf_unparsed_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
774 struct mailimf_unparsed_fields * fields)
775{
776 clistiter * cur;
777
778 for(cur = clist_begin(fields->list) ; cur != NULL ; cur = cur->next) {
779 int r;
780
781 r = mailimf_optional_field_write_driver(do_write, data, col, cur->data);
782 if (r != MAILIMF_NO_ERROR)
783 return r;
784 }
785
786 return MAILIMF_NO_ERROR;
787}
788#endif
789
790int mailimf_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
791 struct mailimf_field * field)
792{
793 int r;
794
795 switch (field->fld_type) {
796 case MAILIMF_FIELD_RETURN_PATH:
797 r = mailimf_return_write_driver(do_write, data, col, field->fld_data.fld_return_path);
798 break;
799 case MAILIMF_FIELD_RESENT_DATE:
800 r = mailimf_resent_date_write_driver(do_write, data, col, field->fld_data.fld_resent_date);
801 break;
802 case MAILIMF_FIELD_RESENT_FROM:
803 r = mailimf_resent_from_write_driver(do_write, data, col, field->fld_data.fld_resent_from);
804 break;
805 case MAILIMF_FIELD_RESENT_SENDER:
806 r = mailimf_resent_sender_write_driver(do_write, data, col, field->fld_data.fld_resent_sender);
807 break;
808 case MAILIMF_FIELD_RESENT_TO:
809 r = mailimf_resent_to_write_driver(do_write, data, col, field->fld_data.fld_resent_to);
810 break;
811 case MAILIMF_FIELD_RESENT_CC:
812 r = mailimf_resent_cc_write_driver(do_write, data, col, field->fld_data.fld_resent_cc);
813 break;
814 case MAILIMF_FIELD_RESENT_BCC:
815 r = mailimf_resent_bcc_write_driver(do_write, data, col, field->fld_data.fld_resent_bcc);
816 break;
817 case MAILIMF_FIELD_RESENT_MSG_ID:
818 r = mailimf_resent_msg_id_write_driver(do_write, data, col, field->fld_data.fld_resent_msg_id);
819 break;
820 case MAILIMF_FIELD_ORIG_DATE:
821 r = mailimf_orig_date_write_driver(do_write, data, col, field->fld_data.fld_orig_date);
822 break;
823 case MAILIMF_FIELD_FROM:
824 r = mailimf_from_write_driver(do_write, data, col, field->fld_data.fld_from);
825 break;
826 case MAILIMF_FIELD_SENDER:
827 r = mailimf_sender_write_driver(do_write, data, col, field->fld_data.fld_sender);
828 break;
829 case MAILIMF_FIELD_REPLY_TO:
830 r = mailimf_reply_to_write_driver(do_write, data, col, field->fld_data.fld_reply_to);
831 break;
832 case MAILIMF_FIELD_TO:
833 r = mailimf_to_write_driver(do_write, data, col, field->fld_data.fld_to);
834 break;
835 case MAILIMF_FIELD_CC:
836 r = mailimf_cc_write_driver(do_write, data, col, field->fld_data.fld_cc);
837 break;
838 case MAILIMF_FIELD_BCC:
839 r = mailimf_bcc_write_driver(do_write, data, col, field->fld_data.fld_bcc);
840 break;
841 case MAILIMF_FIELD_MESSAGE_ID:
842 r = mailimf_message_id_write_driver(do_write, data, col, field->fld_data.fld_message_id);
843 break;
844 case MAILIMF_FIELD_IN_REPLY_TO:
845 r = mailimf_in_reply_to_write_driver(do_write, data, col, field->fld_data.fld_in_reply_to);
846 break;
847 case MAILIMF_FIELD_REFERENCES:
848 r = mailimf_references_write_driver(do_write, data, col, field->fld_data.fld_references);
849 break;
850 case MAILIMF_FIELD_SUBJECT:
851 r = mailimf_subject_write_driver(do_write, data, col, field->fld_data.fld_subject);
852 break;
853 case MAILIMF_FIELD_COMMENTS:
854 r = mailimf_comments_write_driver(do_write, data, col, field->fld_data.fld_comments);
855 break;
856 case MAILIMF_FIELD_KEYWORDS:
857 r = mailimf_keywords_write_driver(do_write, data, col, field->fld_data.fld_keywords);
858 break;
859 case MAILIMF_FIELD_OPTIONAL_FIELD:
860 r = mailimf_optional_field_write_driver(do_write, data, col, field->fld_data.fld_optional_field);
861 break;
862 default:
863 r = MAILIMF_ERROR_INVAL;
864 break;
865 }
866
867 if (r != MAILIMF_NO_ERROR)
868 return r;
869
870 return MAILIMF_NO_ERROR;
871}
872
873
874static int mailimf_orig_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
875 struct mailimf_orig_date * date)
876{
877 int r;
878
879 r = mailimf_string_write_driver(do_write, data, col, "Date: ", 6);
880 if (r != MAILIMF_NO_ERROR)
881 return r;
882
883 r = mailimf_date_time_write_driver(do_write, data, col, date->dt_date_time);
884 if (r != MAILIMF_NO_ERROR)
885 return r;
886
887 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
888 if (r != MAILIMF_NO_ERROR)
889 return r;
890#if 0
891 * col = 0;
892#endif
893
894 return MAILIMF_NO_ERROR;
895}
896
897#define MAX_DATE_STR 256
898
899/* 0 = Sunday */
900/* y > 1752 */
901
902static int dayofweek(int year, int month, int day)
903{
904 static int offset[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
905
906 year -= month < 3;
907
908 return (year + year/4 - year/100 + year/400 + offset[month-1] + day) % 7;
909}
910
911static const char * week_of_day_str[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
912 "Fri", "Sat"};
913static const char * month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
914 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
915
916static int mailimf_date_time_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
917 struct mailimf_date_time * date_time)
918{
919 int r;
920 char date_str[MAX_DATE_STR];
921#if 0
922 struct tm tmval;
923 time_t timeval;
924#endif
925 int wday;
926
927#if 0
928 tmval.tm_sec = date_time->sec;
929 tmval.tm_min = date_time->min;
930 tmval.tm_hour = date_time->hour;
931 tmval.tm_sec = date_time->sec;
932 tmval.tm_mday = date_time->day;
933 tmval.tm_mon = date_time->month - 1;
934 tmval.tm_year = date_time->year - 1900;
935 tmval.tm_isdst = 1;
936
937 timeval = mktime(&tmval);
938
939 localtime_r(&timeval, &tmval);
940#endif
941
942 wday = dayofweek(date_time->dt_year, date_time->dt_month, date_time->dt_day);
943
944 snprintf(date_str, MAX_DATE_STR, "%s, %i %s %i %02i:%02i:%02i %+05i",
945 week_of_day_str[wday], date_time->dt_day,
946 month_str[date_time->dt_month - 1],
947 date_time->dt_year, date_time->dt_hour,
948 date_time->dt_min, date_time->dt_sec,
949 date_time->dt_zone);
950
951 r = mailimf_string_write_driver(do_write, data, col, date_str, strlen(date_str));
952
953 if (r != MAILIMF_NO_ERROR)
954 return r;
955
956 return MAILIMF_NO_ERROR;
957}
958
959static int mailimf_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
960 struct mailimf_from * from)
961{
962 int r;
963
964 r = mailimf_string_write_driver(do_write, data, col, "From: ", 6);
965 if (r != MAILIMF_NO_ERROR)
966 return r;
967
968 r = mailimf_mailbox_list_write_driver(do_write, data, col, from->frm_mb_list);
969 if (r != MAILIMF_NO_ERROR)
970 return r;
971
972 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
973 if (r != MAILIMF_NO_ERROR)
974 return r;
975#if 0
976 * col = 0;
977#endif
978
979 return MAILIMF_NO_ERROR;
980}
981
982static int mailimf_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
983 struct mailimf_sender * sender)
984{
985 int r;
986
987 r = mailimf_string_write_driver(do_write, data, col, "Sender: ", 8);
988 if (r != MAILIMF_NO_ERROR)
989 return r;
990
991 r = mailimf_mailbox_write_driver(do_write, data, col, sender->snd_mb);
992 if (r != MAILIMF_NO_ERROR)
993 return r;
994
995 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
996 if (r != MAILIMF_NO_ERROR)
997 return r;
998#if 0
999 * col = 0;
1000#endif
1001
1002 return MAILIMF_NO_ERROR;
1003}
1004
1005static int mailimf_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1006 struct mailimf_reply_to * reply_to)
1007{
1008 int r;
1009
1010 r = mailimf_string_write_driver(do_write, data, col, "Reply-To: ", 10);
1011 if (r != MAILIMF_NO_ERROR)
1012 return r;
1013
1014 r = mailimf_address_list_write_driver(do_write, data, col, reply_to->rt_addr_list);
1015 if (r != MAILIMF_NO_ERROR)
1016 return r;
1017
1018 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1019 if (r != MAILIMF_NO_ERROR)
1020 return r;
1021#if 0
1022 * col = 0;
1023#endif
1024
1025 return MAILIMF_NO_ERROR;
1026}
1027
1028
1029static int mailimf_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1030 struct mailimf_to * to)
1031{
1032 int r;
1033
1034 r = mailimf_string_write_driver(do_write, data, col, "To: ", 4);
1035 if (r != MAILIMF_NO_ERROR)
1036 return r;
1037
1038 r = mailimf_address_list_write_driver(do_write, data, col, to->to_addr_list);
1039 if (r != MAILIMF_NO_ERROR)
1040 return r;
1041
1042 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1043 if (r != MAILIMF_NO_ERROR)
1044 return r;
1045#if 0
1046 * col = 0;
1047#endif
1048
1049 return MAILIMF_NO_ERROR;
1050}
1051
1052
1053static int mailimf_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1054 struct mailimf_cc * cc)
1055{
1056 int r;
1057
1058 r = mailimf_string_write_driver(do_write, data, col, "Cc: ", 4);
1059 if (r != MAILIMF_NO_ERROR)
1060 return r;
1061
1062 r = mailimf_address_list_write_driver(do_write, data, col, cc->cc_addr_list);
1063 if (r != MAILIMF_NO_ERROR)
1064 return r;
1065
1066 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1067 if (r != MAILIMF_NO_ERROR)
1068 return r;
1069#if 0
1070 * col = 0;
1071#endif
1072
1073 return MAILIMF_NO_ERROR;
1074}
1075
1076
1077static int mailimf_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1078 struct mailimf_bcc * bcc)
1079{
1080 int r;
1081
1082 r = mailimf_string_write_driver(do_write, data, col, "Bcc: ", 5);
1083 if (r != MAILIMF_NO_ERROR)
1084 return r;
1085
1086 if (bcc->bcc_addr_list != NULL) {
1087 r = mailimf_address_list_write_driver(do_write, data, col, bcc->bcc_addr_list);
1088 if (r != MAILIMF_NO_ERROR)
1089 return r;
1090 }
1091
1092 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1093 if (r != MAILIMF_NO_ERROR)
1094 return r;
1095#if 0
1096 * col = 0;
1097#endif
1098
1099 return MAILIMF_NO_ERROR;
1100}
1101
1102
1103static int mailimf_message_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1104 struct mailimf_message_id * message_id)
1105{
1106 int r;
1107
1108 r = mailimf_string_write_driver(do_write, data, col, "Message-ID: ", 12);
1109 if (r != MAILIMF_NO_ERROR)
1110 return r;
1111
1112 r = mailimf_string_write_driver(do_write, data, col, "<", 1);
1113 if (r != MAILIMF_NO_ERROR)
1114 return r;
1115
1116 r = mailimf_string_write_driver(do_write, data, col,
1117 message_id->mid_value,
1118 strlen(message_id->mid_value));
1119 if (r != MAILIMF_NO_ERROR)
1120 return r;
1121
1122 r = mailimf_string_write_driver(do_write, data, col, ">", 1);
1123 if (r != MAILIMF_NO_ERROR)
1124 return r;
1125
1126 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1127 if (r != MAILIMF_NO_ERROR)
1128 return r;
1129#if 0
1130 * col = 0;
1131#endif
1132
1133 return MAILIMF_NO_ERROR;
1134}
1135
1136
1137static int mailimf_msg_id_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, clist * mid_list)
1138{
1139 clistiter * cur;
1140 int r;
1141 int first;
1142
1143 first = TRUE;
1144
1145 for(cur = clist_begin(mid_list) ; cur != NULL ; cur = clist_next(cur)) {
1146 char * msgid;
1147 size_t len;
1148
1149 msgid = clist_content(cur);
1150 len = strlen(msgid);
1151
1152 /*
1153 XXX - if this is the first message ID, don't fold.
1154 This is a workaround for a bug of old versions of INN.
1155 */
1156 if (!first) {
1157 if (* col > 1) {
1158
1159 if (* col + len >= MAX_MAIL_COL) {
1160 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1161 if (r != MAILIMF_NO_ERROR)
1162 return r;
1163#if 0
1164 * col = 1;
1165#endif
1166 first = TRUE;
1167 }
1168 }
1169 }
1170
1171 if (!first) {
1172 r = mailimf_string_write_driver(do_write, data, col, " ", 1);
1173 if (r != MAILIMF_NO_ERROR)
1174 return r;
1175 }
1176 else {
1177 first = FALSE;
1178 }
1179
1180 r = mailimf_string_write_driver(do_write, data, col, "<", 1);
1181 if (r != MAILIMF_NO_ERROR)
1182 return r;
1183
1184 r = mailimf_string_write_driver(do_write, data, col, msgid, len);
1185 if (r != MAILIMF_NO_ERROR)
1186 return r;
1187
1188 r = mailimf_string_write_driver(do_write, data, col, ">", 1);
1189 if (r != MAILIMF_NO_ERROR)
1190 return r;
1191 }
1192
1193 return MAILIMF_NO_ERROR;
1194}
1195
1196
1197static int mailimf_in_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1198 struct mailimf_in_reply_to * in_reply_to)
1199{
1200 int r;
1201
1202 r = mailimf_string_write_driver(do_write, data, col, "In-Reply-To: ", 13);
1203 if (r != MAILIMF_NO_ERROR)
1204 return r;
1205
1206 r = mailimf_msg_id_list_write_driver(do_write, data, col, in_reply_to->mid_list);
1207 if (r != MAILIMF_NO_ERROR)
1208 return r;
1209
1210 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1211 if (r != MAILIMF_NO_ERROR)
1212 return r;
1213#if 0
1214 * col = 0;
1215#endif
1216
1217 return MAILIMF_NO_ERROR;
1218}
1219
1220
1221static int mailimf_references_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1222 struct mailimf_references * references)
1223{
1224 int r;
1225
1226 r = mailimf_string_write_driver(do_write, data, col, "References: ", 12);
1227 if (r != MAILIMF_NO_ERROR)
1228 return r;
1229
1230 r = mailimf_msg_id_list_write_driver(do_write, data, col, references->mid_list);
1231 if (r != MAILIMF_NO_ERROR)
1232 return r;
1233
1234 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1235 if (r != MAILIMF_NO_ERROR)
1236 return r;
1237#if 0
1238 * col = 0;
1239#endif
1240
1241 return MAILIMF_NO_ERROR;
1242}
1243
1244
1245
1246static int mailimf_subject_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1247 struct mailimf_subject * subject)
1248{
1249 int r;
1250
1251 r = mailimf_string_write_driver(do_write, data, col, "Subject: ", 9);
1252 if (r != MAILIMF_NO_ERROR)
1253 return r;
1254
1255 r = mailimf_header_string_write_driver(do_write, data, col,
1256 subject->sbj_value, strlen(subject->sbj_value));
1257 if (r != MAILIMF_NO_ERROR)
1258 return r;
1259
1260 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1261 if (r != MAILIMF_NO_ERROR)
1262 return r;
1263#if 0
1264 * col = 0;
1265#endif
1266
1267 return MAILIMF_NO_ERROR;
1268}
1269
1270int mailimf_address_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1271 struct mailimf_address_list * addr_list)
1272{
1273 clistiter * cur;
1274 int r;
1275 int first;
1276
1277 first = TRUE;
1278
1279 for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ;
1280 cur = clist_next(cur)) {
1281 struct mailimf_address * addr;
1282
1283 addr = clist_content(cur);
1284
1285 if (!first) {
1286 r = mailimf_string_write_driver(do_write, data, col, ", ", 2);
1287 if (r != MAILIMF_NO_ERROR)
1288 return r;
1289 }
1290 else {
1291 first = FALSE;
1292 }
1293
1294 r = mailimf_address_write_driver(do_write, data, col, addr);
1295 if (r != MAILIMF_NO_ERROR)
1296 return r;
1297 }
1298
1299 return MAILIMF_NO_ERROR;
1300}
1301
1302
1303static int mailimf_address_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1304 struct mailimf_address * addr)
1305{
1306 int r;
1307
1308 switch(addr->ad_type) {
1309 case MAILIMF_ADDRESS_MAILBOX:
1310 r = mailimf_mailbox_write_driver(do_write, data, col, addr->ad_data.ad_mailbox);
1311 if (r != MAILIMF_NO_ERROR)
1312 return r;
1313
1314 break;
1315
1316 case MAILIMF_ADDRESS_GROUP:
1317 r = mailimf_group_write_driver(do_write, data, col, addr->ad_data.ad_group);
1318 if (r != MAILIMF_NO_ERROR)
1319 return r;
1320
1321 break;
1322 }
1323
1324 return MAILIMF_NO_ERROR;
1325}
1326
1327
1328static int mailimf_group_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1329 struct mailimf_group * group)
1330{
1331 int r;
1332
1333 r = mailimf_header_string_write_driver(do_write, data, col, group->grp_display_name,
1334 strlen(group->grp_display_name));
1335 if (r != MAILIMF_NO_ERROR)
1336 return r;
1337
1338 r = mailimf_string_write_driver(do_write, data, col, ": ", 2);
1339 if (r != MAILIMF_NO_ERROR)
1340 return r;
1341
1342 if (group->grp_mb_list != NULL) {
1343 r = mailimf_mailbox_list_write_driver(do_write, data, col, group->grp_mb_list);
1344 if (r != MAILIMF_NO_ERROR)
1345 return r;
1346 }
1347
1348 r = mailimf_string_write_driver(do_write, data, col, ";", 1);
1349 if (r != MAILIMF_NO_ERROR)
1350 return r;
1351
1352 return MAILIMF_NO_ERROR;
1353}
1354
1355
1356int mailimf_mailbox_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1357 struct mailimf_mailbox_list * mb_list)
1358{
1359 clistiter * cur;
1360 int r;
1361 int first;
1362
1363 first = TRUE;
1364
1365 for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ;
1366 cur = clist_next(cur)) {
1367 struct mailimf_mailbox * mb;
1368
1369 mb = clist_content(cur);
1370
1371 if (!first) {
1372 r = mailimf_string_write_driver(do_write, data, col, ", ", 2);
1373 if (r != MAILIMF_NO_ERROR)
1374 return r;
1375 }
1376 else {
1377 first = FALSE;
1378 }
1379
1380 r = mailimf_mailbox_write_driver(do_write, data, col, mb);
1381 if (r != MAILIMF_NO_ERROR)
1382 return r;
1383 }
1384
1385 return MAILIMF_NO_ERROR;
1386}
1387
1388
1389int mailimf_quoted_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1390 const char * string, size_t len)
1391{
1392 int r;
1393 size_t i;
1394
1395 r = do_write(data, "\"", 1);
1396 if (r == 0)
1397 return MAILIMF_ERROR_FILE;
1398 for(i = 0 ; i < len ; i ++) {
1399 switch (string[i]) {
1400 case '\\':
1401 case '\"':
1402 r = do_write(data, "\\", 1);
1403 if (r == 0)
1404 return MAILIMF_ERROR_FILE;
1405 r = do_write(data, &string[i], 1);
1406 if (r == 0)
1407 return MAILIMF_ERROR_FILE;
1408 (* col) += 2;
1409 break;
1410
1411 default:
1412 r = do_write(data, &string[i], 1);
1413 if (r == 0)
1414 return MAILIMF_ERROR_FILE;
1415 (* col) ++;
1416 break;
1417 }
1418 }
1419 r = do_write(data, "\"", 1);
1420 if (r == 0)
1421 return MAILIMF_ERROR_FILE;
1422
1423 return MAILIMF_NO_ERROR;
1424}
1425
1426
1427/*
1428static int
1429atext = ALPHA / DIGIT / ; Any character except controls,
1430 "!" / "#" / ; SP, and specials.
1431 "$" / "%" / ; Used for atoms
1432 "&" / "'" /
1433 "*" / "+" /
1434 "-" / "/" /
1435 "=" / "?" /
1436 "^" / "_" /
1437 "`" / "{" /
1438 "|" / "}" /
1439 "~"
1440*/
1441
1442static int is_atext(const char * s)
1443{
1444 const char * p;
1445
1446 for(p = s ; * p != 0 ; p ++) {
1447 if (isalpha((unsigned char) * p))
1448 continue;
1449 if (isdigit((unsigned char) * p))
1450 continue;
1451 switch (*p) {
1452 case ' ':
1453 case '\t':
1454 case '!':
1455 case '#':
1456 case '$':
1457 case '%':
1458 case '&':
1459 case '\'':
1460 case '*':
1461 case '+':
1462 case '-':
1463 case '/':
1464 case '=':
1465 case '?':
1466 case '^':
1467 case '_':
1468 case '`':
1469 case '{':
1470 case '|':
1471 case '}':
1472 case '~':
1473 break;
1474 default:
1475 return 0;
1476 }
1477 }
1478
1479 return 1;
1480}
1481
1482static int mailimf_mailbox_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1483 struct mailimf_mailbox * mb)
1484{
1485 int r;
1486 int do_fold;
1487
1488#if 0
1489 if (* col > 1) {
1490
1491 if (mb->mb_display_name != NULL) {
1492 if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) {
1493 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1494 if (r != MAILIMF_NO_ERROR)
1495 return r;
1496#if 0
1497 * col = 1;
1498#endif
1499 }
1500 }
1501 }
1502#endif
1503
1504 if (mb->mb_display_name) {
1505
1506 if (is_atext(mb->mb_display_name)) {
1507 r = mailimf_header_string_write_driver(do_write, data, col, mb->mb_display_name,
1508 strlen(mb->mb_display_name));
1509 if (r != MAILIMF_NO_ERROR)
1510 return r;
1511 }
1512 else {
1513 if (mb->mb_display_name != NULL) {
1514 if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) {
1515 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1516 if (r != MAILIMF_NO_ERROR)
1517 return r;
1518 }
1519 }
1520
1521 if (strlen(mb->mb_display_name) > MAX_VALID_IMF_LINE / 2)
1522 return MAILIMF_ERROR_INVAL;
1523
1524 r = mailimf_quoted_string_write_driver(do_write, data, col, mb->mb_display_name,
1525 strlen(mb->mb_display_name));
1526 if (r != MAILIMF_NO_ERROR)
1527 return r;
1528 }
1529
1530 do_fold = 0;
1531 if (* col > 1) {
1532
1533 if (* col + strlen(mb->mb_addr_spec) + 3 >= MAX_MAIL_COL) {
1534 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1535 if (r != MAILIMF_NO_ERROR)
1536 return r;
1537#if 0
1538 * col = 1;
1539#endif
1540 do_fold = 1;
1541 }
1542 }
1543
1544 if (do_fold)
1545 r = mailimf_string_write_driver(do_write, data, col, "<", 1);
1546 else
1547 r = mailimf_string_write_driver(do_write, data, col, " <", 2);
1548 if (r != MAILIMF_NO_ERROR)
1549 return r;
1550
1551 r = mailimf_string_write_driver(do_write, data, col, mb->mb_addr_spec,
1552 strlen(mb->mb_addr_spec));
1553 if (r != MAILIMF_NO_ERROR)
1554 return r;
1555
1556 r = mailimf_string_write_driver(do_write, data, col, ">", 1);
1557 if (r != MAILIMF_NO_ERROR)
1558 return r;
1559 }
1560 else {
1561 if (* col + strlen(mb->mb_addr_spec) >= MAX_MAIL_COL) {
1562 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1563 if (r != MAILIMF_NO_ERROR)
1564 return r;
1565 }
1566
1567 r = mailimf_string_write_driver(do_write, data, col,
1568 mb->mb_addr_spec, strlen(mb->mb_addr_spec));
1569 if (r != MAILIMF_NO_ERROR)
1570 return r;
1571 }
1572
1573
1574 return MAILIMF_NO_ERROR;
1575}
1576
1577static int mailimf_comments_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1578 struct mailimf_comments * comments)
1579{
1580 int r;
1581
1582 r = mailimf_string_write_driver(do_write, data, col, "Comments: ", 10);
1583 if (r != MAILIMF_NO_ERROR)
1584 return r;
1585
1586 r = mailimf_header_string_write_driver(do_write, data, col,
1587 comments->cm_value, strlen(comments->cm_value));
1588 if (r != MAILIMF_NO_ERROR)
1589 return r;
1590
1591 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1592 if (r != MAILIMF_NO_ERROR)
1593 return r;
1594#if 0
1595 * col = 0;
1596#endif
1597
1598 return MAILIMF_NO_ERROR;
1599}
1600
1601static int mailimf_optional_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1602 struct mailimf_optional_field * field)
1603{
1604 int r;
1605
1606 if (strlen(field->fld_name) + 2 > MAX_VALID_IMF_LINE)
1607 return MAILIMF_ERROR_INVAL;
1608
1609 r = mailimf_string_write_driver(do_write, data, col, field->fld_name, strlen(field->fld_name));
1610 if (r != MAILIMF_NO_ERROR)
1611 return r;
1612
1613 r = mailimf_string_write_driver(do_write, data, col, ": ", 2);
1614 if (r != MAILIMF_NO_ERROR)
1615 return r;
1616
1617 r = mailimf_header_string_write_driver(do_write, data, col, field->fld_value,
1618 strlen(field->fld_value));
1619 if (r != MAILIMF_NO_ERROR)
1620 return r;
1621
1622#if 0
1623 /* XXX parsing debug */
1624 mailimf_string_write_driver(do_write, data, col, " (X)", 4);
1625#endif
1626
1627 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1628 if (r != MAILIMF_NO_ERROR)
1629 return r;
1630#if 0
1631 * col = 0;
1632#endif
1633
1634 return MAILIMF_NO_ERROR;
1635}
1636
1637static int mailimf_keywords_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1638 struct mailimf_keywords * keywords)
1639{
1640 int r;
1641 clistiter * cur;
1642 int first;
1643
1644 r = mailimf_string_write_driver(do_write, data, col, "Keywords: ", 10);
1645 if (r != MAILIMF_NO_ERROR)
1646 return r;
1647
1648 first = TRUE;
1649
1650 for(cur = clist_begin(keywords->kw_list) ; cur != NULL ;
1651 cur = clist_next(cur)) {
1652 char * keyword;
1653 size_t len;
1654
1655 keyword = clist_content(cur);
1656 len = strlen(keyword);
1657
1658 if (!first) {
1659 r = mailimf_string_write_driver(do_write, data, col, ", ", 2);
1660 if (r != MAILIMF_NO_ERROR)
1661 return r;
1662 }
1663 else {
1664 first = FALSE;
1665 }
1666
1667#if 0
1668 if (* col > 1) {
1669
1670 if (* col + len >= MAX_MAIL_COL) {
1671 r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3);
1672 if (r != MAILIMF_NO_ERROR)
1673 return r;
1674#if 0
1675 * col = 1;
1676#endif
1677 }
1678 }
1679#endif
1680
1681 r = mailimf_header_string_write_driver(do_write, data, col, keyword, len);
1682 if (r != MAILIMF_NO_ERROR)
1683 return r;
1684 }
1685
1686 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1687 if (r != MAILIMF_NO_ERROR)
1688 return r;
1689#if 0
1690 * col = 0;
1691#endif
1692
1693 return MAILIMF_NO_ERROR;
1694}
1695
1696#if 0
1697static int mailimf_delivering_info_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1698 struct mailimf_delivering_info * info)
1699{
1700 clistiter * cur;
1701 int r;
1702
1703 for(cur = clist_begin(info->received_fields) ;
1704 cur != NULL ; cur = cur->next) {
1705 struct mailimf_trace_resent_fields * field;
1706
1707 field = cur->data;
1708
1709 r = mailimf_trace_resent_fields_write_driver(do_write, data, col, field);
1710 if (r != MAILIMF_NO_ERROR)
1711 return r;
1712 }
1713
1714 return MAILIMF_NO_ERROR;
1715}
1716
1717
1718static int
1719mailimf_trace_resent_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1720 struct mailimf_trace_resent_fields * field)
1721{
1722 int r;
1723
1724 if (field->return_path != NULL) {
1725 r = mailimf_return_write_driver(do_write, data, col, field->return_path);
1726 if (r != MAILIMF_NO_ERROR)
1727 return r;
1728 }
1729
1730 if (field->resent_fields != NULL) {
1731 r = mailimf_resent_fields_write_driver(do_write, data, col, field->resent_fields);
1732 if (r != MAILIMF_NO_ERROR)
1733 return r;
1734 }
1735
1736 return MAILIMF_NO_ERROR;
1737}
1738#endif
1739
1740static int mailimf_return_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1741 struct mailimf_return * return_path)
1742{
1743 int r;
1744
1745 r = mailimf_string_write_driver(do_write, data, col, "Return-Path: ", 13);
1746 if (r != MAILIMF_NO_ERROR)
1747 return r;
1748
1749 r = mailimf_path_write_driver(do_write, data, col, return_path->ret_path);
1750 if (r != MAILIMF_NO_ERROR)
1751 return r;
1752
1753 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1754 if (r != MAILIMF_NO_ERROR)
1755 return r;
1756#if 0
1757 * col = 0;
1758#endif
1759
1760 return MAILIMF_NO_ERROR;
1761}
1762
1763static int mailimf_path_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1764 struct mailimf_path * path)
1765{
1766 int r;
1767
1768 r = mailimf_string_write_driver(do_write, data, col, "<", 1);
1769 if (r != MAILIMF_NO_ERROR)
1770 return r;
1771
1772 r = mailimf_string_write_driver(do_write, data, col, path->pt_addr_spec,
1773 strlen(path->pt_addr_spec));
1774 if (r != MAILIMF_NO_ERROR)
1775 return r;
1776
1777 r = mailimf_string_write_driver(do_write, data, col, ">", 1);
1778 if (r != MAILIMF_NO_ERROR)
1779 return r;
1780
1781 return MAILIMF_NO_ERROR;
1782}
1783
1784#if 0
1785static int mailimf_resent_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1786 struct mailimf_resent_fields_list *
1787 resent_fields)
1788{
1789 clistiter * cur;
1790 int r;
1791
1792 for(cur = clist_begin(resent_fields->list) ; cur != NULL ; cur = cur->next) {
1793 struct mailimf_resent_field * field;
1794
1795 field = cur->data;
1796
1797 r = mailimf_resent_field_write_driver(do_write, data, col, field);
1798 if (r != MAILIMF_NO_ERROR)
1799 return r;
1800 }
1801
1802 return MAILIMF_NO_ERROR;
1803}
1804
1805
1806
1807static int mailimf_resent_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1808 struct mailimf_resent_field *
1809 resent_field)
1810{
1811 int r;
1812
1813 switch (resent_field->type) {
1814 case MAILIMF_RESENT_FIELD_DATE:
1815 r = mailimf_resent_date_write_driver(do_write, data, col, resent_field->resent_date);
1816 break;
1817
1818 case MAILIMF_RESENT_FIELD_FROM:
1819 r = mailimf_resent_from_write_driver(do_write, data, col, resent_field->resent_from);
1820 break;
1821
1822 case MAILIMF_RESENT_FIELD_SENDER:
1823 r = mailimf_resent_sender_write_driver(do_write, data, col, resent_field->resent_sender);
1824 break;
1825
1826 case MAILIMF_RESENT_FIELD_TO:
1827 r = mailimf_resent_to_write_driver(do_write, data, col, resent_field->resent_to);
1828 break;
1829
1830 case MAILIMF_RESENT_FIELD_CC:
1831 r = mailimf_resent_cc_write_driver(do_write, data, col, resent_field->resent_cc);
1832 break;
1833
1834 case MAILIMF_RESENT_FIELD_BCC:
1835 r = mailimf_resent_bcc_write_driver(do_write, data, col, resent_field->resent_bcc);
1836 break;
1837
1838 case MAILIMF_RESENT_FIELD_MSG_ID:
1839 r = mailimf_resent_msg_id_write_driver(do_write, data, col, resent_field->resent_msg_id);
1840 break;
1841 default:
1842 r = MAILIMF_ERROR_INVAL;
1843 break;
1844 }
1845
1846
1847 if (r != MAILIMF_NO_ERROR)
1848 return r;
1849
1850 return MAILIMF_NO_ERROR;
1851}
1852#endif
1853
1854static int mailimf_resent_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1855 struct mailimf_orig_date * date)
1856{
1857 int r;
1858
1859 r = mailimf_string_write_driver(do_write, data, col, "Resent-Date: ", 13);
1860 if (r != MAILIMF_NO_ERROR)
1861 return r;
1862
1863 r = mailimf_date_time_write_driver(do_write, data, col, date->dt_date_time);
1864 if (r != MAILIMF_NO_ERROR)
1865 return r;
1866
1867 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1868 if (r != MAILIMF_NO_ERROR)
1869 return r;
1870#if 0
1871 * col = 0;
1872#endif
1873
1874 return MAILIMF_NO_ERROR;
1875}
1876
1877static int mailimf_resent_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1878 struct mailimf_from * from)
1879{
1880 int r;
1881
1882 r = mailimf_string_write_driver(do_write, data, col, "Resent-From: ", 13);
1883 if (r != MAILIMF_NO_ERROR)
1884 return r;
1885
1886 r = mailimf_mailbox_list_write_driver(do_write, data, col, from->frm_mb_list);
1887 if (r != MAILIMF_NO_ERROR)
1888 return r;
1889
1890 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1891 if (r != MAILIMF_NO_ERROR)
1892 return r;
1893#if 0
1894 * col = 0;
1895#endif
1896
1897 return MAILIMF_NO_ERROR;
1898}
1899
1900static int mailimf_resent_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1901 struct mailimf_sender * sender)
1902{
1903 int r;
1904
1905 r = mailimf_string_write_driver(do_write, data, col, "Resent-Sender: ", 15);
1906 if (r != MAILIMF_NO_ERROR)
1907 return r;
1908
1909 r = mailimf_mailbox_write_driver(do_write, data, col, sender->snd_mb);
1910 if (r != MAILIMF_NO_ERROR)
1911 return r;
1912
1913 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1914 if (r != MAILIMF_NO_ERROR)
1915 return r;
1916#if 0
1917 * col = 0;
1918#endif
1919
1920 return MAILIMF_NO_ERROR;
1921}
1922
1923static int mailimf_resent_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1924 struct mailimf_to * to)
1925{
1926 int r;
1927
1928 r = mailimf_string_write_driver(do_write, data, col, "Resent-To: ", 11);
1929 if (r != MAILIMF_NO_ERROR)
1930 return r;
1931
1932 r = mailimf_address_list_write_driver(do_write, data, col, to->to_addr_list);
1933 if (r != MAILIMF_NO_ERROR)
1934 return r;
1935
1936 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1937 if (r != MAILIMF_NO_ERROR)
1938 return r;
1939#if 0
1940 * col = 0;
1941#endif
1942
1943 return MAILIMF_NO_ERROR;
1944}
1945
1946
1947static int mailimf_resent_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1948 struct mailimf_cc * cc)
1949{
1950 int r;
1951
1952 r = mailimf_string_write_driver(do_write, data, col, "Resent-Cc: ", 11);
1953 if (r != MAILIMF_NO_ERROR)
1954 return r;
1955
1956 r = mailimf_address_list_write_driver(do_write, data, col, cc->cc_addr_list);
1957 if (r != MAILIMF_NO_ERROR)
1958 return r;
1959
1960 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1961 if (r != MAILIMF_NO_ERROR)
1962 return r;
1963#if 0
1964 * col = 0;
1965#endif
1966
1967 return MAILIMF_NO_ERROR;
1968}
1969
1970
1971static int mailimf_resent_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1972 struct mailimf_bcc * bcc)
1973{
1974 int r;
1975
1976 r = mailimf_string_write_driver(do_write, data, col, "Resent-Bcc: ", 12);
1977 if (r != MAILIMF_NO_ERROR)
1978 return r;
1979
1980 if (bcc->bcc_addr_list != NULL) {
1981 r = mailimf_address_list_write_driver(do_write, data, col, bcc->bcc_addr_list);
1982 if (r != MAILIMF_NO_ERROR)
1983 return r;
1984 }
1985
1986 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
1987 if (r != MAILIMF_NO_ERROR)
1988 return r;
1989#if 0
1990 * col = 0;
1991#endif
1992
1993 return MAILIMF_NO_ERROR;
1994}
1995
1996
1997static int
1998mailimf_resent_msg_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1999 struct mailimf_message_id * message_id)
2000{
2001 int r;
2002
2003 r = mailimf_string_write_driver(do_write, data, col, "Resent-Message-ID: ", 19);
2004 if (r != MAILIMF_NO_ERROR)
2005 return r;
2006
2007 r = mailimf_string_write_driver(do_write, data, col, "<", 1);
2008 if (r != MAILIMF_NO_ERROR)
2009 return r;
2010
2011 r = mailimf_string_write_driver(do_write, data, col,
2012 message_id->mid_value, strlen(message_id->mid_value));
2013 if (r != MAILIMF_NO_ERROR)
2014 return r;
2015
2016 r = mailimf_string_write_driver(do_write, data, col, ">", 1);
2017 if (r != MAILIMF_NO_ERROR)
2018 return r;
2019
2020 r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2);
2021 if (r != MAILIMF_NO_ERROR)
2022 return r;
2023#if 0
2024 * col = 0;
2025#endif
2026
2027 return MAILIMF_NO_ERROR;
2028}