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