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