summaryrefslogtreecommitdiffabout
path: root/kmicromail/libetpan/imf
authorzautrix <zautrix>2004-09-01 10:23:29 (UTC)
committer zautrix <zautrix>2004-09-01 10:23:29 (UTC)
commit6cefbdc9c8f3f3001373f10715361e2740c45395 (patch) (side-by-side diff)
treecb2c36f57620e698913c27ca4ebe59e4a7c9d46e /kmicromail/libetpan/imf
parentb9257cb225cd29bab5d96fcdaf557926603ee587 (diff)
downloadkdepimpi-6cefbdc9c8f3f3001373f10715361e2740c45395.zip
kdepimpi-6cefbdc9c8f3f3001373f10715361e2740c45395.tar.gz
kdepimpi-6cefbdc9c8f3f3001373f10715361e2740c45395.tar.bz2
Mail fixes and libetpan updated
Diffstat (limited to 'kmicromail/libetpan/imf') (more/less context) (ignore whitespace changes)
-rw-r--r--kmicromail/libetpan/imf/mailimf.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/kmicromail/libetpan/imf/mailimf.c b/kmicromail/libetpan/imf/mailimf.c
index 84d81a1..e0164b8 100644
--- a/kmicromail/libetpan/imf/mailimf.c
+++ b/kmicromail/libetpan/imf/mailimf.c
@@ -1,7585 +1,7585 @@
/*
* libEtPan! -- a mail stuff library
*
* Copyright (C) 2001, 2002 - 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 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.
*/
/*
* $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 "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;
}