Fix CID 1491401 and 1491402: (possible) modulo by zero.
[claws.git] / src / plugins / mailmbox / mailimf_types_helper.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 #include "mailimf_types_helper.h"
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include <time.h>
37 #include <unistd.h>
38 #include <errno.h>
39
40 #include "mailimf.h"
41 #include "utils.h"
42
43 struct mailimf_mailbox_list *
44 mailimf_mailbox_list_new_empty()
45 {
46   clist * list;
47   struct mailimf_mailbox_list * mb_list;
48
49   list = clist_new();
50   if (list == NULL)
51     return NULL;
52
53   mb_list = mailimf_mailbox_list_new(list);
54   if (mb_list == NULL)
55     return NULL;
56
57   return mb_list;
58 }
59
60 int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list,
61                              struct mailimf_mailbox * mb)
62 {
63   int r;
64
65   r = clist_append(mailbox_list->mb_list, mb);
66   if (r < 0)
67     return MAILIMF_ERROR_MEMORY;
68
69   return MAILIMF_NO_ERROR;
70 }
71
72 int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list,
73                                    char * mb_str)
74 {
75   int r;
76   size_t cur_token;
77   struct mailimf_mailbox * mb;
78   int res;
79
80   cur_token = 0;
81   r = mailimf_mailbox_parse(mb_str, strlen(mb_str), &cur_token, &mb);
82   if (r != MAILIMF_NO_ERROR) {
83     res = r;
84     goto err;
85   }
86   
87   r = mailimf_mailbox_list_add(mailbox_list, mb);
88   if (r != MAILIMF_NO_ERROR) {
89     res = r;
90     goto free;
91   }
92
93   return MAILIMF_NO_ERROR;
94
95  free:
96   mailimf_mailbox_free(mb);
97  err:
98   return res;
99 }
100
101 int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list,
102                                 char * display_name, char * address)
103 {
104   int r;
105   struct mailimf_mailbox * mb;
106   int res;
107
108   mb = mailimf_mailbox_new(display_name, address);
109   if (mb == NULL) {
110     res = MAILIMF_ERROR_MEMORY;
111     goto err;
112   }
113   
114   r = mailimf_mailbox_list_add(mailbox_list, mb);
115   if (r != MAILIMF_NO_ERROR) {
116     res = r;
117     goto free;
118   }
119
120   return MAILIMF_NO_ERROR;
121
122  free:
123   mailimf_mailbox_free(mb);
124  err:
125   return res;
126 }
127
128
129
130 struct mailimf_address_list *
131 mailimf_address_list_new_empty()
132 {
133   clist * list;
134   struct mailimf_address_list * addr_list;
135
136   list = clist_new();
137   if (list == NULL)
138     return NULL;
139
140   addr_list = mailimf_address_list_new(list);
141   if (addr_list == NULL)
142     return NULL;
143
144   return addr_list;
145 }
146
147 int mailimf_address_list_add(struct mailimf_address_list * address_list,
148                              struct mailimf_address * addr)
149 {
150   int r;
151
152   r = clist_append(address_list->ad_list, addr);
153   if (r < 0)
154     return MAILIMF_ERROR_MEMORY;
155
156   return MAILIMF_NO_ERROR;
157 }
158
159 int mailimf_address_list_add_parse(struct mailimf_address_list * address_list,
160                                    char * addr_str)
161 {
162   int r;
163   size_t cur_token;
164   struct mailimf_address * addr;
165   int res;
166
167   cur_token = 0;
168   r = mailimf_address_parse(addr_str, strlen(addr_str), &cur_token, &addr);
169   if (r != MAILIMF_NO_ERROR) {
170     res = r;
171     goto err;
172   }
173   
174   r = mailimf_address_list_add(address_list, addr);
175   if (r != MAILIMF_NO_ERROR) {
176     res = r;
177     goto free;
178   }
179
180   return MAILIMF_NO_ERROR;
181
182  free:
183   mailimf_address_free(addr);
184  err:
185   return res;
186 }
187
188 int mailimf_address_list_add_mb(struct mailimf_address_list * address_list,
189                                 char * display_name, char * address)
190 {
191   int r;
192   struct mailimf_mailbox * mb;
193   struct mailimf_address * addr;
194   int res;
195
196   mb = mailimf_mailbox_new(display_name, address);
197   if (mb == NULL) {
198     res = MAILIMF_ERROR_MEMORY;
199     goto err;
200   }
201
202   addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
203   if (addr == NULL) {
204     res = MAILIMF_ERROR_MEMORY;
205     goto free_mb;
206   }
207
208   r = mailimf_address_list_add(address_list, addr);
209   if (r != MAILIMF_NO_ERROR) {
210     res = r;
211     goto free_addr;
212   }
213
214   return MAILIMF_NO_ERROR;
215
216  free_addr:
217   mailimf_address_free(addr);
218  free_mb:
219   mailimf_mailbox_free(mb);
220  err:
221   return res;
222 }
223
224
225 #if 0
226 struct mailimf_resent_fields_list *
227 mailimf_resent_fields_list_new_empty()
228 {
229   clist * list;
230   struct mailimf_resent_fields_list * rf_list;
231
232   list = clist_new();
233   if (list == NULL)
234     return NULL;
235
236   rf_list = mailimf_resent_fields_list_new(list);
237   if (rf_list == NULL)
238     return NULL;
239
240   return rf_list;
241 }
242
243 int mailimf_resent_fields_add(struct mailimf_resent_fields_list * fields,
244                               struct mailimf_resent_field * field)
245 {
246   int r;
247
248   r = clist_append(fields->list, field);
249   if (r < 0)
250     return MAILIMF_ERROR_MEMORY;
251   
252   return MAILIMF_NO_ERROR;
253 }
254 #endif
255
256
257 static void detach_free_common_fields(struct mailimf_orig_date * imf_date,
258                                       struct mailimf_from * imf_from,
259                                       struct mailimf_sender * imf_sender,
260                                       struct mailimf_to * imf_to,
261                                       struct mailimf_cc * imf_cc,
262                                       struct mailimf_bcc * imf_bcc,
263                                       struct mailimf_message_id * imf_msg_id)
264 {
265   if (imf_date != NULL) {
266     imf_date->dt_date_time = NULL;
267     mailimf_orig_date_free(imf_date);
268   }
269   if (imf_from != NULL) {
270     imf_from->frm_mb_list = NULL;
271     mailimf_from_free(imf_from);
272   }
273   if (imf_sender != NULL) {
274     imf_sender->snd_mb = NULL;
275     mailimf_sender_free(imf_sender);
276   }
277   if (imf_to != NULL) {
278     imf_to->to_addr_list = NULL;
279     mailimf_to_free(imf_to);
280   }
281   if (imf_cc != NULL) {
282     imf_cc->cc_addr_list = NULL;
283     mailimf_cc_free(imf_cc);
284   }
285   if (imf_bcc != NULL) {
286     imf_bcc->bcc_addr_list = NULL;
287     mailimf_bcc_free(imf_bcc);
288   }
289   if (imf_msg_id != NULL) {
290     imf_msg_id->mid_value = NULL;
291     mailimf_message_id_free(imf_msg_id);
292   }
293 }
294
295 static void detach_resent_field(struct mailimf_field * field)
296 {
297   field->fld_type = MAILIMF_FIELD_NONE;
298   mailimf_field_free(field);
299 }
300
301 int
302 mailimf_resent_fields_add_data(struct mailimf_fields * fields,
303     struct mailimf_date_time * resent_date,
304     struct mailimf_mailbox_list * resent_from,
305     struct mailimf_mailbox * resent_sender,
306     struct mailimf_address_list * resent_to,
307     struct mailimf_address_list * resent_cc,
308     struct mailimf_address_list * resent_bcc,
309     char * resent_msg_id)
310 {
311   struct mailimf_orig_date * imf_resent_date;
312   struct mailimf_from * imf_resent_from;
313   struct mailimf_sender * imf_resent_sender;
314   struct mailimf_to * imf_resent_to;
315   struct mailimf_cc * imf_resent_cc;
316   struct mailimf_bcc * imf_resent_bcc;
317   struct mailimf_message_id * imf_resent_msg_id;
318   struct mailimf_field * field;
319   int r;
320
321   imf_resent_date = NULL;
322   imf_resent_from = NULL;
323   imf_resent_sender = NULL;
324   imf_resent_to = NULL;
325   imf_resent_cc = NULL;
326   imf_resent_bcc = NULL;
327   imf_resent_msg_id = NULL;
328   field = NULL;
329
330   if (resent_date != NULL) {
331     imf_resent_date = mailimf_orig_date_new(resent_date);
332     if (imf_resent_date == NULL)
333       goto free;
334     field = mailimf_field_new(MAILIMF_FIELD_RESENT_DATE,
335         NULL /* return-path */,
336         imf_resent_date /* resent date */,
337         NULL /* resent from */,
338         NULL /* resent sender */,
339         NULL /* resent to */,
340         NULL /* resent cc */,
341         NULL /* resent bcc */,
342         NULL /* resent msg id */,
343         NULL /* date */,
344         NULL /* from */,
345         NULL /* sender */,
346         NULL /* reply-to */,
347         NULL /* to */,
348         NULL /* cc */,
349         NULL /* bcc */,
350         NULL /* message id */,
351         NULL /* in reply to */,
352         NULL /* references */,
353         NULL /* subject */,
354         NULL /* comments */,
355         NULL /* keywords */,
356         NULL /* optional field */);
357     if (field == NULL)
358       goto free;
359     r =  mailimf_fields_add(fields, field);
360     if (r != MAILIMF_NO_ERROR)
361       goto free_field;
362   }
363
364   if (resent_from != NULL) {
365     imf_resent_from = mailimf_from_new(resent_from);
366     if (imf_resent_from == NULL)
367       goto free_field;
368     field = mailimf_field_new(MAILIMF_FIELD_RESENT_FROM,
369         NULL /* return-path */,
370         NULL /* resent date */,
371         imf_resent_from /* resent from */,
372         NULL /* resent sender */,
373         NULL /* resent to */,
374         NULL /* resent cc */,
375         NULL /* resent bcc */,
376         NULL /* resent msg id */,
377         NULL /* date */,
378         NULL /* from */,
379         NULL /* sender */,
380         NULL /* reply-to */,
381         NULL /* to */,
382         NULL /* cc */,
383         NULL /* bcc */,
384         NULL /* message id */,
385         NULL /* in reply to */,
386         NULL /* references */,
387         NULL /* subject */,
388         NULL /* comments */,
389         NULL /* keywords */,
390         NULL /* optional field */);
391     if (field == NULL)
392       goto free;
393     r =  mailimf_fields_add(fields, field);
394     if (r != MAILIMF_NO_ERROR)
395       goto free_field;
396   }
397
398   if (resent_sender != NULL) {
399     imf_resent_sender = mailimf_sender_new(resent_sender);
400     if (imf_resent_sender == NULL)
401       goto free;
402     field = mailimf_field_new(MAILIMF_FIELD_RESENT_SENDER,
403         NULL /* return-path */,
404         NULL /* resent date */,
405         NULL /* resent from */,
406         imf_resent_sender /* resent sender */,
407         NULL /* resent to */,
408         NULL /* resent cc */,
409         NULL /* resent bcc */,
410         NULL /* resent msg id */,
411         NULL /* date */,
412         NULL /* from */,
413         NULL /* sender */,
414         NULL /* reply-to */,
415         NULL /* to */,
416         NULL /* cc */,
417         NULL /* bcc */,
418         NULL /* message id */,
419         NULL /* in reply to */,
420         NULL /* references */,
421         NULL /* subject */,
422         NULL /* comments */,
423         NULL /* keywords */,
424         NULL /* optional field */);
425     if (field == NULL)
426       goto free;
427     r =  mailimf_fields_add(fields, field);
428     if (r != MAILIMF_NO_ERROR)
429       goto free_field;
430   }
431
432   if (resent_to != NULL) {
433     imf_resent_to = mailimf_to_new(resent_to);
434     if (imf_resent_to == NULL)
435       goto free;
436     field = mailimf_field_new(MAILIMF_FIELD_RESENT_TO,
437         NULL /* return-path */,
438         NULL /* resent date */,
439         NULL /* resent from */,
440         NULL /* resent sender */,
441         imf_resent_to /* resent to */,
442         NULL /* resent cc */,
443         NULL /* resent bcc */,
444         NULL /* resent msg id */,
445         NULL /* date */,
446         NULL /* from */,
447         NULL /* sender */,
448         NULL /* reply-to */,
449         NULL /* to */,
450         NULL /* cc */,
451         NULL /* bcc */,
452         NULL /* message id */,
453         NULL /* in reply to */,
454         NULL /* references */,
455         NULL /* subject */,
456         NULL /* comments */,
457         NULL /* keywords */,
458         NULL /* optional field */);
459     if (field == NULL)
460       goto free;
461     r =  mailimf_fields_add(fields, field);
462     if (r != MAILIMF_NO_ERROR)
463       goto free_field;
464   }
465
466   if (resent_cc != NULL) {
467     imf_resent_cc = mailimf_cc_new(resent_cc);
468     if (imf_resent_cc == NULL)
469       goto free;
470     field = mailimf_field_new(MAILIMF_FIELD_RESENT_CC,
471         NULL /* return-path */,
472         NULL /* resent date */,
473         NULL /* resent from */,
474         NULL /* resent sender */,
475         NULL /* resent to */,
476         imf_resent_cc /* resent cc */,
477         NULL /* resent bcc */,
478         NULL /* resent msg id */,
479         NULL /* date */,
480         NULL /* from */,
481         NULL /* sender */,
482         NULL /* reply-to */,
483         NULL /* to */,
484         NULL /* cc */,
485         NULL /* bcc */,
486         NULL /* message id */,
487         NULL /* in reply to */,
488         NULL /* references */,
489         NULL /* subject */,
490         NULL /* comments */,
491         NULL /* keywords */,
492         NULL /* optional field */);
493     if (field == NULL)
494       goto free;
495     r =  mailimf_fields_add(fields, field);
496     if (r != MAILIMF_NO_ERROR)
497       goto free_field;
498   }
499
500   if (resent_bcc != NULL) {
501     imf_resent_bcc = mailimf_bcc_new(resent_bcc);
502     if (imf_resent_bcc == NULL)
503       goto free;
504     field = mailimf_field_new(MAILIMF_FIELD_RESENT_BCC,
505         NULL /* return-path */,
506         NULL /* resent date */,
507         NULL /* resent from */,
508         NULL /* resent sender */,
509         NULL /* resent to */,
510         NULL /* resent cc */,
511         imf_resent_bcc /* resent bcc */,
512         NULL /* resent msg id */,
513         NULL /* date */,
514         NULL /* from */,
515         NULL /* sender */,
516         NULL /* reply-to */,
517         NULL /* to */,
518         NULL /* cc */,
519         NULL /* bcc */,
520         NULL /* message id */,
521         NULL /* in reply to */,
522         NULL /* references */,
523         NULL /* subject */,
524         NULL /* comments */,
525         NULL /* keywords */,
526         NULL /* optional field */);
527     if (field == NULL)
528       goto free;
529     r =  mailimf_fields_add(fields, field);
530     if (r != MAILIMF_NO_ERROR)
531       goto free_field;
532   }
533
534   if (resent_msg_id != NULL) {
535     imf_resent_msg_id = mailimf_message_id_new(resent_msg_id);
536     if (imf_resent_msg_id == NULL)
537       goto free;
538     field = mailimf_field_new(MAILIMF_FIELD_RESENT_MSG_ID,
539         NULL /* return-path */,
540         NULL /* resent date */,
541         NULL /* resent from */,
542         NULL /* resent sender */,
543         NULL /* resent to */,
544         NULL /* resent cc */,
545         NULL /* resent bcc */,
546         imf_resent_msg_id /* resent msg id */,
547         NULL /* date */,
548         NULL /* from */,
549         NULL /* sender */,
550         NULL /* reply-to */,
551         NULL /* to */,
552         NULL /* cc */,
553         NULL /* bcc */,
554         NULL /* message id */,
555         NULL /* in reply to */,
556         NULL /* references */,
557         NULL /* subject */,
558         NULL /* comments */,
559         NULL /* keywords */,
560         NULL /* optional field */);
561     if (field == NULL)
562       goto free;
563     r =  mailimf_fields_add(fields, field);
564     if (r != MAILIMF_NO_ERROR)
565       goto free_field;
566   }
567
568   return MAILIMF_NO_ERROR;
569
570  free_field:
571   if (field != NULL) {
572     detach_resent_field(field);
573   }
574  free:
575   detach_free_common_fields(imf_resent_date,
576                             imf_resent_from,
577                             imf_resent_sender,
578                             imf_resent_to,
579                             imf_resent_cc,
580                             imf_resent_bcc,
581                             imf_resent_msg_id);
582   return MAILIMF_ERROR_MEMORY;
583 }
584
585 struct mailimf_fields *
586 mailimf_resent_fields_new_with_data_all(struct mailimf_date_time *
587     resent_date,
588     struct mailimf_mailbox_list *
589     resent_from,
590     struct mailimf_mailbox *
591     resent_sender,
592     struct mailimf_address_list *
593     resent_to,
594     struct mailimf_address_list *
595     resent_cc,
596     struct mailimf_address_list *
597     resent_bcc,
598     char * resent_msg_id)
599 {
600   struct mailimf_fields * resent_fields;
601   int r;
602
603   resent_fields = mailimf_fields_new_empty();
604   if (resent_fields == NULL)
605     goto err;
606
607   r = mailimf_resent_fields_add_data(resent_fields,
608       resent_date, resent_from,
609       resent_sender, resent_to,
610       resent_cc, resent_bcc,
611       resent_msg_id);
612   if (r != MAILIMF_NO_ERROR)
613     goto free;
614
615   return resent_fields;
616
617  free:
618   mailimf_fields_free(resent_fields);
619  err:
620   return NULL;
621 }
622
623
624 struct mailimf_fields *
625 mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from,
626     struct mailimf_mailbox * sender,
627     struct mailimf_address_list * to,
628     struct mailimf_address_list * cc,
629     struct mailimf_address_list * bcc)
630 {
631   struct mailimf_date_time * date;
632   char * msg_id;
633   struct mailimf_fields * fields;
634
635   date = mailimf_get_current_date();
636   if (date == NULL)
637     goto err;
638
639   msg_id = mailimf_get_message_id();
640   if (msg_id == NULL)
641     goto free_date;
642
643   fields = mailimf_resent_fields_new_with_data_all(date,
644       from, sender, to, cc, bcc, msg_id);
645   if (fields == NULL)
646     goto free_msg_id;
647
648   return fields;
649
650  free_msg_id:
651   free(msg_id);
652  free_date:
653   mailimf_date_time_free(date);
654  err:
655   return NULL;
656 }
657
658
659 struct mailimf_fields *
660 mailimf_fields_new_empty(void)
661 {
662   clist * list;
663   struct mailimf_fields * fields_list;
664
665   list = clist_new();
666   if (list == NULL)
667     return NULL;
668
669   fields_list = mailimf_fields_new(list);
670   if (fields_list == NULL)
671     return NULL;
672
673   return fields_list;
674 }
675
676 int mailimf_fields_add(struct mailimf_fields * fields,
677                        struct mailimf_field * field)
678 {
679   int r;
680
681   r = clist_append(fields->fld_list, field);
682   if (r < 0)
683     return MAILIMF_ERROR_MEMORY;
684   
685   return MAILIMF_NO_ERROR;
686 }
687
688 static void detach_free_fields(struct mailimf_orig_date * date,
689                                struct mailimf_from * from,
690                                struct mailimf_sender * sender,
691                                struct mailimf_reply_to * reply_to,
692                                struct mailimf_to * to,
693                                struct mailimf_cc * cc,
694                                struct mailimf_bcc * bcc,
695                                struct mailimf_message_id * msg_id,
696                                struct mailimf_in_reply_to * in_reply_to,
697                                struct mailimf_references * references,
698                                struct mailimf_subject * subject)
699 {
700   detach_free_common_fields(date,
701       from,
702       sender,
703       to,
704       cc,
705       bcc,
706       msg_id);
707
708   if (reply_to != NULL) {
709     reply_to->rt_addr_list = NULL;
710     mailimf_reply_to_free(reply_to);
711   }
712
713   if (in_reply_to != NULL) {
714     in_reply_to->mid_list = NULL;
715     mailimf_in_reply_to_free(in_reply_to);
716   }
717
718   if (references != NULL) {
719     references->mid_list = NULL;
720     mailimf_references_free(references);
721   }
722
723   if (subject != NULL) {
724     subject->sbj_value = NULL;
725     mailimf_subject_free(subject);
726   }
727 }
728
729
730 static void detach_field(struct mailimf_field * field)
731 {
732   field->fld_type = MAILIMF_FIELD_NONE;
733   mailimf_field_free(field);
734 }
735
736 int mailimf_fields_add_data(struct mailimf_fields * fields,
737                             struct mailimf_date_time * date,
738                             struct mailimf_mailbox_list * from,
739                             struct mailimf_mailbox * sender,
740                             struct mailimf_address_list * reply_to,
741                             struct mailimf_address_list * to,
742                             struct mailimf_address_list * cc,
743                             struct mailimf_address_list * bcc,
744                             char * msg_id,
745                             clist * in_reply_to,
746                             clist * references,
747                             char * subject)
748 {
749   struct mailimf_orig_date * imf_date;
750   struct mailimf_from * imf_from;
751   struct mailimf_sender * imf_sender;
752   struct mailimf_reply_to * imf_reply_to;
753   struct mailimf_to * imf_to;
754   struct mailimf_cc * imf_cc;
755   struct mailimf_bcc * imf_bcc;
756   struct mailimf_message_id * imf_msg_id;
757   struct mailimf_references * imf_references;
758   struct mailimf_in_reply_to * imf_in_reply_to;
759   struct mailimf_subject * imf_subject;
760   struct mailimf_field * field;
761   int r;
762
763   imf_date = NULL;
764   imf_from = NULL;
765   imf_sender = NULL;
766   imf_reply_to = NULL;
767   imf_to = NULL;
768   imf_cc = NULL;
769   imf_bcc = NULL;
770   imf_msg_id = NULL;
771   imf_references = NULL;
772   imf_in_reply_to = NULL;
773   imf_subject =NULL;
774   field = NULL;
775
776   if (date != NULL) {
777     imf_date = mailimf_orig_date_new(date);
778     if (imf_date == NULL)
779       goto free;
780     field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE,
781         NULL /* return-path */,
782         NULL /* resent date */,
783         NULL /* resent from */,
784         NULL /* resent sender */,
785         NULL /* resent to */,
786         NULL /* resent cc */,
787         NULL /* resent bcc */,
788         NULL /* resent msg id */,
789         imf_date /* date */,
790         NULL /* from */,
791         NULL /* sender */,
792         NULL /* reply-to */,
793         NULL /* to */,
794         NULL /* cc */,
795         NULL /* bcc */,
796         NULL /* message id */,
797         NULL /* in reply to */,
798         NULL /* references */,
799         NULL /* subject */,
800         NULL /* comments */,
801         NULL /* keywords */,
802         NULL /* optional field */);
803     if (field == NULL)
804       goto free;
805     r =  mailimf_fields_add(fields, field);
806     if (r != MAILIMF_NO_ERROR)
807       goto free_field;
808   }
809
810   if (from != NULL) {
811     imf_from = mailimf_from_new(from);
812     if (imf_from == NULL)
813       goto free_field;
814     field = mailimf_field_new(MAILIMF_FIELD_FROM,
815         NULL /* return-path */,
816         NULL /* resent date */,
817         NULL /* resent from */,
818         NULL /* resent sender */,
819         NULL /* resent to */,
820         NULL /* resent cc */,
821         NULL /* resent bcc */,
822         NULL /* resent msg id */,
823         NULL /* date */,
824         imf_from /* from */,
825         NULL /* sender */,
826         NULL /* reply-to */,
827         NULL /* to */,
828         NULL /* cc */,
829         NULL /* bcc */,
830         NULL /* message id */,
831         NULL /* in reply to */,
832         NULL /* references */,
833         NULL /* subject */,
834         NULL /* comments */,
835         NULL /* keywords */,
836         NULL /* optional field */);
837     if (field == NULL)
838       goto free;
839     r =  mailimf_fields_add(fields, field);
840     if (r != MAILIMF_NO_ERROR)
841       goto free_field;
842   }
843
844   if (sender != NULL) {
845     imf_sender = mailimf_sender_new(sender);
846     if (imf_sender == NULL)
847       goto free;
848     field = mailimf_field_new(MAILIMF_FIELD_SENDER,
849         NULL /* return-path */,
850         NULL /* resent date */,
851         NULL /* resent from */,
852         NULL /* resent sender */,
853         NULL /* resent to */,
854         NULL /* resent cc */,
855         NULL /* resent bcc */,
856         NULL /* resent msg id */,
857         NULL /* date */,
858         NULL /* from */,
859         imf_sender /* sender */,
860         NULL /* reply-to */,
861         NULL /* to */,
862         NULL /* cc */,
863         NULL /* bcc */,
864         NULL /* message id */,
865         NULL /* in reply to */,
866         NULL /* references */,
867         NULL /* subject */,
868         NULL /* comments */,
869         NULL /* keywords */,
870         NULL /* optional field */);
871     if (field == NULL)
872       goto free;
873     r =  mailimf_fields_add(fields, field);
874     if (r != MAILIMF_NO_ERROR)
875       goto free_field;
876   }
877
878   if (reply_to != NULL) {
879     imf_reply_to = mailimf_reply_to_new(reply_to);
880     if (imf_reply_to == NULL)
881       goto free;
882     field = mailimf_field_new(MAILIMF_FIELD_REPLY_TO,
883         NULL /* return-path */,
884         NULL /* resent date */,
885         NULL /* resent from */,
886         NULL /* resent sender */,
887         NULL /* resent to */,
888         NULL /* resent cc */,
889         NULL /* resent bcc */,
890         NULL /* resent msg id */,
891         NULL /* date */,
892         NULL /* from */,
893         NULL /* sender */,
894         imf_reply_to /* reply-to */,
895         NULL /* to */,
896         NULL /* cc */,
897         NULL /* bcc */,
898         NULL /* message id */,
899         NULL /* in reply to */,
900         NULL /* references */,
901         NULL /* subject */,
902         NULL /* comments */,
903         NULL /* keywords */,
904         NULL /* optional field */);
905     if (field == NULL)
906       goto free;
907     r =  mailimf_fields_add(fields, field);
908     if (r != MAILIMF_NO_ERROR)
909       goto free_field;
910   }
911
912   if (to != NULL) {
913     imf_to = mailimf_to_new(to);
914     if (imf_to == NULL)
915       goto free;
916     field = mailimf_field_new(MAILIMF_FIELD_TO,
917         NULL /* return-path */,
918         NULL /* resent date */,
919         NULL /* resent from */,
920         NULL /* resent sender */,
921         NULL /* resent to */,
922         NULL /* resent cc */,
923         NULL /* resent bcc */,
924         NULL /* resent msg id */,
925         NULL /* date */,
926         NULL /* from */,
927         NULL /* sender */,
928         NULL /* reply-to */,
929         imf_to /* to */,
930         NULL /* cc */,
931         NULL /* bcc */,
932         NULL /* message id */,
933         NULL /* in reply to */,
934         NULL /* references */,
935         NULL /* subject */,
936         NULL /* comments */,
937         NULL /* keywords */,
938         NULL /* optional field */);
939     if (field == NULL)
940       goto free;
941     r =  mailimf_fields_add(fields, field);
942     if (r != MAILIMF_NO_ERROR)
943       goto free_field;
944   }
945
946   if (cc != NULL) {
947     imf_cc = mailimf_cc_new(cc);
948     if (imf_cc == NULL)
949       goto free;
950     field = mailimf_field_new(MAILIMF_FIELD_CC,
951         NULL /* return-path */,
952         NULL /* resent date */,
953         NULL /* resent from */,
954         NULL /* resent sender */,
955         NULL /* resent to */,
956         NULL /* resent cc */,
957         NULL /* resent bcc */,
958         NULL /* resent msg id */,
959         NULL /* date */,
960         NULL /* from */,
961         NULL /* sender */,
962         NULL /* reply-to */,
963         NULL /* to */,
964         imf_cc /* cc */,
965         NULL /* bcc */,
966         NULL /* message id */,
967         NULL /* in reply to */,
968         NULL /* references */,
969         NULL /* subject */,
970         NULL /* comments */,
971         NULL /* keywords */,
972         NULL /* optional field */);
973     if (field == NULL)
974       goto free;
975     r =  mailimf_fields_add(fields, field);
976     if (r != MAILIMF_NO_ERROR)
977       goto free_field;
978   }
979
980   if (bcc != NULL) {
981     imf_bcc = mailimf_bcc_new(bcc);
982     if (imf_bcc == NULL)
983       goto free;
984     field = mailimf_field_new(MAILIMF_FIELD_BCC,
985         NULL /* return-path */,
986         NULL /* resent date */,
987         NULL /* resent from */,
988         NULL /* resent sender */,
989         NULL /* resent to */,
990         NULL /* resent cc */,
991         NULL /* resent bcc */,
992         NULL /* resent msg id */,
993         NULL /* date */,
994         NULL /* from */,
995         NULL /* sender */,
996         NULL /* reply-to */,
997         NULL /* to */,
998         NULL /* cc */,
999         imf_bcc /* bcc */,
1000         NULL /* message id */,
1001         NULL /* in reply to */,
1002         NULL /* references */,
1003         NULL /* subject */,
1004         NULL /* comments */,
1005         NULL /* keywords */,
1006         NULL /* optional field */);
1007     if (field == NULL)
1008       goto free;
1009     r =  mailimf_fields_add(fields, field);
1010     if (r != MAILIMF_NO_ERROR)
1011       goto free_field;
1012   }
1013
1014   if (msg_id != NULL) {
1015     imf_msg_id = mailimf_message_id_new(msg_id);
1016     if (imf_msg_id == NULL)
1017       goto free;
1018     field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID,
1019         NULL /* return-path */,
1020         NULL /* resent date */,
1021         NULL /* resent from */,
1022         NULL /* resent sender */,
1023         NULL /* resent to */,
1024         NULL /* resent cc */,
1025         NULL /* resent bcc */,
1026         NULL /* resent msg id */,
1027         NULL /* date */,
1028         NULL /* from */,
1029         NULL /* sender */,
1030         NULL /* reply-to */,
1031         NULL /* to */,
1032         NULL /* cc */,
1033         NULL /* bcc */,
1034         imf_msg_id /* message id */,
1035         NULL /* in reply to */,
1036         NULL /* references */,
1037         NULL /* subject */,
1038         NULL /* comments */,
1039         NULL /* keywords */,
1040         NULL /* optional field */);
1041     if (field == NULL)
1042       goto free;
1043     r =  mailimf_fields_add(fields, field);
1044     if (r != MAILIMF_NO_ERROR)
1045       goto free_field;
1046   }
1047
1048   if (in_reply_to != NULL) {
1049     imf_in_reply_to = mailimf_in_reply_to_new(in_reply_to);
1050     if (imf_in_reply_to == NULL)
1051       goto free;
1052     field = mailimf_field_new(MAILIMF_FIELD_IN_REPLY_TO,
1053         NULL /* return-path */,
1054         NULL /* resent date */,
1055         NULL /* resent from */,
1056         NULL /* resent sender */,
1057         NULL /* resent to */,
1058         NULL /* resent cc */,
1059         NULL /* resent bcc */,
1060         NULL /* resent msg id */,
1061         NULL /* date */,
1062         NULL /* from */,
1063         NULL /* sender */,
1064         NULL /* reply-to */,
1065         NULL /* to */,
1066         NULL /* cc */,
1067         NULL /* bcc */,
1068         NULL /* message id */,
1069         imf_in_reply_to /* in reply to */,
1070         NULL /* references */,
1071         NULL /* subject */,
1072         NULL /* comments */,
1073         NULL /* keywords */,
1074         NULL /* optional field */);
1075     if (field == NULL)
1076       goto free;
1077     r =  mailimf_fields_add(fields, field);
1078     if (r != MAILIMF_NO_ERROR)
1079       goto free_field;
1080   }
1081
1082   if (references != NULL) {
1083     imf_references = mailimf_references_new(references);
1084     if (imf_references == NULL)
1085       goto free;
1086     field = mailimf_field_new(MAILIMF_FIELD_REFERENCES,
1087         NULL /* return-path */,
1088         NULL /* resent date */,
1089         NULL /* resent from */,
1090         NULL /* resent sender */,
1091         NULL /* resent to */,
1092         NULL /* resent cc */,
1093         NULL /* resent bcc */,
1094         NULL /* resent msg id */,
1095         NULL /* date */,
1096         NULL /* from */,
1097         NULL /* sender */,
1098         NULL /* reply-to */,
1099         NULL /* to */,
1100         NULL /* cc */,
1101         NULL /* bcc */,
1102         NULL /* message id */,
1103         NULL /* in reply to */,
1104         imf_references /* references */,
1105         NULL /* subject */,
1106         NULL /* comments */,
1107         NULL /* keywords */,
1108         NULL /* optional field */);
1109     if (field == NULL)
1110       goto free;
1111     r =  mailimf_fields_add(fields, field);
1112     if (r != MAILIMF_NO_ERROR)
1113       goto free_field;
1114   }
1115
1116   if (subject != NULL) {
1117     imf_subject = mailimf_subject_new(subject);
1118     if (imf_subject == NULL)
1119       goto free;
1120     field = mailimf_field_new(MAILIMF_FIELD_SUBJECT,
1121         NULL /* return-path */,
1122         NULL /* resent date */,
1123         NULL /* resent from */,
1124         NULL /* resent sender */,
1125         NULL /* resent to */,
1126         NULL /* resent cc */,
1127         NULL /* resent bcc */,
1128         NULL /* resent msg id */,
1129         NULL /* date */,
1130         NULL /* from */,
1131         NULL /* sender */,
1132         NULL /* reply-to */,
1133         NULL /* to */,
1134         NULL /* cc */,
1135         NULL /* bcc */,
1136         NULL /* message id */,
1137         NULL /* in reply to */,
1138         NULL /* references */,
1139         imf_subject /* subject */,
1140         NULL /* comments */,
1141         NULL /* keywords */,
1142         NULL /* optional field */);
1143     if (field == NULL)
1144       goto free;
1145     r =  mailimf_fields_add(fields, field);
1146     if (r != MAILIMF_NO_ERROR)
1147       goto free_field;
1148   }
1149
1150   return MAILIMF_NO_ERROR;
1151
1152  free_field:
1153   if (field != NULL) {
1154     detach_field(field);
1155   }
1156  free:
1157   detach_free_fields(imf_date,
1158                      imf_from,
1159                      imf_sender,
1160                      imf_reply_to,
1161                      imf_to,
1162                      imf_cc,
1163                      imf_bcc,
1164                      imf_msg_id,
1165                      imf_in_reply_to,
1166                      imf_references,
1167                      imf_subject);
1168
1169   return MAILIMF_ERROR_MEMORY;
1170 }
1171
1172 struct mailimf_fields *
1173 mailimf_fields_new_with_data_all(struct mailimf_date_time * date,
1174                                  struct mailimf_mailbox_list * from,
1175                                  struct mailimf_mailbox * sender,
1176                                  struct mailimf_address_list * reply_to,
1177                                  struct mailimf_address_list * to,
1178                                  struct mailimf_address_list * cc,
1179                                  struct mailimf_address_list * bcc,
1180                                  char * message_id,
1181                                  clist * in_reply_to,
1182                                  clist * references,
1183                                  char * subject)
1184 {
1185   struct mailimf_fields * fields;
1186   int r;
1187
1188   fields = mailimf_fields_new_empty();
1189   if (fields == NULL)
1190     goto err;
1191
1192   r = mailimf_fields_add_data(fields,
1193                               date,
1194                               from,
1195                               sender,
1196                               reply_to,
1197                               to,
1198                               cc,
1199                               bcc,
1200                               message_id,
1201                               in_reply_to,
1202                               references,
1203                               subject);
1204   if (r != MAILIMF_NO_ERROR)
1205     goto free;
1206
1207   return fields;
1208
1209  free:
1210   mailimf_fields_free(fields);
1211  err:
1212   return NULL;
1213 }
1214
1215 struct mailimf_fields *
1216 mailimf_fields_new_with_data(struct mailimf_mailbox_list * from,
1217                              struct mailimf_mailbox * sender,
1218                              struct mailimf_address_list * reply_to,
1219                              struct mailimf_address_list * to,
1220                              struct mailimf_address_list * cc,
1221                              struct mailimf_address_list * bcc,
1222                              clist * in_reply_to,
1223                              clist * references,
1224                              char * subject)
1225 {
1226   struct mailimf_date_time * date;
1227   char * msg_id;
1228   struct mailimf_fields * fields;
1229
1230   date = mailimf_get_current_date();
1231   if (date == NULL)
1232     goto err;
1233
1234   msg_id = mailimf_get_message_id();
1235   if (msg_id == NULL)
1236     goto free_date;
1237
1238   fields = mailimf_fields_new_with_data_all(date,
1239                                             from, sender, reply_to,
1240                                             to, cc, bcc,
1241                                             msg_id,
1242                                             in_reply_to, references,
1243                                             subject);
1244   if (fields == NULL)
1245     goto free_msg_id;
1246
1247   return fields;
1248
1249  free_msg_id:
1250   free(msg_id);
1251  free_date:
1252   mailimf_date_time_free(date);
1253  err:
1254   return NULL;
1255 }
1256
1257
1258
1259 #define MAX_MESSAGE_ID 512
1260
1261 char * mailimf_get_message_id(void)
1262 {
1263   char id[MAX_MESSAGE_ID];
1264   time_t now;
1265   char name[HOST_NAME_MAX];
1266   long value;
1267         int ret;
1268
1269   now = time(NULL);
1270   value = random();
1271
1272         /* It's unlikely that HOST_NAME_MAX goes above 64, but let's
1273          * leave a generous reserve for the hostname in the message
1274          * id string. */
1275   if (HOST_NAME_MAX > MAX_MESSAGE_ID - 64 ||
1276                         (ret = gethostname(name, HOST_NAME_MAX)) != 0) {
1277                 if (ret != 0)
1278                         perror("gethostname");
1279                 strncpy(name, "unknown", HOST_NAME_MAX);
1280         }
1281
1282   snprintf(id, MAX_MESSAGE_ID, "etPan.%llx.%lx.%x@%s",
1283            (long long)now, value, getpid(), name);
1284
1285   return strdup(id);
1286 }
1287
1288
1289
1290 static time_t mkgmtime(struct tm * tmp);
1291
1292
1293 struct mailimf_date_time * mailimf_get_current_date(void)
1294 {
1295   struct tm gmt;
1296   struct tm lt;
1297   int off;
1298   time_t now;
1299   struct mailimf_date_time * date_time;
1300
1301   now = time(NULL);
1302
1303   if (gmtime_r(&now, &gmt) == NULL)
1304     return NULL;
1305
1306   if (localtime_r(&now, &lt) == NULL)
1307     return NULL;
1308
1309   off = (mkgmtime(&lt) - mkgmtime(&gmt)) / (60 * 60) * 100;
1310
1311   date_time = mailimf_date_time_new(lt.tm_mday, lt.tm_mon + 1, lt.tm_year + 1900,
1312                                     lt.tm_hour, lt.tm_min, lt.tm_sec,
1313                                     off);
1314
1315   return date_time;
1316 }
1317
1318
1319
1320 /* mkgmtime.c - make time corresponding to a GMT timeval struct
1321  $Id$
1322  
1323  * Copyright (c) 1998-2000 Carnegie Mellon University.  All rights reserved.
1324  *
1325  * Redistribution and use in source and binary forms, with or without
1326  * modification, are permitted provided that the following conditions
1327  * are met:
1328  *
1329  * 1. Redistributions of source code must retain the above copyright
1330  *    notice, this list of conditions and the following disclaimer. 
1331  *
1332  * 2. Redistributions in binary form must reproduce the above copyright
1333  *    notice, this list of conditions and the following disclaimer in
1334  *    the documentation and/or other materials provided with the
1335  *    distribution.
1336  *
1337  * 3. The name "Carnegie Mellon University" must not be used to
1338  *    endorse or promote products derived from this software without
1339  *    prior written permission. For permission or any other legal
1340  *    details, please contact  
1341  *      Office of Technology Transfer
1342  *      Carnegie Mellon University
1343  *      5000 Forbes Avenue
1344  *      Pittsburgh, PA  15213-3890
1345  *      (412) 268-4387, fax: (412) 268-7395
1346  *      tech-transfer@andrew.cmu.edu
1347  *
1348  * 4. Redistributions of any form whatsoever must retain the following
1349  *    acknowledgment:
1350  *    "This product includes software developed by Computing Services
1351  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
1352  *
1353  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
1354  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1355  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
1356  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1357  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
1358  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
1359  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1360  *
1361  *
1362  */
1363 /*
1364  * Copyright (c) 1987, 1989, 1993
1365  *      The Regents of the University of California.  All rights reserved.
1366  *
1367  * This code is derived from software contributed to Berkeley by
1368  * Arthur David Olson of the National Cancer Institute.
1369  *
1370  * Redistribution and use in source and binary forms, with or without
1371  * modification, are permitted provided that the following conditions
1372  * are met:
1373  * 1. Redistributions of source code must retain the above copyright
1374  *    notice, this list of conditions and the following disclaimer.
1375  * 2. Redistributions in binary form must reproduce the above copyright
1376  *    notice, this list of conditions and the following disclaimer in the
1377  *    documentation and/or other materials provided with the distribution.
1378  * 3. All advertising materials mentioning features or use of this software
1379  *    must display the following acknowledgement:
1380  *      This product includes software developed by the University of
1381  *      California, Berkeley and its contributors.
1382  * 4. Neither the name of the University nor the names of its contributors
1383  *    may be used to endorse or promote products derived from this software
1384  *    without specific prior written permission.
1385  *
1386  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1387  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1388  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1389  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1390  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1391  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1392  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1393  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1394  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1395  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1396  * SUCH DAMAGE.
1397  */
1398
1399 /*
1400 ** Adapted from code provided by Robert Elz, who writes:
1401 **      The "best" way to do mktime I think is based on an idea of Bob
1402 **      Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
1403 **      It does a binary search of the time_t space.  Since time_t's are
1404 **      just 32 bits, its a max of 32 iterations (even at 64 bits it
1405 **      would still be very reasonable).
1406 */
1407
1408 /*
1409   adapted for libEtPan! by DINH V. Hoa
1410 */
1411
1412 #ifndef WRONG
1413 #define WRONG   (-1)
1414 #endif /* !defined WRONG */
1415
1416 static int tmcomp(struct tm * atmp, struct tm * btmp)
1417 {
1418   register int  result;
1419   
1420   if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
1421       (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1422       (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1423       (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1424       (result = (atmp->tm_min - btmp->tm_min)) == 0)
1425     result = atmp->tm_sec - btmp->tm_sec;
1426   return result;
1427 }
1428
1429 static time_t mkgmtime(struct tm * tmp)
1430 {
1431   register int                  dir;
1432   register int                  bits;
1433   register int                  saved_seconds;
1434   time_t                                t;
1435   struct tm                     yourtm, *mytm, buft;
1436   
1437   yourtm = *tmp;
1438   saved_seconds = yourtm.tm_sec;
1439   yourtm.tm_sec = 0;
1440   /*
1441   ** Calculate the number of magnitude bits in a time_t
1442   ** (this works regardless of whether time_t is
1443   ** signed or unsigned, though lint complains if unsigned).
1444   */
1445   for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
1446     ;
1447   /*
1448   ** If time_t is signed, then 0 is the median value,
1449   ** if time_t is unsigned, then 1 << bits is median.
1450   */
1451   t = (t < 0) ? 0 : ((time_t) 1 << bits);
1452   for ( ; ; ) {
1453     mytm = gmtime_r(&t, &buft);
1454     dir = tmcomp(mytm, &yourtm);
1455     if (dir != 0) {
1456       if (bits-- < 0)
1457         return WRONG;
1458       if (bits < 0)
1459         --t;
1460       else if (dir > 0)
1461         t -= (time_t) 1 << bits;
1462       else      t += (time_t) 1 << bits;
1463       continue;
1464     }
1465     break;
1466   }
1467   t += saved_seconds;
1468   return t;
1469 }
1470
1471
1472
1473
1474
1475
1476
1477 void mailimf_single_fields_init(struct mailimf_single_fields * single_fields,
1478                                 struct mailimf_fields * fields)
1479 {
1480   clistiter * cur;
1481
1482   memset(single_fields, 0, sizeof(struct mailimf_single_fields));
1483
1484   cur = clist_begin(fields->fld_list);
1485   while (cur != NULL) {
1486     struct mailimf_field * field;
1487
1488     field = clist_content(cur);
1489
1490     switch (field->fld_type) {
1491     case MAILIMF_FIELD_ORIG_DATE:
1492       if (single_fields->fld_orig_date == NULL)
1493         single_fields->fld_orig_date = field->fld_data.fld_orig_date;
1494       cur = clist_next(cur);
1495       break;
1496     case MAILIMF_FIELD_FROM:
1497       if (single_fields->fld_from == NULL) {
1498         single_fields->fld_from = field->fld_data.fld_from;
1499         cur = clist_next(cur);
1500       }
1501       else {
1502         clist_concat(single_fields->fld_from->frm_mb_list->mb_list,
1503                      field->fld_data.fld_from->frm_mb_list->mb_list);
1504         mailimf_field_free(field);
1505         cur = clist_delete(fields->fld_list, cur);
1506       }
1507       break;
1508     case MAILIMF_FIELD_SENDER:
1509       if (single_fields->fld_sender == NULL)
1510         single_fields->fld_sender = field->fld_data.fld_sender;
1511       cur = clist_next(cur);
1512       break;
1513     case MAILIMF_FIELD_REPLY_TO:
1514       if (single_fields->fld_reply_to == NULL) {
1515         single_fields->fld_reply_to = field->fld_data.fld_reply_to;
1516         cur = clist_next(cur);
1517       }
1518       else {
1519         clist_concat(single_fields->fld_reply_to->rt_addr_list->ad_list,
1520                      field->fld_data.fld_reply_to->rt_addr_list->ad_list);
1521         mailimf_field_free(field);
1522         cur = clist_delete(fields->fld_list, cur);
1523       }
1524       break;
1525     case MAILIMF_FIELD_TO:
1526       if (single_fields->fld_to == NULL) {
1527         single_fields->fld_to = field->fld_data.fld_to;
1528         cur = clist_next(cur);
1529       }
1530       else {
1531         clist_concat(single_fields->fld_to->to_addr_list->ad_list,
1532                      field->fld_data.fld_to->to_addr_list->ad_list);
1533         mailimf_field_free(field);
1534         cur = clist_delete(fields->fld_list, cur);
1535       }
1536       break;
1537     case MAILIMF_FIELD_CC:
1538       if (single_fields->fld_cc == NULL) {
1539         single_fields->fld_cc = field->fld_data.fld_cc;
1540         cur = clist_next(cur);
1541       }
1542       else {
1543         clist_concat(single_fields->fld_cc->cc_addr_list->ad_list, 
1544                      field->fld_data.fld_cc->cc_addr_list->ad_list);
1545         mailimf_field_free(field);
1546         cur = clist_delete(fields->fld_list, cur);
1547       }
1548       break;
1549     case MAILIMF_FIELD_BCC:
1550       if (single_fields->fld_bcc == NULL) {
1551         single_fields->fld_bcc = field->fld_data.fld_bcc;
1552         cur = clist_next(cur);
1553       }
1554       else {
1555         clist_concat(single_fields->fld_bcc->bcc_addr_list->ad_list,
1556                      field->fld_data.fld_bcc->bcc_addr_list->ad_list);
1557         mailimf_field_free(field);
1558         cur = clist_delete(fields->fld_list, cur);
1559       }
1560       break;
1561     case MAILIMF_FIELD_MESSAGE_ID:
1562       if (single_fields->fld_message_id == NULL)
1563         single_fields->fld_message_id = field->fld_data.fld_message_id;
1564       cur = clist_next(cur);
1565       break;
1566     case MAILIMF_FIELD_IN_REPLY_TO:
1567       if (single_fields->fld_in_reply_to == NULL)
1568         single_fields->fld_in_reply_to = field->fld_data.fld_in_reply_to;
1569       cur = clist_next(cur);
1570       break;
1571     case MAILIMF_FIELD_REFERENCES:
1572       if (single_fields->fld_references == NULL)
1573         single_fields->fld_references = field->fld_data.fld_references;
1574       cur = clist_next(cur);
1575       break;
1576     case MAILIMF_FIELD_SUBJECT:
1577       if (single_fields->fld_subject == NULL)
1578         single_fields->fld_subject = field->fld_data.fld_subject;
1579       cur = clist_next(cur);
1580       break;
1581     case MAILIMF_FIELD_COMMENTS:
1582       if (single_fields->fld_comments == NULL)
1583         single_fields->fld_comments = field->fld_data.fld_comments;
1584       cur = clist_next(cur);
1585       break;
1586     case MAILIMF_FIELD_KEYWORDS:
1587       if (single_fields->fld_keywords == NULL)
1588         single_fields->fld_keywords = field->fld_data.fld_keywords;
1589       cur = clist_next(cur);
1590       break;
1591     default:
1592       cur = clist_next(cur);
1593       break;
1594     }
1595   }
1596 }
1597
1598
1599 struct mailimf_single_fields *
1600 mailimf_single_fields_new(struct mailimf_fields * fields)
1601 {
1602   struct mailimf_single_fields * single_fields;
1603
1604   single_fields = malloc(sizeof(struct mailimf_single_fields));
1605   if (single_fields == NULL)
1606     goto err;
1607
1608   mailimf_single_fields_init(single_fields, fields);
1609
1610   return single_fields;
1611
1612  err:
1613   return NULL;
1614 }
1615
1616 void mailimf_single_fields_free(struct mailimf_single_fields *
1617                                 single_fields)
1618 {
1619   free(single_fields);
1620 }
1621
1622 struct mailimf_field * mailimf_field_new_custom(char * name, char * value)
1623 {
1624   struct mailimf_optional_field * opt_field;
1625   struct mailimf_field * field;
1626
1627   opt_field = mailimf_optional_field_new(name, value);
1628   if (opt_field == NULL)
1629     goto err;
1630
1631   field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD,
1632       NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1633       NULL, NULL, NULL, NULL,
1634       NULL, NULL, NULL, NULL,
1635       NULL, NULL, NULL, NULL,
1636       NULL, NULL, opt_field);
1637   if (field == NULL)
1638     goto free_opt_field;
1639
1640   return field;
1641   
1642  free_opt_field:
1643   mailimf_optional_field_free(opt_field);
1644  err:
1645   return NULL;
1646 }