summaryrefslogtreecommitdiffabout
path: root/kmicromail/libetpan/imf/mailimf.c
Side-by-side diff
Diffstat (limited to 'kmicromail/libetpan/imf/mailimf.c') (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,1587 +1,1587 @@
/*
* 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;