Diffstat (limited to 'libetpan/src/low-level/imf/mailimf_types_helper.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libetpan/src/low-level/imf/mailimf_types_helper.c | 1636 |
1 files changed, 1636 insertions, 0 deletions
diff --git a/libetpan/src/low-level/imf/mailimf_types_helper.c b/libetpan/src/low-level/imf/mailimf_types_helper.c new file mode 100644 index 0000000..a4f669c --- a/dev/null +++ b/libetpan/src/low-level/imf/mailimf_types_helper.c @@ -0,0 +1,1636 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mailimf_types_helper.h" + +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include "mailimf.h" + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new_empty() +{ + clist * list; + struct mailimf_mailbox_list * mb_list; + + list = clist_new(); + if (list == NULL) + return NULL; + + mb_list = mailimf_mailbox_list_new(list); + if (mb_list == NULL) + return NULL; + + return mb_list; +} + +int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list, + struct mailimf_mailbox * mb) +{ + int r; + + r = clist_append(mailbox_list->mb_list, mb); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + +int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list, + char * mb_str) +{ + int r; + size_t cur_token; + struct mailimf_mailbox * mb; + int res; + + cur_token = 0; + r = mailimf_mailbox_parse(mb_str, strlen(mb_str), &cur_token, &mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_list_add(mailbox_list, mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + + return MAILIMF_NO_ERROR; + + free: + mailimf_mailbox_free(mb); + err: + return res; +} + +int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list, + char * display_name, char * address) +{ + int r; + struct mailimf_mailbox * mb; + int res; + + mb = mailimf_mailbox_new(display_name, address); + if (mb == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = mailimf_mailbox_list_add(mailbox_list, mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + + return MAILIMF_NO_ERROR; + + free: + mailimf_mailbox_free(mb); + err: + return res; +} + + + +struct mailimf_address_list * +mailimf_address_list_new_empty() +{ + clist * list; + struct mailimf_address_list * addr_list; + + list = clist_new(); + if (list == NULL) + return NULL; + + addr_list = mailimf_address_list_new(list); + if (addr_list == NULL) + return NULL; + + return addr_list; +} + +int mailimf_address_list_add(struct mailimf_address_list * address_list, + struct mailimf_address * addr) +{ + int r; + + r = clist_append(address_list->ad_list, addr); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + +int mailimf_address_list_add_parse(struct mailimf_address_list * address_list, + char * addr_str) +{ + int r; + size_t cur_token; + struct mailimf_address * addr; + int res; + + cur_token = 0; + r = mailimf_address_parse(addr_str, strlen(addr_str), &cur_token, &addr); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_add(address_list, addr); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + + return MAILIMF_NO_ERROR; + + free: + mailimf_address_free(addr); + err: + return res; +} + +int mailimf_address_list_add_mb(struct mailimf_address_list * address_list, + char * display_name, char * address) +{ + int r; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + int res; + + mb = mailimf_mailbox_new(display_name, address); + if (mb == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + if (addr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb; + } + + r = mailimf_address_list_add(address_list, addr); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr; + } + + return MAILIMF_NO_ERROR; + + free_addr: + mailimf_address_free(addr); + free_mb: + mailimf_mailbox_free(mb); + err: + return res; +} + + +#if 0 +struct mailimf_resent_fields_list * +mailimf_resent_fields_list_new_empty() +{ + clist * list; + struct mailimf_resent_fields_list * rf_list; + + list = clist_new(); + if (list == NULL) + return NULL; + + rf_list = mailimf_resent_fields_list_new(list); + if (rf_list == NULL) + return NULL; + + return rf_list; +} + +int mailimf_resent_fields_add(struct mailimf_resent_fields_list * fields, + struct mailimf_resent_field * field) +{ + int r; + + r = clist_append(fields->list, field); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} +#endif + + +static void 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) +{ + if (imf_date != NULL) { + imf_date->dt_date_time = NULL; + mailimf_orig_date_free(imf_date); + } + if (imf_from != NULL) { + imf_from->frm_mb_list = NULL; + mailimf_from_free(imf_from); + } + if (imf_sender != NULL) { + imf_sender->snd_mb = NULL; + mailimf_sender_free(imf_sender); + } + if (imf_to != NULL) { + imf_to->to_addr_list = NULL; + mailimf_to_free(imf_to); + } + if (imf_cc != NULL) { + imf_cc->cc_addr_list = NULL; + mailimf_to_free(imf_to); + } + if (imf_bcc != NULL) { + imf_bcc->bcc_addr_list = NULL; + mailimf_bcc_free(imf_bcc); + } + if (imf_msg_id != NULL) { + imf_msg_id->mid_value = NULL; + mailimf_message_id_free(imf_msg_id); + } +} + +static void detach_resent_field(struct mailimf_field * field) +{ + field->fld_type = MAILIMF_FIELD_NONE; + mailimf_field_free(field); +} + +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) +{ + struct mailimf_orig_date * imf_resent_date; + struct mailimf_from * imf_resent_from; + struct mailimf_sender * imf_resent_sender; + struct mailimf_to * imf_resent_to; + struct mailimf_cc * imf_resent_cc; + struct mailimf_bcc * imf_resent_bcc; + struct mailimf_message_id * imf_resent_msg_id; + struct mailimf_field * field; + int r; + + imf_resent_date = NULL; + imf_resent_from = NULL; + imf_resent_sender = NULL; + imf_resent_to = NULL; + imf_resent_cc = NULL; + imf_resent_bcc = NULL; + imf_resent_msg_id = NULL; + field = NULL; + + if (resent_date != NULL) { + imf_resent_date = mailimf_orig_date_new(resent_date); + if (imf_resent_date == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_DATE, + NULL /* return-path */, + imf_resent_date /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_from != NULL) { + imf_resent_from = mailimf_from_new(resent_from); + if (imf_resent_from == NULL) + goto free_field; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_FROM, + NULL /* return-path */, + NULL /* resent date */, + imf_resent_from /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_sender != NULL) { + imf_resent_sender = mailimf_sender_new(resent_sender); + if (imf_resent_sender == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_SENDER, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + imf_resent_sender /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_to != NULL) { + imf_resent_to = mailimf_to_new(resent_to); + if (imf_resent_to == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_TO, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + imf_resent_to /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_cc != NULL) { + imf_resent_cc = mailimf_cc_new(resent_cc); + if (imf_resent_cc == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_CC, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + imf_resent_cc /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_bcc != NULL) { + imf_resent_bcc = mailimf_bcc_new(resent_bcc); + if (imf_resent_bcc == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_BCC, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + imf_resent_bcc /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_msg_id != NULL) { + imf_resent_msg_id = mailimf_message_id_new(resent_msg_id); + if (imf_resent_msg_id == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_MSG_ID, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + imf_resent_msg_id /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + return MAILIMF_NO_ERROR; + + free_field: + if (field != NULL) { + detach_resent_field(field); + mailimf_field_free(field); + } + free: + detach_free_common_fields(imf_resent_date, + imf_resent_from, + imf_resent_sender, + imf_resent_to, + imf_resent_cc, + imf_resent_bcc, + imf_resent_msg_id); + return MAILIMF_ERROR_MEMORY; +} + +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) +{ + struct mailimf_fields * resent_fields; + int r; + + resent_fields = mailimf_fields_new_empty(); + if (resent_fields == NULL) + goto err; + + r = mailimf_resent_fields_add_data(resent_fields, + resent_date, resent_from, + resent_sender, resent_to, + resent_cc, resent_bcc, + resent_msg_id); + if (r != MAILIMF_NO_ERROR) + goto free; + + return resent_fields; + + free: + mailimf_fields_free(resent_fields); + err: + return NULL; +} + + +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) +{ + struct mailimf_date_time * date; + char * msg_id; + struct mailimf_fields * fields; + + date = mailimf_get_current_date(); + if (date == NULL) + goto err; + + msg_id = mailimf_get_message_id(); + if (msg_id == NULL) + goto free_date; + + fields = mailimf_resent_fields_new_with_data_all(date, + from, sender, to, cc, bcc, msg_id); + if (fields == NULL) + goto free_msg_id; + + return fields; + + free_msg_id: + free(msg_id); + free_date: + mailimf_date_time_free(date); + err: + return NULL; +} + + +struct mailimf_fields * +mailimf_fields_new_empty(void) +{ + clist * list; + struct mailimf_fields * fields_list; + + list = clist_new(); + if (list == NULL) + return NULL; + + fields_list = mailimf_fields_new(list); + if (fields_list == NULL) + return NULL; + + return fields_list; +} + +int mailimf_fields_add(struct mailimf_fields * fields, + struct mailimf_field * field) +{ + int r; + + r = clist_append(fields->fld_list, field); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + +static void 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) +{ + detach_free_common_fields(date, + from, + sender, + to, + cc, + bcc, + msg_id); + + if (reply_to != NULL) { + reply_to->rt_addr_list = NULL; + mailimf_reply_to_free(reply_to); + } + + if (in_reply_to != NULL) { + in_reply_to->mid_list = NULL; + mailimf_in_reply_to_free(in_reply_to); + } + + if (references != NULL) { + references->mid_list = NULL; + mailimf_references_free(references); + } + + if (subject != NULL) { + subject->sbj_value = NULL; + mailimf_subject_free(subject); + } +} + + +static void detach_field(struct mailimf_field * field) +{ + field->fld_type = MAILIMF_FIELD_NONE; + mailimf_field_free(field); +} + +int 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) +{ + struct mailimf_orig_date * imf_date; + struct mailimf_from * imf_from; + struct mailimf_sender * imf_sender; + struct mailimf_reply_to * imf_reply_to; + struct mailimf_to * imf_to; + struct mailimf_cc * imf_cc; + struct mailimf_bcc * imf_bcc; + struct mailimf_message_id * imf_msg_id; + struct mailimf_references * imf_references; + struct mailimf_in_reply_to * imf_in_reply_to; + struct mailimf_subject * imf_subject; + struct mailimf_field * field; + int r; + + imf_date = NULL; + imf_from = NULL; + imf_sender = NULL; + imf_reply_to = NULL; + imf_to = NULL; + imf_cc = NULL; + imf_bcc = NULL; + imf_msg_id = NULL; + imf_references = NULL; + imf_in_reply_to = NULL; + imf_subject =NULL; + field = NULL; + + if (date != NULL) { + imf_date = mailimf_orig_date_new(date); + if (imf_date == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + imf_date /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (from != NULL) { + imf_from = mailimf_from_new(from); + if (imf_from == NULL) + goto free_field; + field = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + imf_from /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (sender != NULL) { + imf_sender = mailimf_sender_new(sender); + if (imf_sender == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_SENDER, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + imf_sender /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (reply_to != NULL) { + imf_reply_to = mailimf_reply_to_new(reply_to); + if (imf_reply_to == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_REPLY_TO, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + imf_reply_to /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (to != NULL) { + imf_to = mailimf_to_new(to); + if (imf_to == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_TO, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + imf_to /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (cc != NULL) { + imf_cc = mailimf_cc_new(cc); + if (imf_cc == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_CC, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + imf_cc /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (bcc != NULL) { + imf_bcc = mailimf_bcc_new(bcc); + if (imf_bcc == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_BCC, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + imf_bcc /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (msg_id != NULL) { + imf_msg_id = mailimf_message_id_new(msg_id); + if (imf_msg_id == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + imf_msg_id /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (in_reply_to != NULL) { + imf_in_reply_to = mailimf_in_reply_to_new(in_reply_to); + if (imf_in_reply_to == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_IN_REPLY_TO, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + imf_in_reply_to /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (references != NULL) { + imf_references = mailimf_references_new(references); + if (imf_references == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_REFERENCES, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + imf_references /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (subject != NULL) { + imf_subject = mailimf_subject_new(subject); + if (imf_subject == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_SUBJECT, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + imf_subject /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + return MAILIMF_NO_ERROR; + + free_field: + if (field != NULL) { + detach_field(field); + mailimf_field_free(field); + } + free: + detach_free_fields(imf_date, + imf_from, + imf_sender, + imf_reply_to, + imf_to, + imf_cc, + imf_bcc, + imf_msg_id, + imf_in_reply_to, + imf_references, + imf_subject); + + return MAILIMF_ERROR_MEMORY; +} + +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) +{ + struct mailimf_fields * fields; + int r; + + fields = mailimf_fields_new_empty(); + if (fields == NULL) + goto err; + + r = mailimf_fields_add_data(fields, + date, + from, + sender, + reply_to, + to, + cc, + bcc, + message_id, + in_reply_to, + references, + subject); + if (r != MAILIMF_NO_ERROR) + goto free; + + return fields; + + free: + mailimf_fields_free(fields); + err: + return NULL; +} + +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) +{ + struct mailimf_date_time * date; + char * msg_id; + struct mailimf_fields * fields; + + date = mailimf_get_current_date(); + if (date == NULL) + goto err; + + msg_id = mailimf_get_message_id(); + if (msg_id == NULL) + goto free_date; + + fields = mailimf_fields_new_with_data_all(date, + from, sender, reply_to, + to, cc, bcc, + msg_id, + in_reply_to, references, + subject); + if (fields == NULL) + goto free_msg_id; + + return fields; + + free_msg_id: + free(msg_id); + free_date: + mailimf_date_time_free(date); + err: + return NULL; +} + + + +#define MAX_MESSAGE_ID 512 + +char * mailimf_get_message_id(void) +{ + char id[MAX_MESSAGE_ID]; + time_t now; + char name[MAX_MESSAGE_ID]; + long value; + + now = time(NULL); + value = random(); + + gethostname(name, MAX_MESSAGE_ID); + snprintf(id, MAX_MESSAGE_ID, "etPan.%lx.%lx.%x@%s", + now, value, getpid(), name); + + return strdup(id); +} + + + +static time_t mkgmtime(struct tm * tmp); + + +struct mailimf_date_time * mailimf_get_current_date(void) +{ + struct tm gmt; + struct tm lt; + int off; + time_t now; + struct mailimf_date_time * date_time; + + now = time(NULL); + + if (gmtime_r(&now, &gmt) == NULL) + return NULL; + + if (localtime_r(&now, <) == NULL) + return NULL; + + off = (mkgmtime(<) - mkgmtime(&gmt)) / (60 * 60) * 100; + + date_time = mailimf_date_time_new(lt.tm_mday, lt.tm_mon + 1, lt.tm_year + 1900, + lt.tm_hour, lt.tm_min, lt.tm_sec, + off); + + return date_time; +} + + + +/* mkgmtime.c - make time corresponding to a GMT timeval struct + $Id$ + + * Copyright (c) 1998-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any other legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + */ +/* + * Copyright (c) 1987, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Arthur David Olson of the National Cancer Institute. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* +** Adapted from code provided by Robert Elz, who writes: +** The "best" way to do mktime I think is based on an idea of Bob +** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now). +** It does a binary search of the time_t space. Since time_t's are +** just 32 bits, its a max of 32 iterations (even at 64 bits it +** would still be very reasonable). +*/ + +/* + adapted for libEtPan! by DINH V. Hoa +*/ + +#ifndef WRONG +#define WRONG (-1) +#endif /* !defined WRONG */ + +static int tmcomp(struct tm * atmp, struct tm * btmp) +{ + register int result; + + if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && + (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && + (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && + (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && + (result = (atmp->tm_min - btmp->tm_min)) == 0) + result = atmp->tm_sec - btmp->tm_sec; + return result; +} + +static time_t mkgmtime(struct tm * tmp) +{ + register int dir; + register int bits; + register int saved_seconds; + time_t t; + struct tm yourtm, *mytm; + + yourtm = *tmp; + saved_seconds = yourtm.tm_sec; + yourtm.tm_sec = 0; + /* + ** Calculate the number of magnitude bits in a time_t + ** (this works regardless of whether time_t is + ** signed or unsigned, though lint complains if unsigned). + */ + for (bits = 0, t = 1; t > 0; ++bits, t <<= 1) + ; + /* + ** If time_t is signed, then 0 is the median value, + ** if time_t is unsigned, then 1 << bits is median. + */ + t = (t < 0) ? 0 : ((time_t) 1 << bits); + for ( ; ; ) { + mytm = gmtime(&t); + dir = tmcomp(mytm, &yourtm); + if (dir != 0) { + if (bits-- < 0) + return WRONG; + if (bits < 0) + --t; + else if (dir > 0) + t -= (time_t) 1 << bits; + else t += (time_t) 1 << bits; + continue; + } + break; + } + t += saved_seconds; + return t; +} + + + + + + + +void mailimf_single_fields_init(struct mailimf_single_fields * single_fields, + struct mailimf_fields * fields) +{ + clistiter * cur; + + memset(single_fields, 0, sizeof(struct mailimf_single_fields)); + + cur = clist_begin(fields->fld_list); + while (cur != NULL) { + struct mailimf_field * field; + + field = clist_content(cur); + + switch (field->fld_type) { + case MAILIMF_FIELD_ORIG_DATE: + if (single_fields->fld_orig_date == NULL) + single_fields->fld_orig_date = field->fld_data.fld_orig_date; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_FROM: + if (single_fields->fld_from == NULL) { + single_fields->fld_from = field->fld_data.fld_from; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_from->frm_mb_list->mb_list, + field->fld_data.fld_from->frm_mb_list->mb_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_SENDER: + if (single_fields->fld_sender == NULL) + single_fields->fld_sender = field->fld_data.fld_sender; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_REPLY_TO: + if (single_fields->fld_reply_to == NULL) { + single_fields->fld_reply_to = field->fld_data.fld_reply_to; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_reply_to->rt_addr_list->ad_list, + field->fld_data.fld_reply_to->rt_addr_list->ad_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_TO: + if (single_fields->fld_to == NULL) { + single_fields->fld_to = field->fld_data.fld_to; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_to->to_addr_list->ad_list, + field->fld_data.fld_to->to_addr_list->ad_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_CC: + if (single_fields->fld_cc == NULL) { + single_fields->fld_cc = field->fld_data.fld_cc; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_cc->cc_addr_list->ad_list, + field->fld_data.fld_cc->cc_addr_list->ad_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_BCC: + if (single_fields->fld_bcc == NULL) { + single_fields->fld_bcc = field->fld_data.fld_bcc; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_bcc->bcc_addr_list->ad_list, + field->fld_data.fld_bcc->bcc_addr_list->ad_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_MESSAGE_ID: + if (single_fields->fld_message_id == NULL) + single_fields->fld_message_id = field->fld_data.fld_message_id; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + if (single_fields->fld_in_reply_to == NULL) + single_fields->fld_in_reply_to = field->fld_data.fld_in_reply_to; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_REFERENCES: + if (single_fields->fld_references == NULL) + single_fields->fld_references = field->fld_data.fld_references; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_SUBJECT: + if (single_fields->fld_subject == NULL) + single_fields->fld_subject = field->fld_data.fld_subject; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_COMMENTS: + if (single_fields->fld_comments == NULL) + single_fields->fld_comments = field->fld_data.fld_comments; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_KEYWORDS: + if (single_fields->fld_keywords == NULL) + single_fields->fld_keywords = field->fld_data.fld_keywords; + cur = clist_next(cur); + break; + default: + cur = clist_next(cur); + break; + } + } +} + + +struct mailimf_single_fields * +mailimf_single_fields_new(struct mailimf_fields * fields) +{ + struct mailimf_single_fields * single_fields; + + single_fields = malloc(sizeof(struct mailimf_single_fields)); + if (single_fields == NULL) + goto err; + + mailimf_single_fields_init(single_fields, fields); + + return single_fields; + + err: + return NULL; +} + +void mailimf_single_fields_free(struct mailimf_single_fields * + single_fields) +{ + free(single_fields); +} + +struct mailimf_field * mailimf_field_new_custom(char * name, char * value) +{ + struct mailimf_optional_field * opt_field; + struct mailimf_field * field; + + opt_field = mailimf_optional_field_new(name, value); + if (opt_field == NULL) + goto err; + + field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, opt_field); + if (field == NULL) + goto free_opt_field; + + return field; + + free_opt_field: + mailimf_optional_field_free(opt_field); + err: + return NULL; +} |