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