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