summaryrefslogtreecommitdiffabout
path: root/libetpan/src/low-level/imf
Side-by-side diff
Diffstat (limited to 'libetpan/src/low-level/imf') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/low-level/imf/TODO12
-rw-r--r--libetpan/src/low-level/imf/mailimf.c7585
-rw-r--r--libetpan/src/low-level/imf/mailimf.h347
-rw-r--r--libetpan/src/low-level/imf/mailimf_types.c868
-rw-r--r--libetpan/src/low-level/imf/mailimf_types.h793
-rw-r--r--libetpan/src/low-level/imf/mailimf_types_helper.c1636
-rw-r--r--libetpan/src/low-level/imf/mailimf_types_helper.h370
-rw-r--r--libetpan/src/low-level/imf/mailimf_write.c2021
-rw-r--r--libetpan/src/low-level/imf/mailimf_write.h134
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_file.c149
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_file.h169
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_generic.c2028
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_generic.h142
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_mem.c98
-rw-r--r--libetpan/src/low-level/imf/mailimf_write_mem.h135
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, &lt) == NULL)
+ return NULL;
+
+ off = (mkgmtime(&lt) - 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