/* * 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 #include #include #include "mailstream.h" #include "mailimap_keywords.h" #include "mailimap_parser.h" #include "mmapstring.h" #include "mail.h" #ifndef UNSTRICT_SYNTAX #define UNSTRICT_SYNTAX #endif /* Document: internet-drafts/draft-crispin-imapv-15.txt RFC 2060 (IMAP but rather used draft) RFC 2234 for all token that are not defined such as ALPHA */ /* ************************************************************************* */ /* ************************************************************************* */ /* ************************************************************************* */ /* ************************************************************************* */ /* ************************************************************************* */ /* ************************************************************************* */ static int mailimap_address_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_address ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_addr_adl_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_addr_host_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_addr_mailbox_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_addr_name_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_astring_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_atom_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_auth_type_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_base64_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_body_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_body_extension_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_extension ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_body_ext_1part_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_ext_1part ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_body_ext_mpart_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_ext_mpart ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_body_fields_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_fields ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_body_fld_desc_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_body_fld_dsp_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_fld_dsp ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_body_fld_enc_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_fld_enc ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_body_fld_id_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_body_fld_lang_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_fld_lang ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_body_fld_lines_parse(mailstream * fd, MMAPString * buffer, size_t * index, uint32_t * result); static int mailimap_body_fld_md5_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_body_fld_octets_parse(mailstream * fd, MMAPString * buffer, size_t * index, uint32_t * result); static int mailimap_body_fld_param_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_fld_param ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_body_type_1part_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_type_1part ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_body_type_basic_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_type_basic ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_body_type_mpart_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_type_mpart ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_body_type_msg_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_type_msg ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_body_type_text_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_type_text ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_capability_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_capability ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_capability_data_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_capability_data ** result, size_t progr_rate, progress_function * progr_fun); /* static gboolean mailimap_date_day_parse(mailstream * fd, MMAPString * buffer, guint32 * index, gint * result); */ static int mailimap_date_day_fixed_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result); static int mailimap_date_month_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result); /* struct mailimap_date_text { gint day; gint month; gint year; }; static gboolean mailimap_date_text_parse(mailstream * fd, MMAPString * buffer, guint32 * index, struct mailimap_date_text ** result); static void mailimap_date_text_free(struct mailimap_date_text * date_text); */ static int mailimap_date_year_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result); static int mailimap_date_time_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_date_time ** t, size_t progr_rate, progress_function * progr_fun); #ifndef UNSTRICT_SYNTAX static int mailimap_digit_nz_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result); #endif static int mailimap_envelope_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_envelope ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_env_bcc_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_env_bcc ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_env_cc_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_env_cc ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_env_date_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_env_from_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_env_from ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_env_in_reply_to_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_env_message_id_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_env_reply_to_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_env_reply_to ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_env_sender_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_env_sender ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_env_subject_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_env_to_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_env_to ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_flag_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_flag ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_flag_extension_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_flag_fetch_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_flag_fetch ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_flag_perm_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_flag_perm ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_flag_keyword_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_flag_list_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_flag_list ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_header_fld_name_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_header_list_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_header_list ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_literal_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t * result_len, size_t progr_rate, progress_function * progr_fun); static int mailimap_mailbox_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_mailbox_data_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_mailbox_data ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_mbx_list_flags_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_mbx_list_flags ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_mbx_list_oflag_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_mbx_list_oflag ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_mbx_list_oflag_no_sflag_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_mbx_list_oflag ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_mbx_list_sflag_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result); static int mailimap_mailbox_list_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_mailbox_list ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_media_basic_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_media_basic ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_media_message_parse(mailstream * fd, MMAPString * buffer, size_t * index); static int mailimap_media_subtype_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_media_text_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_message_data_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_message_data ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_msg_att_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_msg_att ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_msg_att_dynamic_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_msg_att_dynamic ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_msg_att_static_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_msg_att_static ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_nil_parse(mailstream * fd, MMAPString * buffer, size_t * index); static int mailimap_nstring_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t * result_len, size_t progr_rate, progress_function * progr_fun); static int mailimap_number_parse(mailstream * fd, MMAPString * buffer, size_t * index, uint32_t * result); static int mailimap_nz_number_parse(mailstream * fd, MMAPString * buffer, size_t * index, uint32_t * result); static int mailimap_quoted_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_quoted_char_parse(mailstream * fd, MMAPString * buffer, size_t * index, char * result); static int mailimap_quoted_specials_parse(mailstream * fd, MMAPString * buffer, size_t * index, char * result); static int mailimap_response_data_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_response_data ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_response_done_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_response_done ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_response_fatal_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_response_fatal ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_response_tagged_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_response_tagged ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_resp_cond_auth_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_resp_cond_auth ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_resp_cond_bye_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_resp_cond_bye ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_resp_cond_state_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_resp_cond_state ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_resp_text_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_resp_text ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_resp_text_code_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_resp_text_code ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_section_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_section ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_section_msgtext_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_section_msgtext ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_section_part_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_section_part ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_section_spec_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_section_spec ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_section_text_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_section_text ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_status_att_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result); static int mailimap_string_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t * result_len, size_t progr_rate, progress_function * progr_fun); static int mailimap_tag_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_text_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun); static int mailimap_time_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * phour, int * pmin, int * psec); static int mailimap_uniqueid_parse(mailstream * fd, MMAPString * buffer, size_t * index, uint32_t * result); static int mailimap_zone_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result); /* ************************************************************************* */ /* ************************************************************************* */ /* ************************************************************************* */ /* ************************************************************************* */ /* ************************************************************************* */ /* ************************************************************************* */ /* ******************** TOOLS **************************** */ static int mailimap_unstrict_char_parse(mailstream * fd, MMAPString * buffer, size_t * index, char token) { size_t cur_token; int r; cur_token = * index; #ifdef UNSTRICT_SYNTAX /* can accept unstrict syntax */ mailimap_space_parse(fd, buffer, &cur_token); if (token == ' ') { * index = cur_token; return MAILIMAP_NO_ERROR; } #endif r = mailimap_char_parse(fd, buffer, &cur_token, token); if (r != MAILIMAP_NO_ERROR) return r; * index = cur_token; return MAILIMAP_NO_ERROR; } static int mailimap_oparenth_parse(mailstream * fd, MMAPString * buffer, size_t * index) { return mailimap_unstrict_char_parse(fd, buffer, index, '('); } static int mailimap_cparenth_parse(mailstream * fd, MMAPString * buffer, size_t * index) { return mailimap_unstrict_char_parse(fd, buffer, index, ')'); } static int mailimap_oaccolade_parse(mailstream * fd, MMAPString * buffer, size_t * index) { return mailimap_unstrict_char_parse(fd, buffer, index, '{'); } static int mailimap_caccolade_parse(mailstream * fd, MMAPString * buffer, size_t * index) { return mailimap_unstrict_char_parse(fd, buffer, index, '}'); } static int mailimap_plus_parse(mailstream * fd, MMAPString * buffer, size_t * index) { return mailimap_unstrict_char_parse(fd, buffer, index, '+'); } static int mailimap_minus_parse(mailstream * fd, MMAPString * buffer, size_t * index) { return mailimap_unstrict_char_parse(fd, buffer, index, '-'); } static int mailimap_star_parse(mailstream * fd, MMAPString * buffer, size_t * index) { return mailimap_unstrict_char_parse(fd, buffer, index, '*'); } static int mailimap_dot_parse(mailstream * fd, MMAPString * buffer, size_t * index) { return mailimap_unstrict_char_parse(fd, buffer, index, '.'); } static int mailimap_colon_parse(mailstream * fd, MMAPString * buffer, size_t * index) { return mailimap_unstrict_char_parse(fd, buffer, index, ':'); } static int mailimap_lower_parse(mailstream * fd, MMAPString * buffer, size_t * index) { return mailimap_unstrict_char_parse(fd, buffer, index, '<'); } static int mailimap_greater_parse(mailstream * fd, MMAPString * buffer, size_t * index) { return mailimap_unstrict_char_parse(fd, buffer, index, '>'); } static int mailimap_obracket_parse(mailstream * fd, MMAPString * buffer, size_t * index) { return mailimap_unstrict_char_parse(fd, buffer, index, '['); } static int mailimap_cbracket_parse(mailstream * fd, MMAPString * buffer, size_t * index) { return mailimap_unstrict_char_parse(fd, buffer, index, ']'); } static int mailimap_dquote_parse(mailstream * fd, MMAPString * buffer, size_t * index) { return mailimap_char_parse(fd, buffer, index, '\"'); } static int mailimap_crlf_parse(mailstream * fd, MMAPString * buffer, size_t * index) { size_t cur_token = * index; #ifdef UNSTRICT_SYNTAX mailimap_space_parse(fd, buffer, &cur_token); #endif if (mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "\r\n")) { * index = cur_token; return MAILIMAP_NO_ERROR; } #ifdef UNSTRICT_SYNTAX else if (mailimap_unstrict_char_parse(fd, buffer, &cur_token, '\n')) { * index = cur_token; return MAILIMAP_NO_ERROR; } #endif else return MAILIMAP_ERROR_PARSE; } typedef int mailimap_struct_parser(mailstream * fd, MMAPString * buffer, size_t * index, void * result, size_t progr_rate, progress_function * progr_fun); typedef int mailimap_struct_destructor(void * result); static int mailimap_struct_multiple_parse(mailstream * fd, MMAPString * buffer, size_t * index, clist ** result, mailimap_struct_parser * parser, mailimap_struct_destructor * destructor, size_t progr_rate, progress_function * progr_fun) { clist * struct_list; size_t cur_token; void * value; int r; int res; cur_token = * index; r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } struct_list = clist_new(); if (struct_list == NULL) { destructor(value); res = MAILIMAP_ERROR_MEMORY; goto err; } r = clist_append(struct_list, value); if (r < 0) { destructor(value); res = MAILIMAP_ERROR_MEMORY; goto free_list; } while (1) { r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun); if (r == MAILIMAP_ERROR_PARSE) break; if (r != MAILIMAP_NO_ERROR) { res = r; goto free_list; } r = clist_append(struct_list, value); if (r < 0) { destructor(value); res = MAILIMAP_ERROR_MEMORY; goto free_list; } } * result = struct_list; * index = cur_token; return MAILIMAP_NO_ERROR; free_list: clist_foreach(struct_list, (clist_func) destructor, NULL); clist_free(struct_list); err: return res; } static int mailimap_struct_list_parse(mailstream * fd, MMAPString * buffer, size_t * index, clist ** result, char symbol, mailimap_struct_parser * parser, mailimap_struct_destructor * destructor, size_t progr_rate, progress_function * progr_fun) { clist * struct_list; size_t cur_token; void * value; size_t final_token; int r; int res; cur_token = * index; struct_list = NULL; r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } struct_list = clist_new(); if (struct_list == NULL) { destructor(value); res = MAILIMAP_ERROR_MEMORY; goto err; } r = clist_append(struct_list, value); if (r < 0) { destructor(value); res = MAILIMAP_ERROR_MEMORY; goto free_list; } final_token = cur_token; while (1) { r = mailimap_unstrict_char_parse(fd, buffer, &cur_token, symbol); if (r == MAILIMAP_ERROR_PARSE) break; if (r != MAILIMAP_NO_ERROR) { res = r; goto free_list; } r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun); if (r == MAILIMAP_ERROR_PARSE) break; if (r != MAILIMAP_NO_ERROR) { res = r; goto free_list; } r = clist_append(struct_list, value); if (r < 0) { destructor(value); res = MAILIMAP_ERROR_MEMORY; goto free_list; } final_token = cur_token; } * result = struct_list; * index = final_token; return MAILIMAP_NO_ERROR; free_list: clist_foreach(struct_list, (clist_func) destructor, NULL); clist_free(struct_list); err: return res; } static int mailimap_struct_spaced_list_parse(mailstream * fd, MMAPString * buffer, size_t * index, clist ** result, mailimap_struct_parser * parser, mailimap_struct_destructor * destructor, size_t progr_rate, progress_function * progr_fun) { return mailimap_struct_list_parse(fd, buffer, index, result, ' ', parser, destructor, progr_rate, progr_fun); } static int mailimap_custom_string_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, int (* is_custom_char)(char)) { size_t begin; size_t end; char * gstr; begin = * index; #ifdef UNSTRICT_SYNTAX mailimap_space_parse(fd, buffer, &begin); #endif end = begin; while (is_custom_char(buffer->str[end])) end ++; if (end != begin) { gstr = malloc(end - begin + 1); if (gstr == NULL) return MAILIMAP_ERROR_MEMORY; strncpy(gstr, buffer->str + begin, end - begin); gstr[end - begin] = '\0'; * index = end; * result = gstr; return MAILIMAP_NO_ERROR; } else return MAILIMAP_ERROR_PARSE; } static int mailimap_nz_number_alloc_parse(mailstream * fd, MMAPString * buffer, size_t * index, uint32_t ** result, size_t progr_rate, progress_function * progr_fun) { uint32_t number; uint32_t * number_alloc; size_t cur_token; int r; cur_token = * index; r = mailimap_nz_number_parse(fd, buffer, &cur_token, &number); if (r != MAILIMAP_NO_ERROR) return r; number_alloc = mailimap_number_alloc_new(number); if (number_alloc == NULL) return MAILIMAP_ERROR_MEMORY; * index = cur_token; * result = number_alloc; return MAILIMAP_NO_ERROR; } static int is_ctl(char ch) { unsigned char uch = (unsigned char) ch; return (uch <= 0x1F); } static int is_char(char ch) { #ifdef UNSTRICT_SYNTAX return (ch != 0); #else unsigned char uch = ch; return (uch >= 0x01) && (uch <= 0x7f); #endif } static int is_alpha(char ch) { return ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && (ch <= 'z'))); } static int is_digit(char ch) { return (ch >= '0') && (ch <= '9'); } static int mailimap_digit_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result) { size_t cur_token; cur_token = * index; if (is_digit(buffer->str[cur_token])) { * result = buffer->str[cur_token] - '0'; cur_token ++; * index = cur_token; return MAILIMAP_NO_ERROR; } else return MAILIMAP_ERROR_PARSE; } /* ******************** parser **************************** */ /* address = "(" addr-name SP addr-adl SP addr-mailbox SP addr-host ")" */ static int mailimap_address_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_address ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; char * addr_name; char * addr_adl; char * addr_mailbox; char * addr_host; struct mailimap_address * addr; int r; int res; cur_token = * index; addr_name = NULL; addr_adl = NULL; addr_mailbox = NULL; addr_host = NULL; r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_addr_name_parse(fd, buffer, &cur_token, &addr_name, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto addr_name_free; } r = mailimap_addr_adl_parse(fd, buffer, &cur_token, &addr_adl, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto addr_name_free; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto addr_adl_free; } r = mailimap_addr_mailbox_parse(fd, buffer, &cur_token, &addr_mailbox, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto addr_adl_free; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto addr_mailbox_free; } r = mailimap_addr_host_parse(fd, buffer, &cur_token, &addr_host, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto addr_mailbox_free; } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto addr_host_free; } addr = mailimap_address_new(addr_name, addr_adl, addr_mailbox, addr_host); if (addr == NULL) { res = MAILIMAP_ERROR_MEMORY; goto addr_host_free; } * result = addr; * index = cur_token; return MAILIMAP_NO_ERROR; addr_host_free: mailimap_addr_host_free(addr_host); addr_mailbox_free: mailimap_addr_mailbox_free(addr_mailbox); addr_adl_free: mailimap_addr_adl_free(addr_adl); addr_name_free: mailimap_addr_name_free(addr_name); err: return res; } /* addr-adl = nstring ; Holds route from [RFC-822] route-addr if ; non-NIL */ static int mailimap_addr_adl_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_nstring_parse(fd, buffer, index, result, NULL, progr_rate, progr_fun); } /* addr-host = nstring ; NIL indicates [RFC-822] group syntax. ; Otherwise, holds [RFC-822] domain name */ static int mailimap_addr_host_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_nstring_parse(fd, buffer, index, result, NULL, progr_rate, progr_fun); } /* addr-mailbox = nstring ; NIL indicates end of [RFC-822] group; if ; non-NIL and addr-host is NIL, holds ; [RFC-822] group name. ; Otherwise, holds [RFC-822] local-part ; after removing [RFC-822] quoting */ static int mailimap_addr_mailbox_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_nstring_parse(fd, buffer, index, result, NULL, progr_rate, progr_fun); } /* addr-name = nstring ; If non-NIL, holds phrase from [RFC-822] ; mailbox after removing [RFC-822] quoting */ static int mailimap_addr_name_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_nstring_parse(fd, buffer, index, result, NULL, progr_rate, progr_fun); } /* NOT IMPLEMENTED append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP literal */ /* astring = 1*ASTRING-CHAR / string */ static int is_astring_char(char ch); static int mailimap_atom_astring_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_custom_string_parse(fd, buffer, index, result, is_astring_char); } static int mailimap_astring_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; char * astring; int r; cur_token = * index; r = mailimap_atom_astring_parse(fd, buffer, &cur_token, &astring, progr_rate, progr_fun); switch (r) { case MAILIMAP_NO_ERROR: break; case MAILIMAP_ERROR_PARSE: r = mailimap_string_parse(fd, buffer, &cur_token, &astring, NULL, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; break; default: return r; } * result = astring; * index = cur_token; return MAILIMAP_NO_ERROR; } /* ASTRING-CHAR = ATOM-CHAR / resp-specials */ static int is_atom_char(char ch); static int is_resp_specials(char ch); static int is_astring_char(char ch) { if (is_atom_char(ch)) return TRUE; if (is_resp_specials(ch)) return TRUE; return FALSE; } /* atom = 1*ATOM-CHAR */ static int mailimap_atom_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_custom_string_parse(fd, buffer, index, result, is_atom_char); } /* ATOM-CHAR = */ static int is_atom_specials(char ch); static int is_atom_char(char ch) { if (is_atom_specials(ch)) return FALSE; return is_char(ch); } /* atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards / quoted-specials / resp-specials no "}" because there is no need (Mark Crispin) */ static int is_quoted_specials(char ch); static int is_list_wildcards(char ch); static int is_atom_specials(char ch) { switch (ch) { case '(': case ')': case '{': case ' ': return TRUE; }; if (is_ctl(ch)) return TRUE; if (is_list_wildcards(ch)) return TRUE; if (is_resp_specials(ch)) return TRUE; return is_quoted_specials(ch); } /* NOT IMPLEMENTED authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64) */ /* auth-type = atom ; Defined by [SASL] */ static int mailimap_auth_type_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_atom_parse(fd, buffer, index, result, progr_rate, progr_fun); } /* base64 = *(4base64-char) [base64-terminal] */ static int is_base64_4char(char * str); static int is_base64_terminal(char * str); static int mailimap_base64_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { size_t begin; size_t end; char * gstr; begin = * index; end = begin; while (is_base64_4char(buffer->str + end)) end += 4; if (is_base64_terminal(buffer->str + end)) end += 4; else return MAILIMAP_ERROR_PARSE; gstr = malloc(end - begin + 1); if (gstr == NULL) return MAILIMAP_ERROR_MEMORY; strncpy(gstr, buffer->str + begin, end - begin); gstr[end - begin] = '\0'; * result = gstr; * index = end; return MAILIMAP_NO_ERROR; } /* base64-char = ALPHA / DIGIT / "+" / "/" ; Case-sensitive */ static int is_base64_char(char ch) { return (is_alpha(ch) || is_digit(ch) || ch == '+' || ch == '/'); } static int is_base64_4char(char * str) { size_t i; for (i = 0 ; i < 4 ; i++) if (!is_base64_char(str[i])) return FALSE; return TRUE; } /* base64-terminal = (2base64-char "==") / (3base64-char "=") */ static int is_base64_terminal(char * str) { if (str[0] == 0) return FALSE; if (str[1] == 0) return FALSE; if (str[2] == 0) return FALSE; if (str[3] == 0) return FALSE; if (is_base64_char(str[0]) || is_base64_char(str[1]) || str[2] == '=' || str[3] == '=') return TRUE; if (is_base64_char(str[0]) || is_base64_char(str[1]) || is_base64_char(str[2]) || str[3] == '=') return TRUE; return FALSE; } /* body = "(" (body-type-1part / body-type-mpart) ")" */ static int mailimap_body_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_body_type_1part * body_type_1part; struct mailimap_body_type_mpart * body_type_mpart; struct mailimap_body * body; size_t cur_token; int type; int r; int res; cur_token = * index; body_type_1part = NULL; body_type_mpart = NULL; r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } type = MAILIMAP_BODY_ERROR; /* XXX - removes a gcc warning */ r = mailimap_body_type_1part_parse(fd, buffer, &cur_token, &body_type_1part, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_BODY_1PART; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_body_type_mpart_parse(fd, buffer, &cur_token, &body_type_mpart, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_BODY_MPART; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free; } body = mailimap_body_new(type, body_type_1part, body_type_mpart); if (body == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = body; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (body_type_1part) mailimap_body_type_1part_free(body_type_1part); if (body_type_mpart) mailimap_body_type_mpart_free(body_type_mpart); err: return res; } /* body-extension = nstring / number / "(" body-extension *(SP body-extension) ")" ; Future expansion. Client implementations ; MUST accept body-extension fields. Server ; implementations MUST NOT generate ; body-extension fields except as defined by ; future standard or standards-track ; revisions of this specification. */ /* "(" body-extension *(SP body-extension) ")" */ static int mailimap_body_ext_list_parse(mailstream * fd, MMAPString * buffer, size_t * index, clist ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; clist * list; int r; int res; cur_token = * index; r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list, (mailimap_struct_parser * ) mailimap_body_extension_parse, (mailimap_struct_destructor * ) mailimap_body_extension_free, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_list; } * index = cur_token; * result = list; return MAILIMAP_NO_ERROR; free_list: clist_foreach(list, (clist_func) mailimap_body_extension_free, NULL); clist_free(list); err: return res; } /* body-extension = nstring / number / "(" body-extension *(SP body-extension) ")" ; Future expansion. Client implementations ; MUST accept body-extension fields. Server ; implementations MUST NOT generate ; body-extension fields except as defined by ; future standard or standards-track ; revisions of this specification. */ static int mailimap_body_extension_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_extension ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; uint32_t number; char * nstring; clist * body_extension_list; struct mailimap_body_extension * body_extension; int type; int r; int res; cur_token = * index; nstring = NULL; number = 0; body_extension_list = NULL; type = MAILIMAP_BODY_EXTENSION_ERROR; /* XXX - removes a gcc warning */ r = mailimap_nstring_parse(fd, buffer, &cur_token, &nstring, NULL, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_BODY_EXTENSION_NSTRING; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_number_parse(fd, buffer, &cur_token, &number); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_BODY_EXTENSION_NUMBER; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_body_ext_list_parse(fd, buffer, &cur_token, &body_extension_list, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_BODY_EXTENSION_LIST; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } body_extension = mailimap_body_extension_new(type, nstring, number, body_extension_list); if (body_extension == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = body_extension; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (nstring != NULL) mailimap_nstring_free(nstring); if (body_extension_list) { clist_foreach(body_extension_list, (clist_func) mailimap_body_extension_free, NULL); clist_free(body_extension_list); } err: return res; } /* body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang *(SP body-extension)]] ; MUST NOT be returned on non-extensible ; "BODY" fetch */ /* *(SP body-extension) */ static int mailimap_body_ext_1part_3_parse(mailstream * fd, MMAPString * buffer, size_t * index, clist ** body_ext_list, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; int r; cur_token = * index; * body_ext_list = NULL; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, body_ext_list, (mailimap_struct_parser *) mailimap_body_extension_parse, (mailimap_struct_destructor *) mailimap_body_extension_free, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; * index = cur_token; return MAILIMAP_NO_ERROR; } /* [SP body-fld-lang *(SP body-extension)]] */ static int mailimap_body_ext_1part_2_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_fld_lang ** fld_lang, clist ** body_ext_list, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; int r; cur_token = * index; * fld_lang = NULL; * body_ext_list = NULL; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_body_fld_lang_parse(fd, buffer, &cur_token, fld_lang, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_body_ext_1part_3_parse(fd, buffer, &cur_token, body_ext_list, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) return r; * index = cur_token; return MAILIMAP_NO_ERROR; } /* SP body-fld-dsp [SP body-fld-lang *(SP body-extension)]] */ static int mailimap_body_ext_1part_1_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_fld_dsp ** fld_dsp, struct mailimap_body_fld_lang ** fld_lang, clist ** body_ext_list, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; int r; cur_token = * index; * fld_dsp = NULL; * fld_lang = NULL; * body_ext_list = NULL; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_body_fld_dsp_parse(fd, buffer, &cur_token, fld_dsp, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_body_ext_1part_2_parse(fd, buffer, &cur_token, fld_lang, body_ext_list, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) return r; * index = cur_token; return MAILIMAP_NO_ERROR; } /* body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang *(SP body-extension)]] ; MUST NOT be returned on non-extensible ; "BODY" fetch */ static int mailimap_body_ext_1part_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_ext_1part ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; char * fld_md5; struct mailimap_body_fld_dsp * fld_dsp; struct mailimap_body_fld_lang * fld_lang; clist * body_ext_list; int r; int res; struct mailimap_body_ext_1part * ext_1part; cur_token = * index; fld_md5 = NULL; fld_dsp = NULL; fld_lang = NULL; body_ext_list = NULL; r = mailimap_body_fld_md5_parse(fd, buffer, &cur_token, &fld_md5, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_body_ext_1part_1_parse(fd, buffer, &cur_token, &fld_dsp, &fld_lang, &body_ext_list, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { res = r; goto free; } ext_1part = mailimap_body_ext_1part_new(fld_md5, fld_dsp, fld_lang, body_ext_list); if (ext_1part == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = ext_1part; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (body_ext_list) { clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free, NULL); clist_free(body_ext_list); } if (fld_lang) mailimap_body_fld_lang_free(fld_lang); if (fld_dsp) mailimap_body_fld_dsp_free(fld_dsp); mailimap_body_fld_md5_free(fld_md5); err: return res; } /* body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang *(SP body-extension)]] ; MUST NOT be returned on non-extensible ; "BODY" fetch */ static int mailimap_body_ext_mpart_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_ext_mpart ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_body_fld_dsp * fld_dsp; struct mailimap_body_fld_lang * fld_lang; struct mailimap_body_fld_param * fld_param; clist * body_ext_list; struct mailimap_body_ext_mpart * ext_mpart; int r; int res; cur_token = * index; fld_param = NULL; fld_dsp = NULL; fld_lang = NULL; body_ext_list = NULL; r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, &fld_param, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_body_ext_1part_1_parse(fd, buffer, &cur_token, &fld_dsp, &fld_lang, &body_ext_list, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { res = r; goto free; } ext_mpart = mailimap_body_ext_mpart_new(fld_param, fld_dsp, fld_lang, body_ext_list); if (ext_mpart == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = ext_mpart; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (body_ext_list) { clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free, NULL); clist_free(body_ext_list); } if (fld_lang) mailimap_body_fld_lang_free(fld_lang); if (fld_dsp) mailimap_body_fld_dsp_free(fld_dsp); if (fld_param != NULL) mailimap_body_fld_param_free(fld_param); err: return res; } /* body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP body-fld-enc SP body-fld-octets */ static int mailimap_body_fields_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_fields ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_body_fields * body_fields; size_t cur_token; struct mailimap_body_fld_param * body_fld_param; char * body_fld_id; char * body_fld_desc; struct mailimap_body_fld_enc * body_fld_enc; size_t body_fld_octets; int r; int res; body_fld_param = NULL; body_fld_id = NULL; body_fld_desc = NULL; body_fld_enc = NULL; body_fld_octets = 0; cur_token = * index; r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, &body_fld_param, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto fld_param_free; } r = mailimap_body_fld_id_parse(fd, buffer, &cur_token, &body_fld_id, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto fld_param_free; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto fld_id_free; } r = mailimap_body_fld_desc_parse(fd, buffer, &cur_token, &body_fld_desc, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto fld_id_free; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto fld_desc_free; } r = mailimap_body_fld_enc_parse(fd, buffer, &cur_token, &body_fld_enc, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto fld_desc_free; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto fld_enc_free; } r = mailimap_body_fld_octets_parse(fd, buffer, &cur_token, &body_fld_octets); if (r != MAILIMAP_NO_ERROR) { res = r; goto fld_enc_free; } body_fields = mailimap_body_fields_new(body_fld_param, body_fld_id, body_fld_desc, body_fld_enc, body_fld_octets); if (body_fields == NULL) { res = MAILIMAP_ERROR_MEMORY; goto fld_enc_free; } * result = body_fields; * index = cur_token; return MAILIMAP_NO_ERROR; fld_enc_free: mailimap_body_fld_enc_free(body_fld_enc); fld_desc_free: mailimap_body_fld_desc_free(body_fld_desc); fld_id_free: mailimap_body_fld_id_free(body_fld_id); fld_param_free: if (body_fld_param != NULL) mailimap_body_fld_param_free(body_fld_param); err: return res; } /* body-fld-desc = nstring */ static int mailimap_body_fld_desc_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_nstring_parse(fd, buffer, index, result, NULL, progr_rate, progr_fun); } /* body-fld-dsp = "(" string SP body-fld-param ")" / nil */ static int mailimap_body_fld_dsp_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_fld_dsp ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; char * name; struct mailimap_body_fld_param * body_fld_param; struct mailimap_body_fld_dsp * body_fld_dsp; int res; int r; cur_token = * index; name = NULL; body_fld_param = NULL; r = mailimap_nil_parse(fd, buffer, &cur_token); if (r == MAILIMAP_NO_ERROR) { * result = NULL; * index = cur_token; return MAILIMAP_NO_ERROR; } if (r != MAILIMAP_ERROR_PARSE) { res = r; goto err; } r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_string_parse(fd, buffer, &cur_token, &name, NULL, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto string_free; } r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, &body_fld_param, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto string_free; } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto string_free; } body_fld_dsp = mailimap_body_fld_dsp_new(name, body_fld_param); if (body_fld_dsp == NULL) { res = MAILIMAP_ERROR_MEMORY; goto fld_param_free; } * index = cur_token; * result = body_fld_dsp; return MAILIMAP_NO_ERROR; fld_param_free: if (body_fld_param != NULL) mailimap_body_fld_param_free(body_fld_param); string_free: mailimap_string_free(name); err: return res; } /* body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ "QUOTED-PRINTABLE") DQUOTE) / string */ static inline int mailimap_body_fld_known_enc_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; int type; int r; int res; cur_token = * index; r = mailimap_dquote_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } type = mailimap_encoding_get_token_value(fd, buffer, &cur_token); if (type == -1) { res = MAILIMAP_ERROR_PARSE; goto err; } r = mailimap_dquote_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } * result = type; * index = cur_token; return MAILIMAP_NO_ERROR; err: return res; } static int mailimap_body_fld_enc_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_fld_enc ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; int type; char * value; struct mailimap_body_fld_enc * body_fld_enc; int r; int res; cur_token = * index; r = mailimap_body_fld_known_enc_parse(fd, buffer, &cur_token, &type, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) { value = NULL; } else if (r == MAILIMAP_ERROR_PARSE) { type = MAILIMAP_BODY_FLD_ENC_OTHER; r = mailimap_string_parse(fd, buffer, &cur_token, &value, NULL, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { // LR start // accept NIL and set type to utf8 int ret = r; r = mailimap_char_parse(fd, buffer, &cur_token, 'N'); if (r == MAILIMAP_NO_ERROR) { r = mailimap_char_parse(fd, buffer, &cur_token, 'I'); if (r == MAILIMAP_NO_ERROR) { r = mailimap_char_parse(fd, buffer, &cur_token, 'L'); if (r == MAILIMAP_NO_ERROR) { type = 4; ret = MAILIMAP_NO_ERROR; value = NULL; } } } if ( ret != MAILIMAP_NO_ERROR ) { res = ret; goto err; } // LR end } } else { res = r; goto err; } body_fld_enc = mailimap_body_fld_enc_new(type, value); if (body_fld_enc == NULL) { res = MAILIMAP_ERROR_MEMORY; goto value_free; } * result = body_fld_enc; * index = cur_token; return MAILIMAP_NO_ERROR; value_free: if (value) mailimap_string_free(value); err: return res; } /* body-fld-id = nstring */ static int mailimap_body_fld_id_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_nstring_parse(fd, buffer, index, result, NULL, progr_rate, progr_fun); } /* body-fld-lang = nstring / "(" string *(SP string) ")" */ /* "(" string *(SP string) ")" */ static int mailimap_body_fld_lang_list_parse(mailstream * fd, MMAPString * buffer, size_t * index, clist ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; clist * list; int r; int res; cur_token = * index; r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } list = clist_new(); if (list == NULL) { res = MAILIMAP_ERROR_MEMORY; goto err; } while (1) { char * elt; r = mailimap_string_parse(fd, buffer, &cur_token, &elt, NULL, progr_rate, progr_fun); if (r != MAILIMAP_ERROR_PARSE) break; else if (r == MAILIMAP_NO_ERROR) { r = clist_append(list, elt); if (r < 0) { mailimap_string_free(elt); res = r; goto list_free; } } else { res = r; goto list_free; } } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto list_free; } * index = cur_token; * result = list; return MAILIMAP_NO_ERROR; list_free: clist_foreach(list, (clist_func) mailimap_string_free, NULL); clist_free(list); err: return res; } /* body-fld-lang = nstring / "(" string *(SP string) ")" */ static int mailimap_body_fld_lang_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_fld_lang ** result, size_t progr_rate, progress_function * progr_fun) { char * value; clist * list; struct mailimap_body_fld_lang * fld_lang; int type; int r; int res; size_t cur_token; cur_token = * index; value = NULL; list = NULL; type = MAILIMAP_BODY_FLD_LANG_ERROR; /* XXX - removes a gcc warning */ r = mailimap_nstring_parse(fd, buffer, &cur_token, &value, NULL, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_BODY_FLD_LANG_SINGLE; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_body_fld_lang_list_parse(fd, buffer, &cur_token, &list, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_BODY_FLD_LANG_LIST; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } fld_lang = mailimap_body_fld_lang_new(type, value, list); if (fld_lang == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * index = cur_token; * result = fld_lang; return MAILIMAP_NO_ERROR; free: if (value) mailimap_nstring_free(value); if (list) { clist_foreach(list, (clist_func) mailimap_string_free, NULL); clist_free(list); } err: return res; } /* body-fld-lines = number */ static int mailimap_body_fld_lines_parse(mailstream * fd, MMAPString * buffer, size_t * index, uint32_t * result) { return mailimap_number_parse(fd, buffer, index, result); } /* body-fld-md5 = nstring */ static int mailimap_body_fld_md5_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_nstring_parse(fd, buffer, index, result, NULL, progr_rate, progr_fun); } /* body-fld-octets = number */ static int mailimap_body_fld_octets_parse(mailstream * fd, MMAPString * buffer, size_t * index, uint32_t * result) { return mailimap_number_parse(fd, buffer, index, result); } /* body-fld-param = "(" string SP string *(SP string SP string) ")" / nil */ /* string SP string */ static int mailimap_single_body_fld_param_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_single_body_fld_param ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_single_body_fld_param * param; char * name; char * value; size_t cur_token; int r; int res; cur_token = * index; name = NULL; value = NULL; r = mailimap_string_parse(fd, buffer, &cur_token, &name, NULL, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_name; } r = mailimap_string_parse(fd, buffer, &cur_token, &value, NULL, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_name; } param = mailimap_single_body_fld_param_new(name, value); if (param == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_value; } * result = param; * index = cur_token; return MAILIMAP_NO_ERROR; free_value: mailimap_string_free(name); free_name: mailimap_string_free(value); err: return res; } /* body-fld-param = "(" string SP string *(SP string SP string) ")" / nil */ static int mailimap_body_fld_param_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_fld_param ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; clist * param_list; struct mailimap_body_fld_param * fld_param; int r; int res; param_list = NULL; cur_token = * index; r = mailimap_nil_parse(fd, buffer, &cur_token); if (r == MAILIMAP_NO_ERROR) { * result = NULL; * index = cur_token; return MAILIMAP_NO_ERROR; } if (r != MAILIMAP_ERROR_PARSE) { res = r; goto err; } r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, ¶m_list, (mailimap_struct_parser *) mailimap_single_body_fld_param_parse, (mailimap_struct_destructor *) mailimap_single_body_fld_param_free, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free; } fld_param = mailimap_body_fld_param_new(param_list); if (fld_param == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * index = cur_token; * result = fld_param; return MAILIMAP_NO_ERROR; free: clist_foreach(param_list, (clist_func) mailimap_single_body_fld_param_free, NULL); clist_free(param_list); err: return res; } /* body-type-1part = (body-type-basic / body-type-msg / body-type-text) [SP body-ext-1part] */ static int mailimap_body_type_1part_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_type_1part ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_body_type_1part * body_type_1part; struct mailimap_body_type_basic * body_type_basic; struct mailimap_body_type_msg * body_type_msg; struct mailimap_body_type_text * body_type_text; struct mailimap_body_ext_1part * body_ext_1part; int type; size_t final_token; int r; int res; cur_token = * index; body_type_basic = NULL; body_type_msg = NULL; body_type_text = NULL; body_ext_1part = NULL; type = MAILIMAP_BODY_TYPE_1PART_ERROR; /* XXX - removes a gcc warning */ r = mailimap_body_type_msg_parse(fd, buffer, &cur_token, &body_type_msg, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_BODY_TYPE_1PART_MSG; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_body_type_text_parse(fd, buffer, &cur_token, &body_type_text, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_BODY_TYPE_1PART_TEXT; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_body_type_basic_parse(fd, buffer, &cur_token, &body_type_basic, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_BODY_TYPE_1PART_BASIC; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } final_token = cur_token; body_ext_1part = NULL; r = mailimap_space_parse(fd, buffer, &cur_token); if (r == MAILIMAP_NO_ERROR) { r = mailimap_body_ext_1part_parse(fd, buffer, &cur_token, &body_ext_1part, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) final_token = cur_token; else if (r == MAILIMAP_ERROR_PARSE) { /* do nothing */ } else { res = r; goto free; } } else if (r == MAILIMAP_ERROR_PARSE) { /* do nothing */ } else { res = r; goto free; } body_type_1part = mailimap_body_type_1part_new(type, body_type_basic, body_type_msg, body_type_text, body_ext_1part); if (body_type_1part == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * index = final_token; * result = body_type_1part; return MAILIMAP_NO_ERROR; free: if (body_type_basic) mailimap_body_type_basic_free(body_type_basic); if (body_type_msg) mailimap_body_type_msg_free(body_type_msg); if (body_type_text) mailimap_body_type_text_free(body_type_text); if (body_ext_1part) mailimap_body_ext_1part_free(body_ext_1part); err: return res; } /* body-type-basic = media-basic SP body-fields ; MESSAGE subtype MUST NOT be "RFC822" */ static int mailimap_body_type_basic_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_type_basic ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_body_type_basic * body_type_basic; struct mailimap_media_basic * media_basic; struct mailimap_body_fields * body_fields; int r; int res; cur_token = * index; media_basic = NULL; body_fields = NULL; r = mailimap_media_basic_parse(fd, buffer, &cur_token, &media_basic, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_media_basic; } r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_media_basic; } body_type_basic = mailimap_body_type_basic_new(media_basic, body_fields); if (body_type_basic == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_body_fields; } * index = cur_token; * result = body_type_basic; return MAILIMAP_NO_ERROR; free_body_fields: mailimap_body_fields_free(body_fields); free_media_basic: mailimap_media_basic_free(media_basic); err: return res; } /* body-type-mpart = 1*body SP media-subtype [SP body-ext-mpart] */ static int mailimap_body_type_mpart_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_type_mpart ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_body_type_mpart * body_type_mpart; clist * body_list; size_t cur_token; size_t final_token; char * media_subtype; struct mailimap_body_ext_mpart * body_ext_mpart; int r; int res; cur_token = * index; body_list = NULL; media_subtype = NULL; body_ext_mpart = NULL; r = mailimap_struct_multiple_parse(fd, buffer, &cur_token, &body_list, (mailimap_struct_parser *) mailimap_body_parse, (mailimap_struct_destructor *) mailimap_body_free, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_body_list; } r = mailimap_media_subtype_parse(fd, buffer, &cur_token, &media_subtype, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_body_list; } final_token = cur_token; body_ext_mpart = NULL; r = mailimap_space_parse(fd, buffer, &cur_token); if (r == MAILIMAP_NO_ERROR) { r = mailimap_body_ext_mpart_parse(fd, buffer, &cur_token, &body_ext_mpart, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) final_token = cur_token; else if (r == MAILIMAP_ERROR_PARSE) { /* do nothing */ } else { res = r; goto free_body_list; } } else if (r == MAILIMAP_ERROR_PARSE) { /* do nothing */ } else { res = r; goto free_body_list; } body_type_mpart = mailimap_body_type_mpart_new(body_list, media_subtype, body_ext_mpart); if (body_type_mpart == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_body_ext_mpart; } * result = body_type_mpart; * index = final_token; return MAILIMAP_NO_ERROR; free_body_ext_mpart: if (body_ext_mpart) mailimap_body_ext_mpart_free(body_ext_mpart); mailimap_media_subtype_free(media_subtype); free_body_list: clist_foreach(body_list, (clist_func) mailimap_body_free, NULL); clist_free(body_list); err: return res; } /* body-type-msg = media-message SP body-fields SP envelope SP body SP body-fld-lines */ static int mailimap_body_type_msg_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_type_msg ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_body_fields * body_fields; struct mailimap_envelope * envelope; struct mailimap_body * body; uint32_t body_fld_lines; struct mailimap_body_type_msg * body_type_msg; size_t cur_token; int r; int res; cur_token = * index; body_fields = NULL; envelope = NULL; body = NULL; body_fld_lines = 0; r = mailimap_media_message_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto body_fields; } r = mailimap_envelope_parse(fd, buffer, &cur_token, &envelope, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto body_fields; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto envelope; } r = mailimap_body_parse(fd, buffer, &cur_token, &body, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto envelope; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto body; } r = mailimap_body_fld_lines_parse(fd, buffer, &cur_token, &body_fld_lines); if (r != MAILIMAP_NO_ERROR) { res = r; goto body; } body_type_msg = mailimap_body_type_msg_new(body_fields, envelope, body, body_fld_lines); if (body_type_msg == NULL) { res = MAILIMAP_ERROR_MEMORY; goto body; } * result = body_type_msg; * index = cur_token; return MAILIMAP_NO_ERROR; body: mailimap_body_free(body); envelope: mailimap_envelope_free(envelope); body_fields: mailimap_body_fields_free(body_fields); err: return res; } /* body-type-text = media-text SP body-fields SP body-fld-lines */ static int mailimap_body_type_text_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_type_text ** result, size_t progr_rate, progress_function * progr_fun) { char * media_text; struct mailimap_body_fields * body_fields; uint32_t body_fld_lines; struct mailimap_body_type_text * body_type_text; size_t cur_token; int r; int res; media_text = NULL; body_fields = NULL; body_fld_lines = 0; cur_token = * index; r = mailimap_media_text_parse(fd, buffer, &cur_token, &media_text, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_media_text; } r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_media_text; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_body_fields; } r = mailimap_body_fld_lines_parse(fd, buffer, &cur_token, &body_fld_lines); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_body_fields; } body_type_text = mailimap_body_type_text_new(media_text, body_fields, body_fld_lines); if (body_type_text == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_body_fields; } * result = body_type_text; * index = cur_token; return MAILIMAP_NO_ERROR; free_body_fields: mailimap_body_fields_free(body_fields); free_media_text: mailimap_media_text_free(media_text); err: return res; } /* capability = ("AUTH=" auth-type) / atom ; New capabilities MUST begin with "X" or be ; registered with IANA as standard or ; standards-track */ static int mailimap_capability_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_capability ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; int type; char * auth_type; char * atom; struct mailimap_capability * cap; int r; int res; cur_token = * index; auth_type = NULL; atom = NULL; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "AUTH="); switch (r) { case MAILIMAP_NO_ERROR: type = MAILIMAP_CAPABILITY_AUTH_TYPE; r = mailimap_auth_type_parse(fd, buffer, &cur_token, &auth_type, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } break; case MAILIMAP_ERROR_PARSE: r = mailimap_atom_parse(fd, buffer, &cur_token, &atom, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } type = MAILIMAP_CAPABILITY_NAME; break; default: res = r; goto err; } cap = mailimap_capability_new(type, auth_type, atom); if (cap == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = cap; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (auth_type) mailimap_auth_type_free(auth_type); if (atom) mailimap_atom_free(atom); err: return res; } /* capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1" *(SP capability) ; IMAP4rev1 servers which offer RFC 1730 ; compatibility MUST list "IMAP4" as the first ; capability. */ /* SP capability *(SP capability) */ static int mailimap_capability_list_parse(mailstream * fd, MMAPString * buffer, size_t * index, clist ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; clist * list; int r; cur_token = * index; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list, (mailimap_struct_parser *) mailimap_capability_parse, (mailimap_struct_destructor *) mailimap_capability_free, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; * index = cur_token; * result = list; return MAILIMAP_NO_ERROR; } static int mailimap_capability_data_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_capability_data ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; clist * cap_list; #if 0 clist * cap_list_2; #endif struct mailimap_capability_data * cap_data; int r; int res; cur_token = * index; cap_list = NULL; #if 0 cap_list_2 = NULL; #endif r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "CAPABILITY"); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_capability_list_parse(fd, buffer, &cur_token, &cap_list, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { res = r; goto err; } #if 0 if (!mailimap_space_parse(fd, buffer, &cur_token)) { res = r; goto free_list; } if (!mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "IMAP4rev1")) goto free_list; r = mailimap_capability_list_parse(fd, buffer, &cur_token, &cap_list_2, progr_rate, progr_fun); cap_list = g_list_concat(cap_list, cap_list_2); #endif cap_data = mailimap_capability_data_new(cap_list); if (cap_data == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_list; } * result = cap_data; * index = cur_token; return MAILIMAP_NO_ERROR; free_list: if (cap_list) { clist_foreach(cap_list, (clist_func) mailimap_capability_free, NULL); clist_free(cap_list); } err: return res; } /* UNIMPLEMENTED BECAUSE UNUSED (only in literal) CHAR8 = %x01-ff ; any OCTET except NUL, %x00 */ /* static gboolean is_char8(gchar ch) { return (ch != 0x00); } */ /* UNIMPLEMENTED command = tag SP (command-any / command-auth / command-nonauth / command-select) CRLF ; Modal based on state */ /* UNIMPLEMENTED command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command ; Valid in all states */ /* UNIMPLEMENTED command-auth = append / create / delete / examine / list / lsub / rename / select / status / subscribe / unsubscribe ; Valid only in Authenticated or Selected state */ /* UNIMPLEMENTED command-nonauth = login / authenticate ; Valid only when in Not Authenticated state */ /* UNIMPLEMENTED command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store / uid / search ; Valid only when in Selected state */ /* continue-req = "+" SP (resp-text / base64) CRLF */ int mailimap_continue_req_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_continue_req ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_resp_text * resp_text; size_t cur_token; struct mailimap_continue_req * cont_req; char * base64; int type; int r; int res; cur_token = * index; r = mailimap_plus_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; resp_text = NULL; base64 = NULL; type = MAILIMAP_CONTINUE_REQ_ERROR; /* XXX - removes a gcc warning */ r = mailimap_base64_parse(fd, buffer, &cur_token, &base64, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_CONTINUE_REQ_BASE64; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_resp_text_parse(fd, buffer, &cur_token, &resp_text, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_CONTINUE_REQ_TEXT; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_crlf_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free; } cont_req = mailimap_continue_req_new(type, resp_text, base64); if (cont_req == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = cont_req; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (base64 != NULL) mailimap_base64_free(base64); if (resp_text != NULL) mailimap_resp_text_free(resp_text); err: return res; } /* UNIMPLEMENTED copy = "COPY" SP set SP mailbox */ /* UNIMPLEMENTED create = "CREATE" SP mailbox ; Use of INBOX gives a NO error */ /* UNIMPLEMENTED date = date-text / DQUOTE date-text DQUOTE */ /* UNIMPLEMENTED date-day = 1*2DIGIT ; Day of month */ /* static gboolean mailimap_date_day_parse(mailstream * fd, MMAPString * buffer, guint32 * index, gint * result) { guint32 cur_token; gint digit; gint number; cur_token = * index; if (!mailimap_digit_parse(fd, buffer, &cur_token, &digit)) return FALSE; number = digit; if (mailimap_digit_parse(fd, buffer, &cur_token, &digit)) number = number * 10 + digit; * result = number; * index = cur_token; return TRUE; } */ /* date-day-fixed = (SP DIGIT) / 2DIGIT ; Fixed-format version of date-day */ static int mailimap_date_day_fixed_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result) { #ifdef UNSTRICT_SYNTAX size_t cur_token; uint32_t day; int r; cur_token = * index; r = mailimap_number_parse(fd, buffer, &cur_token, &day); if (r != MAILIMAP_NO_ERROR) return r; * index = cur_token; * result = day; return MAILIMAP_NO_ERROR; #else size_t cur_token; int r; cur_token = * index; if (mailimap_space_parse(fd, buffer, &cur_token)) { int digit; r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); if (r != MAILIMAP_NO_ERROR) return r; * result = digit; * index = cur_token; return MAILIMAP_NO_ERROR; } else { int digit1; int digit2; r = mailimap_digit_parse(fd, buffer, &cur_token, &digit1); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_digit_parse(fd, buffer, &cur_token, &digit2); if (r != MAILIMAP_NO_ERROR) return r; * result = digit1 * 10 + digit2; * index = cur_token; return MAILIMAP_NO_ERROR; } #endif } /* date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" */ static int mailimap_date_month_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result) { size_t cur_token; int month; cur_token = * index; month = mailimap_month_get_token_value(fd, buffer, &cur_token); if (month == -1) return MAILIMAP_ERROR_PARSE; * result = month; * index = cur_token; return MAILIMAP_NO_ERROR; } /* UNIMPLEMENTED date-text = date-day "-" date-month "-" date-year */ /* static struct mailimap_date_text * mailimap_date_text_new(gint day, gint month, gint year) { struct mailimap_date_text * date_text; date_text = g_new(struct mailimap_date_text, 1); if (date_text == NULL) return NULL; date_text->day = day; date_text->month = month; date_text->year = year; return date_text; } static void mailimap_date_text_free(struct mailimap_date_text * date_text) { g_free(date_text); } static gboolean mailimap_date_text_parse(mailstream * fd, MMAPString * buffer, guint32 * index, struct mailimap_date_text ** result) { struct mailimap_date_text * date_text; gint day; gint month; gint year; guint32 cur_token; cur_token = * index; if (!mailimap_date_day_parse(fd, buffer, &cur_token, &day)) return FALSE; if (!mailimap_minus_parse(fd, buffer, &cur_token)) return FALSE; if (!mailimap_date_month_parse(fd, buffer, &cur_token, &month)) return FALSE; if (!mailimap_minus_parse(fd, buffer, &cur_token)) return FALSE; if (!mailimap_date_year_parse(fd, buffer, &cur_token, &year)) return FALSE; date_text = mailimap_date_text_new(day, month, year); if (date_text == NULL) return FALSE; * result = date_text; * index = cur_token; return TRUE; } */ /* date-year = 4DIGIT */ static int mailimap_date_year_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result) { #ifdef UNSTRICT_SYNTAX uint32_t year; int r; size_t cur_token; cur_token = * index; r = mailimap_number_parse(fd, buffer, &cur_token, &year); if (r != MAILIMAP_NO_ERROR) return r; * result = year; * index = cur_token; return MAILIMAP_NO_ERROR; #else int i; size_t cur_token; int year; int digit; int r; cur_token = * index; year = 0; for(i = 0 ; i < 4 ; i ++) { r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); if (r != MAILIMAP_NO_ERROR) return r; year = year * 10 + digit; } * result = year; * index = cur_token; return MAILIMAP_NO_ERROR; #endif } /* date-time = DQUOTE date-day-fixed "-" date-month "-" date-year SP time SP zone DQUOTE */ static int mailimap_date_time_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_date_time ** result, size_t progr_rate, progress_function * progr_fun) { int day; int month; int year; int hour; int min; int sec; struct mailimap_date_time * date_time; size_t cur_token; int zone; int r; cur_token = * index; r = mailimap_dquote_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_date_day_fixed_parse(fd, buffer, &cur_token, &day); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_minus_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_date_month_parse(fd, buffer, &cur_token, &month); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_minus_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_date_year_parse(fd, buffer, &cur_token, &year); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_time_parse(fd, buffer, &cur_token, &hour, &min, &sec); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_zone_parse(fd, buffer, &cur_token, &zone); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_dquote_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; date_time = mailimap_date_time_new(day, month, year, hour, min, sec, zone); if (date_time == NULL) return MAILIMAP_ERROR_MEMORY; * result = date_time; * index = cur_token; return MAILIMAP_NO_ERROR; } /* UNIMPLEMENTED delete = "DELETE" SP mailbox ; Use of INBOX gives a NO error */ /* digit-nz = %x31-39 ; 1-9 */ #ifndef UNSTRICT_SYNTAX static int is_digit_nz(char ch) { return (ch >= '1') && (ch <= '9'); } static int mailimap_digit_nz_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result) { size_t cur_token; cur_token = * index; if (is_digit_nz(buffer->str[cur_token])) { * result = buffer->str[cur_token] - '0'; cur_token ++; * index = cur_token; return MAILIMAP_NO_ERROR; } else return MAILIMAP_ERROR_PARSE; } #endif /* envelope = "(" env-date SP env-subject SP env-from SP env-sender SP env-reply-to SP env-to SP env-cc SP env-bcc SP env-in-reply-to SP env-message-id ")" */ static int mailimap_envelope_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_envelope ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; char * date; char * subject; struct mailimap_env_from * from; struct mailimap_env_sender * sender; struct mailimap_env_reply_to * reply_to; struct mailimap_env_to * to; struct mailimap_env_cc * cc; struct mailimap_env_bcc * bcc; char * in_reply_to; char * message_id; struct mailimap_envelope * envelope; int r; int res; date = NULL; subject = NULL; from = NULL; sender = NULL; reply_to = NULL; to = NULL; cc = NULL; bcc = NULL; in_reply_to = NULL; message_id = NULL; cur_token = * index; r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_env_date_parse(fd, buffer, &cur_token, &date, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto date; } r = mailimap_env_subject_parse(fd, buffer, &cur_token, &subject, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto date; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto subject; } r = mailimap_env_from_parse(fd, buffer, &cur_token, &from, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto subject; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto from; } r = mailimap_env_sender_parse(fd, buffer, &cur_token, &sender, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto from; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto sender; } r = mailimap_env_reply_to_parse(fd, buffer, &cur_token, &reply_to, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto sender; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto reply_to; } r = mailimap_env_to_parse(fd, buffer, &cur_token, &to, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto reply_to; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto to; } r = mailimap_env_cc_parse(fd, buffer, &cur_token, &cc, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto to; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto cc; } r = mailimap_env_bcc_parse(fd, buffer, &cur_token, &bcc, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto cc; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto bcc; } r = mailimap_env_in_reply_to_parse(fd, buffer, &cur_token, &in_reply_to, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto bcc; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto in_reply_to; } r = mailimap_env_message_id_parse(fd, buffer, &cur_token, &message_id, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto in_reply_to; } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto message_id; } envelope = mailimap_envelope_new(date, subject, from, sender, reply_to, to, cc, bcc, in_reply_to, message_id); if (envelope == NULL) { res = MAILIMAP_ERROR_MEMORY; goto message_id; } * result = envelope; * index = cur_token; return MAILIMAP_NO_ERROR; message_id: mailimap_env_message_id_free(message_id); in_reply_to: mailimap_env_in_reply_to_free(in_reply_to); bcc: mailimap_env_bcc_free(bcc); cc: mailimap_env_cc_free(cc); to: mailimap_env_to_free(to); reply_to: mailimap_env_reply_to_free(reply_to); sender: mailimap_env_sender_free(sender); from: mailimap_env_from_free(from); subject: mailimap_env_subject_free(date); date: mailimap_env_date_free(date); err: return res; } /* "(" 1*address ")" */ static int mailimap_address_list_parse(mailstream * fd, MMAPString * buffer, size_t * index, clist ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; clist * address_list; int r; int res; cur_token = * index; address_list = NULL; r = mailimap_nil_parse(fd, buffer, &cur_token); switch (r) { case MAILIMAP_NO_ERROR: address_list = NULL; break; case MAILIMAP_ERROR_PARSE: r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_struct_multiple_parse(fd, buffer, &cur_token, &address_list, (mailimap_struct_parser *) mailimap_address_parse, (mailimap_struct_destructor *) mailimap_address_free, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto address_list; } break; default: res = r; goto err; } * result = address_list; * index = cur_token; return MAILIMAP_NO_ERROR; address_list: if (address_list) { clist_foreach(address_list, (clist_func) mailimap_address_free, NULL); clist_free(address_list); } err: return res; } /* env-bcc = "(" 1*address ")" / nil */ static int mailimap_env_bcc_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_env_bcc ** result, size_t progr_rate, progress_function * progr_fun) { clist * list; size_t cur_token; struct mailimap_env_bcc * env_bcc; int r; int res; cur_token = * index; list = NULL; r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } env_bcc = mailimap_env_bcc_new(list); if (env_bcc == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * index = cur_token; * result = env_bcc; return MAILIMAP_NO_ERROR; free: clist_foreach(list, (clist_func) mailimap_address_free, NULL); clist_free(list); err: return res; } /* env-cc = "(" 1*address ")" / nil */ static int mailimap_env_cc_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_env_cc ** result, size_t progr_rate, progress_function * progr_fun) { clist * list; size_t cur_token; struct mailimap_env_cc * env_cc; int r; int res; cur_token = * index; list = NULL; r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } env_cc = mailimap_env_cc_new(list); if (env_cc == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * index = cur_token; * result = env_cc; return MAILIMAP_NO_ERROR; free: clist_foreach(list, (clist_func) mailimap_address_free, NULL); clist_free(list); err: return res; } /* env-date = nstring */ static int mailimap_env_date_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_nstring_parse(fd, buffer, index, result, NULL, progr_rate, progr_fun); } /* env-from = "(" 1*address ")" / nil */ static int mailimap_env_from_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_env_from ** result, size_t progr_rate, progress_function * progr_fun) { clist * list; size_t cur_token; struct mailimap_env_from * env_from; int r; int res; cur_token = * index; list = NULL; r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } env_from = mailimap_env_from_new(list); if (env_from == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * index = cur_token; * result = env_from; return MAILIMAP_NO_ERROR; free: clist_foreach(list, (clist_func) mailimap_address_free, NULL); clist_free(list); err: return res; } /* env-in-reply-to = nstring */ static int mailimap_env_in_reply_to_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_nstring_parse(fd, buffer, index, result, NULL, progr_rate, progr_fun); } /* env-message-id = nstring */ static int mailimap_env_message_id_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_nstring_parse(fd, buffer, index, result, NULL, progr_rate, progr_fun); } /* env-reply-to = "(" 1*address ")" / nil */ static int mailimap_env_reply_to_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_env_reply_to ** result, size_t progr_rate, progress_function * progr_fun) { clist * list; size_t cur_token; struct mailimap_env_reply_to * env_reply_to; int r; int res; cur_token = * index; list = NULL; r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } env_reply_to = mailimap_env_reply_to_new(list); if (env_reply_to == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * index = cur_token; * result = env_reply_to; return MAILIMAP_NO_ERROR; free: clist_foreach(list, (clist_func) mailimap_address_free, NULL); clist_free(list); err: return res; } /* env-sender = "(" 1*address ")" / nil */ static int mailimap_env_sender_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_env_sender ** result, size_t progr_rate, progress_function * progr_fun) { clist * list; size_t cur_token; struct mailimap_env_sender * env_sender; int r; int res; cur_token = * index; list = NULL; r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } env_sender = mailimap_env_sender_new(list); if (env_sender == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * index = cur_token; * result = env_sender; return MAILIMAP_NO_ERROR; free: clist_foreach(list, (clist_func) mailimap_address_free, NULL); clist_free(list); err: return res; } /* env-subject = nstring */ static int mailimap_env_subject_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_nstring_parse(fd, buffer, index, result, NULL, progr_rate, progr_fun); } /* env-to = "(" 1*address ")" / nil */ static int mailimap_env_to_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_env_to ** result, size_t progr_rate, progress_function * progr_fun) { clist * list; size_t cur_token; struct mailimap_env_to * env_to; int r; int res; cur_token = * index; list = NULL; r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } env_to = mailimap_env_to_new(list); if (env_to == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * index = cur_token; * result = env_to; return MAILIMAP_NO_ERROR; free: clist_foreach(list, (clist_func) mailimap_address_free, NULL); clist_free(list); err: return res; } /* UNIMPLEMENTED examine = "EXAMINE" SP mailbox */ /* UNIMPLEMENTED fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att / "(" fetch-att *(SP fetch-att) ")") */ /* UNIMPLEMENTED fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" / "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] / "BODY" ["STRUCTURE"] / "UID" / "BODY" [".PEEK"] section ["<" number "." nz-number ">"] */ /* flag = "\Answered" / "\Flagged" / "\Deleted" / "\Seen" / "\Draft" / flag-keyword / flag-extension ; Does not include "\Recent" */ static int mailimap_flag_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_flag ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_flag * flag; size_t cur_token; char * flag_keyword; char * flag_extension; int type; int r; int res; cur_token = * index; flag_keyword = NULL; flag_extension = NULL; type = mailimap_flag_get_token_value(fd, buffer, &cur_token); if (type == -1) { r = mailimap_flag_keyword_parse(fd, buffer, &cur_token, &flag_keyword, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_FLAG_KEYWORD; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_flag_extension_parse(fd, buffer, &cur_token, &flag_extension, progr_rate, progr_fun); type = MAILIMAP_FLAG_EXTENSION; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } } flag = mailimap_flag_new(type, flag_keyword, flag_extension); if (flag == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = flag; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (flag_keyword != NULL) mailimap_flag_keyword_free(flag_keyword); if (flag_extension != NULL) mailimap_flag_extension_free(flag_extension); err: return res; } /* flag-extension = "\" atom ; Future expansion. Client implementations ; MUST accept flag-extension flags. Server ; implementations MUST NOT generate ; flag-extension flags except as defined by ; future standard or standards-track ; revisions of this specification. */ static int mailimap_flag_extension_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; char * atom; int r; cur_token = * index; r = mailimap_char_parse(fd, buffer, &cur_token, '\\'); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_atom_parse(fd, buffer, &cur_token, &atom, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; * result = atom; * index = cur_token; return MAILIMAP_NO_ERROR; } /* flag-fetch = flag / "\Recent" */ static int mailimap_flag_fetch_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_flag_fetch ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_flag * flag; struct mailimap_flag_fetch * flag_fetch; int type; int r; int res; cur_token = * index; flag = NULL; type = MAILIMAP_FLAG_FETCH_ERROR; /* XXX - removes a gcc warning */ r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "\\Recent"); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_FLAG_FETCH_RECENT; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_flag_parse(fd, buffer, &cur_token, &flag, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_FLAG_FETCH_OTHER; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } flag_fetch = mailimap_flag_fetch_new(type, flag); if (flag_fetch == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * index = cur_token; * result = flag_fetch; return MAILIMAP_NO_ERROR; free: if (flag != NULL) mailimap_flag_free(flag); err: return res; } /* flag-keyword = atom */ static int mailimap_flag_keyword_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_atom_parse(fd, buffer, index, result, progr_rate, progr_fun); } /* flag-list = "(" [flag *(SP flag)] ")" */ static int mailimap_flag_list_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_flag_list ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; clist * list; struct mailimap_flag_list * flag_list; int r; int res; list = NULL; cur_token = * index; r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list, (mailimap_struct_parser *) mailimap_flag_parse, (mailimap_struct_destructor *) mailimap_flag_free, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { res = r; goto err; } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free; } flag_list = mailimap_flag_list_new(list); if (flag_list == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = flag_list; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (list != NULL) { clist_foreach(list, (clist_func) mailimap_flag_free, NULL); clist_free(list); } err: return res; } /* flag-perm = flag / "\*" */ static int mailimap_flag_perm_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_flag_perm ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_flag_perm * flag_perm; struct mailimap_flag * flag; int type; int r; int res; flag = NULL; cur_token = * index; type = MAILIMAP_FLAG_PERM_ERROR; /* XXX - removes a gcc warning */ r = mailimap_flag_parse(fd, buffer, &cur_token, &flag, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_FLAG_PERM_FLAG; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "\\*"); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_FLAG_PERM_ALL; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } flag_perm = mailimap_flag_perm_new(type, flag); if (flag_perm == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = flag_perm; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (flag != NULL) mailimap_flag_free(flag); err: return res; } /* greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF */ int mailimap_greeting_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_greeting ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_resp_cond_auth * resp_cond_auth; struct mailimap_resp_cond_bye * resp_cond_bye; struct mailimap_greeting * greeting; int type; int r; int res; cur_token = * index; resp_cond_bye = NULL; resp_cond_auth = NULL; r = mailimap_star_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } type = MAILIMAP_GREETING_RESP_COND_ERROR; /* XXX - removes a gcc warning */ r = mailimap_resp_cond_auth_parse(fd, buffer, &cur_token, &resp_cond_auth, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_GREETING_RESP_COND_AUTH; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_resp_cond_bye_parse(fd, buffer, &cur_token, &resp_cond_bye, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_GREETING_RESP_COND_BYE; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_crlf_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free; } greeting = mailimap_greeting_new(type, resp_cond_auth, resp_cond_bye); if (greeting == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = greeting; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (resp_cond_auth) mailimap_resp_cond_auth_free(resp_cond_auth); if (resp_cond_bye) mailimap_resp_cond_bye_free(resp_cond_bye); err: return res; } /* header-fld-name = astring */ static int mailimap_header_fld_name_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_astring_parse(fd, buffer, index, result, progr_rate, progr_fun); } /* header-list = "(" header-fld-name *(SP header-fld-name) ")" */ static int mailimap_header_list_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_header_list ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_header_list * header_list; clist * list; int r; int res; cur_token = * index; list = NULL; r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list, (mailimap_struct_parser *) mailimap_header_fld_name_parse, (mailimap_struct_destructor *) mailimap_header_fld_name_free, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free; } header_list = mailimap_header_list_new(list); if (header_list == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = header_list; * index = cur_token; return MAILIMAP_NO_ERROR; free: clist_foreach(list, (clist_func) mailimap_header_fld_name_free, NULL); clist_free(list); err: return res; } /* UNIMPLEMENTED list = "LIST" SP mailbox SP list-mailbox UNIMPLEMENTED list-mailbox = 1*list-char / string UNIMPLEMENTED list-char = ATOM-CHAR / list-wildcards / resp-specials */ /* list-wildcards = "%" / "*" */ static int is_list_wildcards(char ch) { switch (ch) { case '%': case '*': return TRUE; } return FALSE; } /* literal = "{" number "}" CRLF *CHAR8 ; Number represents the number of CHAR8s */ static int mailimap_literal_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t * result_len, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; uint32_t number; MMAPString * literal; char * literal_p; uint32_t left; int r; int res; size_t number_token; cur_token = * index; r = mailimap_oaccolade_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } number_token = cur_token; r = mailimap_number_parse(fd, buffer, &cur_token, &number); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_caccolade_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_crlf_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } literal = mmap_string_sized_new(number); /* literal = g_new(char, number + 1); */ if (literal == NULL) { res = MAILIMAP_ERROR_MEMORY; goto err; } left = buffer->len - cur_token; if (left >= number) { /* if (number > 0) strncpy(literal, buffer->str + cur_token, number); literal[number] = 0; */ if (number > 0) if (mmap_string_append_len(literal, buffer->str + cur_token, number) == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_literal; } if ((progr_fun != NULL) && (progr_rate != 0)) progr_fun(number, number); cur_token = cur_token + number; } else { uint32_t needed; uint32_t current_prog = 0; uint32_t last_prog = 0; needed = number - left; memcpy(literal->str, buffer->str + cur_token, left); literal->len += left; literal_p = literal->str + left; current_prog = left; while (needed > 0) { ssize_t read_bytes; read_bytes = mailstream_read(fd, literal_p, needed); if (read_bytes == -1) { res = MAILIMAP_ERROR_STREAM; goto free_literal; } literal->len += read_bytes; needed -= read_bytes; literal_p += read_bytes; current_prog += read_bytes; if ((progr_fun != NULL) && (progr_rate != 0)) if (current_prog - last_prog > progr_rate) { progr_fun(current_prog, number); last_prog = current_prog; } } literal->str[number] = 0; #if 0 literal->str[number] = 0; if (mmap_string_append_len(buffer, literal->str + left, literal->len - left) == NULL) { res = MAILIMAP_ERROR_STREAM; goto free_literal; } #endif if (mmap_string_truncate(buffer, number_token) == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_literal; } if (mmap_string_append(buffer, "0}\r\n") == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_literal; } cur_token = number_token + 4; } if ((progr_fun != NULL) && (progr_rate != 0)) progr_fun(number, number); if (mailstream_read_line_append(fd, buffer) == NULL) { res = MAILIMAP_ERROR_STREAM; goto free_literal; } if (mmap_string_ref(literal) < 0) { res = MAILIMAP_ERROR_MEMORY; goto free_literal; } * result = literal->str; if (result_len != NULL) * result_len = literal->len; * index = cur_token; return MAILIMAP_NO_ERROR; free_literal: mmap_string_free(literal); err: return res; } /* UNIMPLEMENTED login = "LOGIN" SP userid SP password UNIMPLEMENTED lsub = "LSUB" SP mailbox SP list-mailbox */ /* mailbox = "INBOX" / astring ; INBOX is case-insensitive. All case variants of ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX ; not as an astring. An astring which consists of ; the case-insensitive sequence "I" "N" "B" "O" "X" ; is considered to be INBOX and not an astring. ; Refer to section 5.1 for further ; semantic details of mailbox names. */ static int mailimap_mailbox_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; char * name; int r; cur_token = * index; r = mailimap_astring_parse(fd, buffer, &cur_token, &name, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; * result = name; * index = cur_token; return MAILIMAP_NO_ERROR; } /* mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list / "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) / "STATUS" SP mailbox SP "(" [status-att SP number *(SP status-att SP number)] ")" / number SP "EXISTS" / number SP "RECENT" */ /* "FLAGS" SP flag-list */ static int mailimap_mailbox_data_flags_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_flag_list ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_flag_list * flag_list; int r; cur_token = * index; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "FLAGS"); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_flag_list_parse(fd, buffer, &cur_token, &flag_list, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; * result = flag_list; * index = cur_token; return MAILIMAP_NO_ERROR; } /* "LIST" SP mailbox-list */ static int mailimap_mailbox_data_list_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_mailbox_list ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_mailbox_list * mb_list; int r; int res; cur_token = * index; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "LIST"); if (r != MAILIMAP_NO_ERROR) { res = r; return r; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; return r; } r = mailimap_mailbox_list_parse(fd, buffer, &cur_token, &mb_list, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; return r; } * result = mb_list; * index = cur_token; return MAILIMAP_NO_ERROR; } /* "LSUB" SP mailbox-list */ static int mailimap_mailbox_data_lsub_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_mailbox_list ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_mailbox_list * mb_list; int r; cur_token = * index; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "LSUB"); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_mailbox_list_parse(fd, buffer, &cur_token, &mb_list, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; * result = mb_list; * index = cur_token; return MAILIMAP_NO_ERROR; } /* "SEARCH" *(SP nz-number) */ static int mailimap_mailbox_data_search_parse(mailstream * fd, MMAPString * buffer, size_t * index, clist ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; size_t final_token; clist * number_list; int r; cur_token = * index; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "SEARCH"); if (r != MAILIMAP_NO_ERROR) return r; final_token = cur_token; number_list = NULL; r = mailimap_space_parse(fd, buffer, &cur_token); if (r == MAILIMAP_NO_ERROR) { r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &number_list, (mailimap_struct_parser *) mailimap_nz_number_alloc_parse, (mailimap_struct_destructor *) mailimap_number_alloc_free, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) final_token = cur_token; } * result = number_list; * index = final_token; return MAILIMAP_NO_ERROR; } /* "STATUS" SP mailbox SP "(" [status-att SP number *(SP status-att SP number)] ")" */ /* status-att SP number */ static int mailimap_status_info_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_status_info ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; int status_att; uint32_t value; struct mailimap_status_info * info; int r; cur_token = * index; value = 0; r = mailimap_status_att_parse(fd, buffer, &cur_token, &status_att); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_number_parse(fd, buffer, &cur_token, &value); if (r != MAILIMAP_NO_ERROR) return r; info = mailimap_status_info_new(status_att, value); if (info == NULL) return MAILIMAP_ERROR_MEMORY; * result = info; * index = cur_token; return MAILIMAP_NO_ERROR; } /* "STATUS" SP mailbox SP "(" [status-att SP number *(SP status-att SP number)] ")" */ static int mailimap_mailbox_data_status_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_mailbox_data_status ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; char * mb; clist * status_info_list; struct mailimap_mailbox_data_status * data_status; int r; int res; cur_token = * index; mb = NULL; status_info_list = NULL; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "STATUS"); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_mailbox_parse(fd, buffer, &cur_token, &mb, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto mailbox; } r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto mailbox; } r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &status_info_list, (mailimap_struct_parser *) mailimap_status_info_parse, (mailimap_struct_destructor *) mailimap_status_info_free, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { res = r; goto mailbox; } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto status_info_list; } data_status = mailimap_mailbox_data_status_new(mb, status_info_list); if (data_status == NULL) { res = MAILIMAP_ERROR_MEMORY; goto status_info_list; } * result = data_status; * index = cur_token; return MAILIMAP_NO_ERROR; status_info_list: if (status_info_list != NULL) { clist_foreach(status_info_list, (clist_func) mailimap_status_info_free, NULL); clist_free(status_info_list); } mailbox: mailimap_mailbox_free(mb); err: return res; } /* number SP "EXISTS" */ static int mailimap_mailbox_data_exists_parse(mailstream * fd, MMAPString * buffer, size_t * index, uint32_t * result) { size_t cur_token; uint32_t number; int r; cur_token = * index; r = mailimap_number_parse(fd, buffer, &cur_token, &number); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "EXISTS"); if (r != MAILIMAP_NO_ERROR) return r; * result = number; * index = cur_token; return MAILIMAP_NO_ERROR; } /* number SP "RECENT" */ static int mailimap_mailbox_data_recent_parse(mailstream * fd, MMAPString * buffer, size_t * index, uint32_t * result) { size_t cur_token; uint32_t number; int r; cur_token = * index; r = mailimap_number_parse(fd, buffer, &cur_token, &number); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "RECENT"); if (r != MAILIMAP_NO_ERROR) return r; * result = number; * index = cur_token; return MAILIMAP_NO_ERROR; } /* mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list / "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) / "STATUS" SP mailbox SP "(" [status-att SP number *(SP status-att SP number)] ")" / number SP "EXISTS" / number SP "RECENT" */ static int mailimap_mailbox_data_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_mailbox_data ** result, size_t progr_rate, progress_function * progr_fun) { int type; struct mailimap_flag_list * data_flags; struct mailimap_mailbox_list * data_list; struct mailimap_mailbox_list * data_lsub; clist * data_search; struct mailimap_mailbox_data_status * data_status; uint32_t data_exists; uint32_t data_recent; struct mailimap_mailbox_data * mailbox_data; size_t cur_token; int r; int res; cur_token = * index; data_flags = NULL; data_list = NULL; data_lsub = NULL; data_search = NULL; data_status = NULL; data_exists = 0; data_recent = 0; type = MAILIMAP_MAILBOX_DATA_ERROR; /* XXX - removes a gcc warning */ r = mailimap_mailbox_data_flags_parse(fd, buffer, &cur_token, &data_flags, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MAILBOX_DATA_FLAGS; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_mailbox_data_list_parse(fd, buffer, &cur_token, &data_list, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MAILBOX_DATA_LIST; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_mailbox_data_lsub_parse(fd, buffer, &cur_token, &data_lsub, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MAILBOX_DATA_LSUB; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_mailbox_data_search_parse(fd, buffer, &cur_token, &data_search, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MAILBOX_DATA_SEARCH; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_mailbox_data_status_parse(fd, buffer, &cur_token, &data_status, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MAILBOX_DATA_STATUS; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_mailbox_data_exists_parse(fd, buffer, &cur_token, &data_exists); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MAILBOX_DATA_EXISTS; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_mailbox_data_recent_parse(fd, buffer, &cur_token, &data_recent); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MAILBOX_DATA_RECENT; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } mailbox_data = mailimap_mailbox_data_new(type, data_flags, data_list, data_lsub, data_search, data_status, data_exists, data_recent); if (mailbox_data == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = mailbox_data; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (data_flags != NULL) mailimap_flag_list_free(data_flags); if (data_list != NULL) mailimap_mailbox_list_free(data_list); if (data_lsub != NULL) mailimap_mailbox_list_free(data_lsub); if (data_search != NULL) mailimap_mailbox_data_search_free(data_search); if (data_status != NULL) mailimap_mailbox_data_status_free(data_status); err: return res; } /* mailbox-list = "(" [mbx-list-flags] ")" SP (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox */ /* DQUOTE QUOTED-CHAR DQUOTE */ static int mailimap_mailbox_list_quoted_char_parse(mailstream * fd, MMAPString * buffer, size_t * index, char * result) { size_t cur_token; char ch; int r; cur_token = * index; r = mailimap_dquote_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_quoted_char_parse(fd, buffer, &cur_token, &ch); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_dquote_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; * index = cur_token; * result = ch; return MAILIMAP_NO_ERROR; } static int mailimap_mailbox_list_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_mailbox_list ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_mailbox_list * mb_list; struct mailimap_mbx_list_flags * mb_flag_list; char ch; char * mb; size_t cur_token; int r; int res; cur_token = * index; r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } mb_flag_list = NULL; ch = 0; mb = NULL; r = mailimap_mbx_list_flags_parse(fd, buffer, &cur_token, &mb_flag_list, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { res = r; goto err; } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_list_flags; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_list_flags; } r = mailimap_mailbox_list_quoted_char_parse(fd, buffer, &cur_token, &ch); if (r == MAILIMAP_ERROR_PARSE) r = mailimap_nil_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_list_flags; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_list_flags; } r = mailimap_mailbox_parse(fd, buffer, &cur_token, &mb, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_list_flags; } mb_list = mailimap_mailbox_list_new(mb_flag_list, ch, mb); if (mb_list == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_mailbox; } * result = mb_list; * index = cur_token; return MAILIMAP_NO_ERROR; free_mailbox: mailimap_mailbox_free(mb); free_list_flags: if (mb_flag_list != NULL) mailimap_mbx_list_flags_free(mb_flag_list); err: return res; } /* mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag *(SP mbx-list-oflag) / mbx-list-oflag *(SP mbx-list-oflag) */ static int mailimap_mbx_list_flags_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_mbx_list_flags ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_mbx_list_flags * mbx_list_flag; size_t cur_token; clist * oflags; clist * oflags_2; int sflag; int type; int r; int res; size_t final_token; int try_sflag; cur_token = * index; final_token = cur_token; oflags = clist_new(); if (oflags == NULL) { res = MAILIMAP_ERROR_MEMORY; goto err; } sflag = MAILIMAP_MBX_LIST_SFLAG_ERROR; oflags_2 = NULL; r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &oflags_2, (mailimap_struct_parser *) mailimap_mbx_list_oflag_no_sflag_parse, (mailimap_struct_destructor *) mailimap_mbx_list_oflag_free, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { res = r; goto free; } try_sflag = 1; if (r == MAILIMAP_NO_ERROR) { clist_concat(oflags, oflags_2); clist_free(oflags_2); final_token = cur_token; try_sflag = 0; r = mailimap_space_parse(fd, buffer, &cur_token); if (r == MAILIMAP_NO_ERROR) try_sflag = 1; } type = MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG; if (try_sflag) { r = mailimap_mbx_list_sflag_parse(fd, buffer, &cur_token, &sflag); switch (r) { case MAILIMAP_ERROR_PARSE: type = MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG; break; case MAILIMAP_NO_ERROR: type = MAILIMAP_MBX_LIST_FLAGS_SFLAG; final_token = cur_token; r = mailimap_space_parse(fd, buffer, &cur_token); if (r == MAILIMAP_NO_ERROR) { r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &oflags_2, (mailimap_struct_parser *) mailimap_mbx_list_oflag_parse, (mailimap_struct_destructor *) mailimap_mbx_list_oflag_free, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { res = r; goto err; } if (r == MAILIMAP_NO_ERROR) { clist_concat(oflags, oflags_2); clist_free(oflags_2); final_token = cur_token; } } break; default: res = r; goto free; } } if ((clist_count(oflags) == 0) && (type == MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG)) { res = MAILIMAP_ERROR_PARSE; goto free; } cur_token = final_token; mbx_list_flag = mailimap_mbx_list_flags_new(type, oflags, sflag); if (mbx_list_flag == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = mbx_list_flag; * index = cur_token; return MAILIMAP_NO_ERROR; free: clist_foreach(oflags, (clist_func) mailimap_mbx_list_oflag_free, NULL); clist_free(oflags); err: return res; } /* mbx-list-oflag = "\Noinferiors" / flag-extension ; Other flags; multiple possible per LIST response */ static int mailimap_mbx_list_oflag_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_mbx_list_oflag ** result, size_t progr_rate, progress_function * progr_fun) { int type; size_t cur_token; struct mailimap_mbx_list_oflag * oflag; char * flag_ext; int r; int res; int sflag_type; cur_token = * index; flag_ext = NULL; type = MAILIMAP_MBX_LIST_OFLAG_ERROR; /* XXX - removes a gcc warning */ r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "\\Noinferiors"); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_flag_extension_parse(fd, buffer, &cur_token, &flag_ext, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } oflag = mailimap_mbx_list_oflag_new(type, flag_ext); if (oflag == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = oflag; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (flag_ext != NULL) mailimap_flag_extension_free(flag_ext); err: return res; } static int mailimap_mbx_list_oflag_no_sflag_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_mbx_list_oflag ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; int sflag_type; int r; cur_token = * index; r = mailimap_mbx_list_sflag_parse(fd, buffer, &cur_token, &sflag_type); if (r == MAILIMAP_NO_ERROR) return MAILIMAP_ERROR_PARSE; return mailimap_mbx_list_oflag_parse(fd, buffer, index, result, progr_rate, progr_fun); } /* mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked" ; Selectability flags; only one per LIST response */ static int mailimap_mbx_list_sflag_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result) { int type; size_t cur_token; cur_token = * index; type = mailimap_mbx_list_sflag_get_token_value(fd, buffer, &cur_token); if (type == -1) return MAILIMAP_ERROR_PARSE; * result = type; * index = cur_token; return MAILIMAP_NO_ERROR; } /* media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / "VIDEO") DQUOTE) / string) SP media-subtype ; Defined in [MIME-IMT] */ /* DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / "VIDEO") DQUOTE */ static int mailimap_media_basic_standard_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result) { size_t cur_token; int type; int r; cur_token = * index; r = mailimap_dquote_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; type = mailimap_media_basic_get_token_value(fd, buffer, &cur_token); if (type == -1) return MAILIMAP_ERROR_PARSE; r = mailimap_dquote_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return FALSE; * index = cur_token; * result = type; return MAILIMAP_NO_ERROR; } /* media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / "VIDEO") DQUOTE) / string) SP media-subtype ; Defined in [MIME-IMT] */ static int mailimap_media_basic_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_media_basic ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; int type; char * basic_type; char * subtype; struct mailimap_media_basic * media_basic; int r; int res; cur_token = * index; basic_type = NULL; subtype = NULL; r = mailimap_media_basic_standard_parse(fd, buffer, &cur_token, &type); if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_string_parse(fd, buffer, &cur_token, &basic_type, NULL, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MEDIA_BASIC_OTHER; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_basic_type; } r = mailimap_media_subtype_parse(fd, buffer, &cur_token, &subtype, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_basic_type; } media_basic = mailimap_media_basic_new(type, basic_type, subtype); if (media_basic == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_subtype; } * result = media_basic; * index = cur_token; return MAILIMAP_NO_ERROR; free_subtype: mailimap_media_subtype_free(subtype); free_basic_type: if (basic_type != NULL) mailimap_string_free(basic_type); err: return res; } /* media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE ; Defined in [MIME-IMT] */ static int mailimap_media_message_parse(mailstream * fd, MMAPString * buffer, size_t * index) { size_t cur_token; int r; cur_token = * index; r = mailimap_dquote_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "MESSAGE"); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_dquote_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_dquote_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "RFC822"); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_dquote_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; * index = cur_token; return MAILIMAP_NO_ERROR; } /* media-subtype = string ; Defined in [MIME-IMT] */ static int mailimap_media_subtype_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_string_parse(fd, buffer, index, result, NULL, progr_rate, progr_fun); } /* media-text = DQUOTE "TEXT" DQUOTE SP media-subtype ; Defined in [MIME-IMT] */ static int mailimap_media_text_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; char * media_subtype; int r; cur_token = * index; r = mailimap_dquote_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "TEXT"); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_dquote_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_media_subtype_parse(fd, buffer, &cur_token, &media_subtype, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; * result = media_subtype; * index = cur_token; return MAILIMAP_NO_ERROR; } /* message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att)) */ static int mailimap_message_data_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_message_data ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; uint32_t number; int type; struct mailimap_msg_att * msg_att; struct mailimap_message_data * msg_data; int r; int res; cur_token = * index; msg_att = NULL; r = mailimap_nz_number_parse(fd, buffer, &cur_token, &number); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } type = MAILIMAP_MESSAGE_DATA_ERROR; /* XXX - removes a gcc warning */ r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "EXPUNGE"); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MESSAGE_DATA_EXPUNGE; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "FETCH"); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_msg_att_parse(fd, buffer, &cur_token, &msg_att, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } type = MAILIMAP_MESSAGE_DATA_FETCH; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } msg_data = mailimap_message_data_new(number, type, msg_att); if (msg_data == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_msg_att; } * result = msg_data; * index = cur_token; return MAILIMAP_NO_ERROR; free_msg_att: if (msg_att != NULL) mailimap_msg_att_free(msg_att); err: return res; } /* msg-att = "(" (msg-att-dynamic / msg-att-static) *(SP (msg-att-dynamic / msg-att-static)) ")" */ /* msg-att-dynamic / msg-att-static */ static int mailimap_msg_att_item_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_msg_att_item ** result, size_t progr_rate, progress_function * progr_fun) { int type; struct mailimap_msg_att_dynamic * msg_att_dynamic; struct mailimap_msg_att_static * msg_att_static; size_t cur_token; struct mailimap_msg_att_item * item; int r; int res; cur_token = * index; msg_att_dynamic = NULL; msg_att_static = NULL; type = MAILIMAP_MSG_ATT_ITEM_ERROR; /* XXX - removes a gcc warning */ r = mailimap_msg_att_dynamic_parse(fd, buffer, &cur_token, &msg_att_dynamic, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MSG_ATT_ITEM_DYNAMIC; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_msg_att_static_parse(fd, buffer, &cur_token, &msg_att_static, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MSG_ATT_ITEM_STATIC; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } item = mailimap_msg_att_item_new(type, msg_att_dynamic, msg_att_static); if (item == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = item; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (msg_att_dynamic != NULL) mailimap_msg_att_dynamic_free(msg_att_dynamic); if (msg_att_static != NULL) mailimap_msg_att_static_free(msg_att_static); err: return res; } /* msg-att = "(" (msg-att-dynamic / msg-att-static) *(SP (msg-att-dynamic / msg-att-static)) ")" */ static int mailimap_msg_att_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_msg_att ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; clist * list; struct mailimap_msg_att * msg_att; int r; int res; cur_token = * index; list = NULL; r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list, (mailimap_struct_parser *) mailimap_msg_att_item_parse, (mailimap_struct_destructor *) mailimap_msg_att_item_free, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free; } msg_att = mailimap_msg_att_new(list); if (msg_att == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * index = cur_token; * result = msg_att; return MAILIMAP_NO_ERROR; free: clist_foreach(list, (clist_func) mailimap_msg_att_item_free, NULL); clist_free(list); err: return res; } /* msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")" ; MAY change for a message */ static int mailimap_msg_att_dynamic_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_msg_att_dynamic ** result, size_t progr_rate, progress_function * progr_fun) { clist * list; struct mailimap_msg_att_dynamic * msg_att_dyn; size_t cur_token; int r; int res; cur_token = * index; list = NULL; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "FLAGS"); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list, (mailimap_struct_parser *) mailimap_flag_fetch_parse, (mailimap_struct_destructor *) mailimap_flag_fetch_free, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { res = r; goto err; } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free; } msg_att_dyn = mailimap_msg_att_dynamic_new(list); if (msg_att_dyn == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = msg_att_dyn; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (list != NULL) { clist_foreach(list, (clist_func) mailimap_flag_fetch_free, NULL); clist_free(list); } err: return res; } /* msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time / "RFC822" [".HEADER" / ".TEXT"] SP nstring / "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body / "BODY" section ["<" number ">"] SP nstring / "UID" SP uniqueid ; MUST NOT change for a message */ /* "ENVELOPE" SP envelope */ static int mailimap_msg_att_envelope_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_envelope ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_envelope * env; int r; cur_token = * index; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "ENVELOPE"); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_envelope_parse(fd, buffer, &cur_token, &env, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; * index = cur_token; * result = env; return MAILIMAP_NO_ERROR; } /* "INTERNALDATE" SP date-time */ static int mailimap_msg_att_internaldate_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_date_time ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_date_time * date_time; int r; cur_token = * index; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "INTERNALDATE"); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return FALSE; r = mailimap_date_time_parse(fd, buffer, &cur_token, &date_time, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; * result = date_time; * index = cur_token; return MAILIMAP_NO_ERROR; } /* "RFC822" SP nstring */ static int mailimap_msg_att_rfc822_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t * result_len, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; char * rfc822_message; int r; size_t length; cur_token = * index; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "RFC822"); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_nstring_parse(fd, buffer, &cur_token, &rfc822_message, &length, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; * result = rfc822_message; if (result_len != NULL) * result_len = length; * index = cur_token; return MAILIMAP_NO_ERROR; } /* "RFC822" ".HEADER" SP nstring */ static int mailimap_msg_att_rfc822_header_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t * result_len, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; char * rfc822_header; int r; size_t length; cur_token = * index; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "RFC822"); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, ".HEADER"); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_nstring_parse(fd, buffer, &cur_token, &rfc822_header, &length, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; * result = rfc822_header; if (result_len != NULL) * result_len = length; * index = cur_token; return MAILIMAP_NO_ERROR; } /* "RFC822" ".TEXT" SP nstring */ static int mailimap_msg_att_rfc822_text_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t * result_len, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; char * rfc822_text; int r; size_t length; cur_token = * index; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "RFC822"); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, ".TEXT"); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_nstring_parse(fd, buffer, &cur_token, &rfc822_text, &length, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; * result = rfc822_text; if (result_len != NULL) * result_len = length; * index = cur_token; return MAILIMAP_NO_ERROR; } /* "RFC822.SIZE" SP number */ static int mailimap_msg_att_rfc822_size_parse(mailstream * fd, MMAPString * buffer, size_t * index, uint32_t * result) { size_t cur_token; uint32_t number; int r; cur_token = * index; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "RFC822.SIZE"); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_number_parse(fd, buffer, &cur_token, &number); if (r != MAILIMAP_NO_ERROR) return r; * result = number; * index = cur_token; return MAILIMAP_NO_ERROR; } /* "BODY" SP body */ static int mailimap_msg_att_body_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_body * body; size_t cur_token; int r; cur_token = * index; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "BODY"); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_body_parse(fd, buffer, &cur_token, &body, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; * result = body; * index = cur_token; return MAILIMAP_NO_ERROR; } /* "BODY" "STRUCTURE" SP body */ static int mailimap_msg_att_bodystructure_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_body * body; size_t cur_token; int r; cur_token = * index; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "BODY"); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "STRUCTURE"); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_body_parse(fd, buffer, &cur_token, &body, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; * result = body; * index = cur_token; return MAILIMAP_NO_ERROR; } /* "BODY" section ["<" number ">"] SP nstring */ static int mailimap_msg_att_body_section_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_msg_att_body_section ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; uint32_t number; struct mailimap_section * section; char * body_part; struct mailimap_msg_att_body_section * msg_att_body_section; int r; int res; size_t length; cur_token = * index; section = NULL; number = 0; body_part = NULL; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "BODY"); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_section_parse(fd, buffer, &cur_token, §ion, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_lower_parse(fd, buffer, &cur_token); switch (r) { case MAILIMAP_NO_ERROR: r = mailimap_number_parse(fd, buffer, &cur_token, &number); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_section; } r = mailimap_greater_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_section; } break; case MAILIMAP_ERROR_PARSE: break; default: return r; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_section; } r = mailimap_nstring_parse(fd, buffer, &cur_token, &body_part, &length, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_section; } msg_att_body_section = mailimap_msg_att_body_section_new(section, number, body_part, length); if (msg_att_body_section == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_string; } * result = msg_att_body_section; * index = cur_token; return MAILIMAP_NO_ERROR; free_string: mailimap_nstring_free(body_part); free_section: if (section != NULL) mailimap_section_free(section); err: return res; } /* "UID" SP uniqueid */ static int mailimap_msg_att_uid_parse(mailstream * fd, MMAPString * buffer, size_t * index, uint32_t * result) { size_t cur_token; uint32_t uid; int r; cur_token = * index; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "UID"); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_uniqueid_parse(fd, buffer, &cur_token, &uid); if (r != MAILIMAP_NO_ERROR) return r; * index = cur_token; * result = uid; return MAILIMAP_NO_ERROR; } /* msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time / "RFC822" [".HEADER" / ".TEXT"] SP nstring / "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body / "BODY" section ["<" number ">"] SP nstring / "UID" SP uniqueid ; MUST NOT change for a message */ static int mailimap_msg_att_static_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_msg_att_static ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_envelope * env; struct mailimap_date_time * internal_date; char * rfc822; char * rfc822_header; char * rfc822_text; uint32_t rfc822_size; struct mailimap_body * bodystructure; struct mailimap_body * body; struct mailimap_msg_att_body_section * body_section; uint32_t uid; struct mailimap_msg_att_static * msg_att_static; int type; int r; int res; size_t length; cur_token = * index; env = NULL; internal_date = NULL; rfc822 = NULL; rfc822_header = NULL; rfc822_text = NULL; rfc822_size = 0; length = 0; bodystructure = NULL; body = NULL; body_section = NULL; uid = 0; type = MAILIMAP_MSG_ATT_ERROR; /* XXX - removes a gcc warning */ r = mailimap_msg_att_envelope_parse(fd, buffer, &cur_token, &env, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MSG_ATT_ENVELOPE; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_msg_att_internaldate_parse(fd, buffer, &cur_token, &internal_date, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MSG_ATT_INTERNALDATE; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_msg_att_rfc822_parse(fd, buffer, &cur_token, &rfc822, &length, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MSG_ATT_RFC822; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_msg_att_rfc822_header_parse(fd, buffer, &cur_token, &rfc822_header, &length, progr_rate, progr_fun); type = MAILIMAP_MSG_ATT_RFC822_HEADER; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_msg_att_rfc822_text_parse(fd, buffer, &cur_token, &rfc822_text, &length, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MSG_ATT_RFC822_TEXT; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_msg_att_rfc822_size_parse(fd, buffer, &cur_token, &rfc822_size); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MSG_ATT_RFC822_SIZE; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_msg_att_body_parse(fd, buffer, &cur_token, &body, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MSG_ATT_BODY; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_msg_att_bodystructure_parse(fd, buffer, &cur_token, &bodystructure, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MSG_ATT_BODYSTRUCTURE; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_msg_att_body_section_parse(fd, buffer, &cur_token, &body_section, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MSG_ATT_BODY_SECTION; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_msg_att_uid_parse(fd, buffer, &cur_token, &uid); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_MSG_ATT_UID; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } msg_att_static = mailimap_msg_att_static_new(type, env, internal_date, rfc822, rfc822_header, rfc822_text, length, rfc822_size, bodystructure, body, body_section, uid); if (msg_att_static == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = msg_att_static; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (env) mailimap_msg_att_envelope_free(env); if (internal_date) mailimap_msg_att_internaldate_free(internal_date); if (rfc822) mailimap_msg_att_rfc822_free(rfc822); if (rfc822_header) mailimap_msg_att_rfc822_header_free(rfc822_header); if (rfc822_text) mailimap_msg_att_rfc822_text_free(rfc822_text); if (bodystructure) mailimap_msg_att_bodystructure_free(bodystructure); if (body) mailimap_msg_att_body_free(body); if (body_section) mailimap_msg_att_body_section_free(body_section); err: return res; } /* nil = "NIL" */ static int mailimap_nil_parse(mailstream * fd, MMAPString * buffer, size_t * index) { return mailimap_token_case_insensitive_parse(fd, buffer, index, "NIL"); } /* nstring = string / nil */ static int mailimap_nstring_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t * result_len, size_t progr_rate, progress_function * progr_fun) { int r; r = mailimap_string_parse(fd, buffer, index, result, result_len, progr_rate, progr_fun); switch (r) { case MAILIMAP_NO_ERROR: return MAILIMAP_NO_ERROR; case MAILIMAP_ERROR_PARSE: r = mailimap_nil_parse(fd, buffer, index); if (r != MAILIMAP_NO_ERROR) { return r; } * result = NULL; if (result_len != NULL) * result_len = 0; return MAILIMAP_NO_ERROR; default: return r; } } /* number = 1*DIGIT ; Unsigned 32-bit integer ; (0 <= n < 4,294,967,296) */ static int mailimap_number_parse(mailstream * fd, MMAPString * buffer, size_t * index, uint32_t * result) { size_t cur_token; int digit; uint32_t number; int parsed; int r; cur_token = * index; parsed = FALSE; #ifdef UNSTRICT_SYNTAX mailimap_space_parse(fd, buffer, &cur_token); #endif number = 0; while (1) { r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); if (r == MAILIMAP_ERROR_PARSE) break; else if (r == MAILIMAP_NO_ERROR) { number *= 10; number += digit; parsed = TRUE; } else return r; } if (!parsed) return MAILIMAP_ERROR_PARSE; * result = number; * index = cur_token; return MAILIMAP_NO_ERROR; } /* nz-number = digit-nz *DIGIT ; Non-zero unsigned 32-bit integer ; (0 < n < 4,294,967,296) */ static int mailimap_nz_number_parse(mailstream * fd, MMAPString * buffer, size_t * index, uint32_t * result) { #ifdef UNSTRICT_SYNTAX size_t cur_token; uint32_t number; int r; cur_token = * index; r = mailimap_number_parse(fd, buffer, &cur_token, &number); if (r != MAILIMAP_NO_ERROR) return r; if (number == 0) return MAILIMAP_ERROR_PARSE; #else size_t cur_token; int digit; uint32_t number; int r; cur_token = * index; r = mailimap_digit_nz_parse(fd, buffer, &cur_token, &digit); if (r != MAILIMAP_NO_ERROR) return r; number = digit; while (1) { r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); if (r == MAILIMAP_ERROR_PARSE) break; else if (r == MAILIMAP_NO_ERROR) { number *= 10; number += (guint32) digit; } else return r; } #endif * result = number; * index = cur_token; return MAILIMAP_NO_ERROR; } /* password = astring */ /* quoted = DQUOTE *QUOTED-CHAR DQUOTE */ static int mailimap_quoted_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { char ch; size_t cur_token; MMAPString * gstr_quoted; int r; int res; cur_token = * index; #ifdef UNSTRICT_SYNTAX r = mailimap_space_parse(fd, buffer, &cur_token); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) return r; #endif r = mailimap_dquote_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } gstr_quoted = mmap_string_new(""); if (gstr_quoted == NULL) { res = MAILIMAP_ERROR_MEMORY; goto err; } while (1) { r = mailimap_quoted_char_parse(fd, buffer, &cur_token, &ch); if (r == MAILIMAP_ERROR_PARSE) break; else if (r == MAILIMAP_NO_ERROR) { if (mmap_string_append_c(gstr_quoted, ch) == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } } else { res = r; goto free; } } r = mailimap_dquote_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free; } if (mmap_string_ref(gstr_quoted) < 0) { res = MAILIMAP_ERROR_MEMORY; goto free; } * index = cur_token; * result = gstr_quoted->str; return MAILIMAP_NO_ERROR; free: mmap_string_free(gstr_quoted); err: return res; } /* QUOTED-CHAR = / "\" quoted-specials */ static int is_quoted_specials(char ch); static int mailimap_quoted_char_parse(mailstream * fd, MMAPString * buffer, size_t * index, char * result) { size_t cur_token; int r; cur_token = * index; if (!is_quoted_specials(buffer->str[cur_token])) { * result = buffer->str[cur_token]; cur_token ++; * index = cur_token; return MAILIMAP_NO_ERROR; } else { char quoted_special; r = mailimap_char_parse(fd, buffer, &cur_token, '\\'); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_quoted_specials_parse(fd, buffer, &cur_token, "ed_special); if (r != MAILIMAP_NO_ERROR) return r; * result = quoted_special; * index = cur_token; return MAILIMAP_NO_ERROR; } } /* quoted-specials = DQUOTE / "\" */ static int is_quoted_specials(char ch) { return (ch == '\"') || (ch == '\\'); } static int mailimap_quoted_specials_parse(mailstream * fd, MMAPString * buffer, size_t * index, char * result) { size_t cur_token; cur_token = * index; if (is_quoted_specials(buffer->str[cur_token])) { * result = buffer->str[cur_token]; cur_token ++; * index = cur_token; return MAILIMAP_NO_ERROR; } else return MAILIMAP_ERROR_PARSE; } /* UNIMPLEMENTED rename = "RENAME" SP mailbox SP mailbox ; Use of INBOX as a destination gives a NO error */ /* response = *(continue-req / response-data) response-done */ /* continue-req / response-data */ /* static */ int mailimap_cont_req_or_resp_data_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_cont_req_or_resp_data ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data; struct mailimap_continue_req * cont_req; struct mailimap_response_data * resp_data; int type; int r; int res; cur_token = * index; cont_req = NULL; resp_data = NULL; type = MAILIMAP_RESP_ERROR; /* XXX - removes a gcc warning */ r = mailimap_continue_req_parse(fd, buffer, &cur_token, &cont_req, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_RESP_CONT_REQ; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_response_data_parse(fd, buffer, &cur_token, &resp_data, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_RESP_RESP_DATA; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } /* multi-lines response read another response line because after that token, there must have something (continue-req, response-data or response-done) */ if (!mailstream_read_line_append(fd, buffer)) { res = MAILIMAP_ERROR_STREAM; goto free; } cont_req_or_resp_data = mailimap_cont_req_or_resp_data_new(type, cont_req, resp_data); if (cont_req_or_resp_data == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = cont_req_or_resp_data; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (cont_req != NULL) mailimap_continue_req_free(cont_req); if (resp_data != NULL) mailimap_response_data_free(resp_data); err: return res; } /* response = *(continue-req / response-data) response-done */ int mailimap_response_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_response ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; clist * cont_req_or_resp_data_list; struct mailimap_response * resp; struct mailimap_response_done * resp_done; int r; int res; cur_token = * index; cont_req_or_resp_data_list = NULL; resp_done = NULL; r = mailimap_struct_multiple_parse(fd, buffer, &cur_token, &cont_req_or_resp_data_list, (mailimap_struct_parser *) mailimap_cont_req_or_resp_data_parse, (mailimap_struct_destructor *) mailimap_cont_req_or_resp_data_free, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) return r; r = mailimap_response_done_parse(fd, buffer, &cur_token, &resp_done, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_list; } resp = mailimap_response_new(cont_req_or_resp_data_list, resp_done); if (resp == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_resp_done; } * result = resp; * index = cur_token; return MAILIMAP_NO_ERROR; free_resp_done: mailimap_response_done_free(resp_done); free_list: if (cont_req_or_resp_data_list != NULL) { clist_foreach(cont_req_or_resp_data_list, (clist_func) mailimap_cont_req_or_resp_data_free, NULL); clist_free(cont_req_or_resp_data_list); } return res; } /* response-data = "*" SP (resp-cond-state / resp-cond-bye / mailbox-data / message-data / capability-data) CRLF */ static int mailimap_response_data_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_response_data ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_response_data * resp_data; size_t cur_token; int type; struct mailimap_resp_cond_state * cond_state; struct mailimap_resp_cond_bye * cond_bye; struct mailimap_mailbox_data * mb_data; struct mailimap_message_data * msg_data; struct mailimap_capability_data * cap_data; int r; int res; cond_state = NULL; cond_bye = NULL; mb_data = NULL; msg_data = NULL; cap_data = NULL; cur_token = * index; r = mailimap_star_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } type = MAILIMAP_RESP_DATA_TYPE_ERROR; /* XXX - removes a gcc warning */ r = mailimap_resp_cond_state_parse(fd, buffer, &cur_token, &cond_state, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_RESP_DATA_TYPE_COND_STATE; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_resp_cond_bye_parse(fd, buffer, &cur_token, &cond_bye, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_RESP_DATA_TYPE_COND_BYE; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_mailbox_data_parse(fd, buffer, &cur_token, &mb_data, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_message_data_parse(fd, buffer, &cur_token, &msg_data, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_capability_data_parse(fd, buffer, &cur_token, &cap_data, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_crlf_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free; } resp_data = mailimap_response_data_new(type, cond_state, cond_bye, mb_data, msg_data, cap_data); if (resp_data == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = resp_data; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (cond_state) mailimap_resp_cond_state_free(cond_state); if (cond_bye) mailimap_resp_cond_bye_free(cond_bye); if (mb_data) mailimap_mailbox_data_free(mb_data); if (msg_data) mailimap_message_data_free(msg_data); if (cap_data) mailimap_capability_data_free(cap_data); err: return res; } /* response-done = response-tagged / response-fatal */ static int mailimap_response_done_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_response_done ** result, size_t progr_rate, progress_function * progr_fun) { int type; struct mailimap_response_done * resp_done; size_t cur_token; struct mailimap_response_tagged * tagged; struct mailimap_response_fatal * fatal; int r; int res; cur_token = * index; tagged = NULL; fatal = NULL; type = MAILIMAP_RESP_DONE_TYPE_ERROR; /* removes a gcc warning */ r = mailimap_response_tagged_parse(fd, buffer, &cur_token, &tagged, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_RESP_DONE_TYPE_TAGGED; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_response_fatal_parse(fd, buffer, &cur_token, &fatal, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_RESP_DONE_TYPE_FATAL; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } resp_done = mailimap_response_done_new(type, tagged, fatal); if (resp_done == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = resp_done; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (tagged == NULL) mailimap_response_tagged_free(tagged); if (fatal == NULL) mailimap_response_fatal_free(fatal); err: return res; } /* response-fatal = "*" SP resp-cond-bye CRLF ; Server closes connection immediately */ static int mailimap_response_fatal_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_response_fatal ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_resp_cond_bye * cond_bye; struct mailimap_response_fatal * fatal; size_t cur_token; int res; int r; cur_token = * index; r = mailimap_star_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_resp_cond_bye_parse(fd, buffer, &cur_token, &cond_bye, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_crlf_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free; } fatal = mailimap_response_fatal_new(cond_bye); if (fatal == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = fatal; * index = cur_token; return MAILIMAP_NO_ERROR; free: mailimap_resp_cond_bye_free(cond_bye); err: return res; } /* response-tagged = tag SP resp-cond-state CRLF */ static int mailimap_response_tagged_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_response_tagged ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; char * tag; struct mailimap_resp_cond_state * cond_state; struct mailimap_response_tagged * resp_tagged; int r; int res; cur_token = * index; cond_state = NULL; r = mailimap_tag_parse(fd, buffer, &cur_token, &tag, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_tag; } r = mailimap_resp_cond_state_parse(fd, buffer, &cur_token, &cond_state, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_tag; } resp_tagged = mailimap_response_tagged_new(tag, cond_state); if (resp_tagged == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_cond_state; } * result = resp_tagged; * index = cur_token; return MAILIMAP_NO_ERROR; free_cond_state: mailimap_resp_cond_state_free(cond_state); free_tag: mailimap_tag_free(tag); err: return res; } /* resp-cond-auth = ("OK" / "PREAUTH") SP resp-text ; Authentication condition */ static int mailimap_resp_cond_auth_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_resp_cond_auth ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_resp_cond_auth * cond_auth; size_t cur_token; struct mailimap_resp_text * text; int type; int r; int res; cur_token = * index; text = NULL; type = MAILIMAP_RESP_COND_AUTH_ERROR; /* XXX - removes a gcc warning */ r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "OK"); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_RESP_COND_AUTH_OK; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "PREAUTH"); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_RESP_COND_AUTH_PREAUTH; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_resp_text_parse(fd, buffer, &cur_token, &text, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } cond_auth = mailimap_resp_cond_auth_new(type, text); if (cond_auth == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = cond_auth; * index = cur_token; return MAILIMAP_NO_ERROR; free: mailimap_resp_text_free(text); err: return res; } /* resp-cond-bye = "BYE" SP resp-text */ static int mailimap_resp_cond_bye_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_resp_cond_bye ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_resp_cond_bye * cond_bye; struct mailimap_resp_text * text; int r; int res; cur_token = * index; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "BYE"); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_resp_text_parse(fd, buffer, &cur_token, &text, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } cond_bye = mailimap_resp_cond_bye_new(text); if (cond_bye == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * index = cur_token; * result = cond_bye; return MAILIMAP_NO_ERROR; free: mailimap_resp_text_free(text); err: return res; } /* resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text ; Status condition */ static int mailimap_resp_cond_state_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_resp_cond_state ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_resp_cond_state * cond_state; size_t cur_token; struct mailimap_resp_text * text; int type; int r; int res; cur_token = * index; text = NULL; type = mailimap_resp_cond_state_get_token_value(fd, buffer, &cur_token); if (type == -1) { res = MAILIMAP_ERROR_PARSE; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_resp_text_parse(fd, buffer, &cur_token, &text, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } cond_state = mailimap_resp_cond_state_new(type, text); if (cond_state == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = cond_state; * index = cur_token; return MAILIMAP_NO_ERROR; free: mailimap_resp_text_free(text); err: return res; } /* resp-specials = "]" */ static int is_resp_specials(char ch) { switch (ch) { case ']': return TRUE; }; return FALSE; } /* resp-text = ["[" resp-text-code "]" SP] text */ /* "[" resp-text-code "]" */ static int mailimap_resp_text_resp_text_code_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_resp_text_code ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_resp_text_code * text_code; size_t cur_token; int r; int res; cur_token = * index; r = mailimap_obracket_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_resp_text_code_parse(fd, buffer, &cur_token, &text_code, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_cbracket_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free; } r = mailimap_space_parse(fd, buffer, &cur_token); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { res = r; goto free; } * result = text_code; * index = cur_token; return MAILIMAP_NO_ERROR; free: mailimap_resp_text_code_free(text_code); err: return res; } /* resp-text = ["[" resp-text-code "]" SP] text */ static int mailimap_resp_text_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_resp_text ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_resp_text_code * text_code; struct mailimap_resp_text * resp_text; char * text; int r; int res; cur_token = * index; text = NULL; text_code = NULL; r = mailimap_resp_text_resp_text_code_parse(fd, buffer, &cur_token, &text_code, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) return r; r = mailimap_text_parse(fd, buffer, &cur_token, &text, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { res = r; goto free_resp_text_code; } resp_text = mailimap_resp_text_new(text_code, text); if (resp_text == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_text; } * result = resp_text; * index = cur_token; return MAILIMAP_NO_ERROR; free_resp_text_code: if (text_code != NULL) mailimap_resp_text_code_free(text_code); free_text: mailimap_text_free(text); return res; } /* resp-text-code = "ALERT" / "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / capability-data / "PARSE" / "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / "UNSEEN" SP nz-number / atom [SP 1*] */ /* ALERT / PARSE / READ-ONLY / READ-WRITE / TRYCREATE */ static int mailimap_resp_text_code_1_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result) { int id; size_t cur_token; cur_token = * index; id = mailimap_resp_text_code_1_get_token_value(fd, buffer, &cur_token); if (id == -1) return MAILIMAP_ERROR_PARSE; * result = id; * index = cur_token; return MAILIMAP_NO_ERROR; } /* "BADCHARSET" [SP "(" astring *(SP astring) ")" ] */ /* SP "(" astring *(SP astring) ")" */ static int mailimap_resp_text_code_badcharset_1_parse(mailstream * fd, MMAPString * buffer, size_t * index, clist ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; clist * charset; int r; int res; cur_token = * index; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &charset, (mailimap_struct_parser *) mailimap_astring_parse, (mailimap_struct_destructor *) mailimap_astring_free, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto charset; } * index = cur_token; * result = charset; return MAILIMAP_NO_ERROR; charset: clist_foreach(charset, (clist_func) mailimap_string_free, NULL); clist_free(charset); err: return res; } /* "BADCHARSET" [SP "(" astring *(SP astring) ")" ] */ static int mailimap_resp_text_code_badcharset_parse(mailstream * fd, MMAPString * buffer, size_t * index, clist ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; clist * charset; int r; cur_token = * index; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "BADCHARSET"); if (r != MAILIMAP_NO_ERROR) return r; charset = NULL; r = mailimap_resp_text_code_badcharset_1_parse(fd, buffer, &cur_token, &charset, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) return r; * result = charset; * index = cur_token; return MAILIMAP_NO_ERROR; } /* "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" */ static int mailimap_resp_text_code_permanentflags_parse(mailstream * fd, MMAPString * buffer, size_t * index, clist ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; clist * flaglist; int r; int res; cur_token = * index; flaglist = NULL; r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "PERMANENTFLAGS"); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &flaglist, (mailimap_struct_parser *) mailimap_flag_perm_parse, (mailimap_struct_destructor *) mailimap_flag_perm_free, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { res = r; goto err; } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free; } * index = cur_token; * result = flaglist; return MAILIMAP_NO_ERROR; free: clist_foreach(flaglist, (clist_func) mailimap_flag_perm_free, NULL); clist_free(flaglist); err: return res; } /* "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / "UNSEEN" SP nz-number */ static int mailimap_resp_text_code_number_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_resp_text_code ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; int type; uint32_t number; struct mailimap_resp_text_code * resp_text_code; int r; cur_token = * index; resp_text_code = NULL; type = mailimap_resp_text_code_2_get_token_value(fd, buffer, &cur_token); if (type == -1) return MAILIMAP_ERROR_PARSE; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_nz_number_parse(fd, buffer, &cur_token, &number); if (r != MAILIMAP_NO_ERROR) return r; switch (type) { case MAILIMAP_RESP_TEXT_CODE_UIDNEXT: resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL, number, 0, 0, NULL , NULL); break; case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY: resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL, 0, number, 0, NULL , NULL); break; case MAILIMAP_RESP_TEXT_CODE_UNSEEN: resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL, 0, 0, number, NULL , NULL); break; } if (resp_text_code == NULL) return MAILIMAP_ERROR_MEMORY; * result = resp_text_code; * index = cur_token; return MAILIMAP_NO_ERROR; } /* atom [SP 1*] */ static int is_text_char(char ch); /* any TEXT-CHAR except "]" */ static int is_text_char_1(char ch) { if (ch == ']') return FALSE; return is_text_char(ch); } /* 1* */ static int mailimap_resp_text_code_other_1_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; char * value; int r; cur_token = * index; r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_resp_text_code_other_2_parse(fd, buffer, &cur_token, &value, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) return r; * result = value; * index = cur_token; return MAILIMAP_NO_ERROR; } /* atom [SP 1*] */ static int mailimap_resp_text_code_other_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_resp_text_code ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; char * atom; char * value; struct mailimap_resp_text_code * resp_text_code; int r; int res; cur_token = * index; atom = NULL; value = NULL; r = mailimap_atom_parse(fd, buffer, &cur_token, &atom, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_resp_text_code_other_1_parse(fd, buffer, &cur_token, &value, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { res = r; goto err; } resp_text_code = mailimap_resp_text_code_new(MAILIMAP_RESP_TEXT_CODE_OTHER, NULL, NULL, NULL, 0, 0, 0, atom, value); if (resp_text_code == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_value; } * result = resp_text_code; * index = cur_token; return MAILIMAP_NO_ERROR; free_value: if (value != NULL) free(value); mailimap_atom_free(atom); err: return res; } /* resp-text-code = "ALERT" / "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / capability-data / "PARSE" / "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / "UNSEEN" SP nz-number / atom [SP 1*] */ static int mailimap_resp_text_code_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_resp_text_code ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_resp_text_code * resp_text_code; clist * badcharset; clist * permanentflags; struct mailimap_capability_data * cap_data; int type; int r; int res; cur_token = * index; resp_text_code = NULL; badcharset = NULL; cap_data = NULL; permanentflags = NULL; r = mailimap_resp_text_code_1_parse(fd, buffer, &cur_token, &type); if (r == MAILIMAP_NO_ERROR) { /* do nothing */ } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_resp_text_code_badcharset_parse(fd, buffer, &cur_token, &badcharset, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_RESP_TEXT_CODE_BADCHARSET; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_capability_data_parse(fd, buffer, &cur_token, &cap_data, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_resp_text_code_permanentflags_parse(fd, buffer, &cur_token, &permanentflags, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS; } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_resp_text_code_number_parse(fd, buffer, &cur_token, &resp_text_code, progr_rate, progr_fun); } if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_resp_text_code_other_parse(fd, buffer, &cur_token, &resp_text_code, progr_rate, progr_fun); } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } if (resp_text_code == NULL) { resp_text_code = mailimap_resp_text_code_new(type, badcharset, cap_data, permanentflags, 0, 0, 0, NULL, NULL); if (resp_text_code == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } } * result = resp_text_code; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (permanentflags) { clist_foreach(permanentflags, (clist_func) mailimap_flag_perm_free, NULL); clist_free(permanentflags); } if (cap_data) mailimap_capability_data_free(cap_data); if (badcharset) { clist_foreach(badcharset, (clist_func) mailimap_astring_free, NULL); clist_free(badcharset); } err: return res; } /* UNIMPLEMENTED search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key) ; CHARSET argument to MUST be registered with IANA */ /* UNIMPLEMENTED search-key = "ALL" / "ANSWERED" / "BCC" SP astring / "BEFORE" SP date / "BODY" SP astring / "CC" SP astring / "DELETED" / "FLAGGED" / "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" / "OLD" / "ON" SP date / "RECENT" / "SEEN" / "SINCE" SP date / "SUBJECT" SP astring / "TEXT" SP astring / "TO" SP astring / "UNANSWERED" / "UNDELETED" / "UNFLAGGED" / "UNKEYWORD" SP flag-keyword / "UNSEEN" / ; Above this line were in [IMAP2] "DRAFT" / "HEADER" SP header-fld-name SP astring / "LARGER" SP number / "NOT" SP search-key / "OR" SP search-key SP search-key / "SENTBEFORE" SP date / "SENTON" SP date / "SENTSINCE" SP date / "SMALLER" SP number / "UID" SP set / "UNDRAFT" / set / "(" search-key *(SP search-key) ")" */ /* section = "[" [section-spec] "]" */ static int mailimap_section_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_section ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_section_spec * section_spec; size_t cur_token; struct mailimap_section * section; int r; int res; cur_token = * index; section_spec = NULL; r = mailimap_obracket_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_section_spec_parse(fd, buffer, &cur_token, §ion_spec, progr_rate, progr_fun); if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { res = r; goto err; } r = mailimap_cbracket_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } if (section_spec == NULL) section = NULL; else { section = mailimap_section_new(section_spec); if (section == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } } * result = section; * index = cur_token; return MAILIMAP_NO_ERROR; free: mailimap_section_spec_free(section_spec); err: return res; } /* section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list / "TEXT" ; top-level or MESSAGE/RFC822 part */ static int mailimap_section_msgtext_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_section_msgtext ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; int type; struct mailimap_header_list * header_list; struct mailimap_section_msgtext * msgtext; int r; int res; cur_token = * index; header_list = NULL; type = mailimap_section_msgtext_get_token_value(fd, buffer, &cur_token); if (type == -1) { res = MAILIMAP_ERROR_PARSE; goto err; } if (type == MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS) { r = mailimap_header_list_parse(fd, buffer, &cur_token, &header_list, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } } else if (type == MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT) { r = mailimap_header_list_parse(fd, buffer, &cur_token, &header_list, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } } msgtext = mailimap_section_msgtext_new(type, header_list); if (msgtext == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_header_list; } * result = msgtext; * index = cur_token; return MAILIMAP_NO_ERROR; free_header_list: if (header_list) mailimap_header_list_free(header_list); err: return res; } /* section-part = nz-number *("." nz-number) ; body part nesting */ static int mailimap_section_part_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_section_part ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_section_part * section_part; size_t cur_token; clist * section_id; int r; int res; cur_token = * index; section_id = NULL; r = mailimap_struct_list_parse(fd, buffer, &cur_token, §ion_id, '.', (mailimap_struct_parser *) mailimap_nz_number_alloc_parse, (mailimap_struct_destructor *) mailimap_number_alloc_free, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } section_part = mailimap_section_part_new(section_id); if (section_part == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_section_id; } * result = section_part; * index = cur_token; return MAILIMAP_NO_ERROR; free_section_id: clist_foreach(section_id, (clist_func) mailimap_number_alloc_free, NULL); clist_free(section_id); err: return res; } /* section-spec = section-msgtext / (section-part ["." section-text]) */ static int mailimap_section_spec_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_section_spec ** result, size_t progr_rate, progress_function * progr_fun) { int type; struct mailimap_section_msgtext * section_msgtext; struct mailimap_section_part * section_part; struct mailimap_section_text * section_text; struct mailimap_section_spec * section_spec; size_t cur_token; int r; int res; size_t final_token; cur_token = * index; section_msgtext = NULL; section_part = NULL; section_text = NULL; r = mailimap_section_msgtext_parse(fd, buffer, &cur_token, §ion_msgtext, progr_rate, progr_fun); switch (r) { case MAILIMAP_NO_ERROR: type = MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT; break; case MAILIMAP_ERROR_PARSE: r = mailimap_section_part_parse(fd, buffer, &cur_token, §ion_part, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } final_token = cur_token; type = MAILIMAP_SECTION_SPEC_SECTION_PART; r = mailimap_dot_parse(fd, buffer, &cur_token); if (r == MAILIMAP_NO_ERROR) { r = mailimap_section_text_parse(fd, buffer, &cur_token, §ion_text, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) { final_token = cur_token; } else if (r != MAILIMAP_ERROR_PARSE) { res = r; goto err; } } else if (r != MAILIMAP_ERROR_PARSE) { res = r; goto err; } cur_token = final_token; break; default: res = r; goto err; } section_spec = mailimap_section_spec_new(type, section_msgtext, section_part, section_text); if (section_spec == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = section_spec; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (section_msgtext) mailimap_section_msgtext_free(section_msgtext); if (section_part) mailimap_section_part_free(section_part); if (section_text) mailimap_section_text_free(section_text); err: return res; } /* section-text = section-msgtext / "MIME" ; text other than actual body part (headers, etc.) */ static int mailimap_section_text_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_section_text ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_section_msgtext * section_msgtext; size_t cur_token; struct mailimap_section_text * section_text; int type; int r; int res; cur_token = * index; section_msgtext = NULL; type = MAILIMAP_SECTION_TEXT_ERROR; /* XXX - removes a gcc warning */ r = mailimap_section_msgtext_parse(fd, buffer, &cur_token, §ion_msgtext, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT; if (r == MAILIMAP_ERROR_PARSE) { r= mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "MIME"); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_SECTION_TEXT_MIME; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } section_text = mailimap_section_text_new(type, section_msgtext); if (section_text == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * result = section_text; * index = cur_token; return MAILIMAP_NO_ERROR; free: if (section_msgtext) mailimap_section_msgtext_free(section_msgtext); err: return res; } /* UNIMPLEMENTED select = "SELECT" SP mailbox */ /* UNIMPLEMENTED sequence-num = nz-number / "*" ; * is the largest number in use. For message ; sequence numbers, it is the number of messages ; in the mailbox. For unique identifiers, it is ; the unique identifier of the last message in ; the mailbox. */ /* UNIMPLEMENTED set = sequence-num / (sequence-num ":" sequence-num) / (set "," set) ; Identifies a set of messages. For message ; sequence numbers, these are consecutive ; numbers from 1 to the number of messages in ; the mailbox ; Comma delimits individual numbers, colon ; delimits between two numbers inclusive. ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13, ; 14,15 for a mailbox with 15 messages. */ /* UNIMPLEMENTED status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")" */ /* status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / "UNSEEN" */ static int mailimap_status_att_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result) { int type; size_t cur_token; cur_token = * index; type = mailimap_status_att_get_token_value(fd, buffer, &cur_token); if (type == -1) return MAILIMAP_ERROR_PARSE; * result = type; * index = cur_token; return MAILIMAP_NO_ERROR; } /* UNIMPLEMENTED store = "STORE" SP set SP store-att-flags */ /* UNIMPLEMENTED store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP (flag-list / (flag *(SP flag))) */ /* string = quoted / literal */ static int mailimap_string_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t * result_len, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; char * string; int r; size_t len; cur_token = * index; r = mailimap_quoted_parse(fd, buffer, &cur_token, &string, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) len = strlen(string); else if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_literal_parse(fd, buffer, &cur_token, &string, &len, progr_rate, progr_fun); } if (r != MAILIMAP_NO_ERROR) return r; * result = string; if (result_len != NULL) * result_len = len; * index = cur_token; return MAILIMAP_NO_ERROR; } /* UNIMPLEMENTED subscribe = "SUBSCRIBE" SP mailbox */ /* tag = 1* */ /* any ASTRING-CHAR except "+" */ static int is_tag_char(char ch) { if (ch == '+') return FALSE; return is_astring_char(ch); } /* tag = 1* */ static int mailimap_tag_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; char * tag; int r; cur_token = * index; r = mailimap_custom_string_parse(fd, buffer, &cur_token, &tag, is_tag_char); if (r != MAILIMAP_NO_ERROR) return r; * index = cur_token; * result = tag; return MAILIMAP_NO_ERROR; } /* text = 1*TEXT-CHAR */ static int mailimap_text_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_custom_string_parse(fd, buffer, index, result, is_text_char); } /* TEXT-CHAR = */ static int is_text_char(char ch) { if ((ch == '\r') || (ch == '\n')) return FALSE; return is_char(ch); } /* time = 2DIGIT ":" 2DIGIT ":" 2DIGIT ; Hours minutes seconds */ /* 2DIGIT */ static int mailimap_2digit_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result) { #ifndef UNSTRICT_SYNTAX int digit; int two_digit; size_t cur_token; int r; cur_token = * index; r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); if (r != MAILIMAP_NO_ERROR) return r; two_digit = digit; r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); if (r != MAILIMAP_NO_ERROR) return r; two_digit = two_digit * 10 + digit; * result = two_digit; * index = cur_token; return MAILIMAP_NO_ERROR; #else uint32_t number; size_t cur_token; int r; cur_token = * index; r = mailimap_number_parse(fd, buffer, &cur_token, &number); if (r != MAILIMAP_NO_ERROR) return r; * index = cur_token; * result = number; return MAILIMAP_NO_ERROR; #endif } /* time = 2DIGIT ":" 2DIGIT ":" 2DIGIT ; Hours minutes seconds */ static int mailimap_time_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * phour, int * pmin, int * psec) { size_t cur_token; int hour; int min; int sec; int r; cur_token = * index; r = mailimap_2digit_parse(fd, buffer, &cur_token, &hour); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_colon_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_2digit_parse(fd, buffer, &cur_token, &min); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_colon_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) return r; r = mailimap_2digit_parse(fd, buffer, &cur_token, &sec); if (r != MAILIMAP_NO_ERROR) return r; * phour = hour; * pmin = min; * psec = sec; * index = cur_token; return MAILIMAP_NO_ERROR; } /* UNIMPLEMENTED uid = "UID" SP (copy / fetch / search / store) ; Unique identifiers used instead of message ; sequence numbers */ /* uniqueid = nz-number ; Strictly ascending */ static int mailimap_uniqueid_parse(mailstream * fd, MMAPString * buffer, size_t * index, uint32_t * result) { return mailimap_nz_number_parse(fd, buffer, index, result); } /* UNIMPLEMENTED unsubscribe = "UNSUBSCRIBE" SP mailbox */ /* UNIMPLEMENTED userid = astring */ /* UNIMPLEMENTED x-command = "X" atom */ /* zone = ("+" / "-") 4DIGIT ; Signed four-digit value of hhmm representing ; hours and minutes east of Greenwich (that is, ; the amount that the given time differs from ; Universal Time). Subtracting the timezone ; from the given time will give the UT form. ; The Universal Time zone is "+0000". */ static int mailimap_zone_parse(mailstream * fd, MMAPString * buffer, size_t * index, int * result) { size_t cur_token; uint32_t zone; #ifndef UNSTRICT_SYNTAX int i; int digit; #endif int sign; int r; cur_token = * index; sign = 1; r = mailimap_plus_parse(fd, buffer, &cur_token); if (r == MAILIMAP_NO_ERROR) sign = 1; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_minus_parse(fd, buffer, &cur_token); if (r == MAILIMAP_NO_ERROR) sign = -1; } if (r != MAILIMAP_NO_ERROR) return r; #ifdef UNSTRICT_SYNTAX r = mailimap_number_parse(fd, buffer, &cur_token, &zone); if (r != MAILIMAP_NO_ERROR) return r; #else zone = 0; for(i = 0 ; i < 4 ; i ++) { r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); if (r != MAILIMAP_NO_ERROR) return r; zone = zone * 10 + digit; } #endif zone *= sign; * result = zone; * index = cur_token; return MAILIMAP_NO_ERROR; }