|
|
- /*
- * libEtPan! -- a mail stuff library
- *
- * Copyright (C) 2001, 2005 - DINH Viet Hoa
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the libEtPan! project nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
- /*
- * $Id: mailimf.c,v 1.50 2011/06/20 23:25:26 hoa Exp $
- */
-
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
-
- #include "mailimf.h"
-
- /*
- RFC 2822
-
- RFC 2821 ...
- A message-originating SMTP system SHOULD NOT send a message that
- already contains a Return-path header. SMTP servers performing a
- relay function MUST NOT inspect the message data, and especially not
- to the extent needed to determine if Return-path headers are present.
- SMTP servers making final delivery MAY remove Return-path headers
- before adding their own.
- */
-
- #include <ctype.h>
- #include "mmapstring.h"
- #include <stdlib.h>
- #include <string.h>
- #include "mailmime_decode.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 * indx, char * result);
-
- static int mailimf_ccontent_parse(const char * message, size_t length,
- size_t * indx);
-
- static int
- mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
- size_t * indx);
-
- static inline int mailimf_comment_parse(const char * message, size_t length,
- size_t * indx);
-
- static int mailimf_qcontent_parse(const char * message, size_t length,
- size_t * indx, char * ch);
-
- static int mailimf_phrase_parse(const char * message, size_t length,
- size_t * indx, char ** result);
-
- static int mailimf_unstructured_parse(const char * message, size_t length,
- size_t * indx, char ** result);
-
- static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
- size_t * indx);
-
- static int mailimf_day_of_week_parse(const char * message, size_t length,
- size_t * indx, int * result);
-
- static int mailimf_day_name_parse(const char * message, size_t length,
- size_t * indx, int * result);
-
- static int mailimf_date_parse(const char * message, size_t length,
- size_t * indx,
- int * pday, int * pmonth, int * pyear);
-
- static int mailimf_year_parse(const char * message, size_t length,
- size_t * indx, int * result);
-
- static int mailimf_month_parse(const char * message, size_t length,
- size_t * indx, int * result);
-
- static int mailimf_month_name_parse(const char * message, size_t length,
- size_t * indx, int * result);
-
- static int mailimf_day_parse(const char * message, size_t length,
- size_t * indx, int * result);
-
- static int mailimf_time_parse(const char * message, size_t length,
- size_t * indx,
- int * phour, int * pmin,
- int * psec,
- int * zone);
- static int mailimf_time_of_day_parse(const char * message, size_t length,
- size_t * indx,
- int * phour, int * pmin,
- int * psec);
-
- static int mailimf_hour_parse(const char * message, size_t length,
- size_t * indx, int * result);
-
- static int mailimf_minute_parse(const char * message, size_t length,
- size_t * indx, int * result);
-
- static int mailimf_second_parse(const char * message, size_t length,
- size_t * indx, int * result);
-
- static int mailimf_zone_parse(const char * message, size_t length,
- size_t * indx, int * result);
-
- static int mailimf_name_addr_parse(const char * message, size_t length,
- size_t * indx,
- char ** pdisplay_name,
- char ** pangle_addr);
-
- static int mailimf_angle_addr_parse(const char * message, size_t length,
- size_t * indx, char ** result);
-
- static int mailimf_group_parse(const char * message, size_t length,
- size_t * indx,
- struct mailimf_group ** result);
-
- static int mailimf_display_name_parse(const char * message, size_t length,
- size_t * indx, char ** result);
-
- static int mailimf_addr_spec_parse(const char * message, size_t length,
- size_t * indx,
- char ** address);
-
- static int
- mailimf_orig_date_parse(const char * message, size_t length,
- size_t * indx, struct mailimf_orig_date ** result);
-
- static int
- mailimf_from_parse(const char * message, size_t length,
- size_t * indx, struct mailimf_from ** result);
-
- static int
- mailimf_sender_parse(const char * message, size_t length,
- size_t * indx, struct mailimf_sender ** result);
-
- static int
- mailimf_reply_to_parse(const char * message, size_t length,
- size_t * indx, struct mailimf_reply_to ** result);
-
- static int
- mailimf_to_parse(const char * message, size_t length,
- size_t * indx, struct mailimf_to ** result);
-
- static int
- mailimf_cc_parse(const char * message, size_t length,
- size_t * indx, struct mailimf_cc ** result);
-
- static int
- mailimf_bcc_parse(const char * message, size_t length,
- size_t * indx, struct mailimf_bcc ** result);
-
- static int mailimf_message_id_parse(const char * message, size_t length,
- size_t * indx,
- struct mailimf_message_id ** result);
-
- static int
- mailimf_in_reply_to_parse(const char * message, size_t length,
- size_t * indx,
- struct mailimf_in_reply_to ** result);
-
- static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
- size_t * indx,
- char ** result);
-
- static int mailimf_subject_parse(const char * message, size_t length,
- size_t * indx,
- struct mailimf_subject ** result);
-
- static int mailimf_comments_parse(const char * message, size_t length,
- size_t * indx,
- struct mailimf_comments ** result);
-
- static int mailimf_keywords_parse(const char * message, size_t length,
- size_t * indx,
- struct mailimf_keywords ** result);
-
- static int
- mailimf_resent_date_parse(const char * message, size_t length,
- size_t * indx, struct mailimf_orig_date ** result);
-
- static int
- mailimf_resent_from_parse(const char * message, size_t length,
- size_t * indx, struct mailimf_from ** result);
-
- static int
- mailimf_resent_sender_parse(const char * message, size_t length,
- size_t * indx, struct mailimf_sender ** result);
-
- static int
- mailimf_resent_to_parse(const char * message, size_t length,
- size_t * indx, struct mailimf_to ** result);
-
- static int
- mailimf_resent_cc_parse(const char * message, size_t length,
- size_t * indx, struct mailimf_cc ** result);
-
- static int
- mailimf_resent_bcc_parse(const char * message, size_t length,
- size_t * indx, struct mailimf_bcc ** result);
-
- static int
- mailimf_resent_msg_id_parse(const char * message, size_t length,
- size_t * indx,
- struct mailimf_message_id ** result);
-
- static int mailimf_return_parse(const char * message, size_t length,
- size_t * indx,
- struct mailimf_return ** result);
-
- static int
- mailimf_path_parse(const char * message, size_t length,
- size_t * indx, struct mailimf_path ** result);
-
- static int
- mailimf_optional_field_parse(const char * message, size_t length,
- size_t * indx,
- struct mailimf_optional_field ** result);
-
- static int mailimf_field_name_parse(const char * message, size_t length,
- size_t * indx, 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 * indx, int * result)
- {
- size_t cur_token;
-
- cur_token = * indx;
-
- if (cur_token >= length)
- return MAILIMF_ERROR_PARSE;
-
- if (is_digit(message[cur_token])) {
- * result = message[cur_token] - '0';
- cur_token ++;
- * indx = cur_token;
- return MAILIMF_NO_ERROR;
- }
- else
- return MAILIMF_ERROR_PARSE;
- }
-
- LIBETPAN_EXPORT
- int
- mailimf_number_parse(const char * message, size_t length,
- size_t * indx, uint32_t * result)
- {
- size_t cur_token;
- int digit;
- uint32_t number;
- int parsed;
- int r;
-
- cur_token = * indx;
- 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;
- * indx = cur_token;
-
- return MAILIMF_NO_ERROR;
- }
-
- LIBETPAN_EXPORT
- int mailimf_char_parse(const char * message, size_t length,
- size_t * indx, char token)
- {
- size_t cur_token;
-
- cur_token = * indx;
-
- if (cur_token >= length)
- return MAILIMF_ERROR_PARSE;
-
- if (message[cur_token] == token) {
- cur_token ++;
- * indx = cur_token;
- return MAILIMF_NO_ERROR;
- }
- else
- return MAILIMF_ERROR_PARSE;
- }
-
- LIBETPAN_EXPORT
- int mailimf_unstrict_char_parse(const char * message, size_t length,
- size_t * indx, char token)
- {
- size_t cur_token;
- int r;
-
- cur_token = * indx;
-
- 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;
-
- * indx = cur_token;
-
- return MAILIMF_NO_ERROR;
- }
-
- LIBETPAN_EXPORT
- int
- mailimf_token_case_insensitive_len_parse(const char * message, size_t length,
- size_t * indx, char * token,
- size_t token_length)
- {
- size_t cur_token;
-
- cur_token = * indx;
-
- if (cur_token + token_length - 1 >= length)
- return MAILIMF_ERROR_PARSE;
-
- if (strncasecmp(message + cur_token, token, token_length) == 0) {
- cur_token += token_length;
- * indx = cur_token;
- return MAILIMF_NO_ERROR;
- }
- else
- return MAILIMF_ERROR_PARSE;
- }
-
- static int mailimf_oparenth_parse(const char * message, size_t length,
- size_t * indx)
- {
- return mailimf_char_parse(message, length, indx, '(');
- }
-
- static int mailimf_cparenth_parse(const char * message, size_t length,
- size_t * indx)
- {
- return mailimf_char_parse(message, length, indx, ')');
- }
-
- static int mailimf_comma_parse(const char * message, size_t length,
- size_t * indx)
- {
- return mailimf_unstrict_char_parse(message, length, indx, ',');
- }
-
- static int mailimf_dquote_parse(const char * message, size_t length,
- size_t * indx)
- {
- return mailimf_char_parse(message, length, indx, '\"');
- }
-
- static int mailimf_colon_parse(const char * message, size_t length,
- size_t * indx)
- {
- return mailimf_unstrict_char_parse(message, length, indx, ':');
- }
-
- static int mailimf_semi_colon_parse(const char * message, size_t length,
- size_t * indx)
- {
- return mailimf_unstrict_char_parse(message, length, indx, ';');
- }
-
- static int mailimf_plus_parse(const char * message, size_t length,
- size_t * indx)
- {
- return mailimf_unstrict_char_parse(message, length, indx, '+');
- }
-
- static int mailimf_minus_parse(const char * message, size_t length,
- size_t * indx)
- {
- return mailimf_unstrict_char_parse(message, length, indx, '-');
- }
-
- static int mailimf_lower_parse(const char * message, size_t length,
- size_t * indx)
- {
- return mailimf_unstrict_char_parse(message, length, indx, '<');
- }
-
- static int mailimf_greater_parse(const char * message, size_t length,
- size_t * indx)
- {
- return mailimf_unstrict_char_parse(message, length, indx, '>');
- }
-
- static int mailimf_at_sign_parse(const char * message, size_t length,
- size_t * indx)
- {
- return mailimf_unstrict_char_parse(message, length, indx, '@');
- }
-
- static int mailimf_point_parse(const char * message, size_t length,
- size_t * indx)
- {
- return mailimf_unstrict_char_parse(message, length, indx, '.');
- }
-
- LIBETPAN_EXPORT
- int
- mailimf_custom_string_parse(const char * message, size_t length,
- size_t * indx, char ** result,
- int (* is_custom_char)(char))
- {
- size_t begin;
- size_t end;
- char * gstr;
-
- begin = * indx;
-
- 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';
-
- * indx = 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 * indx, void * result);
-
- typedef int mailimf_struct_destructor(void * result);
-
-
- static int
- mailimf_struct_multiple_parse(const char * message, size_t length,
- size_t * indx, 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 = * indx;
-
- 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;
- * indx = 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 * indx, 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 = * indx;
-
- 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;
- * indx = 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 * indx)
- {
- size_t cur_token;
-
- cur_token = * indx;
-
- if (cur_token >= length)
- return MAILIMF_ERROR_PARSE;
-
- if ((message[cur_token] != ' ') && (message[cur_token] != '\t'))
- return MAILIMF_ERROR_PARSE;
-
- cur_token ++;
- * indx = cur_token;
-
- return MAILIMF_NO_ERROR;
- }
-
-
- LIBETPAN_EXPORT
- int mailimf_crlf_parse(const char * message, size_t length, size_t * indx)
- {
- size_t cur_token;
- int r;
-
- cur_token = * indx;
-
- 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;
-
- * indx = cur_token;
- return MAILIMF_NO_ERROR;
- }
-
- static int mailimf_unstrict_crlf_parse(const char * message,
- size_t length, size_t * indx)
- {
- size_t cur_token;
- int r;
-
- cur_token = * indx;
-
- 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;
-
- * indx = 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 * indx, char * result)
- {
- size_t cur_token;
-
- cur_token = * indx;
-
- 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 ++;
- * indx = cur_token;
-
- return MAILIMF_NO_ERROR;
- }
-
- /*
- FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space
- obs-FWS
- */
-
- LIBETPAN_EXPORT
- int mailimf_fws_parse(const char * message, size_t length, size_t * indx)
- {
- size_t cur_token;
- size_t final_token;
- int fws_1;
- int fws_2;
- int fws_3;
- int r;
-
- cur_token = * indx;
-
- 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;
-
- * indx = 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 * indx)
- {
- size_t cur_token;
- char ch;
- int r;
-
- cur_token = * indx;
-
- 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;
- }
-
- * indx = cur_token;
-
- return MAILIMF_NO_ERROR;
- }
-
- /*
- [FWS] ccontent
- */
-
- static inline int
- mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
- size_t * indx)
- {
- size_t cur_token;
- int r;
-
- cur_token = * indx;
-
- 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;
-
- * indx = cur_token;
-
- return MAILIMF_NO_ERROR;
- }
-
- /*
- comment = "(" *([FWS] ccontent) [FWS] ")"
- */
-
- static inline int mailimf_comment_parse(const char * message, size_t length,
- size_t * indx)
- {
- size_t cur_token;
- int r;
-
- cur_token = * indx;
-
- 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;
-
- * indx = cur_token;
-
- return MAILIMF_NO_ERROR;
- }
-
- /*
- [FWS] comment
- */
-
- static inline int mailimf_cfws_fws_comment_parse(const char * message, size_t length,
- size_t * indx)
- {
- size_t cur_token;
- int r;
-
- cur_token = * indx;
-
- 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;
-
- * indx = cur_token;
-
- return MAILIMF_NO_ERROR;
- }
-
- /*
- CFWS = *([FWS] comment) (([FWS] comment) / FWS)
- */
-
- LIBETPAN_EXPORT
- int mailimf_cfws_parse(const char * message, size_t length,
- size_t * indx)
- {
- size_t cur_token;
- int has_comment;
- int r;
-
- cur_token = * indx;
-
- 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;
- }
-
- * indx = 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]
- */
-
- LIBETPAN_EXPORT
- int mailimf_atom_parse(const char * message, size_t length,
- size_t * indx, char ** result)
- {
- size_t cur_token;
- int r;
- int res;
- char * atom;
- size_t end;
-
- cur_token = * indx;
-
- 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;
-
- * indx = cur_token;
- * result = atom;
-
- return MAILIMF_NO_ERROR;
-
- err:
- return res;
- }
-
- LIBETPAN_EXPORT
- int mailimf_fws_atom_for_word_parse(const char * message, size_t length,
- size_t * indx, char ** result, int * p_missing_closing_quote)
- {
- size_t end;
- size_t cur_token;
- int r;
- int res;
- struct mailmime_encoded_word * word;
- int has_fwd;
- int missing_closing_quote;
- char * atom;
-
- cur_token = * indx;
- missing_closing_quote = 0;
-
- r = mailimf_fws_parse(message, length, &cur_token);
- if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
- res = r;
- goto err;
- }
-
- end = cur_token;
-
- r = mailmime_encoded_word_parse(message, length, &cur_token, &word, &has_fwd, &missing_closing_quote);
- if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
- res = r;
- goto err;
- }
-
- if (r == MAILIMF_ERROR_PARSE) {
- return mailimf_fws_atom_parse(message, length, indx, result);
- }
-
- mailmime_encoded_word_free(word);
-
- atom = malloc(cur_token - end + 1);
- if (atom == NULL) {
- res = MAILIMF_ERROR_MEMORY;
- goto err;
- }
- strncpy(atom, message + end, cur_token - end);
- atom[cur_token - end] = '\0';
-
- * result = atom;
- * indx = cur_token;
- * p_missing_closing_quote = missing_closing_quote;
-
- return MAILIMF_NO_ERROR;
-
- err:
- return res;
- }
-
- LIBETPAN_EXPORT
- int mailimf_fws_atom_parse(const char * message, size_t length,
- size_t * indx, char ** result)
- {
- size_t cur_token;
- int r;
- int res;
- char * atom;
- size_t end;
-
- cur_token = * indx;
-
- 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;
-
- * indx = 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 * indx, char ** result)
- {
- return mailimf_atom_parse(message, length, indx, 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 * indx, char ** result)
- {
- return mailimf_atom_parse(message, length, indx, 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 * indx, char * result)
- {
- size_t cur_token;
- char ch;
- int r;
-
- cur_token = * indx;
-
- 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;
- * indx = cur_token;
-
- return MAILIMF_NO_ERROR;
- }
-
- /*
- quoted-string = [CFWS]
- DQUOTE *([FWS] qcontent) [FWS] DQUOTE
- [CFWS]
- */
-
- LIBETPAN_EXPORT
- int mailimf_quoted_string_parse(const char * message, size_t length,
- size_t * indx, char ** result)
- {
- size_t cur_token;
- MMAPString * gstr;
- char ch;
- char * str;
- int r;
- int res;
-
- cur_token = * indx;
-
- 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);
-
- * indx = cur_token;
- * result = str;
-
- return MAILIMF_NO_ERROR;
-
- free_gstr:
- mmap_string_free(gstr);
- err:
- return res;
- }
-
- LIBETPAN_EXPORT
- int mailimf_fws_quoted_string_parse(const char * message, size_t length,
- size_t * indx, char ** result)
- {
- size_t cur_token;
- MMAPString * gstr;
- char ch;
- char * str;
- int r;
- int res;
-
- cur_token = * indx;
-
- 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);
-
- * indx = cur_token;
- * result = str;
-
- return MAILIMF_NO_ERROR;
-
- free_gstr:
- mmap_string_free(gstr);
- err:
- return res;
- }
-
- /*
- word = atom / quoted-string
- */
-
- LIBETPAN_EXPORT
- int mailimf_word_parse(const char * message, size_t length,
- size_t * indx, char ** result)
- {
- size_t cur_token;
- char * word;
- int r;
-
- cur_token = * indx;
-
- 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;
- * indx = cur_token;
-
- return MAILIMF_NO_ERROR;
- }
-
- LIBETPAN_EXPORT
- int mailimf_fws_word_parse(const char * message, size_t length,
- size_t * indx, char ** result, int * p_missing_closing_quote)
- {
- size_t cur_token;
- char * word;
- int r;
- int missing_closing_quote;
-
- cur_token = * indx;
- missing_closing_quote = 0;
-
- r = mailimf_fws_atom_for_word_parse(message, length, &cur_token, &word, &missing_closing_quote);
-
- 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;
- * indx = cur_token;
- * p_missing_closing_quote = missing_closing_quote;
-
- return MAILIMF_NO_ERROR;
- }
-
- /*
- phrase = 1*word / obs-phrase
- */
-
- static int mailimf_phrase_parse(const char * message, size_t length,
- size_t * indx, char ** result)
- {
- MMAPString * gphrase;
- char * word;
- int first;
- size_t cur_token;
- int r;
- int res;
- char * str;
- int has_missing_closing_quote;
-
- cur_token = * indx;
- has_missing_closing_quote = 0;
-
- gphrase = mmap_string_new("");
- if (gphrase == NULL) {
- res = MAILIMF_ERROR_MEMORY;
- goto err;
- }
-
- first = TRUE;
-
- while (1) {
- int missing_quote = 0;
- r = mailimf_fws_word_parse(message, length, &cur_token, &word, &missing_quote);
- if (missing_quote) {
- has_missing_closing_quote = 1;
- }
- 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;
- }
-
- if (has_missing_closing_quote) {
- r = mailimf_char_parse(message, length, &cur_token, '\"');
- }
-
- str = strdup(gphrase->str);
- if (str == NULL) {
- res = MAILIMF_ERROR_MEMORY;
- goto free;
- }
- mmap_string_free(gphrase);
-
- * result = str;
- * indx = 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 * indx, char ** result)
- {
- size_t cur_token;
- int state;
- size_t begin;
- size_t terminal;
- char * str;
-
- cur_token = * indx;
-
-
- 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';
-
- * indx = terminal;
- * result = str;
-
- return MAILIMF_NO_ERROR;
- }
-
-
- static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
- size_t * indx)
- {
- size_t cur_token;
- int state;
- size_t terminal;
-
- cur_token = * indx;
-
- 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 ++;
- }
-
- * indx = terminal;
-
- return MAILIMF_NO_ERROR;
- }
-
-
- LIBETPAN_EXPORT
- int mailimf_ignore_field_parse(const char * message, size_t length,
- size_t * indx)
- {
- int has_field;
- size_t cur_token;
- int state;
- size_t terminal;
-
- has_field =
|