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