-rw-r--r-- | libetpan/src/low-level/imf/TODO | 12 | ||||
-rw-r--r-- | libetpan/src/low-level/imf/mailimf.c | 7585 | ||||
-rw-r--r-- | libetpan/src/low-level/imf/mailimf.h | 347 | ||||
-rw-r--r-- | libetpan/src/low-level/imf/mailimf_types.c | 868 | ||||
-rw-r--r-- | libetpan/src/low-level/imf/mailimf_types.h | 793 | ||||
-rw-r--r-- | libetpan/src/low-level/imf/mailimf_types_helper.c | 1636 | ||||
-rw-r--r-- | libetpan/src/low-level/imf/mailimf_types_helper.h | 370 | ||||
-rw-r--r-- | libetpan/src/low-level/imf/mailimf_write.c | 2021 | ||||
-rw-r--r-- | libetpan/src/low-level/imf/mailimf_write.h | 134 | ||||
-rw-r--r-- | libetpan/src/low-level/imf/mailimf_write_file.c | 149 | ||||
-rw-r--r-- | libetpan/src/low-level/imf/mailimf_write_file.h | 169 | ||||
-rw-r--r-- | libetpan/src/low-level/imf/mailimf_write_generic.c | 2028 | ||||
-rw-r--r-- | libetpan/src/low-level/imf/mailimf_write_generic.h | 142 | ||||
-rw-r--r-- | libetpan/src/low-level/imf/mailimf_write_mem.c | 98 | ||||
-rw-r--r-- | libetpan/src/low-level/imf/mailimf_write_mem.h | 135 |
15 files changed, 16487 insertions, 0 deletions
diff --git a/libetpan/src/low-level/imf/TODO b/libetpan/src/low-level/imf/TODO new file mode 100644 index 0000000..f36f55f --- a/dev/null +++ b/libetpan/src/low-level/imf/TODO @@ -0,0 +1,12 @@ +- define a EP_parserstate_s +- remove clist usage +- add a errorcode to string function +- error codes are EP_errornr_s +- prefix everything with EP_ +- mailimf_dot_atom_text_free +- mailimf_address_XX -> _new(void) _init(&addr, ...) _free(addr) +- in fact that data structure should then also contain a + 'dynamically' allocated flag + +- RFC 822 : test the examples +- RFC 2822 : obsolete syntax diff --git a/libetpan/src/low-level/imf/mailimf.c b/libetpan/src/low-level/imf/mailimf.c new file mode 100644 index 0000000..333767a --- a/dev/null +++ b/libetpan/src/low-level/imf/mailimf.c @@ -0,0 +1,7585 @@ +/* + * 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. + */ + +/* + * $Id$ + */ + +#include "mailimf.h" + +/* + RFC 2822 + + RFC 2821 ... + A message-originating SMTP system SHOULD NOT send a message that + already contains a Return-path header. SMTP servers performing a + relay function MUST NOT inspect the message data, and especially not + to the extent needed to determine if Return-path headers are present. + SMTP servers making final delivery MAY remove Return-path headers + before adding their own. +*/ + +#include <ctype.h> +#include "mmapstring.h" +#include <stdlib.h> +#include <string.h> + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + + + + + + + +static inline int is_dtext(char ch); + +static int mailimf_quoted_pair_parse(const char * message, size_t length, + size_t * index, char * result); + +static int mailimf_ccontent_parse(const char * message, size_t length, + size_t * index); + +static int +mailimf_comment_fws_ccontent_parse(const char * message, size_t length, + size_t * index); + +static inline int mailimf_comment_parse(const char * message, size_t length, + size_t * index); + +static int mailimf_qcontent_parse(const char * message, size_t length, + size_t * index, char * ch); + +static int mailimf_phrase_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_unstructured_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_ignore_unstructured_parse(const char * message, size_t length, + size_t * index); + +static int mailimf_day_of_week_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_day_name_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_date_parse(const char * message, size_t length, + size_t * index, + int * pday, int * pmonth, int * pyear); + +static int mailimf_year_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_month_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_month_name_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_day_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_time_parse(const char * message, size_t length, + size_t * index, + int * phour, int * pmin, + int * psec, + int * zone); +static int mailimf_time_of_day_parse(const char * message, size_t length, + size_t * index, + int * phour, int * pmin, + int * psec); + +static int mailimf_hour_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_minute_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_second_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_zone_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_name_addr_parse(const char * message, size_t length, + size_t * index, + char ** pdisplay_name, + char ** pangle_addr); + +static int mailimf_angle_addr_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_group_parse(const char * message, size_t length, + size_t * index, + struct mailimf_group ** result); + +static int mailimf_display_name_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_addr_spec_parse(const char * message, size_t length, + size_t * index, + char ** address); + +#if 0 +static int mailimf_local_part_parse(const char * message, size_t length, + size_t * index, + char ** result); + +static int mailimf_domain_parse(const char * message, size_t length, + size_t * index, + char ** result); +#endif + +#if 0 +static int mailimf_domain_literal_parse(const char * message, size_t length, + size_t * index, char ** result); +#endif + +#if 0 +static int mailimf_dcontent_parse(const char * message, size_t length, + size_t * index, char * result); +#endif + +static int +mailimf_orig_date_parse(const char * message, size_t length, + size_t * index, struct mailimf_orig_date ** result); + +static int +mailimf_from_parse(const char * message, size_t length, + size_t * index, struct mailimf_from ** result); + +static int +mailimf_sender_parse(const char * message, size_t length, + size_t * index, struct mailimf_sender ** result); + +static int +mailimf_reply_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_reply_to ** result); + +static int +mailimf_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_to ** result); + +static int +mailimf_cc_parse(const char * message, size_t length, + size_t * index, struct mailimf_cc ** result); + +static int +mailimf_bcc_parse(const char * message, size_t length, + size_t * index, struct mailimf_bcc ** result); + +static int mailimf_message_id_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message_id ** result); + +static int +mailimf_in_reply_to_parse(const char * message, size_t length, + size_t * index, + struct mailimf_in_reply_to ** result); + +#if 0 +static int mailimf_references_parse(const char * message, size_t length, + size_t * index, + struct mailimf_references ** + result); +#endif + +static int mailimf_unstrict_msg_id_parse(const char * message, size_t length, + size_t * index, + char ** result); + +#if 0 +static int mailimf_id_left_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_id_right_parse(const char * message, size_t length, + size_t * index, char ** result); +#endif + +#if 0 +static int mailimf_no_fold_quote_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_no_fold_literal_parse(const char * message, size_t length, + size_t * index, char ** result); +#endif + +static int mailimf_subject_parse(const char * message, size_t length, + size_t * index, + struct mailimf_subject ** result); + +static int mailimf_comments_parse(const char * message, size_t length, + size_t * index, + struct mailimf_comments ** result); + +static int mailimf_keywords_parse(const char * message, size_t length, + size_t * index, + struct mailimf_keywords ** result); + +static int +mailimf_resent_date_parse(const char * message, size_t length, + size_t * index, struct mailimf_orig_date ** result); + +static int +mailimf_resent_from_parse(const char * message, size_t length, + size_t * index, struct mailimf_from ** result); + +static int +mailimf_resent_sender_parse(const char * message, size_t length, + size_t * index, struct mailimf_sender ** result); + +static int +mailimf_resent_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_to ** result); + +static int +mailimf_resent_cc_parse(const char * message, size_t length, + size_t * index, struct mailimf_cc ** result); + +static int +mailimf_resent_bcc_parse(const char * message, size_t length, + size_t * index, struct mailimf_bcc ** result); + +static int +mailimf_resent_msg_id_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message_id ** result); + +static int mailimf_return_parse(const char * message, size_t length, + size_t * index, + struct mailimf_return ** result); + +static int +mailimf_path_parse(const char * message, size_t length, + size_t * index, struct mailimf_path ** result); + +static int +mailimf_optional_field_parse(const char * message, size_t length, + size_t * index, + struct mailimf_optional_field ** result); + +static int mailimf_field_name_parse(const char * message, size_t length, + size_t * index, char ** result); + + + + + + + + + + + + + + + + + + + + + + + + + +/* *************************************************************** */ + +static inline int is_digit(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + +static int mailimf_digit_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_digit(message[cur_token])) { + * result = message[cur_token] - '0'; + cur_token ++; + * index = cur_token; + return MAILIMF_NO_ERROR; + } + else + return MAILIMF_ERROR_PARSE; +} + +int +mailimf_number_parse(const char * message, size_t length, + size_t * index, uint32_t * result) +{ + size_t cur_token; + int digit; + uint32_t number; + int parsed; + int r; + + cur_token = * index; + parsed = FALSE; + + number = 0; + while (1) { + r = mailimf_digit_parse(message, length, &cur_token, &digit); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + number *= 10; + number += digit; + parsed = TRUE; + } + + if (!parsed) + return MAILIMF_ERROR_PARSE; + + * result = number; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +int mailimf_char_parse(const char * message, size_t length, + size_t * index, char token) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (message[cur_token] == token) { + cur_token ++; + * index = cur_token; + return MAILIMF_NO_ERROR; + } + else + return MAILIMF_ERROR_PARSE; +} + +int mailimf_unstrict_char_parse(const char * message, size_t length, + size_t * index, char token) +{ + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_char_parse(message, length, &cur_token, token); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +int +mailimf_token_case_insensitive_len_parse(const char * message, size_t length, + size_t * index, char * token, + size_t token_length) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token + token_length - 1 >= length) + return MAILIMF_ERROR_PARSE; + + if (strncasecmp(message + cur_token, token, token_length) == 0) { + cur_token += token_length; + * index = cur_token; + return MAILIMF_NO_ERROR; + } + else + return MAILIMF_ERROR_PARSE; +} + +static int mailimf_oparenth_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_char_parse(message, length, index, '('); +} + +static int mailimf_cparenth_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_char_parse(message, length, index, ')'); +} + +static int mailimf_comma_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, ','); +} + +static int mailimf_dquote_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_char_parse(message, length, index, '\"'); +} + +static int mailimf_colon_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, ':'); +} + +static int mailimf_semi_colon_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, ';'); +} + +static int mailimf_plus_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '+'); +} + +static int mailimf_minus_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '-'); +} + +static int mailimf_lower_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '<'); +} + +static int mailimf_greater_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '>'); +} + +#if 0 +static int mailimf_obracket_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '['); +} + +static int mailimf_cbracket_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, ']'); +} +#endif + +static int mailimf_at_sign_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '@'); +} + +static int mailimf_point_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '.'); +} + +int +mailimf_custom_string_parse(const char * message, size_t length, + size_t * index, char ** result, + int (* is_custom_char)(char)) +{ + size_t begin; + size_t end; + char * gstr; + + begin = * index; + + end = begin; + + if (end >= length) + return MAILIMF_ERROR_PARSE; + + while (is_custom_char(message[end])) { + end ++; + if (end >= length) + break; + } + + if (end != begin) { + /* + gstr = strndup(message + begin, end - begin); + */ + gstr = malloc(end - begin + 1); + if (gstr == NULL) + return MAILIMF_ERROR_MEMORY; + strncpy(gstr, message + begin, end - begin); + gstr[end - begin] = '\0'; + + * index = end; + * result = gstr; + return MAILIMF_NO_ERROR; + } + else + return MAILIMF_ERROR_PARSE; +} + + + + + + + +typedef int mailimf_struct_parser(const char * message, size_t length, + size_t * index, void * result); + +typedef int mailimf_struct_destructor(void * result); + + +static int +mailimf_struct_multiple_parse(const char * message, size_t length, + size_t * index, clist ** result, + mailimf_struct_parser * parser, + mailimf_struct_destructor * destructor) +{ + clist * struct_list; + size_t cur_token; + void * value; + int r; + int res; + + cur_token = * index; + + r = parser(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + struct_list = clist_new(); + if (struct_list == NULL) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + while (1) { + r = parser(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free; + } + } + r = clist_append(struct_list, value); + if (r < 0) { + (* destructor)(value); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + + * result = struct_list; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + clist_foreach(struct_list, (clist_func) destructor, NULL); + clist_free(struct_list); + err: + return res; +} + + + +static int +mailimf_struct_list_parse(const char * message, size_t length, + size_t * index, clist ** result, + char symbol, + mailimf_struct_parser * parser, + mailimf_struct_destructor * destructor) +{ + clist * struct_list; + size_t cur_token; + void * value; + size_t final_token; + int r; + int res; + + cur_token = * index; + + r = parser(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + struct_list = clist_new(); + if (struct_list == NULL) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + final_token = cur_token; + + while (1) { + r = mailimf_unstrict_char_parse(message, length, &cur_token, symbol); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free; + } + } + + r = parser(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free; + } + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + final_token = cur_token; + } + + * result = struct_list; + * index = final_token; + + return MAILIMF_NO_ERROR; + + free: + clist_foreach(struct_list, (clist_func) destructor, NULL); + clist_free(struct_list); + err: + return res; +} + +static inline int mailimf_wsp_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if ((message[cur_token] != ' ') && (message[cur_token] != '\t')) + return MAILIMF_ERROR_PARSE; + + cur_token ++; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + + +int mailimf_crlf_parse(const char * message, size_t length, size_t * index) +{ + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_char_parse(message, length, &cur_token, '\r'); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_char_parse(message, length, &cur_token, '\n'); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + return MAILIMF_NO_ERROR; +} + +static int mailimf_unstrict_crlf_parse(const char * message, + size_t length, size_t * index) +{ + size_t cur_token; + int r; + + cur_token = * index; + + mailimf_cfws_parse(message, length, &cur_token); + + r = mailimf_char_parse(message, length, &cur_token, '\r'); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_char_parse(message, length, &cur_token, '\n'); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + return MAILIMF_NO_ERROR; +} + +/* ************************************************************************ */ + + + +/* RFC 2822 grammar */ + +/* +NO-WS-CTL = %d1-8 / ; US-ASCII control characters + %d11 / ; that do not include the + %d12 / ; carriage return, line feed, + %d14-31 / ; and white space characters + %d127 +*/ + +static inline int is_no_ws_ctl(char ch) +{ + if ((ch == 9) || (ch == 10) || (ch == 13)) + return FALSE; + + if (ch == 127) + return TRUE; + + return (ch >= 1) && (ch <= 31); +} + +/* +text = %d1-9 / ; Characters excluding CR and LF + %d11 / + %d12 / + %d14-127 / + obs-text +*/ + +/* +specials = "(" / ")" / ; Special characters used in + "<" / ">" / ; other parts of the syntax + "[" / "]" / + ":" / ";" / + "@" / "\" / + "," / "." / + DQUOTE +*/ + +/* +quoted-pair = ("\" text) / obs-qp +*/ + +static inline int mailimf_quoted_pair_parse(const char * message, size_t length, + size_t * index, char * result) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token + 1 >= length) + return MAILIMF_ERROR_PARSE; + + if (message[cur_token] != '\\') + return MAILIMF_ERROR_PARSE; + + cur_token ++; + * result = message[cur_token]; + cur_token ++; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space + obs-FWS +*/ + +int mailimf_fws_parse(const char * message, size_t length, size_t * index) +{ + size_t cur_token; + size_t final_token; + int fws_1; + int fws_2; + int fws_3; + int r; + + cur_token = * index; + + fws_1 = FALSE; + while (1) { + r = mailimf_wsp_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + fws_1 = TRUE; + } + final_token = cur_token; + + r = mailimf_crlf_parse(message, length, &cur_token); + switch (r) { + case MAILIMF_NO_ERROR: + fws_2 = TRUE; + break; + case MAILIMF_ERROR_PARSE: + fws_2 = FALSE; + break; + default: + return r; + } + + fws_3 = FALSE; + if (fws_2) { + while (1) { + r = mailimf_wsp_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + fws_3 = TRUE; + } + } + + if ((!fws_1) && (!fws_3)) + return MAILIMF_ERROR_PARSE; + + if (!fws_3) + cur_token = final_token; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + + +/* +ctext = NO-WS-CTL / ; Non white space controls + + %d33-39 / ; The rest of the US-ASCII + %d42-91 / ; characters not including "(", + %d93-126 ; ")", or "\" +*/ + +static inline int is_ctext(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (is_no_ws_ctl(ch)) + return TRUE; + + if (uch < 33) + return FALSE; + + if ((uch == 40) || (uch == 41)) + return FALSE; + + if (uch == 92) + return FALSE; + + if (uch == 127) + return FALSE; + + return TRUE; +} + +/* +ccontent = ctext / quoted-pair / comment +*/ + +static inline int mailimf_ccontent_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_ctext(message[cur_token])) { + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_comment_parse(message, length, &cur_token); + + if (r == MAILIMF_ERROR_PARSE) + return r; + } + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +[FWS] ccontent +*/ + +static inline int +mailimf_comment_fws_ccontent_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_ccontent_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +comment = "(" *([FWS] ccontent) [FWS] ")" +*/ + +static inline int mailimf_comment_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_oparenth_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + while (1) { + r = mailimf_comment_fws_ccontent_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + } + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_cparenth_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +[FWS] comment +*/ + +static inline int mailimf_cfws_fws_comment_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_comment_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +CFWS = *([FWS] comment) (([FWS] comment) / FWS) +*/ + +int mailimf_cfws_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int has_comment; + int r; + + cur_token = * index; + + has_comment = FALSE; + while (1) { + r = mailimf_cfws_fws_comment_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + has_comment = TRUE; + } + + if (!has_comment) { + r = mailimf_fws_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + } + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +atext = ALPHA / DIGIT / ; Any character except controls, + "!" / "#" / ; SP, and specials. + "$" / "%" / ; Used for atoms + "&" / "'" / + "*" / "+" / + "-" / "/" / + "=" / "?" / + "^" / "_" / + "`" / "{" / + "|" / "}" / + "~" +*/ + +static inline int is_atext(char ch) +{ + switch (ch) { + case ' ': + case '\t': + case '\n': + case '\r': +#if 0 + case '(': + case ')': +#endif + case '<': + case '>': +#if 0 + case '@': +#endif + case ',': + case '"': + case ':': + case ';': + return FALSE; + default: + return TRUE; + } +} + +/* +atom = [CFWS] 1*atext [CFWS] +*/ + +int mailimf_atom_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + int r; + int res; + char * atom; + size_t end; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + end = cur_token; + if (end >= length) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + while (is_atext(message[end])) { + end ++; + if (end >= length) + break; + } + if (end == cur_token) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + atom = malloc(end - cur_token + 1); + if (atom == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + strncpy(atom, message + cur_token, end - cur_token); + atom[end - cur_token] = '\0'; + + cur_token = end; + + * index = cur_token; + * result = atom; + + return MAILIMF_NO_ERROR; + + err: + return res; +} + +int mailimf_fws_atom_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + int r; + int res; + char * atom; + size_t end; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + end = cur_token; + if (end >= length) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + while (is_atext(message[end])) { + end ++; + if (end >= length) + break; + } + if (end == cur_token) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + atom = malloc(end - cur_token + 1); + if (atom == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + strncpy(atom, message + cur_token, end - cur_token); + atom[end - cur_token] = '\0'; + + cur_token = end; + + * index = cur_token; + * result = atom; + + return MAILIMF_NO_ERROR; + + err: + return res; +} + +/* +dot-atom = [CFWS] dot-atom-text [CFWS] +*/ + +#if 0 +static int mailimf_dot_atom_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_atom_parse(message, length, index, result); +} +#endif + +/* +dot-atom-text = 1*atext *("." 1*atext) +*/ + +#if 0 +static int +mailimf_dot_atom_text_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_atom_parse(message, length, index, result); +} +#endif + +/* +qtext = NO-WS-CTL / ; Non white space controls + + %d33 / ; The rest of the US-ASCII + %d35-91 / ; characters not including "\" + %d93-126 ; or the quote character +*/ + +static inline int is_qtext(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (is_no_ws_ctl(ch)) + return TRUE; + + if (uch < 33) + return FALSE; + + if (uch == 34) + return FALSE; + + if (uch == 92) + return FALSE; + + if (uch == 127) + return FALSE; + + return TRUE; +} + +/* +qcontent = qtext / quoted-pair +*/ + +static int mailimf_qcontent_parse(const char * message, size_t length, + size_t * index, char * result) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_qtext(message[cur_token])) { + ch = message[cur_token]; + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r != MAILIMF_NO_ERROR) + return r; + } + + * result = ch; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +quoted-string = [CFWS] + DQUOTE *([FWS] qcontent) [FWS] DQUOTE + [CFWS] +*/ + +int mailimf_quoted_string_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + MMAPString * gstr; + char ch; + char * str; + int r; + int res; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + gstr = mmap_string_new(""); + if (gstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + +#if 0 + if (mmap_string_append_c(gstr, '\"') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } +#endif + + while (1) { + r = mailimf_fws_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + if (mmap_string_append_c(gstr, ' ') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + } + else if (r != MAILIMF_ERROR_PARSE) { + res = r; + goto free_gstr; + } + + r = mailimf_qcontent_parse(message, length, &cur_token, &ch); + if (r == MAILIMF_NO_ERROR) { + if (mmap_string_append_c(gstr, ch) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free_gstr; + } + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_gstr; + } + +#if 0 + if (mmap_string_append_c(gstr, '\"') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } +#endif + + str = strdup(gstr->str); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + mmap_string_free(gstr); + + * index = cur_token; + * result = str; + + return MAILIMF_NO_ERROR; + + free_gstr: + mmap_string_free(gstr); + err: + return res; +} + +int mailimf_fws_quoted_string_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + MMAPString * gstr; + char ch; + char * str; + int r; + int res; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + gstr = mmap_string_new(""); + if (gstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + +#if 0 + if (mmap_string_append_c(gstr, '\"') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } +#endif + + while (1) { + r = mailimf_fws_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + if (mmap_string_append_c(gstr, ' ') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + } + else if (r != MAILIMF_ERROR_PARSE) { + res = r; + goto free_gstr; + } + + r = mailimf_qcontent_parse(message, length, &cur_token, &ch); + if (r == MAILIMF_NO_ERROR) { + if (mmap_string_append_c(gstr, ch) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free_gstr; + } + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_gstr; + } + +#if 0 + if (mmap_string_append_c(gstr, '\"') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } +#endif + + str = strdup(gstr->str); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + mmap_string_free(gstr); + + * index = cur_token; + * result = str; + + return MAILIMF_NO_ERROR; + + free_gstr: + mmap_string_free(gstr); + err: + return res; +} + +/* +word = atom / quoted-string +*/ + +int mailimf_word_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + char * word; + int r; + + cur_token = * index; + + r = mailimf_atom_parse(message, length, &cur_token, &word); + + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_quoted_string_parse(message, length, &cur_token, &word); + + if (r != MAILIMF_NO_ERROR) + return r; + + * result = word; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +int mailimf_fws_word_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + char * word; + int r; + + cur_token = * index; + + r = mailimf_fws_atom_parse(message, length, &cur_token, &word); + + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_fws_quoted_string_parse(message, length, &cur_token, &word); + + if (r != MAILIMF_NO_ERROR) + return r; + + * result = word; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +phrase = 1*word / obs-phrase +*/ + +static int mailimf_phrase_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + MMAPString * gphrase; + char * word; + int first; + size_t cur_token; + int r; + int res; + char * str; + + cur_token = * index; + + gphrase = mmap_string_new(""); + if (gphrase == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + first = TRUE; + + while (1) { + r = mailimf_fws_word_parse(message, length, &cur_token, &word); + if (r == MAILIMF_NO_ERROR) { + if (!first) { + if (mmap_string_append_c(gphrase, ' ') == NULL) { + mailimf_word_free(word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + if (mmap_string_append(gphrase, word) == NULL) { + mailimf_word_free(word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + mailimf_word_free(word); + first = FALSE; + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free; + } + } + + if (first) { + res = MAILIMF_ERROR_PARSE; + goto free; + } + + str = strdup(gphrase->str); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + mmap_string_free(gphrase); + + * result = str; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(gphrase); + err: + return res; +} + +/* +utext = NO-WS-CTL / ; Non white space controls + %d33-126 / ; The rest of US-ASCII + obs-utext + +added : WSP +*/ + +enum { + UNSTRUCTURED_START, + UNSTRUCTURED_CR, + UNSTRUCTURED_LF, + UNSTRUCTURED_WSP, + UNSTRUCTURED_OUT +}; + +static int mailimf_unstructured_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + int state; + size_t begin; + size_t terminal; + char * str; + + cur_token = * index; + + + while (1) { + int r; + + r = mailimf_wsp_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + return r; + } + } + + state = UNSTRUCTURED_START; + begin = cur_token; + terminal = cur_token; + + while (state != UNSTRUCTURED_OUT) { + + switch(state) { + case UNSTRUCTURED_START: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + terminal = cur_token; + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_CR: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + + case UNSTRUCTURED_LF: + if (cur_token >= length) { + state = UNSTRUCTURED_OUT; + break; + } + + switch(message[cur_token]) { + case '\t': + case ' ': + state = UNSTRUCTURED_WSP; + break; + default: + state = UNSTRUCTURED_OUT; + break; + } + break; + case UNSTRUCTURED_WSP: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + } + + cur_token ++; + } + + str = malloc(terminal - begin + 1); + if (str == NULL) + return MAILIMF_ERROR_MEMORY; + strncpy(str, message + begin, terminal - begin); + str[terminal - begin] = '\0'; + + * index = terminal; + * result = str; + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_ignore_unstructured_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int state; + size_t terminal; + + cur_token = * index; + + state = UNSTRUCTURED_START; + terminal = cur_token; + + while (state != UNSTRUCTURED_OUT) { + + switch(state) { + case UNSTRUCTURED_START: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + terminal = cur_token; + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_CR: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + switch(message[cur_token]) { + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_LF: + if (cur_token >= length) { + state = UNSTRUCTURED_OUT; + break; + } + switch(message[cur_token]) { + case '\t': + case ' ': + state = UNSTRUCTURED_WSP; + break; + default: + state = UNSTRUCTURED_OUT; + break; + } + break; + case UNSTRUCTURED_WSP: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + } + + cur_token ++; + } + + * index = terminal; + + return MAILIMF_NO_ERROR; +} + + +int mailimf_ignore_field_parse(const char * message, size_t length, + size_t * index) +{ + int has_field; + size_t cur_token; + int state; + size_t terminal; + + has_field = FALSE; + cur_token = * index; + + terminal = cur_token; + state = UNSTRUCTURED_START; + + /* check if this is not a beginning CRLF */ + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch (message[cur_token]) { + case '\r': + return MAILIMF_ERROR_PARSE; + case '\n': + return MAILIMF_ERROR_PARSE; + } + + while (state != UNSTRUCTURED_OUT) { + + switch(state) { + case UNSTRUCTURED_START: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + case ':': + has_field = TRUE; + state = UNSTRUCTURED_START; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_CR: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\n': + state = UNSTRUCTURED_LF; + break; + case ':': + has_field = TRUE; + state = UNSTRUCTURED_START; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_LF: + if (cur_token >= length) { + terminal = cur_token; + state = UNSTRUCTURED_OUT; + break; + } + + switch(message[cur_token]) { + case '\t': + case ' ': + state = UNSTRUCTURED_WSP; + break; + default: + terminal = cur_token; + state = UNSTRUCTURED_OUT; + break; + } + break; + case UNSTRUCTURED_WSP: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + case ':': + has_field = TRUE; + state = UNSTRUCTURED_START; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + } + + cur_token ++; + } + + if (!has_field) + return MAILIMF_ERROR_PARSE; + + * index = terminal; + + return MAILIMF_NO_ERROR; +} + + +/* +date-time = [ day-of-week "," ] date FWS time [CFWS] +*/ + +int mailimf_date_time_parse(const char * message, size_t length, + size_t * index, + struct mailimf_date_time ** result) +{ + size_t cur_token; + int day_of_week; + struct mailimf_date_time * date_time; + int day; + int month; + int year; + int hour; + int min; + int sec; + int zone; + int r; + + cur_token = * index; + + day_of_week = -1; + r = mailimf_day_of_week_parse(message, length, &cur_token, &day_of_week); + if (r == MAILIMF_NO_ERROR) { + r = mailimf_comma_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + } + else if (r != MAILIMF_ERROR_PARSE) + return r; + + r = mailimf_date_parse(message, length, &cur_token, &day, &month, &year); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_fws_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_time_parse(message, length, &cur_token, + &hour, &min, &sec, &zone); + if (r != MAILIMF_NO_ERROR) + return r; + + date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone); + if (date_time == NULL) + return MAILIMF_ERROR_MEMORY; + + * index = cur_token; + * result = date_time; + + return MAILIMF_NO_ERROR; +} + +/* +day-of-week = ([FWS] day-name) / obs-day-of-week +*/ + +static int mailimf_day_of_week_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + int day_of_week; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_day_name_parse(message, length, &cur_token, &day_of_week); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = day_of_week; + + return MAILIMF_NO_ERROR; +} + +/* +day-name = "Mon" / "Tue" / "Wed" / "Thu" / + "Fri" / "Sat" / "Sun" +*/ + +struct mailimf_token_value { + int value; + char * str; +}; + +static struct mailimf_token_value day_names[] = { + {1, "Mon"}, + {2, "Tue"}, + {3, "Wed"}, + {4, "Thu"}, + {5, "Fri"}, + {6, "Sat"}, + {7, "Sun"}, +}; + +enum { + DAY_NAME_START, + DAY_NAME_T, + DAY_NAME_S +}; + +static int guess_day_name(const char * message, size_t length, size_t index) +{ + int state; + + state = DAY_NAME_START; + + while (1) { + + if (index >= length) + return -1; + + switch(state) { + case DAY_NAME_START: + switch((char) toupper((unsigned char) message[index])) { + case 'M': /* Mon */ + return 1; + break; + case 'T': /* Tue Thu */ + state = DAY_NAME_T; + break; + case 'W': /* Wed */ + return 3; + case 'F': + return 5; + case 'S': /* Sat Sun */ + state = DAY_NAME_S; + break; + default: + return -1; + } + break; + case DAY_NAME_T: + switch((char) toupper((unsigned char) message[index])) { + case 'U': + return 2; + case 'H': + return 4; + default: + return -1; + } + break; + case DAY_NAME_S: + switch((char) toupper((unsigned char) message[index])) { + case 'A': + return 6; + case 'U': + return 7; + default: + return -1; + } + break; + } + + index ++; + } +} + +static int mailimf_day_name_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + int day_of_week; + int guessed_day; + int r; + + cur_token = * index; + + guessed_day = guess_day_name(message, length, cur_token); + if (guessed_day == -1) + return MAILIMF_ERROR_PARSE; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, + day_names[guessed_day - 1].str); + if (r != MAILIMF_NO_ERROR) + return r; + + day_of_week = guessed_day; + + * result = day_of_week; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +date = day month year +*/ + +static int mailimf_date_parse(const char * message, size_t length, + size_t * index, + int * pday, int * pmonth, int * pyear) +{ + size_t cur_token; + int day; + int month; + int year; + int r; + + cur_token = * index; + + r = mailimf_day_parse(message, length, &cur_token, &day); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_month_parse(message, length, &cur_token, &month); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_year_parse(message, length, &cur_token, &year); + if (r != MAILIMF_NO_ERROR) + return r; + + * pday = day; + * pmonth = month; + * pyear = year; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +year = 4*DIGIT / obs-year +*/ + +static int mailimf_year_parse(const char * message, size_t length, + size_t * index, int * result) +{ + uint32_t number; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_number_parse(message, length, &cur_token, &number); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = number; + + return MAILIMF_NO_ERROR; +} + +/* +month = (FWS month-name FWS) / obs-month +*/ + +static int mailimf_month_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + int month; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_month_name_parse(message, length, &cur_token, &month); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = month; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +month-name = "Jan" / "Feb" / "Mar" / "Apr" / + "May" / "Jun" / "Jul" / "Aug" / + "Sep" / "Oct" / "Nov" / "Dec" +*/ + +static struct mailimf_token_value month_names[] = { + {1, "Jan"}, + {2, "Feb"}, + {3, "Mar"}, + {4, "Apr"}, + {5, "May"}, + {6, "Jun"}, + {7, "Jul"}, + {8, "Aug"}, + {9, "Sep"}, + {10, "Oct"}, + {11, "Nov"}, + {12, "Dec"}, +}; + +enum { + MONTH_START, + MONTH_J, + MONTH_JU, + MONTH_M, + MONTH_MA, + MONTH_A +}; + +static int guess_month(const char * message, size_t length, size_t index) +{ + int state; + + state = MONTH_START; + + while (1) { + + if (index >= length) + return -1; + + switch(state) { + case MONTH_START: + switch((char) toupper((unsigned char) message[index])) { + case 'J': /* Jan Jun Jul */ + state = MONTH_J; + break; + case 'F': /* Feb */ + return 2; + case 'M': /* Mar May */ + state = MONTH_M; + break; + case 'A': /* Apr Aug */ + state = MONTH_A; + break; + case 'S': /* Sep */ + return 9; + case 'O': /* Oct */ + return 10; + case 'N': /* Nov */ + return 11; + case 'D': /* Dec */ + return 12; + default: + return -1; + } + break; + case MONTH_J: + switch((char) toupper((unsigned char) message[index])) { + case 'A': + return 1; + case 'U': + state = MONTH_JU; + break; + default: + return -1; + } + break; + case MONTH_JU: + switch((char) toupper((unsigned char) message[index])) { + case 'N': + return 6; + case 'L': + return 7; + default: + return -1; + } + break; + case MONTH_M: + switch((char) toupper((unsigned char) message[index])) { + case 'A': + state = MONTH_MA; + break; + default: + return -1; + } + break; + case MONTH_MA: + switch((char) toupper((unsigned char) message[index])) { + case 'Y': + return 5; + case 'R': + return 3; + default: + return -1; + } + break; + case MONTH_A: + switch((char) toupper((unsigned char) message[index])) { + case 'P': + return 4; + case 'U': + return 8; + default: + return -1; + } + break; + } + + index ++; + } +} + +static int mailimf_month_name_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + int month; + int guessed_month; + int r; + + cur_token = * index; + + guessed_month = guess_month(message, length, cur_token); + if (guessed_month == -1) + return MAILIMF_ERROR_PARSE; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, + month_names[guessed_month - 1].str); + if (r != MAILIMF_NO_ERROR) + return r; + + month = guessed_month; + + * result = month; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +day = ([FWS] 1*2DIGIT) / obs-day +*/ + +static int mailimf_day_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + uint32_t day; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_number_parse(message, length, &cur_token, &day); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = day; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +time = time-of-day FWS zone +*/ + +static int mailimf_time_parse(const char * message, size_t length, + size_t * index, + int * phour, int * pmin, + int * psec, + int * pzone) +{ + size_t cur_token; + int hour; + int min; + int sec; + int zone; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_time_of_day_parse(message, length, &cur_token, + &hour, &min, &sec); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_zone_parse(message, length, &cur_token, &zone); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + zone = 0; + } + else { + return r; + } + + * phour = hour; + * pmin = min; + * psec = sec; + * pzone = zone; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +time-of-day = hour ":" minute [ ":" second ] +*/ + +static int mailimf_time_of_day_parse(const char * message, size_t length, + size_t * index, + int * phour, int * pmin, + int * psec) +{ + int hour; + int min; + int sec; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_hour_parse(message, length, &cur_token, &hour); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_minute_parse(message, length, &cur_token, &min); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_colon_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + r = mailimf_second_parse(message, length, &cur_token, &sec); + if (r != MAILIMF_NO_ERROR) + return r; + } + else if (r == MAILIMF_ERROR_PARSE) + sec = 0; + else + return r; + + * phour = hour; + * pmin = min; + * psec = sec; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +hour = 2DIGIT / obs-hour +*/ + +static int mailimf_hour_parse(const char * message, size_t length, + size_t * index, int * result) +{ + uint32_t hour; + int r; + + r = mailimf_number_parse(message, length, index, &hour); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = hour; + + return MAILIMF_NO_ERROR; +} + +/* +minute = 2DIGIT / obs-minute +*/ + +static int mailimf_minute_parse(const char * message, size_t length, + size_t * index, int * result) +{ + uint32_t minute; + int r; + + r = mailimf_number_parse(message, length, index, &minute); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = minute; + + return MAILIMF_NO_ERROR; +} + +/* +second = 2DIGIT / obs-second +*/ + +static int mailimf_second_parse(const char * message, size_t length, + size_t * index, int * result) +{ + uint32_t second; + int r; + + r = mailimf_number_parse(message, length, index, &second); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = second; + + return MAILIMF_NO_ERROR; +} + +/* +zone = (( "+" / "-" ) 4DIGIT) / obs-zone +*/ + +/* +obs-zone = "UT" / "GMT" / ; Universal Time + ; North American UT + ; offsets + "EST" / "EDT" / ; Eastern: - 5/ - 4 + "CST" / "CDT" / ; Central: - 6/ - 5 + "MST" / "MDT" / ; Mountain: - 7/ - 6 + "PST" / "PDT" / ; Pacific: - 8/ - 7 + + %d65-73 / ; Military zones - "A" + %d75-90 / ; through "I" and "K" + %d97-105 / ; through "Z", both + %d107-122 ; upper and lower case +*/ + +enum { + STATE_ZONE_1 = 0, + STATE_ZONE_2 = 1, + STATE_ZONE_3 = 2, + STATE_ZONE_OK = 3, + STATE_ZONE_ERR = 4, + STATE_ZONE_CONT = 5, +}; + +static int mailimf_zone_parse(const char * message, size_t length, + size_t * index, int * result) +{ + uint32_t zone; + int sign; + size_t cur_token; + int r; + + cur_token = * index; + + if (cur_token + 1 < length) { + if ((message[cur_token] == 'U') && (message[cur_token] == 'T')) { + * result = TRUE; + * index = cur_token + 2; + + return MAILIMF_NO_ERROR; + } + } + + if (cur_token + 2 < length) { + int state; + + state = STATE_ZONE_1; + + while (state <= 2) { + switch (state) { + case STATE_ZONE_1: + switch (message[cur_token]) { + case 'G': + if (message[cur_token + 1] == 'M' && message[cur_token + 2] == 'T') { + zone = 0; + state = STATE_ZONE_OK; + } + else { + state = STATE_ZONE_ERR; + } + break; + case 'E': + zone = -5; + state = STATE_ZONE_2; + break; + case 'C': + zone = -6; + state = STATE_ZONE_2; + break; + case 'M': + zone = -7; + state = STATE_ZONE_2; + break; + case 'P': + zone = -8; + state = STATE_ZONE_2; + break; + default: + state = STATE_ZONE_CONT; + break; + } + break; + case STATE_ZONE_2: + switch (message[cur_token + 1]) { + case 'S': + state = STATE_ZONE_3; + break; + case 'D': + zone ++; + state = STATE_ZONE_3; + break; + default: + state = STATE_ZONE_ERR; + break; + } + break; + case STATE_ZONE_3: + if (message[cur_token + 2] == 'T') { + zone *= 100; + state = STATE_ZONE_OK; + } + else + state = STATE_ZONE_ERR; + break; + } + } + + switch (state) { + case STATE_ZONE_OK: + * result = zone; + * index = cur_token + 3; + return MAILIMF_NO_ERROR; + + case STATE_ZONE_ERR: + return MAILIMF_ERROR_PARSE; + } + } + + sign = 1; + r = mailimf_plus_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + sign = 1; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_minus_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + sign = -1; + } + + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + sign = 1; + else + return r; + + r = mailimf_number_parse(message, length, &cur_token, &zone); + if (r != MAILIMF_NO_ERROR) + return r; + + zone = zone * sign; + + * index = cur_token; + * result = zone; + + return MAILIMF_NO_ERROR; +} + +/* +address = mailbox / group +*/ + +int mailimf_address_parse(const char * message, size_t length, + size_t * index, + struct mailimf_address ** result) +{ + int type; + size_t cur_token; + struct mailimf_mailbox * mailbox; + struct mailimf_group * group; + struct mailimf_address * address; + int r; + int res; + + cur_token = * index; + + mailbox = NULL; + group = NULL; + + type = MAILIMF_ADDRESS_ERROR; /* XXX - removes a gcc warning */ + r = mailimf_group_parse(message, length, &cur_token, &group); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ADDRESS_GROUP; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_mailbox_parse(message, length, &cur_token, &mailbox); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ADDRESS_MAILBOX; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + address = mailimf_address_new(type, mailbox, group); + if (address == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = address; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (mailbox != NULL) + mailimf_mailbox_free(mailbox); + if (group != NULL) + mailimf_group_free(group); + err: + return res; +} + + +/* +mailbox = name-addr / addr-spec +*/ + + +int mailimf_mailbox_parse(const char * message, size_t length, + size_t * index, + struct mailimf_mailbox ** result) +{ + size_t cur_token; + char * display_name; + struct mailimf_mailbox * mailbox; + char * addr_spec; + int r; + int res; + + cur_token = * index; + display_name = NULL; + addr_spec = NULL; + + r = mailimf_name_addr_parse(message, length, &cur_token, + &display_name, &addr_spec); + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec); + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + mailbox = mailimf_mailbox_new(display_name, addr_spec); + if (mailbox == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = mailbox; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (display_name != NULL) + mailimf_display_name_free(display_name); + if (addr_spec != NULL) + mailimf_addr_spec_free(addr_spec); + err: + return res; +} + +/* +name-addr = [display-name] angle-addr +*/ + +static int mailimf_name_addr_parse(const char * message, size_t length, + size_t * index, + char ** pdisplay_name, + char ** pangle_addr) +{ + char * display_name; + char * angle_addr; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + display_name = NULL; + angle_addr = NULL; + + r = mailimf_display_name_parse(message, length, &cur_token, &display_name); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_angle_addr_parse(message, length, &cur_token, &angle_addr); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_display_name; + } + + * pdisplay_name = display_name; + * pangle_addr = angle_addr; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_display_name: + if (display_name != NULL) + mailimf_display_name_free(display_name); + err: + return res; +} + +/* +angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr +*/ + +static int mailimf_angle_addr_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + char * addr_spec; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_lower_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_greater_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + free(addr_spec); + return r; + } + + * result = addr_spec; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +group = display-name ":" [mailbox-list / CFWS] ";" + [CFWS] +*/ + +static int mailimf_group_parse(const char * message, size_t length, + size_t * index, + struct mailimf_group ** result) +{ + size_t cur_token; + char * display_name; + struct mailimf_mailbox_list * mailbox_list; + struct mailimf_group * group; + int r; + int res; + + cur_token = * index; + + mailbox_list = NULL; + + r = mailimf_display_name_parse(message, length, &cur_token, &display_name); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_display_name; + } + + r = mailimf_mailbox_list_parse(message, length, &cur_token, &mailbox_list); + switch (r) { + case MAILIMF_NO_ERROR: + break; + case MAILIMF_ERROR_PARSE: + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + break; + default: + return r; + } + + r = mailimf_semi_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mailbox_list; + } + + group = mailimf_group_new(display_name, mailbox_list); + if (group == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mailbox_list; + } + + * index = cur_token; + * result = group; + + return MAILIMF_NO_ERROR; + + free_mailbox_list: + mailimf_mailbox_list_free(mailbox_list); + free_display_name: + mailimf_display_name_free(display_name); + err: + return res; +} + +/* +display-name = phrase +*/ + +static int mailimf_display_name_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_phrase_parse(message, length, index, result); +} + +/* +mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list +*/ + +int +mailimf_mailbox_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_mailbox_list ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_mailbox_list * mailbox_list; + int r; + int res; + + cur_token = * index; + + r = mailimf_struct_list_parse(message, length, + &cur_token, &list, ',', + (mailimf_struct_parser *) + mailimf_mailbox_parse, + (mailimf_struct_destructor *) + mailimf_mailbox_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + mailbox_list = mailimf_mailbox_list_new(list); + if (mailbox_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = mailbox_list; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL); + clist_free(list); + err: + return res; +} + +/* +address-list = (address *("," address)) / obs-addr-list +*/ + + +int +mailimf_address_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_address_list ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_address_list * address_list; + int r; + int res; + + cur_token = * index; + + r = mailimf_struct_list_parse(message, length, + &cur_token, &list, ',', + (mailimf_struct_parser *) + mailimf_address_parse, + (mailimf_struct_destructor *) + mailimf_address_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + address_list = mailimf_address_list_new(list); + if (address_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = address_list; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_address_free, NULL); + clist_free(list); + err: + return res; +} + +/* +addr-spec = local-part "@" domain +*/ + + +static int mailimf_addr_spec_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + size_t cur_token; +#if 0 + char * local_part; + char * domain; +#endif + char * addr_spec; + int r; + int res; + size_t begin; + size_t end; + int final; + size_t count; + const char * src; + char * dest; + size_t i; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + end = cur_token; + if (end >= length) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + begin = cur_token; + + final = FALSE; + while (1) { + switch (message[end]) { + case '>': + case ',': + case '\r': + case '\n': + case '(': + case ')': + case ':': + case ';': + final = TRUE; + break; + } + + if (final) + break; + + end ++; + if (end >= length) + break; + } + + if (end == begin) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + addr_spec = malloc(end - cur_token + 1); + if (addr_spec == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + count = end - cur_token; + src = message + cur_token; + dest = addr_spec; + for(i = 0 ; i < count ; i ++) { + if ((* src != ' ') && (* src != '\t')) { + * dest = * src; + dest ++; + } + src ++; + } + * dest = '\0'; + +#if 0 + strncpy(addr_spec, message + cur_token, end - cur_token); + addr_spec[end - cur_token] = '\0'; +#endif + + cur_token = end; + +#if 0 + r = mailimf_local_part_parse(message, length, &cur_token, &local_part); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_at_sign_parse(message, length, &cur_token); + switch (r) { + case MAILIMF_NO_ERROR: + r = mailimf_domain_parse(message, length, &cur_token, &domain); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_local_part; + } + break; + + case MAILIMF_ERROR_PARSE: + domain = NULL; + break; + + default: + res = r; + goto free_local_part; + } + + if (domain) { + addr_spec = malloc(strlen(local_part) + strlen(domain) + 2); + if (addr_spec == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_domain; + } + + strcpy(addr_spec, local_part); + strcat(addr_spec, "@"); + strcat(addr_spec, domain); + + mailimf_domain_free(domain); + mailimf_local_part_free(local_part); + } + else { + addr_spec = local_part; + } +#endif + + * result = addr_spec; + * index = cur_token; + + return MAILIMF_NO_ERROR; + +#if 0 + free_domain: + mailimf_domain_free(domain); + free_local_part: + mailimf_local_part_free(local_part); +#endif + err: + return res; +} + +/* +local-part = dot-atom / quoted-string / obs-local-part +*/ + +#if 0 +static int mailimf_local_part_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + int r; + + r = mailimf_dot_atom_parse(message, length, index, result); + switch (r) { + case MAILIMF_NO_ERROR: + return r; + case MAILIMF_ERROR_PARSE: + break; + default: + return r; + } + + r = mailimf_quoted_string_parse(message, length, index, result); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +domain = dot-atom / domain-literal / obs-domain +*/ + +#if 0 +static int mailimf_domain_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + int r; + + r = mailimf_dot_atom_parse(message, length, index, result); + switch (r) { + case MAILIMF_NO_ERROR: + return r; + case MAILIMF_ERROR_PARSE: + break; + default: + return r; + } + + r = mailimf_domain_literal_parse(message, length, index, result); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +[FWS] dcontent +*/ + +#if 0 +static int +mailimf_domain_literal_fws_dcontent_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_dcontent_parse(message, length, &cur_token, &ch); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS] +*/ + +#if 0 +static int mailimf_domain_literal_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + int len; + int begin; + char * domain_literal; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + begin = cur_token; + r = mailimf_obracket_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + while (1) { + r = mailimf_domain_literal_fws_dcontent_parse(message, length, + &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_cbracket_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + len = cur_token - begin; + + domain_literal = malloc(len + 1); + if (domain_literal == NULL) + return MAILIMF_ERROR_MEMORY; + strncpy(domain_literal, message + begin, len); + domain_literal[len] = '\0'; + + * result = domain_literal; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +dcontent = dtext / quoted-pair +*/ + +#if 0 +static int mailimf_dcontent_parse(const char * message, size_t length, + size_t * index, char * result) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_dtext(message[cur_token])) { + ch = message[cur_token]; + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r != MAILIMF_NO_ERROR) + return r; + } + + * index = cur_token; + * result = ch; + + return MAILIMF_NO_ERROR; +} +#endif + + +/* +dtext = NO-WS-CTL / ; Non white space controls + + %d33-90 / ; The rest of the US-ASCII + %d94-126 ; characters not including "[", + ; "]", or "\" +*/ + +static inline int is_dtext(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (is_no_ws_ctl(ch)) + return TRUE; + + if (uch < 33) + return FALSE; + + if ((uch >= 91) && (uch <= 93)) + return FALSE; + + if (uch == 127) + return FALSE; + + return TRUE; +} + +/* +message = (fields / obs-fields) + [CRLF body] +*/ + +int mailimf_message_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message ** result) +{ + struct mailimf_fields * fields; + struct mailimf_body * body; + struct mailimf_message * msg; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_fields_parse(message, length, &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_crlf_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_body_parse(message, length, &cur_token, &body); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_fields; + } + + msg = mailimf_message_new(fields, body); + if (msg == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_body; + } + + * index = cur_token; + * result = msg; + + return MAILIMF_NO_ERROR; + + free_body: + mailimf_body_free(body); + free_fields: + mailimf_fields_free(fields); + err: + return res; +} + +/* +body = *(*998text CRLF) *998text +*/ + +int mailimf_body_parse(const char * message, size_t length, + size_t * index, + struct mailimf_body ** result) +{ + size_t cur_token; + struct mailimf_body * body; + + cur_token = * index; + + body = mailimf_body_new(message + cur_token, length - cur_token); + if (body == NULL) + return MAILIMF_ERROR_MEMORY; + + cur_token = length; + + * result = body; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +CHANGE TO THE RFC 2822 + +original : + +fields = *(trace + *(resent-date / + resent-from / + resent-sender / + resent-to / + resent-cc / + resent-bcc / + resent-msg-id)) + *(orig-date / + from / + sender / + reply-to / + to / + cc / + bcc / + message-id / + in-reply-to / + references / + subject / + comments / + keywords / + optional-field) + +INTO THE FOLLOWING : +*/ + +/* +resent-fields-list = *(resent-date / + resent-from / + resent-sender / + resent-to / + resent-cc / + resent-bcc / + resent-msg-id)) +*/ + +#if 0 +enum { + RESENT_HEADER_START, +}; + +static int guess_resent_header_type(char * message, + size_t length, size_t index) +{ + int r; + + r = mailimf_token_case_insensitive_parse(message, + length, &index, "Resent-"); + if (r != MAILIMF_NO_ERROR) + return MAILIMF_RESENT_FIELD_NONE; + + if (index >= length) + return MAILIMF_RESENT_FIELD_NONE; + + switch(toupper(message[index])) { + case 'D': + return MAILIMF_RESENT_FIELD_DATE; + case 'F': + return MAILIMF_RESENT_FIELD_FROM; + case 'S': + return MAILIMF_RESENT_FIELD_SENDER; + case 'T': + return MAILIMF_RESENT_FIELD_TO; + case 'C': + return MAILIMF_RESENT_FIELD_CC; + case 'B': + return MAILIMF_RESENT_FIELD_BCC; + case 'M': + return MAILIMF_RESENT_FIELD_MSG_ID; + default: + return MAILIMF_RESENT_FIELD_NONE; + } +} +#endif + +#if 0 +static int +mailimf_resent_field_parse(const char * message, size_t length, + size_t * index, + struct mailimf_resent_field ** result) +{ + struct mailimf_orig_date * resent_date; + struct mailimf_from * resent_from; + struct mailimf_sender * resent_sender; + struct mailimf_to* resent_to; + struct mailimf_cc * resent_cc; + struct mailimf_bcc * resent_bcc; + struct mailimf_message_id * resent_msg_id; + size_t cur_token; + int type; + struct mailimf_resent_field * resent_field; + int r; + int res; + + cur_token = * index; + + resent_date = NULL; + resent_from = NULL; + resent_sender = NULL; + resent_to = NULL; + resent_cc = NULL; + resent_bcc = NULL; + resent_msg_id = NULL; + + type = guess_resent_header_type(message, length, cur_token); + + switch(type) { + case MAILIMF_RESENT_FIELD_DATE: + r = mailimf_resent_date_parse(message, length, &cur_token, + &resent_date); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_FROM: + r = mailimf_resent_from_parse(message, length, &cur_token, + &resent_from); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_SENDER: + r = mailimf_resent_sender_parse(message, length, &cur_token, + &resent_sender); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_TO: + r = mailimf_resent_to_parse(message, length, &cur_token, + &resent_to); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_CC: + r= mailimf_resent_cc_parse(message, length, &cur_token, + &resent_cc); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_BCC: + r = mailimf_resent_bcc_parse(message, length, &cur_token, + &resent_bcc); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_MSG_ID: + r = mailimf_resent_msg_id_parse(message, length, &cur_token, + &resent_msg_id); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + default: + res = MAILIMF_ERROR_PARSE; + goto err; + } + + resent_field = mailimf_resent_field_new(type, resent_date, + resent_from, resent_sender, + resent_to, resent_cc, + resent_bcc, resent_msg_id); + if (resent_field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_resent; + } + + * result = resent_field; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_resent: + if (resent_msg_id != NULL) + mailimf_message_id_free(resent_msg_id); + if (resent_bcc != NULL) + mailimf_bcc_free(resent_bcc); + if (resent_cc != NULL) + mailimf_cc_free(resent_cc); + if (resent_to != NULL) + mailimf_to_free(resent_to); + if (resent_sender != NULL) + mailimf_sender_free(resent_sender); + if (resent_from != NULL) + mailimf_from_free(resent_from); + if (resent_date != NULL) + mailimf_orig_date_free(resent_date); + err: + return res; +} +#endif + +#if 0 +static int +mailimf_resent_fields_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_resent_fields_list ** result) +{ + clist * list; + size_t cur_token; + struct mailimf_resent_fields_list * resent_fields_list; + int r; + int res; + + cur_token = * index; + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, &list, + (mailimf_struct_parser *) + mailimf_resent_field_parse, + (mailimf_struct_destructor *) + mailimf_resent_field_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + resent_fields_list = mailimf_resent_fields_list_new(list); + if (resent_fields_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = resent_fields_list; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_resent_field_free, NULL); + clist_free(list); + err: + return res; +} +#endif + +/* + ([trace] + [resent-fields-list]) +*/ + +#if 0 +static int +mailimf_trace_resent_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_trace_resent_fields ** result) +{ + size_t cur_token; + struct mailimf_return * return_path; + struct mailimf_resent_fields_list * resent_fields; + struct mailimf_trace_resent_fields * trace_resent_fields; + int res; + int r; + + cur_token = * index; + + return_path = NULL; + resent_fields = NULL; + + r = mailimf_return_parse(message, length, &cur_token, + &return_path); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_resent_fields_list_parse(message, length, &cur_token, + &resent_fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + if ((return_path == NULL) && (resent_fields == NULL)) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + trace_resent_fields = mailimf_trace_resent_fields_new(return_path, + resent_fields); + if (trace_resent_fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_resent_fields; + } + + * result = trace_resent_fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_resent_fields: + if (resent_fields != NULL) + mailimf_resent_fields_list_free(resent_fields); + if (return_path != NULL) + mailimf_return_free(return_path); + err: + return res; +} +#endif + +/* +delivering-info = *([trace] + [resent-fields-list]) +*/ + +#if 0 +static int +mailimf_delivering_info_parse(const char * message, size_t length, + size_t * index, + struct mailimf_delivering_info ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_delivering_info * delivering_info; + int r; + int res; + + cur_token = * index; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_trace_resent_fields_parse, + (mailimf_struct_destructor *) + mailimf_trace_resent_fields_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + delivering_info = mailimf_delivering_info_new(list); + if (delivering_info == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = delivering_info; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_trace_resent_fields_free, NULL); + clist_free(list); + err: + return res; +} +#endif + +/* +field = delivering-info / + orig-date / + from / + sender / + reply-to / + to / + cc / + bcc / + message-id / + in-reply-to / + references / + subject / + comments / + keywords / + optional-field +*/ + +enum { + HEADER_START, + HEADER_C, + HEADER_R, + HEADER_RE, + HEADER_S, + HEADER_RES, +}; + +static int guess_header_type(const char * message, size_t length, size_t index) +{ + int state; + int r; + + state = HEADER_START; + + while (1) { + + if (index >= length) + return MAILIMF_FIELD_NONE; + + switch(state) { + case HEADER_START: + switch((char) toupper((unsigned char) message[index])) { + case 'B': + return MAILIMF_FIELD_BCC; + case 'C': + state = HEADER_C; + break; + case 'D': + return MAILIMF_FIELD_ORIG_DATE; + case 'F': + return MAILIMF_FIELD_FROM; + case 'I': + return MAILIMF_FIELD_IN_REPLY_TO; + case 'K': + return MAILIMF_FIELD_KEYWORDS; + case 'M': + return MAILIMF_FIELD_MESSAGE_ID; + case 'R': + state = HEADER_R; + break; + case 'T': + return MAILIMF_FIELD_TO; + break; + case 'S': + state = HEADER_S; + break; + default: + return MAILIMF_FIELD_NONE; + } + break; + case HEADER_C: + switch((char) toupper((unsigned char) message[index])) { + case 'O': + return MAILIMF_FIELD_COMMENTS; + case 'C': + return MAILIMF_FIELD_CC; + default: + return MAILIMF_FIELD_NONE; + } + break; + case HEADER_R: + switch((char) toupper((unsigned char) message[index])) { + case 'E': + state = HEADER_RE; + break; + default: + return MAILIMF_FIELD_NONE; + } + break; + case HEADER_RE: + switch((char) toupper((unsigned char) message[index])) { + case 'F': + return MAILIMF_FIELD_REFERENCES; + case 'P': + return MAILIMF_FIELD_REPLY_TO; + case 'S': + state = HEADER_RES; + break; + case 'T': + return MAILIMF_FIELD_RETURN_PATH; + default: + return MAILIMF_FIELD_NONE; + } + break; + case HEADER_S: + switch((char) toupper((unsigned char) message[index])) { + case 'E': + return MAILIMF_FIELD_SENDER; + case 'U': + return MAILIMF_FIELD_SUBJECT; + default: + return MAILIMF_FIELD_NONE; + } + break; + + case HEADER_RES: + r = mailimf_token_case_insensitive_parse(message, + length, &index, "ent-"); + if (r != MAILIMF_NO_ERROR) + return MAILIMF_FIELD_NONE; + + if (index >= length) + return MAILIMF_FIELD_NONE; + + switch((char) toupper((unsigned char) message[index])) { + case 'D': + return MAILIMF_FIELD_RESENT_DATE; + case 'F': + return MAILIMF_FIELD_RESENT_FROM; + case 'S': + return MAILIMF_FIELD_RESENT_SENDER; + case 'T': + return MAILIMF_FIELD_RESENT_TO; + case 'C': + return MAILIMF_FIELD_RESENT_CC; + case 'B': + return MAILIMF_FIELD_RESENT_BCC; + case 'M': + return MAILIMF_FIELD_RESENT_MSG_ID; + default: + return MAILIMF_FIELD_NONE; + } + break; + } + index ++; + } +} + +static int mailimf_field_parse(const char * message, size_t length, + size_t * index, + struct mailimf_field ** result) +{ + size_t cur_token; + int type; + struct mailimf_return * return_path; + struct mailimf_orig_date * resent_date; + struct mailimf_from * resent_from; + struct mailimf_sender * resent_sender; + struct mailimf_to* resent_to; + struct mailimf_cc * resent_cc; + struct mailimf_bcc * resent_bcc; + struct mailimf_message_id * resent_msg_id; + struct mailimf_orig_date * orig_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 * message_id; + struct mailimf_in_reply_to * in_reply_to; + struct mailimf_references * references; + struct mailimf_subject * subject; + struct mailimf_comments * comments; + struct mailimf_keywords * keywords; + struct mailimf_optional_field * optional_field; + struct mailimf_field * field; + int guessed_type; + int r; + int res; + + cur_token = * index; + + 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; + orig_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 = NULL; + + guessed_type = guess_header_type(message, length, cur_token); + type = MAILIMF_FIELD_NONE; + + switch (guessed_type) { + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_orig_date_parse(message, length, &cur_token, + &orig_date); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_FIELD_ORIG_DATE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_FROM: + r = mailimf_from_parse(message, length, &cur_token, + &from); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_sender_parse(message, length, &cur_token, + &sender); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_reply_to_parse(message, length, &cur_token, + &reply_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_TO: + r = mailimf_to_parse(message, length, &cur_token, + &to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_CC: + r = mailimf_cc_parse(message, length, &cur_token, + &cc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_BCC: + r = mailimf_bcc_parse(message, length, &cur_token, + &bcc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_message_id_parse(message, length, &cur_token, + &message_id); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_in_reply_to_parse(message, length, &cur_token, + &in_reply_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_references_parse(message, length, &cur_token, + &references); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_subject_parse(message, length, &cur_token, + &subject); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_COMMENTS: + r = mailimf_comments_parse(message, length, &cur_token, + &comments); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_KEYWORDS: + r = mailimf_keywords_parse(message, length, &cur_token, + &keywords); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RETURN_PATH: + r = mailimf_return_parse(message, length, &cur_token, + &return_path); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_DATE: + r = mailimf_resent_date_parse(message, length, &cur_token, + &resent_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_FROM: + r = mailimf_resent_from_parse(message, length, &cur_token, + &resent_from); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_SENDER: + r = mailimf_resent_sender_parse(message, length, &cur_token, + &resent_sender); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_TO: + r = mailimf_resent_to_parse(message, length, &cur_token, + &resent_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_CC: + r= mailimf_resent_cc_parse(message, length, &cur_token, + &resent_cc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_BCC: + r = mailimf_resent_bcc_parse(message, length, &cur_token, + &resent_bcc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + r = mailimf_resent_msg_id_parse(message, length, &cur_token, + &resent_msg_id); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + } + + if (type == MAILIMF_FIELD_NONE) { + r = mailimf_optional_field_parse(message, length, &cur_token, + &optional_field); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMF_FIELD_OPTIONAL_FIELD; + } + + field = mailimf_field_new(type, return_path, resent_date, + resent_from, resent_sender, resent_to, resent_cc, resent_bcc, + resent_msg_id, orig_date, from, sender, reply_to, to, + cc, bcc, message_id, in_reply_to, references, + subject, comments, keywords, optional_field); + if (field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_field; + } + + * result = field; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_field: + if (return_path != NULL) + mailimf_return_free(return_path); + if (resent_date != NULL) + mailimf_orig_date_free(resent_date); + if (resent_from != NULL) + mailimf_from_free(resent_from); + if (resent_sender != NULL) + mailimf_sender_free(resent_sender); + if (resent_to != NULL) + mailimf_to_free(resent_to); + if (resent_cc != NULL) + mailimf_cc_free(resent_cc); + if (resent_bcc != NULL) + mailimf_bcc_free(resent_bcc); + if (resent_msg_id != NULL) + mailimf_message_id_free(resent_msg_id); + if (orig_date != NULL) + mailimf_orig_date_free(orig_date); + if (from != NULL) + mailimf_from_free(from); + if (sender != NULL) + mailimf_sender_free(sender); + if (reply_to != NULL) + mailimf_reply_to_free(reply_to); + if (to != NULL) + mailimf_to_free(to); + if (cc != NULL) + mailimf_cc_free(cc); + if (bcc != NULL) + mailimf_bcc_free(bcc); + if (message_id != NULL) + mailimf_message_id_free(message_id); + if (in_reply_to != NULL) + mailimf_in_reply_to_free(in_reply_to); + if (references != NULL) + mailimf_references_free(references); + if (subject != NULL) + mailimf_subject_free(subject); + if (comments != NULL) + mailimf_comments_free(comments); + if (keywords != NULL) + mailimf_keywords_free(keywords); + if (optional_field != NULL) + mailimf_optional_field_free(optional_field); + err: + return res; +} + + +/* +fields = *(delivering-info / + orig-date / + from / + sender / + reply-to / + to / + cc / + bcc / + message-id / + in-reply-to / + references / + subject / + comments / + keywords / + optional-field) +*/ + +#if 0 +int +mailimf_unparsed_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_unparsed_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_unparsed_fields * fields; + int r; + int res; + + cur_token = * index; + + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_optional_field_parse, + (mailimf_struct_destructor *) + mailimf_optional_field_free); + /* + if ((r = MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + */ + + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + + case MAILIMF_ERROR_PARSE: + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + break; + + default: + res = r; + goto err; + } + + fields = mailimf_unparsed_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_optional_field_free, NULL); + clist_free(list); + } + err: + return res; +} +#endif + +int mailimf_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r; + int res; + + cur_token = * index; + + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_field_parse, + (mailimf_struct_destructor *) + mailimf_field_free); + /* + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + */ + + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + + case MAILIMF_ERROR_PARSE: + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + break; + + default: + res = r; + goto err; + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + } + err: + return res; +} + +/* +orig-date = "Date:" date-time CRLF +*/ + + +static int +mailimf_orig_date_parse(const char * message, size_t length, + size_t * index, struct mailimf_orig_date ** result) +{ + struct mailimf_date_time * date_time; + struct mailimf_orig_date * orig_date; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Date:"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_date_time_parse(message, length, &cur_token, &date_time); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_ignore_unstructured_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_date_time; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_date_time; + } + + orig_date = mailimf_orig_date_new(date_time); + if (orig_date == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_date_time; + } + + * result = orig_date; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_date_time: + mailimf_date_time_free(date_time); + err: + return res; +} + +/* +from = "From:" mailbox-list CRLF +*/ + +static int +mailimf_from_parse(const char * message, size_t length, + size_t * index, struct mailimf_from ** result) +{ + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "From"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list); + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mb_list; + } + + from = mailimf_from_new(mb_list); + if (from == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb_list; + } + + * result = from; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_mb_list: + mailimf_mailbox_list_free(mb_list); + err: + return res; +} + +/* +sender = "Sender:" mailbox CRLF +*/ + +static int +mailimf_sender_parse(const char * message, size_t length, + size_t * index, struct mailimf_sender ** result) +{ + struct mailimf_mailbox * mb; + struct mailimf_sender * sender; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Sender"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_parse(message, length, &cur_token, &mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mb; + } + + sender = mailimf_sender_new(mb); + if (sender == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb; + } + + * result = sender; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_mb: + mailimf_mailbox_free(mb); + err: + return res; +} + +/* +reply-to = "Reply-To:" address-list CRLF +*/ + + +static int +mailimf_reply_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_reply_to ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_reply_to * reply_to; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Reply-To"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + reply_to = mailimf_reply_to_new(addr_list); + if (reply_to == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = reply_to; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +to = "To:" address-list CRLF +*/ + +static int +mailimf_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_to ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "To"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + to = mailimf_to_new(addr_list); + if (to == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = to; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +cc = "Cc:" address-list CRLF +*/ + + +static int +mailimf_cc_parse(const char * message, size_t length, + size_t * index, struct mailimf_cc ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Cc"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + cc = mailimf_cc_new(addr_list); + if (cc == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = cc; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +bcc = "Bcc:" (address-list / [CFWS]) CRLF +*/ + + +static int +mailimf_bcc_parse(const char * message, size_t length, + size_t * index, struct mailimf_bcc ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + size_t cur_token; + int r; + int res; + + cur_token = * index; + addr_list = NULL; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Bcc"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + case MAILIMF_ERROR_PARSE: + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + break; + default: + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + bcc = mailimf_bcc_new(addr_list); + if (bcc == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = bcc; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +message-id = "Message-ID:" msg-id CRLF +*/ + +static int mailimf_message_id_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message_id ** result) +{ + char * value; + size_t cur_token; + struct mailimf_message_id * message_id; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Message-ID"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_msg_id_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + message_id = mailimf_message_id_new(value); + if (message_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = message_id; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_msg_id_free(value); + err: + return res; +} + +/* +in-reply-to = "In-Reply-To:" 1*msg-id CRLF +*/ + +int mailimf_msg_id_list_parse(const char * message, size_t length, + size_t * index, clist ** result) +{ + return mailimf_struct_multiple_parse(message, length, index, + result, + (mailimf_struct_parser *) + mailimf_unstrict_msg_id_parse, + (mailimf_struct_destructor *) + mailimf_msg_id_free); +} + +static int mailimf_in_reply_to_parse(const char * message, size_t length, + size_t * index, + struct mailimf_in_reply_to ** result) +{ + struct mailimf_in_reply_to * in_reply_to; + size_t cur_token; + clist * msg_id_list; + int res; + int r; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "In-Reply-To"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_list; + } + + in_reply_to = mailimf_in_reply_to_new(msg_id_list); + if (in_reply_to == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = in_reply_to; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL); + clist_free(msg_id_list); + err: + return res; +} + +/* +references = "References:" 1*msg-id CRLF +*/ + +int mailimf_references_parse(const char * message, size_t length, + size_t * index, + struct mailimf_references ** result) +{ + struct mailimf_references * references; + size_t cur_token; + clist * msg_id_list; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "References"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_list; + } + + references = mailimf_references_new(msg_id_list); + if (references == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = references; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL); + clist_free(msg_id_list); + err: + return res; +} + +/* +msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS] +*/ + +int mailimf_msg_id_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + size_t cur_token; +#if 0 + char * id_left; + char * id_right; +#endif + char * msg_id; + int r; + int res; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_lower_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_addr_spec_parse(message, length, &cur_token, &msg_id); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_greater_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + free(msg_id); + res = r; + goto err; + } + +#if 0 + r = mailimf_id_left_parse(message, length, &cur_token, &id_left); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_at_sign_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_id_left; + } + + r = mailimf_id_right_parse(message, length, &cur_token, &id_right); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_id_left; + } + + r = mailimf_greater_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_id_right; + } + + msg_id = malloc(strlen(id_left) + strlen(id_right) + 2); + if (msg_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_id_right; + } + strcpy(msg_id, id_left); + strcat(msg_id, "@"); + strcat(msg_id, id_right); + + mailimf_id_left_free(id_left); + mailimf_id_right_free(id_right); +#endif + + * result = msg_id; + * index = cur_token; + + return MAILIMF_NO_ERROR; + +#if 0 + free_id_right: + mailimf_id_right_free(id_right); + free_id_left: + mailimf_id_left_free(id_left); +#endif + /* + free: + mailimf_atom_free(msg_id); + */ + err: + return res; +} + +static int mailimf_parse_unwanted_msg_id(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int r; + char * word; + int token_parsed; + + cur_token = * index; + + token_parsed = TRUE; + while (token_parsed) { + token_parsed = FALSE; + r = mailimf_word_parse(message, length, &cur_token, &word); + if (r == MAILIMF_NO_ERROR) { + mailimf_word_free(word); + token_parsed = TRUE; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_semi_colon_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_comma_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_plus_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_colon_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_point_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_at_sign_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + } + + return MAILIMF_NO_ERROR; +} + +static int mailimf_unstrict_msg_id_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + char * msgid; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_parse_unwanted_msg_id(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_msg_id_parse(message, length, &cur_token, &msgid); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_parse_unwanted_msg_id(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = msgid; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +id-left = dot-atom-text / no-fold-quote / obs-id-left +*/ + +#if 0 +static int mailimf_id_left_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + int r; + + r = mailimf_dot_atom_text_parse(message, length, index, result); + switch (r) { + case MAILIMF_NO_ERROR: + return MAILIMF_NO_ERROR; + case MAILIMF_ERROR_PARSE: + break; + default: + return r; + } + + r = mailimf_no_fold_quote_parse(message, length, index, result); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +id-right = dot-atom-text / no-fold-literal / obs-id-right +*/ + +#if 0 +static int mailimf_id_right_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + int r; + + r = mailimf_dot_atom_text_parse(message, length, index, result); + switch (r) { + case MAILIMF_NO_ERROR: + return MAILIMF_NO_ERROR; + case MAILIMF_ERROR_PARSE: + break; + default: + return r; + } + + r = mailimf_no_fold_literal_parse(message, length, index, result); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE +*/ + +#if 0 +static int mailimf_no_fold_quote_char_parse(const char * message, size_t length, + size_t * index, char * result) +{ + char ch; + size_t cur_token; + int r; + + cur_token = * index; + +#if 0 + r = mailimf_qtext_parse(message, length, &cur_token, &ch); +#endif + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_qtext(message[cur_token])) { + ch = message[cur_token]; + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r != MAILIMF_NO_ERROR) + return r; + } + + * index = cur_token; + * result = ch; + + return MAILIMF_NO_ERROR; +} +#endif + +#if 0 +static int mailimf_no_fold_quote_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + size_t begin; + char ch; + char * no_fold_quote; + int r; + int res; + + begin = cur_token; + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + while (1) { + r = mailimf_no_fold_quote_char_parse(message, length, &cur_token, &ch); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto err; + } + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + /* no_fold_quote = strndup(message + begin, cur_token - begin); */ + no_fold_quote = malloc(cur_token - begin + 1); + if (no_fold_quote == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + strncpy(no_fold_quote, message + begin, cur_token - begin); + no_fold_quote[cur_token - begin] = '\0'; + + * result = no_fold_quote; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + err: + return res; +} +#endif + +/* +no-fold-literal = "[" *(dtext / quoted-pair) "]" +*/ + +#if 0 +static inline int +mailimf_no_fold_literal_char_parse(const char * message, size_t length, + size_t * index, char * result) +{ + char ch; + size_t cur_token; + int r; + + cur_token = * index; + +#if 0 + r = mailimf_dtext_parse(message, length, &cur_token, &ch); +#endif + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_dtext(message[cur_token])) { + ch = message[cur_token]; + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r != MAILIMF_NO_ERROR) + return r; + } + + * index = cur_token; + * result = ch; + + return MAILIMF_NO_ERROR; +} +#endif + +#if 0 +static int mailimf_no_fold_literal_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + size_t begin; + char ch; + char * no_fold_literal; + int r; + int res; + + begin = cur_token; + r = mailimf_obracket_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + while (1) { + r = mailimf_no_fold_literal_char_parse(message, length, + &cur_token, &ch); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto err; + } + } + + r = mailimf_cbracket_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + /* + no_fold_literal = strndup(message + begin, cur_token - begin); + */ + no_fold_literal = malloc(cur_token - begin + 1); + if (no_fold_literal == NULL) { + res = MAILIMF_NO_ERROR; + goto err; + } + strncpy(no_fold_literal, message + begin, cur_token - begin); + no_fold_literal[cur_token - begin] = '\0'; + + * result = no_fold_literal; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + err: + return res; +} +#endif + +/* +subject = "Subject:" unstructured CRLF +*/ + +static int mailimf_subject_parse(const char * message, size_t length, + size_t * index, + struct mailimf_subject ** result) +{ + struct mailimf_subject * subject; + char * value; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Subject"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstructured_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + subject = mailimf_subject_new(value); + if (subject == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = subject; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_unstructured_free(value); + err: + return res; +} + +/* +comments = "Comments:" unstructured CRLF +*/ + +static int mailimf_comments_parse(const char * message, size_t length, + size_t * index, + struct mailimf_comments ** result) +{ + struct mailimf_comments * comments; + char * value; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Comments"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstructured_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + comments = mailimf_comments_new(value); + if (comments == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = comments; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_unstructured_free(value); + err: + return res; +} + +/* +keywords = "Keywords:" phrase *("," phrase) CRLF +*/ + +static int mailimf_keywords_parse(const char * message, size_t length, + size_t * index, + struct mailimf_keywords ** result) +{ + struct mailimf_keywords * keywords; + clist * list; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Keywords"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_struct_list_parse(message, length, &cur_token, + &list, ',', + (mailimf_struct_parser *) + mailimf_phrase_parse, + (mailimf_struct_destructor *) + mailimf_phrase_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_list; + } + + keywords = mailimf_keywords_new(list); + if (keywords == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = keywords; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_phrase_free, NULL); + clist_free(list); + err: + return res; +} + +/* +resent-date = "Resent-Date:" date-time CRLF +*/ + +static int +mailimf_resent_date_parse(const char * message, size_t length, + size_t * index, struct mailimf_orig_date ** result) +{ + struct mailimf_orig_date * orig_date; + struct mailimf_date_time * date_time; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Date"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_date_time_parse(message, length, &cur_token, &date_time); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_date_time; + } + + orig_date = mailimf_orig_date_new(date_time); + if (orig_date == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_date_time; + } + + * result = orig_date; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_date_time: + mailimf_date_time_free(date_time); + err: + return res; +} + +/* +resent-from = "Resent-From:" mailbox-list CRLF +*/ + +static int +mailimf_resent_from_parse(const char * message, size_t length, + size_t * index, struct mailimf_from ** result) +{ + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-From"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mb_list; + } + + from = mailimf_from_new(mb_list); + if (from == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb_list; + } + + * result = from; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_mb_list: + mailimf_mailbox_list_free(mb_list); + err: + return res; +} + +/* +resent-sender = "Resent-Sender:" mailbox CRLF +*/ + +static int +mailimf_resent_sender_parse(const char * message, size_t length, + size_t * index, struct mailimf_sender ** result) +{ + struct mailimf_mailbox * mb; + struct mailimf_sender * sender; + size_t cur_token; + int r; + int res; + + cur_token = length; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Sender"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_parse(message, length, &cur_token, &mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mb; + } + + sender = mailimf_sender_new(mb); + if (sender == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb; + } + + * result = sender; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_mb: + mailimf_mailbox_free(mb); + err: + return res; +} + +/* +resent-to = "Resent-To:" address-list CRLF +*/ + +static int +mailimf_resent_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_to ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-To"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + to = mailimf_to_new(addr_list); + if (to == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = to; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +resent-cc = "Resent-Cc:" address-list CRLF +*/ + +static int +mailimf_resent_cc_parse(const char * message, size_t length, + size_t * index, struct mailimf_cc ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Cc"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + cc = mailimf_cc_new(addr_list); + if (cc == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = cc; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +resent-bcc = "Resent-Bcc:" (address-list / [CFWS]) CRLF +*/ + +static int +mailimf_resent_bcc_parse(const char * message, size_t length, + size_t * index, struct mailimf_bcc ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + size_t cur_token; + int r; + int res; + + cur_token = * index; + bcc = NULL; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Bcc"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + bcc = mailimf_bcc_new(addr_list); + if (bcc == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = bcc; + * index = cur_token; + + return TRUE; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +resent-msg-id = "Resent-Message-ID:" msg-id CRLF +*/ + +static int +mailimf_resent_msg_id_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message_id ** result) +{ + char * value; + size_t cur_token; + struct mailimf_message_id * message_id; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Message-ID"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_msg_id_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + message_id = mailimf_message_id_new(value); + if (message_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = message_id; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_msg_id_free(value); + err: + return res; +} + +/* +trace = [return] + 1*received +*/ + +#if 0 +static int mailimf_trace_parse(const char * message, size_t length, + size_t * index, + struct mailimf_trace ** result) +{ + size_t cur_token; + struct mailimf_return * return_path; + clist * received_list; + struct mailimf_trace * trace; + int r; + int res; + + cur_token = * index; + return_path = NULL; + received_list = NULL; + + r = mailimf_return_parse(message, length, &cur_token, &return_path); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &received_list, + (mailimf_struct_parser *) + mailimf_received_parse, + (mailimf_struct_destructor *) + mailimf_received_free); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + if ((received_list == NULL) && (return_path == NULL)) { + res = MAILIMF_ERROR_PARSE; + goto free_return; + } + + trace = mailimf_trace_new(return_path, received_list); + if (trace == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = trace; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(received_list, (clist_func) mailimf_received_free, NULL); + clist_free(received_list); + free_return: + if (return_path != NULL) + mailimf_return_free(return_path); + err: + return res; +} +#endif + +/* +return = "Return-Path:" path CRLF +*/ + +static int mailimf_return_parse(const char * message, size_t length, + size_t * index, + struct mailimf_return ** result) +{ + struct mailimf_path * path; + struct mailimf_return * return_path; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Return-Path"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_path_parse(message, length, &cur_token, &path); + if ( r!= MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_path; + } + + return_path = mailimf_return_new(path); + if (return_path == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_path; + } + + * result = return_path; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_path: + mailimf_path_free(path); + err: + return res; +} + +/* +path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) / + obs-path +*/ + +static int mailimf_path_parse(const char * message, size_t length, + size_t * index, struct mailimf_path ** result) +{ + size_t cur_token; + char * addr_spec; + struct mailimf_path * path; + int res; + int r; + + cur_token = * index; + addr_spec = NULL; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_lower_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec); + switch (r) { + case MAILIMF_NO_ERROR: + break; + case MAILIMF_ERROR_PARSE: + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + break; + default: + return r; + } + + r = mailimf_greater_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + path = mailimf_path_new(addr_spec); + if (path == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_spec; + } + + * index = cur_token; + * result = path; + + return MAILIMF_NO_ERROR; + + free_addr_spec: + if (addr_spec == NULL) + mailimf_addr_spec_free(addr_spec); + err: + return res; +} + +/* +received = "Received:" name-val-list ";" date-time CRLF +*/ + +#if 0 +static int mailimf_received_parse(const char * message, size_t length, + size_t * index, + struct mailimf_received ** result) +{ + size_t cur_token; + struct mailimf_received * received; + struct mailimf_name_val_list * name_val_list; + struct mailimf_date_time * date_time; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Received"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_name_val_list_parse(message, length, + &cur_token, &name_val_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_semi_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_name_val_list; + } + + r = mailimf_date_time_parse(message, length, &cur_token, &date_time); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_name_val_list; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_date_time; + } + + received = mailimf_received_new(name_val_list, date_time); + if (received == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_date_time; + } + + * index = cur_token; + * result = received; + + return MAILIMF_NO_ERROR; + + free_date_time: + mailimf_date_time_free(date_time); + free_name_val_list: + mailimf_name_val_list_free(name_val_list); + err: + return res; +} +#endif + +/* +name-val-list = [CFWS] [name-val-pair *(CFWS name-val-pair)] +*/ + +#if 0 +static int +mailimf_name_val_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_name_val_list ** result) +{ + size_t cur_token; + struct mailimf_name_val_pair * pair; + struct mailimf_name_val_list * name_val_list; + clist* list; + int res; + int r; + + cur_token = * index; + list = NULL; + + r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair); + + if (r == MAILIMF_NO_ERROR){ + size_t final_token; + + list = clist_new(); + if (list == NULL) { + mailimf_name_val_pair_free(pair); + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = clist_append(list, pair); + if (r < 0) { + mailimf_name_val_pair_free(pair); + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + final_token = cur_token; + + while (1) { + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_list; + } + + r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free_list; + } + + r = clist_append(list, pair); + if (r < 0) { + mailimf_name_val_pair_free(pair); + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + final_token = cur_token; + } + cur_token = final_token; + } + + name_val_list = mailimf_name_val_list_new(list); + if (name_val_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * index = cur_token; + * result = name_val_list; + + return MAILIMF_NO_ERROR; + + free_list: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_name_val_pair_free, NULL); + clist_free(list); + } + err: + return res; +} +#endif + +/* +name-val-pair = item-name CFWS item-value +*/ + +#if 0 +static int +mailimf_name_val_pair_parse(const char * message, size_t length, + size_t * index, + struct mailimf_name_val_pair ** result) +{ + size_t cur_token; + char * item_name; + struct mailimf_item_value * item_value; + struct mailimf_name_val_pair * name_val_pair; + int r; + int res; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_item_name_parse(message, length, &cur_token, &item_name); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_cfws_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_item_name; + } + + r = mailimf_item_value_parse(message, length, &cur_token, &item_value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_item_name; + } + + name_val_pair = mailimf_name_val_pair_new(item_name, item_value); + if (name_val_pair == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_item_value; + } + + * result = name_val_pair; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_item_value: + mailimf_item_value_free(item_value); + free_item_name: + mailimf_item_name_free(item_name); + err: + return res; +} +#endif + +/* +item-name = ALPHA *(["-"] (ALPHA / DIGIT)) +*/ + +#if 0 +static int mailimf_item_name_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + size_t begin; + char * item_name; + char ch; + int digit; + int r; + int res; + + cur_token = * index; + + begin = cur_token; + + r = mailimf_alpha_parse(message, length, &cur_token, &ch); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + while (1) { + int minus_sign; + + minus_sign = mailimf_minus_parse(message, length, &cur_token); + + r = mailimf_alpha_parse(message, length, &cur_token, &ch); + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_digit_parse(message, length, &cur_token, &digit); + + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + if (r == MAILIMF_ERROR_PARSE) + break; + else if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + } + + item_name = strndup(message + begin, cur_token - begin); + if (item_name == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + * index = cur_token; + * result = item_name; + + return MAILIMF_NO_ERROR; + + err: + return res; +} +#endif + +/* +item-value = 1*angle-addr / addr-spec / + atom / domain / msg-id +*/ + +#if 0 +static int is_item_value_atext(char ch) +{ + switch (ch) { + case '\t': + case ' ': + case '\r': + case '\n': + case ';': + return FALSE; + default: + return TRUE; + } +} + +static int mailimf_item_value_atom_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * atom; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_custom_string_parse(message, length, &cur_token, + &atom, is_item_value_atext); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + * index = cur_token; + * result = atom; + + return MAILIMF_NO_ERROR; +} + +static int mailimf_item_value_parse(const char * message, size_t length, + size_t * index, + struct mailimf_item_value ** result) +{ + size_t cur_token; + clist * angle_addr_list; + char * addr_spec; + char * atom; + char * domain; + char * msg_id; + int type; + struct mailimf_item_value * item_value; + int r; + int res; + + cur_token = * index; + + angle_addr_list = NULL; + addr_spec = NULL; + atom = NULL; + domain = NULL; + msg_id = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &angle_addr_list, + (mailimf_struct_parser *) + mailimf_angle_addr_parse, + (mailimf_struct_destructor *) + mailimf_angle_addr_free); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ITEM_VALUE_ANGLE_ADDR_LIST; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_addr_spec_parse(message, length, &cur_token, + &addr_spec); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ITEM_VALUE_ADDR_SPEC; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_msg_id_parse(message, length, &cur_token, + &msg_id); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ITEM_VALUE_MSG_ID; + } + + /* + else if (mailimf_domain_parse(message, length, &cur_token, + &domain)) + type = MAILIMF_ITEM_VALUE_DOMAIN; + */ + /* + else if (mailimf_atom_parse(message, length, &cur_token, + &atom)) + type = MAILIMF_ITEM_VALUE_ATOM; + */ + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_item_value_atom_parse(message, length, &cur_token, + &atom); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ITEM_VALUE_ATOM; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + item_value = mailimf_item_value_new(type, angle_addr_list, addr_spec, + atom, domain, msg_id); + if (item_value == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = item_value; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (angle_addr_list != NULL) { + clist_foreach(angle_addr_list, (clist_func) mailimf_angle_addr_free, NULL); + clist_free(angle_addr_list); + } + if (addr_spec != NULL) + mailimf_addr_spec_free(addr_spec); + if (atom != NULL) + mailimf_atom_free(atom); + if (domain != NULL) + mailimf_domain_free(domain); + if (msg_id != NULL) + mailimf_msg_id_free(msg_id); + err: + return res; +} +#endif + +/* +optional-field = field-name ":" unstructured CRLF +*/ + +static int +mailimf_optional_field_parse(const char * message, size_t length, + size_t * index, + struct mailimf_optional_field ** result) +{ + char * name; + char * value; + struct mailimf_optional_field * optional_field; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_field_name_parse(message, length, &cur_token, &name); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_name; + } + + r = mailimf_unstructured_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_name; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + optional_field = mailimf_optional_field_new(name, value); + if (optional_field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = optional_field; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_unstructured_free(value); + free_name: + mailimf_field_name_free(name); + err: + return res; +} + +/* +field-name = 1*ftext +*/ + +static inline int is_ftext(char ch); + +static int mailimf_field_name_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * field_name; + size_t cur_token; + size_t end; + + cur_token = * index; + + end = cur_token; + if (end >= length) { + return MAILIMF_ERROR_PARSE; + } + + while (is_ftext(message[end])) { + end ++; + if (end >= length) + break; + } + if (end == cur_token) { + return MAILIMF_ERROR_PARSE; + } + + /* field_name = strndup(message + cur_token, end - cur_token); */ + field_name = malloc(end - cur_token + 1); + if (field_name == NULL) { + return MAILIMF_ERROR_MEMORY; + } + strncpy(field_name, message + cur_token, end - cur_token); + field_name[end - cur_token] = '\0'; + + cur_token = end; + + * index = cur_token; + * result = field_name; + + return MAILIMF_NO_ERROR; +} + +/* +ftext = %d33-57 / ; Any character except + %d59-126 ; controls, SP, and + ; ":". +*/ + +static inline int is_ftext(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (uch < 33) + return FALSE; + + if (uch == 58) + return FALSE; + + return TRUE; +} + +/* +static int mailimf_ftext_parse(const char * message, size_t length, + size_t * index, gchar * result) +{ + return mailimf_typed_text_parse(message, length, index, result, is_ftext); +} +*/ + + + + +static int mailimf_envelope_field_parse(const char * message, size_t length, + size_t * index, + struct mailimf_field ** result) +{ + size_t cur_token; + int type; + struct mailimf_orig_date * orig_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 * message_id; + struct mailimf_in_reply_to * in_reply_to; + struct mailimf_references * references; + struct mailimf_subject * subject; + struct mailimf_optional_field * optional_field; + struct mailimf_field * field; + int guessed_type; + int r; + int res; + + cur_token = * index; + + orig_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; + optional_field = NULL; + + guessed_type = guess_header_type(message, length, cur_token); + type = MAILIMF_FIELD_NONE; + + switch (guessed_type) { + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_orig_date_parse(message, length, &cur_token, + &orig_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_FROM: + r = mailimf_from_parse(message, length, &cur_token, + &from); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_sender_parse(message, length, &cur_token, + &sender); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_reply_to_parse(message, length, &cur_token, + &reply_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_TO: + r = mailimf_to_parse(message, length, &cur_token, + &to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_CC: + r = mailimf_cc_parse(message, length, &cur_token, + &cc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_BCC: + r = mailimf_bcc_parse(message, length, &cur_token, + &bcc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_message_id_parse(message, length, &cur_token, + &message_id); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_in_reply_to_parse(message, length, &cur_token, + &in_reply_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_references_parse(message, length, &cur_token, + &references); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_subject_parse(message, length, &cur_token, + &subject); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + } + + if (type == MAILIMF_FIELD_NONE) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + orig_date, from, sender, reply_to, to, + cc, bcc, message_id, in_reply_to, references, + subject, NULL, NULL, optional_field); + if (field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_field; + } + + * result = field; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_field: + if (orig_date != NULL) + mailimf_orig_date_free(orig_date); + if (from != NULL) + mailimf_from_free(from); + if (sender != NULL) + mailimf_sender_free(sender); + if (reply_to != NULL) + mailimf_reply_to_free(reply_to); + if (to != NULL) + mailimf_to_free(to); + if (cc != NULL) + mailimf_cc_free(cc); + if (bcc != NULL) + mailimf_bcc_free(bcc); + if (message_id != NULL) + mailimf_message_id_free(message_id); + if (in_reply_to != NULL) + mailimf_in_reply_to_free(in_reply_to); + if (references != NULL) + mailimf_references_free(references); + if (subject != NULL) + mailimf_subject_free(subject); + if (optional_field != NULL) + mailimf_optional_field_free(optional_field); + err: + return res; +} + +int mailimf_envelope_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r; + int res; + + cur_token = * index; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + while (1) { + struct mailimf_field * elt; + + r = mailimf_envelope_field_parse(message, length, &cur_token, &elt); + if (r == MAILIMF_NO_ERROR) { + r = clist_append(list, elt); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + else if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_ignore_field_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto free; + } + } + else { + res = r; + goto free; + } + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + } + err: + return res; +} + + +static int +mailimf_envelope_or_optional_field_parse(const char * message, + size_t length, + size_t * index, + struct mailimf_field ** result) +{ + int r; + size_t cur_token; + struct mailimf_optional_field * optional_field; + struct mailimf_field * field; + + r = mailimf_envelope_field_parse(message, length, index, result); + if (r == MAILIMF_NO_ERROR) + return MAILIMF_NO_ERROR; + + cur_token = * index; + + r = mailimf_optional_field_parse(message, length, &cur_token, + &optional_field); + if (r != MAILIMF_NO_ERROR) + return r; + + 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, optional_field); + if (field == NULL) { + mailimf_optional_field_free(optional_field); + return MAILIMF_ERROR_MEMORY; + } + + * result = field; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + + +int +mailimf_envelope_and_optional_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r; + int res; + + cur_token = * index; + + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_envelope_or_optional_field_parse, + (mailimf_struct_destructor *) + mailimf_field_free); + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + + case MAILIMF_ERROR_PARSE: + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + break; + + default: + res = r; + goto err; + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + } + err: + return res; +} + + + +static int +mailimf_only_optional_field_parse(const char * message, + size_t length, + size_t * index, + struct mailimf_field ** result) +{ + int r; + size_t cur_token; + struct mailimf_optional_field * optional_field; + struct mailimf_field * field; + + cur_token = * index; + + r = mailimf_optional_field_parse(message, length, &cur_token, + &optional_field); + if (r != MAILIMF_NO_ERROR) + return r; + + 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, optional_field); + if (field == NULL) { + mailimf_optional_field_free(optional_field); + return MAILIMF_ERROR_MEMORY; + } + + * result = field; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + + +int +mailimf_optional_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r; + int res; + + cur_token = * index; + + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_only_optional_field_parse, + (mailimf_struct_destructor *) + mailimf_field_free); + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + + case MAILIMF_ERROR_PARSE: + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + break; + + default: + res = r; + goto err; + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + } + err: + return res; +} diff --git a/libetpan/src/low-level/imf/mailimf.h b/libetpan/src/low-level/imf/mailimf.h new file mode 100644 index 0000000..c2231dd --- a/dev/null +++ b/libetpan/src/low-level/imf/mailimf.h @@ -0,0 +1,347 @@ +/* + * 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. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMF_H + +#define MAILIMF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailimf_types.h> +#include <libetpan/mailimf_write_generic.h> +#include <libetpan/mailimf_write_file.h> +#include <libetpan/mailimf_write_mem.h> +#include <libetpan/mailimf_types_helper.h> + +#include <inttypes.h> +#include <sys/types.h> + +/* + mailimf_message_parse will parse the given message + + @param message this is a string containing the message content + @param length this is the size of the given string + @param index this is a pointer to the start of the message in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_message_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message ** result); + +/* + mailimf_body_parse will parse the given text part of a message + + @param message this is a string containing the message text part + @param length this is the size of the given string + @param index this is a pointer to the start of the message text part in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_body_parse(const char * message, size_t length, + size_t * index, + struct mailimf_body ** result); + +/* + mailimf_fields_parse will parse the given header fields + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param index this is a pointer to the start of the header fields in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + +/* + mailimf_mailbox_list_parse will parse the given mailbox list + + @param message this is a string containing the mailbox list + @param length this is the size of the given string + @param index this is a pointer to the start of the mailbox list in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int +mailimf_mailbox_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_mailbox_list ** result); + +/* + mailimf_address_list_parse will parse the given address list + + @param message this is a string containing the address list + @param length this is the size of the given string + @param index this is a pointer to the start of the address list in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int +mailimf_address_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_address_list ** result); + +/* + mailimf_address_parse will parse the given address + + @param message this is a string containing the address + @param length this is the size of the given string + @param index this is a pointer to the start of the address in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_address_parse(const char * message, size_t length, + size_t * index, + struct mailimf_address ** result); + +/* + mailimf_mailbox_parse will parse the given address + + @param message this is a string containing the mailbox + @param length this is the size of the given string + @param index this is a pointer to the start of the mailbox in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_mailbox_parse(const char * message, size_t length, + size_t * index, + struct mailimf_mailbox ** result); + +/* + mailimf_date_time_parse will parse the given RFC 2822 date + + @param message this is a string containing the date + @param length this is the size of the given string + @param index this is a pointer to the start of the date in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_date_time_parse(const char * message, size_t length, + size_t * index, + struct mailimf_date_time ** result); + +/* + mailimf_envelope_fields_parse will parse the given fields (Date, + From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To, + References and Subject) + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param index this is a pointer to the start of the header fields in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int mailimf_envelope_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + +/* + mailimf_ignore_field_parse will skip the given field + + @param message this is a string containing the header field + @param length this is the size of the given string + @param index this is a pointer to the start of the header field in + the given string, (* index) is modified to point at the end + of the parsed data + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + + +int mailimf_ignore_field_parse(const char * message, size_t length, + size_t * index); + +/* + mailimf_envelope_fields will parse the given fields (Date, + From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To, + References and Subject), other fields will be added as optional + fields. + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param index this is a pointer to the start of the header fields in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + + +int +mailimf_envelope_and_optional_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + +/* + mailimf_envelope_fields will parse the given fields as optional + fields. + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param index this is a pointer to the start of the header fields in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +int +mailimf_optional_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + + +/* internal use, exported for MIME */ + +int mailimf_fws_parse(const char * message, size_t length, size_t * index); + +int mailimf_cfws_parse(const char * message, size_t length, + size_t * index); + +int mailimf_char_parse(const char * message, size_t length, + size_t * index, char token); + +int mailimf_unstrict_char_parse(const char * message, size_t length, + size_t * index, char token); + +int mailimf_crlf_parse(const char * message, size_t length, size_t * index); + +int +mailimf_custom_string_parse(const char * message, size_t length, + size_t * index, char ** result, + int (* is_custom_char)(char)); + +int +mailimf_token_case_insensitive_len_parse(const char * message, size_t length, + size_t * index, char * token, + size_t token_length); + +#define mailimf_token_case_insensitive_parse(message, length, index, token) \ + mailimf_token_case_insensitive_len_parse(message, length, index, token, \ + sizeof(token) - 1) + +int mailimf_quoted_string_parse(const char * message, size_t length, + size_t * index, char ** result); + +int +mailimf_number_parse(const char * message, size_t length, + size_t * index, uint32_t * result); + +int mailimf_msg_id_parse(const char * message, size_t length, + size_t * index, + char ** result); + +int mailimf_msg_id_list_parse(const char * message, size_t length, + size_t * index, clist ** result); + +int mailimf_word_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailimf_atom_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailimf_fws_atom_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailimf_fws_word_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailimf_fws_quoted_string_parse(const char * message, size_t length, + size_t * index, char ** result); + +/* exported for IMAP */ + +int mailimf_references_parse(const char * message, size_t length, + size_t * index, + struct mailimf_references ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libetpan/src/low-level/imf/mailimf_types.c b/libetpan/src/low-level/imf/mailimf_types.c new file mode 100644 index 0000000..a6e4db9 --- a/dev/null +++ b/libetpan/src/low-level/imf/mailimf_types.c @@ -0,0 +1,868 @@ +/* + * 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. + */ + +/* + * $Id$ + */ + +#include "mailimf_types.h" +#include "mmapstring.h" +#include <stdlib.h> + +void mailimf_atom_free(char * atom) +{ + free(atom); +} + +void mailimf_dot_atom_free(char * dot_atom) +{ + free(dot_atom); +} + +void mailimf_dot_atom_text_free(char * dot_atom) +{ + free(dot_atom); +} + +void mailimf_quoted_string_free(char * quoted_string) +{ + free(quoted_string); +} + +void mailimf_word_free(char * word) +{ + free(word); +} + +void mailimf_phrase_free(char * phrase) +{ + free(phrase); +} + +void mailimf_unstructured_free(char * unstructured) +{ + free(unstructured); +} + + +struct mailimf_date_time * +mailimf_date_time_new(int dt_day, int dt_month, int dt_year, + int dt_hour, int dt_min, int dt_sec, int dt_zone) +{ + struct mailimf_date_time * date_time; + + date_time = malloc(sizeof(* date_time)); + if (date_time == NULL) + return NULL; + + date_time->dt_day = dt_day; + date_time->dt_month = dt_month; + date_time->dt_year = dt_year; + date_time->dt_hour = dt_hour; + date_time->dt_min = dt_min; + date_time->dt_sec = dt_sec; + date_time->dt_zone = dt_zone; + + return date_time; +} + + +void mailimf_date_time_free(struct mailimf_date_time * date_time) +{ + free(date_time); +} + + + + +struct mailimf_address * +mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox, + struct mailimf_group * ad_group) +{ + struct mailimf_address * address; + + address = malloc(sizeof(* address)); + if (address == NULL) + return NULL; + + address->ad_type = ad_type; + switch (ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + address->ad_data.ad_mailbox = ad_mailbox; + break; + case MAILIMF_ADDRESS_GROUP: + address->ad_data.ad_group = ad_group; + break; + } + + return address; +} + +void mailimf_address_free(struct mailimf_address * address) +{ + switch (address->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + mailimf_mailbox_free(address->ad_data.ad_mailbox); + break; + case MAILIMF_ADDRESS_GROUP: + mailimf_group_free(address->ad_data.ad_group); + } + free(address); +} + +struct mailimf_mailbox * +mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec) +{ + struct mailimf_mailbox * mb; + + mb = malloc(sizeof(* mb)); + if (mb == NULL) + return NULL; + + mb->mb_display_name = mb_display_name; + mb->mb_addr_spec = mb_addr_spec; + + return mb; +} + +void mailimf_mailbox_free(struct mailimf_mailbox * mailbox) +{ + if (mailbox->mb_display_name != NULL) + mailimf_display_name_free(mailbox->mb_display_name); + mailimf_addr_spec_free(mailbox->mb_addr_spec); + free(mailbox); +} + + +void mailimf_angle_addr_free(char * angle_addr) +{ + free(angle_addr); +} + + +struct mailimf_group * +mailimf_group_new(char * grp_display_name, + struct mailimf_mailbox_list * grp_mb_list) +{ + struct mailimf_group * group; + + group = malloc(sizeof(* group)); + if (group == NULL) + return NULL; + + group->grp_display_name = grp_display_name; + group->grp_mb_list = grp_mb_list; + + return group; +} + +void mailimf_group_free(struct mailimf_group * group) +{ + if (group->grp_mb_list) + mailimf_mailbox_list_free(group->grp_mb_list); + mailimf_display_name_free(group->grp_display_name); + free(group); +} + +void mailimf_display_name_free(char * display_name) +{ + mailimf_phrase_free(display_name); +} + + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new(clist * mb_list) +{ + struct mailimf_mailbox_list * mbl; + + mbl = malloc(sizeof(* mbl)); + if (mbl == NULL) + return NULL; + + mbl->mb_list = mb_list; + + return mbl; +} + +void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list) +{ + clist_foreach(mb_list->mb_list, (clist_func) mailimf_mailbox_free, NULL); + clist_free(mb_list->mb_list); + free(mb_list); +} + + + +struct mailimf_address_list * +mailimf_address_list_new(clist * ad_list) +{ + struct mailimf_address_list * addr_list; + + addr_list = malloc(sizeof(* addr_list)); + if (addr_list == NULL) + return NULL; + + addr_list->ad_list = ad_list; + + return addr_list; +} + +void mailimf_address_list_free(struct mailimf_address_list * addr_list) +{ + clist_foreach(addr_list->ad_list, (clist_func) mailimf_address_free, NULL); + clist_free(addr_list->ad_list); + free(addr_list); +} + + +void mailimf_addr_spec_free(char * addr_spec) +{ + free(addr_spec); +} + +void mailimf_local_part_free(char * local_part) +{ + free(local_part); +} + +void mailimf_domain_free(char * domain) +{ + free(domain); +} + +void mailimf_domain_literal_free(char * domain_literal) +{ + free(domain_literal); +} + + + +struct mailimf_message * +mailimf_message_new(struct mailimf_fields * msg_fields, + struct mailimf_body * msg_body) +{ + struct mailimf_message * message; + + message = malloc(sizeof(* message)); + if (message == NULL) + return NULL; + + message->msg_fields = msg_fields; + message->msg_body = msg_body; + + return message; +} + +void mailimf_message_free(struct mailimf_message * message) +{ + mailimf_body_free(message->msg_body); + mailimf_fields_free(message->msg_fields); + free(message); +} + + +struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size) +{ + struct mailimf_body * body; + + body = malloc(sizeof(* body)); + if (body == NULL) + return NULL; + body->bd_text = bd_text; + body->bd_size = bd_size; + + return body; +} + +void mailimf_body_free(struct mailimf_body * body) +{ + free(body); +} + + + +struct mailimf_field * +mailimf_field_new(int fld_type, + struct mailimf_return * fld_return_path, + struct mailimf_orig_date * fld_resent_date, + struct mailimf_from * fld_resent_from, + struct mailimf_sender * fld_resent_sender, + struct mailimf_to * fld_resent_to, + struct mailimf_cc * fld_resent_cc, + struct mailimf_bcc * fld_resent_bcc, + struct mailimf_message_id * fld_resent_msg_id, + struct mailimf_orig_date * fld_orig_date, + struct mailimf_from * fld_from, + struct mailimf_sender * fld_sender, + struct mailimf_reply_to * fld_reply_to, + struct mailimf_to * fld_to, + struct mailimf_cc * fld_cc, + struct mailimf_bcc * fld_bcc, + struct mailimf_message_id * fld_message_id, + struct mailimf_in_reply_to * fld_in_reply_to, + struct mailimf_references * fld_references, + struct mailimf_subject * fld_subject, + struct mailimf_comments * fld_comments, + struct mailimf_keywords * fld_keywords, + struct mailimf_optional_field * fld_optional_field) +{ + struct mailimf_field * field; + + field = malloc(sizeof(* field)); + if (field == NULL) + return NULL; + + field->fld_type = fld_type; + switch (fld_type) { + case MAILIMF_FIELD_RETURN_PATH: + field->fld_data.fld_return_path = fld_return_path; + break; + case MAILIMF_FIELD_RESENT_DATE: + field->fld_data.fld_resent_date = fld_resent_date; + break; + case MAILIMF_FIELD_RESENT_FROM: + field->fld_data.fld_resent_from = fld_resent_from; + break; + case MAILIMF_FIELD_RESENT_SENDER: + field->fld_data.fld_resent_sender = fld_resent_sender; + break; + case MAILIMF_FIELD_RESENT_TO: + field->fld_data.fld_resent_to = fld_resent_to; + break; + case MAILIMF_FIELD_RESENT_CC: + field->fld_data.fld_resent_cc = fld_resent_cc; + break; + case MAILIMF_FIELD_RESENT_BCC: + field->fld_data.fld_resent_bcc = fld_resent_bcc; + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + field->fld_data.fld_resent_msg_id = fld_resent_msg_id; + break; + case MAILIMF_FIELD_ORIG_DATE: + field->fld_data.fld_orig_date = fld_orig_date; + break; + case MAILIMF_FIELD_FROM: + field->fld_data.fld_from = fld_from; + break; + case MAILIMF_FIELD_SENDER: + field->fld_data.fld_sender = fld_sender; + break; + case MAILIMF_FIELD_REPLY_TO: + field->fld_data.fld_reply_to = fld_reply_to; + break; + case MAILIMF_FIELD_TO: + field->fld_data.fld_to = fld_to; + break; + case MAILIMF_FIELD_CC: + field->fld_data.fld_cc = fld_cc; + break; + case MAILIMF_FIELD_BCC: + field->fld_data.fld_bcc = fld_bcc; + break; + case MAILIMF_FIELD_MESSAGE_ID: + field->fld_data.fld_message_id = fld_message_id; + break; + case MAILIMF_FIELD_IN_REPLY_TO: + field->fld_data.fld_in_reply_to = fld_in_reply_to; + break; + case MAILIMF_FIELD_REFERENCES: + field->fld_data.fld_references = fld_references; + break; + case MAILIMF_FIELD_SUBJECT: + field->fld_data.fld_subject = fld_subject; + break; + case MAILIMF_FIELD_COMMENTS: + field->fld_data.fld_comments = fld_comments; + break; + case MAILIMF_FIELD_KEYWORDS: + field->fld_data.fld_keywords = fld_keywords; + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + field->fld_data.fld_optional_field = fld_optional_field; + break; + } + + return field; +} + +void mailimf_field_free(struct mailimf_field * field) +{ + switch (field->fld_type) { + case MAILIMF_FIELD_RETURN_PATH: + mailimf_return_free(field->fld_data.fld_return_path); + break; + case MAILIMF_FIELD_RESENT_DATE: + mailimf_orig_date_free(field->fld_data.fld_resent_date); + break; + case MAILIMF_FIELD_RESENT_FROM: + mailimf_from_free(field->fld_data.fld_resent_from); + break; + case MAILIMF_FIELD_RESENT_SENDER: + mailimf_sender_free(field->fld_data.fld_resent_sender); + break; + case MAILIMF_FIELD_RESENT_TO: + mailimf_to_free(field->fld_data.fld_resent_to); + break; + case MAILIMF_FIELD_RESENT_CC: + mailimf_cc_free(field->fld_data.fld_resent_cc); + break; + case MAILIMF_FIELD_RESENT_BCC: + mailimf_bcc_free(field->fld_data.fld_resent_bcc); + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + mailimf_message_id_free(field->fld_data.fld_resent_msg_id); + break; + case MAILIMF_FIELD_ORIG_DATE: + mailimf_orig_date_free(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + mailimf_from_free(field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + mailimf_sender_free(field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + mailimf_reply_to_free(field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + mailimf_to_free(field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + mailimf_cc_free(field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + mailimf_bcc_free(field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + mailimf_message_id_free(field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + mailimf_in_reply_to_free(field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + mailimf_references_free(field->fld_data.fld_references); + break; + case MAILIMF_FIELD_SUBJECT: + mailimf_subject_free(field->fld_data.fld_subject); + break; + case MAILIMF_FIELD_COMMENTS: + mailimf_comments_free(field->fld_data.fld_comments); + break; + case MAILIMF_FIELD_KEYWORDS: + mailimf_keywords_free(field->fld_data.fld_keywords); + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + mailimf_optional_field_free(field->fld_data.fld_optional_field); + break; + } + + free(field); +} + +struct mailimf_fields * mailimf_fields_new(clist * fld_list) +{ + struct mailimf_fields * fields; + + fields = malloc(sizeof(* fields)); + if (fields == NULL) + return NULL; + + fields->fld_list = fld_list; + + return fields; +} + +void mailimf_fields_free(struct mailimf_fields * fields) +{ + if (fields->fld_list != NULL) { + clist_foreach(fields->fld_list, (clist_func) mailimf_field_free, NULL); + clist_free(fields->fld_list); + } + free(fields); +} + + +struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time * + dt_date_time) +{ + struct mailimf_orig_date * orig_date; + + orig_date = malloc(sizeof(* orig_date)); + if (orig_date == NULL) + return NULL; + + orig_date->dt_date_time = dt_date_time; + + return orig_date; +} + +void mailimf_orig_date_free(struct mailimf_orig_date * orig_date) +{ + if (orig_date->dt_date_time != NULL) + mailimf_date_time_free(orig_date->dt_date_time); + free(orig_date); +} + +struct mailimf_from * +mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list) +{ + struct mailimf_from * from; + + from = malloc(sizeof(* from)); + if (from == NULL) + return NULL; + + from->frm_mb_list = frm_mb_list; + + return from; +} + +void mailimf_from_free(struct mailimf_from * from) +{ + if (from->frm_mb_list != NULL) + mailimf_mailbox_list_free(from->frm_mb_list); + free(from); +} + +struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb) +{ + struct mailimf_sender * sender; + + sender = malloc(sizeof(* sender)); + if (sender == NULL) + return NULL; + + sender->snd_mb = snd_mb; + + return sender; +} + +void mailimf_sender_free(struct mailimf_sender * sender) +{ + if (sender->snd_mb != NULL) + mailimf_mailbox_free(sender->snd_mb); + free(sender); +} + +struct mailimf_reply_to * +mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list) +{ + struct mailimf_reply_to * reply_to; + + reply_to = malloc(sizeof(* reply_to)); + if (reply_to == NULL) + return NULL; + + reply_to->rt_addr_list = rt_addr_list; + + return reply_to; +} + +void mailimf_reply_to_free(struct mailimf_reply_to * reply_to) +{ + if (reply_to->rt_addr_list != NULL) + mailimf_address_list_free(reply_to->rt_addr_list); + free(reply_to); +} + +struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list) +{ + struct mailimf_to * to; + + to = malloc(sizeof(* to)); + if (to == NULL) + return NULL; + + to->to_addr_list = to_addr_list; + + return to; +} + +void mailimf_to_free(struct mailimf_to * to) +{ + if (to->to_addr_list != NULL) + mailimf_address_list_free(to->to_addr_list); + free(to); +} + +struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list) +{ + struct mailimf_cc * cc; + + cc = malloc(sizeof(* cc)); + if (cc == NULL) + return NULL; + + cc->cc_addr_list = cc_addr_list; + + return cc; +} + +void mailimf_cc_free(struct mailimf_cc * cc) +{ + if (cc->cc_addr_list != NULL) + mailimf_address_list_free(cc->cc_addr_list); + free(cc); +} + +struct mailimf_bcc * +mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list) +{ + struct mailimf_bcc * bcc; + + bcc = malloc(sizeof(* bcc)); + if (bcc == NULL) + return NULL; + + bcc->bcc_addr_list = bcc_addr_list; + + return bcc; +} + +void mailimf_bcc_free(struct mailimf_bcc * bcc) +{ + if (bcc->bcc_addr_list != NULL) + mailimf_address_list_free(bcc->bcc_addr_list); + free(bcc); +} + +struct mailimf_message_id * mailimf_message_id_new(char * mid_value) +{ + struct mailimf_message_id * message_id; + + message_id = malloc(sizeof(* message_id)); + if (message_id == NULL) + return NULL; + + message_id->mid_value = mid_value; + + return message_id; +} + +void mailimf_message_id_free(struct mailimf_message_id * message_id) +{ + if (message_id->mid_value != NULL) + mailimf_msg_id_free(message_id->mid_value); + free(message_id); +} + +struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list) +{ + struct mailimf_in_reply_to * in_reply_to; + + in_reply_to = malloc(sizeof(* in_reply_to)); + if (in_reply_to == NULL) + return NULL; + + in_reply_to->mid_list = mid_list; + + return in_reply_to; +} + +void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to) +{ + clist_foreach(in_reply_to->mid_list, + (clist_func) mailimf_msg_id_free, NULL); + clist_free(in_reply_to->mid_list); + free(in_reply_to); +} + +struct mailimf_references * mailimf_references_new(clist * mid_list) +{ + struct mailimf_references * ref; + + ref = malloc(sizeof(* ref)); + if (ref == NULL) + return NULL; + + ref->mid_list = mid_list; + + return ref; +} + +void mailimf_references_free(struct mailimf_references * references) +{ + clist_foreach(references->mid_list, + (clist_func) mailimf_msg_id_free, NULL); + clist_free(references->mid_list); + free(references); +} + +void mailimf_msg_id_free(char * msg_id) +{ + free(msg_id); +} + +void mailimf_id_left_free(char * id_left) +{ + free(id_left); +} + +void mailimf_id_right_free(char * id_right) +{ + free(id_right); +} + +void mailimf_no_fold_quote_free(char * nfq) +{ + free(nfq); +} + +void mailimf_no_fold_literal_free(char * nfl) +{ + free(nfl); +} + +struct mailimf_subject * mailimf_subject_new(char * sbj_value) +{ + struct mailimf_subject * subject; + + subject = malloc(sizeof(* subject)); + if (subject == NULL) + return NULL; + + subject->sbj_value = sbj_value; + + return subject; +} + +void mailimf_subject_free(struct mailimf_subject * subject) +{ + mailimf_unstructured_free(subject->sbj_value); + free(subject); +} + +struct mailimf_comments * mailimf_comments_new(char * cm_value) +{ + struct mailimf_comments * comments; + + comments = malloc(sizeof(* comments)); + if (comments == NULL) + return NULL; + + comments->cm_value = cm_value; + + return comments; +} + +void mailimf_comments_free(struct mailimf_comments * comments) +{ + mailimf_unstructured_free(comments->cm_value); + free(comments); +} + +struct mailimf_keywords * mailimf_keywords_new(clist * kw_list) +{ + struct mailimf_keywords * keywords; + + keywords = malloc(sizeof(* keywords)); + if (keywords == NULL) + return NULL; + + keywords->kw_list = kw_list; + + return keywords; +} + +void mailimf_keywords_free(struct mailimf_keywords * keywords) +{ + clist_foreach(keywords->kw_list, (clist_func) mailimf_phrase_free, NULL); + clist_free(keywords->kw_list); + free(keywords); +} + +struct mailimf_return * +mailimf_return_new(struct mailimf_path * ret_path) +{ + struct mailimf_return * return_path; + + return_path = malloc(sizeof(* return_path)); + if (return_path == NULL) + return NULL; + + return_path->ret_path = ret_path; + + return return_path; +} + +void mailimf_return_free(struct mailimf_return * return_path) +{ + mailimf_path_free(return_path->ret_path); + free(return_path); +} + + +struct mailimf_path * mailimf_path_new(char * pt_addr_spec) +{ + struct mailimf_path * path; + + path = malloc(sizeof(* path)); + if (path == NULL) + return NULL; + + path->pt_addr_spec = pt_addr_spec; + + return path; +} + +void mailimf_path_free(struct mailimf_path * path) +{ + if (path->pt_addr_spec != NULL) + mailimf_addr_spec_free(path->pt_addr_spec); + free(path); +} + +struct mailimf_optional_field * +mailimf_optional_field_new(char * fld_name, char * fld_value) +{ + struct mailimf_optional_field * opt_field; + + opt_field = malloc(sizeof(* opt_field)); + if (opt_field == NULL) + return NULL; + + opt_field->fld_name = fld_name; + opt_field->fld_value = fld_value; + + return opt_field; +} + +void mailimf_optional_field_free(struct mailimf_optional_field * opt_field) +{ + mailimf_field_name_free(opt_field->fld_name); + mailimf_unstructured_free(opt_field->fld_value); + free(opt_field); +} + +void mailimf_field_name_free(char * field_name) +{ + free(field_name); +} diff --git a/libetpan/src/low-level/imf/mailimf_types.h b/libetpan/src/low-level/imf/mailimf_types.h new file mode 100644 index 0000000..e73db48 --- a/dev/null +++ b/libetpan/src/low-level/imf/mailimf_types.h @@ -0,0 +1,793 @@ +/* + * 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. + */ + + +/* + * $Id$ + */ + +#ifndef MAILIMF_TYPES_H + +#define MAILIMF_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/clist.h> +#include <sys/types.h> + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + mailimf_date_time is a date + + - day is the day of month (1 to 31) + + - month (1 to 12) + + - year (4 digits) + + - hour (0 to 23) + + - min (0 to 59) + + - sec (0 to 59) + + - zone (this is the decimal value that we can read, for example: + for "-0200", the value is -200) +*/ + +struct mailimf_date_time { + int dt_day; + int dt_month; + int dt_year; + int dt_hour; + int dt_min; + int dt_sec; + int dt_zone; +}; + +struct mailimf_date_time * +mailimf_date_time_new(int dt_day, int dt_month, int dt_year, + int dt_hour, int dt_min, int dt_sec, int dt_zone); + +void mailimf_date_time_free(struct mailimf_date_time * date_time); + + + +/* this is the type of address */ + +enum { + MAILIMF_ADDRESS_ERROR, /* on parse error */ + MAILIMF_ADDRESS_MAILBOX, /* if this is a mailbox (mailbox@domain) */ + MAILIMF_ADDRESS_GROUP, /* if this is a group + (group_name: address1@domain1, + address2@domain2; ) */ +}; + +/* + mailimf_address is an address + + - type can be MAILIMF_ADDRESS_MAILBOX or MAILIMF_ADDRESS_GROUP + + - mailbox is a mailbox if type is MAILIMF_ADDRESS_MAILBOX + + - group is a group if type is MAILIMF_ADDRESS_GROUP +*/ + +struct mailimf_address { + int ad_type; + union { + struct mailimf_mailbox * ad_mailbox; /* can be NULL */ + struct mailimf_group * ad_group; /* can be NULL */ + } ad_data; +}; + + +struct mailimf_address * +mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox, + struct mailimf_group * ad_group); + +void mailimf_address_free(struct mailimf_address * address); + + + +/* + mailimf_mailbox is a mailbox + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" <mailbox@domain>, + should be allocated with malloc() + + - addr_spec is the mailbox, for example 'mailbox@domain' + in '"name" <mailbox@domain>, should be allocated with malloc() +*/ + +struct mailimf_mailbox { + char * mb_display_name; /* can be NULL */ + char * mb_addr_spec; /* != NULL */ +}; + +struct mailimf_mailbox * +mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec); + +void mailimf_mailbox_free(struct mailimf_mailbox * mailbox); + + + +/* + mailimf_group is a group + + - display_name is the name that will be displayed for this group, + for example 'group_name' in + 'group_name: address1@domain1, address2@domain2;', should be allocated + with malloc() + + - mb_list is a list of mailboxes +*/ + +struct mailimf_group { + char * grp_display_name; /* != NULL */ + struct mailimf_mailbox_list * grp_mb_list; /* can be NULL */ +}; + +struct mailimf_group * +mailimf_group_new(char * grp_display_name, + struct mailimf_mailbox_list * grp_mb_list); + +void mailimf_group_free(struct mailimf_group * group); + + + +/* + mailimf_mailbox_list is a list of mailboxes + + - list is a list of mailboxes +*/ + +struct mailimf_mailbox_list { + clist * mb_list; /* list of (struct mailimf_mailbox *), != NULL */ +}; + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new(clist * mb_list); + +void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list); + + + +/* + mailimf_address_list is a list of addresses + + - list is a list of addresses +*/ + +struct mailimf_address_list { + clist * ad_list; /* list of (struct mailimf_address *), != NULL */ +}; + +struct mailimf_address_list * +mailimf_address_list_new(clist * ad_list); + +void mailimf_address_list_free(struct mailimf_address_list * addr_list); + + + + + +/* + mailimf_body is the text part of a message + + - text is the beginning of the text part, it is a substring + of an other string + + - size is the size of the text part +*/ + +struct mailimf_body { + const char * bd_text; /* != NULL */ + size_t bd_size; +}; + +struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size); + +void mailimf_body_free(struct mailimf_body * body); + + + + +/* + mailimf_message is the content of the message + + - msg_fields is the header fields of the message + + - msg_body is the text part of the message +*/ + +struct mailimf_message { + struct mailimf_fields * msg_fields; /* != NULL */ + struct mailimf_body * msg_body; /* != NULL */ +}; + +struct mailimf_message * +mailimf_message_new(struct mailimf_fields * msg_fields, + struct mailimf_body * msg_body); + +void mailimf_message_free(struct mailimf_message * message); + + + + +/* + mailimf_fields is a list of header fields + + - fld_list is a list of header fields +*/ + +struct mailimf_fields { + clist * fld_list; /* list of (struct mailimf_field *), != NULL */ +}; + +struct mailimf_fields * mailimf_fields_new(clist * fld_list); + +void mailimf_fields_free(struct mailimf_fields * fields); + + + +/* this is a type of field */ + +enum { + MAILIMF_FIELD_NONE, /* on parse error */ + MAILIMF_FIELD_RETURN_PATH, /* Return-Path */ + MAILIMF_FIELD_RESENT_DATE, /* Resent-Date */ + MAILIMF_FIELD_RESENT_FROM, /* Resent-From */ + MAILIMF_FIELD_RESENT_SENDER, /* Resent-Sender */ + MAILIMF_FIELD_RESENT_TO, /* Resent-To */ + MAILIMF_FIELD_RESENT_CC, /* Resent-Cc */ + MAILIMF_FIELD_RESENT_BCC, /* Resent-Bcc */ + MAILIMF_FIELD_RESENT_MSG_ID, /* Resent-Message-ID */ + MAILIMF_FIELD_ORIG_DATE, /* Date */ + MAILIMF_FIELD_FROM, /* From */ + MAILIMF_FIELD_SENDER, /* Sender */ + MAILIMF_FIELD_REPLY_TO, /* Reply-To */ + MAILIMF_FIELD_TO, /* To */ + MAILIMF_FIELD_CC, /* Cc */ + MAILIMF_FIELD_BCC, /* Bcc */ + MAILIMF_FIELD_MESSAGE_ID, /* Message-ID */ + MAILIMF_FIELD_IN_REPLY_TO, /* In-Reply-To */ + MAILIMF_FIELD_REFERENCES, /* References */ + MAILIMF_FIELD_SUBJECT, /* Subject */ + MAILIMF_FIELD_COMMENTS, /* Comments */ + MAILIMF_FIELD_KEYWORDS, /* Keywords */ + MAILIMF_FIELD_OPTIONAL_FIELD, /* other field */ +}; + +/* + mailimf_field is a field + + - fld_type is the type of the field + + - fld_data.fld_return_path is the parsed content of the Return-Path + field if type is MAILIMF_FIELD_RETURN_PATH + + - fld_data.fld_resent_date is the parsed content of the Resent-Date field + if type is MAILIMF_FIELD_RESENT_DATE + + - fld_data.fld_resent_from is the parsed content of the Resent-From field + + - fld_data.fld_resent_sender is the parsed content of the Resent-Sender field + + - fld_data.fld_resent_to is the parsed content of the Resent-To field + + - fld_data.fld_resent_cc is the parsed content of the Resent-Cc field + + - fld_data.fld_resent_bcc is the parsed content of the Resent-Bcc field + + - fld_data.fld_resent_msg_id is the parsed content of the Resent-Message-ID + field + + - fld_data.fld_orig_date is the parsed content of the Date field + + - fld_data.fld_from is the parsed content of the From field + + - fld_data.fld_sender is the parsed content of the Sender field + + - fld_data.fld_reply_to is the parsed content of the Reply-To field + + - fld_data.fld_to is the parsed content of the To field + + - fld_data.fld_cc is the parsed content of the Cc field + + - fld_data.fld_bcc is the parsed content of the Bcc field + + - fld_data.fld_message_id is the parsed content of the Message-ID field + + - fld_data.fld_in_reply_to is the parsed content of the In-Reply-To field + + - fld_data.fld_references is the parsed content of the References field + + - fld_data.fld_subject is the content of the Subject field + + - fld_data.fld_comments is the content of the Comments field + + - fld_data.fld_keywords is the parsed content of the Keywords field + + - fld_data.fld_optional_field is an other field and is not parsed +*/ + +#define LIBETPAN_MAILIMF_FIELD_UNION + +struct mailimf_field { + int fld_type; + union { + struct mailimf_return * fld_return_path; /* can be NULL */ + struct mailimf_orig_date * fld_resent_date; /* can be NULL */ + struct mailimf_from * fld_resent_from; /* can be NULL */ + struct mailimf_sender * fld_resent_sender; /* can be NULL */ + struct mailimf_to * fld_resent_to; /* can be NULL */ + struct mailimf_cc * fld_resent_cc; /* can be NULL */ + struct mailimf_bcc * fld_resent_bcc; /* can be NULL */ + struct mailimf_message_id * fld_resent_msg_id; /* can be NULL */ + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ + struct mailimf_optional_field * fld_optional_field; /* can be NULL */ + } fld_data; +}; + +struct mailimf_field * +mailimf_field_new(int fld_type, + struct mailimf_return * fld_return_path, + struct mailimf_orig_date * fld_resent_date, + struct mailimf_from * fld_resent_from, + struct mailimf_sender * fld_resent_sender, + struct mailimf_to * fld_resent_to, + struct mailimf_cc * fld_resent_cc, + struct mailimf_bcc * fld_resent_bcc, + struct mailimf_message_id * fld_resent_msg_id, + struct mailimf_orig_date * fld_orig_date, + struct mailimf_from * fld_from, + struct mailimf_sender * fld_sender, + struct mailimf_reply_to * fld_reply_to, + struct mailimf_to * fld_to, + struct mailimf_cc * fld_cc, + struct mailimf_bcc * fld_bcc, + struct mailimf_message_id * fld_message_id, + struct mailimf_in_reply_to * fld_in_reply_to, + struct mailimf_references * fld_references, + struct mailimf_subject * fld_subject, + struct mailimf_comments * fld_comments, + struct mailimf_keywords * fld_keywords, + struct mailimf_optional_field * fld_optional_field); + +void mailimf_field_free(struct mailimf_field * field); + + + +/* + mailimf_orig_date is the parsed Date field + + - date_time is the parsed date +*/ + +struct mailimf_orig_date { + struct mailimf_date_time * dt_date_time; /* != NULL */ +}; + +struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time * + dt_date_time); + +void mailimf_orig_date_free(struct mailimf_orig_date * orig_date); + + + + +/* + mailimf_from is the parsed From field + + - mb_list is the parsed mailbox list +*/ + +struct mailimf_from { + struct mailimf_mailbox_list * frm_mb_list; /* != NULL */ +}; + +struct mailimf_from * +mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list); + +void mailimf_from_free(struct mailimf_from * from); + + + +/* + mailimf_sender is the parsed Sender field + + - snd_mb is the parsed mailbox +*/ + +struct mailimf_sender { + struct mailimf_mailbox * snd_mb; /* != NULL */ +}; + +struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb); + +void mailimf_sender_free(struct mailimf_sender * sender); + + + + +/* + mailimf_reply_to is the parsed Reply-To field + + - rt_addr_list is the parsed address list + */ + +struct mailimf_reply_to { + struct mailimf_address_list * rt_addr_list; /* != NULL */ +}; + +struct mailimf_reply_to * +mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list); + +void mailimf_reply_to_free(struct mailimf_reply_to * reply_to); + + + + +/* + mailimf_to is the parsed To field + + - to_addr_list is the parsed address list +*/ + +struct mailimf_to { + struct mailimf_address_list * to_addr_list; /* != NULL */ +}; + +struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list); + +void mailimf_to_free(struct mailimf_to * to); + + + + +/* + mailimf_cc is the parsed Cc field + + - cc_addr_list is the parsed addres list +*/ + +struct mailimf_cc { + struct mailimf_address_list * cc_addr_list; /* != NULL */ +}; + +struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list); + +void mailimf_cc_free(struct mailimf_cc * cc); + + + + +/* + mailimf_bcc is the parsed Bcc field + + - bcc_addr_list is the parsed addres list +*/ + +struct mailimf_bcc { + struct mailimf_address_list * bcc_addr_list; /* can be NULL */ +}; + +struct mailimf_bcc * +mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list); + +void mailimf_bcc_free(struct mailimf_bcc * bcc); + + + +/* + mailimf_message_id is the parsed Message-ID field + + - mid_value is the message identifier +*/ + +struct mailimf_message_id { + char * mid_value; /* != NULL */ +}; + +struct mailimf_message_id * mailimf_message_id_new(char * mid_value); + +void mailimf_message_id_free(struct mailimf_message_id * message_id); + + + + +/* + mailimf_in_reply_to is the parsed In-Reply-To field + + - mid_list is the list of message identifers +*/ + +struct mailimf_in_reply_to { + clist * mid_list; /* list of (char *), != NULL */ +}; + +struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list); + +void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to); + + + +/* + mailimf_references is the parsed References field + + - msg_id_list is the list of message identifiers + */ + +struct mailimf_references { + clist * mid_list; /* list of (char *) */ + /* != NULL */ +}; + +struct mailimf_references * mailimf_references_new(clist * mid_list); + +void mailimf_references_free(struct mailimf_references * references); + + + +/* + mailimf_subject is the parsed Subject field + + - sbj_value is the value of the field +*/ + +struct mailimf_subject { + char * sbj_value; /* != NULL */ +}; + +struct mailimf_subject * mailimf_subject_new(char * sbj_value); + +void mailimf_subject_free(struct mailimf_subject * subject); + + +/* + mailimf_comments is the parsed Comments field + + - cm_value is the value of the field +*/ + +struct mailimf_comments { + char * cm_value; /* != NULL */ +}; + +struct mailimf_comments * mailimf_comments_new(char * cm_value); + +void mailimf_comments_free(struct mailimf_comments * comments); + + +/* + mailimf_keywords is the parsed Keywords field + + - kw_list is the list of keywords +*/ + +struct mailimf_keywords { + clist * kw_list; /* list of (char *), != NULL */ +}; + +struct mailimf_keywords * mailimf_keywords_new(clist * kw_list); + +void mailimf_keywords_free(struct mailimf_keywords * keywords); + + +/* + mailimf_return is the parsed Return-Path field + + - ret_path is the parsed value of Return-Path +*/ + +struct mailimf_return { + struct mailimf_path * ret_path; /* != NULL */ +}; + +struct mailimf_return * +mailimf_return_new(struct mailimf_path * ret_path); + +void mailimf_return_free(struct mailimf_return * return_path); + + +/* + mailimf_path is the parsed value of Return-Path + + - pt_addr_spec is a mailbox +*/ + +struct mailimf_path { + char * pt_addr_spec; /* can be NULL */ +}; + +struct mailimf_path * mailimf_path_new(char * pt_addr_spec); + +void mailimf_path_free(struct mailimf_path * path); + + +/* + mailimf_optional_field is a non-parsed field + + - fld_name is the name of the field + + - fld_value is the value of the field +*/ + +struct mailimf_optional_field { + char * fld_name; /* != NULL */ + char * fld_value; /* != NULL */ +}; + +struct mailimf_optional_field * +mailimf_optional_field_new(char * fld_name, char * fld_value); + +void mailimf_optional_field_free(struct mailimf_optional_field * opt_field); + + +/* + mailimf_fields is the native structure that IMF module will use, + this module will provide an easier structure to use when parsing fields. + + mailimf_single_fields is an easier structure to get parsed fields, + rather than iteration over the list of fields + + - fld_orig_date is the parsed "Date" field + + - fld_from is the parsed "From" field + + - fld_sender is the parsed "Sender "field + + - fld_reply_to is the parsed "Reply-To" field + + - fld_to is the parsed "To" field + + - fld_cc is the parsed "Cc" field + + - fld_bcc is the parsed "Bcc" field + + - fld_message_id is the parsed "Message-ID" field + + - fld_in_reply_to is the parsed "In-Reply-To" field + + - fld_references is the parsed "References" field + + - fld_subject is the parsed "Subject" field + + - fld_comments is the parsed "Comments" field + + - fld_keywords is the parsed "Keywords" field +*/ + +struct mailimf_single_fields { + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ +}; + + + + + + +/* internal use */ + +void mailimf_atom_free(char * atom); + +void mailimf_dot_atom_free(char * dot_atom); + +void mailimf_dot_atom_text_free(char * dot_atom); + +void mailimf_quoted_string_free(char * quoted_string); + +void mailimf_word_free(char * word); + +void mailimf_phrase_free(char * phrase); + +void mailimf_unstructured_free(char * unstructured); + +void mailimf_angle_addr_free(char * angle_addr); + +void mailimf_display_name_free(char * display_name); + +void mailimf_addr_spec_free(char * addr_spec); + +void mailimf_local_part_free(char * local_part); + +void mailimf_domain_free(char * domain); + +void mailimf_domain_literal_free(char * domain); + +void mailimf_msg_id_free(char * msg_id); + +void mailimf_id_left_free(char * id_left); + +void mailimf_id_right_free(char * id_right); + +void mailimf_no_fold_quote_free(char * nfq); + +void mailimf_no_fold_literal_free(char * nfl); + +void mailimf_field_name_free(char * field_name); + + + +/* these are the possible returned error codes */ + +enum { + MAILIMF_NO_ERROR = 0, + MAILIMF_ERROR_PARSE, + MAILIMF_ERROR_MEMORY, + MAILIMF_ERROR_INVAL, + MAILIMF_ERROR_FILE, +}; + + +#ifdef __cplusplus +} +#endif + +#endif 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; +} diff --git a/libetpan/src/low-level/imf/mailimf_types_helper.h b/libetpan/src/low-level/imf/mailimf_types_helper.h new file mode 100644 index 0000000..337b1d0 --- a/dev/null +++ b/libetpan/src/low-level/imf/mailimf_types_helper.h @@ -0,0 +1,370 @@ +/* + * 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. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMF_TYPES_HELPER + +#define MAILIMF_TYPES_HELPER + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailimf_types.h> + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + mailimf_mailbox_list_new_empty creates an empty list of mailboxes +*/ + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new_empty(); + +/* + mailimf_mailbox_list_add adds a mailbox to the list of mailboxes + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list, + struct mailimf_mailbox * mb); + +/* + mailimf_mailbox_list_add_parse parse the given string + into a mailimf_mailbox structure and adds it to the list of mailboxes + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list, + char * mb_str); + +/* + mailimf_mailbox creates a mailimf_mailbox structure with the given + arguments and adds it to the list of mailboxes + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" <mailbox@domain>, + should be allocated with malloc() + + - address is the mailbox, for example 'mailbox@domain' + in '"name" <mailbox@domain>, should be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list, + char * display_name, char * address); + +/* + mailimf_address_list_new_empty creates an empty list of addresses +*/ + +struct mailimf_address_list * +mailimf_address_list_new_empty(); + +/* + mailimf_address_list_add adds a mailbox to the list of addresses + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_address_list_add(struct mailimf_address_list * address_list, + struct mailimf_address * addr); + +/* + mailimf_address_list_add_parse parse the given string + into a mailimf_address structure and adds it to the list of addresses + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_address_list_add_parse(struct mailimf_address_list * address_list, + char * addr_str); + +/* + mailimf_address_list_add_mb creates a mailbox mailimf_address + with the given arguments and adds it to the list of addresses + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" <mailbox@domain>, + should be allocated with malloc() + + - address is the mailbox, for example 'mailbox@domain' + in '"name" <mailbox@domain>, should be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_address_list_add_mb(struct mailimf_address_list * address_list, + char * display_name, char * address); + +/* + mailimf_resent_fields_add_data adds a set of resent fields in the + given mailimf_fields structure. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param resent_msg_id sould be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +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); + +/* + mailimf_resent_fields_new_with_data_all creates a new mailimf_fields + structure with a set of resent fields + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param resent_msg_id sould be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +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); + +/* + mailimf_resent_fields_new_with_data_all creates a new mailimf_fields + structure with a set of resent fields. + Resent-Date and Resent-Message-ID fields will be generated for you. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +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); + +/* + this function creates a new mailimf_fields structure with no fields +*/ + +struct mailimf_fields * +mailimf_fields_new_empty(void); + + +/* + this function adds a field to the mailimf_fields structure + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_fields_add(struct mailimf_fields * fields, + struct mailimf_field * field); + + +/* + mailimf_fields_add_data adds a set of fields in the + given mailimf_fields structure. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param msg_id sould be allocated with malloc() + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +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); + +/* + mailimf_fields_new_with_data_all creates a new mailimf_fields + structure with a set of fields + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param message_id sould be allocated with malloc() + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +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); + +/* + mailimf_fields_new_with_data creates a new mailimf_fields + structure with a set of fields + Date and Message-ID fields will be generated for you. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +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); + +/* + this function returns an allocated message identifier to + use in a Message-ID or Resent-Message-ID field +*/ + +char * mailimf_get_message_id(void); + +/* + this function returns a mailimf_date_time structure to + use in a Date or Resent-Date field +*/ + +struct mailimf_date_time * mailimf_get_current_date(void); + + +/* + mailimf_single_fields_init fills a mailimf_single_fields structure + with the content of a mailimf_fields structure +*/ + +void mailimf_single_fields_init(struct mailimf_single_fields * single_fields, + struct mailimf_fields * fields); + +/* + mailimf_single_fields_new creates a new mailimf_single_fields and + fills the structure with mailimf_fields +*/ + +struct mailimf_single_fields * +mailimf_single_fields_new(struct mailimf_fields * fields); + +void mailimf_single_fields_free(struct mailimf_single_fields * + single_fields); + +/* + mailimf_field_new_custom creates a new field of type optional + + @param name should be allocated with malloc() + @param value should be allocated with malloc() +*/ + +struct mailimf_field * mailimf_field_new_custom(char * name, char * value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libetpan/src/low-level/imf/mailimf_write.c b/libetpan/src/low-level/imf/mailimf_write.c new file mode 100644 index 0000000..7301f37 --- a/dev/null +++ b/libetpan/src/low-level/imf/mailimf_write.c @@ -0,0 +1,2021 @@ +/* + * 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. + */ + +/* + * $Id$ + */ + +#include "mailimf_write.h" + +#include <time.h> +#include <string.h> +#include <ctype.h> + +#define MAX_MAIL_COL 72 + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define MAX_VALID_IMF_LINE 998 + +static int mailimf_orig_date_write(FILE * f, int * col, + struct mailimf_orig_date * date); +static int mailimf_date_time_write(FILE * f, int * col, + struct mailimf_date_time * date_time); +static int mailimf_from_write(FILE * f, int * col, + struct mailimf_from * from); +static int mailimf_sender_write(FILE * f, int * col, + struct mailimf_sender * sender); +static int mailimf_reply_to_write(FILE * f, int * col, + struct mailimf_reply_to * reply_to); +static int mailimf_to_write(FILE * f, int * col, + struct mailimf_to * to); +static int mailimf_cc_write(FILE * f, int * col, + struct mailimf_cc * to); +static int mailimf_bcc_write(FILE * f, int * col, + struct mailimf_bcc * to); +static int mailimf_message_id_write(FILE * f, int * col, + struct mailimf_message_id * message_id); +static int mailimf_msg_id_list_write(FILE * f, int * col, + clist * list); +static int mailimf_in_reply_to_write(FILE * f, int * col, + struct mailimf_in_reply_to * + in_reply_to); +static int mailimf_references_write(FILE * f, int * col, + struct mailimf_references * references); +static int mailimf_subject_write(FILE * f, int * col, + struct mailimf_subject * subject); + +static int mailimf_address_write(FILE * f, int * col, + struct mailimf_address * addr); +static int mailimf_group_write(FILE * f, int * col, + struct mailimf_group * group); + +static int mailimf_mailbox_write(FILE * f, int * col, + struct mailimf_mailbox * mb); + +static int mailimf_comments_write(FILE * f, int * col, + struct mailimf_comments * comments); + +static int mailimf_optional_field_write(FILE * f, int * col, + struct mailimf_optional_field * field); + +static int mailimf_keywords_write(FILE * f, int * col, + struct mailimf_keywords * keywords); + +static int mailimf_return_write(FILE * f, int * col, + struct mailimf_return * return_path); + +static int mailimf_path_write(FILE * f, int * col, + struct mailimf_path * path); + +static int mailimf_resent_date_write(FILE * f, int * col, + struct mailimf_orig_date * date); + +static int mailimf_resent_from_write(FILE * f, int * col, + struct mailimf_from * from); + +static int mailimf_resent_sender_write(FILE * f, int * col, + struct mailimf_sender * sender); + +static int mailimf_resent_to_write(FILE * f, int * col, + struct mailimf_to * to); + +static int mailimf_resent_cc_write(FILE * f, int * col, + struct mailimf_cc * cc); + +static int mailimf_resent_bcc_write(FILE * f, int * col, + struct mailimf_bcc * bcc); + +static int +mailimf_resent_msg_id_write(FILE * f, int * col, + struct mailimf_message_id * message_id); + + + +/* ************************ */ + +#if 0 +int mailimf_string_write(FILE * f, int * col, + char * str, size_t length) +{ + int r; + + if (length != 0) { + r = fwrite(str, sizeof(char), length, f); + if (r < 0) + return MAILIMF_ERROR_FILE; + * col += length; + } + + return MAILIMF_NO_ERROR; +} +#endif + +#define CRLF "\r\n" +#define HEADER_FOLD "\r\n " + +static inline int flush_buf(FILE * f, const char * str, size_t length) +{ + if (length != 0) { + int r; + + r = fwrite(str, 1, length, f); + if (r == 0) + return MAILIMF_ERROR_FILE; + } + return MAILIMF_NO_ERROR; +} + +#define CUT_AT_MAX_VALID_IMF_LINE + +int mailimf_string_write(FILE * f, int * col, + const char * str, size_t length) +{ + int r; + size_t count; + const char * block_begin; + const char * p; + int done; + + p = str; + block_begin = str; + count = 0; + + while (length > 0) { +#ifdef CUT_AT_MAX_VALID_IMF_LINE + if (count >= 998) { + /* + cut lines at maximum valid length for internet message + format standard (currently RFC 2822) + + This should not happen. + In case there are some lines larger than 998 in body, + the encoding must be changed into base64 or quoted-printable + so that wrapping to 72 columns is done. + */ + + r = flush_buf(f, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f); + if (r == 0) + return MAILIMF_ERROR_FILE; + + count = 0; + block_begin = p; + + * col = 0; + } +#endif + switch (* p) { + case '\n': + r = flush_buf(f, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p ++; + length --; + count = 0; + block_begin = p; + + * col = 0; + break; + + case '\r': + done = 0; + if (length >= 2) { + if (* (p + 1) == '\n') { + r = flush_buf(f, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p += 2; + length -= 2; + count = 0; + block_begin = p; + + * col = 0; + + done = 1; + } + } + if (!done) { + r = flush_buf(f, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p ++; + length --; + count = 0; + block_begin = p; + + * col = 0; + } + break; + + default: + p ++; + count ++; + length --; + break; + } + } + + r = flush_buf(f, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + * col += count; + + return MAILIMF_NO_ERROR; +} + +#if 0 +int mailimf_header_string_write(FILE * f, int * col, + char * str, size_t length) +{ + char * p; + char * block_begin; + int current_col; + char * last_cut; + int r; + int first; + + if (* col + length < MAX_MAIL_COL) + return mailimf_string_write(f, col, str, length); + + first = 1; + p = str; + block_begin = p; + last_cut = block_begin; + current_col = * col; + + while (1) { + if (current_col >= MAX_MAIL_COL) { + /* if we reach the maximum recommanded size of line */ + if (last_cut == block_begin) { + /* if we could not find any place to cut */ + if (first) { + /* fold the header */ + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + current_col = * col + p - block_begin; + first = 0; + } + else { + /* cut the header */ + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + first = 0; + block_begin = p; + last_cut = block_begin; + current_col = * col + p - block_begin; + } + } + else { + /* if we found a place to cut */ + r = mailimf_string_write(f, col, block_begin, last_cut - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + first = 0; + block_begin = last_cut; + last_cut = block_begin; + current_col = * col + p - block_begin; + continue; + } + } + else { + if (length == 0) + break; + + switch (* p) { + case ' ': + case '\t': + last_cut = p; + current_col ++; + break; + + case '\r': + case '\n': + current_col = 0; + break; + + default: + current_col ++; + break; + } + + p ++; + length --; + } + } + + return mailimf_string_write(f, col, block_begin, p - block_begin); +} +#endif + +#if 0 +enum { + STATE_LOWER_72, + STATE_LOWER_72_CUT, + STATE_EQUAL_72, + STATE_LOWER_998, + STATE_EQUAL_998, +}; + +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length) +{ + int state; + const char * p; + const char * block_begin; + size_t size; + const char * cut; + int r; + + if (* col < MAX_MAIL_COL) + state = STATE_LOWER_72_CUT; + else if (* col == MAX_MAIL_COL) + state = STATE_EQUAL_72; + else if (* col < MAX_VALID_IMF_LINE) + state = STATE_LOWER_998; + else + state = STATE_EQUAL_998; + + p = str; + block_begin = p; + size = * col; + cut = p; + + while (length > 0) { + switch (state) { + case STATE_LOWER_72: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + break; + + case ' ': + case '\t': + cut = p; + p ++; + length --; + size ++; + state = STATE_LOWER_72_CUT; + break; + + default: + if (size < MAX_MAIL_COL - 1) { + p ++; + length --; + size ++; + } + else { + state = STATE_EQUAL_72; + p ++; + length --; + size ++; + } + break; + } + break; /* end of STATE_LOWER_72 */ + + case STATE_LOWER_72_CUT: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + cut = p; + p ++; + length --; + size ++; + break; + + default: + if (size < MAX_MAIL_COL) { + p ++; + length --; + size ++; + } + else { + r = mailimf_string_write(f, col, block_begin, cut - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = cut; + if ((* block_begin == ' ') || (* block_begin == '\t')) + block_begin ++; + size = p - block_begin + * col; + state = STATE_LOWER_72; + } + break; + } + break; /* end of STATE_LOWER_72_CUT */ + + case STATE_EQUAL_72: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: + p ++; + length --; + size ++; + state = STATE_LOWER_998; + break; + } + break; /* end of STATE_EQUAL_72 */ + + case STATE_LOWER_998: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: + if (size < MAX_VALID_IMF_LINE - 1) { + p ++; + length --; + size ++; + } + else { + p ++; + length --; + size = 0; + state = STATE_EQUAL_998; + } + break; + } + break; /* end of STATE_LOWER_998 */ + + case STATE_EQUAL_998: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: +#ifdef CUT_AT_MAX_VALID_IMF_LINE + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; +#else + p ++; + length --; + size ++; +#endif + break; + } + break; /* end of STATE_EQUAL_998 */ + } + } + + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +enum { + STATE_BEGIN, + STATE_WORD, + STATE_SPACE, +}; + +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length) +{ + int state; + const char * p; + const char * word_begin; + const char * word_end; + const char * next_word; + int first; + + state = STATE_BEGIN; + + p = str; + word_begin = p; + word_end = p; + next_word = p; + first = 1; + + while (length > 0) { + switch (state) { + case STATE_BEGIN: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + p ++; + length --; + break; + + default: + word_begin = p; + state = STATE_WORD; + break; + } + break; + + case STATE_SPACE: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + p ++; + length --; + break; + + default: + word_begin = p; + state = STATE_WORD; + break; + } + break; + + case STATE_WORD: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + if (p - word_begin + (* col) + 1 > MAX_MAIL_COL) + mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + else { + if (!first) + mailimf_string_write(f, col, " ", 1); + } + first = 0; + mailimf_string_write(f, col, word_begin, p - word_begin); + state = STATE_SPACE; + break; + + default: + if (p - word_begin + (* col) >= MAX_VALID_IMF_LINE) { + mailimf_string_write(f, col, word_begin, p - word_begin); + mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + word_begin = p; + } + p ++; + length --; + break; + } + break; + } + } + + if (state == STATE_WORD) { + if (p - word_begin + (* col) >= MAX_MAIL_COL) + mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + else { + if (!first) + mailimf_string_write(f, col, " ", 1); + } + first = 0; + mailimf_string_write(f, col, word_begin, p - word_begin); + } + + return MAILIMF_NO_ERROR; +} + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + int r; + struct mailimf_field * field; + + field = clist_content(cur); + if (field->fld_type != MAILIMF_FIELD_OPTIONAL_FIELD) { + r = mailimf_field_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + return MAILIMF_NO_ERROR; +} + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + int r; + + r = mailimf_field_write(f, col, clist_content(cur)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + +#if 0 +int mailimf_unparsed_fields_write(FILE * f, int * col, + struct mailimf_unparsed_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->list) ; cur != NULL ; cur = cur->next) { + int r; + + r = mailimf_optional_field_write(f, col, cur->data); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} +#endif + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field) +{ + int r; + + switch (field->fld_type) { + case MAILIMF_FIELD_RETURN_PATH: + r = mailimf_return_write(f, col, field->fld_data.fld_return_path); + break; + case MAILIMF_FIELD_RESENT_DATE: + r = mailimf_resent_date_write(f, col, field->fld_data.fld_resent_date); + break; + case MAILIMF_FIELD_RESENT_FROM: + r = mailimf_resent_from_write(f, col, field->fld_data.fld_resent_from); + break; + case MAILIMF_FIELD_RESENT_SENDER: + r = mailimf_resent_sender_write(f, col, field->fld_data.fld_resent_sender); + break; + case MAILIMF_FIELD_RESENT_TO: + r = mailimf_resent_to_write(f, col, field->fld_data.fld_resent_to); + break; + case MAILIMF_FIELD_RESENT_CC: + r = mailimf_resent_cc_write(f, col, field->fld_data.fld_resent_cc); + break; + case MAILIMF_FIELD_RESENT_BCC: + r = mailimf_resent_bcc_write(f, col, field->fld_data.fld_resent_bcc); + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + r = mailimf_resent_msg_id_write(f, col, field->fld_data.fld_resent_msg_id); + break; + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_orig_date_write(f, col, field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + r = mailimf_from_write(f, col, field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_sender_write(f, col, field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_reply_to_write(f, col, field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + r = mailimf_to_write(f, col, field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + r = mailimf_cc_write(f, col, field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + r = mailimf_bcc_write(f, col, field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_message_id_write(f, col, field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_in_reply_to_write(f, col, field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_references_write(f, col, field->fld_data.fld_references); + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_subject_write(f, col, field->fld_data.fld_subject); + break; + case MAILIMF_FIELD_COMMENTS: + r = mailimf_comments_write(f, col, field->fld_data.fld_comments); + break; + case MAILIMF_FIELD_KEYWORDS: + r = mailimf_keywords_write(f, col, field->fld_data.fld_keywords); + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + r = mailimf_optional_field_write(f, col, field->fld_data.fld_optional_field); + break; + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_orig_date_write(FILE * f, int * col, + struct mailimf_orig_date * date) +{ + int r; + + r = mailimf_string_write(f, col, "Date: ", 6); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_date_time_write(f, col, date->dt_date_time); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +#define MAX_DATE_STR 256 + +/* 0 = Sunday */ +/* y > 1752 */ + +static int dayofweek(int year, int month, int day) +{ + static int offset[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; + + year -= month < 3; + + return (year + year/4 - year/100 + year/400 + offset[month-1] + day) % 7; +} + +static const char * week_of_day_str[] = { "Sun", "Mon", "Tue", "Wed", "Thu", + "Fri", "Sat"}; +static const char * month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +static int mailimf_date_time_write(FILE * f, int * col, + struct mailimf_date_time * date_time) +{ + int r; + char date_str[MAX_DATE_STR]; +#if 0 + struct tm tmval; + time_t timeval; +#endif + int wday; + +#if 0 + tmval.tm_sec = date_time->sec; + tmval.tm_min = date_time->min; + tmval.tm_hour = date_time->hour; + tmval.tm_sec = date_time->sec; + tmval.tm_mday = date_time->day; + tmval.tm_mon = date_time->month - 1; + tmval.tm_year = date_time->year - 1900; + tmval.tm_isdst = 1; + + timeval = mktime(&tmval); + + localtime_r(&timeval, &tmval); +#endif + + wday = dayofweek(date_time->dt_year, date_time->dt_month, date_time->dt_day); + + snprintf(date_str, MAX_DATE_STR, "%s, %i %s %i %02i:%02i:%02i %+05i", + week_of_day_str[wday], date_time->dt_day, + month_str[date_time->dt_month - 1], + date_time->dt_year, date_time->dt_hour, + date_time->dt_min, date_time->dt_sec, + date_time->dt_zone); + + r = mailimf_string_write(f, col, date_str, strlen(date_str)); + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int mailimf_from_write(FILE * f, int * col, + struct mailimf_from * from) +{ + int r; + + r = mailimf_string_write(f, col, "From: ", 6); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_list_write(f, col, from->frm_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_sender_write(FILE * f, int * col, + struct mailimf_sender * sender) +{ + int r; + + r = mailimf_string_write(f, col, "Sender: ", 8); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_write(f, col, sender->snd_mb); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_reply_to_write(FILE * f, int * col, + struct mailimf_reply_to * reply_to) +{ + int r; + + r = mailimf_string_write(f, col, "Reply-To: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write(f, col, reply_to->rt_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_to_write(FILE * f, int * col, + struct mailimf_to * to) +{ + int r; + + r = mailimf_string_write(f, col, "To: ", 4); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write(f, col, to->to_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_cc_write(FILE * f, int * col, + struct mailimf_cc * cc) +{ + int r; + + r = mailimf_string_write(f, col, "Cc: ", 4); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write(f, col, cc->cc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_bcc_write(FILE * f, int * col, + struct mailimf_bcc * bcc) +{ + int r; + + r = mailimf_string_write(f, col, "Bcc: ", 5); + if (r != MAILIMF_NO_ERROR) + return r; + + if (bcc->bcc_addr_list != NULL) { + r = mailimf_address_list_write(f, col, bcc->bcc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_message_id_write(FILE * f, int * col, + struct mailimf_message_id * message_id) +{ + int r; + + r = mailimf_string_write(f, col, "Message-ID: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, + message_id->mid_value, + strlen(message_id->mid_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_msg_id_list_write(FILE * f, int * col, clist * mid_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(mid_list) ; cur != NULL ; cur = clist_next(cur)) { + char * msgid; + size_t len; + + msgid = clist_content(cur); + len = strlen(msgid); + + /* + XXX - if this is the first message ID, don't fold. + This is a workaround for a bug of old versions of INN. + */ + if (!first) { + if (* col > 1) { + + if (* col + len >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + first = TRUE; + } + } + } + + if (!first) { + r = mailimf_string_write(f, col, " ", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_string_write(f, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, msgid, len); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_in_reply_to_write(FILE * f, int * col, + struct mailimf_in_reply_to * in_reply_to) +{ + int r; + + r = mailimf_string_write(f, col, "In-Reply-To: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_msg_id_list_write(f, col, in_reply_to->mid_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_references_write(FILE * f, int * col, + struct mailimf_references * references) +{ + int r; + + r = mailimf_string_write(f, col, "References: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_msg_id_list_write(f, col, references->mid_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + + +static int mailimf_subject_write(FILE * f, int * col, + struct mailimf_subject * subject) +{ + int r; + + r = mailimf_string_write(f, col, "Subject: ", 9); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write(f, col, + subject->sbj_value, strlen(subject->sbj_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +int mailimf_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_address_write(f, col, addr); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_address_write(FILE * f, int * col, + struct mailimf_address * addr) +{ + int r; + + switch(addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + r = mailimf_mailbox_write(f, col, addr->ad_data.ad_mailbox); + if (r != MAILIMF_NO_ERROR) + return r; + + break; + + case MAILIMF_ADDRESS_GROUP: + r = mailimf_group_write(f, col, addr->ad_data.ad_group); + if (r != MAILIMF_NO_ERROR) + return r; + + break; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_group_write(FILE * f, int * col, + struct mailimf_group * group) +{ + int r; + + r = mailimf_header_string_write(f, col, group->grp_display_name, + strlen(group->grp_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ": ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + if (group->grp_mb_list != NULL) { + r = mailimf_mailbox_list_write(f, col, group->grp_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, ";", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + + +int mailimf_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_mailbox_write(f, col, mb); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +int mailimf_quoted_string_write(FILE * f, int * col, + const char * string, size_t len) +{ + int r; + size_t i; + + fputc('\"', f); + for(i = 0 ; i < len ; i ++) { + switch (string[i]) { + case '\\': + case '\"': + r = fputc('\\', f); + if (r < 0) + return MAILIMF_ERROR_FILE; + r = fputc(string[i], f); + if (r < 0) + return MAILIMF_ERROR_FILE; + (* col) += 2; + break; + + default: + r = fputc(string[i], f); + if (r < 0) + return MAILIMF_ERROR_FILE; + (* col) ++; + break; + } + } + fputc('\"', f); + + return MAILIMF_NO_ERROR; +} + + +/* +static int +atext = ALPHA / DIGIT / ; Any character except controls, + "!" / "#" / ; SP, and specials. + "$" / "%" / ; Used for atoms + "&" / "'" / + "*" / "+" / + "-" / "/" / + "=" / "?" / + "^" / "_" / + "`" / "{" / + "|" / "}" / + "~" +*/ + +static int is_atext(const char * s) +{ + const char * p; + + for(p = s ; * p != 0 ; p ++) { + if (isalpha((unsigned char) * p)) + continue; + if (isdigit((unsigned char) * p)) + continue; + switch (*p) { + case ' ': + case '\t': + case '!': + case '#': + case '$': + case '%': + case '&': + case '\'': + case '*': + case '+': + case '-': + case '/': + case '=': + case '?': + case '^': + case '_': + case '`': + case '{': + case '|': + case '}': + case '~': + break; + default: + return 0; + } + } + + return 1; +} + +static int mailimf_mailbox_write(FILE * f, int * col, + struct mailimf_mailbox * mb) +{ + int r; + int do_fold; + +#if 0 + if (* col > 1) { + + if (mb->mb_display_name != NULL) { + if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + } +#endif + + if (mb->mb_display_name) { + + if (is_atext(mb->mb_display_name)) { + r = mailimf_header_string_write(f, col, mb->mb_display_name, + strlen(mb->mb_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + if (mb->mb_display_name != NULL) { + if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + if (strlen(mb->mb_display_name) > MAX_VALID_IMF_LINE / 2) + return MAILIMF_ERROR_INVAL; + + r = mailimf_quoted_string_write(f, col, mb->mb_display_name, + strlen(mb->mb_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + do_fold = 0; + if (* col > 1) { + + if (* col + strlen(mb->mb_addr_spec) + 3 >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + do_fold = 1; + } + } + + if (do_fold) + r = mailimf_string_write(f, col, "<", 1); + else + r = mailimf_string_write(f, col, " <", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, mb->mb_addr_spec, + strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + if (* col + strlen(mb->mb_addr_spec) >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, + mb->mb_addr_spec, strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + + return MAILIMF_NO_ERROR; +} + +static int mailimf_comments_write(FILE * f, int * col, + struct mailimf_comments * comments) +{ + int r; + + r = mailimf_string_write(f, col, "Comments: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write(f, col, + comments->cm_value, strlen(comments->cm_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_optional_field_write(FILE * f, int * col, + struct mailimf_optional_field * field) +{ + int r; + + if (strlen(field->fld_name) + 2 > MAX_VALID_IMF_LINE) + return MAILIMF_ERROR_INVAL; + + r = mailimf_string_write(f, col, field->fld_name, strlen(field->fld_name)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ": ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write(f, col, field->fld_value, + strlen(field->fld_value)); + if (r != MAILIMF_NO_ERROR) + return r; + +#if 0 + /* XXX parsing debug */ + mailimf_string_write(f, col, " (X)", 4); +#endif + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_keywords_write(FILE * f, int * col, + struct mailimf_keywords * keywords) +{ + int r; + clistiter * cur; + int first; + + r = mailimf_string_write(f, col, "Keywords: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + first = TRUE; + + for(cur = clist_begin(keywords->kw_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * keyword; + size_t len; + + keyword = clist_content(cur); + len = strlen(keyword); + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + +#if 0 + if (* col > 1) { + + if (* col + len >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } +#endif + + r = mailimf_header_string_write(f, col, keyword, len); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +#if 0 +static int mailimf_delivering_info_write(FILE * f, int * col, + struct mailimf_delivering_info * info) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(info->received_fields) ; + cur != NULL ; cur = cur->next) { + struct mailimf_trace_resent_fields * field; + + field = cur->data; + + r = mailimf_trace_resent_fields_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int +mailimf_trace_resent_fields_write(FILE * f, int * col, + struct mailimf_trace_resent_fields * field) +{ + int r; + + if (field->return_path != NULL) { + r = mailimf_return_write(f, col, field->return_path); + if (r != MAILIMF_NO_ERROR) + return r; + } + + if (field->resent_fields != NULL) { + r = mailimf_resent_fields_write(f, col, field->resent_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} +#endif + +static int mailimf_return_write(FILE * f, int * col, + struct mailimf_return * return_path) +{ + int r; + + r = mailimf_string_write(f, col, "Return-Path: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_path_write(f, col, return_path->ret_path); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_path_write(FILE * f, int * col, + struct mailimf_path * path) +{ + int r; + + r = mailimf_string_write(f, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, path->pt_addr_spec, + strlen(path->pt_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +#if 0 +static int mailimf_resent_fields_write(FILE * f, int * col, + struct mailimf_resent_fields_list * + resent_fields) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(resent_fields->list) ; cur != NULL ; cur = cur->next) { + struct mailimf_resent_field * field; + + field = cur->data; + + r = mailimf_resent_field_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + + +static int mailimf_resent_field_write(FILE * f, int * col, + struct mailimf_resent_field * + resent_field) +{ + int r; + + switch (resent_field->type) { + case MAILIMF_RESENT_FIELD_DATE: + r = mailimf_resent_date_write(f, col, resent_field->resent_date); + break; + + case MAILIMF_RESENT_FIELD_FROM: + r = mailimf_resent_from_write(f, col, resent_field->resent_from); + break; + + case MAILIMF_RESENT_FIELD_SENDER: + r = mailimf_resent_sender_write(f, col, resent_field->resent_sender); + break; + + case MAILIMF_RESENT_FIELD_TO: + r = mailimf_resent_to_write(f, col, resent_field->resent_to); + break; + + case MAILIMF_RESENT_FIELD_CC: + r = mailimf_resent_cc_write(f, col, resent_field->resent_cc); + break; + + case MAILIMF_RESENT_FIELD_BCC: + r = mailimf_resent_bcc_write(f, col, resent_field->resent_bcc); + break; + + case MAILIMF_RESENT_FIELD_MSG_ID: + r = mailimf_resent_msg_id_write(f, col, resent_field->resent_msg_id); + break; + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +static int mailimf_resent_date_write(FILE * f, int * col, + struct mailimf_orig_date * date) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-Date: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_date_time_write(f, col, date->dt_date_time); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_from_write(FILE * f, int * col, + struct mailimf_from * from) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-From: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_list_write(f, col, from->frm_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_sender_write(FILE * f, int * col, + struct mailimf_sender * sender) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-Sender: ", 15); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_write(f, col, sender->snd_mb); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_to_write(FILE * f, int * col, + struct mailimf_to * to) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-To: ", 11); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write(f, col, to->to_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_resent_cc_write(FILE * f, int * col, + struct mailimf_cc * cc) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-Cc: ", 11); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write(f, col, cc->cc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_resent_bcc_write(FILE * f, int * col, + struct mailimf_bcc * bcc) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-Bcc: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + if (bcc->bcc_addr_list != NULL) { + r = mailimf_address_list_write(f, col, bcc->bcc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int +mailimf_resent_msg_id_write(FILE * f, int * col, + struct mailimf_message_id * message_id) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-Message-ID: ", 19); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, + message_id->mid_value, strlen(message_id->mid_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} diff --git a/libetpan/src/low-level/imf/mailimf_write.h b/libetpan/src/low-level/imf/mailimf_write.h new file mode 100644 index 0000000..a3441dd --- a/dev/null +++ b/libetpan/src/low-level/imf/mailimf_write.h @@ -0,0 +1,134 @@ +/* + * 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. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMF_WRITE_H + +#define MAILIMF_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> +#include <libetpan/mailimf_types.h> + +/* + mailimf_string_write writes a string to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_string_write(FILE * f, int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write writes the fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write writes only some fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write writes a field to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write writes a string that is quoted + to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ + +int mailimf_quoted_string_write(FILE * f, int * col, + const char * string, size_t len); + +int mailimf_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list); + +int mailimf_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write writes a header value and fold the header + if needed. + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libetpan/src/low-level/imf/mailimf_write_file.c b/libetpan/src/low-level/imf/mailimf_write_file.c new file mode 100644 index 0000000..a1f7187 --- a/dev/null +++ b/libetpan/src/low-level/imf/mailimf_write_file.c @@ -0,0 +1,149 @@ +/* + * 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. + */ + +/* + * $Id$ + */ + +#include "mailimf_write_file.h" +#include "mailimf_write_generic.h" + +static int do_write(void * data, const char * str, size_t length) +{ + FILE * f; + + f = data; + + return fwrite(str, 1, length, f); +} + +int mailimf_string_write_file(FILE * f, int * col, + const char * str, size_t length) +{ + return mailimf_string_write_driver(do_write, f, col, str, length); +} + +int mailimf_fields_write_file(FILE * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_fields_write_driver(do_write, f, col, fields); +} + +int mailimf_envelope_fields_write_file(FILE * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_envelope_fields_write_driver(do_write, f, col, fields); +} + +int mailimf_field_write_file(FILE * f, int * col, + struct mailimf_field * field) +{ + return mailimf_field_write_driver(do_write, f, col, field); +} + +int mailimf_quoted_string_write_file(FILE * f, int * col, + const char * string, size_t len) +{ + return mailimf_quoted_string_write_driver(do_write, f, col, string, len); +} + +int mailimf_address_list_write_file(FILE * f, int * col, + struct mailimf_address_list * addr_list) +{ + return mailimf_address_list_write_driver(do_write, f, col, addr_list); +} + +int mailimf_mailbox_list_write_file(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list) +{ + return mailimf_mailbox_list_write_driver(do_write, f, col, mb_list); +} + +int mailimf_header_string_write_file(FILE * f, int * col, + const char * str, size_t length) +{ + return mailimf_header_string_write_driver(do_write, f, col, str, length); +} + + +/* binary compatibility with 0.34 - begin */ + +#ifdef MAILIMF_WRITE_COMPATIBILITY +int mailimf_string_write(FILE * f, int * col, + const char * str, size_t length) +{ + return mailimf_string_write_file(f, col, str, length); +} + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_fields_write_file(f, col, fields); +} + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_envelope_fields_write_file(f, col, fields); +} + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field) +{ + return mailimf_field_write_file(f, col, field); +} + +int mailimf_quoted_string_write(FILE * f, int * col, + const char * string, size_t len) +{ + return mailimf_quoted_string_write_file(f, col, string, len); +} + +int mailimf_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list) +{ + return mailimf_address_list_write_file(f, col, addr_list); +} + +int mailimf_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list) +{ + return mailimf_mailbox_list_write_file(f, col, mb_list); +} + +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length) +{ + return mailimf_header_string_write_file(f, col, str, length); +} +#endif + +/* binary compatibility with 0.34 - end */ diff --git a/libetpan/src/low-level/imf/mailimf_write_file.h b/libetpan/src/low-level/imf/mailimf_write_file.h new file mode 100644 index 0000000..2b7707f --- a/dev/null +++ b/libetpan/src/low-level/imf/mailimf_write_file.h @@ -0,0 +1,169 @@ +/* + * 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. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMF_WRITE_H + +#define MAILIMF_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> +#include <libetpan/mailimf_types.h> + + //#define MAILIMF_WRITE_COMPATIBILITY + +/* + mailimf_string_write_file writes a string to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_string_write_file(FILE * f, int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write_file writes the fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_fields_write_file(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write_file writes only some fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_envelope_fields_write_file(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write_file writes a field to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ + +int mailimf_field_write_file(FILE * f, int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write_file writes a string that is quoted + to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ + +int mailimf_quoted_string_write_file(FILE * f, int * col, + const char * string, size_t len); + +int mailimf_address_list_write_file(FILE * f, int * col, + struct mailimf_address_list * addr_list); + +int mailimf_mailbox_list_write_file(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write_file writes a header value and fold the header + if needed. + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_header_string_write_file(FILE * f, int * col, + const char * str, size_t length); + + + +/* binary compatibility with 0.34 - begin */ + +#ifdef MAILIMF_WRITE_COMPATIBILITY +int mailimf_string_write(FILE * f, int * col, + const char * str, size_t length); + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field); + +int mailimf_quoted_string_write(FILE * f, int * col, + const char * string, size_t len); + +int mailimf_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list); + +int mailimf_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list); + +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length); +#endif + +/* binary compatibility with 0.34 - end */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libetpan/src/low-level/imf/mailimf_write_generic.c b/libetpan/src/low-level/imf/mailimf_write_generic.c new file mode 100644 index 0000000..74c1d43 --- a/dev/null +++ b/libetpan/src/low-level/imf/mailimf_write_generic.c @@ -0,0 +1,2028 @@ +/* + * 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. + */ + +/* + * $Id$ + */ + +#include "mailimf_write_generic.h" + +#include <time.h> +#include <string.h> +#include <ctype.h> + +#define MAX_MAIL_COL 72 + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define MAX_VALID_IMF_LINE 998 + +static int mailimf_orig_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_orig_date * date); +static int mailimf_date_time_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_date_time * date_time); +static int mailimf_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_from * from); +static int mailimf_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_sender * sender); +static int mailimf_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_reply_to * reply_to); +static int mailimf_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_to * to); +static int mailimf_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_cc * to); +static int mailimf_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_bcc * to); +static int mailimf_message_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_message_id * message_id); +static int mailimf_msg_id_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + clist * list); +static int mailimf_in_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_in_reply_to * + in_reply_to); +static int mailimf_references_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_references * references); +static int mailimf_subject_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_subject * subject); + +static int mailimf_address_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_address * addr); +static int mailimf_group_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_group * group); + +static int mailimf_mailbox_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_mailbox * mb); + +static int mailimf_comments_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_comments * comments); + +static int mailimf_optional_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_optional_field * field); + +static int mailimf_keywords_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_keywords * keywords); + +static int mailimf_return_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_return * return_path); + +static int mailimf_path_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_path * path); + +static int mailimf_resent_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_orig_date * date); + +static int mailimf_resent_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_from * from); + +static int mailimf_resent_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_sender * sender); + +static int mailimf_resent_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_to * to); + +static int mailimf_resent_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_cc * cc); + +static int mailimf_resent_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_bcc * bcc); + +static int +mailimf_resent_msg_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_message_id * message_id); + + + +/* ************************ */ + +#if 0 +int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + char * str, size_t length) +{ + int r; + + if (length != 0) { + r = fwrite(str, sizeof(char), length, f); + if (r < 0) + return MAILIMF_ERROR_FILE; + * col += length; + } + + return MAILIMF_NO_ERROR; +} +#endif + +#define CRLF "\r\n" +#define HEADER_FOLD "\r\n " + +static inline int flush_buf(int (* do_write)(void *, const char *, size_t), void * data, const char * str, size_t length) +{ + if (length != 0) { + int r; + + if (length > 0) { + r = do_write(data, str, length); + if (r == 0) + return MAILIMF_ERROR_FILE; + } + } + return MAILIMF_NO_ERROR; +} + +#define CUT_AT_MAX_VALID_IMF_LINE + +int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char * str, size_t length) +{ + int r; + size_t count; + const char * block_begin; + const char * p; + int done; + + p = str; + block_begin = str; + count = 0; + + while (length > 0) { +#ifdef CUT_AT_MAX_VALID_IMF_LINE + if (count >= 998) { + /* + cut lines at maximum valid length for internet message + format standard (currently RFC 2822) + + This should not happen. + In case there are some lines larger than 998 in body, + the encoding must be changed into base64 or quoted-printable + so that wrapping to 72 columns is done. + */ + + r = flush_buf(do_write, data, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = do_write(data, CRLF, sizeof(CRLF) - 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + + count = 0; + block_begin = p; + + * col = 0; + } +#endif + switch (* p) { + case '\n': + r = flush_buf(do_write, data, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = do_write(data, CRLF, sizeof(CRLF) - 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p ++; + length --; + count = 0; + block_begin = p; + + * col = 0; + break; + + case '\r': + done = 0; + if (length >= 2) { + if (* (p + 1) == '\n') { + r = flush_buf(do_write, data, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = do_write(data, CRLF, sizeof(CRLF) - 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p += 2; + length -= 2; + count = 0; + block_begin = p; + + * col = 0; + + done = 1; + } + } + if (!done) { + r = flush_buf(do_write, data, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = do_write(data, CRLF, sizeof(CRLF) - 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p ++; + length --; + count = 0; + block_begin = p; + + * col = 0; + } + break; + + default: + p ++; + count ++; + length --; + break; + } + } + + r = flush_buf(do_write, data, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + * col += count; + + return MAILIMF_NO_ERROR; +} + +#if 0 +int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + char * str, size_t length) +{ + char * p; + char * block_begin; + int current_col; + char * last_cut; + int r; + int first; + + if (* col + length < MAX_MAIL_COL) + return mailimf_string_write_driver(do_write, data, col, str, length); + + first = 1; + p = str; + block_begin = p; + last_cut = block_begin; + current_col = * col; + + while (1) { + if (current_col >= MAX_MAIL_COL) { + /* if we reach the maximum recommanded size of line */ + if (last_cut == block_begin) { + /* if we could not find any place to cut */ + if (first) { + /* fold the header */ + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + current_col = * col + p - block_begin; + first = 0; + } + else { + /* cut the header */ + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + first = 0; + block_begin = p; + last_cut = block_begin; + current_col = * col + p - block_begin; + } + } + else { + /* if we found a place to cut */ + r = mailimf_string_write_driver(do_write, data, col, block_begin, last_cut - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + first = 0; + block_begin = last_cut; + last_cut = block_begin; + current_col = * col + p - block_begin; + continue; + } + } + else { + if (length == 0) + break; + + switch (* p) { + case ' ': + case '\t': + last_cut = p; + current_col ++; + break; + + case '\r': + case '\n': + current_col = 0; + break; + + default: + current_col ++; + break; + } + + p ++; + length --; + } + } + + return mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); +} +#endif + +#if 0 +enum { + STATE_LOWER_72, + STATE_LOWER_72_CUT, + STATE_EQUAL_72, + STATE_LOWER_998, + STATE_EQUAL_998, +}; + +int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char * str, size_t length) +{ + int state; + const char * p; + const char * block_begin; + size_t size; + const char * cut; + int r; + + if (* col < MAX_MAIL_COL) + state = STATE_LOWER_72_CUT; + else if (* col == MAX_MAIL_COL) + state = STATE_EQUAL_72; + else if (* col < MAX_VALID_IMF_LINE) + state = STATE_LOWER_998; + else + state = STATE_EQUAL_998; + + p = str; + block_begin = p; + size = * col; + cut = p; + + while (length > 0) { + switch (state) { + case STATE_LOWER_72: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + break; + + case ' ': + case '\t': + cut = p; + p ++; + length --; + size ++; + state = STATE_LOWER_72_CUT; + break; + + default: + if (size < MAX_MAIL_COL - 1) { + p ++; + length --; + size ++; + } + else { + state = STATE_EQUAL_72; + p ++; + length --; + size ++; + } + break; + } + break; /* end of STATE_LOWER_72 */ + + case STATE_LOWER_72_CUT: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + cut = p; + p ++; + length --; + size ++; + break; + + default: + if (size < MAX_MAIL_COL) { + p ++; + length --; + size ++; + } + else { + r = mailimf_string_write_driver(do_write, data, col, block_begin, cut - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = cut; + if ((* block_begin == ' ') || (* block_begin == '\t')) + block_begin ++; + size = p - block_begin + * col; + state = STATE_LOWER_72; + } + break; + } + break; /* end of STATE_LOWER_72_CUT */ + + case STATE_EQUAL_72: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: + p ++; + length --; + size ++; + state = STATE_LOWER_998; + break; + } + break; /* end of STATE_EQUAL_72 */ + + case STATE_LOWER_998: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: + if (size < MAX_VALID_IMF_LINE - 1) { + p ++; + length --; + size ++; + } + else { + p ++; + length --; + size = 0; + state = STATE_EQUAL_998; + } + break; + } + break; /* end of STATE_LOWER_998 */ + + case STATE_EQUAL_998: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: +#ifdef CUT_AT_MAX_VALID_IMF_LINE + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; +#else + p ++; + length --; + size ++; +#endif + break; + } + break; /* end of STATE_EQUAL_998 */ + } + } + + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +enum { + STATE_BEGIN, + STATE_WORD, + STATE_SPACE, +}; + +int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char * str, size_t length) +{ + int state; + const char * p; + const char * word_begin; + const char * word_end; + const char * next_word; + int first; + + state = STATE_BEGIN; + + p = str; + word_begin = p; + word_end = p; + next_word = p; + first = 1; + + while (length > 0) { + switch (state) { + case STATE_BEGIN: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + p ++; + length --; + break; + + default: + word_begin = p; + state = STATE_WORD; + break; + } + break; + + case STATE_SPACE: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + p ++; + length --; + break; + + default: + word_begin = p; + state = STATE_WORD; + break; + } + break; + + case STATE_WORD: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + if (p - word_begin + (* col) + 1 > MAX_MAIL_COL) + mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + else { + if (!first) + mailimf_string_write_driver(do_write, data, col, " ", 1); + } + first = 0; + mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin); + state = STATE_SPACE; + break; + + default: + if (p - word_begin + (* col) >= MAX_VALID_IMF_LINE) { + mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin); + mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + word_begin = p; + } + p ++; + length --; + break; + } + break; + } + } + + if (state == STATE_WORD) { + if (p - word_begin + (* col) >= MAX_MAIL_COL) + mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + else { + if (!first) + mailimf_string_write_driver(do_write, data, col, " ", 1); + } + first = 0; + mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin); + } + + return MAILIMF_NO_ERROR; +} + +int mailimf_envelope_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + int r; + struct mailimf_field * field; + + field = clist_content(cur); + if (field->fld_type != MAILIMF_FIELD_OPTIONAL_FIELD) { + r = mailimf_field_write_driver(do_write, data, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + return MAILIMF_NO_ERROR; +} + +int mailimf_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + int r; + + r = mailimf_field_write_driver(do_write, data, col, clist_content(cur)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + +#if 0 +int mailimf_unparsed_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_unparsed_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->list) ; cur != NULL ; cur = cur->next) { + int r; + + r = mailimf_optional_field_write_driver(do_write, data, col, cur->data); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} +#endif + +int mailimf_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_field * field) +{ + int r; + + switch (field->fld_type) { + case MAILIMF_FIELD_RETURN_PATH: + r = mailimf_return_write_driver(do_write, data, col, field->fld_data.fld_return_path); + break; + case MAILIMF_FIELD_RESENT_DATE: + r = mailimf_resent_date_write_driver(do_write, data, col, field->fld_data.fld_resent_date); + break; + case MAILIMF_FIELD_RESENT_FROM: + r = mailimf_resent_from_write_driver(do_write, data, col, field->fld_data.fld_resent_from); + break; + case MAILIMF_FIELD_RESENT_SENDER: + r = mailimf_resent_sender_write_driver(do_write, data, col, field->fld_data.fld_resent_sender); + break; + case MAILIMF_FIELD_RESENT_TO: + r = mailimf_resent_to_write_driver(do_write, data, col, field->fld_data.fld_resent_to); + break; + case MAILIMF_FIELD_RESENT_CC: + r = mailimf_resent_cc_write_driver(do_write, data, col, field->fld_data.fld_resent_cc); + break; + case MAILIMF_FIELD_RESENT_BCC: + r = mailimf_resent_bcc_write_driver(do_write, data, col, field->fld_data.fld_resent_bcc); + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + r = mailimf_resent_msg_id_write_driver(do_write, data, col, field->fld_data.fld_resent_msg_id); + break; + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_orig_date_write_driver(do_write, data, col, field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + r = mailimf_from_write_driver(do_write, data, col, field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_sender_write_driver(do_write, data, col, field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_reply_to_write_driver(do_write, data, col, field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + r = mailimf_to_write_driver(do_write, data, col, field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + r = mailimf_cc_write_driver(do_write, data, col, field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + r = mailimf_bcc_write_driver(do_write, data, col, field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_message_id_write_driver(do_write, data, col, field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_in_reply_to_write_driver(do_write, data, col, field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_references_write_driver(do_write, data, col, field->fld_data.fld_references); + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_subject_write_driver(do_write, data, col, field->fld_data.fld_subject); + break; + case MAILIMF_FIELD_COMMENTS: + r = mailimf_comments_write_driver(do_write, data, col, field->fld_data.fld_comments); + break; + case MAILIMF_FIELD_KEYWORDS: + r = mailimf_keywords_write_driver(do_write, data, col, field->fld_data.fld_keywords); + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + r = mailimf_optional_field_write_driver(do_write, data, col, field->fld_data.fld_optional_field); + break; + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_orig_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_orig_date * date) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Date: ", 6); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_date_time_write_driver(do_write, data, col, date->dt_date_time); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +#define MAX_DATE_STR 256 + +/* 0 = Sunday */ +/* y > 1752 */ + +static int dayofweek(int year, int month, int day) +{ + static int offset[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; + + year -= month < 3; + + return (year + year/4 - year/100 + year/400 + offset[month-1] + day) % 7; +} + +static const char * week_of_day_str[] = { "Sun", "Mon", "Tue", "Wed", "Thu", + "Fri", "Sat"}; +static const char * month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +static int mailimf_date_time_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_date_time * date_time) +{ + int r; + char date_str[MAX_DATE_STR]; +#if 0 + struct tm tmval; + time_t timeval; +#endif + int wday; + +#if 0 + tmval.tm_sec = date_time->sec; + tmval.tm_min = date_time->min; + tmval.tm_hour = date_time->hour; + tmval.tm_sec = date_time->sec; + tmval.tm_mday = date_time->day; + tmval.tm_mon = date_time->month - 1; + tmval.tm_year = date_time->year - 1900; + tmval.tm_isdst = 1; + + timeval = mktime(&tmval); + + localtime_r(&timeval, &tmval); +#endif + + wday = dayofweek(date_time->dt_year, date_time->dt_month, date_time->dt_day); + + snprintf(date_str, MAX_DATE_STR, "%s, %i %s %i %02i:%02i:%02i %+05i", + week_of_day_str[wday], date_time->dt_day, + month_str[date_time->dt_month - 1], + date_time->dt_year, date_time->dt_hour, + date_time->dt_min, date_time->dt_sec, + date_time->dt_zone); + + r = mailimf_string_write_driver(do_write, data, col, date_str, strlen(date_str)); + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int mailimf_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_from * from) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "From: ", 6); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_list_write_driver(do_write, data, col, from->frm_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_sender * sender) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Sender: ", 8); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_write_driver(do_write, data, col, sender->snd_mb); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_reply_to * reply_to) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Reply-To: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write_driver(do_write, data, col, reply_to->rt_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_to * to) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "To: ", 4); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write_driver(do_write, data, col, to->to_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_cc * cc) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Cc: ", 4); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write_driver(do_write, data, col, cc->cc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_bcc * bcc) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Bcc: ", 5); + if (r != MAILIMF_NO_ERROR) + return r; + + if (bcc->bcc_addr_list != NULL) { + r = mailimf_address_list_write_driver(do_write, data, col, bcc->bcc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_message_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_message_id * message_id) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Message-ID: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, + message_id->mid_value, + strlen(message_id->mid_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_msg_id_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, clist * mid_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(mid_list) ; cur != NULL ; cur = clist_next(cur)) { + char * msgid; + size_t len; + + msgid = clist_content(cur); + len = strlen(msgid); + + /* + XXX - if this is the first message ID, don't fold. + This is a workaround for a bug of old versions of INN. + */ + if (!first) { + if (* col > 1) { + + if (* col + len >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + first = TRUE; + } + } + } + + if (!first) { + r = mailimf_string_write_driver(do_write, data, col, " ", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_string_write_driver(do_write, data, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, msgid, len); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_in_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_in_reply_to * in_reply_to) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "In-Reply-To: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_msg_id_list_write_driver(do_write, data, col, in_reply_to->mid_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_references_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_references * references) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "References: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_msg_id_list_write_driver(do_write, data, col, references->mid_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + + +static int mailimf_subject_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_subject * subject) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Subject: ", 9); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write_driver(do_write, data, col, + subject->sbj_value, strlen(subject->sbj_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +int mailimf_address_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_address_list * addr_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + if (!first) { + r = mailimf_string_write_driver(do_write, data, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_address_write_driver(do_write, data, col, addr); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_address_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_address * addr) +{ + int r; + + switch(addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + r = mailimf_mailbox_write_driver(do_write, data, col, addr->ad_data.ad_mailbox); + if (r != MAILIMF_NO_ERROR) + return r; + + break; + + case MAILIMF_ADDRESS_GROUP: + r = mailimf_group_write_driver(do_write, data, col, addr->ad_data.ad_group); + if (r != MAILIMF_NO_ERROR) + return r; + + break; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_group_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_group * group) +{ + int r; + + r = mailimf_header_string_write_driver(do_write, data, col, group->grp_display_name, + strlen(group->grp_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ": ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + if (group->grp_mb_list != NULL) { + r = mailimf_mailbox_list_write_driver(do_write, data, col, group->grp_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, ";", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + + +int mailimf_mailbox_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + if (!first) { + r = mailimf_string_write_driver(do_write, data, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_mailbox_write_driver(do_write, data, col, mb); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +int mailimf_quoted_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char * string, size_t len) +{ + int r; + size_t i; + + r = do_write(data, "\"", 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + for(i = 0 ; i < len ; i ++) { + switch (string[i]) { + case '\\': + case '\"': + r = do_write(data, "\\", 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + r = do_write(data, &string[i], 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + (* col) += 2; + break; + + default: + r = do_write(data, &string[i], 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + (* col) ++; + break; + } + } + r = do_write(data, "\"", 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + + return MAILIMF_NO_ERROR; +} + + +/* +static int +atext = ALPHA / DIGIT / ; Any character except controls, + "!" / "#" / ; SP, and specials. + "$" / "%" / ; Used for atoms + "&" / "'" / + "*" / "+" / + "-" / "/" / + "=" / "?" / + "^" / "_" / + "`" / "{" / + "|" / "}" / + "~" +*/ + +static int is_atext(const char * s) +{ + const char * p; + + for(p = s ; * p != 0 ; p ++) { + if (isalpha((unsigned char) * p)) + continue; + if (isdigit((unsigned char) * p)) + continue; + switch (*p) { + case ' ': + case '\t': + case '!': + case '#': + case '$': + case '%': + case '&': + case '\'': + case '*': + case '+': + case '-': + case '/': + case '=': + case '?': + case '^': + case '_': + case '`': + case '{': + case '|': + case '}': + case '~': + break; + default: + return 0; + } + } + + return 1; +} + +static int mailimf_mailbox_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_mailbox * mb) +{ + int r; + int do_fold; + +#if 0 + if (* col > 1) { + + if (mb->mb_display_name != NULL) { + if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + } +#endif + + if (mb->mb_display_name) { + + if (is_atext(mb->mb_display_name)) { + r = mailimf_header_string_write_driver(do_write, data, col, mb->mb_display_name, + strlen(mb->mb_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + if (mb->mb_display_name != NULL) { + if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + if (strlen(mb->mb_display_name) > MAX_VALID_IMF_LINE / 2) + return MAILIMF_ERROR_INVAL; + + r = mailimf_quoted_string_write_driver(do_write, data, col, mb->mb_display_name, + strlen(mb->mb_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + do_fold = 0; + if (* col > 1) { + + if (* col + strlen(mb->mb_addr_spec) + 3 >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + do_fold = 1; + } + } + + if (do_fold) + r = mailimf_string_write_driver(do_write, data, col, "<", 1); + else + r = mailimf_string_write_driver(do_write, data, col, " <", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, mb->mb_addr_spec, + strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + if (* col + strlen(mb->mb_addr_spec) >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, + mb->mb_addr_spec, strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + + return MAILIMF_NO_ERROR; +} + +static int mailimf_comments_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_comments * comments) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Comments: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write_driver(do_write, data, col, + comments->cm_value, strlen(comments->cm_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_optional_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_optional_field * field) +{ + int r; + + if (strlen(field->fld_name) + 2 > MAX_VALID_IMF_LINE) + return MAILIMF_ERROR_INVAL; + + r = mailimf_string_write_driver(do_write, data, col, field->fld_name, strlen(field->fld_name)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ": ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write_driver(do_write, data, col, field->fld_value, + strlen(field->fld_value)); + if (r != MAILIMF_NO_ERROR) + return r; + +#if 0 + /* XXX parsing debug */ + mailimf_string_write_driver(do_write, data, col, " (X)", 4); +#endif + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_keywords_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_keywords * keywords) +{ + int r; + clistiter * cur; + int first; + + r = mailimf_string_write_driver(do_write, data, col, "Keywords: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + first = TRUE; + + for(cur = clist_begin(keywords->kw_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * keyword; + size_t len; + + keyword = clist_content(cur); + len = strlen(keyword); + + if (!first) { + r = mailimf_string_write_driver(do_write, data, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + +#if 0 + if (* col > 1) { + + if (* col + len >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } +#endif + + r = mailimf_header_string_write_driver(do_write, data, col, keyword, len); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +#if 0 +static int mailimf_delivering_info_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_delivering_info * info) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(info->received_fields) ; + cur != NULL ; cur = cur->next) { + struct mailimf_trace_resent_fields * field; + + field = cur->data; + + r = mailimf_trace_resent_fields_write_driver(do_write, data, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int +mailimf_trace_resent_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_trace_resent_fields * field) +{ + int r; + + if (field->return_path != NULL) { + r = mailimf_return_write_driver(do_write, data, col, field->return_path); + if (r != MAILIMF_NO_ERROR) + return r; + } + + if (field->resent_fields != NULL) { + r = mailimf_resent_fields_write_driver(do_write, data, col, field->resent_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} +#endif + +static int mailimf_return_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_return * return_path) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Return-Path: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_path_write_driver(do_write, data, col, return_path->ret_path); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_path_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_path * path) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, path->pt_addr_spec, + strlen(path->pt_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +#if 0 +static int mailimf_resent_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_resent_fields_list * + resent_fields) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(resent_fields->list) ; cur != NULL ; cur = cur->next) { + struct mailimf_resent_field * field; + + field = cur->data; + + r = mailimf_resent_field_write_driver(do_write, data, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + + +static int mailimf_resent_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_resent_field * + resent_field) +{ + int r; + + switch (resent_field->type) { + case MAILIMF_RESENT_FIELD_DATE: + r = mailimf_resent_date_write_driver(do_write, data, col, resent_field->resent_date); + break; + + case MAILIMF_RESENT_FIELD_FROM: + r = mailimf_resent_from_write_driver(do_write, data, col, resent_field->resent_from); + break; + + case MAILIMF_RESENT_FIELD_SENDER: + r = mailimf_resent_sender_write_driver(do_write, data, col, resent_field->resent_sender); + break; + + case MAILIMF_RESENT_FIELD_TO: + r = mailimf_resent_to_write_driver(do_write, data, col, resent_field->resent_to); + break; + + case MAILIMF_RESENT_FIELD_CC: + r = mailimf_resent_cc_write_driver(do_write, data, col, resent_field->resent_cc); + break; + + case MAILIMF_RESENT_FIELD_BCC: + r = mailimf_resent_bcc_write_driver(do_write, data, col, resent_field->resent_bcc); + break; + + case MAILIMF_RESENT_FIELD_MSG_ID: + r = mailimf_resent_msg_id_write_driver(do_write, data, col, resent_field->resent_msg_id); + break; + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +static int mailimf_resent_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_orig_date * date) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-Date: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_date_time_write_driver(do_write, data, col, date->dt_date_time); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_from * from) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-From: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_list_write_driver(do_write, data, col, from->frm_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_sender * sender) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-Sender: ", 15); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_write_driver(do_write, data, col, sender->snd_mb); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_to * to) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-To: ", 11); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write_driver(do_write, data, col, to->to_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_resent_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_cc * cc) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-Cc: ", 11); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write_driver(do_write, data, col, cc->cc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_resent_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_bcc * bcc) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-Bcc: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + if (bcc->bcc_addr_list != NULL) { + r = mailimf_address_list_write_driver(do_write, data, col, bcc->bcc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int +mailimf_resent_msg_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_message_id * message_id) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-Message-ID: ", 19); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, + message_id->mid_value, strlen(message_id->mid_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} diff --git a/libetpan/src/low-level/imf/mailimf_write_generic.h b/libetpan/src/low-level/imf/mailimf_write_generic.h new file mode 100644 index 0000000..c207d7e --- a/dev/null +++ b/libetpan/src/low-level/imf/mailimf_write_generic.h @@ -0,0 +1,142 @@ +/* + * 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. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMF_WRITE_GENERIC_H + +#define MAILIMF_WRITE_GENERIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> +#include <libetpan/mailimf_types.h> + +/* + mailimf_string_write writes a string to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write writes the fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write writes only some fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_envelope_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write writes a field to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ + +int mailimf_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write writes a string that is quoted + to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ + +int mailimf_quoted_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + const char * string, size_t len); + +int mailimf_address_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_address_list * addr_list); + +int mailimf_mailbox_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write writes a header value and fold the header + if needed. + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + const char * str, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libetpan/src/low-level/imf/mailimf_write_mem.c b/libetpan/src/low-level/imf/mailimf_write_mem.c new file mode 100644 index 0000000..00c043f --- a/dev/null +++ b/libetpan/src/low-level/imf/mailimf_write_mem.c @@ -0,0 +1,98 @@ +/* + * 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. + */ + +/* + * $Id$ + */ + +#include "mailimf_write_mem.h" +#include "mailimf_write_generic.h" + +static int do_write(void * data, const char * str, size_t length) +{ + MMAPString * f; + + f = data; + + if (mmap_string_append_len(f, str, length) == NULL) + return 0; + else + return length; +} + +int mailimf_string_write_mem(MMAPString * f, int * col, + const char * str, size_t length) +{ + return mailimf_string_write_driver(do_write, f, col, str, length); +} + +int mailimf_fields_write_mem(MMAPString * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_fields_write_driver(do_write, f, col, fields); +} + +int mailimf_envelope_fields_write_mem(MMAPString * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_envelope_fields_write_driver(do_write, f, col, fields); +} + +int mailimf_field_write_mem(MMAPString * f, int * col, + struct mailimf_field * field) +{ + return mailimf_field_write_driver(do_write, f, col, field); +} + +int mailimf_quoted_string_write_mem(MMAPString * f, int * col, + const char * string, size_t len) +{ + return mailimf_quoted_string_write_driver(do_write, f, col, string, len); +} + +int mailimf_address_list_write_mem(MMAPString * f, int * col, + struct mailimf_address_list * addr_list) +{ + return mailimf_address_list_write_driver(do_write, f, col, addr_list); +} + +int mailimf_mailbox_list_write_mem(MMAPString * f, int * col, + struct mailimf_mailbox_list * mb_list) +{ + return mailimf_mailbox_list_write_driver(do_write, f, col, mb_list); +} + +int mailimf_header_string_write_mem(MMAPString * f, int * col, + const char * str, size_t length) +{ + return mailimf_header_string_write_driver(do_write, f, col, str, length); +} + diff --git a/libetpan/src/low-level/imf/mailimf_write_mem.h b/libetpan/src/low-level/imf/mailimf_write_mem.h new file mode 100644 index 0000000..796f178 --- a/dev/null +++ b/libetpan/src/low-level/imf/mailimf_write_mem.h @@ -0,0 +1,135 @@ +/* + * 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. + */ + +/* + * $Id$ + */ + +#ifndef MAILIMF_WRITE_MEM_H + +#define MAILIMF_WRITE_MEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> +#include <libetpan/mailimf_types.h> +#include <libetpan/mmapstring.h> + +/* + mailimf_string_write_mem appends a string to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_string_write_mem(MMAPString * f, int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write_mem appends the fields to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_fields_write_mem(MMAPString * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write_mem appends some fields to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_envelope_fields_write_mem(MMAPString * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write_mem appends a field to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ + +int mailimf_field_write_mem(MMAPString * f, int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write_mem appends a string that is quoted + to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ + +int mailimf_quoted_string_write_mem(MMAPString * f, int * col, + const char * string, size_t len); + +int mailimf_address_list_write_mem(MMAPString * f, int * col, + struct mailimf_address_list * addr_list); + +int mailimf_mailbox_list_write_mem(MMAPString * f, int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write_mem appends a header value and fold the header + if needed. + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_header_string_write_mem(MMAPString * f, int * col, + const char * str, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif |