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