22 files changed, 26161 insertions, 0 deletions
diff --git a/kmicromail/libetpan/imap/.libs/libmailimap.a b/kmicromail/libetpan/imap/.libs/libmailimap.a Binary files differnew file mode 100644 index 0000000..c98f6a7 --- a/dev/null +++ b/kmicromail/libetpan/imap/.libs/libmailimap.a diff --git a/kmicromail/libetpan/imap/TODO b/kmicromail/libetpan/imap/TODO new file mode 100644 index 0000000..a787a3b --- a/dev/null +++ b/kmicromail/libetpan/imap/TODO @@ -0,0 +1,4 @@ +- literal data send progress +- implement draft-16 (rfc 2822 things) +- more efficient parser + diff --git a/kmicromail/libetpan/imap/mailimap.c b/kmicromail/libetpan/imap/mailimap.c new file mode 100644 index 0000000..c8fbfee --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap.c @@ -0,0 +1,2161 @@ +/* + * 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 "mailimap.h" +#include "mailimap_parser.h" +#include "mailimap_sender.h" +#include "mail.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef DEBUG +#include "mailimap_print.h" +#endif + +/* + RFC 2060 : IMAP4rev1 + draft-crispin-imapv-15 + RFC 2222 : Simple Authentication and Security Layer + +2061 IMAP4 Compatibility with IMAP2bis. M. Crispin. December 1996. + (Format: TXT=5867 bytes) (Obsoletes RFC1730) (Status: INFORMATIONAL) + +2062 Internet Message Access Protocol - Obsolete Syntax. M. Crispin. + December 1996. (Format: TXT=14222 bytes) (Status: INFORMATIONAL) + +2086 IMAP4 ACL extension. J. Myers. January 1997. (Format: TXT=13925 + bytes) (Status: PROPOSED STANDARD) + +2087 IMAP4 QUOTA extension. J. Myers. January 1997. (Format: TXT=8542 + bytes) (Status: PROPOSED STANDARD) + +2088 IMAP4 non-synchronizing literals. J. Myers. January 1997. + (Format: TXT=4052 bytes) (Status: PROPOSED STANDARD) + +2177 IMAP4 IDLE command. B. Leiba. June 1997. (Format: TXT=6770 bytes) + (Status: PROPOSED STANDARD) + +2180 IMAP4 Multi-Accessed Mailbox Practice. M. Gahrns. July 1997. + (Format: TXT=24750 bytes) (Status: INFORMATIONAL) + +2192 IMAP URL Scheme. C. Newman. September 1997. (Format: TXT=31426 + bytes) (Status: PROPOSED STANDARD) + +2193 IMAP4 Mailbox Referrals. M. Gahrns. September 1997. (Format: + TXT=16248 bytes) (Status: PROPOSED STANDARD) + +2195 IMAP/POP AUTHorize Extension for Simple Challenge/Response. J. + Klensin, R. Catoe, P. Krumviede. September 1997. (Format: TXT=10468 + bytes) (Obsoletes RFC2095) (Status: PROPOSED STANDARD) + +2221 IMAP4 Login Referrals. M. Gahrns. October 1997. (Format: TXT=9251 + bytes) (Status: PROPOSED STANDARD) + +2342 IMAP4 Namespace. M. Gahrns, C. Newman. May 1998. (Format: + TXT=19489 bytes) (Status: PROPOSED STANDARD) + +2359 IMAP4 UIDPLUS extension. J. Myers. June 1998. (Format: TXT=10862 + bytes) (Status: PROPOSED STANDARD) + +2595 Using TLS with IMAP, POP3 and ACAP. C. Newman. June 1999. + (Format: TXT=32440 bytes) (Status: PROPOSED STANDARD) + +2683 IMAP4 Implementation Recommendations. B. Leiba. September 1999. + (Format: TXT=56300 bytes) (Status: INFORMATIONAL) + +2971 IMAP4 ID extension. T. Showalter. October 2000. (Format: + TXT=14670 bytes) (Status: PROPOSED STANDARD) + +http://www.ietf.org/ids.by.wg/imapext.html +*/ + +static char * read_line(mailimap * session); + +static int send_current_tag(mailimap * session); + +static int parse_response(mailimap * session, + struct mailimap_response ** result); + +static int parse_greeting(mailimap * session, + struct mailimap_greeting ** result); + + +/* struct mailimap_response_info * */ + +static void resp_text_store(mailimap * session, + struct mailimap_resp_text * + resp_text) +{ + struct mailimap_resp_text_code * resp_text_code; + + resp_text_code = resp_text->rsp_code; + + if (resp_text_code != NULL) { + switch (resp_text_code->rc_type) { + case MAILIMAP_RESP_TEXT_CODE_ALERT: + if (session->imap_response_info) + if (session->imap_response_info->rsp_alert != NULL) + free(session->imap_response_info->rsp_alert); + session->imap_response_info->rsp_alert = strdup(resp_text->rsp_text); + break; + + case MAILIMAP_RESP_TEXT_CODE_BADCHARSET: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_badcharset != NULL) { + clist_foreach(resp_text_code->rc_data.rc_badcharset, + (clist_func) mailimap_astring_free, NULL); + clist_free(resp_text_code->rc_data.rc_badcharset); + } + session->imap_response_info->rsp_badcharset = + resp_text_code->rc_data.rc_badcharset; + resp_text_code->rc_data.rc_badcharset = NULL; + } + break; + + case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA: + if (session->imap_connection_info) { + if (session->imap_connection_info->imap_capability != NULL) + mailimap_capability_data_free(session->imap_connection_info->imap_capability); + session->imap_connection_info->imap_capability = + resp_text_code->rc_data.rc_cap_data; + /* detach before free */ + resp_text_code->rc_data.rc_cap_data = NULL; + } + break; + + case MAILIMAP_RESP_TEXT_CODE_PARSE: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_parse != NULL) + free(session->imap_response_info->rsp_parse); + session->imap_response_info->rsp_parse = strdup(resp_text->rsp_text); + } + break; + + case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS: + if (session->imap_selection_info) { + if (session->imap_selection_info->sel_perm_flags != NULL) { + clist_foreach(session->imap_selection_info->sel_perm_flags, + (clist_func) mailimap_flag_perm_free, NULL); + clist_free(session->imap_selection_info->sel_perm_flags); + } + session->imap_selection_info->sel_perm_flags = + resp_text_code->rc_data.rc_perm_flags; + /* detach before free */ + resp_text_code->rc_data.rc_perm_flags = NULL; + } + break; + + case MAILIMAP_RESP_TEXT_CODE_READ_ONLY: + if (session->imap_selection_info) + session->imap_selection_info->sel_perm = MAILIMAP_MAILBOX_READONLY; + break; + + case MAILIMAP_RESP_TEXT_CODE_READ_WRITE: + if (session->imap_selection_info) + session->imap_selection_info->sel_perm = MAILIMAP_MAILBOX_READWRITE; + break; + + case MAILIMAP_RESP_TEXT_CODE_TRY_CREATE: + if (session->imap_response_info) + session->imap_response_info->rsp_trycreate = TRUE; + break; + + case MAILIMAP_RESP_TEXT_CODE_UIDNEXT: + if (session->imap_selection_info) + session->imap_selection_info->sel_uidnext = + resp_text_code->rc_data.rc_uidnext; + break; + + case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY: + if (session->imap_selection_info) + session->imap_selection_info->sel_uidvalidity = + resp_text_code->rc_data.rc_uidvalidity; + break; + + case MAILIMAP_RESP_TEXT_CODE_UNSEEN: + if (session->imap_selection_info) + session->imap_selection_info->sel_first_unseen = + resp_text_code->rc_data.rc_first_unseen; + break; + } + } +} + +static void resp_cond_state_store(mailimap * session, + struct mailimap_resp_cond_state * resp_cond_state) +{ + resp_text_store(session, resp_cond_state->rsp_text); +} + +static void mailbox_data_store(mailimap * session, + struct mailimap_mailbox_data * mb_data) +{ + int r; + + switch (mb_data->mbd_type) { + case MAILIMAP_MAILBOX_DATA_FLAGS: + if (session->imap_selection_info) { + if (session->imap_selection_info->sel_flags != NULL) + mailimap_flag_list_free(session->imap_selection_info->sel_flags); + session->imap_selection_info->sel_flags = mb_data->mbd_data.mbd_flags; + mb_data->mbd_data.mbd_flags = NULL; + } + break; + + case MAILIMAP_MAILBOX_DATA_LIST: + if (session->imap_response_info) { + r = clist_append(session->imap_response_info->rsp_mailbox_list, + mb_data->mbd_data.mbd_list); + if (r == 0) + mb_data->mbd_data.mbd_list = NULL; + else { + /* TODO must handle error case */ + } + } + break; + + case MAILIMAP_MAILBOX_DATA_LSUB: + if (session->imap_response_info) { + r = clist_append(session->imap_response_info->rsp_mailbox_lsub, + mb_data->mbd_data.mbd_lsub); + if (r == 0) + mb_data->mbd_data.mbd_lsub = NULL; + else { + /* TODO must handle error case */ + } + } + break; + + case MAILIMAP_MAILBOX_DATA_SEARCH: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_search_result != NULL) { + if (mb_data->mbd_data.mbd_search != NULL) { + clist_concat(session->imap_response_info->rsp_search_result, + mb_data->mbd_data.mbd_search); + clist_free(mb_data->mbd_data.mbd_search); + mb_data->mbd_data.mbd_search = NULL; + } + } + else { + if (mb_data->mbd_data.mbd_search != NULL) { + session->imap_response_info->rsp_search_result = + mb_data->mbd_data.mbd_search; + mb_data->mbd_data.mbd_search = NULL; + } + } + } + break; + + case MAILIMAP_MAILBOX_DATA_STATUS: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_status != NULL) + mailimap_mailbox_data_status_free(session->imap_response_info->rsp_status); + session->imap_response_info->rsp_status = mb_data->mbd_data.mbd_status; +#if 0 + if (session->imap_selection_info != NULL) { + clistiter * cur; + + for(cur = clist_begin(mb_data->status->status_info_list) + ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_status_info * info; + + info = clist_content(cur); + switch (info->att) { + case MAILIMAP_STATUS_ATT_MESSAGES: + session->imap_selection_info->exists = info->value; + break; + case MAILIMAP_STATUS_ATT_RECENT: + session->imap_selection_info->recent = info->value; + break; + case MAILIMAP_STATUS_ATT_UIDNEXT: + session->imap_selection_info->uidnext = info->value; + break; + case MAILIMAP_STATUS_ATT_UIDVALIDITY: + session->imap_selection_info->uidvalidity = info->value; + break; + case MAILIMAP_STATUS_ATT_UNSEEN: + session->imap_selection_info->unseen = info->value; + break; + } + } + } +#endif +#if 0 + mailimap_mailbox_data_status_free(mb_data->status); +#endif + mb_data->mbd_data.mbd_status = NULL; + } + break; + + case MAILIMAP_MAILBOX_DATA_EXISTS: + if (session->imap_selection_info) + session->imap_selection_info->sel_exists = mb_data->mbd_data.mbd_exists; + break; + + case MAILIMAP_MAILBOX_DATA_RECENT: + if (session->imap_selection_info) + session->imap_selection_info->sel_recent = + mb_data->mbd_data.mbd_recent; + break; + } +} + +static void +message_data_store(mailimap * session, + struct mailimap_message_data * msg_data) +{ + uint32_t * expunged; + int r; + + switch (msg_data->mdt_type) { + case MAILIMAP_MESSAGE_DATA_EXPUNGE: + if (session->imap_response_info) { + expunged = mailimap_number_alloc_new(msg_data->mdt_number); + if (expunged != NULL) { + r = clist_append(session->imap_response_info->rsp_expunged, expunged); + if (r == 0) { + /* do nothing */ + } + else { + /* TODO : must handle error case */ + mailimap_number_alloc_free(expunged); + } + if (session->imap_selection_info != NULL) + session->imap_selection_info->sel_exists --; + } + } + break; + + case MAILIMAP_MESSAGE_DATA_FETCH: + r = clist_append(session->imap_response_info->rsp_fetch_list, + msg_data->mdt_msg_att); + if (r == 0) { + msg_data->mdt_msg_att->att_number = msg_data->mdt_number; + msg_data->mdt_msg_att = NULL; + } + else { + /* TODO : must handle error case */ + } + break; + } +} + +static void +cont_req_or_resp_data_store(mailimap * session, + struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data) +{ + if (cont_req_or_resp_data->rsp_type == MAILIMAP_RESP_RESP_DATA) { + struct mailimap_response_data * resp_data; + + resp_data = cont_req_or_resp_data->rsp_data.rsp_resp_data; + + switch (resp_data->rsp_type) { + case MAILIMAP_RESP_DATA_TYPE_COND_STATE: + resp_cond_state_store(session, resp_data->rsp_data.rsp_cond_state); + break; + case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA: + mailbox_data_store(session, resp_data->rsp_data.rsp_mailbox_data); + break; + case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA: + message_data_store(session, resp_data->rsp_data.rsp_message_data); + break; + case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA: + if (session->imap_connection_info) { + if (session->imap_connection_info->imap_capability != NULL) + mailimap_capability_data_free(session->imap_connection_info->imap_capability); + session->imap_connection_info->imap_capability = resp_data->rsp_data.rsp_capability_data; + resp_data->rsp_data.rsp_capability_data = NULL; + } + break; + } + } +} + +static void response_tagged_store(mailimap * session, + struct mailimap_response_tagged * tagged) +{ + resp_cond_state_store(session, tagged->rsp_cond_state); +} + +static void resp_cond_bye_store(mailimap * session, + struct mailimap_resp_cond_bye * resp_cond_bye) +{ + resp_text_store(session, resp_cond_bye->rsp_text); +} + +static void response_fatal_store(mailimap * session, + struct mailimap_response_fatal * fatal) +{ + resp_cond_bye_store(session, fatal->rsp_bye); +} + +static void response_done_store(mailimap * session, + struct mailimap_response_done * resp_done) +{ + switch(resp_done->rsp_type) { + case MAILIMAP_RESP_DONE_TYPE_TAGGED: + response_tagged_store(session, resp_done->rsp_data.rsp_tagged); + break; + case MAILIMAP_RESP_DONE_TYPE_FATAL: + response_fatal_store(session, resp_done->rsp_data.rsp_fatal); + break; + } +} + +static void +response_store(mailimap * session, + struct mailimap_response * response) +{ + clistiter * cur; + + if (session->imap_response_info) { + mailimap_response_info_free(session->imap_response_info); + session->imap_response_info = NULL; + } + + session->imap_response_info = mailimap_response_info_new(); + if (session->imap_response_info == NULL) { + /* ignored error */ + return; + } + + if (response->rsp_cont_req_or_resp_data_list != NULL) { + for(cur = clist_begin(response->rsp_cont_req_or_resp_data_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data; + + cont_req_or_resp_data = clist_content(cur); + + cont_req_or_resp_data_store(session, cont_req_or_resp_data); + } + } + + response_done_store(session, response->rsp_resp_done); +} + +static void resp_cond_auth_store(mailimap * session, + struct mailimap_resp_cond_auth * cond_auth) +{ + resp_text_store(session, cond_auth->rsp_text); +} + +static void greeting_store(mailimap * session, + struct mailimap_greeting * greeting) +{ + switch (greeting->gr_type) { + case MAILIMAP_GREETING_RESP_COND_AUTH: + resp_cond_auth_store(session, greeting->gr_data.gr_auth); + break; + + case MAILIMAP_GREETING_RESP_COND_BYE: + resp_cond_bye_store(session, greeting->gr_data.gr_bye); + break; + } +} + +int mailimap_connect(mailimap * session, mailstream * s) +{ + struct mailimap_greeting * greeting; + int r; + int auth_type; + struct mailimap_connection_info * connection_info; + + if (session->imap_state != MAILIMAP_STATE_DISCONNECTED) + return MAILIMAP_ERROR_BAD_STATE; + + session->imap_stream = s; + + if (session->imap_connection_info) + mailimap_connection_info_free(session->imap_connection_info); + connection_info = mailimap_connection_info_new(); + if (connection_info != NULL) + session->imap_connection_info = connection_info; + + if (read_line(session) == NULL) { + return MAILIMAP_ERROR_STREAM; + } + + r = parse_greeting(session, &greeting); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + auth_type = greeting->gr_data.gr_auth->rsp_type; + + mailimap_greeting_free(greeting); + + switch (auth_type) { + case MAILIMAP_RESP_COND_AUTH_PREAUTH: + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_NO_ERROR_AUTHENTICATED; + default: + session->imap_state = MAILIMAP_STATE_NON_AUTHENTICATED; + return MAILIMAP_NO_ERROR_NON_AUTHENTICATED; + } +} + + + + + + + + +/* ********************************************************************** */ + + + +int mailimap_append(mailimap * session, const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + const char * literal, size_t literal_size) +{ + struct mailimap_response * response; + int r; + int error_code; + struct mailimap_continue_req * cont_req; + size_t index; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_append_send(session->imap_stream, mailbox, flag_list, date_time, + literal_size); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + index = 0; + + r = mailimap_continue_req_parse(session->imap_stream, + session->imap_stream_buffer, + &index, &cont_req, + session->imap_progr_rate, session->imap_progr_fun); + if (r == MAILIMAP_NO_ERROR) + mailimap_continue_req_free(cont_req); + + if (r == MAILIMAP_ERROR_PARSE) { + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + mailimap_response_free(response); + + return MAILIMAP_ERROR_APPEND; + } + + r = mailimap_literal_data_send(session->imap_stream, literal, literal_size, + session->imap_progr_rate, session->imap_progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_APPEND; + } +} + +/* +gboolean mailimap_authenticate(mailimap * session, + gchar * auth_type) +{ +} + +gboolean mailimap_authenticate_resp_send(mailimap * session, + gchar * base64) +{ +} +*/ + +int mailimap_noop(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_noop_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_NOOP; + } +} + +int mailimap_logout(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + int res; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto close; + } + + r = mailimap_logout_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto close; + } + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto close; + } + + if (mailstream_flush(session->imap_stream) == -1) { + res = MAILIMAP_ERROR_STREAM; + goto close; + } + + if (read_line(session) == NULL) { + res = MAILIMAP_ERROR_STREAM; + goto close; + } + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto close; + } + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + if (session->imap_connection_info) { + mailimap_connection_info_free(session->imap_connection_info); + session->imap_connection_info = NULL; + } + res = MAILIMAP_NO_ERROR; + goto close; + + default: + res = MAILIMAP_ERROR_LOGOUT; + goto close; + } + + close: + mailstream_close(session->imap_stream); + session->imap_stream = NULL; + session->imap_state = MAILIMAP_STATE_DISCONNECTED; + return res; +} + +/* send the results back to the caller */ +/* duplicate the result */ + +static struct mailimap_capability * +mailimap_capability_dup(struct mailimap_capability * orig_cap) +{ + struct mailimap_capability * cap; + char * auth_type; + char * name; + + name = NULL; + auth_type = NULL; + switch (orig_cap->cap_type) { + case MAILIMAP_CAPABILITY_NAME: + name = strdup(orig_cap->cap_data.cap_name); + if (name == NULL) + goto err; + break; + case MAILIMAP_CAPABILITY_AUTH_TYPE: + auth_type = strdup(orig_cap->cap_data.cap_auth_type); + if (auth_type == NULL) + goto err; + break; + } + + cap = mailimap_capability_new(orig_cap->cap_type, auth_type, name); + if (cap == NULL) + goto free; + + return cap; + + free: + if (name != NULL) + free(name); + if (auth_type != NULL) + free(auth_type); + err: + return NULL; +} + +static struct mailimap_capability_data * +mailimap_capability_data_dup(struct mailimap_capability_data * orig_cap_data) +{ + struct mailimap_capability_data * cap_data; + struct mailimap_capability * cap_dup; + clist * list; + clistiter * cur; + int r; + + list = clist_new(); + if (list == NULL) + goto err; + + for(cur = clist_begin(orig_cap_data->cap_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_capability * cap; + + cap = clist_content(cur); + + cap_dup = mailimap_capability_dup(cap); + if (cap_dup == NULL) + goto list; + + r = clist_append(list, cap_dup); + if (r < 0) { + mailimap_capability_free(cap_dup); + goto list; + } + } + + cap_data = mailimap_capability_data_new(list); + if (cap_data == NULL) + goto list; + + return cap_data; + +list: + clist_foreach(list, (clist_func) mailimap_capability_free, NULL); + clist_free(list); +err: + return NULL; +} + +int mailimap_capability(mailimap * session, + struct mailimap_capability_data ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + struct mailimap_capability_data * cap_data; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_capability_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + cap_data = + mailimap_capability_data_dup(session->imap_connection_info->imap_capability); + if (cap_data == NULL) + return MAILIMAP_ERROR_MEMORY; + + * result = cap_data; + + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CAPABILITY; + } +} + +int mailimap_check(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_check_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CHECK; + } +} + +int mailimap_close(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_close_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + /* leave selected state */ + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = NULL; + + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CLOSE; + } +} + +int mailimap_expunge(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_expunge_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXPUNGE; + } +} + +int mailimap_copy(mailimap * session, struct mailimap_set * set, + const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_copy_send(session->imap_stream, set, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_COPY; + } +} + +int mailimap_uid_copy(mailimap * session, struct mailimap_set * set, + const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_copy_send(session->imap_stream, set, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UID_COPY; + } +} + +int mailimap_create(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_create_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CREATE; + } +} + + +int mailimap_delete(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_delete_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_DELETE; + } +} + +int mailimap_examine(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_examine_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + if (session->imap_selection_info != NULL) + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = mailimap_selection_info_new(); + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + session->imap_state = MAILIMAP_STATE_SELECTED; + return MAILIMAP_NO_ERROR; + + default: + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = NULL; + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_ERROR_EXAMINE; + } +} + +int +mailimap_fetch(mailimap * session, struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fetch_send(session->imap_stream, set, fetch_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_fetch_list; + session->imap_response_info->rsp_fetch_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_FETCH; + } +} + +void mailimap_fetch_list_free(clist * fetch_list) +{ + clist_foreach(fetch_list, (clist_func) mailimap_msg_att_free, NULL); + clist_free(fetch_list); +} + +int +mailimap_uid_fetch(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_fetch_send(session->imap_stream, set, fetch_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_fetch_list; + session->imap_response_info->rsp_fetch_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UID_FETCH; + } +} + +int mailimap_list(mailimap * session, const char * mb, + const char * list_mb, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_list_send(session->imap_stream, mb, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_mailbox_list; + session->imap_response_info->rsp_mailbox_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_LIST; + } +} + +int mailimap_login(mailimap * session, + const char * userid, const char * password) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_NON_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_login_send(session->imap_stream, userid, password); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_LOGIN; + } +} + +int mailimap_lsub(mailimap * session, const char * mb, + const char * list_mb, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_lsub_send(session->imap_stream, mb, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_mailbox_lsub; + session->imap_response_info->rsp_mailbox_lsub = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_LSUB; + } +} + +void mailimap_list_result_free(clist * list) +{ + clist_foreach(list, (clist_func) mailimap_mailbox_list_free, NULL); + clist_free(list); +} + +int mailimap_rename(mailimap * session, + const char * mb, const char * new_name) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_rename_send(session->imap_stream, mb, new_name); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (!mailimap_crlf_send(session->imap_stream)) + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_RENAME; + } +} + +int +mailimap_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_search_send(session->imap_stream, charset, key); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_search_result; + session->imap_response_info->rsp_search_result = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_SEARCH; + } +} + +int +mailimap_uid_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_search_send(session->imap_stream, charset, key); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_search_result; + session->imap_response_info->rsp_search_result = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UID_SEARCH; + } +} + +void mailimap_search_result_free(clist * search_result) +{ + clist_foreach(search_result, (clist_func) free, NULL); + clist_free(search_result); +} + +int +mailimap_select(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_select_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + if (session->imap_selection_info != NULL) + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = mailimap_selection_info_new(); + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + session->imap_state = MAILIMAP_STATE_SELECTED; + return MAILIMAP_NO_ERROR; + + default: + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = NULL; + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_ERROR_SELECT; + } +} + +int +mailimap_status(mailimap * session, const char * mb, + struct mailimap_status_att_list * status_att_list, + struct mailimap_mailbox_data_status ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_status_send(session->imap_stream, mb, status_att_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_status; + session->imap_response_info->rsp_status = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_STATUS; + } +} + + +int +mailimap_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_store_send(session->imap_stream, set, store_att_flags); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_STORE; + } +} + +int +mailimap_uid_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_store_send(session->imap_stream, set, store_att_flags); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UID_STORE; + } +} + +int mailimap_subscribe(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_subscribe_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_SUBSCRIBE; + } +} + +int mailimap_unsubscribe(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_subscribe_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UNSUBSCRIBE; + } +} + + +int mailimap_starttls(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_starttls_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_STARTTLS; + } +} + + + +static char * read_line(mailimap * session) +{ + return mailstream_read_line(session->imap_stream, session->imap_stream_buffer); +} + +static int send_current_tag(mailimap * session) +{ + char tag_str[15]; + int r; + + session->imap_tag ++; + snprintf(tag_str, 15, "%i", session->imap_tag); + + r = mailimap_tag_send(session->imap_stream, tag_str); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int parse_response(mailimap * session, + struct mailimap_response ** result) +{ + size_t index; + struct mailimap_response * response; + char tag_str[15]; + int r; + + index = 0; + + session->imap_response = NULL; + + r = mailimap_response_parse(session->imap_stream, + session->imap_stream_buffer, + &index, &response, + session->imap_progr_rate, session->imap_progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + +#if 0 + mailimap_response_print(response); +#endif + + response_store(session, response); + + if (mmap_string_assign(session->imap_response_buffer, + response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_text->rsp_text) + == NULL) + return MAILIMAP_ERROR_MEMORY; + + session->imap_response = session->imap_response_buffer->str; + + if (response->rsp_resp_done->rsp_type == MAILIMAP_RESP_DONE_TYPE_FATAL) + return MAILIMAP_ERROR_FATAL; + + snprintf(tag_str, 15, "%i", session->imap_tag); + if (strcmp(response->rsp_resp_done->rsp_data.rsp_tagged->rsp_tag, tag_str) != 0) + return MAILIMAP_ERROR_PROTOCOL; + + if (response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type == + MAILIMAP_RESP_COND_STATE_BAD) + return MAILIMAP_ERROR_PROTOCOL; + + * result = response; + + return MAILIMAP_NO_ERROR; +} + + +static int parse_greeting(mailimap * session, + struct mailimap_greeting ** result) +{ + size_t index; + struct mailimap_greeting * greeting; + int r; + + index = 0; + + session->imap_response = NULL; + + r = mailimap_greeting_parse(session->imap_stream, + session->imap_stream_buffer, + &index, &greeting, session->imap_progr_rate, + session->imap_progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + +#if 0 + mailimap_greeting_print(greeting); +#endif + + greeting_store(session, greeting); + + if (greeting->gr_type == MAILIMAP_GREETING_RESP_COND_BYE) { + if (mmap_string_assign(session->imap_response_buffer, + greeting->gr_data.gr_bye->rsp_text->rsp_text) == NULL) + return MAILIMAP_ERROR_MEMORY; + + session->imap_response = session->imap_response_buffer->str; + + return MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION; + } + + if (mmap_string_assign(session->imap_response_buffer, + greeting->gr_data.gr_auth->rsp_text->rsp_text) == NULL) + return MAILIMAP_ERROR_MEMORY; + + session->imap_response = session->imap_response_buffer->str; + + * result = greeting; + + return MAILIMAP_NO_ERROR; +} + + +mailimap * mailimap_new(size_t imap_progr_rate, + progress_function * imap_progr_fun) +{ + mailimap * f; + + f = malloc(sizeof(* f)); + if (f == NULL) + goto err; + + f->imap_response = NULL; + + f->imap_stream = NULL; + + f->imap_progr_rate = imap_progr_rate; + f->imap_progr_fun = imap_progr_fun; + + f->imap_stream_buffer = mmap_string_new(""); + if (f->imap_stream_buffer == NULL) + goto free_f; + + f->imap_response_buffer = mmap_string_new(""); + if (f->imap_response_buffer == NULL) + goto free_stream_buffer; + + f->imap_state = MAILIMAP_STATE_DISCONNECTED; + f->imap_tag = 0; + + f->imap_selection_info = NULL; + f->imap_response_info = NULL; + f->imap_connection_info = NULL; + + return f; + + free_stream_buffer: + mmap_string_free(f->imap_stream_buffer); + free_f: + free(f); + err: + return NULL; +} + +void mailimap_free(mailimap * session) +{ + if (session->imap_stream) + mailimap_logout(session); + + mmap_string_free(session->imap_response_buffer); + mmap_string_free(session->imap_stream_buffer); + + if (session->imap_response_info) + mailimap_response_info_free(session->imap_response_info); + if (session->imap_selection_info) + mailimap_selection_info_free(session->imap_selection_info); + if (session->imap_connection_info) + mailimap_connection_info_free(session->imap_connection_info); + + free(session); +} diff --git a/kmicromail/libetpan/imap/mailimap.h b/kmicromail/libetpan/imap/mailimap.h new file mode 100644 index 0000000..8dfa3d4 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap.h @@ -0,0 +1,598 @@ +/* + * 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$ + */ + +#ifndef MAILIMAP_H + +#define MAILIMAP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailimap_types.h> +#include <libetpan/mailimap_types_helper.h> +#include <libetpan/mailimap_helper.h> + +#include <libetpan/mailimap_socket.h> +#include <libetpan/mailimap_ssl.h> + +/* + mailimap_connect() + + This function will connect the IMAP session with the given stream. + + @param session the IMAP session + @param s stream to use + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + + note that on success, MAILIMAP_NO_ERROR_AUTHENTICATED or + MAILIMAP_NO_ERROR_NON_AUTHENTICATED is returned + + MAILIMAP_NO_ERROR_NON_AUTHENTICATED is returned when you need to + use mailimap_login() to authenticate, else + MAILIMAP_NO_ERROR_AUTHENTICATED is returned. +*/ + +int mailimap_connect(mailimap * session, mailstream * s); + +/* + mailimap_append() + + This function will append a given message to the given mailbox + by sending an APPEND command. + + @param session the IMAP session + @param mailbox name of the mailbox + @param flag_list flags of the message + @param date_time timestamp of the message + @param literal content of the message + @param literal_size size of the message + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_append(mailimap * session, const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + const char * literal, size_t literal_size); + +/* + mailimap_noop() + + This function will poll for an event on the server by + sending a NOOP command to the IMAP server + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR_XXX codes +*/ + +int mailimap_noop(mailimap * session); + +/* + mailimap_logout() + + This function will logout from an IMAP server by sending + a LOGOUT command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_logout(mailimap * session); + +/* + mailimap_capability() + + This function will query an IMAP server for his capabilities + by sending a CAPABILITY command. + + @param session IMAP session + @param result The result of this command is a list of + capabilities and it is stored into (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +int mailimap_capability(mailimap * session, + struct mailimap_capability_data ** result); + +/* + mailimap_check() + + This function will request for a checkpoint of the mailbox by + sending a CHECK command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +int mailimap_check(mailimap * session); + +/* + mailimap_close() + + This function will close the selected mailbox by sending + a CLOSE command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +int mailimap_close(mailimap * session); + +/* + mailimap_expunge() + + This function will permanently remove from the selected mailbox + message that have the \Deleted flag set. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_expunge(mailimap * session); + +/* + mailimap_copy() + + This function will copy the given messages from the selected mailbox + to the given mailbox. + + @param session IMAP session + @param set This is a set of message numbers. + @param mb This is the destination mailbox. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +int mailimap_copy(mailimap * session, struct mailimap_set * set, + const char * mb); + +/* + mailimap_uid_copy() + + This function will copy the given messages from the selected mailbox + to the given mailbox. + + @param session IMAP session + @param set This is a set of message unique identifiers. + @param mb This is the destination mailbox. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +int mailimap_uid_copy(mailimap * session, + struct mailimap_set * set, const char * mb); + +/* + mailimap_create() + + This function will create a mailbox. + + @param session IMAP session + @param mb This is the name of the mailbox to create. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_create(mailimap * session, const char * mb); + +/* + mailimap_delete() + + This function will delete a mailox. + + @param session IMAP session + @param mb This is the name of the mailbox to delete. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_delete(mailimap * session, const char * mb); + +/* + mailimap_examine() + + This function will select the mailbox for read-only operations. + + @param session IMAP session + @param mb This is the name of the mailbox to select. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_examine(mailimap * session, const char * mb); + +/* + mailimap_fetch() + + This function will retrieve data associated with the given message + numbers. + + @param session IMAP session + @param set set of message numbers + @param fetch_type type of information to be retrieved + @param result The result of this command is a clist + and it is stored into (* result). Each element of the clist is a + (struct mailimap_msg_att *). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_fetch(mailimap * session, struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result); + +/* + mailimap_fetch() + + This function will retrieve data associated with the given message + numbers. + + @param session IMAP session + @param set set of message unique identifiers + @param fetch_type type of information to be retrieved + @param result The result of this command is a clist + and it is stored into (* result). Each element of the clist is a + (struct mailimap_msg_att *). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_uid_fetch(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result); + +/* + mailimap_fetch_list_free() + + This function will free the result of a fetch command. + + @param fetch_list This is the clist containing + (struct mailimap_msg_att *) elements to free. +*/ + +void mailimap_fetch_list_free(clist * fetch_list); + +/* + mailimap_list() + + This function will return the list of the mailbox + available on the server. + + @param session IMAP session + @param mb This is the reference name that informs + of the level of hierarchy + @param list_mb mailbox name with possible wildcard + @param result This will store a clist of (struct mailimap_mailbox_list *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_list(mailimap * session, const char * mb, + const char * list_mb, clist ** result); + +/* + mailimap_login() + + This function will authenticate the client. + + @param session IMAP session + @param userid login of the user + @param password password of the user + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_login(mailimap * session, + const char * userid, const char * password); + +/* + mailimap_lsub() + + This function will return the list of the mailbox + that the client has subscribed to. + + @param session IMAP session + @param mb This is the reference name that informs + of the level of hierarchy + @param list_mb mailbox name with possible wildcard + @param result This will store a list of (struct mailimap_mailbox_list *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_lsub(mailimap * session, const char * mb, + const char * list_mb, clist ** result); + +/* + mailimap_list_result_free() + + This function will free the clist of (struct mailimap_mailbox_list *) + + @param list This is the clist to free. +*/ + +void mailimap_list_result_free(clist * list); + +/* + mailimap_rename() + + This function will change the name of a mailbox. + + @param session IMAP session + @param mb current name + @param new_name new name + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_rename(mailimap * session, + const char * mb, const char * new_name); + +/* + mailimap_search() + + All mails that match the given criteria will be returned + their numbers in the result list. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result); + +/* + mailimap_uid_search() + + + All mails that match the given criteria will be returned + their unique identifiers in the result list. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_uid_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result); + +/* + mailimap_search_result_free() + + This function will free the result of the a search. + + @param search_result This is a clist of (uint32_t *) returned + by mailimap_uid_search() or mailimap_search() +*/ + +void mailimap_search_result_free(clist * search_result); + +/* + mailimap_select() + + This function will select a given mailbox so that messages in the + mailbox can be accessed. + + @param session IMAP session + @param mb This is the name of the mailbox to select. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_select(mailimap * session, const char * mb); + +/* + mailimap_status() + + This function will return informations about a given mailbox. + + @param session IMAP session + @param mb This is the name of the mailbox + @param status_att_list This is the list of mailbox information to return + @param result List of returned values + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_status(mailimap * session, const char * mb, + struct mailimap_status_att_list * status_att_list, + struct mailimap_mailbox_data_status ** result); + +/* + mailimap_uid_store() + + This function will alter the data associated with some messages + (flags of the messages). + + @param session IMAP session + @param set This is a list of message numbers. + @param store_att_flags This is the data to associate with the + given messages + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +/* + mailimap_uid_store() + + This function will alter the data associated with some messages + (flags of the messages). + + @param session IMAP session + @param set This is a list of message unique identifiers. + @param store_att_flags This is the data to associate with the + given messages + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int +mailimap_uid_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +/* + mailimap_subscribe() + + This function adds the specified mailbox name to the + server's set of "active" or "subscribed" mailboxes. + + @param session IMAP session + @param mb This is the name of the mailbox + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_subscribe(mailimap * session, const char * mb); + +/* + mailimap_unsubscribe() + + This function removes the specified mailbox name to the + server's set of "active" or "subscribed" mailboxes. + + @param session IMAP session + @param mb This is the name of the mailbox + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +int mailimap_unsubscribe(mailimap * session, const char * mb); + +/* + mailimap_starttls() + + This function starts change the mode of the connection to + switch to SSL connection. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR_XXX codes + */ + +int mailimap_starttls(mailimap * session); + +/* + mailimap_new() + + This function returns a new IMAP session. + + @param progr_rate When downloading messages, a function will be called + each time the amount of bytes downloaded reaches a multiple of this + value, this can be 0. + @param progr_fun This is the function to call to notify the progress, + this can be NULL. + + @return an IMAP session is returned. + */ + +mailimap * mailimap_new(size_t imap_progr_rate, + progress_function * imap_progr_fun); + +/* + mailimap_free() + + This function will free the data structures associated with + the IMAP session. + + @param session IMAP session + */ + +void mailimap_free(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imap/mailimap_helper.c b/kmicromail/libetpan/imap/mailimap_helper.c new file mode 100644 index 0000000..afc9098 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_helper.c @@ -0,0 +1,205 @@ +/* + * 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 "mailimap_helper.h" + +#include <stdlib.h> +#include "mailimap.h" + +int mailimap_fetch_rfc822(mailimap * session, + uint32_t msgid, char ** result) +{ + int r; + clist * fetch_list; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * item; + int res; + + fetch_att = mailimap_fetch_att_new_rfc822(); + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + set = mailimap_set_new_single(msgid); + + r = mailimap_fetch(session, set, fetch_type, &fetch_list); + + mailimap_set_free(set); + mailimap_fetch_type_free(fetch_type); + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (clist_isempty(fetch_list)) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + msg_att = (struct mailimap_msg_att *) clist_begin(fetch_list)->data; + + if (clist_isempty(msg_att->att_list)) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + item = (struct mailimap_msg_att_item *) clist_begin(msg_att->att_list)->data; + + if (item->att_type != MAILIMAP_MSG_ATT_ITEM_STATIC) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + if (item->att_data.att_static->att_type != MAILIMAP_MSG_ATT_RFC822) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + * result = item->att_data.att_static->att_data.att_rfc822.att_content; + item->att_data.att_static->att_data.att_rfc822.att_content = NULL; + mailimap_fetch_list_free(fetch_list); + + return MAILIMAP_NO_ERROR; + +free: + mailimap_fetch_list_free(fetch_list); +err: + return res; +} + +int mailimap_fetch_rfc822_header(mailimap * session, + uint32_t msgid, char ** result) +{ + int r; + int res; + clist * fetch_list; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * item; + + fetch_att = mailimap_fetch_att_new_rfc822_header(); + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + set = mailimap_set_new_single(msgid); + + r = mailimap_fetch(session, set, fetch_type, &fetch_list); + + mailimap_set_free(set); + mailimap_fetch_type_free(fetch_type); + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (clist_isempty(fetch_list)) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + msg_att = (struct mailimap_msg_att *) clist_begin(fetch_list)->data; + + if (clist_isempty(msg_att->att_list)) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + item = (struct mailimap_msg_att_item *) clist_begin(msg_att->att_list)->data; + + if (item->att_type != MAILIMAP_MSG_ATT_ITEM_STATIC) { + res = MAILIMAP_ERROR_FETCH; + goto err; + } + + if (item->att_data.att_static->att_type != MAILIMAP_MSG_ATT_RFC822_HEADER) { + res = MAILIMAP_ERROR_FETCH; + goto err; + } + + * result = item->att_data.att_static->att_data.att_rfc822_header.att_content; + item->att_data.att_static->att_data.att_rfc822_header.att_content = NULL; + mailimap_fetch_list_free(fetch_list); + + return MAILIMAP_NO_ERROR; + +free: + mailimap_fetch_list_free(fetch_list); +err: + return res; +} + +int mailimap_fetch_envelope(mailimap * session, + uint32_t first, uint32_t last, + clist ** result) +{ + int r; + clist * fetch_list; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + + fetch_att = mailimap_fetch_att_new_envelope(); + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + set = mailimap_set_new_interval(first, last); + + r = mailimap_fetch(session, set, fetch_type, &fetch_list); + + mailimap_set_free(set); + mailimap_fetch_type_free(fetch_type); + + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = fetch_list; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_append_simple(mailimap * session, char * mailbox, + char * content, uint32_t size) +{ + return mailimap_append(session, mailbox, NULL, NULL, content, size); +} + +int mailimap_login_simple(mailimap * session, + char * userid, char * password) +{ + if (session->imap_state == MAILIMAP_STATE_NON_AUTHENTICATED) + return mailimap_login(session, userid, password); + else + return MAILIMAP_NO_ERROR; +} + diff --git a/kmicromail/libetpan/imap/mailimap_helper.h b/kmicromail/libetpan/imap/mailimap_helper.h new file mode 100644 index 0000000..d73cf5f --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_helper.h @@ -0,0 +1,66 @@ +/* + * 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$ + */ + +#ifndef MAILIMAP_HELPER_H + +#define MAILIMAP_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailimap_types.h> + +int mailimap_fetch_rfc822(mailimap * session, + uint32_t msgid, char ** result); + +int mailimap_fetch_rfc822_header(mailimap * session, + uint32_t msgid, char ** result); + +int mailimap_fetch_envelope(mailimap * session, + uint32_t first, uint32_t last, + clist ** result); + +int mailimap_append_simple(mailimap * session, char * mailbox, + char * content, uint32_t size); + +int mailimap_login_simple(mailimap * session, + char * userid, char * password); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imap/mailimap_keywords.c b/kmicromail/libetpan/imap/mailimap_keywords.c new file mode 100644 index 0000000..b277aed --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_keywords.c @@ -0,0 +1,353 @@ +/* + * 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 "mailimap_keywords.h" +#include "mailimap_types.h" +#include <string.h> +#include <stdio.h> + +#ifndef UNSTRICT_SYNTAX +#define UNSTRICT_SYNTAX +#endif + +struct mailimap_token_value { + int value; + const char * str; +}; + +int mailimap_token_case_insensitive_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + const char * token) +{ + int len; + int cur_token; + int r; + + cur_token = * index; + len = strlen(token); + +#ifdef UNSTRICT_SYNTAX + r = mailimap_space_parse(fd, buffer, &cur_token); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; +#endif + + if (strncasecmp(buffer->str + cur_token, token, len) == 0) { + cur_token += len; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} + + +static int is_space_or_tab(char ch) +{ + return (ch == ' ') || (ch == '\t'); +} + +int mailimap_char_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char token) +{ + int cur_token; + + cur_token = * index; + + if (buffer->str[cur_token] == token) { + cur_token ++; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} + +int mailimap_space_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ +#ifdef UNSTRICT_SYNTAX + + /* can accept unstrict syntax */ + size_t cur_token; + + cur_token = * index; + + while (is_space_or_tab(* (buffer->str + cur_token))) + cur_token ++; + + if (cur_token == * index) + return MAILIMAP_ERROR_PARSE; + + * index = cur_token; + + return MAILIMAP_NO_ERROR; + +#else + return mailimap_char_parse(fd, buffer, index, ' '); +#endif +} + + + +#define mailimap_get_token_str(index, tab) \ + mailimap_get_token_str_size(index, tab, \ + sizeof(tab) / sizeof(struct mailimap_token_value)) + +#define mailimap_get_token_value(fd, buffer, index, tab) \ + mailimap_get_token_value_size(fd, buffer, index, tab, \ + sizeof(tab) / sizeof(struct mailimap_token_value)) + + +static const char * mailimap_get_token_str_size(int index, + struct mailimap_token_value * tab, + size_t size) +{ + size_t i; + + for(i = 0 ; i < size ; i++) + if (index == tab[i].value) + return tab[i].str; + + return NULL; +} + + + +static int mailimap_get_token_value_size(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_token_value * tab, + size_t size) +{ + size_t i; + int r; + +#ifdef UNSTRICT_SYNTAX + /* can accept unstrict syntax */ + r = mailimap_space_parse(fd, buffer, index); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; +#endif + + for(i = 0 ; i < size ; i++) { + r = mailimap_token_case_insensitive_parse(fd, buffer, index, tab[i].str); + if (r == MAILIMAP_NO_ERROR) + return tab[i].value; + } + + return -1; +} + + +static struct mailimap_token_value status_att_tab[] = { + {MAILIMAP_STATUS_ATT_MESSAGES, "MESSAGES"}, + {MAILIMAP_STATUS_ATT_RECENT, "RECENT"}, + {MAILIMAP_STATUS_ATT_UIDNEXT, "UIDNEXT"}, + {MAILIMAP_STATUS_ATT_UIDVALIDITY, "UIDVALIDITY"}, + {MAILIMAP_STATUS_ATT_UNSEEN, "UNSEEN"} +}; + +int mailimap_status_att_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + int r; + +#ifdef UNSTRICT_SYNTAX + /* can accept unstrict syntax */ + r = mailimap_space_parse(fd, buffer, index); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; +#endif + return mailimap_get_token_value(fd, buffer, index, + status_att_tab); +} + + +const char * mailimap_status_att_get_token_str(size_t index) +{ + return mailimap_get_token_str(index, status_att_tab); +} + +static struct mailimap_token_value month_tab[] = { + {1, "Jan"}, + {2, "Feb"}, + {3, "Mar"}, + {4, "Apr"}, + {5, "May"}, + {6, "Jun"}, + {7, "Jul"}, + {8, "Aug"}, + {9, "Sep"}, + {10, "Oct"}, + {11, "Nov"}, + {12, "Dec"} +}; + +int mailimap_month_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, month_tab); +} + + +const char * mailimap_month_get_token_str(size_t index) +{ + return mailimap_get_token_str(index, month_tab); +} + + + + + +static struct mailimap_token_value mailimap_flag_tab[] = { + {MAILIMAP_FLAG_ANSWERED, "\\Answered"}, + {MAILIMAP_FLAG_FLAGGED, "\\Flagged"}, + {MAILIMAP_FLAG_DELETED, "\\Deleted"}, + {MAILIMAP_FLAG_SEEN, "\\Seen"}, + {MAILIMAP_FLAG_DRAFT, "\\Draft"} +}; + +int mailimap_flag_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, + mailimap_flag_tab); +} + + +const char * mailimap_flag_get_token_str(size_t index) +{ + return mailimap_get_token_str(index, mailimap_flag_tab); +} + + + + +static struct mailimap_token_value encoding_tab[] = { + {MAILIMAP_BODY_FLD_ENC_7BIT, "7BIT"}, + {MAILIMAP_BODY_FLD_ENC_8BIT, "8BIT"}, + {MAILIMAP_BODY_FLD_ENC_BINARY, "BINARY"}, + {MAILIMAP_BODY_FLD_ENC_BASE64, "BASE64"}, + {MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE, "QUOTED-PRINTABLE"} +}; + +int mailimap_encoding_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, encoding_tab); +} + +static struct mailimap_token_value mbx_list_sflag_tab[] = { + {MAILIMAP_MBX_LIST_SFLAG_MARKED, "\\Marked"}, + {MAILIMAP_MBX_LIST_SFLAG_NOSELECT, "\\Noselect"}, + {MAILIMAP_MBX_LIST_SFLAG_UNMARKED, "\\Unmarked"} +}; + +int mailimap_mbx_list_sflag_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, mbx_list_sflag_tab); +} + +static struct mailimap_token_value media_basic_tab[] = { + {MAILIMAP_MEDIA_BASIC_APPLICATION, "APPLICATION"}, + {MAILIMAP_MEDIA_BASIC_AUDIO, "AUDIO"}, + {MAILIMAP_MEDIA_BASIC_IMAGE, "IMAGE"}, + {MAILIMAP_MEDIA_BASIC_MESSAGE, "MESSAGE"}, + {MAILIMAP_MEDIA_BASIC_VIDEO, "VIDEO"} +}; + +int mailimap_media_basic_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, media_basic_tab); +} + +static struct mailimap_token_value resp_cond_state_tab[] = { + {MAILIMAP_RESP_COND_STATE_OK, "OK"}, + {MAILIMAP_RESP_COND_STATE_NO, "NO"}, + {MAILIMAP_RESP_COND_STATE_BAD, "BAD"} +}; + +int mailimap_resp_cond_state_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, resp_cond_state_tab); +} + +static struct mailimap_token_value resp_text_code_1_tab[] = { + {MAILIMAP_RESP_TEXT_CODE_ALERT, "ALERT"}, + {MAILIMAP_RESP_TEXT_CODE_PARSE, "PARSE"}, + {MAILIMAP_RESP_TEXT_CODE_READ_ONLY, "READ-ONLY"}, + {MAILIMAP_RESP_TEXT_CODE_READ_WRITE, "READ-WRITE"}, + {MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, "TRYCREATE"} +}; + +int mailimap_resp_text_code_1_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, resp_text_code_1_tab); +} + +static struct mailimap_token_value resp_text_code_2_tab[] = { + {MAILIMAP_RESP_TEXT_CODE_UIDNEXT, "UIDNEXT"}, + {MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, "UIDVALIDITY"}, + {MAILIMAP_RESP_TEXT_CODE_UNSEEN, "UNSEEN"}, +}; + +int mailimap_resp_text_code_2_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, resp_text_code_2_tab); +} + +static struct mailimap_token_value section_msgtext_tab[] = { + {MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, "HEADER.FIELDS.NOT"}, + {MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, "HEADER.FIELDS"}, + {MAILIMAP_SECTION_MSGTEXT_HEADER, "HEADER"}, + {MAILIMAP_SECTION_MSGTEXT_TEXT, "TEXT"} +}; + +int mailimap_section_msgtext_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, section_msgtext_tab); +} diff --git a/kmicromail/libetpan/imap/mailimap_keywords.h b/kmicromail/libetpan/imap/mailimap_keywords.h new file mode 100644 index 0000000..a8443aa --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_keywords.h @@ -0,0 +1,107 @@ +/* + * 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$ + */ + +#ifndef MAILIMAP_COMMON_H + +#define MAILIMAP_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailstream.h" + + +/* tools */ + +int mailimap_char_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char token); + +int mailimap_space_parse(mailstream * fd, MMAPString * buffer, + size_t * index); + +/* tokens */ + +int mailimap_token_case_insensitive_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + const char * token); + +int mailimap_status_att_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index); +const char * mailimap_status_att_get_token_str(size_t index); + + +int mailimap_month_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index); +const char * mailimap_month_get_token_str(size_t index); + + +int mailimap_flag_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index); + +const char * mailimap_flag_get_token_str(size_t index); + +int mailimap_encoding_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index); + +int mailimap_mbx_list_sflag_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index); + +int mailimap_media_basic_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index); + +int mailimap_resp_cond_state_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index); + +int mailimap_resp_text_code_1_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index); + +int mailimap_resp_text_code_2_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index); + +int mailimap_section_msgtext_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imap/mailimap_parser.c b/kmicromail/libetpan/imap/mailimap_parser.c new file mode 100644 index 0000000..1c2ecde --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_parser.c @@ -0,0 +1,9506 @@ +/* + * 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 <string.h> +#include <stdlib.h> +#include <stdio.h> + +#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 = <any CHAR except atom-specials> +*/ + +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) { + res = r; + goto err; + } + } + 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 = <any TEXT-CHAR except quoted-specials> / + "\" 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*<any TEXT-CHAR except "]">] +*/ + +/* + 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*<any TEXT-CHAR except "]">] +*/ + +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*<any TEXT-CHAR except "]" +*/ + +static int +mailimap_resp_text_code_other_2_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_1); +} + +/* + SP 1*<any TEXT-CHAR except "]"> +*/ + +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*<any TEXT-CHAR except "]">] +*/ + +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*<any TEXT-CHAR except "]">] +*/ + +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 "+"> +*/ + +/* + any ASTRING-CHAR except "+" +*/ + +static int is_tag_char(char ch) +{ + if (ch == '+') + return FALSE; + return is_astring_char(ch); +} + +/* + tag = 1*<any ASTRING-CHAR except "+"> +*/ + +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 = <any CHAR except CR and LF> +*/ + +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 <experimental command arguments> +*/ + +/* + 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; +} diff --git a/kmicromail/libetpan/imap/mailimap_parser.h b/kmicromail/libetpan/imap/mailimap_parser.h new file mode 100644 index 0000000..b1de75b --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_parser.h @@ -0,0 +1,69 @@ +/* + * 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$ + */ + +#ifndef MAILIMAP_PARSER_H + +#define MAILIMAP_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +int mailimap_greeting_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_greeting ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_response_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_response ** result, + size_t progr_rate, + progress_function * progr_fun); + +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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imap/mailimap_print.c b/kmicromail/libetpan/imap/mailimap_print.c new file mode 100644 index 0000000..8a04348 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_print.c @@ -0,0 +1,1615 @@ +/* + * 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$ + */ +#ifdef DEBUG +#include "mailimap_print.h" + +#include <stdio.h> + +static void mailimap_body_fields_print(struct mailimap_body_fields * + body_fields); +static void mailimap_envelope_print(struct mailimap_envelope * env); +static void mailimap_body_print(struct mailimap_body * body); +static void mailimap_body_fld_enc_print(struct mailimap_body_fld_enc * + fld_enc); + +static int indent_size = 0; + +static void indent() +{ + indent_size ++; +} + +static void unindent() +{ + indent_size --; +} + +static void print_indent() +{ + int i; + + for (i = 0 ; i < indent_size ; i++) + printf(" "); +} + + +static void mailimap_body_fld_lang_print(struct mailimap_body_fld_lang * + fld_lang) +{ + clistiter * cur; + + print_indent(); + printf("body-fld-lang { "); + + switch (fld_lang->lg_type) { + case MAILIMAP_BODY_FLD_LANG_SINGLE: + printf("%s ", fld_lang->lg_data.lg_single); + break; + + case MAILIMAP_BODY_FLD_LANG_LIST: + for(cur = clist_begin(fld_lang->lg_data.lg_list) ; + cur != NULL ; cur = clist_next(cur)) { + char * lang; + + lang = clist_content(cur); + + printf("%s ", lang); + } + break; + } + + print_indent(); + printf("}\n"); +} + +static void +mailimap_single_body_fld_param_print(struct mailimap_single_body_fld_param * + single) +{ + printf("(%s = %s)", single->pa_name, single->pa_value); +} + +static void mailimap_body_fld_param_print(struct mailimap_body_fld_param * + fld_param) +{ + clistiter * cur; + + print_indent(); + printf("body-fld-param { "); + + for(cur = clist_begin(fld_param->pa_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_single_body_fld_param * single; + + single = clist_content(cur); + + mailimap_single_body_fld_param_print(single); + printf(" "); + } + printf("\n"); +} + +static void mailimap_body_fld_dsp_print(struct mailimap_body_fld_dsp * fld_dsp) +{ + print_indent(); + printf("body-fld-dsp {\n"); + indent(); + + print_indent(); + printf("name { %s }\n", fld_dsp->dsp_type); + + mailimap_body_fld_param_print(fld_dsp->dsp_attributes); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_body_extension_list_print(clist * ext_list); + +static void mailimap_body_extension_print(struct mailimap_body_extension * ext) +{ + print_indent(); + printf("body-extention {\n"); + indent(); + + switch (ext->ext_type) { + case MAILIMAP_BODY_EXTENSION_NSTRING: + print_indent(); + printf("%s\n", ext->ext_data.ext_nstring); + break; + case MAILIMAP_BODY_EXTENSION_NUMBER: + print_indent(); + printf("%i\n", ext->ext_data.ext_number); + break; + case MAILIMAP_BODY_EXTENSION_LIST: + mailimap_body_extension_list_print(ext->ext_data.ext_body_extension_list); + break; + } + + unindent(); + print_indent(); + printf("}\n"); + +} + +static void mailimap_body_extension_list_print(clist * ext_list) +{ + clistiter * cur; + + print_indent(); + printf("body-extention-list {\n"); + indent(); + + for (cur = clist_begin(ext_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_body_extension * ext; + + ext = clist_content(cur); + + mailimap_body_extension_print(ext); + } + + unindent(); + print_indent(); + printf("}"); +} + +static void mailimap_body_ext_1part_print(struct mailimap_body_ext_1part * + body_ext_1part) +{ + print_indent(); + printf("body-type-1part {\n"); + indent(); + + print_indent(); + printf("md5 { %s }\n", body_ext_1part->bd_md5); + if (body_ext_1part->bd_disposition) { + mailimap_body_fld_dsp_print(body_ext_1part->bd_disposition); + if (body_ext_1part->bd_language) { + mailimap_body_fld_lang_print(body_ext_1part->bd_language); + + if (body_ext_1part->bd_extension_list) + mailimap_body_extension_list_print(body_ext_1part->bd_extension_list); + } + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_body_type_text_print(struct mailimap_body_type_text * + body_type_text) +{ + print_indent(); + printf("body-type-text {\n"); + indent(); + + print_indent(); + printf("media-text { %s }\n", body_type_text->bd_media_text); + mailimap_body_fields_print(body_type_text->bd_fields); + print_indent(); + printf("lines { %i }\n", body_type_text->bd_lines); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_body_type_msg_print(struct mailimap_body_type_msg * + body_type_msg) +{ + print_indent(); + printf("body-type-msg {\n"); + indent(); + + mailimap_body_fields_print(body_type_msg->bd_fields); + mailimap_envelope_print(body_type_msg->bd_envelope); + mailimap_body_print(body_type_msg->bd_body); + + print_indent(); + printf("lines { %i }\n", body_type_msg->bd_lines); + + unindent(); + print_indent(); + printf("}\n"); +} + + +static void mailimap_body_fld_enc_print(struct mailimap_body_fld_enc * fld_enc) +{ + print_indent(); + printf("body-fld-enc { "); + + switch (fld_enc->enc_type) { + case MAILIMAP_BODY_FLD_ENC_7BIT: + print_indent(); + printf("7bit"); + break; + case MAILIMAP_BODY_FLD_ENC_8BIT: + printf("8bit"); + break; + case MAILIMAP_BODY_FLD_ENC_BINARY: + printf("binary"); + break; + case MAILIMAP_BODY_FLD_ENC_BASE64: + printf("base64"); + break; + case MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE: + printf("quoted-printable"); + break; + case MAILIMAP_BODY_FLD_ENC_OTHER: + printf("%s", fld_enc->enc_value); + break; + } + + printf("}\n"); +} + +static void mailimap_body_fields_print(struct mailimap_body_fields * + body_fields) +{ + print_indent(); + printf("body-fields {\n"); + indent(); + + mailimap_body_fld_param_print(body_fields->bd_parameter); + + print_indent(); + printf("body-fld-id { %s }\n", body_fields->bd_id); + printf("body-fld-desc { %s }\n", body_fields->bd_description); + mailimap_body_fld_enc_print(body_fields->bd_encoding); + printf("body-fld-octets { %i }\n", body_fields->bd_size); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_media_basic_print(struct mailimap_media_basic * + media_basic) +{ + print_indent(); + printf("media-basic {"); + + switch (media_basic->med_type) { + case MAILIMAP_MEDIA_BASIC_APPLICATION: + printf("application"); + break; + case MAILIMAP_MEDIA_BASIC_AUDIO: + printf("audio"); + break; + case MAILIMAP_MEDIA_BASIC_IMAGE: + printf("image"); + break; + case MAILIMAP_MEDIA_BASIC_MESSAGE: + printf("message"); + break; + case MAILIMAP_MEDIA_BASIC_VIDEO: + printf("video"); + break; + case MAILIMAP_MEDIA_BASIC_OTHER: + printf("%s", media_basic->med_basic_type); + break; + } + printf(" / %s }\n", media_basic->med_subtype); +} + +static void mailimap_body_type_basic_print(struct mailimap_body_type_basic * + body_type_basic) +{ + print_indent(); + printf("body-type-basic {\n"); + indent(); + + mailimap_media_basic_print(body_type_basic->bd_media_basic); + mailimap_body_fields_print(body_type_basic->bd_fields); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_body_type_1part_print(struct mailimap_body_type_1part * + body_type_1part) +{ + print_indent(); + printf("body-type-1part {\n"); + indent(); + + switch (body_type_1part->bd_type) { + case MAILIMAP_BODY_TYPE_1PART_BASIC: + mailimap_body_type_basic_print(body_type_1part->bd_data.bd_type_basic); + break; + + case MAILIMAP_BODY_TYPE_1PART_MSG: + mailimap_body_type_msg_print(body_type_1part->bd_data.bd_type_msg); + break; + + case MAILIMAP_BODY_TYPE_1PART_TEXT: + mailimap_body_type_text_print(body_type_1part->bd_data.bd_type_text); + break; + } + + if (body_type_1part->bd_ext_1part != NULL) + mailimap_body_ext_1part_print(body_type_1part->bd_ext_1part); + + unindent(); + print_indent(); + printf("\n"); +} + +static void mailimap_body_ext_mpart(struct mailimap_body_ext_mpart * ext_mpart) +{ + print_indent(); + printf("body-ext-mpart {\n"); + indent(); + + mailimap_body_fld_param_print(ext_mpart->bd_parameter); + if (ext_mpart->bd_disposition) { + mailimap_body_fld_dsp_print(ext_mpart->bd_disposition); + if (ext_mpart->bd_language) { + mailimap_body_fld_lang_print(ext_mpart->bd_language); + + if (ext_mpart->bd_extension_list) + mailimap_body_extension_list_print(ext_mpart->bd_extension_list); + } + } + + unindent(); + print_indent(); + printf("\n"); +} + +static void mailimap_body_type_mpart_print(struct mailimap_body_type_mpart * + mpart) +{ + clistiter * cur; + + print_indent(); + printf("body-type-mpart {\n"); + indent(); + + for(cur = clist_begin(mpart->bd_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_body * body; + + body = clist_content(cur); + + mailimap_body_print(body); + } + + printf("media-subtype { %s }\n", mpart->bd_media_subtype); + + if (mpart->bd_ext_mpart) + mailimap_body_ext_mpart(mpart->bd_ext_mpart); + + unindent(); + print_indent(); + printf("}\n"); +} + + +static void mailimap_body_print(struct mailimap_body * body) +{ + print_indent(); + printf("body {\n"); + indent(); + + switch (body->bd_type) { + case MAILIMAP_BODY_1PART: + mailimap_body_type_1part_print(body->bd_data.bd_body_1part); + break; + case MAILIMAP_BODY_MPART: + mailimap_body_type_mpart_print(body->bd_data.bd_body_mpart); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_date_time_print(struct mailimap_date_time * date_time) +{ + print_indent(); + printf("date-time { %i/%i/%i - %i:%i:%i %i }\n", + date_time->dt_day, date_time->dt_month, date_time->dt_year, + date_time->dt_hour, date_time->dt_min, date_time->dt_month, + date_time->dt_zone); +} + +static void mailimap_address_print(struct mailimap_address * address) +{ + print_indent(); + printf("address { name: %s, addr: %s, mailbox: %s, host: %s) }\n", + address->ad_personal_name, address->ad_source_route, + address->ad_mailbox_name, address->ad_host_name); +} + +static void mailimap_envelope_address_list_print(clist * address) +{ + clistiter * cur; + + print_indent(); + printf("envelope-address-list {\n"); + indent(); + + for(cur = clist_begin(address) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_address * addr; + + addr = clist_content(cur); + + mailimap_address_print(addr); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_envelope_print(struct mailimap_envelope * env) +{ + print_indent(); + printf("envelope {\n"); + indent(); + + print_indent(); + printf("date { %s }\n", env->env_date); + + print_indent(); + printf("subject { %s }\n", env->env_subject); + + print_indent(); + printf("from {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_from->frm_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("sender {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_sender->snd_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("reply-to {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_reply_to->rt_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("to {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_to->to_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("cc {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_cc->cc_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("bcc {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_bcc->bcc_list); + unindent(); + print_indent(); + printf("}\n"); + + printf("in-reply-to { %s }\n", env->env_in_reply_to); + printf("message-id { %s }\n", env->env_message_id); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_header_list_print(struct mailimap_header_list * + header_list) +{ + clistiter * cur; + + print_indent(); + printf("header-list { "); + for(cur = clist_begin(header_list->hdr_list) ; cur != NULL ; + cur = clist_next(cur)) + printf("%s ", (char *) clist_content(cur)); + printf("}\n"); +} + +static void mailimap_section_msgtext_print(struct mailimap_section_msgtext * + section_msgtext) +{ + print_indent(); + printf("section-msgtext {\n"); + indent(); + + switch(section_msgtext->sec_type) { + case MAILIMAP_SECTION_MSGTEXT_HEADER: + print_indent(); + printf("header\n"); + break; + + case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS: + print_indent(); + printf("header fields {"); + indent(); + mailimap_header_list_print(section_msgtext->sec_header_list); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT: + print_indent(); + printf("header fields not {"); + indent(); + mailimap_header_list_print(section_msgtext->sec_header_list); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_SECTION_MSGTEXT_TEXT: + print_indent(); + printf("text\n"); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_section_part_print(struct mailimap_section_part * + section_part) +{ + clistiter * cur; + + print_indent(); + printf("section-part { "); + + for(cur = clist_begin(section_part->sec_id) ; + cur != NULL ; cur = clist_next(cur)) { + printf("%i", * ((uint32_t *) clist_content(cur))); + if (clist_next(cur) != NULL) + printf("."); + } + printf(" }\n"); +} + +static void mailimap_section_text_print(struct mailimap_section_text * + section_text) +{ + print_indent(); + printf("section-text {\n"); + indent(); + + switch (section_text->sec_type) { + case MAILIMAP_SECTION_TEXT_MIME: + print_indent(); + printf("MIME"); + break; + case MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT: + mailimap_section_msgtext_print(section_text->sec_msgtext); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_section_spec_print(struct mailimap_section_spec * + section_spec) +{ + print_indent(); + printf("section-spec {"); + indent(); + + switch(section_spec->sec_type) { + case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT: + mailimap_section_msgtext_print(section_spec->sec_data.sec_msgtext); + break; + case MAILIMAP_SECTION_SPEC_SECTION_PART: + mailimap_section_part_print(section_spec->sec_data.sec_part); + if (section_spec->sec_text != NULL) + mailimap_section_text_print(section_spec->sec_text); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_section_print(struct mailimap_section * section) +{ + print_indent(); + printf("section {\n"); + indent(); + + if (section != NULL) + if (section->sec_spec != NULL) + mailimap_section_spec_print(section->sec_spec); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_msg_att_body_section_print(struct + mailimap_msg_att_body_section * + msg_att_body_section) +{ + print_indent(); + printf("msg-att-body-section {\n"); + indent(); + + mailimap_section_print(msg_att_body_section->sec_section); + printf("origin-octet: %i\n", msg_att_body_section->sec_origin_octet); + printf("body-part: %s\n", msg_att_body_section->sec_body_part); + + unindent(); + print_indent(); + printf("}\n"); +} + + +static void mailimap_msg_att_static_print(struct mailimap_msg_att_static * + msg_att_static) +{ + print_indent(); + printf("msg-att-static {\n"); + indent(); + + switch (msg_att_static->att_type) { + + case MAILIMAP_MSG_ATT_ENVELOPE: + print_indent(); + printf("envelope {\n"); + indent(); + print_indent(); + mailimap_envelope_print(msg_att_static->att_data.att_env); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_INTERNALDATE: + print_indent(); + printf("internaldate {\n"); + indent(); + print_indent(); + mailimap_date_time_print(msg_att_static->att_data.att_internal_date); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_RFC822: + print_indent(); + printf("rfc822 {\n"); + printf("%s\n", msg_att_static->att_data.att_rfc822.att_content); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_RFC822_HEADER: + print_indent(); + printf("rfc822-header {\n"); + printf("%s\n", msg_att_static->att_data.att_rfc822_header.att_content); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_RFC822_TEXT: + print_indent(); + printf("rfc822-text {\n"); + printf("%s\n", msg_att_static->att_data.att_rfc822_text.att_content); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_RFC822_SIZE: + print_indent(); + printf("rfc822-size { %i }\n", msg_att_static->att_data.att_rfc822_size); + break; + + case MAILIMAP_MSG_ATT_BODY: + print_indent(); + printf("body {\n"); + indent(); + print_indent(); + mailimap_body_print(msg_att_static->att_data.att_body); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_BODYSTRUCTURE: + print_indent(); + printf("bodystructure {\n"); + indent(); + print_indent(); + mailimap_body_print(msg_att_static->att_data.att_bodystructure); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_BODY_SECTION: + print_indent(); + printf("body-section {\n"); + indent(); + print_indent(); + mailimap_msg_att_body_section_print(msg_att_static->att_data.att_body_section); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_UID: + printf("uid { %i }\n", msg_att_static->att_data.att_uid); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_flag_print(struct mailimap_flag * flag); + +static void mailimap_flag_fetch_print(struct mailimap_flag_fetch * flag) +{ + print_indent(); + printf("flag fetch {\n"); + indent(); + + switch (flag->fl_type) { + case MAILIMAP_FLAG_FETCH_RECENT: + printf("recent\n"); + break; + case MAILIMAP_FLAG_FETCH_OTHER: + print_indent(); + printf("flag {\n"); + indent(); + mailimap_flag_print(flag->fl_flag); + unindent(); + print_indent(); + printf("}\n"); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_msg_att_dynamic_print(struct mailimap_msg_att_dynamic * + dynamic) +{ + clistiter * cur; + + print_indent(); + printf("msg-att-dynamic {\n"); + indent(); + + for(cur = clist_begin(dynamic->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_flag_fetch * flag; + + flag = (struct mailimap_flag_fetch *) clist_content(cur); + mailimap_flag_fetch_print(flag); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_msg_att_item_print(struct mailimap_msg_att_item * item) +{ + print_indent(); + printf("msg-att-item {\n"); + indent(); + + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ITEM_DYNAMIC: + mailimap_msg_att_dynamic_print(item->att_data.att_dyn); + break; + case MAILIMAP_MSG_ATT_ITEM_STATIC: + mailimap_msg_att_static_print(item->att_data.att_static); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_msg_att_print(struct mailimap_msg_att * msg_att) +{ + clistiter * cur; + + print_indent(); + printf("msg-att {\n"); + indent(); + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_msg_att_item * item; + + item = clist_content(cur); + + mailimap_msg_att_item_print(item); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_message_data_print(struct mailimap_message_data * + msg_data) +{ + print_indent(); + printf("message-data {\n"); + indent(); + + switch (msg_data->mdt_type) { + case MAILIMAP_MESSAGE_DATA_EXPUNGE: + print_indent(); + printf("expunged { %i }\n", msg_data->mdt_number); + break; + case MAILIMAP_MESSAGE_DATA_FETCH: + print_indent(); + printf("message-number { %i }\n", msg_data->mdt_number); + mailimap_msg_att_print(msg_data->mdt_msg_att); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_status_att_print(int status_att) +{ + print_indent(); + printf("status-att { "); + + switch(status_att) { + case MAILIMAP_STATUS_ATT_MESSAGES: + printf("messages"); + break; + case MAILIMAP_STATUS_ATT_RECENT: + printf("recent"); + break; + case MAILIMAP_STATUS_ATT_UIDNEXT: + printf("uidnext"); + break; + case MAILIMAP_STATUS_ATT_UIDVALIDITY: + printf("status att uidvalidity"); + break; + case MAILIMAP_STATUS_ATT_UNSEEN: + printf("status att unseen"); + break; + } + + printf(" \n"); +} + +static void +mailimap_status_info_print(struct mailimap_status_info * info) +{ + print_indent(); + printf("status-info {\n"); + indent(); + + mailimap_status_att_print(info->st_att); + + print_indent(); + printf("value { %i }\n", info->st_value); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void +mailimap_mailbox_data_status_print(struct mailimap_mailbox_data_status * + mb_data_status) +{ + clistiter * cur; + + print_indent(); + printf("mailbox-data-status {\n"); + indent(); + + print_indent(); + printf("mailbox { %s }\n", mb_data_status->st_mailbox); + + for(cur = clist_begin(mb_data_status->st_info_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_status_info * info; + + info = clist_content(cur); + + mailimap_status_info_print(info); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_mbx_list_oflag_print(struct mailimap_mbx_list_oflag * + oflag) +{ + print_indent(); + printf("mbx-list-oflag { "); + + switch (oflag->of_type) { + case MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS: + printf("noinferiors"); + break; + case MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT: + printf("%s", oflag->of_flag_ext); + break; + } + + printf(" }\n"); +} + +static void mailimap_mbx_list_sflag_print(int sflag) +{ + print_indent(); + printf("mbx-list-sflag { "); + + switch (sflag) { + case MAILIMAP_MBX_LIST_SFLAG_MARKED: + printf("marked"); + break; + case MAILIMAP_MBX_LIST_SFLAG_NOSELECT: + printf("noselected"); + break; + case MAILIMAP_MBX_LIST_SFLAG_UNMARKED: + printf("unmarked"); + break; + } + + printf(" }\n"); +} + +static void mailimap_mbx_list_flags_print(struct mailimap_mbx_list_flags * + mbx_list_flags) +{ + clistiter * cur; + + print_indent(); + printf("mbx-list-flags {"); + indent(); + + if (mbx_list_flags->mbf_type == MAILIMAP_MBX_LIST_FLAGS_SFLAG) + mailimap_mbx_list_sflag_print(mbx_list_flags->mbf_sflag); + + for(cur = clist_begin(mbx_list_flags->mbf_oflags) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_mbx_list_oflag * oflag; + + oflag = clist_content(cur); + + mailimap_mbx_list_oflag_print(oflag); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_mailbox_list_print(struct mailimap_mailbox_list * mb_list) +{ + print_indent(); + printf("mailbox-list {\n"); + indent(); + + mailimap_mbx_list_flags_print(mb_list->mb_flag); + printf("dir-separator { %c }\n", mb_list->mb_delimiter); + printf("mailbox { %s }\n", mb_list->mb_name); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_flag_list_print(struct mailimap_flag_list * flag_list) +{ + clistiter * cur; + + print_indent(); + printf("flag-list {\n"); + indent(); + + for(cur = clist_begin(flag_list->fl_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_flag * flag; + + flag = clist_content(cur); + + print_indent(); + mailimap_flag_print(flag); + printf("\n"); + } + + unindent(); + print_indent(); + printf("}\n"); +} + + +static void mailimap_mailbox_data_print(struct mailimap_mailbox_data * mb_data) +{ + clistiter * cur; + + print_indent(); + printf("mailbox-data {\n"); + indent(); + + switch (mb_data->mbd_type) { + case MAILIMAP_MAILBOX_DATA_FLAGS: + print_indent(); + printf("flags {\n"); + indent(); + mailimap_flag_list_print(mb_data->mbd_data.mbd_flags); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MAILBOX_DATA_LIST: + print_indent(); + printf("list {\n"); + indent(); + mailimap_mailbox_list_print(mb_data->mbd_data.mbd_list); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MAILBOX_DATA_LSUB: + print_indent(); + printf("lsub {\n"); + indent(); + mailimap_mailbox_list_print(mb_data->mbd_data.mbd_lsub); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MAILBOX_DATA_SEARCH: + print_indent(); + printf("search { "); + for(cur = clist_begin(mb_data->mbd_data.mbd_search) ; + cur != NULL ; cur = clist_next(cur)) { + uint32_t * id; + + id = clist_content(cur); + printf("%i ", * id); + } + printf(" }\n"); + break; + + case MAILIMAP_MAILBOX_DATA_STATUS: + print_indent(); + printf("status {\n"); + indent(); + mailimap_mailbox_data_status_print(mb_data->mbd_data.mbd_status); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MAILBOX_DATA_EXISTS: + print_indent(); + printf("exists { %i }\n", mb_data->mbd_data.mbd_exists); + break; + + case MAILIMAP_MAILBOX_DATA_RECENT: + print_indent(); + printf("recent { %i }\n", mb_data->mbd_data.mbd_recent); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void +mailimap_resp_text_code_print(struct mailimap_resp_text_code * text_code); + +static void mailimap_resp_text_print(struct mailimap_resp_text * resp_text); + +static void mailimap_resp_cond_bye_print(struct mailimap_resp_cond_bye * + resp_cond_bye) +{ + print_indent(); + printf("resp-cond-bye {\n"); + indent(); + mailimap_resp_text_print(resp_cond_bye->rsp_text); + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_resp_cond_state_print(struct mailimap_resp_cond_state * + resp_cond_state) +{ + print_indent(); + printf("resp-cond-state {\n"); + indent(); + + switch(resp_cond_state->rsp_type) { + case MAILIMAP_RESP_COND_STATE_OK: + print_indent(); + printf("OK\n"); + break; + case MAILIMAP_RESP_COND_STATE_NO: + print_indent(); + printf("NO\n"); + break; + case MAILIMAP_RESP_COND_STATE_BAD: + print_indent(); + printf("BAD\n"); + break; + } + + mailimap_resp_text_print(resp_cond_state->rsp_text); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_capability_data_print(struct mailimap_capability_data * + cap_data); + +static void mailimap_response_data_print(struct mailimap_response_data * + resp_data) +{ + print_indent(); + printf("response-data {\n"); + indent(); + + switch (resp_data->rsp_type) { + case MAILIMAP_RESP_DATA_TYPE_COND_STATE: + mailimap_resp_cond_state_print(resp_data->rsp_data.rsp_cond_state); + break; + case MAILIMAP_RESP_DATA_TYPE_COND_BYE: + mailimap_resp_cond_bye_print(resp_data->rsp_data.rsp_bye); + break; + case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA: + mailimap_mailbox_data_print(resp_data->rsp_data.rsp_mailbox_data); + break; + case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA: + mailimap_message_data_print(resp_data->rsp_data.rsp_message_data); + break; + case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA: + mailimap_capability_data_print(resp_data->rsp_data.rsp_capability_data); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_flag_print(struct mailimap_flag * flag) +{ + printf("flag { "); + + switch (flag->fl_type) { + case MAILIMAP_FLAG_ANSWERED: + printf("answered"); + break; + + case MAILIMAP_FLAG_FLAGGED: + printf("flagged"); + break; + + case MAILIMAP_FLAG_DELETED: + printf("deleted"); + break; + + case MAILIMAP_FLAG_SEEN: + printf("seen"); + break; + + case MAILIMAP_FLAG_DRAFT: + printf("flag draft"); + break; + + case MAILIMAP_FLAG_KEYWORD: + printf("keyword { %s }", flag->fl_data.fl_keyword); + break; + + case MAILIMAP_FLAG_EXTENSION: + printf("extention { %s }", flag->fl_data.fl_extension); + break; + } + + printf(" }"); +} + +static void mailimap_flag_perm_print(struct mailimap_flag_perm * flag_perm) +{ + print_indent(); + printf("flag-perm { "); + + switch (flag_perm->fl_type) { + case MAILIMAP_FLAG_PERM_FLAG: + mailimap_flag_print(flag_perm->fl_flag); + break; + + case MAILIMAP_FLAG_PERM_ALL: + printf("all"); + break; + } + + printf(" }\n"); +} + +static void mailimap_capability_print(struct mailimap_capability * cap) +{ + print_indent(); + printf("capability { "); + + switch (cap->cap_type) { + case MAILIMAP_CAPABILITY_AUTH_TYPE: + printf("auth { %s }", cap->cap_data.cap_auth_type); + break; + case MAILIMAP_CAPABILITY_NAME: + printf("atom { %s }", cap->cap_data.cap_name); + break; + } + + printf(" }\n"); +} + +static void mailimap_capability_data_print(struct mailimap_capability_data * + cap_data) +{ + clistiter * cur; + + print_indent(); + printf("capability-data {\n"); + indent(); + + for(cur = clist_begin(cap_data->cap_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_capability * cap; + + cap = clist_content(cur); + + mailimap_capability_print(cap); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void +mailimap_resp_text_code_print(struct mailimap_resp_text_code * text_code) +{ + clistiter * cur; + + print_indent(); + printf("resp-text-code {\n"); + indent(); + + switch (text_code->rc_type) { + case MAILIMAP_RESP_TEXT_CODE_BADCHARSET: + print_indent(); + printf("badcharset { "); + for(cur = clist_begin(text_code->rc_data.rc_badcharset) ; cur != NULL ; + cur = clist_next(cur)) + printf("%s ", (char *) clist_content(cur)); + printf("}\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA: + print_indent(); + printf("capability {\n"); + indent(); + mailimap_capability_data_print(text_code->rc_data.rc_cap_data); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS: + print_indent(); + printf("permanent-flags {\n"); + indent(); + cur = clist_begin(text_code->rc_data.rc_perm_flags); + while (cur != NULL) { + mailimap_flag_perm_print(clist_content(cur)); + cur = clist_next(cur); + } + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_READ_ONLY: + print_indent(); + printf("readonly\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_READ_WRITE: + print_indent(); + printf("readwrite\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_TRY_CREATE: + print_indent(); + printf("trycreate\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_UIDNEXT: + print_indent(); + printf("uidnext { %i }\n", text_code->rc_data.rc_uidnext); + break; + + case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY: + print_indent(); + printf("uidvalidity { %i }\n", text_code->rc_data.rc_uidvalidity); + break; + + case MAILIMAP_RESP_TEXT_CODE_UNSEEN: + print_indent(); + printf("unseen { %i }\n", text_code->rc_data.rc_first_unseen); + break; + + case MAILIMAP_RESP_TEXT_CODE_OTHER: + print_indent(); + printf("other { %s = %s }\n", + text_code->rc_data.rc_atom.atom_name, + text_code->rc_data.rc_atom.atom_value); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_resp_text_print(struct mailimap_resp_text * resp_text) +{ + print_indent(); + printf("resp-text {\n"); + indent(); + + if (resp_text->rsp_code) + mailimap_resp_text_code_print(resp_text->rsp_code); + print_indent(); + printf("text { %s }\n", resp_text->rsp_text); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_continue_req_print(struct mailimap_continue_req * + cont_req) +{ + print_indent(); + printf("continue-req {\n"); + indent(); + + switch (cont_req->cr_type) { + case MAILIMAP_CONTINUE_REQ_TEXT: + print_indent(); + printf("resp-text {\n"); + indent(); + mailimap_resp_text_print(cont_req->cr_data.cr_text); + unindent(); + print_indent(); + printf("}\n"); + break; + case MAILIMAP_CONTINUE_REQ_BASE64: + printf("base64 { %s }\n", cont_req->cr_data.cr_base64); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_cont_req_or_resp_data_print(struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data) +{ + print_indent(); + printf("cont-req-or-resp-data {\n"); + indent(); + + switch (cont_req_or_resp_data->rsp_type) { + case MAILIMAP_RESP_CONT_REQ: + mailimap_continue_req_print(cont_req_or_resp_data->rsp_data.rsp_cont_req); + break; + case MAILIMAP_RESP_RESP_DATA: + mailimap_response_data_print(cont_req_or_resp_data->rsp_data.rsp_resp_data); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_response_tagged_print(struct mailimap_response_tagged * + tagged) +{ + print_indent(); + printf("response-tagged {\n"); + indent(); + + print_indent(); + printf("tag { %s }\n", tagged->rsp_tag); + mailimap_resp_cond_state_print(tagged->rsp_cond_state); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_response_fatal_print(struct mailimap_response_fatal * + fatal) +{ + print_indent(); + printf("response-fatal {\n"); + indent(); + + mailimap_resp_cond_bye_print(fatal->rsp_bye); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_response_done_print(struct mailimap_response_done * + resp_done) +{ + print_indent(); + printf("response-done {\n"); + indent(); + + switch (resp_done->rsp_type) { + case MAILIMAP_RESP_DONE_TYPE_TAGGED: + mailimap_response_tagged_print(resp_done->rsp_data.rsp_tagged); + break; + case MAILIMAP_RESP_DONE_TYPE_FATAL: + mailimap_response_fatal_print(resp_done->rsp_data.rsp_fatal); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +void mailimap_response_print(struct mailimap_response * resp) +{ + clistiter * cur; + + print_indent(); + printf("response {\n"); + indent(); + + for(cur = clist_begin(resp->rsp_cont_req_or_resp_data_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_cont_req_or_resp_data * resp; + + resp = clist_content(cur); + + mailimap_cont_req_or_resp_data_print(resp); + } + + mailimap_response_done_print(resp->rsp_resp_done); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_resp_cond_auth_print(struct mailimap_resp_cond_auth * + cond_auth) +{ + print_indent(); + printf("resp-cond-auth {\n"); + indent(); + + switch (cond_auth->rsp_type) { + case MAILIMAP_RESP_COND_AUTH_OK: + print_indent(); + printf("OK\n"); + case MAILIMAP_RESP_COND_AUTH_PREAUTH: + print_indent(); + printf("PREAUTH\n"); + } + mailimap_resp_text_print(cond_auth->rsp_text); + + unindent(); + print_indent(); + printf("}\n"); +} + +void mailimap_greeting_print(struct mailimap_greeting * greeting) +{ + print_indent(); + printf("greeting {\n"); + indent(); + + switch(greeting->gr_type) { + case MAILIMAP_GREETING_RESP_COND_AUTH: + mailimap_resp_cond_auth_print(greeting->gr_data.gr_auth); + break; + case MAILIMAP_GREETING_RESP_COND_BYE: + mailimap_resp_cond_bye_print(greeting->gr_data.gr_bye); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} +#endif diff --git a/kmicromail/libetpan/imap/mailimap_print.h b/kmicromail/libetpan/imap/mailimap_print.h new file mode 100644 index 0000000..24016fa --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_print.h @@ -0,0 +1,54 @@ +/* + * 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$ + */ + +#ifndef MAILIMAP_PRINT_H + +#define MAILIMAP_PRINT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +void mailimap_response_print(struct mailimap_response * resp); + +void mailimap_greeting_print(struct mailimap_greeting * greeting); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imap/mailimap_sender.c b/kmicromail/libetpan/imap/mailimap_sender.c new file mode 100644 index 0000000..ac4bfe8 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_sender.c @@ -0,0 +1,2743 @@ +/* + * 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 "mailstream.h" +#include "mailimap_keywords.h" +#include "mailimap_sender.h" +#include "clist.h" +#include "mail.h" +#include <string.h> + +#include <stdio.h> +#include <ctype.h> + +/* + TODO : + implement progression for literal +*/ + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + +static int mailimap_atom_send(mailstream * fd, const char * atom); + +static int mailimap_auth_type_send(mailstream * fd, const char * auth_type); + +static int mailimap_base64_send(mailstream * fd, const char * base64); + + +static int mailimap_date_send(mailstream * fd, + struct mailimap_date * date); + +static int mailimap_date_day_send(mailstream * fd, int day); + +static int mailimap_date_month_send(mailstream * fd, int month); + + +/* +static gboolean mailimap_date_text_send(mailstream * fd, + struct mailimap_date_text * date_text); +*/ + + +static int mailimap_date_year_send(mailstream *fd, int year); + +static int +mailimap_date_time_send(mailstream * fd, + struct mailimap_date_time * date_time); + +static int mailimap_digit_send(mailstream * fd, int digit); + + + +static int +mailimap_fetch_type_send(mailstream * fd, + struct mailimap_fetch_type * fetch_type); + + +static int mailimap_fetch_att_send(mailstream * fd, + struct mailimap_fetch_att * fetch_att); + + +static int mailimap_flag_send(mailstream * fd, + struct mailimap_flag * flag); + + +static int mailimap_flag_extension_send(mailstream * fd, + const char * flag_extension); + + +static int mailimap_flag_keyword_send(mailstream * fd, + const char * flag_keyword); + + +static int mailimap_flag_list_send(mailstream * fd, + struct mailimap_flag_list * flag_list); + + + +static int mailimap_header_fld_name_send(mailstream * fd, const char * header); + + +static int +mailimap_header_list_send(mailstream * fd, + struct mailimap_header_list * header_list); + +static int +mailimap_list_mailbox_send(mailstream * fd, const char * pattern); + + +static int mailimap_mailbox_send(mailstream * fd, const char * mb); + +static int mailimap_number_send(mailstream * fd, uint32_t number); + +static int mailimap_password_send(mailstream * fd, const char * pass); + +static int mailimap_quoted_char_send(mailstream * fd, char ch); + +static int mailimap_quoted_send(mailstream * fd, const char * quoted); + + +static int mailimap_search_key_send(mailstream * fd, + struct mailimap_search_key * key); + +static int +mailimap_section_send(mailstream * fd, + struct mailimap_section * section); + +static int +mailimap_section_msgtext_send(mailstream * fd, + struct mailimap_section_msgtext * + section_msgtext); + + +static int +mailimap_section_part_send(mailstream * fd, + struct mailimap_section_part * section); + + +static int +mailimap_section_spec_send(mailstream * fd, + struct mailimap_section_spec * section_spec); + + +static int +mailimap_section_text_send(mailstream * fd, + struct mailimap_section_text * section_text); + + +static int +mailimap_sequence_num_send(mailstream * fd, uint32_t sequence_num); + + +static int mailimap_set_item_send(mailstream * fd, + struct mailimap_set_item * item); + + +static int mailimap_set_send(mailstream * fd, + struct mailimap_set * set); + + + +static int mailimap_status_att_send(mailstream * fd, int * status_att); + + + +static int +mailimap_store_att_flags_send(mailstream * fd, + struct mailimap_store_att_flags * store_flags); + + +static int mailimap_userid_send(mailstream * fd, const char * user); + + + + + + + + + + + + + + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + + +static int mailimap_sized_token_send(mailstream * fd, const char * atom, + size_t len) +{ + if (mailstream_write(fd, atom, len) == -1) + return MAILIMAP_ERROR_STREAM; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_token_send(mailstream * fd, const char * atom) +{ + if (mailstream_write(fd, atom, strlen(atom)) == -1) + return MAILIMAP_ERROR_STREAM; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_char_send(mailstream * fd, char ch) +{ + if (mailstream_write(fd, &ch, 1) == -1) + return MAILIMAP_ERROR_STREAM; + + return MAILIMAP_NO_ERROR; +} + +typedef int mailimap_struct_sender(mailstream * fd, void * data); + +static int +mailimap_struct_list_send(mailstream * fd, clist * list, + char symbol, + mailimap_struct_sender * sender) +{ + clistiter * cur; + void * elt; + int r; + + cur = clist_begin(list); + + if (cur == NULL) + return MAILIMAP_NO_ERROR; + + elt = clist_content(cur); + r = (* sender)(fd, elt); + if (r != MAILIMAP_NO_ERROR) + return r; + cur = clist_next(cur); + + while (cur != NULL) { + r = mailimap_char_send(fd, symbol); + if (r != MAILIMAP_NO_ERROR) + return r; + elt = clist_content(cur); + r = (* sender)(fd, elt); + if (r != MAILIMAP_NO_ERROR) + return r; + cur = clist_next(cur); + } + + return MAILIMAP_NO_ERROR; +} + + +static int +mailimap_struct_spaced_list_send(mailstream * fd, clist * list, + mailimap_struct_sender * sender) +{ + return mailimap_struct_list_send(fd, list, ' ', sender); +} + +int mailimap_space_send(mailstream * fd) +{ + return mailimap_char_send(fd, ' '); +} + +int mailimap_crlf_send(mailstream * fd) +{ + int r; + + r = mailimap_char_send(fd, '\r'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '\n'); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_oparenth_send(mailstream * fd) +{ + return mailimap_char_send(fd, '('); +} + +static int mailimap_cparenth_send(mailstream * fd) +{ + return mailimap_char_send(fd, ')'); +} + +static int mailimap_dquote_send(mailstream * fd) +{ + return mailimap_char_send(fd, '"'); +} + +/* + address = "(" addr-name SP addr-adl SP addr-mailbox SP + addr-host ")" + + addr-adl = nstring + ; Holds route from [RFC-822] route-addr if + ; non-NIL + + addr-host = nstring + ; NIL indicates [RFC-822] group syntax. + ; Otherwise, holds [RFC-822] domain name + + 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 + + addr-name = nstring + ; If non-NIL, holds phrase from [RFC-822] + ; mailbox after removing [RFC-822] quoting +*/ + +/* +=> append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP + literal +*/ + +int mailimap_append_send(mailstream * fd, + const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + size_t literal_size) +{ + int r; + + r = mailimap_token_send(fd, "APPEND"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + if (flag_list != NULL) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_flag_list_send(fd, flag_list); + if (r != MAILIMAP_NO_ERROR) + return r; + } + if (date_time != NULL) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_time_send(fd, date_time); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_literal_count_send(fd, literal_size); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + astring = 1*ASTRING-CHAR / string + +=> ASTRING-CHAR = ATOM-CHAR / resp-specials +*/ + +static int is_atom(const char * str) +{ + if (* str == '\0') + return 0; + + while (* str != '\0') { + unsigned char uch = (unsigned char) * str; + + if (!isalnum(uch)) + return 0; + + str ++; + } + + return 1; +} + +static int mailimap_astring_send(mailstream * fd, const char * astring) +{ + /* + workaround for buggy Courier-IMAP that does not accept + quoted-strings for fields name but prefer atoms. + */ + if (is_atom(astring)) + return mailimap_atom_send(fd, astring); + else + return mailimap_quoted_send(fd, astring); +} + +/* +=> atom = 1*ATOM-CHAR +*/ + +static int mailimap_atom_send(mailstream * fd, const char * atom) +{ + return mailimap_token_send(fd, atom); +} + +/* +=> ATOM-CHAR = <any CHAR except atom-specials> +*/ + +/* +=> atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards / + quoted-specials / resp-specials +*/ + +/* +=> authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64) +*/ + +int mailimap_authenticate_send(mailstream * fd, + const char * auth_type) +{ + int r; + + r = mailimap_token_send(fd, "AUTHENTICATE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_auth_type_send(fd, auth_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_authenticate_resp_send(mailstream * fd, + const char * base64) +{ + int r; + + r = mailimap_base64_send(fd, base64); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> auth-type = atom + ; Defined by [SASL] +*/ + +static int mailimap_auth_type_send(mailstream * fd, const char * auth_type) +{ + return mailimap_atom_send(fd, auth_type); +} + + +/* +=> base64 = *(4base64-char) [base64-terminal] +*/ + +static int mailimap_base64_send(mailstream * fd, const char * base64) +{ + return mailimap_token_send(fd, base64); +} + +/* +=> base64-char = ALPHA / DIGIT / "+" / "/" + ; Case-sensitive + + base64-terminal = (2base64-char "==") / (3base64-char "=") + + body = "(" (body-type-1part / body-type-mpart) ")" + + 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-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 + + 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 + + body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP + body-fld-enc SP body-fld-octets + + body-fld-desc = nstring + + body-fld-dsp = "(" string SP body-fld-param ")" / nil + + body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ + "QUOTED-PRINTABLE") DQUOTE) / string + + body-fld-id = nstring + + body-fld-lang = nstring / "(" string *(SP string) ")" + + body-fld-lines = number + + body-fld-md5 = nstring + + body-fld-octets = number + + body-fld-param = "(" string SP string *(SP string SP string) ")" / nil + + body-type-1part = (body-type-basic / body-type-msg / body-type-text) + [SP body-ext-1part] + + body-type-basic = media-basic SP body-fields + ; MESSAGE subtype MUST NOT be "RFC822" + + body-type-mpart = 1*body SP media-subtype + [SP body-ext-mpart] + + body-type-msg = media-message SP body-fields SP envelope + SP body SP body-fld-lines + + body-type-text = media-text SP body-fields SP body-fld-lines + + capability = ("AUTH=" auth-type) / atom + ; New capabilities MUST begin with "X" or be + ; registered with IANA as standard or + ; standards-track + + capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1" + *(SP capability) + ; IMAP4rev1 servers which offer RFC 1730 + ; compatibility MUST list "IMAP4" as the first + ; capability. + + CHAR8 = %x01-ff + ; any OCTET except NUL, %x00 +*/ + +/* +=> command = tag SP (command-any / command-auth / command-nonauth / + command-select) CRLF + ; Modal based on state +*/ + +/* +=> command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command + ; Valid in all states +*/ + +int mailimap_capability_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "CAPABILITY"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_logout_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "LOGOUT"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_noop_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "NOOP"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> command-auth = append / create / delete / examine / list / lsub / + rename / select / status / subscribe / unsubscribe + ; Valid only in Authenticated or Selected state +*/ + +/* +=> command-nonauth = login / authenticate + ; Valid only when in Not Authenticated state +*/ + +/* +=> command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store / + uid / search + ; Valid only when in Selected state +*/ + +int mailimap_check_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "CHECK"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_close_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "CLOSE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_expunge_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "EXPUNGE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + continue-req = "+" SP (resp-text / base64) CRLF +*/ + +/* +=> copy = "COPY" SP set SP mailbox +*/ + +int mailimap_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "COPY"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_set_send(fd, set); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_uid_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_copy_send(fd, set, mb); +} + +/* +=> create = "CREATE" SP mailbox + ; Use of INBOX gives a NO error +*/ + +int mailimap_create_send(mailstream * fd, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "CREATE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> date = date-text / DQUOTE date-text DQUOTE +*/ + +static int mailimap_date_send(mailstream * fd, + struct mailimap_date * date) +{ + int r; + + r = mailimap_date_day_send(fd, date->dt_day); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_month_send(fd, date->dt_month); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_year_send(fd, date->dt_year); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> date-day = 1*2DIGIT + ; Day of month +*/ + +static int mailimap_date_day_send(mailstream * fd, int day) +{ + return mailimap_number_send(fd, day); +} + +/* +=> date-day-fixed = (SP DIGIT) / 2DIGIT + ; Fixed-format version of date-day +*/ + +static int mailimap_date_day_fixed_send(mailstream * fd, int day) +{ + int r; + + if (day < 10) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_number_send(fd, day); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; + } + else + return mailimap_number_send(fd, day); +} + +/* +=> date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / + "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" +*/ + +static int mailimap_date_month_send(mailstream * fd, int month) +{ + const char * name; + int r; + + name = mailimap_month_get_token_str(month); + + if (name == NULL) + return MAILIMAP_ERROR_INVAL; + + r = mailimap_token_send(fd, name); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> date-text = date-day "-" date-month "-" date-year +*/ + +/* +static gboolean mailimap_date_text_send(mailstream * fd, + struct mailimap_date_text * date_text) +{ + if (!mailimap_date_day_send(fd, date_text->day)) + return FALSE; + if (!mailimap_char_send(fd, '-')) + return FALSE; + if (!mailimap_date_month_send(fd, date_text->month)) + return FALSE; + if (!mailimap_char_send(fd, '-')) + return FALSE; + if (!mailimap_date_year_send(fd, date_text->year)) + return FALSE; + + return TRUE; +} +*/ + +/* +=> date-year = 4DIGIT +*/ + +static int mailimap_fixed_digit_send(mailstream * fd, + int num, int count) +{ + int r; + + r = mailimap_fixed_digit_send(fd, num / 10, count); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_digit_send(fd, num % 10); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_date_year_send(mailstream *fd, int year) +{ + int r; + + r = mailimap_fixed_digit_send(fd, year, 4); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> date-time = DQUOTE date-day-fixed "-" date-month "-" date-year + SP time SP zone DQUOTE +*/ + +static int +mailimap_date_time_send(mailstream * fd, + struct mailimap_date_time * date_time) +{ + int r; + + r = mailimap_date_day_fixed_send(fd, date_time->dt_day); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_month_send(fd, date_time->dt_month); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_year_send(fd, date_time->dt_month); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fixed_digit_send(fd, date_time->dt_hour, 2); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ':'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fixed_digit_send(fd, date_time->dt_min, 2); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ':'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fixed_digit_send(fd, date_time->dt_sec, 2); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> delete = "DELETE" SP mailbox + ; Use of INBOX gives a NO error +*/ + +int mailimap_delete_send(mailstream * fd, const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "DELETE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + +digit + +digit-nz = %x31-39 + ; 1-9 +*/ + +static int mailimap_digit_send(mailstream * fd, int digit) +{ + return mailimap_char_send(fd, digit + '0'); +} + + +/* + 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 ")" + + env-bcc = "(" 1*address ")" / nil + + env-cc = "(" 1*address ")" / nil + + env-date = nstring + + env-from = "(" 1*address ")" / nil + + env-in-reply-to = nstring + + env-message-id = nstring + + env-reply-to = "(" 1*address ")" / nil + + env-sender = "(" 1*address ")" / nil + + env-subject = nstring + + env-to = "(" 1*address ")" / nil +*/ + +/* +=> examine = "EXAMINE" SP mailbox +*/ + +int mailimap_examine_send(mailstream * fd, const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "EXAMINE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att / + "(" fetch-att *(SP fetch-att) ")") +*/ + +static int +mailimap_fetch_att_list_send(mailstream * fd, clist * fetch_att_list); + +static int +mailimap_fetch_type_send(mailstream * fd, + struct mailimap_fetch_type * fetch_type) +{ + switch (fetch_type->ft_type) { + case MAILIMAP_FETCH_TYPE_ALL: + return mailimap_token_send(fd, "ALL"); + case MAILIMAP_FETCH_TYPE_FULL: + return mailimap_token_send(fd, "FULL"); + case MAILIMAP_FETCH_TYPE_FAST: + return mailimap_token_send(fd, "FAST"); + case MAILIMAP_FETCH_TYPE_FETCH_ATT: + return mailimap_fetch_att_send(fd, fetch_type->ft_data.ft_fetch_att); + case MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST: + return mailimap_fetch_att_list_send(fd, + fetch_type->ft_data.ft_fetch_att_list); + default: + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } +} + +int mailimap_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type) +{ + int r; + + r = mailimap_token_send(fd, "FETCH"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_set_send(fd, set); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fetch_type_send(fd, fetch_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int +mailimap_uid_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_fetch_send(fd, set, fetch_type); +} + +/* currently porting */ + +static int +mailimap_fetch_att_list_send(mailstream * fd, clist * fetch_att_list) +{ + int r; + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_send(fd, fetch_att_list, + (mailimap_struct_sender *) + mailimap_fetch_att_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" / + "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] / + "BODY" ["STRUCTURE"] / "UID" / + "BODY" [".PEEK"] section ["<" number "." nz-number ">"] +*/ + +static int mailimap_fetch_att_send(mailstream * fd, + struct mailimap_fetch_att * fetch_att) +{ + int r; + + switch(fetch_att->att_type) { + case MAILIMAP_FETCH_ATT_ENVELOPE: + return mailimap_token_send(fd, "ENVELOPE"); + + case MAILIMAP_FETCH_ATT_FLAGS: + return mailimap_token_send(fd, "FLAGS"); + + case MAILIMAP_FETCH_ATT_INTERNALDATE: + return mailimap_token_send(fd, "INTERNALDATE"); + + case MAILIMAP_FETCH_ATT_RFC822: + return mailimap_token_send(fd, "RFC822"); + + case MAILIMAP_FETCH_ATT_RFC822_HEADER: + return mailimap_token_send(fd, "RFC822.HEADER"); + + case MAILIMAP_FETCH_ATT_RFC822_SIZE: + return mailimap_token_send(fd, "RFC822.SIZE"); + + case MAILIMAP_FETCH_ATT_RFC822_TEXT: + return mailimap_token_send(fd, "RFC822.TEXT"); + + case MAILIMAP_FETCH_ATT_BODY: + return mailimap_token_send(fd, "BODY"); + + case MAILIMAP_FETCH_ATT_BODYSTRUCTURE: + return mailimap_token_send(fd, "BODYSTRUCTURE"); + + case MAILIMAP_FETCH_ATT_UID: + return mailimap_token_send(fd, "UID"); + + case MAILIMAP_FETCH_ATT_BODY_SECTION: + + r = mailimap_token_send(fd, "BODY"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_section_send(fd, fetch_att->att_section); + if (r != MAILIMAP_NO_ERROR) + return r; + if (fetch_att->att_size != 0) { + r = mailimap_char_send(fd, '<'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, fetch_att->att_offset); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '.'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, fetch_att->att_size); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '>'); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + return MAILIMAP_NO_ERROR; + + case MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION: + r = mailimap_token_send(fd, "BODY.PEEK"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_section_send(fd, fetch_att->att_section); + if (r != MAILIMAP_NO_ERROR) + return r; + if (fetch_att->att_size != 0) { + r = mailimap_char_send(fd, '<'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, fetch_att->att_offset); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '.'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, fetch_att->att_size); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '>'); + if (r != MAILIMAP_NO_ERROR) + return r; + } + return MAILIMAP_NO_ERROR; + + default: + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } +} + +/* +=> flag = "\Answered" / "\Flagged" / "\Deleted" / + "\Seen" / "\Draft" / flag-keyword / flag-extension + ; Does not include "\Recent" +*/ + +/* +enum { + FLAG_ANSWERED, + FLAG_FLAGGED, + FLAG_DELETED, + FLAG_SEEN, + FLAG_DRAFT, + FLAG_KEYWORD, + FLAG_EXTENSION +}; + +struct mailimap_flag { + gint type; + gchar * flag_keyword; + gchar * flag_extension; +}; +*/ + +static int mailimap_flag_send(mailstream * fd, + struct mailimap_flag * flag) +{ + switch(flag->fl_type) { + case MAILIMAP_FLAG_ANSWERED: + return mailimap_token_send(fd, "\\Answered"); + case MAILIMAP_FLAG_FLAGGED: + return mailimap_token_send(fd, "\\Flagged"); + case MAILIMAP_FLAG_DELETED: + return mailimap_token_send(fd, "\\Deleted"); + case MAILIMAP_FLAG_SEEN: + return mailimap_token_send(fd, "\\Seen"); + case MAILIMAP_FLAG_DRAFT: + return mailimap_token_send(fd, "\\Draft"); + case MAILIMAP_FLAG_KEYWORD: + return mailimap_flag_keyword_send(fd, flag->fl_data.fl_keyword); + case MAILIMAP_FLAG_EXTENSION: + return mailimap_flag_extension_send(fd, flag->fl_data.fl_extension); + default: + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } +} + + +/* +=> 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_send(mailstream * fd, + const char * flag_extension) +{ + int r; + + r = mailimap_char_send(fd, '\\'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_atom_send(fd, flag_extension); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + flag-fetch = flag / "\Recent" +*/ + +/* +=> flag-keyword = atom +*/ + +static int mailimap_flag_keyword_send(mailstream * fd, + const char * flag_keyword) +{ + return mailimap_token_send(fd, flag_keyword); +} + +/* +=> flag-list = "(" [flag *(SP flag)] ")" +*/ + +static int mailimap_flag_list_send(mailstream * fd, + struct mailimap_flag_list * flag_list) +{ + int r; + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (flag_list->fl_list != NULL) { + r = mailimap_struct_spaced_list_send(fd, flag_list->fl_list, + (mailimap_struct_sender *) mailimap_flag_send); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + flag-perm = flag / "\*" + + greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF +*/ + +/* +=> header-fld-name = astring +*/ + +static int mailimap_header_fld_name_send(mailstream * fd, const char * header) +{ + return mailimap_astring_send(fd, header); +} + +/* +=> header-list = "(" header-fld-name *(SP header-fld-name) ")" +*/ + +static int +mailimap_header_list_send(mailstream * fd, + struct mailimap_header_list * header_list) +{ + int r; + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_send(fd, header_list->hdr_list, + (mailimap_struct_sender *) mailimap_header_fld_name_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> list = "LIST" SP mailbox SP list-mailbox +*/ + +int mailimap_list_send(mailstream * fd, + const char * mb, + const char * list_mb) +{ + int r; + + r = mailimap_token_send(fd, "LIST"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_list_mailbox_send(fd, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> list-mailbox = 1*list-char / string +*/ + +static int +mailimap_list_mailbox_send(mailstream * fd, const char * pattern) +{ + return mailimap_quoted_send(fd, pattern); +} + +/* + list-char = ATOM-CHAR / list-wildcards / resp-specials + + list-wildcards = "%" / "*" +*/ + +/* +=> literal = "{" number "}" CRLF *CHAR8 + ; Number represents the number of CHAR8s +*/ + +int +mailimap_literal_send(mailstream * fd, const char * literal, + size_t progr_rate, + progress_function * progr_fun) +{ + uint32_t len; + int r; + + len = strlen(literal); + + r = mailimap_literal_count_send(fd, len); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_literal_data_send(fd, literal, len, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + "{" number "}" CRLF +*/ + +int +mailimap_literal_count_send(mailstream * fd, uint32_t count) +{ + int r; + + r = mailimap_char_send(fd, '{'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_number_send(fd, count); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '}'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + *CHAR8 +*/ + +int +mailimap_literal_data_send(mailstream * fd, const char * literal, uint32_t len, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + + r = mailimap_sized_token_send(fd, literal, len); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + + +/* +=> login = "LOGIN" SP userid SP password +*/ + +int mailimap_login_send(mailstream * fd, + const char * userid, const char * password) +{ + int r; + + r = mailimap_token_send(fd, "LOGIN"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_userid_send(fd, userid); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_password_send(fd, password); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> lsub = "LSUB" SP mailbox SP list-mailbox +*/ + +int mailimap_lsub_send(mailstream * fd, + const char * mb, const char * list_mb) +{ + int r; + + r = mailimap_token_send(fd, "LSUB"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_list_mailbox_send(fd, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + 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_send(mailstream * fd, const char * mb) +{ + return mailimap_astring_send(fd, mb); +} + +/* + 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" + + mailbox-list = "(" [mbx-list-flags] ")" SP + (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox + + mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag + *(SP mbx-list-oflag) / + mbx-list-oflag *(SP mbx-list-oflag) + + mbx-list-oflag = "\Noinferiors" / flag-extension + ; Other flags; multiple possible per LIST response + + mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked" + ; Selectability flags; only one per LIST response + + media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE) / string) SP media-subtype + ; Defined in [MIME-IMT] + + media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE + ; Defined in [MIME-IMT] + + media-subtype = string + ; Defined in [MIME-IMT] + + media-text = DQUOTE "TEXT" DQUOTE SP media-subtype + ; Defined in [MIME-IMT] + + message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att)) + + msg-att = "(" (msg-att-dynamic / msg-att-static) + *(SP (msg-att-dynamic / msg-att-static)) ")" + + msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")" + ; MAY change for a message + + 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 + + nil = "NIL" + + nstring = string / nil +*/ + +/* +=> number = 1*DIGIT + ; Unsigned 32-bit integer + ; (0 <= n < 4,294,967,296) +*/ + +/* + nz-number = digit-nz *DIGIT + ; Non-zero unsigned 32-bit integer + ; (0 < n < 4,294,967,296) +*/ + +static int mailimap_number_send(mailstream * fd, uint32_t number) +{ + int r; + + if (number / 10 != 0) { + r = mailimap_number_send(fd, number / 10); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_digit_send(fd, number % 10); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> password = astring +*/ + +static int mailimap_password_send(mailstream * fd, const char * pass) +{ + return mailimap_astring_send(fd, pass); +} + +/* +=> quoted = DQUOTE *QUOTED-CHAR DQUOTE + +=> QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> / + "\" quoted-specials + +=> quoted-specials = DQUOTE / "\" +*/ + +static int is_quoted_specials(char ch) +{ + return (ch == '\"') || (ch == '\\'); +} + +static int mailimap_quoted_char_send(mailstream * fd, char ch) +{ + int r; + + if (is_quoted_specials(ch)) { + r = mailimap_char_send(fd, '\\'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, ch); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; + } + else + return mailimap_char_send(fd, ch); +} + +static int mailimap_quoted_send(mailstream * fd, const char * quoted) +{ + const char * pos; + int r; + + pos = quoted; + + r = mailimap_dquote_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + while (* pos != 0) { + r = mailimap_quoted_char_send(fd, * pos); + if (r != MAILIMAP_NO_ERROR) + return r; + pos ++; + } + + r = mailimap_dquote_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> rename = "RENAME" SP mailbox SP mailbox + ; Use of INBOX as a destination gives a NO error +*/ + +int mailimap_rename_send(mailstream * fd, const char * mb, + const char * new_name) +{ + int r; + + r = mailimap_token_send(fd, "RENAME"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, new_name); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + response = *(continue-req / response-data) response-done + + response-data = "*" SP (resp-cond-state / resp-cond-bye / + mailbox-data / message-data / capability-data) CRLF + + response-done = response-tagged / response-fatal + + response-fatal = "*" SP resp-cond-bye CRLF + ; Server closes connection immediately + + response-tagged = tag SP resp-cond-state CRLF + + resp-cond-auth = ("OK" / "PREAUTH") SP resp-text + ; Authentication condition + + resp-cond-bye = "BYE" SP resp-text + + resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text + ; Status condition + + resp-specials = "]" + + resp-text = ["[" resp-text-code "]" SP] text + + 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*<any TEXT-CHAR except "]">] +*/ + +/* +=> search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key) + ; CHARSET argument to MUST be registered with IANA +*/ + +int +mailimap_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key) +{ + int r; + + r = mailimap_token_send(fd, "SEARCH"); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (charset != NULL) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_send(fd, "CHARSET"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, charset); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_search_key_send(fd, key); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int +mailimap_uid_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_search_send(fd, charset, key); +} + + +/* +=> 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) ")" +*/ + + +static int mailimap_search_key_send(mailstream * fd, + struct mailimap_search_key * key) +{ + int r; + + switch (key->sk_type) { + + case MAILIMAP_SEARCH_KEY_ALL: + return mailimap_token_send(fd, "ALL"); + + case MAILIMAP_SEARCH_KEY_ANSWERED: + return mailimap_token_send(fd, "ANSWERED"); + + case MAILIMAP_SEARCH_KEY_BCC: + r = mailimap_token_send(fd, "BCC"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_bcc); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_BEFORE: + r = mailimap_token_send(fd, "BEFORE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_before); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_BODY: + r = mailimap_token_send(fd, "BODY"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_body); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_CC: + r = mailimap_token_send(fd, "CC"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_cc); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_DELETED: + return mailimap_token_send(fd, "DELETED"); + + case MAILIMAP_SEARCH_KEY_FLAGGED: + return mailimap_token_send(fd, "FLAGGED"); + + case MAILIMAP_SEARCH_KEY_FROM: + r = mailimap_token_send(fd, "FROM"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_from); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_KEYWORD: + r = mailimap_token_send(fd, "KEYWORD"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_flag_keyword_send(fd, key->sk_data.sk_keyword); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_NEW: + return mailimap_token_send(fd, "NEW"); + + case MAILIMAP_SEARCH_KEY_OLD: + return mailimap_token_send(fd, "OLD"); + + case MAILIMAP_SEARCH_KEY_ON: + r = mailimap_token_send(fd, "ON"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_on); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_RECENT: + return mailimap_token_send(fd, "RECENT"); + + case MAILIMAP_SEARCH_KEY_SEEN: + return mailimap_token_send(fd, "SEEN"); + + case MAILIMAP_SEARCH_KEY_SINCE: + r = mailimap_token_send(fd, "SINCE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_since); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_SUBJECT: + r = mailimap_token_send(fd, "SUBJECT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_subject); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_TEXT: + r = mailimap_token_send(fd, "TEXT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_text); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_TO: + r = mailimap_token_send(fd, "TO"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_text); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_UNANSWERED: + return mailimap_token_send(fd, "UNANSWERED"); + + case MAILIMAP_SEARCH_KEY_UNDELETED: + return mailimap_token_send(fd, "UNDELETED"); + + case MAILIMAP_SEARCH_KEY_UNFLAGGED: + return mailimap_token_send(fd, "UNFLAGGED"); + + case MAILIMAP_SEARCH_KEY_UNKEYWORD: + r = mailimap_token_send(fd, "UNKEYWORD"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_flag_keyword_send(fd, key->sk_data.sk_keyword); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_UNSEEN: + return mailimap_token_send(fd, "UNSEEN"); + + case MAILIMAP_SEARCH_KEY_DRAFT: + return mailimap_token_send(fd, "DRAFT"); + + case MAILIMAP_SEARCH_KEY_HEADER: + r = mailimap_token_send(fd, "HEADER"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_header_fld_name_send(fd, + key->sk_data.sk_header.sk_header_name); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, + key->sk_data.sk_header.sk_header_value); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_LARGER: + r = mailimap_token_send(fd, "LARGER"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, key->sk_data.sk_larger); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_NOT: + r = mailimap_token_send(fd, "NOT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_search_key_send(fd, key->sk_data.sk_not); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_OR: + r = mailimap_token_send(fd, "OR"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_search_key_send(fd, key->sk_data.sk_or.sk_or1); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_search_key_send(fd, key->sk_data.sk_or.sk_or2); + if (r != MAILIMAP_NO_ERROR) + return r; + return TRUE; + + case MAILIMAP_SEARCH_KEY_SENTBEFORE: + r = mailimap_token_send(fd, "SENTBEFORE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_sentbefore); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_SENTON: + r = mailimap_token_send(fd, "SENTON"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_senton); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_SENTSINCE: + r = mailimap_token_send(fd, "SENTSINCE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_sentsince); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_SMALLER: + r = mailimap_token_send(fd, "SMALLER"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, key->sk_data.sk_smaller); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_UID: + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_set_send(fd, key->sk_data.sk_set); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_UNDRAFT: + return mailimap_token_send(fd, "UNDRAFT"); + + case MAILIMAP_SEARCH_KEY_SET: + return mailimap_set_send(fd, key->sk_data.sk_set); + + case MAILIMAP_SEARCH_KEY_MULTIPLE: + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_send(fd, key->sk_data.sk_multiple, + (mailimap_struct_sender *) + mailimap_search_key_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; + default: + /* should not happend */ + return MAILIMAP_ERROR_INVAL; + } +} + +/* +=> section = "[" [section-spec] "]" +*/ + +static int +mailimap_section_send(mailstream * fd, + struct mailimap_section * section) +{ + int r; + + r = mailimap_char_send(fd, '['); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (section != NULL) { + if (section->sec_spec != NULL) { + r = mailimap_section_spec_send(fd, section->sec_spec); + if (r != MAILIMAP_NO_ERROR) + return r; + } + } + + r = mailimap_char_send(fd, ']'); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list / + "TEXT" + ; top-level or MESSAGE/RFC822 part +*/ + +static int +mailimap_section_msgtext_send(mailstream * fd, + struct mailimap_section_msgtext * + section_msgtext) +{ + int r; + + switch (section_msgtext->sec_type) { + case MAILIMAP_SECTION_MSGTEXT_HEADER: + return mailimap_token_send(fd, "HEADER"); + + case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS: + r = mailimap_token_send(fd, "HEADER.FIELDS"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_header_list_send(fd, section_msgtext->sec_header_list); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT: + r = mailimap_token_send(fd, "HEADER.FIELDS.NOT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_header_list_send(fd, section_msgtext->sec_header_list); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SECTION_MSGTEXT_TEXT: + return mailimap_token_send(fd, "TEXT"); + + default: + /* should not happend */ + return MAILIMAP_ERROR_INVAL; + } +} + +/* +=> section-part = nz-number *("." nz-number) + ; body part nesting +*/ + +static int +mailimap_pnumber_send(mailstream * fd, uint32_t * pnumber) +{ + return mailimap_number_send(fd, * pnumber); +} + +static int +mailimap_section_part_send(mailstream * fd, + struct mailimap_section_part * section) +{ + int r; + + r = mailimap_struct_list_send(fd, section->sec_id, '.', + (mailimap_struct_sender *) mailimap_pnumber_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> section-spec = section-msgtext / (section-part ["." section-text]) +*/ + +static int +mailimap_section_spec_send(mailstream * fd, + struct mailimap_section_spec * section_spec) +{ + int r; + + switch (section_spec->sec_type) { + case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT: + return mailimap_section_msgtext_send(fd, + section_spec->sec_data.sec_msgtext); + + case MAILIMAP_SECTION_SPEC_SECTION_PART: + r = mailimap_section_part_send(fd, section_spec->sec_data.sec_part); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (section_spec->sec_text != NULL) { + r = mailimap_char_send(fd, '.'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_section_text_send(fd, + section_spec->sec_text); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + return MAILIMAP_NO_ERROR; + + default: + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } +} + +/* +=> section-text = section-msgtext / "MIME" + ; text other than actual body part (headers, etc.) +*/ + +static int +mailimap_section_text_send(mailstream * fd, + struct mailimap_section_text * section_text) +{ + switch (section_text->sec_type) { + case MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT: + return mailimap_section_msgtext_send(fd, section_text->sec_msgtext); + + case MAILIMAP_SECTION_TEXT_MIME: + return mailimap_token_send(fd, "MIME"); + + default: + /* should not happen */ + return MAILIMAP_NO_ERROR; + } +} + +/* +=> select = "SELECT" SP mailbox +*/ + +int +mailimap_select_send(mailstream * fd, const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "SELECT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> 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. +*/ + +/* if sequence_num == 0 then "*" */ + +static int +mailimap_sequence_num_send(mailstream * fd, uint32_t sequence_num) +{ + if (sequence_num == 0) + return mailimap_char_send(fd, '*'); + else + return mailimap_number_send(fd, sequence_num); +} + +/* +=> 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. +*/ + +static int mailimap_set_item_send(mailstream * fd, + struct mailimap_set_item * item) +{ + int r; + + if (item->set_first == item->set_last) + return mailimap_sequence_num_send(fd, item->set_first); + else { + r = mailimap_sequence_num_send(fd, item->set_first); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, ':'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_sequence_num_send(fd, item->set_last); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + } +} + +static int mailimap_set_send(mailstream * fd, + struct mailimap_set * set) +{ + return mailimap_struct_list_send(fd, set->set_list, ',', + (mailimap_struct_sender *) mailimap_set_item_send); +} + +/* +=> status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")" +*/ + +static int +mailimap_status_att_list_send(mailstream * fd, + struct mailimap_status_att_list * status_att_list) +{ + return mailimap_struct_spaced_list_send(fd, status_att_list->att_list, + (mailimap_struct_sender *) mailimap_status_att_send); +} + +int +mailimap_status_send(mailstream * fd, const char * mb, + struct mailimap_status_att_list * status_att_list) +{ + int r; + + r = mailimap_token_send(fd, "STATUS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '('); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_status_att_list_send(fd, status_att_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ')'); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / + "UNSEEN" +*/ + + +static int mailimap_status_att_send(mailstream * fd, int * status_att) +{ + const char * token; + + token = mailimap_status_att_get_token_str(* status_att); + if (token == NULL) { + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } + + return mailimap_token_send(fd, token); +} + +/* +=> store = "STORE" SP set SP store-att-flags +*/ + +int +mailimap_store_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags) +{ + int r; + + r = mailimap_token_send(fd, "STORE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_set_send(fd, set); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_store_att_flags_send(fd, store_att_flags); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int +mailimap_uid_store_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_store_send(fd, set, store_att_flags); +} + +/* +=> store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP + (flag-list / (flag *(SP flag))) +*/ + +static int +mailimap_store_att_flags_send(mailstream * fd, + struct mailimap_store_att_flags * store_flags) +{ + int r; + + switch (store_flags->fl_sign) { + case 1: + r = mailimap_char_send(fd, '+'); + if (r != MAILIMAP_NO_ERROR) + return r; + case -1: + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_token_send(fd, "FLAGS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (store_flags->fl_silent) { + r = mailimap_token_send(fd, ".SILENT"); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_flag_list_send(fd, store_flags->fl_flag_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + string = quoted / literal +*/ + +/* +=> subscribe = "SUBSCRIBE" SP mailbox +*/ + +int mailimap_subscribe_send(mailstream * fd, const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "SUBSCRIBE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> tag = 1*<any ASTRING-CHAR except "+"> +*/ + +int mailimap_tag_send(mailstream * fd, const char * tag) +{ + return mailimap_token_send(fd, tag); +} + +/* + text = 1*TEXT-CHAR + + TEXT-CHAR = <any CHAR except CR and LF> + + time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + ; Hours minutes seconds +*/ + +/* +=> uid = "UID" SP (copy / fetch / search / store) + ; Unique identifiers used instead of message + ; sequence numbers + +functions uid_copy, uid_fetch ... +*/ + + +/* + uniqueid = nz-number + ; Strictly ascending +*/ + +/* +=> unsubscribe = "UNSUBSCRIBE" SP mailbox +*/ + +int mailimap_unsubscribe_send(mailstream * fd, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "UNSUBSCRIBE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_starttls_send(mailstream * fd) +{ + return mailimap_token_send(fd, "STARTTLS"); +} + +/* +=> userid = astring +*/ + +static int mailimap_userid_send(mailstream * fd, const char * user) +{ + return mailimap_astring_send(fd, user); +} + +/* + x-command = "X" atom <experimental command arguments> + + 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". +*/ diff --git a/kmicromail/libetpan/imap/mailimap_sender.h b/kmicromail/libetpan/imap/mailimap_sender.h new file mode 100644 index 0000000..3fc30ea --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_sender.h @@ -0,0 +1,164 @@ +/* + * 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$ + */ + +#ifndef MAILIMAP_SENDER_H + +#define MAILIMAP_SENDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +int mailimap_append_send(mailstream * fd, + const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + size_t literal_size); + +int mailimap_authenticate_send(mailstream * fd, + const char * auth_type); + +int mailimap_authenticate_resp_send(mailstream * fd, + const char * base64); + +int mailimap_noop_send(mailstream * fd); + +int mailimap_logout_send(mailstream * fd); + +int mailimap_capability_send(mailstream * fd); + +int mailimap_check_send(mailstream * fd); + +int mailimap_close_send(mailstream * fd); + +int mailimap_expunge_send(mailstream * fd); + +int mailimap_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb); + +int mailimap_uid_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb); + +int mailimap_create_send(mailstream * fd, + const char * mb); + + +int mailimap_delete_send(mailstream * fd, const char * mb); + +int mailimap_examine_send(mailstream * fd, const char * mb); + +int +mailimap_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type); + +int +mailimap_uid_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type); + +int mailimap_list_send(mailstream * fd, + const char * mb, const char * list_mb); + +int mailimap_login_send(mailstream * fd, + const char * userid, const char * password); + +int mailimap_lsub_send(mailstream * fd, + const char * mb, const char * list_mb); + +int mailimap_rename_send(mailstream * fd, const char * mb, + const char * new_name); + +int +mailimap_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key); + +int +mailimap_uid_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key); + +int +mailimap_select_send(mailstream * fd, const char * mb); + +int +mailimap_status_send(mailstream * fd, const char * mb, + struct mailimap_status_att_list * status_att_list); + +int +mailimap_store_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +int +mailimap_uid_store_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +int mailimap_subscribe_send(mailstream * fd, const char * mb); + + +int mailimap_tag_send(mailstream * fd, const char * tag); + +int mailimap_unsubscribe_send(mailstream * fd, + const char * mb); + +int mailimap_crlf_send(mailstream * fd); + +int mailimap_space_send(mailstream * fd); + +int +mailimap_literal_send(mailstream * fd, const char * literal, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_literal_count_send(mailstream * fd, uint32_t count); + +int +mailimap_literal_data_send(mailstream * fd, const char * literal, uint32_t len, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_starttls_send(mailstream * fd); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imap/mailimap_socket.c b/kmicromail/libetpan/imap/mailimap_socket.c new file mode 100644 index 0000000..6f846f2 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_socket.c @@ -0,0 +1,73 @@ +/* + * 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 "mailimap_socket.h" + +#include "mailimap.h" + +#include "connect.h" +#include <netinet/in.h> +#include <unistd.h> + +#define DEFAULT_IMAP_PORT 143 +#define SERVICE_NAME_IMAP "imap2" +#define SERVICE_TYPE_TCP "tcp" + +int mailimap_socket_connect(mailimap * f, const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_IMAP, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_IMAP_PORT; + port = ntohs(port); + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return MAILIMAP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_socket_open(s); + if (stream == NULL) { + close(s); + return MAILIMAP_ERROR_MEMORY; + } + + return mailimap_connect(f, stream); +} diff --git a/kmicromail/libetpan/imap/mailimap_socket.h b/kmicromail/libetpan/imap/mailimap_socket.h new file mode 100644 index 0000000..aadc67e --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_socket.h @@ -0,0 +1,54 @@ +/* + * 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$ + */ + +#ifndef MAILIMAP_SOCKET_H + +#define MAILIMAP_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <inttypes.h> + +#include <libetpan/mailimap_types.h> + +int mailimap_socket_connect(mailimap * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imap/mailimap_ssl.c b/kmicromail/libetpan/imap/mailimap_ssl.c new file mode 100644 index 0000000..ace5678 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_ssl.c @@ -0,0 +1,73 @@ +/* + * 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 "mailimap_ssl.h" + +#include "mailimap.h" + +#include "connect.h" +#include <netinet/in.h> +#include <unistd.h> + +#define DEFAULT_IMAPS_PORT 993 +#define SERVICE_NAME_IMAPS "imaps" +#define SERVICE_TYPE_TCP "tcp" + +int mailimap_ssl_connect(mailimap * f, const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_IMAPS, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_IMAPS_PORT; + port = ntohs(port); + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return MAILIMAP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_ssl_open(s); + if (stream == NULL) { + close(s); + return MAILIMAP_ERROR_CONNECTION_REFUSED; + } + + return mailimap_connect(f, stream); +} diff --git a/kmicromail/libetpan/imap/mailimap_ssl.h b/kmicromail/libetpan/imap/mailimap_ssl.h new file mode 100644 index 0000000..76906a0 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_ssl.h @@ -0,0 +1,54 @@ +/* + * 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$ + */ + +#ifndef MAILIMAP_SSL_H + +#define MAILIMAP_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <inttypes.h> + +#include <libetpan/mailimap_types.h> + +int mailimap_ssl_connect(mailimap * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/imap/mailimap_types.c b/kmicromail/libetpan/imap/mailimap_types.c new file mode 100644 index 0000000..c5dde7c --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_types.c @@ -0,0 +1,2961 @@ +/* + * 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 "mailimap_types.h" +#include "mmapstring.h" +#include "mail.h" + +#include <stdlib.h> + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + + + +/* from parser */ + + +uint32_t * mailimap_number_alloc_new(uint32_t number) +{ + uint32_t * pnumber; + + pnumber = malloc(sizeof(* pnumber)); + if (pnumber == NULL) + return NULL; + + * pnumber = number; + + return pnumber; +} + +void mailimap_number_alloc_free(uint32_t * pnumber) +{ + free(pnumber); +} + + +/* ************************************************************************* */ + + +struct mailimap_address * +mailimap_address_new(char * ad_personal_name, char * ad_source_route, + char * ad_mailbox_name, char * ad_host_name) +{ + struct mailimap_address * addr; + + addr = malloc(sizeof(* addr)); + if (addr == NULL) + return NULL; + + addr->ad_personal_name = ad_personal_name; + addr->ad_source_route = ad_source_route; + addr->ad_mailbox_name = ad_mailbox_name; + addr->ad_host_name = ad_host_name; + + return addr; +} + +void mailimap_address_free(struct mailimap_address * addr) +{ + mailimap_addr_host_free(addr->ad_host_name); + mailimap_addr_mailbox_free(addr->ad_mailbox_name); + mailimap_addr_adl_free(addr->ad_source_route); + mailimap_addr_name_free(addr->ad_personal_name); + free(addr); +} + +void mailimap_addr_host_free(char * addr_host) +{ + mailimap_nstring_free(addr_host); +} + +void mailimap_addr_mailbox_free(char * addr_mailbox) +{ + mailimap_nstring_free(addr_mailbox); +} + +void mailimap_addr_adl_free(char * addr_adl) +{ + mailimap_nstring_free(addr_adl); +} + +void mailimap_addr_name_free(char * addr_name) +{ + mailimap_nstring_free(addr_name); +} + + + + + +/* +struct mailimap_astring * +mailimap_astring_new(gint type, + gchar * atom_astring, + gchar * string) +{ + struct mailimap_astring * astring; + + astring = g_new(struct mailimap_astring, 1); + if (astring == NULL) + return FALSE; + + astring->type = type; + astring->atom_astring = atom_astring; + astring->string = string; + + return astring; +} + +void mailimap_astring_free(struct mailimap_astring * astring) +{ + if (astring->atom_astring) + mailimap_atom_astring_free(astring->atom_astring); + if (astring->string) + mailimap_string_free(astring->string); + free(astring); +} +*/ + +void mailimap_astring_free(char * astring) +{ + if (mmap_string_unref(astring) != 0) + free(astring); +} + +static void mailimap_custom_string_free(char * str) +{ + free(str); +} + + +void mailimap_atom_free(char * atom) +{ + free(atom); +} + + + + +void mailimap_auth_type_free(char * auth_type) +{ + mailimap_atom_free(auth_type); +} + + + + + +void mailimap_base64_free(char * base64) +{ + free(base64); +} + + + + +struct mailimap_body * +mailimap_body_new(int bd_type, + struct mailimap_body_type_1part * bd_body_1part, + struct mailimap_body_type_mpart * bd_body_mpart) +{ + struct mailimap_body * body; + + body = malloc(sizeof(* body)); + if (body == NULL) + return NULL; + + body->bd_type = bd_type; + switch (bd_type) { + case MAILIMAP_BODY_1PART: + body->bd_data.bd_body_1part = bd_body_1part; + break; + case MAILIMAP_BODY_MPART: + body->bd_data.bd_body_mpart = bd_body_mpart; + break; + } + + return body; +} + +void mailimap_body_free(struct mailimap_body * body) +{ + switch (body->bd_type) { + case MAILIMAP_BODY_1PART: + mailimap_body_type_1part_free(body->bd_data.bd_body_1part); + break; + case MAILIMAP_BODY_MPART: + mailimap_body_type_mpart_free(body->bd_data.bd_body_mpart); + break; + } + free(body); +} + + +struct mailimap_body_extension * +mailimap_body_extension_new(int ext_type, char * ext_nstring, + uint32_t ext_number, + clist * ext_body_extension_list) +{ + struct mailimap_body_extension * body_extension; + + body_extension = malloc(sizeof(* body_extension)); + if (body_extension == NULL) + return NULL; + + body_extension->ext_type = ext_type; + switch (ext_type) { + case MAILIMAP_BODY_EXTENSION_NSTRING: + body_extension->ext_data.ext_nstring = ext_nstring; + break; + case MAILIMAP_BODY_EXTENSION_NUMBER: + body_extension->ext_data.ext_number = ext_number; + break; + case MAILIMAP_BODY_EXTENSION_LIST: + body_extension->ext_data.ext_body_extension_list = ext_body_extension_list; + break; + } + + return body_extension; +} + +static void +mailimap_body_ext_list_free(clist * body_ext_list); + +void mailimap_body_extension_free(struct mailimap_body_extension * be) +{ + switch (be->ext_type) { + case MAILIMAP_BODY_EXTENSION_NSTRING: + mailimap_nstring_free(be->ext_data.ext_nstring); + break; + case MAILIMAP_BODY_EXTENSION_LIST: + mailimap_body_ext_list_free(be->ext_data.ext_body_extension_list); + break; + } + + free(be); +} + + +static void +mailimap_body_ext_list_free(clist * body_ext_list) +{ + clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free, + NULL); + clist_free(body_ext_list); +} + + +struct mailimap_body_ext_1part * +mailimap_body_ext_1part_new(char * bd_md5, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + clist * bd_extension_list) +{ + struct mailimap_body_ext_1part * body_ext_1part; + + body_ext_1part = malloc(sizeof(* body_ext_1part)); + if (body_ext_1part == NULL) + return NULL; + + body_ext_1part->bd_md5 = bd_md5; + body_ext_1part->bd_disposition = bd_disposition; + body_ext_1part->bd_language = bd_language; + body_ext_1part->bd_extension_list = bd_extension_list; + + return body_ext_1part; +} + +void +mailimap_body_ext_1part_free(struct mailimap_body_ext_1part * body_ext_1part) +{ + mailimap_body_fld_md5_free(body_ext_1part->bd_md5); + if (body_ext_1part->bd_disposition) + mailimap_body_fld_dsp_free(body_ext_1part->bd_disposition); + if (body_ext_1part->bd_language) + mailimap_body_fld_lang_free(body_ext_1part->bd_language); + if (body_ext_1part->bd_extension_list) + mailimap_body_ext_list_free(body_ext_1part->bd_extension_list); + + free(body_ext_1part); +} + +struct mailimap_body_ext_mpart * +mailimap_body_ext_mpart_new(struct mailimap_body_fld_param * bd_parameter, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + clist * bd_extension_list) +{ + struct mailimap_body_ext_mpart * body_ext_mpart; + + body_ext_mpart = malloc(sizeof(* body_ext_mpart)); + if (body_ext_mpart == NULL) + return NULL; + + body_ext_mpart->bd_parameter = bd_parameter; + body_ext_mpart->bd_disposition = bd_disposition; + body_ext_mpart->bd_language = bd_language; + body_ext_mpart->bd_extension_list = bd_extension_list; + + return body_ext_mpart; +} + +void +mailimap_body_ext_mpart_free(struct mailimap_body_ext_mpart * body_ext_mpart) +{ + if (body_ext_mpart->bd_parameter != NULL) + mailimap_body_fld_param_free(body_ext_mpart->bd_parameter); + if (body_ext_mpart->bd_disposition) + mailimap_body_fld_dsp_free(body_ext_mpart->bd_disposition); + if (body_ext_mpart->bd_language) + mailimap_body_fld_lang_free(body_ext_mpart->bd_language); + if (body_ext_mpart->bd_extension_list) + mailimap_body_ext_list_free(body_ext_mpart->bd_extension_list); + free(body_ext_mpart); +} + + +struct mailimap_body_fields * +mailimap_body_fields_new(struct mailimap_body_fld_param * bd_parameter, + char * bd_id, + char * bd_description, + struct mailimap_body_fld_enc * bd_encoding, + uint32_t bd_size) +{ + struct mailimap_body_fields * body_fields; + + body_fields = malloc(sizeof(* body_fields)); + if (body_fields == NULL) + return NULL; + body_fields->bd_parameter = bd_parameter; + body_fields->bd_id = bd_id; + body_fields->bd_description = bd_description; + body_fields->bd_encoding = bd_encoding; + body_fields->bd_size = bd_size; + + return body_fields; +} + +void +mailimap_body_fields_free(struct mailimap_body_fields * body_fields) +{ + if (body_fields->bd_parameter != NULL) + mailimap_body_fld_param_free(body_fields->bd_parameter); + mailimap_body_fld_id_free(body_fields->bd_id); + mailimap_body_fld_desc_free(body_fields->bd_description); + mailimap_body_fld_enc_free(body_fields->bd_encoding); + free(body_fields); +} + + + + + + +void mailimap_body_fld_desc_free(char * body_fld_desc) +{ + mailimap_nstring_free(body_fld_desc); +} + + + + +struct mailimap_body_fld_dsp * +mailimap_body_fld_dsp_new(char * dsp_type, + struct mailimap_body_fld_param * dsp_attributes) +{ + struct mailimap_body_fld_dsp * body_fld_dsp; + + body_fld_dsp = malloc(sizeof(* body_fld_dsp)); + if (body_fld_dsp == NULL) + return NULL; + + body_fld_dsp->dsp_type = dsp_type; + body_fld_dsp->dsp_attributes = dsp_attributes; + + return body_fld_dsp; +} + +void mailimap_body_fld_dsp_free(struct mailimap_body_fld_dsp * bfd) +{ + if (bfd->dsp_type != NULL) + mailimap_string_free(bfd->dsp_type); + if (bfd->dsp_attributes != NULL) + mailimap_body_fld_param_free(bfd->dsp_attributes); + free(bfd); +} + + + +struct mailimap_body_fld_enc * +mailimap_body_fld_enc_new(int enc_type, char * enc_value) +{ + struct mailimap_body_fld_enc * body_fld_enc; + + body_fld_enc = malloc(sizeof(* body_fld_enc)); + if (body_fld_enc == NULL) + return NULL; + + body_fld_enc->enc_type = enc_type; + body_fld_enc->enc_value = enc_value; + + return body_fld_enc; +} + +void mailimap_body_fld_enc_free(struct mailimap_body_fld_enc * bfe) +{ + if (bfe->enc_value) + mailimap_string_free(bfe->enc_value); + free(bfe); +} + + + +void mailimap_body_fld_id_free(char * body_fld_id) +{ + mailimap_nstring_free(body_fld_id); +} + + + +struct mailimap_body_fld_lang * +mailimap_body_fld_lang_new(int lg_type, char * lg_single, clist * lg_list) +{ + struct mailimap_body_fld_lang * fld_lang; + + fld_lang = malloc(sizeof(* fld_lang)); + if (fld_lang == NULL) + return NULL; + + fld_lang->lg_type = lg_type; + switch (lg_type) { + case MAILIMAP_BODY_FLD_LANG_SINGLE: + fld_lang->lg_data.lg_single = lg_single; + break; + case MAILIMAP_BODY_FLD_LANG_LIST: + fld_lang->lg_data.lg_list = lg_list; + break; + } + + return fld_lang; +} + +void +mailimap_body_fld_lang_free(struct mailimap_body_fld_lang * fld_lang) +{ + switch (fld_lang->lg_type) { + case MAILIMAP_BODY_FLD_LANG_SINGLE: + mailimap_nstring_free(fld_lang->lg_data.lg_single); + break; + case MAILIMAP_BODY_FLD_LANG_LIST: + clist_foreach(fld_lang->lg_data.lg_list, + (clist_func) mailimap_string_free, NULL); + clist_free(fld_lang->lg_data.lg_list); + break; + } + free(fld_lang); +} + + + +void mailimap_body_fld_md5_free(char * body_fld_md5) +{ + mailimap_nstring_free(body_fld_md5); +} + + + +struct mailimap_single_body_fld_param * +mailimap_single_body_fld_param_new(char * pa_name, char * pa_value) +{ + struct mailimap_single_body_fld_param * param; + + param = malloc(sizeof(* param)); + if (param == NULL) + return NULL; + param->pa_name = pa_name; + param->pa_value = pa_value; + + return param; +} + +void +mailimap_single_body_fld_param_free(struct mailimap_single_body_fld_param * p) +{ + mailimap_string_free(p->pa_name); + mailimap_string_free(p->pa_value); + free(p); +} + + +struct mailimap_body_fld_param * +mailimap_body_fld_param_new(clist * pa_list) +{ + struct mailimap_body_fld_param * fld_param; + + fld_param = malloc(sizeof(* fld_param)); + if (fld_param == NULL) + return NULL; + fld_param->pa_list = pa_list; + + return fld_param; +} + +void +mailimap_body_fld_param_free(struct mailimap_body_fld_param * fld_param) +{ + clist_foreach(fld_param->pa_list, + (clist_func) mailimap_single_body_fld_param_free, NULL); + clist_free(fld_param->pa_list); + free(fld_param); +} + + +struct mailimap_body_type_1part * +mailimap_body_type_1part_new(int bd_type, + struct mailimap_body_type_basic * bd_type_basic, + struct mailimap_body_type_msg * bd_type_msg, + struct mailimap_body_type_text * bd_type_text, + struct mailimap_body_ext_1part * bd_ext_1part) +{ + struct mailimap_body_type_1part * body_type_1part; + + body_type_1part = malloc(sizeof(* body_type_1part)); + if (body_type_1part == NULL) + return NULL; + + body_type_1part->bd_type = bd_type; + switch (bd_type) { + case MAILIMAP_BODY_TYPE_1PART_BASIC: + body_type_1part->bd_data.bd_type_basic = bd_type_basic; + break; + case MAILIMAP_BODY_TYPE_1PART_MSG: + body_type_1part->bd_data.bd_type_msg = bd_type_msg; + break; + case MAILIMAP_BODY_TYPE_1PART_TEXT: + body_type_1part->bd_data.bd_type_text = bd_type_text; + break; + } + body_type_1part->bd_ext_1part = bd_ext_1part; + + return body_type_1part; +} + +void +mailimap_body_type_1part_free(struct mailimap_body_type_1part * bt1p) +{ + switch (bt1p->bd_type) { + case MAILIMAP_BODY_TYPE_1PART_BASIC: + mailimap_body_type_basic_free(bt1p->bd_data.bd_type_basic); + break; + case MAILIMAP_BODY_TYPE_1PART_MSG: + mailimap_body_type_msg_free(bt1p->bd_data.bd_type_msg); + break; + case MAILIMAP_BODY_TYPE_1PART_TEXT: + mailimap_body_type_text_free(bt1p->bd_data.bd_type_text); + break; + } + if (bt1p->bd_ext_1part) + mailimap_body_ext_1part_free(bt1p->bd_ext_1part); + + free(bt1p); +} + + + +struct mailimap_body_type_basic * +mailimap_body_type_basic_new(struct mailimap_media_basic * bd_media_basic, + struct mailimap_body_fields * bd_fields) +{ + struct mailimap_body_type_basic * body_type_basic; + + body_type_basic = malloc(sizeof(* body_type_basic)); + if (body_type_basic == NULL) + return NULL; + + body_type_basic->bd_media_basic = bd_media_basic; + body_type_basic->bd_fields = bd_fields; + + return body_type_basic; +} + +void mailimap_body_type_basic_free(struct mailimap_body_type_basic * + body_type_basic) +{ + mailimap_media_basic_free(body_type_basic->bd_media_basic); + mailimap_body_fields_free(body_type_basic->bd_fields); + free(body_type_basic); +} + + +struct mailimap_body_type_mpart * +mailimap_body_type_mpart_new(clist * bd_list, char * bd_media_subtype, + struct mailimap_body_ext_mpart * bd_ext_mpart) +{ + struct mailimap_body_type_mpart * body_type_mpart; + + body_type_mpart = malloc(sizeof(* body_type_mpart)); + if (body_type_mpart == NULL) + return NULL; + + body_type_mpart->bd_list = bd_list; + body_type_mpart->bd_media_subtype = bd_media_subtype; + body_type_mpart->bd_ext_mpart = bd_ext_mpart; + + return body_type_mpart; +} + +void mailimap_body_type_mpart_free(struct mailimap_body_type_mpart * + body_type_mpart) +{ + clist_foreach(body_type_mpart->bd_list, + (clist_func) mailimap_body_free, NULL); + clist_free(body_type_mpart->bd_list); + mailimap_media_subtype_free(body_type_mpart->bd_media_subtype); + if (body_type_mpart->bd_ext_mpart) + mailimap_body_ext_mpart_free(body_type_mpart->bd_ext_mpart); + + free(body_type_mpart); +} + + +struct mailimap_body_type_msg * +mailimap_body_type_msg_new(struct mailimap_body_fields * bd_fields, + struct mailimap_envelope * bd_envelope, + struct mailimap_body * bd_body, + uint32_t bd_lines) +{ + struct mailimap_body_type_msg * body_type_msg; + + body_type_msg = malloc(sizeof(* body_type_msg)); + if (body_type_msg == NULL) + return NULL; + + body_type_msg->bd_fields = bd_fields; + body_type_msg->bd_envelope = bd_envelope; + body_type_msg->bd_body = bd_body; + body_type_msg->bd_lines = bd_lines; + + return body_type_msg; +} + +void +mailimap_body_type_msg_free(struct mailimap_body_type_msg * body_type_msg) +{ + mailimap_body_fields_free(body_type_msg->bd_fields); + mailimap_envelope_free(body_type_msg->bd_envelope); + mailimap_body_free(body_type_msg->bd_body); + free(body_type_msg); +} + + + +struct mailimap_body_type_text * +mailimap_body_type_text_new(char * bd_media_text, + struct mailimap_body_fields * bd_fields, + uint32_t bd_lines) +{ + struct mailimap_body_type_text * body_type_text; + + body_type_text = malloc(sizeof(* body_type_text)); + if (body_type_text == NULL) + return NULL; + + body_type_text->bd_media_text = bd_media_text; + body_type_text->bd_fields = bd_fields; + body_type_text->bd_lines = bd_lines; + + return body_type_text; +} + +void +mailimap_body_type_text_free(struct mailimap_body_type_text * body_type_text) +{ + mailimap_media_text_free(body_type_text->bd_media_text); + mailimap_body_fields_free(body_type_text->bd_fields); + free(body_type_text); +} + + + +struct mailimap_capability * +mailimap_capability_new(int cap_type, char * cap_auth_type, char * cap_name) +{ + struct mailimap_capability * cap; + + cap = malloc(sizeof(* cap)); + if (cap == NULL) + return NULL; + cap->cap_type = cap_type; + switch (cap_type) { + case MAILIMAP_CAPABILITY_AUTH_TYPE: + cap->cap_data.cap_auth_type = cap_auth_type; + break; + case MAILIMAP_CAPABILITY_NAME: + cap->cap_data.cap_name = cap_name; + break; + } + + return cap; +} + +void mailimap_capability_free(struct mailimap_capability * c) +{ + switch (c->cap_type) { + case MAILIMAP_CAPABILITY_AUTH_TYPE: + free(c->cap_data.cap_auth_type); + break; + case MAILIMAP_CAPABILITY_NAME: + free(c->cap_data.cap_name); + break; + } + free(c); +} + + +struct mailimap_capability_data * +mailimap_capability_data_new(clist * cap_list) +{ + struct mailimap_capability_data * cap_data; + + cap_data = malloc(sizeof(* cap_data)); + if (cap_data == NULL) + return NULL; + + cap_data->cap_list = cap_list; + + return cap_data; +} + +void +mailimap_capability_data_free(struct mailimap_capability_data * cap_data) +{ + if (cap_data->cap_list) { + clist_foreach(cap_data->cap_list, + (clist_func) mailimap_capability_free, NULL); + clist_free(cap_data->cap_list); + } + free(cap_data); +} + + + + +struct mailimap_continue_req * +mailimap_continue_req_new(int cr_type, struct mailimap_resp_text * cr_text, + char * cr_base64) +{ + struct mailimap_continue_req * cont_req; + + cont_req = malloc(sizeof(* cont_req)); + if (cont_req == NULL) + return NULL; + cont_req->cr_type = cr_type; + switch (cr_type) { + case MAILIMAP_CONTINUE_REQ_TEXT: + cont_req->cr_data.cr_text = cr_text; + break; + case MAILIMAP_CONTINUE_REQ_BASE64: + cont_req->cr_data.cr_base64 = cr_base64; + break; + } + + return cont_req; +} + +void mailimap_continue_req_free(struct mailimap_continue_req * cont_req) +{ + switch (cont_req->cr_type) { + case MAILIMAP_CONTINUE_REQ_TEXT: + mailimap_resp_text_free(cont_req->cr_data.cr_text); + break; + case MAILIMAP_CONTINUE_REQ_BASE64: + mailimap_base64_free(cont_req->cr_data.cr_base64); + break; + } + free(cont_req); +} + +struct mailimap_date_time * +mailimap_date_time_new(int dt_day, int dt_month, int dt_year, int dt_hour, + int dt_min, int dt_sec, int dt_zone) +{ + struct mailimap_date_time * date_time; + + date_time = malloc(sizeof(* date_time)); + if (date_time == NULL) + return NULL; + + date_time->dt_day = dt_day; + date_time->dt_month = dt_month; + date_time->dt_year = dt_year; + date_time->dt_hour = dt_hour; + date_time->dt_min = dt_min; + date_time->dt_day = dt_sec; + date_time->dt_zone = dt_zone; + + return date_time; +} + +void mailimap_date_time_free(struct mailimap_date_time * date_time) +{ + free(date_time); +} + + + +struct mailimap_envelope * +mailimap_envelope_new(char * env_date, char * env_subject, + struct mailimap_env_from * env_from, + struct mailimap_env_sender * env_sender, + struct mailimap_env_reply_to * env_reply_to, + struct mailimap_env_to * env_to, + struct mailimap_env_cc* env_cc, + struct mailimap_env_bcc * env_bcc, + char * env_in_reply_to, char * env_message_id) +{ + struct mailimap_envelope * env; + + env = malloc(sizeof(* env)); + if (env == NULL) + return NULL; + + env->env_date = env_date; + env->env_subject = env_subject; + env->env_from = env_from; + env->env_sender = env_sender; + env->env_reply_to = env_reply_to; + env->env_to = env_to; + env->env_cc = env_cc; + env->env_bcc = env_bcc; + env->env_in_reply_to = env_in_reply_to; + env->env_message_id = env_message_id; + + return env; +} + + +void mailimap_envelope_free(struct mailimap_envelope * env) +{ + if (env->env_date) + mailimap_env_date_free(env->env_date); + if (env->env_subject) + mailimap_env_subject_free(env->env_subject); + if (env->env_from) + mailimap_env_from_free(env->env_from); + if (env->env_sender) + mailimap_env_sender_free(env->env_sender); + if (env->env_reply_to) + mailimap_env_reply_to_free(env->env_reply_to); + if (env->env_to) + mailimap_env_to_free(env->env_to); + if (env->env_cc) + mailimap_env_cc_free(env->env_cc); + if (env->env_bcc) + mailimap_env_bcc_free(env->env_bcc); + if (env->env_in_reply_to) + mailimap_env_in_reply_to_free(env->env_in_reply_to); + if (env->env_message_id) + mailimap_env_message_id_free(env->env_message_id); + + free(env); +} + + +static void mailimap_address_list_free(clist * addr_list) +{ + if (addr_list != NULL) { + clist_foreach(addr_list, (clist_func) mailimap_address_free, NULL); + clist_free(addr_list); + } +} + + +struct mailimap_env_bcc * mailimap_env_bcc_new(clist * bcc_list) +{ + struct mailimap_env_bcc * env_bcc; + + env_bcc = malloc(sizeof(* env_bcc)); + if (env_bcc == NULL) + return NULL; + env_bcc->bcc_list = bcc_list; + + return env_bcc; +} + +void mailimap_env_bcc_free(struct mailimap_env_bcc * env_bcc) +{ + mailimap_address_list_free(env_bcc->bcc_list); + free(env_bcc); +} + + +struct mailimap_env_cc * mailimap_env_cc_new(clist * cc_list) +{ + struct mailimap_env_cc * env_cc; + + env_cc = malloc(sizeof(* env_cc)); + if (env_cc == NULL) + return NULL; + env_cc->cc_list = cc_list; + + return env_cc; +} + +void mailimap_env_cc_free(struct mailimap_env_cc * env_cc) +{ + mailimap_address_list_free(env_cc->cc_list); + free(env_cc); +} + + +void mailimap_env_date_free(char * date) +{ + mailimap_nstring_free(date); +} + + +struct mailimap_env_from * mailimap_env_from_new(clist * frm_list) +{ + struct mailimap_env_from * env_from; + + env_from = malloc(sizeof(* env_from)); + if (env_from == NULL) + return NULL; + env_from->frm_list = frm_list; + + return env_from; +} + +void mailimap_env_from_free(struct mailimap_env_from * env_from) +{ + mailimap_address_list_free(env_from->frm_list); + free(env_from); +} + + +void mailimap_env_in_reply_to_free(char * in_reply_to) +{ + mailimap_nstring_free(in_reply_to); +} + +void mailimap_env_message_id_free(char * message_id) +{ + mailimap_nstring_free(message_id); +} + +struct mailimap_env_reply_to * mailimap_env_reply_to_new(clist * rt_list) +{ + struct mailimap_env_reply_to * env_reply_to; + + env_reply_to = malloc(sizeof(* env_reply_to)); + if (env_reply_to == NULL) + return NULL; + env_reply_to->rt_list = rt_list; + + return env_reply_to; +} + +void +mailimap_env_reply_to_free(struct mailimap_env_reply_to * env_reply_to) +{ + mailimap_address_list_free(env_reply_to->rt_list); + free(env_reply_to); +} + +struct mailimap_env_sender * mailimap_env_sender_new(clist * snd_list) +{ + struct mailimap_env_sender * env_sender; + + env_sender = malloc(sizeof(* env_sender)); + if (env_sender == NULL) + return NULL; + env_sender->snd_list = snd_list; + + return env_sender; +} + +void mailimap_env_sender_free(struct mailimap_env_sender * env_sender) +{ + mailimap_address_list_free(env_sender->snd_list); + free(env_sender); +} + +void mailimap_env_subject_free(char * subject) +{ + mailimap_nstring_free(subject); +} + +struct mailimap_env_to * mailimap_env_to_new(clist * to_list) +{ + struct mailimap_env_to * env_to; + + env_to = malloc(sizeof(* env_to)); + if (env_to == NULL) + return NULL; + env_to->to_list = to_list; + + return env_to; +} + +void mailimap_env_to_free(struct mailimap_env_to * env_to) +{ + mailimap_address_list_free(env_to->to_list); + free(env_to); +} + + + +struct mailimap_flag * mailimap_flag_new(int fl_type, + char * fl_keyword, char * fl_extension) +{ + struct mailimap_flag * f; + + f = malloc(sizeof(* f)); + if (f == NULL) + return NULL; + f->fl_type = fl_type; + switch (fl_type) { + case MAILIMAP_FLAG_KEYWORD: + f->fl_data.fl_keyword = fl_keyword; + break; + case MAILIMAP_FLAG_EXTENSION: + f->fl_data.fl_extension = fl_extension; + break; + } + + return f; +} + +void mailimap_flag_free(struct mailimap_flag * f) +{ + switch (f->fl_type) { + case MAILIMAP_FLAG_KEYWORD: + mailimap_flag_keyword_free(f->fl_data.fl_keyword); + break; + case MAILIMAP_FLAG_EXTENSION: + mailimap_flag_extension_free(f->fl_data.fl_extension); + break; + } + free(f); +} + + + +void mailimap_flag_extension_free(char * flag_extension) +{ + mailimap_atom_free(flag_extension); +} + + + +struct mailimap_flag_fetch * +mailimap_flag_fetch_new(int fl_type, struct mailimap_flag * fl_flag) +{ + struct mailimap_flag_fetch * flag_fetch; + + flag_fetch = malloc(sizeof(* flag_fetch)); + if (flag_fetch == NULL) + return NULL; + + flag_fetch->fl_type = fl_type; + flag_fetch->fl_flag = fl_flag; + + return flag_fetch; +} + +void mailimap_flag_fetch_free(struct mailimap_flag_fetch * flag_fetch) +{ + if (flag_fetch->fl_flag) + mailimap_flag_free(flag_fetch->fl_flag); + free(flag_fetch); +} + + + +void mailimap_flag_keyword_free(char * flag_keyword) +{ + mailimap_atom_free(flag_keyword); +} + + + + +struct mailimap_flag_list * +mailimap_flag_list_new(clist * fl_list) +{ + struct mailimap_flag_list * flag_list; + + flag_list = malloc(sizeof(* flag_list)); + if (flag_list == NULL) + return NULL; + flag_list->fl_list = fl_list; + + return flag_list; +} + +void mailimap_flag_list_free(struct mailimap_flag_list * flag_list) +{ + clist_foreach(flag_list->fl_list, (clist_func) mailimap_flag_free, NULL); + clist_free(flag_list->fl_list); + free(flag_list); +} + + + + + +struct mailimap_flag_perm * +mailimap_flag_perm_new(int fl_type, struct mailimap_flag * fl_flag) +{ + struct mailimap_flag_perm * flag_perm; + + flag_perm = malloc(sizeof(* flag_perm)); + if (flag_perm == NULL) + return NULL; + + flag_perm->fl_type = fl_type; + flag_perm->fl_flag = fl_flag; + + return flag_perm; +} + +void mailimap_flag_perm_free(struct mailimap_flag_perm * flag_perm) +{ + if (flag_perm->fl_flag != NULL) + mailimap_flag_free(flag_perm->fl_flag); + free(flag_perm); +} + + + + +struct mailimap_greeting * +mailimap_greeting_new(int gr_type, + struct mailimap_resp_cond_auth * gr_auth, + struct mailimap_resp_cond_bye * gr_bye) +{ + struct mailimap_greeting * greeting; + + greeting = malloc(sizeof(* greeting)); + if (greeting == NULL) + return NULL; + greeting->gr_type = gr_type; + switch (gr_type) { + case MAILIMAP_GREETING_RESP_COND_AUTH: + greeting->gr_data.gr_auth = gr_auth; + break; + case MAILIMAP_GREETING_RESP_COND_BYE: + greeting->gr_data.gr_bye = gr_bye; + break; + } + + return greeting; +} + +void mailimap_greeting_free(struct mailimap_greeting * greeting) +{ + switch (greeting->gr_type) { + case MAILIMAP_GREETING_RESP_COND_AUTH: + mailimap_resp_cond_auth_free(greeting->gr_data.gr_auth); + break; + case MAILIMAP_GREETING_RESP_COND_BYE: + mailimap_resp_cond_bye_free(greeting->gr_data.gr_bye); + break; + } + free(greeting); +} + + + +void +mailimap_header_fld_name_free(char * header_fld_name) +{ + mailimap_astring_free(header_fld_name); +} + + + +struct mailimap_header_list * +mailimap_header_list_new(clist * hdr_list) +{ + struct mailimap_header_list * header_list; + + header_list = malloc(sizeof(* header_list)); + if (header_list == NULL) + return NULL; + + header_list->hdr_list = hdr_list; + + return header_list; +} + +void +mailimap_header_list_free(struct mailimap_header_list * header_list) +{ + clist_foreach(header_list->hdr_list, + (clist_func) mailimap_header_fld_name_free, + NULL); + clist_free(header_list->hdr_list); + free(header_list); +} + + + +void mailimap_literal_free(char * literal) +{ + /* free(literal); */ + mmap_string_unref(literal); +} + +void mailimap_mailbox_free(char * mb) +{ + mailimap_astring_free(mb); +} + + + + +struct mailimap_status_info * +mailimap_status_info_new(int st_att, uint32_t st_value) +{ + struct mailimap_status_info * info; + + info = malloc(sizeof(* info)); + if (info == NULL) + return NULL; + info->st_att = st_att; + info->st_value = st_value; + + return info; +} + +void mailimap_status_info_free(struct mailimap_status_info * info) +{ + free(info); +} + + + +struct mailimap_mailbox_data_status * +mailimap_mailbox_data_status_new(char * st_mailbox, + clist * st_info_list) +{ + struct mailimap_mailbox_data_status * mb_data_status; + + mb_data_status = malloc(sizeof(* mb_data_status)); + if (mb_data_status == NULL) + return NULL; + mb_data_status->st_mailbox = st_mailbox; + mb_data_status->st_info_list = st_info_list; + + return mb_data_status; +} + +void +mailimap_mailbox_data_search_free(clist * data_search) +{ + clist_foreach(data_search, (clist_func) mailimap_number_alloc_free, NULL); + clist_free(data_search); +} + +void +mailimap_mailbox_data_status_free(struct mailimap_mailbox_data_status * info) +{ + mailimap_mailbox_free(info->st_mailbox); + clist_foreach(info->st_info_list, (clist_func) mailimap_status_info_free, + NULL); + clist_free(info->st_info_list); + free(info); +} + + +static void +mailimap_mailbox_data_flags_free(struct mailimap_flag_list * flag_list) +{ + mailimap_flag_list_free(flag_list); +} + +static void +mailimap_mailbox_data_list_free(struct mailimap_mailbox_list * mb_list) +{ + mailimap_mailbox_list_free(mb_list); +} + +static void +mailimap_mailbox_data_lsub_free(struct mailimap_mailbox_list * mb_lsub) +{ + mailimap_mailbox_list_free(mb_lsub); +} + + + + + + +struct mailimap_mailbox_data * +mailimap_mailbox_data_new(int mbd_type, struct mailimap_flag_list * mbd_flags, + struct mailimap_mailbox_list * mbd_list, + struct mailimap_mailbox_list * mbd_lsub, + clist * mbd_search, + struct mailimap_mailbox_data_status * mbd_status, + uint32_t mbd_exists, + uint32_t mbd_recent) +{ + struct mailimap_mailbox_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + return NULL; + + data->mbd_type = mbd_type; + switch (mbd_type) { + case MAILIMAP_MAILBOX_DATA_FLAGS: + data->mbd_data.mbd_flags = mbd_flags; + break; + case MAILIMAP_MAILBOX_DATA_LIST: + data->mbd_data.mbd_list = mbd_list; + break; + case MAILIMAP_MAILBOX_DATA_LSUB: + data->mbd_data.mbd_lsub = mbd_lsub; + break; + case MAILIMAP_MAILBOX_DATA_SEARCH: + data->mbd_data.mbd_search = mbd_search; + break; + case MAILIMAP_MAILBOX_DATA_STATUS: + data->mbd_data.mbd_status = mbd_status; + break; + case MAILIMAP_MAILBOX_DATA_EXISTS: + data->mbd_data.mbd_exists = mbd_exists; + break; + case MAILIMAP_MAILBOX_DATA_RECENT: + data->mbd_data.mbd_recent = mbd_recent; + break; + } + + return data; +} + +void +mailimap_mailbox_data_free(struct mailimap_mailbox_data * mb_data) +{ + switch (mb_data->mbd_type) { + case MAILIMAP_MAILBOX_DATA_FLAGS: + if (mb_data->mbd_data.mbd_flags != NULL) + mailimap_mailbox_data_flags_free(mb_data->mbd_data.mbd_flags); + break; + case MAILIMAP_MAILBOX_DATA_LIST: + if (mb_data->mbd_data.mbd_list != NULL) + mailimap_mailbox_data_list_free(mb_data->mbd_data.mbd_list); + break; + case MAILIMAP_MAILBOX_DATA_LSUB: + if (mb_data->mbd_data.mbd_lsub != NULL) + mailimap_mailbox_data_lsub_free(mb_data->mbd_data.mbd_lsub); + break; + case MAILIMAP_MAILBOX_DATA_SEARCH: + if (mb_data->mbd_data.mbd_search != NULL) + mailimap_mailbox_data_search_free(mb_data->mbd_data.mbd_search); + break; + case MAILIMAP_MAILBOX_DATA_STATUS: + if (mb_data->mbd_data.mbd_status != NULL) + mailimap_mailbox_data_status_free(mb_data->mbd_data.mbd_status); + break; + } + free(mb_data); +} + + + + + +struct mailimap_mbx_list_flags * +mailimap_mbx_list_flags_new(int mbf_type, clist * mbf_oflags, + int mbf_sflag) +{ + struct mailimap_mbx_list_flags * mbx_list_flags; + + mbx_list_flags = malloc(sizeof(* mbx_list_flags)); + if (mbx_list_flags == NULL) + return NULL; + + mbx_list_flags->mbf_type = mbf_type; + mbx_list_flags->mbf_oflags = mbf_oflags; + mbx_list_flags->mbf_sflag = mbf_sflag; + + return mbx_list_flags; +} + +void +mailimap_mbx_list_flags_free(struct mailimap_mbx_list_flags * mbx_list_flags) +{ + clist_foreach(mbx_list_flags->mbf_oflags, + (clist_func) mailimap_mbx_list_oflag_free, + NULL); + clist_free(mbx_list_flags->mbf_oflags); + + free(mbx_list_flags); +} + + +struct mailimap_mbx_list_oflag * +mailimap_mbx_list_oflag_new(int of_type, char * of_flag_ext) +{ + struct mailimap_mbx_list_oflag * oflag; + + oflag = malloc(sizeof(* oflag)); + if (oflag == NULL) + return NULL; + + oflag->of_type = of_type; + oflag->of_flag_ext = of_flag_ext; + + return oflag; +} + +void +mailimap_mbx_list_oflag_free(struct mailimap_mbx_list_oflag * oflag) +{ + if (oflag->of_flag_ext != NULL) + mailimap_flag_extension_free(oflag->of_flag_ext); + free(oflag); +} + + + +struct mailimap_mailbox_list * +mailimap_mailbox_list_new(struct mailimap_mbx_list_flags * mbx_flags, + char mb_delimiter, char * mb_name) +{ + struct mailimap_mailbox_list * mb_list; + + mb_list = malloc(sizeof(* mb_list)); + if (mb_list == NULL) + return NULL; + + mb_list->mb_flag = mbx_flags; + mb_list->mb_delimiter = mb_delimiter; + mb_list->mb_name = mb_name; + + return mb_list; +} + +void +mailimap_mailbox_list_free(struct mailimap_mailbox_list * mb_list) +{ + if (mb_list->mb_flag != NULL) + mailimap_mbx_list_flags_free(mb_list->mb_flag); + if (mb_list->mb_name != NULL) + mailimap_mailbox_free(mb_list->mb_name); + free(mb_list); +} + + + +struct mailimap_media_basic * +mailimap_media_basic_new(int med_type, + char * med_basic_type, char * med_subtype) +{ + struct mailimap_media_basic * media_basic; + + media_basic = malloc(sizeof(* media_basic)); + if (media_basic == NULL) + return NULL; + media_basic->med_type = med_type; + media_basic->med_basic_type = med_basic_type; + media_basic->med_subtype = med_subtype; + + return media_basic; +} + +void +mailimap_media_basic_free(struct mailimap_media_basic * media_basic) +{ + mailimap_string_free(media_basic->med_basic_type); + mailimap_media_subtype_free(media_basic->med_subtype); + free(media_basic); +} + + + +void mailimap_media_subtype_free(char * media_subtype) +{ + mmap_string_unref(media_subtype); +} + + +void mailimap_media_text_free(char * media_text) +{ + mailimap_media_subtype_free(media_text); +} + + + +struct mailimap_message_data * +mailimap_message_data_new(uint32_t mdt_number, int mdt_type, + struct mailimap_msg_att * mdt_msg_att) +{ + struct mailimap_message_data * msg_data; + + msg_data = malloc(sizeof(* msg_data)); + if (msg_data == NULL) + free(msg_data); + + msg_data->mdt_number = mdt_number; + msg_data->mdt_type = mdt_type; + msg_data->mdt_msg_att = mdt_msg_att; + + return msg_data; +} + +void +mailimap_message_data_free(struct mailimap_message_data * msg_data) +{ + if (msg_data->mdt_msg_att != NULL) + mailimap_msg_att_free(msg_data->mdt_msg_att); + free(msg_data); +} + + + + +struct mailimap_msg_att_item * +mailimap_msg_att_item_new(int att_type, + struct mailimap_msg_att_dynamic * att_dyn, + struct mailimap_msg_att_static * att_static) +{ + struct mailimap_msg_att_item * item; + + item = malloc(sizeof(* item)); + if (item == NULL) + return item; + + item->att_type = att_type; + switch (att_type) { + case MAILIMAP_MSG_ATT_ITEM_DYNAMIC: + item->att_data.att_dyn = att_dyn; + break; + case MAILIMAP_MSG_ATT_ITEM_STATIC: + item->att_data.att_static = att_static; + break; + } + + return item; +} + +void +mailimap_msg_att_item_free(struct mailimap_msg_att_item * item) +{ + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ITEM_DYNAMIC: + mailimap_msg_att_dynamic_free(item->att_data.att_dyn); + break; + case MAILIMAP_MSG_ATT_ITEM_STATIC: + mailimap_msg_att_static_free(item->att_data.att_static); + break; + } + free(item); +} + + +struct mailimap_msg_att * +mailimap_msg_att_new(clist * att_list) +{ + struct mailimap_msg_att * msg_att; + + msg_att = malloc(sizeof(* msg_att)); + if (msg_att == NULL) + return NULL; + + msg_att->att_list = att_list; + msg_att->att_number = 0; + + return msg_att; +} + +void mailimap_msg_att_free(struct mailimap_msg_att * msg_att) +{ + clist_foreach(msg_att->att_list, + (clist_func) mailimap_msg_att_item_free, NULL); + clist_free(msg_att->att_list); + free(msg_att); +} + + + +struct mailimap_msg_att_dynamic * +mailimap_msg_att_dynamic_new(clist * att_list) +{ + struct mailimap_msg_att_dynamic * msg_att_dyn; + + msg_att_dyn = malloc(sizeof(* msg_att_dyn)); + if (msg_att_dyn == NULL) + return NULL; + + msg_att_dyn->att_list = att_list; + + return msg_att_dyn; +} + +void +mailimap_msg_att_dynamic_free(struct mailimap_msg_att_dynamic * msg_att_dyn) +{ + if (msg_att_dyn->att_list != NULL) { + clist_foreach(msg_att_dyn->att_list, + (clist_func) mailimap_flag_fetch_free, + NULL); + clist_free(msg_att_dyn->att_list); + } + free(msg_att_dyn); +} + + +struct mailimap_msg_att_body_section * +mailimap_msg_att_body_section_new(struct mailimap_section * sec_section, + uint32_t sec_origin_octet, + char * sec_body_part, + size_t sec_length) +{ + struct mailimap_msg_att_body_section * msg_att_body_section; + + msg_att_body_section = malloc(sizeof(* msg_att_body_section)); + if (msg_att_body_section == NULL) + return NULL; + + msg_att_body_section->sec_section = sec_section; + msg_att_body_section->sec_origin_octet = sec_origin_octet; + msg_att_body_section->sec_body_part = sec_body_part; + msg_att_body_section->sec_length = sec_length; + + return msg_att_body_section; +} + +void +mailimap_msg_att_body_section_free(struct mailimap_msg_att_body_section * + msg_att_body_section) +{ + if (msg_att_body_section->sec_section != NULL) + mailimap_section_free(msg_att_body_section->sec_section); + if (msg_att_body_section->sec_body_part != NULL) + mailimap_nstring_free(msg_att_body_section->sec_body_part); + free(msg_att_body_section); +} + + + + + + +void mailimap_msg_att_envelope_free(struct mailimap_envelope * env) +{ + mailimap_envelope_free(env); +} + +void +mailimap_msg_att_internaldate_free(struct mailimap_date_time * date_time) +{ + mailimap_date_time_free(date_time); +} + +void +mailimap_msg_att_rfc822_free(char * str) +{ + mailimap_nstring_free(str); +} + + +void +mailimap_msg_att_rfc822_header_free(char * str) +{ + mailimap_nstring_free(str); +} + +void +mailimap_msg_att_rfc822_text_free(char * str) +{ + mailimap_nstring_free(str); +} + +void +mailimap_msg_att_body_free(struct mailimap_body * body) +{ + mailimap_body_free(body); +} + +void +mailimap_msg_att_bodystructure_free(struct mailimap_body * body) +{ + mailimap_body_free(body); +} + + + +struct mailimap_msg_att_static * +mailimap_msg_att_static_new(int att_type, struct mailimap_envelope * att_env, + struct mailimap_date_time * att_internal_date, + char * att_rfc822, + char * att_rfc822_header, + char * att_rfc822_text, + size_t att_length, + uint32_t att_rfc822_size, + struct mailimap_body * att_bodystructure, + struct mailimap_body * att_body, + struct mailimap_msg_att_body_section * att_body_section, + uint32_t att_uid) +{ + struct mailimap_msg_att_static * item; + + item = malloc(sizeof(* item)); + if (item == NULL) + return FALSE; + + item->att_type = att_type; + switch (att_type) { + case MAILIMAP_MSG_ATT_ENVELOPE: + item->att_data.att_env = att_env; + break; + case MAILIMAP_MSG_ATT_INTERNALDATE: + item->att_data.att_internal_date = att_internal_date; + break; + case MAILIMAP_MSG_ATT_RFC822: + item->att_data.att_rfc822.att_content = att_rfc822; + item->att_data.att_rfc822.att_length = att_length; + break; + case MAILIMAP_MSG_ATT_RFC822_HEADER: + item->att_data.att_rfc822_header.att_content = att_rfc822_header; + item->att_data.att_rfc822_header.att_length = att_length; + break; + case MAILIMAP_MSG_ATT_RFC822_TEXT: + item->att_data.att_rfc822_text.att_content = att_rfc822_text; + item->att_data.att_rfc822_text.att_length = att_length; + break; + case MAILIMAP_MSG_ATT_RFC822_SIZE: + item->att_data.att_rfc822_size = att_rfc822_size; + break; + case MAILIMAP_MSG_ATT_BODY: + item->att_data.att_body = att_body; + break; + case MAILIMAP_MSG_ATT_BODYSTRUCTURE: + item->att_data.att_bodystructure = att_bodystructure; + break; + case MAILIMAP_MSG_ATT_BODY_SECTION: + item->att_data.att_body_section = att_body_section; + break; + case MAILIMAP_MSG_ATT_UID: + item->att_data.att_uid = att_uid; + break; + } + + return item; +} + +void +mailimap_msg_att_static_free(struct mailimap_msg_att_static * item) +{ + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ENVELOPE: + if (item->att_data.att_env != NULL) + mailimap_msg_att_envelope_free(item->att_data.att_env); + break; + case MAILIMAP_MSG_ATT_INTERNALDATE: + if (item->att_data.att_internal_date != NULL) + mailimap_msg_att_internaldate_free(item->att_data.att_internal_date); + break; + case MAILIMAP_MSG_ATT_RFC822: + if (item->att_data.att_rfc822.att_content != NULL) + mailimap_msg_att_rfc822_free(item->att_data.att_rfc822.att_content); + break; + case MAILIMAP_MSG_ATT_RFC822_HEADER: + if (item->att_data.att_rfc822_header.att_content != NULL) + mailimap_msg_att_rfc822_header_free(item->att_data.att_rfc822_header.att_content); + break; + case MAILIMAP_MSG_ATT_RFC822_TEXT: + if (item->att_data.att_rfc822_text.att_content != NULL) + mailimap_msg_att_rfc822_text_free(item->att_data.att_rfc822_text.att_content); + break; + case MAILIMAP_MSG_ATT_BODYSTRUCTURE: + if (item->att_data.att_bodystructure != NULL) + mailimap_msg_att_bodystructure_free(item->att_data.att_bodystructure); + break; + case MAILIMAP_MSG_ATT_BODY: + if (item->att_data.att_body != NULL) + mailimap_msg_att_body_free(item->att_data.att_body); + break; + case MAILIMAP_MSG_ATT_BODY_SECTION: + if (item->att_data.att_body_section != NULL) + mailimap_msg_att_body_section_free(item->att_data.att_body_section); + break; + } + free(item); +} + + + + +void mailimap_nstring_free(char * str) +{ + if (str != NULL) + mailimap_string_free(str); +} + + + + + + + +struct mailimap_cont_req_or_resp_data * +mailimap_cont_req_or_resp_data_new(int rsp_type, + struct mailimap_continue_req * rsp_cont_req, + struct mailimap_response_data * rsp_resp_data) +{ + struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data; + + cont_req_or_resp_data = malloc(sizeof(* cont_req_or_resp_data)); + if (cont_req_or_resp_data == NULL) + return NULL; + + cont_req_or_resp_data->rsp_type = rsp_type; + switch (rsp_type) { + case MAILIMAP_RESP_CONT_REQ: + cont_req_or_resp_data->rsp_data.rsp_cont_req = rsp_cont_req; + break; + case MAILIMAP_RESP_RESP_DATA: + cont_req_or_resp_data->rsp_data.rsp_resp_data = rsp_resp_data; + break; + } + + return cont_req_or_resp_data; +} + +void +mailimap_cont_req_or_resp_data_free(struct mailimap_cont_req_or_resp_data * + cont_req_or_resp_data) +{ + switch (cont_req_or_resp_data->rsp_type) { + case MAILIMAP_RESP_CONT_REQ: + if (cont_req_or_resp_data->rsp_data.rsp_cont_req != NULL) + mailimap_continue_req_free(cont_req_or_resp_data->rsp_data.rsp_cont_req); + break; + case MAILIMAP_RESP_RESP_DATA: + if (cont_req_or_resp_data->rsp_data.rsp_resp_data != NULL) + mailimap_response_data_free(cont_req_or_resp_data->rsp_data.rsp_resp_data); + break; + } + free(cont_req_or_resp_data); +} + + + + +struct mailimap_response * +mailimap_response_new(clist * rsp_cont_req_or_resp_data_list, + struct mailimap_response_done * rsp_resp_done) +{ + struct mailimap_response * resp; + + resp = malloc(sizeof(* resp)); + if (resp == NULL) + return NULL; + + resp->rsp_cont_req_or_resp_data_list = rsp_cont_req_or_resp_data_list; + resp->rsp_resp_done = rsp_resp_done; + + return resp; +} + +void +mailimap_response_free(struct mailimap_response * resp) +{ + if (resp->rsp_cont_req_or_resp_data_list != NULL) { + clist_foreach(resp->rsp_cont_req_or_resp_data_list, + (clist_func) mailimap_cont_req_or_resp_data_free, NULL); + clist_free(resp->rsp_cont_req_or_resp_data_list); + } + mailimap_response_done_free(resp->rsp_resp_done); + free(resp); +} + + + +struct mailimap_response_data * +mailimap_response_data_new(int rsp_type, + struct mailimap_resp_cond_state * rsp_cond_state, + struct mailimap_resp_cond_bye * rsp_bye, + struct mailimap_mailbox_data * rsp_mailbox_data, + struct mailimap_message_data * rsp_message_data, + struct mailimap_capability_data * rsp_capability_data) +{ + struct mailimap_response_data * resp_data; + + resp_data = malloc(sizeof(* resp_data)); + if (resp_data == NULL) + return NULL; + resp_data->rsp_type = rsp_type; + + switch (rsp_type) { + case MAILIMAP_RESP_DATA_TYPE_COND_STATE: + resp_data->rsp_data.rsp_cond_state = rsp_cond_state; + break; + case MAILIMAP_RESP_DATA_TYPE_COND_BYE: + resp_data->rsp_data.rsp_bye = rsp_bye; + break; + case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA: + resp_data->rsp_data.rsp_mailbox_data = rsp_mailbox_data; + break; + case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA: + resp_data->rsp_data.rsp_message_data = rsp_message_data; + break; + case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA: + resp_data->rsp_data.rsp_capability_data = rsp_capability_data; + break; + } + + return resp_data; +} + +void +mailimap_response_data_free(struct mailimap_response_data * resp_data) +{ + switch (resp_data->rsp_type) { + case MAILIMAP_RESP_DATA_TYPE_COND_STATE: + if (resp_data->rsp_data.rsp_cond_state != NULL) + mailimap_resp_cond_state_free(resp_data->rsp_data.rsp_cond_state); + break; + case MAILIMAP_RESP_DATA_TYPE_COND_BYE: + if (resp_data->rsp_data.rsp_bye != NULL) + mailimap_resp_cond_bye_free(resp_data->rsp_data.rsp_bye); + break; + case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA: + if (resp_data->rsp_data.rsp_mailbox_data != NULL) + mailimap_mailbox_data_free(resp_data->rsp_data.rsp_mailbox_data); + break; + case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA: + if (resp_data->rsp_data.rsp_message_data != NULL) + mailimap_message_data_free(resp_data->rsp_data.rsp_message_data); + break; + case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA: + if (resp_data->rsp_data.rsp_capability_data != NULL) + mailimap_capability_data_free(resp_data->rsp_data.rsp_capability_data); + break; + } + free(resp_data); +} + + + +struct mailimap_response_done * +mailimap_response_done_new(int rsp_type, + struct mailimap_response_tagged * rsp_tagged, + struct mailimap_response_fatal * rsp_fatal) +{ + struct mailimap_response_done * resp_done; + + resp_done = malloc(sizeof(* resp_done)); + if (resp_done == NULL) + return NULL; + + resp_done->rsp_type = rsp_type; + switch (rsp_type) { + case MAILIMAP_RESP_DONE_TYPE_TAGGED: + resp_done->rsp_data.rsp_tagged = rsp_tagged; + break; + case MAILIMAP_RESP_DONE_TYPE_FATAL: + resp_done->rsp_data.rsp_fatal = rsp_fatal; + break; + } + + return resp_done; +} + +void mailimap_response_done_free(struct mailimap_response_done * + resp_done) +{ + switch (resp_done->rsp_type) { + case MAILIMAP_RESP_DONE_TYPE_TAGGED: + mailimap_response_tagged_free(resp_done->rsp_data.rsp_tagged); + break; + case MAILIMAP_RESP_DONE_TYPE_FATAL: + mailimap_response_fatal_free(resp_done->rsp_data.rsp_fatal); + break; + } + free(resp_done); +} + +struct mailimap_response_fatal * +mailimap_response_fatal_new(struct mailimap_resp_cond_bye * rsp_bye) +{ + struct mailimap_response_fatal * resp_fatal; + + resp_fatal = malloc(sizeof(* resp_fatal)); + if (resp_fatal == NULL) + return NULL; + + resp_fatal->rsp_bye = rsp_bye; + + return NULL; +} + +void mailimap_response_fatal_free(struct mailimap_response_fatal * resp_fatal) +{ + mailimap_resp_cond_bye_free(resp_fatal->rsp_bye); + free(resp_fatal); +} + +struct mailimap_response_tagged * +mailimap_response_tagged_new(char * rsp_tag, + struct mailimap_resp_cond_state * rsp_cond_state) +{ + struct mailimap_response_tagged * resp_tagged; + + resp_tagged = malloc(sizeof(* resp_tagged)); + if (resp_tagged == NULL) + return NULL; + + resp_tagged->rsp_tag = rsp_tag; + resp_tagged->rsp_cond_state = rsp_cond_state; + + return resp_tagged; +} + +void +mailimap_response_tagged_free(struct mailimap_response_tagged * tagged) +{ + mailimap_tag_free(tagged->rsp_tag); + mailimap_resp_cond_state_free(tagged->rsp_cond_state); + free(tagged); +} + + + +struct mailimap_resp_cond_auth * +mailimap_resp_cond_auth_new(int rsp_type, + struct mailimap_resp_text * rsp_text) +{ + struct mailimap_resp_cond_auth * cond_auth; + + cond_auth = malloc(sizeof(* cond_auth)); + if (cond_auth == NULL) + return NULL; + + cond_auth->rsp_type = rsp_type; + cond_auth->rsp_text = rsp_text; + + return cond_auth; +} + +void +mailimap_resp_cond_auth_free(struct mailimap_resp_cond_auth * cond_auth) +{ + mailimap_resp_text_free(cond_auth->rsp_text); + free(cond_auth); +} + + + +struct mailimap_resp_cond_bye * +mailimap_resp_cond_bye_new(struct mailimap_resp_text * rsp_text) +{ + struct mailimap_resp_cond_bye * cond_bye; + + cond_bye = malloc(sizeof(* cond_bye)); + if (cond_bye == NULL) + return NULL; + + cond_bye->rsp_text = rsp_text; + + return cond_bye; +} + + +void +mailimap_resp_cond_bye_free(struct mailimap_resp_cond_bye * cond_bye) +{ + mailimap_resp_text_free(cond_bye->rsp_text); + free(cond_bye); +} + + +struct mailimap_resp_cond_state * +mailimap_resp_cond_state_new(int rsp_type, + struct mailimap_resp_text * rsp_text) +{ + struct mailimap_resp_cond_state * cond_state; + + cond_state = malloc(sizeof(* cond_state)); + if (cond_state == NULL) + return NULL; + + cond_state->rsp_type = rsp_type; + cond_state->rsp_text = rsp_text; + + return cond_state; +} + +void +mailimap_resp_cond_state_free(struct mailimap_resp_cond_state * cond_state) +{ + mailimap_resp_text_free(cond_state->rsp_text); + free(cond_state); +} + + +struct mailimap_resp_text * +mailimap_resp_text_new(struct mailimap_resp_text_code * rsp_code, + char * rsp_text) +{ + struct mailimap_resp_text * resp_text; + + resp_text = malloc(sizeof(* resp_text)); + if (resp_text == NULL) + return NULL; + + resp_text->rsp_code = rsp_code; + resp_text->rsp_text = rsp_text; + + return resp_text; +} + +void mailimap_resp_text_free(struct mailimap_resp_text * resp_text) +{ + if (resp_text->rsp_code) + mailimap_resp_text_code_free(resp_text->rsp_code); + if (resp_text->rsp_text) + mailimap_text_free(resp_text->rsp_text); + free(resp_text); +} + + + + +struct mailimap_resp_text_code * +mailimap_resp_text_code_new(int rc_type, clist * rc_badcharset, + struct mailimap_capability_data * rc_cap_data, + clist * rc_perm_flags, + uint32_t rc_uidnext, uint32_t rc_uidvalidity, + uint32_t rc_first_unseen, char * rc_atom, char * rc_atom_value) +{ + struct mailimap_resp_text_code * resp_text_code; + + resp_text_code = malloc(sizeof(* resp_text_code)); + if (resp_text_code == NULL) + return NULL; + + resp_text_code->rc_type = rc_type; + switch (rc_type) { + case MAILIMAP_RESP_TEXT_CODE_BADCHARSET: + resp_text_code->rc_data.rc_badcharset = rc_badcharset; + break; + case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA: + resp_text_code->rc_data.rc_cap_data = rc_cap_data; + break; + case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS: + resp_text_code->rc_data.rc_perm_flags = rc_perm_flags; + break; + case MAILIMAP_RESP_TEXT_CODE_UIDNEXT: + resp_text_code->rc_data.rc_uidnext = rc_uidnext; + break; + case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY: + resp_text_code->rc_data.rc_uidvalidity = rc_uidvalidity; + break; + case MAILIMAP_RESP_TEXT_CODE_UNSEEN: + resp_text_code->rc_data.rc_first_unseen = rc_first_unseen; + break; + case MAILIMAP_RESP_TEXT_CODE_OTHER: + resp_text_code->rc_data.rc_atom.atom_name = rc_atom; + resp_text_code->rc_data.rc_atom.atom_value = rc_atom_value; + break; + } + + return resp_text_code; +} + +void +mailimap_resp_text_code_free(struct mailimap_resp_text_code * resp_text_code) +{ + switch (resp_text_code->rc_type) { + case MAILIMAP_RESP_TEXT_CODE_BADCHARSET: + if (resp_text_code->rc_data.rc_badcharset != NULL) { + clist_foreach(resp_text_code->rc_data.rc_badcharset, + (clist_func) mailimap_astring_free, + NULL); + clist_free(resp_text_code->rc_data.rc_badcharset); + } + break; + case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA: + if (resp_text_code->rc_data.rc_cap_data != NULL) + mailimap_capability_data_free(resp_text_code->rc_data.rc_cap_data); + break; + case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS: + if (resp_text_code->rc_data.rc_perm_flags != NULL) { + clist_foreach(resp_text_code->rc_data.rc_perm_flags, + (clist_func) mailimap_flag_perm_free, NULL); + clist_free(resp_text_code->rc_data.rc_perm_flags); + } + break; + case MAILIMAP_RESP_TEXT_CODE_OTHER: + if (resp_text_code->rc_data.rc_atom.atom_name != NULL) + mailimap_atom_free(resp_text_code->rc_data.rc_atom.atom_name); + if (resp_text_code->rc_data.rc_atom.atom_value != NULL) + mailimap_custom_string_free(resp_text_code->rc_data.rc_atom.atom_value); + break; + } + free(resp_text_code); +} + + +struct mailimap_section * +mailimap_section_new(struct mailimap_section_spec * sec_spec) +{ + struct mailimap_section * section; + + section = malloc(sizeof(* section)); + if (section == NULL) + return NULL; + + section->sec_spec = sec_spec; + + return section; +} + +void mailimap_section_free(struct mailimap_section * section) +{ + if (section->sec_spec != NULL) + mailimap_section_spec_free(section->sec_spec); + free(section); +} + + + +struct mailimap_section_msgtext * +mailimap_section_msgtext_new(int sec_type, + struct mailimap_header_list * sec_header_list) +{ + struct mailimap_section_msgtext * msgtext; + + msgtext = malloc(sizeof(* msgtext)); + if (msgtext == NULL) + return FALSE; + + msgtext->sec_type = sec_type; + msgtext->sec_header_list = sec_header_list; + + return msgtext; +} + +void +mailimap_section_msgtext_free(struct mailimap_section_msgtext * msgtext) +{ + if (msgtext->sec_header_list != NULL) + mailimap_header_list_free(msgtext->sec_header_list); + free(msgtext); +} + + +struct mailimap_section_part * +mailimap_section_part_new(clist * sec_id) +{ + struct mailimap_section_part * section_part; + + section_part = malloc(sizeof(* section_part)); + if (section_part == NULL) + return NULL; + + section_part->sec_id = sec_id; + + return section_part; +} + +void +mailimap_section_part_free(struct mailimap_section_part * section_part) +{ + clist_foreach(section_part->sec_id, + (clist_func) mailimap_number_alloc_free, NULL); + clist_free(section_part->sec_id); + free(section_part); +} + + +struct mailimap_section_spec * +mailimap_section_spec_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext, + struct mailimap_section_part * sec_part, + struct mailimap_section_text * sec_text) +{ + struct mailimap_section_spec * section_spec; + + section_spec = malloc(sizeof(* section_spec)); + if (section_spec == NULL) + return NULL; + + section_spec->sec_type = sec_type; + switch (sec_type) { + case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT: + section_spec->sec_data.sec_msgtext = sec_msgtext; + break; + case MAILIMAP_SECTION_SPEC_SECTION_PART: + section_spec->sec_data.sec_part = sec_part; + break; + } + section_spec->sec_text = sec_text; + + return section_spec; +} + +void +mailimap_section_spec_free(struct mailimap_section_spec * section_spec) +{ + if (section_spec->sec_text) + mailimap_section_text_free(section_spec->sec_text); + + switch (section_spec->sec_type) { + case MAILIMAP_SECTION_SPEC_SECTION_PART: + if (section_spec->sec_data.sec_part != NULL) + mailimap_section_part_free(section_spec->sec_data.sec_part); + break; + case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT: + /* handle case where it can be detached */ + if (section_spec->sec_data.sec_msgtext != NULL) + mailimap_section_msgtext_free(section_spec->sec_data.sec_msgtext); + break; + } + free(section_spec); +} + + +struct mailimap_section_text * +mailimap_section_text_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext) +{ + struct mailimap_section_text * section_text; + + section_text = malloc(sizeof(* section_text)); + if (section_text == NULL) + return NULL; + + section_text->sec_type = sec_type; + section_text->sec_msgtext = sec_msgtext; + + return section_text; +} + +void +mailimap_section_text_free(struct mailimap_section_text * section_text) +{ + if (section_text->sec_msgtext != NULL) + mailimap_section_msgtext_free(section_text->sec_msgtext); + free(section_text); +} + + + + +void +mailimap_string_free(char * str) +{ + mmap_string_unref(str); +} + + + + + +void mailimap_tag_free(char * tag) +{ + mailimap_custom_string_free(tag); +} + + +void mailimap_text_free(char * text) +{ + mailimap_custom_string_free(text); +} + + + + + + + + + + + + + + + + + + + + + + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + + + +/* sender only */ + + +/* COPY FETCH SEARCH STORE */ +/* set */ + +struct mailimap_set_item * +mailimap_set_item_new(uint32_t set_first, uint32_t set_last) +{ + struct mailimap_set_item * item; + + item = malloc(sizeof(* item)); + if (item == NULL) + return NULL; + + item->set_first = set_first; + item->set_last = set_last; + + return item; +} + +void mailimap_set_item_free(struct mailimap_set_item * set_item) +{ + free(set_item); +} + +struct mailimap_set * mailimap_set_new(clist * set_list) +{ + struct mailimap_set * set; + + set = malloc(sizeof(* set)); + if (set == NULL) + return NULL; + + set->set_list = set_list; + + return set; +} + +void mailimap_set_free(struct mailimap_set * set) +{ + clist_foreach(set->set_list, (clist_func) mailimap_set_item_free, NULL); + clist_free(set->set_list); + free(set); +} + +/* SEARCH with date key */ +/* date */ + +struct mailimap_date * +mailimap_date_new(int dt_day, int dt_month, int dt_year) +{ + struct mailimap_date * date; + + date = malloc(sizeof(* date)); + if (date == NULL) + return NULL; + + date->dt_day = dt_day; + date->dt_month = dt_month; + date->dt_year = dt_year; + + return date; +} + +void mailimap_date_free(struct mailimap_date * date) +{ + free(date); +} + + + +struct mailimap_fetch_att * +mailimap_fetch_att_new(int att_type, struct mailimap_section * att_section, + uint32_t att_offset, uint32_t att_size) +{ + struct mailimap_fetch_att * fetch_att; + + fetch_att = malloc(sizeof(* fetch_att)); + if (fetch_att == NULL) + return NULL; + fetch_att->att_type = att_type; + fetch_att->att_section = att_section; + fetch_att->att_offset = att_offset; + fetch_att->att_size = att_size; + + return fetch_att; +} + +void mailimap_fetch_att_free(struct mailimap_fetch_att * fetch_att) +{ + if (fetch_att->att_section != NULL) + mailimap_section_free(fetch_att->att_section); + free(fetch_att); +} + + + +struct mailimap_fetch_type * +mailimap_fetch_type_new(int ft_type, + struct mailimap_fetch_att * ft_fetch_att, + clist * ft_fetch_att_list) +{ + struct mailimap_fetch_type * fetch_type; + + fetch_type = malloc(sizeof(* fetch_type)); + if (fetch_type == NULL) + return NULL; + fetch_type->ft_type = ft_type; + switch (ft_type) { + case MAILIMAP_FETCH_TYPE_FETCH_ATT: + fetch_type->ft_data.ft_fetch_att = ft_fetch_att; + break; + case MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST: + fetch_type->ft_data.ft_fetch_att_list = ft_fetch_att_list; + break; + } + + return fetch_type; +} + +void mailimap_fetch_type_free(struct mailimap_fetch_type * fetch_type) +{ + switch (fetch_type->ft_type) { + case MAILIMAP_FETCH_TYPE_FETCH_ATT: + mailimap_fetch_att_free(fetch_type->ft_data.ft_fetch_att); + break; + case MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST: + clist_foreach(fetch_type->ft_data.ft_fetch_att_list, + (clist_func) mailimap_fetch_att_free, NULL); + clist_free(fetch_type->ft_data.ft_fetch_att_list); + break; + } + free(fetch_type); +} + + + + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new(int fl_sign, int fl_silent, + struct mailimap_flag_list * fl_flag_list) +{ + struct mailimap_store_att_flags * store_att_flags; + + store_att_flags = malloc(sizeof(* store_att_flags)); + if (store_att_flags == NULL) + return NULL; + + store_att_flags->fl_sign = fl_sign; + store_att_flags->fl_silent = fl_silent; + store_att_flags->fl_flag_list = fl_flag_list; + + return store_att_flags; +} + +void mailimap_store_att_flags_free(struct mailimap_store_att_flags * + store_att_flags) +{ + mailimap_flag_list_free(store_att_flags->fl_flag_list); + free(store_att_flags); +} + + +struct mailimap_search_key * +mailimap_search_key_new(int sk_type, + char * sk_bcc, struct mailimap_date * sk_before, char * sk_body, + char * sk_cc, char * sk_from, char * sk_keyword, + struct mailimap_date * sk_on, struct mailimap_date * sk_since, + char * sk_subject, char * sk_text, char * sk_to, + char * sk_unkeyword, char * sk_header_name, + char * sk_header_value, uint32_t sk_larger, + struct mailimap_search_key * sk_not, + struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2, + struct mailimap_date * sk_sentbefore, + struct mailimap_date * sk_senton, + struct mailimap_date * sk_sentsince, + uint32_t sk_smaller, struct mailimap_set * sk_uid, + struct mailimap_set * sk_set, clist * sk_multiple) +{ + struct mailimap_search_key * key; + + key = malloc(sizeof(* key)); + if (key == NULL) + return NULL; + + key->sk_type = sk_type; + switch (sk_type) { + case MAILIMAP_SEARCH_KEY_BCC: + key->sk_data.sk_bcc = sk_bcc; + break; + case MAILIMAP_SEARCH_KEY_BEFORE: + key->sk_data.sk_before = sk_before; + break; + case MAILIMAP_SEARCH_KEY_BODY: + key->sk_data.sk_body = sk_body; + break; + case MAILIMAP_SEARCH_KEY_CC: + key->sk_data.sk_cc = sk_cc; + break; + case MAILIMAP_SEARCH_KEY_FROM: + key->sk_data.sk_from = sk_from; + break; + case MAILIMAP_SEARCH_KEY_KEYWORD: + key->sk_data.sk_keyword = sk_keyword; + break; + case MAILIMAP_SEARCH_KEY_ON: + key->sk_data.sk_on = sk_on; + break; + case MAILIMAP_SEARCH_KEY_SINCE: + key->sk_data.sk_since = sk_since; + break; + case MAILIMAP_SEARCH_KEY_SUBJECT: + key->sk_data.sk_subject = sk_subject; + break; + case MAILIMAP_SEARCH_KEY_TEXT: + key->sk_data.sk_text = sk_text; + break; + case MAILIMAP_SEARCH_KEY_TO: + key->sk_data.sk_to = sk_to; + break; + case MAILIMAP_SEARCH_KEY_UNKEYWORD: + key->sk_data.sk_unkeyword = sk_unkeyword; + break; + case MAILIMAP_SEARCH_KEY_HEADER: + key->sk_data.sk_header.sk_header_name = sk_header_name; + key->sk_data.sk_header.sk_header_value = sk_header_value; + break; + case MAILIMAP_SEARCH_KEY_LARGER: + key->sk_data.sk_larger = sk_larger; + break; + case MAILIMAP_SEARCH_KEY_NOT: + key->sk_data.sk_not = sk_not; + break; + case MAILIMAP_SEARCH_KEY_OR: + key->sk_data.sk_or.sk_or1 = sk_or1; + key->sk_data.sk_or.sk_or2 = sk_or2; + break; + case MAILIMAP_SEARCH_KEY_SENTBEFORE: + key->sk_data.sk_sentbefore = sk_sentbefore; + break; + case MAILIMAP_SEARCH_KEY_SENTON: + key->sk_data.sk_senton = sk_senton; + break; + case MAILIMAP_SEARCH_KEY_SENTSINCE: + key->sk_data.sk_sentsince = sk_sentsince; + break; + case MAILIMAP_SEARCH_KEY_SMALLER: + key->sk_data.sk_smaller = sk_smaller; + break; + case MAILIMAP_SEARCH_KEY_UID: + key->sk_data.sk_uid = sk_uid; + break; + case MAILIMAP_SEARCH_KEY_SET: + key->sk_data.sk_set = sk_set; + break; + case MAILIMAP_SEARCH_KEY_MULTIPLE: + key->sk_data.sk_multiple = sk_multiple; + break; + } + return key; +} + + +void mailimap_search_key_free(struct mailimap_search_key * key) +{ + switch (key->sk_type) { + case MAILIMAP_SEARCH_KEY_BCC: + mailimap_astring_free(key->sk_data.sk_bcc); + break; + case MAILIMAP_SEARCH_KEY_BEFORE: + mailimap_date_free(key->sk_data.sk_before); + break; + case MAILIMAP_SEARCH_KEY_BODY: + mailimap_astring_free(key->sk_data.sk_body); + break; + case MAILIMAP_SEARCH_KEY_CC: + mailimap_astring_free(key->sk_data.sk_cc); + break; + case MAILIMAP_SEARCH_KEY_FROM: + mailimap_astring_free(key->sk_data.sk_from); + break; + case MAILIMAP_SEARCH_KEY_KEYWORD: + mailimap_flag_keyword_free(key->sk_data.sk_keyword); + break; + case MAILIMAP_SEARCH_KEY_ON: + mailimap_date_free(key->sk_data.sk_on); + break; + case MAILIMAP_SEARCH_KEY_SINCE: + mailimap_date_free(key->sk_data.sk_since); + break; + case MAILIMAP_SEARCH_KEY_SUBJECT: + mailimap_astring_free(key->sk_data.sk_subject); + break; + case MAILIMAP_SEARCH_KEY_TEXT: + mailimap_astring_free(key->sk_data.sk_text); + break; + case MAILIMAP_SEARCH_KEY_TO: + mailimap_astring_free(key->sk_data.sk_to); + break; + case MAILIMAP_SEARCH_KEY_UNKEYWORD: + mailimap_flag_keyword_free(key->sk_data.sk_unkeyword); + break; + case MAILIMAP_SEARCH_KEY_HEADER: + mailimap_header_fld_name_free(key->sk_data.sk_header.sk_header_name); + mailimap_astring_free(key->sk_data.sk_header.sk_header_value); + break; + case MAILIMAP_SEARCH_KEY_NOT: + mailimap_search_key_free(key->sk_data.sk_not); + break; + case MAILIMAP_SEARCH_KEY_OR: + mailimap_search_key_free(key->sk_data.sk_or.sk_or1); + mailimap_search_key_free(key->sk_data.sk_or.sk_or2); + break; + case MAILIMAP_SEARCH_KEY_SENTBEFORE: + mailimap_date_free(key->sk_data.sk_sentbefore); + break; + case MAILIMAP_SEARCH_KEY_SENTON: + mailimap_date_free(key->sk_data.sk_senton); + break; + case MAILIMAP_SEARCH_KEY_SENTSINCE: + mailimap_date_free(key->sk_data.sk_sentsince); + break; + case MAILIMAP_SEARCH_KEY_UID: + mailimap_set_free(key->sk_data.sk_uid); + break; + case MAILIMAP_SEARCH_KEY_SET: + mailimap_set_free(key->sk_data.sk_set); + break; + case MAILIMAP_SEARCH_KEY_MULTIPLE: + clist_foreach(key->sk_data.sk_multiple, + (clist_func) mailimap_search_key_free, NULL); + clist_free(key->sk_data.sk_multiple); + break; + } + + free(key); +} + + + + + + + + +struct mailimap_status_att_list * +mailimap_status_att_list_new(clist * att_list) +{ + struct mailimap_status_att_list * status_att_list; + + status_att_list = malloc(sizeof(* status_att_list)); + if (status_att_list == NULL) + return NULL; + status_att_list->att_list = att_list; + + return status_att_list; +} + +void mailimap_status_att_list_free(struct mailimap_status_att_list * + status_att_list) +{ + clist_foreach(status_att_list->att_list, (clist_func) free, NULL); + clist_free(status_att_list->att_list); + free(status_att_list); +} + + + + +/* main */ + + +struct mailimap_selection_info * +mailimap_selection_info_new(void) +{ + struct mailimap_selection_info * sel_info; + + sel_info = malloc(sizeof(* sel_info)); + if (sel_info == NULL) + return NULL; + + sel_info->sel_perm_flags = NULL; + sel_info->sel_perm = MAILIMAP_MAILBOX_READWRITE; + sel_info->sel_uidnext = 0; + sel_info->sel_uidvalidity = 0; + sel_info->sel_first_unseen = 0; + sel_info->sel_flags = NULL; + sel_info->sel_exists = 0; + sel_info->sel_recent = 0; + sel_info->sel_unseen = 0; + + return sel_info; +} + +void +mailimap_selection_info_free(struct mailimap_selection_info * sel_info) +{ + if (sel_info->sel_perm_flags != NULL) { + clist_foreach(sel_info->sel_perm_flags, + (clist_func) mailimap_flag_perm_free, NULL); + clist_free(sel_info->sel_perm_flags); + } + if (sel_info->sel_flags) + mailimap_flag_list_free(sel_info->sel_flags); + + free(sel_info); +} + +struct mailimap_connection_info * +mailimap_connection_info_new(void) +{ + struct mailimap_connection_info * conn_info; + + conn_info = malloc(sizeof(* conn_info)); + if (conn_info == NULL) + return NULL; + + conn_info->imap_capability = NULL; + + return conn_info; +} + +void +mailimap_connection_info_free(struct mailimap_connection_info * conn_info) +{ + if (conn_info->imap_capability != NULL) + mailimap_capability_data_free(conn_info->imap_capability); + free(conn_info); +} + +struct mailimap_response_info * +mailimap_response_info_new(void) +{ + struct mailimap_response_info * resp_info; + + resp_info = malloc(sizeof(* resp_info)); + if (resp_info == NULL) + goto err; + + resp_info->rsp_alert = NULL; + resp_info->rsp_parse = NULL; + resp_info->rsp_badcharset = NULL; + resp_info->rsp_trycreate = FALSE; + resp_info->rsp_mailbox_list = clist_new(); + if (resp_info->rsp_mailbox_list == NULL) + goto free; + resp_info->rsp_mailbox_lsub = clist_new(); + if (resp_info->rsp_mailbox_lsub == NULL) + goto free_mb_list; + resp_info->rsp_search_result = clist_new(); + if (resp_info->rsp_search_result == NULL) + goto free_mb_lsub; + resp_info->rsp_status = NULL; + resp_info->rsp_expunged = clist_new(); + if (resp_info->rsp_expunged == NULL) + goto free_search_result; + resp_info->rsp_fetch_list = clist_new(); + if (resp_info->rsp_fetch_list == NULL) + goto free_expunged; + + return resp_info; + + free_expunged: + clist_free(resp_info->rsp_expunged); + free_search_result: + clist_free(resp_info->rsp_search_result); + free_mb_lsub: + clist_free(resp_info->rsp_mailbox_lsub); + free_mb_list: + clist_free(resp_info->rsp_mailbox_list); + free: + free(resp_info); + err: + return NULL; +} + +void +mailimap_response_info_free(struct mailimap_response_info * resp_info) +{ + if (resp_info->rsp_alert != NULL) + free(resp_info->rsp_alert); + if (resp_info->rsp_parse != NULL) + free(resp_info->rsp_parse); + if (resp_info->rsp_badcharset != NULL) { + clist_foreach(resp_info->rsp_badcharset, + (clist_func) mailimap_astring_free, NULL); + clist_free(resp_info->rsp_badcharset); + } + if (resp_info->rsp_mailbox_list != NULL) { + clist_foreach(resp_info->rsp_mailbox_list, + (clist_func) mailimap_mailbox_list_free, NULL); + clist_free(resp_info->rsp_mailbox_list); + } + if (resp_info->rsp_mailbox_lsub != NULL) { + clist_foreach(resp_info->rsp_mailbox_lsub, + (clist_func) mailimap_mailbox_list_free, NULL); + clist_free(resp_info->rsp_mailbox_lsub); + } + if (resp_info->rsp_search_result != NULL) + mailimap_mailbox_data_search_free(resp_info->rsp_search_result); + if (resp_info->rsp_status != NULL) + mailimap_mailbox_data_status_free(resp_info->rsp_status); + if (resp_info->rsp_expunged != NULL) { + clist_foreach(resp_info->rsp_expunged, + (clist_func) mailimap_number_alloc_free, NULL); + clist_free(resp_info->rsp_expunged); + } + if (resp_info->rsp_fetch_list != NULL) { + clist_foreach(resp_info->rsp_fetch_list, + (clist_func) mailimap_msg_att_free, NULL); + clist_free(resp_info->rsp_fetch_list); + } + + free(resp_info); +} diff --git a/kmicromail/libetpan/imap/mailimap_types.h b/kmicromail/libetpan/imap/mailimap_types.h new file mode 100644 index 0000000..2996b53 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_types.h @@ -0,0 +1,3274 @@ +/* + * 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$ + */ + +/* + IMAP4rev1 grammar + + address = "(" addr-name SP addr-adl SP addr-mailbox SP + addr-host ")" + + addr-adl = nstring + ; Holds route from [RFC-822] route-addr if + ; non-NIL + + addr-host = nstring + ; NIL indicates [RFC-822] group syntax. + ; Otherwise, holds [RFC-822] domain name + + 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 + + + + addr-name = nstring + ; If non-NIL, holds phrase from [RFC-822] + ; mailbox after removing [RFC-822] quoting + + append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP + literal + + astring = 1*ASTRING-CHAR / string + + ASTRING-CHAR = ATOM-CHAR / resp-specials + + atom = 1*ATOM-CHAR + + ATOM-CHAR = <any CHAR except atom-specials> + + atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards / + quoted-specials / resp-specials + + authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64) + + auth-type = atom + ; Defined by [SASL] + + base64 = *(4base64-char) [base64-terminal] + + base64-char = ALPHA / DIGIT / "+" / "/" + ; Case-sensitive + + base64-terminal = (2base64-char "==") / (3base64-char "=") + + body = "(" (body-type-1part / body-type-mpart) ")" + + 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-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 + + + 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 + + body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP + body-fld-enc SP body-fld-octets + + body-fld-desc = nstring + + body-fld-dsp = "(" string SP body-fld-param ")" / nil + + body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ + "QUOTED-PRINTABLE") DQUOTE) / string + + body-fld-id = nstring + + body-fld-lang = nstring / "(" string *(SP string) ")" + + body-fld-lines = number + + body-fld-md5 = nstring + + body-fld-octets = number + + body-fld-param = "(" string SP string *(SP string SP string) ")" / nil + + body-type-1part = (body-type-basic / body-type-msg / body-type-text) + [SP body-ext-1part] + + body-type-basic = media-basic SP body-fields + ; MESSAGE subtype MUST NOT be "RFC822" + + body-type-mpart = 1*body SP media-subtype + [SP body-ext-mpart] + + body-type-msg = media-message SP body-fields SP envelope + SP body SP body-fld-lines + + body-type-text = media-text SP body-fields SP body-fld-lines + + capability = ("AUTH=" auth-type) / atom + ; New capabilities MUST begin with "X" or be + ; registered with IANA as standard or + ; standards-track + + + capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1" + *(SP capability) + ; IMAP4rev1 servers which offer RFC 1730 + ; compatibility MUST list "IMAP4" as the first + ; capability. + + CHAR8 = %x01-ff + ; any OCTET except NUL, %x00 + + command = tag SP (command-any / command-auth / command-nonauth / + command-select) CRLF + ; Modal based on state + + command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command + ; Valid in all states + + command-auth = append / create / delete / examine / list / lsub / + rename / select / status / subscribe / unsubscribe + ; Valid only in Authenticated or Selected state + + command-nonauth = login / authenticate + ; Valid only when in Not Authenticated state + + command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store / + uid / search + ; Valid only when in Selected state + + continue-req = "+" SP (resp-text / base64) CRLF + + copy = "COPY" SP set SP mailbox + + create = "CREATE" SP mailbox + ; Use of INBOX gives a NO error + + date = date-text / DQUOTE date-text DQUOTE + + date-day = 1*2DIGIT + ; Day of month + + date-day-fixed = (SP DIGIT) / 2DIGIT + ; Fixed-format version of date-day + + date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / + "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" + + date-text = date-day "-" date-month "-" date-year + + date-year = 4DIGIT + + date-time = DQUOTE date-day-fixed "-" date-month "-" date-year + SP time SP zone DQUOTE + + delete = "DELETE" SP mailbox + ; Use of INBOX gives a NO error + + digit-nz = %x31-39 + ; 1-9 + + 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 ")" + + env-bcc = "(" 1*address ")" / nil + + env-cc = "(" 1*address ")" / nil + + env-date = nstring + + env-from = "(" 1*address ")" / nil + + env-in-reply-to = nstring + + env-message-id = nstring + + env-reply-to = "(" 1*address ")" / nil + + env-sender = "(" 1*address ")" / nil + + env-subject = nstring + + env-to = "(" 1*address ")" / nil + + examine = "EXAMINE" SP mailbox + + fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att / + "(" fetch-att *(SP fetch-att) ")") + + 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" + + 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. + + flag-fetch = flag / "\Recent" + + flag-keyword = atom + + flag-list = "(" [flag *(SP flag)] ")" + + flag-perm = flag / "\*" + + greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF + + header-fld-name = astring + + header-list = "(" header-fld-name *(SP header-fld-name) ")" + + list = "LIST" SP mailbox SP list-mailbox + + list-mailbox = 1*list-char / string + + list-char = ATOM-CHAR / list-wildcards / resp-specials + + list-wildcards = "%" / "*" + + literal = "{" number "}" CRLF *CHAR8 + ; Number represents the number of CHAR8s + + login = "LOGIN" SP userid SP password + + 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. + + 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" + + mailbox-list = "(" [mbx-list-flags] ")" SP + (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox + + mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag + *(SP mbx-list-oflag) / + mbx-list-oflag *(SP mbx-list-oflag) + + mbx-list-oflag = "\Noinferiors" / flag-extension + ; Other flags; multiple possible per LIST response + + mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked" + ; Selectability flags; only one per LIST response + + media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE) / string) SP media-subtype + ; Defined in [MIME-IMT] + + media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE + ; Defined in [MIME-IMT] + + media-subtype = string + ; Defined in [MIME-IMT] + + media-text = DQUOTE "TEXT" DQUOTE SP media-subtype + ; Defined in [MIME-IMT] + + message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att)) + + msg-att = "(" (msg-att-dynamic / msg-att-static) + *(SP (msg-att-dynamic / msg-att-static)) ")" + + msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")" + ; MAY change for a message + + 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 + + nil = "NIL" + + nstring = string / nil + + number = 1*DIGIT + ; Unsigned 32-bit integer + ; (0 <= n < 4,294,967,296) + + nz-number = digit-nz *DIGIT + ; Non-zero unsigned 32-bit integer + ; (0 < n < 4,294,967,296) + + password = astring + + quoted = DQUOTE *QUOTED-CHAR DQUOTE + + QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> / + "\" quoted-specials + + quoted-specials = DQUOTE / "\" + + rename = "RENAME" SP mailbox SP mailbox + ; Use of INBOX as a destination gives a NO error + + response = *(continue-req / response-data) response-done + + response-data = "*" SP (resp-cond-state / resp-cond-bye / + mailbox-data / message-data / capability-data) CRLF + + response-done = response-tagged / response-fatal + + response-fatal = "*" SP resp-cond-bye CRLF + ; Server closes connection immediately + + response-tagged = tag SP resp-cond-state CRLF + + resp-cond-auth = ("OK" / "PREAUTH") SP resp-text + ; Authentication condition + + resp-cond-bye = "BYE" SP resp-text + + resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text + ; Status condition + + resp-specials = "]" + + resp-text = ["[" resp-text-code "]" SP] text + + 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*<any TEXT-CHAR except "]">] + + search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key) + ; CHARSET argument to MUST be registered with IANA + + 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] "]" + + section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list / + "TEXT" + ; top-level or MESSAGE/RFC822 part + + section-part = nz-number *("." nz-number) + ; body part nesting + + section-spec = section-msgtext / (section-part ["." section-text]) + + section-text = section-msgtext / "MIME" + ; text other than actual body part (headers, etc.) + + select = "SELECT" SP mailbox + + 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. + + 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. + + + status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")" + + status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / + "UNSEEN" + + store = "STORE" SP set SP store-att-flags + + store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP + (flag-list / (flag *(SP flag))) + + string = quoted / literal + + subscribe = "SUBSCRIBE" SP mailbox + + tag = 1*<any ASTRING-CHAR except "+"> + + text = 1*TEXT-CHAR + + TEXT-CHAR = <any CHAR except CR and LF> + + time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + ; Hours minutes seconds + + uid = "UID" SP (copy / fetch / search / store) + ; Unique identifiers used instead of message + ; sequence numbers + + uniqueid = nz-number + ; Strictly ascending + + unsubscribe = "UNSUBSCRIBE" SP mailbox + + userid = astring + + x-command = "X" atom <experimental command arguments> + + 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". +*/ + + +#ifndef MAILIMAP_TYPES_H + +#define MAILIMAP_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <inttypes.h> +#include <libetpan/mailstream.h> +#include <libetpan/clist.h> + + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + + +/* + mailimap_address represents a mail address + + - personal_name is the name to display in an address + '"name"' in '"name" <address@domain>', should be allocated + with a malloc() + + - source_route is the source-route information in the + mail address (RFC 822), should be allocated with a malloc() + + - mailbox_name is the name of the mailbox 'address' in + '"name" <address@domain>', should be allocated with a malloc() + + - host_name is the name of the host 'domain' in + '"name" <address@domain>', should be allocated with a malloc() + + if mailbox_name is not NULL and host_name is NULL, this is the name + of a group, the next addresses in the list are elements of the group + until we reach an address with a NULL mailbox_name. +*/ + +struct mailimap_address { + char * ad_personal_name; /* can be NULL */ + char * ad_source_route; /* can be NULL */ + char * ad_mailbox_name; /* can be NULL */ + char * ad_host_name; /* can be NULL */ +}; + + +struct mailimap_address * +mailimap_address_new(char * ad_personal_name, char * ad_source_route, + char * ad_mailbox_name, char * ad_host_name); + +void mailimap_address_free(struct mailimap_address * addr); + + +/* this is the type of MIME body parsed by IMAP server */ + +enum { + MAILIMAP_BODY_ERROR, + MAILIMAP_BODY_1PART, /* single part */ + MAILIMAP_BODY_MPART, /* multi-part */ +}; + +/* + mailimap_body represent a MIME body parsed by IMAP server + + - type is the type of the MIME part (single part or multipart) + + - body_1part is defined if this is a single part + + - body_mpart is defined if this is a multipart +*/ + +struct mailimap_body { + int bd_type; + /* can be MAILIMAP_BODY_1PART or MAILIMAP_BODY_MPART */ + union { + struct mailimap_body_type_1part * bd_body_1part; /* can be NULL */ + struct mailimap_body_type_mpart * bd_body_mpart; /* can be NULL */ + } bd_data; +}; + + +struct mailimap_body * +mailimap_body_new(int bd_type, + struct mailimap_body_type_1part * bd_body_1part, + struct mailimap_body_type_mpart * bd_body_mpart); + +void mailimap_body_free(struct mailimap_body * body); + + + +/* + this is the type of MIME body extension +*/ + +enum { + MAILIMAP_BODY_EXTENSION_ERROR, + MAILIMAP_BODY_EXTENSION_NSTRING, /* string */ + MAILIMAP_BODY_EXTENSION_NUMBER, /* number */ + MAILIMAP_BODY_EXTENSION_LIST, /* list of + (struct mailimap_body_extension *) */ +}; + +/* + mailimap_body_extension is a future extension header field value + + - type is the type of the body extension (string, number or + list of extension) + + - nstring is a string value if the type is string + + - number is a integer value if the type is number + + - list is a list of body extension if the type is a list +*/ + +struct mailimap_body_extension { + int ext_type; + /* + can be MAILIMAP_BODY_EXTENSION_NSTRING, MAILIMAP_BODY_EXTENSION_NUMBER + or MAILIMAP_BODY_EXTENSION_LIST + */ + union { + char * ext_nstring; /* can be NULL */ + uint32_t ext_number; + clist * ext_body_extension_list; + /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ + } ext_data; +}; + +struct mailimap_body_extension * +mailimap_body_extension_new(int ext_type, char * ext_nstring, + uint32_t ext_number, + clist * ext_body_extension_list); + +void mailimap_body_extension_free(struct mailimap_body_extension * be); + + +/* + mailimap_body_ext_1part is the extended result part of a single part + bodystructure. + + - body_md5 is the value of the Content-MD5 header field, should be + allocated with malloc() + + - body_disposition is the value of the Content-Disposition header field + + - body_language is the value of the Content-Language header field + + - body_extension_list is the list of extension fields value. +*/ + +struct mailimap_body_ext_1part { + char * bd_md5; /* != NULL */ + struct mailimap_body_fld_dsp * bd_disposition; /* can be NULL */ + struct mailimap_body_fld_lang * bd_language; /* can be NULL */ + + clist * bd_extension_list; /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ +}; + +struct mailimap_body_ext_1part * +mailimap_body_ext_1part_new(char * bd_md5, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + clist * bd_extension_list); + + +void +mailimap_body_ext_1part_free(struct mailimap_body_ext_1part * body_ext_1part); + + +/* + mailimap_body_ext_mpart is the extended result part of a multipart + bodystructure. + + - body_parameter is the list of parameters of Content-Type header field + + - body_disposition is the value of Content-Disposition header field + + - body_language is the value of Content-Language header field + + - body_extension_list is the list of extension fields value. +*/ + +struct mailimap_body_ext_mpart { + struct mailimap_body_fld_param * bd_parameter; /* != NULL */ + struct mailimap_body_fld_dsp * bd_disposition; /* can be NULL */ + struct mailimap_body_fld_lang * bd_language; /* can be NULL */ + clist * bd_extension_list; /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ +}; + +struct mailimap_body_ext_mpart * +mailimap_body_ext_mpart_new(struct mailimap_body_fld_param * bd_parameter, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + clist * bd_extension_list); + +void +mailimap_body_ext_mpart_free(struct mailimap_body_ext_mpart * body_ext_mpart); + + +/* + mailimap_body_fields is the MIME fields of a MIME part. + + - body_parameter is the list of parameters of Content-Type header field + + - body_id is the value of Content-ID header field, should be allocated + with malloc() + + - body_description is the value of Content-Description header field, + should be allocated with malloc() + + - body_encoding is the value of Content-Transfer-Encoding header field + + - body_disposition is the value of Content-Disposition header field + + - body_size is the size of the MIME part +*/ + +struct mailimap_body_fields { + struct mailimap_body_fld_param * bd_parameter; /* != NULL */ + char * bd_id; /* can be NULL */ + char * bd_description; /* can be NULL */ + struct mailimap_body_fld_enc * bd_encoding; /* != NULL */ + uint32_t bd_size; +}; + +struct mailimap_body_fields * +mailimap_body_fields_new(struct mailimap_body_fld_param * bd_parameter, + char * bd_id, + char * bd_description, + struct mailimap_body_fld_enc * bd_encoding, + uint32_t bd_size); + +void +mailimap_body_fields_free(struct mailimap_body_fields * body_fields); + + + +/* + mailimap_body_fld_dsp is the parsed value of the Content-Disposition field + + - disposition_type is the type of Content-Disposition + (usually attachment or inline), should be allocated with malloc() + + - attributes is the list of Content-Disposition attributes +*/ + +struct mailimap_body_fld_dsp { + char * dsp_type; /* != NULL */ + struct mailimap_body_fld_param * dsp_attributes; /* != NULL */ +}; + +struct mailimap_body_fld_dsp * +mailimap_body_fld_dsp_new(char * dsp_type, + struct mailimap_body_fld_param * dsp_attributes); + +void mailimap_body_fld_dsp_free(struct mailimap_body_fld_dsp * bfd); + + + +/* these are the different parsed values for Content-Transfer-Encoding */ + +enum { + MAILIMAP_BODY_FLD_ENC_7BIT, /* 7bit */ + MAILIMAP_BODY_FLD_ENC_8BIT, /* 8bit */ + MAILIMAP_BODY_FLD_ENC_BINARY, /* binary */ + MAILIMAP_BODY_FLD_ENC_BASE64, /* base64 */ + MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE, /* quoted-printable */ + MAILIMAP_BODY_FLD_ENC_OTHER, /* other */ +}; + +/* + mailimap_body_fld_enc is a parsed value for Content-Transfer-Encoding + + - type is the kind of Content-Transfer-Encoding, this can be + MAILIMAP_BODY_FLD_ENC_7BIT, MAILIMAP_BODY_FLD_ENC_8BIT, + MAILIMAP_BODY_FLD_ENC_BINARY, MAILIMAP_BODY_FLD_ENC_BASE64, + MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE or MAILIMAP_BODY_FLD_ENC_OTHER + + - in case of MAILIMAP_BODY_FLD_ENC_OTHER, this value is defined, + should be allocated with malloc() +*/ + +struct mailimap_body_fld_enc { + int enc_type; + char * enc_value; /* can be NULL */ +}; + +struct mailimap_body_fld_enc * +mailimap_body_fld_enc_new(int enc_type, char * enc_value); + +void mailimap_body_fld_enc_free(struct mailimap_body_fld_enc * bfe); + + +/* this is the type of Content-Language header field value */ + +enum { + MAILIMAP_BODY_FLD_LANG_ERROR, /* error parse */ + MAILIMAP_BODY_FLD_LANG_SINGLE, /* single value */ + MAILIMAP_BODY_FLD_LANG_LIST /* list of values */ +}; + +/* + mailimap_body_fld_lang is the parsed value of the Content-Language field + + - type is the type of content, this can be MAILIMAP_BODY_FLD_LANG_SINGLE + if this is a single value or MAILIMAP_BODY_FLD_LANG_LIST if there are + several values + + - single is the single value if the type is MAILIMAP_BODY_FLD_LANG_SINGLE, + should be allocated with malloc() + + - list is the list of value if the type is MAILIMAP_BODY_FLD_LANG_LIST, + all elements of the list should be allocated with malloc() +*/ + +struct mailimap_body_fld_lang { + int lg_type; + union { + char * lg_single; /* can be NULL */ + clist * lg_list; /* list of string (char *), can be NULL */ + } lg_data; +}; + +struct mailimap_body_fld_lang * +mailimap_body_fld_lang_new(int lg_type, char * lg_single, clist * lg_list); + +void +mailimap_body_fld_lang_free(struct mailimap_body_fld_lang * fld_lang); + + + +/* + mailimap_single_body_fld_param is a body field parameter + + - name is the name of the parameter, should be allocated with malloc() + + - value is the value of the parameter, should be allocated with malloc() +*/ + +struct mailimap_single_body_fld_param { + char * pa_name; /* != NULL */ + char * pa_value; /* != NULL */ +}; + +struct mailimap_single_body_fld_param * +mailimap_single_body_fld_param_new(char * pa_name, char * pa_value); + +void +mailimap_single_body_fld_param_free(struct mailimap_single_body_fld_param * p); + + +/* + mailmap_body_fld_param is a list of parameters + + - list is the list of parameters. +*/ + +struct mailimap_body_fld_param { + clist * pa_list; /* list of (struct mailimap_single_body_fld_param *) */ + /* != NULL */ +}; + +struct mailimap_body_fld_param * +mailimap_body_fld_param_new(clist * pa_list); + +void +mailimap_body_fld_param_free(struct mailimap_body_fld_param * fld_param); + + +/* + this is the kind of single part: a text part + (when Content-Type is text/xxx), a message part (when Content-Type is + message/rfc2822) or a basic part (others than multpart/xxx) +*/ + +enum { + MAILIMAP_BODY_TYPE_1PART_ERROR, /* parse error */ + MAILIMAP_BODY_TYPE_1PART_BASIC, /* others then multipart/xxx */ + MAILIMAP_BODY_TYPE_1PART_MSG, /* message/rfc2822 */ + MAILIMAP_BODY_TYPE_1PART_TEXT /* text/xxx */ +}; + + +/* + mailimap_body_type_1part is + + - type is the kind of single part, this can be + MAILIMAP_BODY_TYPE_1PART_BASIC, MAILIMAP_BODY_TYPE_1PART_MSG or + MAILIMAP_BODY_TYPE_1PART_TEXT. + + - body_type_basic is the basic part when type is + MAILIMAP_BODY_TYPE_1PART_BASIC + + - body_type_msg is the message part when type is + MAILIMAP_BODY_TYPE_1PART_MSG + + - body_type_text is the text part when type is + MAILIMAP_BODY_TYPE_1PART_TEXT +*/ + +struct mailimap_body_type_1part { + int bd_type; + union { + struct mailimap_body_type_basic * bd_type_basic; /* can be NULL */ + struct mailimap_body_type_msg * bd_type_msg; /* can be NULL */ + struct mailimap_body_type_text * bd_type_text; /* can be NULL */ + } bd_data; + struct mailimap_body_ext_1part * bd_ext_1part; /* can be NULL */ +}; + +struct mailimap_body_type_1part * +mailimap_body_type_1part_new(int bd_type, + struct mailimap_body_type_basic * bd_type_basic, + struct mailimap_body_type_msg * bd_type_msg, + struct mailimap_body_type_text * bd_type_text, + struct mailimap_body_ext_1part * bd_ext_1part); + +void +mailimap_body_type_1part_free(struct mailimap_body_type_1part * bt1p); + + + +/* + mailimap_body_type_basic is a basic field (with Content-Type other + than multipart/xxx, message/rfc2822 and text/xxx + + - media_basic will be the MIME type of the part + + - body_fields will be the parsed fields of the MIME part +*/ + +struct mailimap_body_type_basic { + struct mailimap_media_basic * bd_media_basic; /* != NULL */ + struct mailimap_body_fields * bd_fields; /* != NULL */ +}; + +struct mailimap_body_type_basic * +mailimap_body_type_basic_new(struct mailimap_media_basic * bd_media_basic, + struct mailimap_body_fields * bd_fields); + +void mailimap_body_type_basic_free(struct mailimap_body_type_basic * + body_type_basic); + +/* + mailimap_body_type_mpart is a MIME multipart. + + - body_list is the list of sub-parts. + + - media_subtype is the subtype of the multipart (for example + in multipart/alternative, this is "alternative") + + - body_ext_mpart is the extended fields of the MIME multipart +*/ + +struct mailimap_body_type_mpart { + clist * bd_list; /* list of (struct mailimap_body *) */ + /* != NULL */ + char * bd_media_subtype; /* != NULL */ + struct mailimap_body_ext_mpart * bd_ext_mpart; /* can be NULL */ +}; + +struct mailimap_body_type_mpart * +mailimap_body_type_mpart_new(clist * bd_list, char * bd_media_subtype, + struct mailimap_body_ext_mpart * bd_ext_mpart); + +void mailimap_body_type_mpart_free(struct mailimap_body_type_mpart * + body_type_mpart); + +/* + mailimap_body_type_msg is a MIME message part + + - body_fields is the MIME fields of the MIME message part + + - envelope is the list of parsed RFC 822 fields of the MIME message + + - body is the sub-part of the message + + - body_lines is the number of lines of the message part +*/ + +struct mailimap_body_type_msg { + struct mailimap_body_fields * bd_fields; /* != NULL */ + struct mailimap_envelope * bd_envelope; /* != NULL */ + struct mailimap_body * bd_body; /* != NULL */ + uint32_t bd_lines; +}; + +struct mailimap_body_type_msg * +mailimap_body_type_msg_new(struct mailimap_body_fields * bd_fields, + struct mailimap_envelope * bd_envelope, + struct mailimap_body * bd_body, + uint32_t bd_lines); + +void +mailimap_body_type_msg_free(struct mailimap_body_type_msg * body_type_msg); + + + +/* + mailimap_body_type_text is a single MIME part where Content-Type is text/xxx + + - media-text is the subtype of the text part (for example, in "text/plain", + this is "plain", should be allocated with malloc() + + - body_fields is the MIME fields of the MIME message part + + - body_lines is the number of lines of the message part +*/ + +struct mailimap_body_type_text { + char * bd_media_text; /* != NULL */ + struct mailimap_body_fields * bd_fields; /* != NULL */ + uint32_t bd_lines; +}; + +struct mailimap_body_type_text * +mailimap_body_type_text_new(char * bd_media_text, + struct mailimap_body_fields * bd_fields, + uint32_t bd_lines); + +void +mailimap_body_type_text_free(struct mailimap_body_type_text * body_type_text); + + + +/* this is the type of capability field */ + +enum { + MAILIMAP_CAPABILITY_AUTH_TYPE, /* when the capability is an + authentication type */ + MAILIMAP_CAPABILITY_NAME, /* other type of capability */ +}; + +/* + mailimap_capability is a capability of the IMAP server + + - type is the type of capability, this is either a authentication type + (MAILIMAP_CAPABILITY_AUTH_TYPE) or an other type of capability + (MAILIMAP_CAPABILITY_NAME) + + - auth_type is a type of authentication "name" in "AUTH=name", + auth_type can be for example "PLAIN", when this is an authentication type, + should be allocated with malloc() + + - name is a type of capability when this is not an authentication type, + should be allocated with malloc() +*/ + +struct mailimap_capability { + int cap_type; + union { + char * cap_auth_type; /* can be NULL */ + char * cap_name; /* can be NULL */ + } cap_data; +}; + +struct mailimap_capability * +mailimap_capability_new(int cap_type, char * cap_auth_type, char * cap_name); + +void mailimap_capability_free(struct mailimap_capability * c); + + + + +/* + mailimap_capability_data is a list of capability + + - list is the list of capability +*/ + +struct mailimap_capability_data { + clist * cap_list; /* list of (struct mailimap_capability *), != NULL */ +}; + +struct mailimap_capability_data * +mailimap_capability_data_new(clist * cap_list); + +void +mailimap_capability_data_free(struct mailimap_capability_data * cap_data); + + + +/* this is the type of continue request data */ + +enum { + MAILIMAP_CONTINUE_REQ_ERROR, /* on parse error */ + MAILIMAP_CONTINUE_REQ_TEXT, /* when data is a text response */ + MAILIMAP_CONTINUE_REQ_BASE64, /* when data is a base64 response */ +}; + +/* + mailimap_continue_req is a continue request (a response prefixed by "+") + + - type is the type of continue request response + MAILIMAP_CONTINUE_REQ_TEXT (when information data is text), + MAILIMAP_CONTINUE_REQ_BASE64 (when information data is base64) + + - text is the information of type text in case of text data + + - base64 is base64 encoded data in the other case, should be allocated + with malloc() +*/ + +struct mailimap_continue_req { + int cr_type; + union { + struct mailimap_resp_text * cr_text; /* can be NULL */ + char * cr_base64; /* can be NULL */ + } cr_data; +}; + +struct mailimap_continue_req * +mailimap_continue_req_new(int cr_type, struct mailimap_resp_text * cr_text, + char * cr_base64); + +void mailimap_continue_req_free(struct mailimap_continue_req * cont_req); + + +/* + mailimap_date_time is a date + + - day is the day of month (1 to 31) + + - month (1 to 12) + + - year (4 digits) + + - hour (0 to 23) + + - min (0 to 59) + + - sec (0 to 59) + + - zone (this is the decimal value that we can read, for example: + for "-0200", the value is -200) +*/ + +struct mailimap_date_time { + int dt_day; + int dt_month; + int dt_year; + int dt_hour; + int dt_min; + int dt_sec; + int dt_zone; +}; + +struct mailimap_date_time * +mailimap_date_time_new(int dt_day, int dt_month, int dt_year, int dt_hour, + int dt_min, int dt_sec, int dt_zone); + +void mailimap_date_time_free(struct mailimap_date_time * date_time); + + + +/* + mailimap_envelope is the list of fields that can be parsed by + the IMAP server. + + - date is the (non-parsed) content of the "Date" header field, + should be allocated with malloc() + + - subject is the subject of the message, should be allocated with + malloc() + + - sender is the the parsed content of the "Sender" field + + - reply-to is the parsed content of the "Reply-To" field + + - to is the parsed content of the "To" field + + - cc is the parsed content of the "Cc" field + + - bcc is the parsed content of the "Bcc" field + + - in_reply_to is the content of the "In-Reply-To" field, + should be allocated with malloc() + + - message_id is the content of the "Message-ID" field, + should be allocated with malloc() +*/ + +struct mailimap_envelope { + char * env_date; /* can be NULL */ + char * env_subject; /* can be NULL */ + struct mailimap_env_from * env_from; /* can be NULL */ + struct mailimap_env_sender * env_sender; /* can be NULL */ + struct mailimap_env_reply_to * env_reply_to; /* can be NULL */ + struct mailimap_env_to * env_to; /* can be NULL */ + struct mailimap_env_cc * env_cc; /* can be NULL */ + struct mailimap_env_bcc * env_bcc; /* can be NULL */ + char * env_in_reply_to; /* can be NULL */ + char * env_message_id; /* can be NULL */ +}; + +struct mailimap_envelope * +mailimap_envelope_new(char * env_date, char * env_subject, + struct mailimap_env_from * env_from, + struct mailimap_env_sender * env_sender, + struct mailimap_env_reply_to * env_reply_to, + struct mailimap_env_to * env_to, + struct mailimap_env_cc* env_cc, + struct mailimap_env_bcc * env_bcc, + char * env_in_reply_to, char * env_message_id); + +void mailimap_envelope_free(struct mailimap_envelope * env); + + + +/* + mailimap_env_bcc is the parsed "Bcc" field + + - list is the list of addresses +*/ + +struct mailimap_env_bcc { + clist * bcc_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_bcc * mailimap_env_bcc_new(clist * bcc_list); + +void mailimap_env_bcc_free(struct mailimap_env_bcc * env_bcc); + + +/* + mailimap_env_cc is the parsed "Cc" field + + - list is the list of addresses +*/ + +struct mailimap_env_cc { + clist * cc_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_cc * mailimap_env_cc_new(clist * cc_list); + +void mailimap_env_cc_free(struct mailimap_env_cc * env_cc); + + + +/* + mailimap_env_from is the parsed "From" field + + - list is the list of addresses +*/ + +struct mailimap_env_from { + clist * frm_list; /* list of (struct mailimap_address *) */ + /* != NULL */ +}; + +struct mailimap_env_from * mailimap_env_from_new(clist * frm_list); + +void mailimap_env_from_free(struct mailimap_env_from * env_from); + + + +/* + mailimap_env_reply_to is the parsed "Reply-To" field + + - list is the list of addresses +*/ + +struct mailimap_env_reply_to { + clist * rt_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_reply_to * mailimap_env_reply_to_new(clist * rt_list); + +void +mailimap_env_reply_to_free(struct mailimap_env_reply_to * env_reply_to); + + + +/* + mailimap_env_sender is the parsed "Sender" field + + - list is the list of addresses +*/ + +struct mailimap_env_sender { + clist * snd_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_sender * mailimap_env_sender_new(clist * snd_list); + +void mailimap_env_sender_free(struct mailimap_env_sender * env_sender); + + + +/* + mailimap_env_to is the parsed "To" field + + - list is the list of addresses +*/ + +struct mailimap_env_to { + clist * to_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_to * mailimap_env_to_new(clist * to_list); + +void mailimap_env_to_free(struct mailimap_env_to * env_to); + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_ANSWERED, /* \Answered flag */ + MAILIMAP_FLAG_FLAGGED, /* \Flagged flag */ + MAILIMAP_FLAG_DELETED, /* \Deleted flag */ + MAILIMAP_FLAG_SEEN, /* \Seen flag */ + MAILIMAP_FLAG_DRAFT, /* \Draft flag */ + MAILIMAP_FLAG_KEYWORD, /* keyword flag */ + MAILIMAP_FLAG_EXTENSION, /* \extension flag */ +}; + + +/* + mailimap_flag is a message flag (that we can associate with a message) + + - type is the type of the flag, MAILIMAP_FLAG_XXX + + - keyword is the flag when the flag is of keyword type, + should be allocated with malloc() + + - extension is the flag when the flag is of extension type, should be + allocated with malloc() +*/ + +struct mailimap_flag { + int fl_type; + union { + char * fl_keyword; /* can be NULL */ + char * fl_extension; /* can be NULL */ + } fl_data; +}; + +struct mailimap_flag * mailimap_flag_new(int fl_type, + char * fl_keyword, char * fl_extension); + +void mailimap_flag_free(struct mailimap_flag * f); + + + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_FETCH_ERROR, /* on parse error */ + MAILIMAP_FLAG_FETCH_RECENT, /* \Recent flag */ + MAILIMAP_FLAG_FETCH_OTHER, /* other type of flag */ +}; + +/* + mailimap_flag_fetch is a message flag (when we fetch it) + + - type is the type of flag fetch + + - flag is the flag when this is not a \Recent flag +*/ + +struct mailimap_flag_fetch { + int fl_type; + struct mailimap_flag * fl_flag; /* can be NULL */ +}; + +struct mailimap_flag_fetch * +mailimap_flag_fetch_new(int fl_type, struct mailimap_flag * fl_flag); + +void mailimap_flag_fetch_free(struct mailimap_flag_fetch * flag_fetch); + + + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_PERM_ERROR, /* on parse error */ + MAILIMAP_FLAG_PERM_FLAG, /* to specify that usual flags can be changed */ + MAILIMAP_FLAG_PERM_ALL /* to specify that new flags can be created */ +}; + + +/* + mailimap_flag_perm is a flag returned in case of PERMANENTFLAGS response + + - type is the type of returned PERMANENTFLAGS, it can be + MAILIMAP_FLAG_PERM_FLAG (the given flag can be changed permanently) or + MAILIMAP_FLAG_PERM_ALL (new flags can be created) + + - flag is the given flag when type is MAILIMAP_FLAG_PERM_FLAG +*/ + +struct mailimap_flag_perm { + int fl_type; + struct mailimap_flag * fl_flag; /* can be NULL */ +}; + +struct mailimap_flag_perm * +mailimap_flag_perm_new(int fl_type, struct mailimap_flag * fl_flag); + +void mailimap_flag_perm_free(struct mailimap_flag_perm * flag_perm); + + +/* + mailimap_flag_list is a list of flags + + - list is a list of flags +*/ + +struct mailimap_flag_list { + clist * fl_list; /* list of (struct mailimap_flag *), != NULL */ +}; + +struct mailimap_flag_list * +mailimap_flag_list_new(clist * fl_list); + +void mailimap_flag_list_free(struct mailimap_flag_list * flag_list); + + + + +/* this is the type of greeting response */ + +enum { + MAILIMAP_GREETING_RESP_COND_ERROR, /* on parse error */ + MAILIMAP_GREETING_RESP_COND_AUTH, /* when connection is accepted */ + MAILIMAP_GREETING_RESP_COND_BYE, /* when connection is refused */ +}; + +/* + mailimap_greeting is the response returned on connection + + - type is the type of response on connection, either + MAILIMAP_GREETING_RESP_COND_AUTH if connection is accepted or + MAIMIMAP_GREETING_RESP_COND_BYE if connection is refused +*/ + +struct mailimap_greeting { + int gr_type; + union { + struct mailimap_resp_cond_auth * gr_auth; /* can be NULL */ + struct mailimap_resp_cond_bye * gr_bye; /* can be NULL */ + } gr_data; +}; + +struct mailimap_greeting * +mailimap_greeting_new(int gr_type, + struct mailimap_resp_cond_auth * gr_auth, + struct mailimap_resp_cond_bye * gr_bye); + +void mailimap_greeting_free(struct mailimap_greeting * greeting); + + +/* + mailimap_header_list is a list of headers that can be specified when + we want to fetch fields + + - list is a list of header names, each header name should be allocated + with malloc() +*/ + +struct mailimap_header_list { + clist * hdr_list; /* list of astring (char *), != NULL */ +}; + +struct mailimap_header_list * +mailimap_header_list_new(clist * hdr_list); + +void +mailimap_header_list_free(struct mailimap_header_list * header_list); + + + +/* this is the type of mailbox STATUS that can be returned */ + +enum { + MAILIMAP_STATUS_ATT_MESSAGES, /* when requesting the number of + messages */ + MAILIMAP_STATUS_ATT_RECENT, /* when requesting the number of + recent messages */ + MAILIMAP_STATUS_ATT_UIDNEXT, /* when requesting the next unique + identifier */ + MAILIMAP_STATUS_ATT_UIDVALIDITY, /* when requesting the validity of + message unique identifiers*/ + MAILIMAP_STATUS_ATT_UNSEEN, /* when requesting the number of + unseen messages */ +}; + +/* + mailimap_status_info is a returned information when a STATUS of + a mailbox is requested + + - att is the type of mailbox STATUS, the value can be + MAILIMAP_STATUS_ATT_MESSAGES, MAILIMAP_STATUS_ATT_RECENT, + MAILIMAP_STATUS_ATT_UIDNEXT, MAILIMAP_STATUS_ATT_UIDVALIDITY or + MAILIMAP_STATUS_ATT_UNSEEN + + - value is the value of the given information +*/ + +struct mailimap_status_info { + int st_att; + uint32_t st_value; +}; + +struct mailimap_status_info * +mailimap_status_info_new(int st_att, uint32_t st_value); + +void mailimap_status_info_free(struct mailimap_status_info * info); + + + +/* + mailimap_mailbox_data_status is the list of information returned + when a STATUS of a mailbox is requested + + - mailbox is the name of the mailbox, should be allocated with malloc() + + - status_info_list is the list of information returned +*/ + +struct mailimap_mailbox_data_status { + char * st_mailbox; + clist * st_info_list; /* list of (struct mailimap_status_info *) */ + /* can be NULL */ +}; + +struct mailimap_mailbox_data_status * +mailimap_mailbox_data_status_new(char * st_mailbox, + clist * st_info_list); + +void +mailimap_mailbox_data_status_free(struct mailimap_mailbox_data_status * info); + + + +/* this is the type of mailbox information that is returned */ + +enum { + MAILIMAP_MAILBOX_DATA_ERROR, /* on parse error */ + MAILIMAP_MAILBOX_DATA_FLAGS, /* flag that are applicable to the mailbox */ + MAILIMAP_MAILBOX_DATA_LIST, /* this is a mailbox in the list of mailboxes + returned on LIST command*/ + MAILIMAP_MAILBOX_DATA_LSUB, /* this is a mailbox in the list of + subscribed mailboxes returned on LSUB + command */ + MAILIMAP_MAILBOX_DATA_SEARCH, /* this is a list of messages numbers or + unique identifiers returned + on a SEARCH command*/ + MAILIMAP_MAILBOX_DATA_STATUS, /* this is the list of information returned + on a STATUS command */ + MAILIMAP_MAILBOX_DATA_EXISTS, /* this is the number of messages in the + mailbox */ + MAILIMAP_MAILBOX_DATA_RECENT, /* this is the number of recent messages + in the mailbox */ +}; + +/* + mailimap_mailbox_data is an information related to a mailbox + + - type is the type of mailbox_data that is filled, the value of this field + can be MAILIMAP_MAILBOX_DATA_FLAGS, MAILIMAP_MAILBOX_DATA_LIST, + MAILIMAP_MAILBOX_DATA_LSUB, MAILIMAP_MAILBOX_DATA_SEARCH, + MAILIMAP_MAILBOX_DATA_STATUS, MAILIMAP_MAILBOX_DATA_EXISTS + or MAILIMAP_MAILBOX_DATA_RECENT. + + - flags is the flags that are applicable to the mailbox when + type is MAILIMAP_MAILBOX_DATA_FLAGS + + - list is a mailbox in the list of mailboxes returned on LIST command + when type is MAILIMAP_MAILBOX_DATA_LIST + + - lsub is a mailbox in the list of subscribed mailboxes returned on + LSUB command when type is MAILIMAP_MAILBOX_DATA_LSUB + + - search is a list of messages numbers or unique identifiers returned + on SEARCH command when type MAILIMAP_MAILBOX_DATA_SEARCH, each element + should be allocated with malloc() + + - status is a list of information returned on STATUS command when + type is MAILIMAP_MAILBOX_DATA_STATUS + + - exists is the number of messages in the mailbox when type + is MAILIMAP_MAILBOX_DATA_EXISTS + + - recent is the number of recent messages in the mailbox when type + is MAILIMAP_MAILBOX_DATA_RECENT +*/ + +struct mailimap_mailbox_data { + int mbd_type; + union { + struct mailimap_flag_list * mbd_flags; /* can be NULL */ + struct mailimap_mailbox_list * mbd_list; /* can be NULL */ + struct mailimap_mailbox_list * mbd_lsub; /* can be NULL */ + clist * mbd_search; /* list of nz-number (uint32_t *), can be NULL */ + struct mailimap_mailbox_data_status * mbd_status; /* can be NULL */ + uint32_t mbd_exists; + uint32_t mbd_recent; + } mbd_data; +}; + +struct mailimap_mailbox_data * +mailimap_mailbox_data_new(int mbd_type, struct mailimap_flag_list * mbd_flags, + struct mailimap_mailbox_list * mbd_list, + struct mailimap_mailbox_list * mbd_lsub, + clist * mbd_search, + struct mailimap_mailbox_data_status * mbd_status, + uint32_t mbd_exists, + uint32_t mbd_recent); + +void +mailimap_mailbox_data_free(struct mailimap_mailbox_data * mb_data); + + + +/* this is the type of mailbox flags */ + +enum { + MAILIMAP_MBX_LIST_FLAGS_SFLAG, /* mailbox single flag - a flag in + {\NoSelect, \Marked, \Unmarked} */ + MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG, /* mailbox other flag - mailbox flag + other than \NoSelect \Marked and + \Unmarked) */ +}; + +/* this is a single flag type */ + +enum { + MAILIMAP_MBX_LIST_SFLAG_ERROR, + MAILIMAP_MBX_LIST_SFLAG_MARKED, + MAILIMAP_MBX_LIST_SFLAG_NOSELECT, + MAILIMAP_MBX_LIST_SFLAG_UNMARKED +}; + +/* + mailimap_mbx_list_flags is a mailbox flag + + - type is the type of mailbox flag, it can be MAILIMAP_MBX_LIST_FLAGS_SFLAG, + or MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG. + + - oflags is a list of "mailbox other flag" + + - sflag is a mailbox single flag +*/ + +struct mailimap_mbx_list_flags { + int mbf_type; + clist * mbf_oflags; /* list of + (struct mailimap_mbx_list_oflag *), != NULL */ + int mbf_sflag; +}; + +struct mailimap_mbx_list_flags * +mailimap_mbx_list_flags_new(int mbf_type, + clist * mbf_oflags, int mbf_sflag); + +void +mailimap_mbx_list_flags_free(struct mailimap_mbx_list_flags * mbx_list_flags); + + + +/* this is the type of the mailbox other flag */ + +enum { + MAILIMAP_MBX_LIST_OFLAG_ERROR, /* on parse error */ + MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS, /* \NoInferior flag */ + MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT /* other flag */ +}; + +/* + mailimap_mbx_list_oflag is a mailbox other flag + + - type can be MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS when this is + a \NoInferior flag or MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT + + - flag_ext is set when MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT and is + an extension flag, should be allocated with malloc() +*/ + +struct mailimap_mbx_list_oflag { + int of_type; + char * of_flag_ext; /* can be NULL */ +}; + +struct mailimap_mbx_list_oflag * +mailimap_mbx_list_oflag_new(int of_type, char * of_flag_ext); + +void +mailimap_mbx_list_oflag_free(struct mailimap_mbx_list_oflag * oflag); + + + +/* + mailimap_mailbox_list is a list of mailbox flags + + - mb_flag is a list of mailbox flags + + - delimiter is the delimiter of the mailbox path + + - mb is the name of the mailbox, should be allocated with malloc() +*/ + +struct mailimap_mailbox_list { + struct mailimap_mbx_list_flags * mb_flag; /* can be NULL */ + char mb_delimiter; + char * mb_name; /* != NULL */ +}; + +struct mailimap_mailbox_list * +mailimap_mailbox_list_new(struct mailimap_mbx_list_flags * mbx_flags, + char mb_delimiter, char * mb_name); + +void +mailimap_mailbox_list_free(struct mailimap_mailbox_list * mb_list); + + + +/* this is the MIME type */ + +enum { + MAILIMAP_MEDIA_BASIC_APPLICATION, /* application/xxx */ + MAILIMAP_MEDIA_BASIC_AUDIO, /* audio/xxx */ + MAILIMAP_MEDIA_BASIC_IMAGE, /* image/xxx */ + MAILIMAP_MEDIA_BASIC_MESSAGE, /* message/xxx */ + MAILIMAP_MEDIA_BASIC_VIDEO, /* video/xxx */ + MAILIMAP_MEDIA_BASIC_OTHER, /* for all other cases */ +}; + + +/* + mailimap_media_basic is the MIME type + + - type can be MAILIMAP_MEDIA_BASIC_APPLICATION, MAILIMAP_MEDIA_BASIC_AUDIO, + MAILIMAP_MEDIA_BASIC_IMAGE, MAILIMAP_MEDIA_BASIC_MESSAGE, + MAILIMAP_MEDIA_BASIC_VIDEO or MAILIMAP_MEDIA_BASIC_OTHER + + - basic_type is defined when type is MAILIMAP_MEDIA_BASIC_OTHER, should + be allocated with malloc() + + - subtype is the subtype of the MIME type, for example, this is + "data" in "application/data", should be allocated with malloc() +*/ + +struct mailimap_media_basic { + int med_type; + char * med_basic_type; /* can be NULL */ + char * med_subtype; /* != NULL */ +}; + +struct mailimap_media_basic * +mailimap_media_basic_new(int med_type, + char * med_basic_type, char * med_subtype); + +void +mailimap_media_basic_free(struct mailimap_media_basic * media_basic); + + + +/* this is the type of message data */ + +enum { + MAILIMAP_MESSAGE_DATA_ERROR, + MAILIMAP_MESSAGE_DATA_EXPUNGE, + MAILIMAP_MESSAGE_DATA_FETCH +}; + +/* + mailimap_message_data is an information related to a message + + - number is the number or the unique identifier of the message + + - type is the type of information, this value can be + MAILIMAP_MESSAGE_DATA_EXPUNGE or MAILIMAP_MESSAGE_DATA_FETCH + + - msg_att is the message data +*/ + +struct mailimap_message_data { + uint32_t mdt_number; + int mdt_type; + struct mailimap_msg_att * mdt_msg_att; /* can be NULL */ + /* if type = EXPUNGE, can be NULL */ +}; + +struct mailimap_message_data * +mailimap_message_data_new(uint32_t mdt_number, int mdt_type, + struct mailimap_msg_att * mdt_msg_att); + +void +mailimap_message_data_free(struct mailimap_message_data * msg_data); + + + +/* this the type of the message attributes */ + +enum { + MAILIMAP_MSG_ATT_ITEM_ERROR, /* on parse error */ + MAILIMAP_MSG_ATT_ITEM_DYNAMIC, /* dynamic message attributes (flags) */ + MAILIMAP_MSG_ATT_ITEM_STATIC, /* static messages attributes + (message content) */ +}; + +/* + mailimap_msg_att_item is a message attribute + + - type is the type of message attribute, the value can be + MAILIMAP_MSG_ATT_ITEM_DYNAMIC or MAILIMAP_MSG_ATT_ITEM_STATIC + + - msg_att_dyn is a dynamic message attribute when type is + MAILIMAP_MSG_ATT_ITEM_DYNAMIC + + - msg_att_static is a static message attribute when type is + MAILIMAP_MSG_ATT_ITEM_STATIC +*/ + +struct mailimap_msg_att_item { + int att_type; + union { + struct mailimap_msg_att_dynamic * att_dyn; /* can be NULL */ + struct mailimap_msg_att_static * att_static; /* can be NULL */ + } att_data; +}; + +struct mailimap_msg_att_item * +mailimap_msg_att_item_new(int att_type, + struct mailimap_msg_att_dynamic * att_dyn, + struct mailimap_msg_att_static * att_static); + +void +mailimap_msg_att_item_free(struct mailimap_msg_att_item * item); + + +/* + mailimap_msg_att is a list of attributes + + - list is a list of message attributes + + - number is the message number or unique identifier, this field + has been added for implementation purpose +*/ + +struct mailimap_msg_att { + clist * att_list; /* list of (struct mailimap_msg_att_item *) */ + /* != NULL */ + uint32_t att_number; /* extra field to store the message number, + used for mailimap */ +}; + +struct mailimap_msg_att * mailimap_msg_att_new(clist * att_list); + +void mailimap_msg_att_free(struct mailimap_msg_att * msg_att); + + +/* + mailimap_msg_att_dynamic is a dynamic message attribute + + - list is a list of flags (that have been fetched) +*/ + +struct mailimap_msg_att_dynamic { + clist * att_list; /* list of (struct mailimap_flag_fetch *) */ + /* can be NULL */ +}; + +struct mailimap_msg_att_dynamic * +mailimap_msg_att_dynamic_new(clist * att_list); + +void +mailimap_msg_att_dynamic_free(struct mailimap_msg_att_dynamic * msg_att_dyn); + + + +/* + mailimap_msg_att_body_section is a MIME part content + + - section is the location of the MIME part in the message + + - origin_octet is the offset of the requested part of the MIME part + + - body_part is the content or partial content of the MIME part, + should be allocated through a MMAPString + + - length is the size of the content +*/ + +struct mailimap_msg_att_body_section { + struct mailimap_section * sec_section; /* != NULL */ + uint32_t sec_origin_octet; + char * sec_body_part; /* can be NULL */ + size_t sec_length; +}; + +struct mailimap_msg_att_body_section * +mailimap_msg_att_body_section_new(struct mailimap_section * section, + uint32_t sec_origin_octet, + char * sec_body_part, + size_t sec_length); + +void +mailimap_msg_att_body_section_free(struct mailimap_msg_att_body_section * + msg_att_body_section); + + + +/* + this is the type of static message attribute +*/ + +enum { + MAILIMAP_MSG_ATT_ERROR, /* on parse error */ + MAILIMAP_MSG_ATT_ENVELOPE, /* this is the fields that can be + parsed by the server */ + MAILIMAP_MSG_ATT_INTERNALDATE, /* this is the message date kept + by the server */ + MAILIMAP_MSG_ATT_RFC822, /* this is the message content + (header and body) */ + MAILIMAP_MSG_ATT_RFC822_HEADER, /* this is the message header */ + MAILIMAP_MSG_ATT_RFC822_TEXT, /* this is the message text part */ + MAILIMAP_MSG_ATT_RFC822_SIZE, /* this is the size of the message content */ + MAILIMAP_MSG_ATT_BODY, /* this is the MIME description of + the message */ + MAILIMAP_MSG_ATT_BODYSTRUCTURE, /* this is the MIME description of the + message with additional information */ + MAILIMAP_MSG_ATT_BODY_SECTION, /* this is a MIME part content */ + MAILIMAP_MSG_ATT_UID, /* this is the message unique identifier */ +}; + +/* + mailimap_msg_att_static is a given part of the message + + - type is the type of the static message attribute, the value can be + MAILIMAP_MSG_ATT_ENVELOPE, MAILIMAP_MSG_ATT_INTERNALDATE, + MAILIMAP_MSG_ATT_RFC822, MAILIMAP_MSG_ATT_RFC822_HEADER, + MAILIMAP_MSG_ATT_RFC822_TEXT, MAILIMAP_MSG_ATT_RFC822_SIZE, + MAILIMAP_MSG_ATT_BODY, MAILIMAP_MSG_ATT_BODYSTRUCTURE, + MAILIMAP_MSG_ATT_BODY_SECTION, MAILIMAP_MSG_ATT_UID + + - env is the headers parsed by the server if type is + MAILIMAP_MSG_ATT_ENVELOPE + + - internal_date is the date of message kept by the server if type is + MAILIMAP_MSG_ATT_INTERNALDATE + + - rfc822 is the message content if type is MAILIMAP_MSG_ATT_RFC822, + should be allocated through a MMAPString + + - rfc822_header is the message header if type is + MAILIMAP_MSG_ATT_RFC822_HEADER, should be allocated through a MMAPString + + - rfc822_text is the message text part if type is + MAILIMAP_MSG_ATT_RFC822_TEXT, should be allocated through a MMAPString + + - rfc822_size is the message size if type is MAILIMAP_MSG_ATT_SIZE + + - body is the MIME description of the message + + - bodystructure is the MIME description of the message with additional + information + + - body_section is a MIME part content + + - uid is a unique message identifier +*/ + +struct mailimap_msg_att_static { + int att_type; + union { + struct mailimap_envelope * att_env; /* can be NULL */ + struct mailimap_date_time * att_internal_date; /* can be NULL */ + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822; + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822_header; + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822_text; + uint32_t att_rfc822_size; + struct mailimap_body * att_bodystructure; /* can be NULL */ + struct mailimap_body * att_body; /* can be NULL */ + struct mailimap_msg_att_body_section * att_body_section; /* can be NULL */ + uint32_t att_uid; + } att_data; +}; + +struct mailimap_msg_att_static * +mailimap_msg_att_static_new(int att_type, struct mailimap_envelope * att_env, + struct mailimap_date_time * att_internal_date, + char * att_rfc822, + char * att_rfc822_header, + char * att_rfc822_text, + size_t att_length, + uint32_t att_rfc822_size, + struct mailimap_body * att_bodystructure, + struct mailimap_body * att_body, + struct mailimap_msg_att_body_section * att_body_section, + uint32_t att_uid); + +void +mailimap_msg_att_static_free(struct mailimap_msg_att_static * item); + + + +/* this is the type of a response element */ + +enum { + MAILIMAP_RESP_ERROR, /* on parse error */ + MAILIMAP_RESP_CONT_REQ, /* continuation request */ + MAILIMAP_RESP_RESP_DATA, /* response data */ +}; + +/* + mailimap_cont_req_or_resp_data is a response element + + - type is the type of response, the value can be MAILIMAP_RESP_CONT_REQ + or MAILIMAP_RESP_RESP_DATA + + - cont_req is a continuation request + + - resp_data is a reponse data +*/ + +struct mailimap_cont_req_or_resp_data { + int rsp_type; + union { + struct mailimap_continue_req * rsp_cont_req; /* can be NULL */ + struct mailimap_response_data * rsp_resp_data; /* can be NULL */ + } rsp_data; +}; + +struct mailimap_cont_req_or_resp_data * +mailimap_cont_req_or_resp_data_new(int rsp_type, + struct mailimap_continue_req * rsp_cont_req, + struct mailimap_response_data * rsp_resp_data); + +void +mailimap_cont_req_or_resp_data_free(struct mailimap_cont_req_or_resp_data * + cont_req_or_resp_data); + + +/* + mailimap_response is a list of response elements + + - cont_req_or_resp_data_list is a list of response elements + + - resp_done is an ending response element +*/ + +struct mailimap_response { + clist * rsp_cont_req_or_resp_data_list; + /* list of (struct mailiap_cont_req_or_resp_data *) */ + /* can be NULL */ + struct mailimap_response_done * rsp_resp_done; /* != NULL */ +}; + +struct mailimap_response * +mailimap_response_new(clist * rsp_cont_req_or_resp_data_list, + struct mailimap_response_done * rsp_resp_done); + +void +mailimap_response_free(struct mailimap_response * resp); + + + +/* this is the type of an untagged response */ + +enum { + MAILIMAP_RESP_DATA_TYPE_ERROR, /* on parse error */ + MAILIMAP_RESP_DATA_TYPE_COND_STATE, /* condition state response */ + MAILIMAP_RESP_DATA_TYPE_COND_BYE, /* BYE response (server is about + to close the connection) */ + MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA, /* response related to a mailbox */ + MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA, /* response related to a message */ + MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA, /* capability information */ +}; + +/* + mailimap_reponse_data is an untagged response + + - type is the type of the untagged response, it can be + MAILIMAP_RESP_DATA_COND_STATE, MAILIMAP_RESP_DATA_COND_BYE, + MAILIMAP_RESP_DATA_MAILBOX_DATA, MAILIMAP_RESP_DATA_MESSAGE_DATA + or MAILIMAP_RESP_DATA_CAPABILITY_DATA + + - cond_state is a condition state response + + - bye is a BYE response (server is about to close the connection) + + - mailbox_data is a response related to a mailbox + + - message_data is a response related to a message + + - capability is information about capabilities +*/ + +struct mailimap_response_data { + int rsp_type; + union { + struct mailimap_resp_cond_state * rsp_cond_state; /* can be NULL */ + struct mailimap_resp_cond_bye * rsp_bye; /* can be NULL */ + struct mailimap_mailbox_data * rsp_mailbox_data; /* can be NULL */ + struct mailimap_message_data * rsp_message_data; /* can be NULL */ + struct mailimap_capability_data * rsp_capability_data; /* can be NULL */ + } rsp_data; +}; + +struct mailimap_response_data * +mailimap_response_data_new(int rsp_type, + struct mailimap_resp_cond_state * rsp_cond_state, + struct mailimap_resp_cond_bye * rsp_bye, + struct mailimap_mailbox_data * rsp_mailbox_data, + struct mailimap_message_data * rsp_message_data, + struct mailimap_capability_data * rsp_capability_data); + +void +mailimap_response_data_free(struct mailimap_response_data * resp_data); + + + +/* this is the type of an ending response */ + +enum { + MAILIMAP_RESP_DONE_TYPE_ERROR, /* on parse error */ + MAILIMAP_RESP_DONE_TYPE_TAGGED, /* tagged response */ + MAILIMAP_RESP_DONE_TYPE_FATAL, /* fatal error response */ +}; + +/* + mailimap_response_done is an ending response + + - type is the type of the ending response + + - tagged is a tagged response + + - fatal is a fatal error response +*/ + +struct mailimap_response_done { + int rsp_type; + union { + struct mailimap_response_tagged * rsp_tagged; /* can be NULL */ + struct mailimap_response_fatal * rsp_fatal; /* can be NULL */ + } rsp_data; +}; + +struct mailimap_response_done * +mailimap_response_done_new(int rsp_type, + struct mailimap_response_tagged * rsp_tagged, + struct mailimap_response_fatal * rsp_fatal); + +void mailimap_response_done_free(struct mailimap_response_done * + resp_done); + + +/* + mailimap_response_fatal is a fatal error response + + - bye is a BYE response text +*/ + +struct mailimap_response_fatal { + struct mailimap_resp_cond_bye * rsp_bye; /* != NULL */ +}; + +struct mailimap_response_fatal * +mailimap_response_fatal_new(struct mailimap_resp_cond_bye * rsp_bye); + +void mailimap_response_fatal_free(struct mailimap_response_fatal * resp_fatal); + + + +/* + mailimap_response_tagged is a tagged response + + - tag is the sent tag, should be allocated with malloc() + + - cond_state is a condition state response +*/ + +struct mailimap_response_tagged { + char * rsp_tag; /* != NULL */ + struct mailimap_resp_cond_state * rsp_cond_state; /* != NULL */ +}; + +struct mailimap_response_tagged * +mailimap_response_tagged_new(char * rsp_tag, + struct mailimap_resp_cond_state * rsp_cond_state); + +void +mailimap_response_tagged_free(struct mailimap_response_tagged * tagged); + + +/* this is the type of an authentication condition response */ + +enum { + MAILIMAP_RESP_COND_AUTH_ERROR, /* on parse error */ + MAILIMAP_RESP_COND_AUTH_OK, /* authentication is needed */ + MAILIMAP_RESP_COND_AUTH_PREAUTH, /* authentication is not needed */ +}; + +/* + mailimap_resp_cond_auth is an authentication condition response + + - type is the type of the authentication condition response, + the value can be MAILIMAP_RESP_COND_AUTH_OK or + MAILIMAP_RESP_COND_AUTH_PREAUTH + + - text is a text response +*/ + +struct mailimap_resp_cond_auth { + int rsp_type; + struct mailimap_resp_text * rsp_text; /* != NULL */ +}; + +struct mailimap_resp_cond_auth * +mailimap_resp_cond_auth_new(int rsp_type, + struct mailimap_resp_text * rsp_text); + +void +mailimap_resp_cond_auth_free(struct mailimap_resp_cond_auth * cond_auth); + + + +/* + mailimap_resp_cond_bye is a BYE response + + - text is a text response +*/ + +struct mailimap_resp_cond_bye { + struct mailimap_resp_text * rsp_text; /* != NULL */ +}; + +struct mailimap_resp_cond_bye * +mailimap_resp_cond_bye_new(struct mailimap_resp_text * rsp_text); + +void +mailimap_resp_cond_bye_free(struct mailimap_resp_cond_bye * cond_bye); + + + +/* this is the type of a condition state response */ + +enum { + MAILIMAP_RESP_COND_STATE_OK, + MAILIMAP_RESP_COND_STATE_NO, + MAILIMAP_RESP_COND_STATE_BAD +}; + +/* + mailimap_resp_cond_state is a condition state reponse + + - type is the type of the condition state response + + - text is a text response +*/ + +struct mailimap_resp_cond_state { + int rsp_type; + struct mailimap_resp_text * rsp_text; /* can be NULL */ +}; + +struct mailimap_resp_cond_state * +mailimap_resp_cond_state_new(int rsp_type, + struct mailimap_resp_text * rsp_text); + +void +mailimap_resp_cond_state_free(struct mailimap_resp_cond_state * cond_state); + + + +/* + mailimap_resp_text is a text response + + - resp_code is a response code + + - text is a human readable text, should be allocated with malloc() +*/ + +struct mailimap_resp_text { + struct mailimap_resp_text_code * rsp_code; /* can be NULL */ + char * rsp_text; /* can be NULL */ +}; + +struct mailimap_resp_text * +mailimap_resp_text_new(struct mailimap_resp_text_code * resp_code, + char * rsp_text); + +void mailimap_resp_text_free(struct mailimap_resp_text * resp_text); + + + +/* this is the type of the response code */ + +enum { + MAILIMAP_RESP_TEXT_CODE_ALERT, /* ALERT response */ + MAILIMAP_RESP_TEXT_CODE_BADCHARSET, /* BADCHARSET response */ + MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA, /* CAPABILITY response */ + MAILIMAP_RESP_TEXT_CODE_PARSE, /* PARSE response */ + MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS, /* PERMANENTFLAGS response */ + MAILIMAP_RESP_TEXT_CODE_READ_ONLY, /* READONLY response */ + MAILIMAP_RESP_TEXT_CODE_READ_WRITE, /* READWRITE response */ + MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, /* TRYCREATE response */ + MAILIMAP_RESP_TEXT_CODE_UIDNEXT, /* UIDNEXT response */ + MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, /* UIDVALIDITY response */ + MAILIMAP_RESP_TEXT_CODE_UNSEEN, /* UNSEEN response */ + MAILIMAP_RESP_TEXT_CODE_OTHER, /* other type of response */ +}; + +/* + mailimap_resp_text_code is a response code + + - type is the type of the response code, the value can be + MAILIMAP_RESP_TEXT_CODE_ALERT, MAILIMAP_RESP_TEXT_CODE_BADCHARSET, + MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA, MAILIMAP_RESP_TEXT_CODE_PARSE, + MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS, MAILIMAP_RESP_TEXT_CODE_READ_ONLY, + MAILIMAP_RESP_TEXT_CODE_READ_WRITE, MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, + MAILIMAP_RESP_TEXT_CODE_UIDNEXT, MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, + MAILIMAP_RESP_TEXT_CODE_UNSEEN or MAILIMAP_RESP_TEXT_CODE_OTHER + + - badcharset is a list of charsets if type + is MAILIMAP_RESP_TEXT_CODE_BADCHARSET, each element should be + allocated with malloc() + + - cap_data is a list of capabilities + + - perm_flags is a list of flags, this is the flags that can be changed + permanently on the messages of the mailbox. + + - uidnext is the next unique identifier of a message + + - uidvalidity is the unique identifier validity value + + - first_unseen is the number of the first message without the \Seen flag + + - atom is a keyword for an extension response code, should be allocated + with malloc() + + - atom_value is the data related with the extension response code, + should be allocated with malloc() +*/ + +struct mailimap_resp_text_code { + int rc_type; + union { + clist * rc_badcharset; /* list of astring (char *) */ + /* can be NULL */ + struct mailimap_capability_data * rc_cap_data; /* != NULL */ + clist * rc_perm_flags; /* list of (struct mailimap_flag_perm *) */ + /* can be NULL */ + uint32_t rc_uidnext; + uint32_t rc_uidvalidity; + uint32_t rc_first_unseen; + struct { + char * atom_name; /* can be NULL */ + char * atom_value; /* can be NULL */ + } rc_atom; + } rc_data; +}; + +struct mailimap_resp_text_code * +mailimap_resp_text_code_new(int rc_type, clist * rc_badcharset, + struct mailimap_capability_data * rc_cap_data, + clist * rc_perm_flags, + uint32_t rc_uidnext, uint32_t rc_uidvalidity, + uint32_t rc_first_unseen, char * rc_atom, char * rc_atom_value); + +void +mailimap_resp_text_code_free(struct mailimap_resp_text_code * resp_text_code); + + +/* + mailimap_section is a MIME part section identifier + + section_spec is the MIME section identifier +*/ + +struct mailimap_section { + struct mailimap_section_spec * sec_spec; /* can be NULL */ +}; + +struct mailimap_section * +mailimap_section_new(struct mailimap_section_spec * sec_spec); + +void mailimap_section_free(struct mailimap_section * section); + + +/* this is the type of the message/rfc822 part description */ + +enum { + MAILIMAP_SECTION_MSGTEXT_HEADER, /* header fields part of the + message */ + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, /* given header fields of the + message */ + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, /* header fields of the + message except the given */ + MAILIMAP_SECTION_MSGTEXT_TEXT, /* text part */ +}; + +/* + mailimap_section_msgtext is a message/rfc822 part description + + - type is the type of the content part and the value can be + MAILIMAP_SECTION_MSGTEXT_HEADER, MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT + or MAILIMAP_SECTION_MSGTEXT_TEXT + + - header_list is the list of headers when type is + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS or + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT +*/ + +struct mailimap_section_msgtext { + int sec_type; + struct mailimap_header_list * sec_header_list; /* can be NULL */ +}; + +struct mailimap_section_msgtext * +mailimap_section_msgtext_new(int sec_type, + struct mailimap_header_list * sec_header_list); + +void +mailimap_section_msgtext_free(struct mailimap_section_msgtext * msgtext); + + + +/* + mailimap_section_part is the MIME part location in a message + + - section_id is a list of number index of the sub-part in the mail structure, + each element should be allocated with malloc() + +*/ + +struct mailimap_section_part { + clist * sec_id; /* list of nz-number (uint32_t *) */ + /* != NULL */ +}; + +struct mailimap_section_part * +mailimap_section_part_new(clist * sec_id); + +void +mailimap_section_part_free(struct mailimap_section_part * section_part); + + + +/* this is the type of section specification */ + +enum { + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT, /* if requesting data of the root + MIME message/rfc822 part */ + MAILIMAP_SECTION_SPEC_SECTION_PART, /* location of the MIME part + in the message */ +}; + +/* + mailimap_section_spec is a section specification + + - type is the type of the section specification, the value can be + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT or + MAILIMAP_SECTION_SPEC_SECTION_PART + + - section_msgtext is a message/rfc822 part description if type is + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT + + - section_part is a body part location in the message if type is + MAILIMAP_SECTION_SPEC_SECTION_PART + + - section_text is a body part location for a given MIME part, + this can be NULL if the body of the part is requested (and not + the MIME header). +*/ + +struct mailimap_section_spec { + int sec_type; + union { + struct mailimap_section_msgtext * sec_msgtext; /* can be NULL */ + struct mailimap_section_part * sec_part; /* can be NULL */ + } sec_data; + struct mailimap_section_text * sec_text; /* can be NULL */ +}; + +struct mailimap_section_spec * +mailimap_section_spec_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext, + struct mailimap_section_part * sec_part, + struct mailimap_section_text * sec_text); + +void +mailimap_section_spec_free(struct mailimap_section_spec * section_spec); + + + +/* this is the type of body part location for a given MIME part */ + +enum { + MAILIMAP_SECTION_TEXT_ERROR, /* on parse error **/ + MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT, /* if the MIME type is + message/rfc822, headers or text + can be requested */ + MAILIMAP_SECTION_TEXT_MIME, /* for all MIME types, + MIME headers can be requested */ +}; + +/* + mailimap_section_text is the body part location for a given MIME part + + - type can be MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT or + MAILIMAP_SECTION_TEXT_MIME + + - section_msgtext is the part of the MIME part when MIME type is + message/rfc822 than can be requested, when type is + MAILIMAP_TEXT_SECTION_MSGTEXT +*/ + +struct mailimap_section_text { + int sec_type; + struct mailimap_section_msgtext * sec_msgtext; /* can be NULL */ +}; + +struct mailimap_section_text * +mailimap_section_text_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext); + +void +mailimap_section_text_free(struct mailimap_section_text * section_text); + + + + + + + + + + +/* ************************************************************************* */ +/* the following part concerns only the IMAP command that are sent */ + + +/* + mailimap_set_item is a message set + + - first is the first message of the set + - last is the last message of the set + + this can be message numbers of message unique identifiers +*/ + +struct mailimap_set_item { + uint32_t set_first; + uint32_t set_last; +}; + +struct mailimap_set_item * +mailimap_set_item_new(uint32_t set_first, uint32_t set_last); + +void mailimap_set_item_free(struct mailimap_set_item * set_item); + + + +/* + set is a list of message sets + + - list is a list of message sets +*/ + +struct mailimap_set { + clist * set_list; /* list of (struct mailimap_set_item *) */ +}; + +struct mailimap_set * mailimap_set_new(clist * list); + +void mailimap_set_free(struct mailimap_set * set); + + +/* + mailimap_date is a date + + - day is the day in the month (1 to 31) + + - month (1 to 12) + + - year (4 digits) +*/ + +struct mailimap_date { + int dt_day; + int dt_month; + int dt_year; +}; + +struct mailimap_date * +mailimap_date_new(int dt_day, int dt_month, int dt_year); + +void mailimap_date_free(struct mailimap_date * date); + + + + +/* this is the type of fetch attribute for a given message */ + +enum { + MAILIMAP_FETCH_ATT_ENVELOPE, /* to fetch the headers parsed by + the IMAP server */ + MAILIMAP_FETCH_ATT_FLAGS, /* to fetch the flags */ + MAILIMAP_FETCH_ATT_INTERNALDATE, /* to fetch the date of the message + kept by the server */ + MAILIMAP_FETCH_ATT_RFC822, /* to fetch the entire message */ + MAILIMAP_FETCH_ATT_RFC822_HEADER, /* to fetch the headers */ + MAILIMAP_FETCH_ATT_RFC822_SIZE, /* to fetch the size */ + MAILIMAP_FETCH_ATT_RFC822_TEXT, /* to fetch the text part */ + MAILIMAP_FETCH_ATT_BODY, /* to fetch the MIME structure */ + MAILIMAP_FETCH_ATT_BODYSTRUCTURE, /* to fetch the MIME structure with + additional information */ + MAILIMAP_FETCH_ATT_UID, /* to fetch the unique identifier */ + MAILIMAP_FETCH_ATT_BODY_SECTION, /* to fetch a given part */ + MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, /* to fetch a given part without + marking the message as read */ +}; + + +/* + mailimap_fetch_att is the description of the fetch attribute + + - type is the type of fetch attribute, the value can be + MAILIMAP_FETCH_ATT_ENVELOPE, MAILIMAP_FETCH_ATT_FLAGS, + MAILIMAP_FETCH_ATT_INTERNALDATE, MAILIMAP_FETCH_ATT_RFC822, + MAILIMAP_FETCH_ATT_RFC822_HEADER, MAILIMAP_FETCH_ATT_RFC822_SIZE, + MAILIMAP_FETCH_ATT_RFC822_TEXT, MAILIMAP_FETCH_ATT_BODY, + MAILIMAP_FETCH_ATT_BODYSTRUCTURE, MAILIMAP_FETCH_ATT_UID, + MAILIMAP_FETCH_ATT_BODY_SECTION or MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION + + - section is the location of the part to fetch if type is + MAILIMAP_FETCH_ATT_BODY_SECTION or MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION + + - offset is the first byte to fetch in the given part + + - size is the maximum size of the part to fetch +*/ + +struct mailimap_fetch_att { + int att_type; + struct mailimap_section * att_section; + uint32_t att_offset; + uint32_t att_size; +}; + +struct mailimap_fetch_att * +mailimap_fetch_att_new(int att_type, struct mailimap_section * att_section, + uint32_t att_offset, uint32_t att_size); + + +void mailimap_fetch_att_free(struct mailimap_fetch_att * fetch_att); + + +/* this is the type of a FETCH operation */ + +enum { + MAILIMAP_FETCH_TYPE_ALL, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE ENVELOPE) */ + MAILIMAP_FETCH_TYPE_FULL, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE ENVELOPE BODY) */ + MAILIMAP_FETCH_TYPE_FAST, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE) */ + MAILIMAP_FETCH_TYPE_FETCH_ATT, /* when there is only of fetch + attribute */ + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST, /* when there is a list of fetch + attributes */ +}; + +/* + mailimap_fetch_type is the description of the FETCH operation + + - type can be MAILIMAP_FETCH_TYPE_ALL, MAILIMAP_FETCH_TYPE_FULL, + MAILIMAP_FETCH_TYPE_FAST, MAILIMAP_FETCH_TYPE_FETCH_ATT or + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST + + - fetch_att is a fetch attribute if type is MAILIMAP_FETCH_TYPE_FETCH_ATT + + - fetch_att_list is a list of fetch attributes if type is + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST +*/ + +struct mailimap_fetch_type { + int ft_type; + union { + struct mailimap_fetch_att * ft_fetch_att; + clist * ft_fetch_att_list; /* list of (struct mailimap_fetch_att *) */ + } ft_data; +}; + +struct mailimap_fetch_type * +mailimap_fetch_type_new(int ft_type, + struct mailimap_fetch_att * ft_fetch_att, + clist * ft_fetch_att_list); + + +void mailimap_fetch_type_free(struct mailimap_fetch_type * fetch_type); + + + +/* + mailimap_store_att_flags is the description of the STORE operation + (change flags of a message) + + - sign can be 0 (set flag), +1 (add flag) or -1 (remove flag) + + - silent has a value of 1 if the flags are changed with no server + response + + - flag_list is the list of flags to change +*/ + +struct mailimap_store_att_flags { + int fl_sign; + int fl_silent; + struct mailimap_flag_list * fl_flag_list; +}; + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new(int fl_sign, int fl_silent, + struct mailimap_flag_list * fl_flag_list); + +void mailimap_store_att_flags_free(struct mailimap_store_att_flags * + store_att_flags); + + + +/* this is the condition of the SEARCH operation */ + +enum { + MAILIMAP_SEARCH_KEY_ALL, /* all messages */ + MAILIMAP_SEARCH_KEY_ANSWERED, /* messages with the flag \Answered */ + MAILIMAP_SEARCH_KEY_BCC, /* messages whose Bcc field contains the + given string */ + MAILIMAP_SEARCH_KEY_BEFORE, /* messages whose internal date is earlier + than the specified date */ + MAILIMAP_SEARCH_KEY_BODY, /* message that contains the given string + (in header and text parts) */ + MAILIMAP_SEARCH_KEY_CC, /* messages whose Cc field contains the + given string */ + MAILIMAP_SEARCH_KEY_DELETED, /* messages with the flag \Deleted */ + MAILIMAP_SEARCH_KEY_FLAGGED, /* messages with the flag \Flagged */ + MAILIMAP_SEARCH_KEY_FROM, /* messages whose From field contains the + given string */ + MAILIMAP_SEARCH_KEY_KEYWORD, /* messages with the flag keyword set */ + MAILIMAP_SEARCH_KEY_NEW, /* messages with the flag \Recent and not + the \Seen flag */ + MAILIMAP_SEARCH_KEY_OLD, /* messages that do not have the + \Recent flag set */ + MAILIMAP_SEARCH_KEY_ON, /* messages whose internal date is the + specified date */ + MAILIMAP_SEARCH_KEY_RECENT, /* messages with the flag \Recent */ + MAILIMAP_SEARCH_KEY_SEEN, /* messages with the flag \Seen */ + MAILIMAP_SEARCH_KEY_SINCE, /* messages whose internal date is later + than specified date */ + MAILIMAP_SEARCH_KEY_SUBJECT, /* messages whose Subject field contains the + given string */ + MAILIMAP_SEARCH_KEY_TEXT, /* messages whose text part contains the + given string */ + MAILIMAP_SEARCH_KEY_TO, /* messages whose To field contains the + given string */ + MAILIMAP_SEARCH_KEY_UNANSWERED, /* messages with no flag \Answered */ + MAILIMAP_SEARCH_KEY_UNDELETED, /* messages with no flag \Deleted */ + MAILIMAP_SEARCH_KEY_UNFLAGGED, /* messages with no flag \Flagged */ + MAILIMAP_SEARCH_KEY_UNKEYWORD, /* messages with no flag keyword */ + MAILIMAP_SEARCH_KEY_UNSEEN, /* messages with no flag \Seen */ + MAILIMAP_SEARCH_KEY_DRAFT, /* messages with no flag \Draft */ + MAILIMAP_SEARCH_KEY_HEADER, /* messages whose given field + contains the given string */ + MAILIMAP_SEARCH_KEY_LARGER, /* messages whose size is larger then + the given size */ + MAILIMAP_SEARCH_KEY_NOT, /* not operation of the condition */ + MAILIMAP_SEARCH_KEY_OR, /* or operation between two conditions */ + MAILIMAP_SEARCH_KEY_SENTBEFORE, /* messages whose date given in Date header + is earlier than the specified date */ + MAILIMAP_SEARCH_KEY_SENTON, /* messages whose date given in Date header + is the specified date */ + MAILIMAP_SEARCH_KEY_SENTSINCE, /* messages whose date given in Date header + is later than specified date */ + MAILIMAP_SEARCH_KEY_SMALLER, /* messages whose size is smaller than + the given size */ + MAILIMAP_SEARCH_KEY_UID, /* messages whose unique identifiers are + in the given range */ + MAILIMAP_SEARCH_KEY_UNDRAFT, /* messages with no flag \Draft */ + MAILIMAP_SEARCH_KEY_SET, /* messages whose number (or unique + identifiers in case of UID SEARCH) are + in the given range */ + MAILIMAP_SEARCH_KEY_MULTIPLE, /* the boolean operator between the + conditions is AND */ +}; + +/* + mailimap_search_key is the condition on the messages to return + + - type is the type of the condition + + - bcc is the text to search in the Bcc field when type is + MAILIMAP_SEARCH_KEY_BCC, should be allocated with malloc() + + - before is a date when type is MAILIMAP_SEARCH_KEY_BEFORE + + - body is the text to search in the message when type is + MAILIMAP_SEARCH_KEY_BODY, should be allocated with malloc() + + - cc is the text to search in the Cc field when type is + MAILIMAP_SEARCH_KEY_CC, should be allocated with malloc() + + - from is the text to search in the From field when type is + MAILIMAP_SEARCH_KEY_FROM, should be allocated with malloc() + + - keyword is the keyword flag name when type is MAILIMAP_SEARCH_KEY_KEYWORD, + should be allocated with malloc() + + - on is a date when type is MAILIMAP_SEARCH_KEY_ON + + - since is a date when type is MAILIMAP_SEARCH_KEY_SINCE + + - subject is the text to search in the Subject field when type is + MAILIMAP_SEARCH_KEY_SUBJECT, should be allocated with malloc() + + - text is the text to search in the text part of the message when + type is MAILIMAP_SEARCH_KEY_TEXT, should be allocated with malloc() + + - to is the text to search in the To field when type is + MAILIMAP_SEARCH_KEY_TO, should be allocated with malloc() + + - unkeyword is the keyword flag name when type is + MAILIMAP_SEARCH_KEY_UNKEYWORD, should be allocated with malloc() + + - header_name is the header name when type is MAILIMAP_SEARCH_KEY_HEADER, + should be allocated with malloc() + + - header_value is the text to search in the given header when type is + MAILIMAP_SEARCH_KEY_HEADER, should be allocated with malloc() + + - larger is a size when type is MAILIMAP_SEARCH_KEY_LARGER + + - not is a condition when type is MAILIMAP_SEARCH_KEY_NOT + + - or1 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - or2 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - sentbefore is a date when type is MAILIMAP_SEARCH_KEY_SENTBEFORE + + - senton is a date when type is MAILIMAP_SEARCH_KEY_SENTON + + - sentsince is a date when type is MAILIMAP_SEARCH_KEY_SENTSINCE + + - smaller is a size when type is MAILIMAP_SEARCH_KEY_SMALLER + + - uid is a set of messages when type is MAILIMAP_SEARCH_KEY_UID + + - set is a set of messages when type is MAILIMAP_SEARCH_KEY_SET + + - multiple is a set of message when type is MAILIMAP_SEARCH_KEY_MULTIPLE +*/ + +struct mailimap_search_key { + int sk_type; + union { + char * sk_bcc; + struct mailimap_date * sk_before; + char * sk_body; + char * sk_cc; + char * sk_from; + char * sk_keyword; + struct mailimap_date * sk_on; + struct mailimap_date * sk_since; + char * sk_subject; + char * sk_text; + char * sk_to; + char * sk_unkeyword; + struct { + char * sk_header_name; + char * sk_header_value; + } sk_header; + uint32_t sk_larger; + struct mailimap_search_key * sk_not; + struct { + struct mailimap_search_key * sk_or1; + struct mailimap_search_key * sk_or2; + } sk_or; + struct mailimap_date * sk_sentbefore; + struct mailimap_date * sk_senton; + struct mailimap_date * sk_sentsince; + uint32_t sk_smaller; + struct mailimap_set * sk_uid; + struct mailimap_set * sk_set; + clist * sk_multiple; /* list of (struct mailimap_search_key *) */ + } sk_data; +}; + +struct mailimap_search_key * +mailimap_search_key_new(int sk_type, + char * sk_bcc, struct mailimap_date * sk_before, char * sk_body, + char * sk_cc, char * sk_from, char * sk_keyword, + struct mailimap_date * sk_on, struct mailimap_date * sk_since, + char * sk_subject, char * sk_text, char * sk_to, + char * sk_unkeyword, char * sk_header_name, + char * sk_header_value, uint32_t sk_larger, + struct mailimap_search_key * sk_not, + struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2, + struct mailimap_date * sk_sentbefore, + struct mailimap_date * sk_senton, + struct mailimap_date * sk_sentsince, + uint32_t sk_smaller, struct mailimap_set * sk_uid, + struct mailimap_set * sk_set, clist * sk_multiple); + + +void mailimap_search_key_free(struct mailimap_search_key * key); + + +/* + mailimap_status_att_list is a list of mailbox STATUS request type + + - list is a list of mailbox STATUS request type + (value of elements in the list can be MAILIMAP_STATUS_ATT_MESSAGES, + MAILIMAP_STATUS_ATT_RECENT, MAILIMAP_STATUS_ATT_UIDNEXT, + MAILIMAP_STATUS_ATT_UIDVALIDITY or MAILIMAP_STATUS_ATT_UNSEEN), + each element should be allocated with malloc() +*/ + +struct mailimap_status_att_list { + clist * att_list; /* list of (uint32_t *) */ +}; + +struct mailimap_status_att_list * +mailimap_status_att_list_new(clist * att_list); + +void mailimap_status_att_list_free(struct mailimap_status_att_list * + status_att_list); + + + + +/* internal use functions */ + + +uint32_t * mailimap_number_alloc_new(uint32_t number); + +void mailimap_number_alloc_free(uint32_t * pnumber); + + +void mailimap_addr_host_free(char * addr_host); + +void mailimap_addr_mailbox_free(char * addr_mailbox); + +void mailimap_addr_adl_free(char * addr_adl); + +void mailimap_addr_name_free(char * addr_name); + +void mailimap_astring_free(char * astring); + +void mailimap_atom_free(char * atom); + +void mailimap_auth_type_free(char * auth_type); + +void mailimap_base64_free(char * base64); + +void mailimap_body_fld_desc_free(char * body_fld_desc); + +void mailimap_body_fld_id_free(char * body_fld_id); + +void mailimap_body_fld_md5_free(char * body_fld_md5); + +void mailimap_env_date_free(char * date); + +void mailimap_env_in_reply_to_free(char * in_reply_to); + +void mailimap_env_message_id_free(char * message_id); + +void mailimap_env_subject_free(char * subject); + +void mailimap_flag_extension_free(char * flag_extension); + +void mailimap_flag_keyword_free(char * flag_keyword); + +void +mailimap_header_fld_name_free(char * header_fld_name); + +void mailimap_literal_free(char * literal); + +void mailimap_mailbox_free(char * mailbox); + +void +mailimap_mailbox_data_search_free(clist * data_search); + +void mailimap_media_subtype_free(char * media_subtype); + +void mailimap_media_text_free(char * media_text); + +void mailimap_msg_att_envelope_free(struct mailimap_envelope * env); + +void +mailimap_msg_att_internaldate_free(struct mailimap_date_time * date_time); + +void +mailimap_msg_att_rfc822_free(char * str); + +void +mailimap_msg_att_rfc822_header_free(char * str); + +void +mailimap_msg_att_rfc822_text_free(char * str); + +void +mailimap_msg_att_body_free(struct mailimap_body * body); + +void +mailimap_msg_att_bodystructure_free(struct mailimap_body * body); + +void mailimap_nstring_free(char * str); + +void +mailimap_string_free(char * str); + +void mailimap_tag_free(char * tag); + +void mailimap_text_free(char * text); + + + + + +/* IMAP connection */ + +/* this is the state of the IMAP connection */ + +enum { + MAILIMAP_STATE_DISCONNECTED, + MAILIMAP_STATE_NON_AUTHENTICATED, + MAILIMAP_STATE_AUTHENTICATED, + MAILIMAP_STATE_SELECTED, + MAILIMAP_STATE_LOGOUT +}; + +/* + mailimap is an IMAP connection + + - response is a human readable message returned with a reponse, + must be accessed read-only + + - stream is the connection with the IMAP server + + - stream_buffer is the buffer where the data to parse are stored + + - state is the state of IMAP connection + + - tag is the current tag being used in IMAP connection + + - response_buffer is the buffer for response messages + + - connection_info is the information returned in response + for the last command about the connection + + - selection_info is the information returned in response + for the last command about the current selected mailbox + + - response_info is the other information returned in response + for the last command +*/ + +struct mailimap { + char * imap_response; + + /* internals */ + mailstream * imap_stream; + + size_t imap_progr_rate; + progress_function * imap_progr_fun; + + MMAPString * imap_stream_buffer; + MMAPString * imap_response_buffer; + + int imap_state; + int imap_tag; + + struct mailimap_connection_info * imap_connection_info; + struct mailimap_selection_info * imap_selection_info; + struct mailimap_response_info * imap_response_info; +}; + +typedef struct mailimap mailimap; + + +/* + mailimap_connection_info is the information about the connection + + - capability is the list of capability of the IMAP server +*/ + +struct mailimap_connection_info { + struct mailimap_capability_data * imap_capability; +}; + +struct mailimap_connection_info * +mailimap_connection_info_new(void); + +void +mailimap_connection_info_free(struct mailimap_connection_info * conn_info); + + +/* this is the type of mailbox access */ + +enum { + MAILIMAP_MAILBOX_READONLY, + MAILIMAP_MAILBOX_READWRITE +}; + +/* + mailimap_selection_info is information about the current selected mailbox + + - perm_flags is a list of flags that can be changed permanently on the + messages of the mailbox + + - perm is the access on the mailbox, value can be + MAILIMAP_MAILBOX_READONLY or MAILIMAP_MAILBOX_READWRITE + + - uidnext is the next unique identifier + + - uidvalidity is the unique identifiers validity + + - first_unseen is the number of the first unseen message + + - flags is a list of flags that can be used on the messages of + the mailbox + + - exists is the number of messages in the mailbox + + - recent is the number of recent messages in the mailbox + + - unseen is the number of unseen messages in the mailbox +*/ + +struct mailimap_selection_info { + clist * sel_perm_flags; /* list of (struct flag_perm *) */ + int sel_perm; + uint32_t sel_uidnext; + uint32_t sel_uidvalidity; + uint32_t sel_first_unseen; + struct mailimap_flag_list * sel_flags; + uint32_t sel_exists; + uint32_t sel_recent; + uint32_t sel_unseen; +}; + +struct mailimap_selection_info * +mailimap_selection_info_new(void); + +void +mailimap_selection_info_free(struct mailimap_selection_info * sel_info); + + +/* + mailimap_response_info is the other information returned in the + response for a command + + - alert is the human readable text returned with ALERT response + + - parse is the human readable text returned with PARSE response + + - badcharset is a list of charset returned with a BADCHARSET response + + - trycreate is set to 1 if a trycreate response was returned + + - mailbox_list is a list of mailboxes + + - mailbox_lsub is a list of subscribed mailboxes + + - search_result is a list of message numbers or unique identifiers + + - status is a STATUS response + + - expunged is a list of message numbers + + - fetch_list is a list of fetch response +*/ + +struct mailimap_response_info { + char * rsp_alert; + char * rsp_parse; + clist * rsp_badcharset; /* list of (char *) */ + int rsp_trycreate; + clist * rsp_mailbox_list; /* list of (struct mailimap_mailbox_list *) */ + clist * rsp_mailbox_lsub; /* list of (struct mailimap_mailbox_list *) */ + clist * rsp_search_result; /* list of (uint32_t *) */ + struct mailimap_mailbox_data_status * rsp_status; + clist * rsp_expunged; /* list of (uint32_t 32 *) */ + clist * rsp_fetch_list; /* list of (struct mailimap_msg_att *) */ +}; + +struct mailimap_response_info * +mailimap_response_info_new(void); + +void +mailimap_response_info_free(struct mailimap_response_info * resp_info); + + +/* these are the possible returned error codes */ + +enum { + MAILIMAP_NO_ERROR = 0, + MAILIMAP_NO_ERROR_AUTHENTICATED = 1, + MAILIMAP_NO_ERROR_NON_AUTHENTICATED = 2, + MAILIMAP_ERROR_BAD_STATE, + MAILIMAP_ERROR_STREAM, + MAILIMAP_ERROR_PARSE, + MAILIMAP_ERROR_CONNECTION_REFUSED, + MAILIMAP_ERROR_MEMORY, + MAILIMAP_ERROR_FATAL, + MAILIMAP_ERROR_PROTOCOL, + MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION, + MAILIMAP_ERROR_APPEND, + MAILIMAP_ERROR_NOOP, + MAILIMAP_ERROR_LOGOUT, + MAILIMAP_ERROR_CAPABILITY, + MAILIMAP_ERROR_CHECK, + MAILIMAP_ERROR_CLOSE, + MAILIMAP_ERROR_EXPUNGE, + MAILIMAP_ERROR_COPY, + MAILIMAP_ERROR_UID_COPY, + MAILIMAP_ERROR_CREATE, + MAILIMAP_ERROR_DELETE, + MAILIMAP_ERROR_EXAMINE, + MAILIMAP_ERROR_FETCH, + MAILIMAP_ERROR_UID_FETCH, + MAILIMAP_ERROR_LIST, + MAILIMAP_ERROR_LOGIN, + MAILIMAP_ERROR_LSUB, + MAILIMAP_ERROR_RENAME, + MAILIMAP_ERROR_SEARCH, + MAILIMAP_ERROR_UID_SEARCH, + MAILIMAP_ERROR_SELECT, + MAILIMAP_ERROR_STATUS, + MAILIMAP_ERROR_STORE, + MAILIMAP_ERROR_UID_STORE, + MAILIMAP_ERROR_SUBSCRIBE, + MAILIMAP_ERROR_UNSUBSCRIBE, + MAILIMAP_ERROR_STARTTLS, + MAILIMAP_ERROR_INVAL, +}; + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/kmicromail/libetpan/imap/mailimap_types_helper.c b/kmicromail/libetpan/imap/mailimap_types_helper.c new file mode 100644 index 0000000..8fe273e --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_types_helper.c @@ -0,0 +1,1269 @@ +/* + * 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 "mailimap_types.h" +#include "mail.h" + +#include <stdlib.h> + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +/* in helper */ + + + + +struct mailimap_set_item * mailimap_set_item_new_single(uint32_t index) +{ + return mailimap_set_item_new(index, index); +} + +struct mailimap_set * +mailimap_set_new_single_item(struct mailimap_set_item * item) +{ + struct mailimap_set * set; + clist * list; + int r; + + list = clist_new(); + if (list == NULL) + return NULL; + + r = clist_append(list, item); + if (r < 0) { + clist_free(list); + return NULL; + } + + set = mailimap_set_new(list); + if (set == NULL) { + clist_free(list); + return NULL; + } + + return set; +} + +struct mailimap_set * mailimap_set_new_interval(uint32_t first, uint32_t last) +{ + struct mailimap_set_item * item; + struct mailimap_set * set; + + item = mailimap_set_item_new(first, last); + if (item == NULL) + return NULL; + + set = mailimap_set_new_single_item(item); + if (set == NULL) { + mailimap_set_item_free(item); + return NULL; + } + + return set; +} + +struct mailimap_set * mailimap_set_new_single(uint32_t index) +{ + return mailimap_set_new_interval(index, index); +} + + +struct mailimap_set * mailimap_set_new_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_set_new(list); +} + +int mailimap_set_add(struct mailimap_set * set, + struct mailimap_set_item * set_item) +{ + int r; + + r = clist_append(set->set_list, set_item); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_set_add_interval(struct mailimap_set * set, + uint32_t first, uint32_t last) +{ + struct mailimap_set_item * item; + int r; + + item = mailimap_set_item_new(first, last); + if (item == NULL) + return MAILIMAP_ERROR_MEMORY; + + r = mailimap_set_add(set, item); + if (r != MAILIMAP_NO_ERROR) { + mailimap_set_item_free(item); + return r; + } + else + return MAILIMAP_NO_ERROR; +} + +int mailimap_set_add_single(struct mailimap_set * set, + uint32_t index) +{ + return mailimap_set_add_interval(set, index, index); +} + +/* CHECK */ +/* no args */ + +/* CLOSE */ +/* no args */ + +/* EXPUNGE */ +/* no args */ + +/* COPY */ +/* set and gchar */ + +/* FETCH */ +/* set and gchar fetch_type */ + + + +/* section */ + +#if 0 +/* not correct XXX */ + +struct mailimap_section * mailimap_section_new_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_section_new(list); +} +#endif + +static struct mailimap_section * +mailimap_section_new_msgtext(struct mailimap_section_msgtext * msgtext) +{ + struct mailimap_section_spec * spec; + struct mailimap_section * section; + + spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT, + msgtext, NULL, NULL); + if (spec == NULL) + return NULL; + + section = mailimap_section_new(spec); + if (section == NULL) { + /* detach section_msgtext so that it will not be freed */ + spec->sec_data.sec_msgtext = NULL; + mailimap_section_spec_free(spec); + return NULL; + } + + return section; +} + +static struct mailimap_section * +mailimap_section_new_part_msgtext(struct mailimap_section_part * part, + struct mailimap_section_msgtext * msgtext) +{ + struct mailimap_section_spec * spec; + struct mailimap_section * section; + struct mailimap_section_text * text; + + text = mailimap_section_text_new(MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT, + msgtext); + if (text == NULL) + return NULL; + + spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART, + NULL, part, text); + if (spec == NULL) { + /* detach section_msgtext so that it will not be freed */ + text->sec_msgtext = NULL; + mailimap_section_text_free(text); + return NULL; + } + + section = mailimap_section_new(spec); + if (section == NULL) { + /* detach section_msgtext so that it will not be freed */ + text->sec_msgtext = NULL; + mailimap_section_spec_free(spec); + return NULL; + } + + return section; +} + +/* +HEADER +HEADER.FIELDS fields +HEADER.FIELDS.NOT fields +TEXT +*/ + +struct mailimap_section * mailimap_section_new_header(void) +{ + struct mailimap_section_msgtext * msgtext; + struct mailimap_section * section; + + msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER, + NULL); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_msgtext(msgtext); + if (section == NULL) { + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_header_fields(struct mailimap_header_list * header_list) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = + mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, + header_list); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_msgtext(msgtext); + if (section == NULL) { + /* detach header_list so that it will not be freed */ + msgtext->sec_header_list = NULL; + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_header_fields_not(struct mailimap_header_list * header_list) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = + mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, + header_list); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_msgtext(msgtext); + if (section == NULL) { + /* detach header_list so that it will not be freed */ + msgtext->sec_header_list = NULL; + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * mailimap_section_new_text(void) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_TEXT, NULL); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_msgtext(msgtext); + if (section == NULL) { + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +/* +section-part +section-part . MIME +section-part . HEADER +section-part . HEADER.FIELDS fields +section-part . HEADER.FIELDS.NOT fields +section-part . TEXT +*/ + +struct mailimap_section * +mailimap_section_new_part(struct mailimap_section_part * part) +{ + struct mailimap_section_spec * spec; + struct mailimap_section * section; + + spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART, + NULL, part, NULL); + if (spec == NULL) + return NULL; + + section = mailimap_section_new(spec); + if (section == NULL) { + /* detach section_part so that it will not be freed */ + spec->sec_data.sec_part = NULL; + mailimap_section_spec_free(spec); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_part_mime(struct mailimap_section_part * part) +{ + struct mailimap_section_spec * spec; + struct mailimap_section * section; + struct mailimap_section_text * text; + + text = mailimap_section_text_new(MAILIMAP_SECTION_TEXT_MIME, NULL); + if (text == NULL) + return NULL; + + spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART, + NULL, part, text); + if (spec == NULL) { + mailimap_section_text_free(text); + return NULL; + } + + section = mailimap_section_new(spec); + if (section == NULL) { + /* detach section_part so that it will not be freed */ + spec->sec_data.sec_part = NULL; + mailimap_section_spec_free(spec); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_part_header(struct mailimap_section_part * part) +{ + struct mailimap_section_msgtext * msgtext; + struct mailimap_section * section; + + msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER, + NULL); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_part_msgtext(part, msgtext); + if (section == NULL) { + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_part_header_fields(struct mailimap_section_part * + part, + struct mailimap_header_list * + header_list) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = + mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, + header_list); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_part_msgtext(part, msgtext); + if (section == NULL) { + /* detach header_list so that it will not be freed */ + msgtext->sec_header_list = NULL; + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_part_header_fields_not(struct mailimap_section_part + * part, + struct mailimap_header_list + * header_list) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = + mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, + header_list); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_part_msgtext(part, msgtext); + if (section == NULL) { + /* detach header_list so that it will not be freed */ + msgtext->sec_header_list = NULL; + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_part_text(struct mailimap_section_part * part) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_TEXT, NULL); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_part_msgtext(part, msgtext); + if (section == NULL) { + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +/* end of section */ + + + + + + +struct mailimap_fetch_att * +mailimap_fetch_att_new_envelope(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_ENVELOPE, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_flags(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_FLAGS, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_internaldate(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_INTERNALDATE, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_header(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822_HEADER, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_size(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822_SIZE, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_text(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822_TEXT, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_bodystructure(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODYSTRUCTURE, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_uid(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_UID, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section(struct mailimap_section * section) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_SECTION, section, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section(struct mailimap_section * section) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, section, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_SECTION, section, + offset, size); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, section, + offset, size); +} + + + +struct mailimap_fetch_type * +mailimap_fetch_type_new_all(void) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_ALL, NULL, NULL); +} + +struct mailimap_fetch_type * +mailimap_fetch_type_new_full(void) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FULL, NULL, NULL); +} + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fast(void) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FAST, NULL, NULL); +} + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att(struct mailimap_fetch_att * fetch_att) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FETCH_ATT, fetch_att, NULL); +} + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list(clist * fetch_att_list) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST, + NULL, fetch_att_list); +} + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST, + NULL, list); +} + +int +mailimap_fetch_type_new_fetch_att_list_add(struct mailimap_fetch_type * + fetch_type, + struct mailimap_fetch_att * fetch_att) +{ + int r; + + r = clist_append(fetch_type->ft_data.ft_fetch_att_list, fetch_att); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + + + +/* STORE */ +/* set and store_att_flags */ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags(struct mailimap_flag_list * flags) +{ + return mailimap_store_att_flags_new(0, FALSE, flags); +} + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags_silent(struct mailimap_flag_list * + flags) +{ + return mailimap_store_att_flags_new(0, TRUE, flags); +} + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags(struct mailimap_flag_list * flags) +{ + return mailimap_store_att_flags_new(1, FALSE, flags); +} + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags_silent(struct mailimap_flag_list * + flags) +{ + return mailimap_store_att_flags_new(1, TRUE, flags); +} + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags(struct mailimap_flag_list * flags) +{ + return mailimap_store_att_flags_new(-1, FALSE, flags); +} + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags_silent(struct mailimap_flag_list * + flags) +{ + return mailimap_store_att_flags_new(-1, TRUE, flags); +} + +/* SEARCH */ +/* date search-key set */ + +/* + return mailimap_search_key_new(type, bcc, before, + body, cc, from, keyword, on, since, + subject, text, to, unkeyword, header_name, + header_value, larger, not, + or1, or2, sentbefore, senton, sentsince, + smaller, uid, set, multiple); +*/ + +struct mailimap_search_key * +mailimap_search_key_new_all(void) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_ALL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_bcc(char * sk_bcc) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_BCC, sk_bcc, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_before(struct mailimap_date * sk_before) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_BEFORE, NULL, sk_before, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_body(char * sk_body) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_BODY, NULL, NULL, + sk_body, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_cc(char * sk_cc) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_CC, NULL, NULL, + NULL, sk_cc, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_from(char * sk_from) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_FROM, NULL, NULL, + NULL, NULL, sk_from, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_keyword(char * sk_keyword) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_FROM, NULL, NULL, + NULL, NULL, NULL, sk_keyword, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_on(struct mailimap_date * sk_on) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_ON, NULL, NULL, + NULL, NULL, NULL, NULL, sk_on, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_since(struct mailimap_date * sk_since) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SINCE, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, sk_since, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_subject(char * sk_subject) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SINCE, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + sk_subject, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_text(char * sk_text) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_TEXT, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, sk_text, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_to(char * sk_to) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_TO, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, sk_to, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_unkeyword(char * sk_unkeyword) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNKEYWORD, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, sk_unkeyword, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_header(char * sk_header_name, char * sk_header_value) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_HEADER, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, sk_header_name, + sk_header_value, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_larger(uint32_t sk_larger) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_LARGER, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, sk_larger, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_not(struct mailimap_search_key * sk_not) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_NOT, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, sk_not, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_or(struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_OR, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + sk_or1, sk_or2, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_sentbefore(struct mailimap_date * sk_sentbefore) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_NOT, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, sk_sentbefore, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_senton(struct mailimap_date * sk_senton) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SENTON, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, sk_senton, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_sentsince(struct mailimap_date * sk_sentsince) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SENTSINCE, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, sk_sentsince, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_smaller(uint32_t sk_smaller) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SMALLER, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + sk_smaller, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_uid(struct mailimap_set * sk_uid) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UID, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, sk_uid, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_set(struct mailimap_set * sk_set) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SET, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, sk_set, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_multiple(clist * sk_multiple) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_MULTIPLE, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, sk_multiple); +} + +struct mailimap_search_key * +mailimap_search_key_new_multiple_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_search_key_new_multiple(list); +} + +int +mailimap_search_key_multiple_add(struct mailimap_search_key * keys, + struct mailimap_search_key * key_item) +{ + int r; + + r = clist_append(keys->sk_data.sk_multiple, key_item); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + + + +/* CAPABILITY */ +/* no args */ + +/* LOGOUT */ +/* no args */ + +/* NOOP */ +/* no args */ + +/* APPEND */ +/* gchar flag_list date_time gchar */ + +struct mailimap_flag_list * +mailimap_flag_list_new_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_flag_list_new(list); +} + +int mailimap_flag_list_add(struct mailimap_flag_list * flag_list, + struct mailimap_flag * f) +{ + int r; + + r = clist_append(flag_list->fl_list, f); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + +struct mailimap_flag * mailimap_flag_new_answered(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_ANSWERED, NULL, NULL); +} + +struct mailimap_flag * mailimap_flag_new_flagged(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_FLAGGED, NULL, NULL); +} + +struct mailimap_flag * mailimap_flag_new_deleted(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_DELETED, NULL, NULL); +} + +struct mailimap_flag * mailimap_flag_new_seen(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_SEEN, NULL, NULL); +} + +struct mailimap_flag * mailimap_flag_new_draft(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_DRAFT, NULL, NULL); +} + +struct mailimap_flag * mailimap_flag_new_flag_keyword(char * flag_keyword) +{ + return mailimap_flag_new(MAILIMAP_FLAG_KEYWORD, flag_keyword, NULL); +} + +struct mailimap_flag * mailimap_flag_new_flag_extension(char * flag_extension) +{ + return mailimap_flag_new(MAILIMAP_FLAG_EXTENSION, NULL, flag_extension); +} + + + + +/* CREATE */ +/* gchar */ + +/* DELETE */ +/* gchar */ + +/* EXAMINE */ +/* gchar */ + +/* LIST */ +/* gchar gchar */ + +/* LSUB */ +/* gchar gchar */ + +/* RENAME */ +/* gchar gchar */ + +/* SELECT */ +/* gchar */ + +/* STATUS */ +/* gchar GList of status_att */ + +struct mailimap_status_att_list * mailimap_status_att_list_new_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_status_att_list_new(list); +} + +int +mailimap_status_att_list_add(struct mailimap_status_att_list * sa_list, + int status_att) +{ + int * pstatus_att; + int r; + + pstatus_att = malloc(sizeof(* pstatus_att)); + * pstatus_att = status_att; + + r = clist_append(sa_list->att_list, pstatus_att); + if (r < 0) { + free(pstatus_att); + return MAILIMAP_ERROR_MEMORY; + } + + return MAILIMAP_NO_ERROR; +} + +/* SUBSCRIBE */ +/* gchar */ + +/* UNSUBSCRIBE */ +/* gchar */ + +/* LOGIN */ +/* gchar gchar */ + +/* AUTHENTICATE */ +/* gchar */ + + +static int recursive_build_path(struct mailimap_body * root_part, + struct mailimap_body * part, + clist ** result); + +static int try_build_part(struct mailimap_body * root_part, + struct mailimap_body * part, uint32_t count, + clist ** result) +{ + int r; + clist * imap_id_list; + uint32_t * id; + + r = recursive_build_path(root_part, part, &imap_id_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + id = malloc(sizeof(* id)); + if (id == NULL) { + clist_free(imap_id_list); + return MAILIMAP_ERROR_MEMORY; + } + + * id = count; + + r = clist_prepend(imap_id_list, id); + if (r < 0) { + free(id); + clist_free(imap_id_list); + return MAILIMAP_ERROR_MEMORY; + } + + * result = imap_id_list; + + return MAILIMAP_NO_ERROR; +} + + +static int recursive_build_path(struct mailimap_body * root_part, + struct mailimap_body * part, + clist ** result) +{ + clistiter * cur; + uint32_t count; + int r; + clist * imap_id_list; + + if (part == root_part) { + imap_id_list = clist_new(); + if (imap_id_list == NULL) { + return MAILIMAP_ERROR_MEMORY; + } + + * result = imap_id_list; + + return MAILIMAP_NO_ERROR; + } + + switch (root_part->bd_type) { + case MAILIMAP_BODY_MPART: + count = 0; + for(cur = clist_begin(root_part->bd_data.bd_body_mpart->bd_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_body * current_part; + + current_part = clist_content(cur); + count ++; + + r = try_build_part(current_part, part, count, &imap_id_list); + if (r == MAILIMAP_ERROR_INVAL) { + continue; + } if (r != MAILIMAP_NO_ERROR) { + return r; + } + else { + * result = imap_id_list; + return MAILIMAP_NO_ERROR; + } + } + return MAILIMAP_ERROR_INVAL; + + case MAILIMAP_BODY_1PART: + if (root_part->bd_data.bd_body_1part->bd_type == + MAILIMAP_BODY_TYPE_1PART_MSG) { + struct mailimap_body * current_part; + + current_part = + root_part->bd_data.bd_body_1part->bd_data.bd_type_msg->bd_body; + + r = try_build_part(current_part, part, 1, &imap_id_list); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + else { + * result = imap_id_list; + return MAILIMAP_NO_ERROR; + } + } + else { + return MAILIMAP_ERROR_INVAL; + } + break; + + default: + return MAILIMAP_ERROR_INVAL; + } +} + +/* return mailimap_section_part from a given mailimap_body */ + +int mailimap_get_section_part_from_body(struct mailimap_body * root_part, + struct mailimap_body * part, + struct mailimap_section_part ** result) +{ + struct mailimap_section_part * section_part; + clist * id_list; + int r; + int res; + + r = recursive_build_path(root_part, part, &id_list); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + section_part = mailimap_section_part_new(id_list); + if (section_part == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + * result = section_part; + + return MAILIMAP_NO_ERROR; + + free_list: + clist_foreach(id_list, (clist_func) free, NULL); + clist_free(id_list); + err: + return res; +} diff --git a/kmicromail/libetpan/imap/mailimap_types_helper.h b/kmicromail/libetpan/imap/mailimap_types_helper.h new file mode 100644 index 0000000..bb0bb99 --- a/dev/null +++ b/kmicromail/libetpan/imap/mailimap_types_helper.h @@ -0,0 +1,758 @@ +/* + * 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$ + */ + +#ifndef MAILIMAP_TYPES_HELPER_H + +#define MAILIMAP_TYPES_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailimap_types.h> + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + this function creates a new set item with a single message + given by index +*/ + +struct mailimap_set_item * mailimap_set_item_new_single(uint32_t index); + +/* + this function creates a new set with one set item + */ + +struct mailimap_set * +mailimap_set_new_single_item(struct mailimap_set_item * item); + +/* + this function creates a set with a single interval +*/ + +struct mailimap_set * mailimap_set_new_interval(uint32_t first, uint32_t last); + +/* + this function creates a set with a single message +*/ + +struct mailimap_set * mailimap_set_new_single(uint32_t index); + +/* + this function creates an empty set of messages +*/ + +struct mailimap_set * mailimap_set_new_empty(void); + +/* + this function adds a set item to the set of messages + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimap_set_add(struct mailimap_set * set, + struct mailimap_set_item * set_item); + +/* + this function adds an interval to the set + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimap_set_add_interval(struct mailimap_set * set, + uint32_t first, uint32_t last); + +/* + this function adds a single message to the set + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimap_set_add_single(struct mailimap_set * set, + uint32_t index); + +/* + this function creates a mailimap_section structure to request + the header of a message +*/ + +struct mailimap_section * mailimap_section_new_header(void); + +/* + this functions creates a mailimap_section structure to describe + a list of headers +*/ + +struct mailimap_section * +mailimap_section_new_header_fields(struct mailimap_header_list * header_list); + +/* + this functions creates a mailimap_section structure to describe headers + other than those given +*/ + +struct mailimap_section * +mailimap_section_new_header_fields_not(struct mailimap_header_list * header_list); + +/* + this function creates a mailimap_section structure to describe the + text of a message + */ + +struct mailimap_section * mailimap_section_new_text(void); + +/* + this function creates a mailimap_section structure to describe the + content of a MIME part +*/ + +struct mailimap_section * +mailimap_section_new_part(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe the + MIME fields of a MIME part +*/ + +struct mailimap_section * +mailimap_section_new_part_mime(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe the + headers of a MIME part if the MIME type is a message/rfc822 +*/ + +struct mailimap_section * +mailimap_section_new_part_header(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe + a list of headers of a MIME part if the MIME type is a message/rfc822 +*/ + +struct mailimap_section * +mailimap_section_new_part_header_fields(struct mailimap_section_part * + part, + struct mailimap_header_list * + header_list); + +/* + this function creates a mailimap_section structure to describe + headers of a MIME part other than those given if the MIME type + is a message/rfc822 +*/ + +struct mailimap_section * +mailimap_section_new_part_header_fields_not(struct mailimap_section_part + * part, + struct mailimap_header_list + * header_list); + +/* + this function creates a mailimap_section structure to describe + text part of message if the MIME type is a message/rfc822 +*/ + +struct mailimap_section * +mailimap_section_new_part_text(struct mailimap_section_part * part); + + +/* + this function creates a mailimap_fetch_att structure to request + envelope of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_envelope(void); + + +/* + this function creates a mailimap_fetch_att structure to request + flags of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_flags(void); + +/* + this function creates a mailimap_fetch_att structure to request + internal date of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_internaldate(void); + + +/* + this function creates a mailimap_fetch_att structure to request + text part of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822(void); + + +/* + this function creates a mailimap_fetch_att structure to request + header of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_header(void); + +/* + this function creates a mailimap_fetch_att structure to request + size of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_size(void); + +/* + this function creates a mailimap_fetch_att structure to request + envelope of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_text(void); + +/* + this function creates a mailimap_fetch_att structure to request + the MIME structure of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body(void); + +/* + this function creates a mailimap_fetch_att structure to request + the MIME structure of a message and additional MIME information +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_bodystructure(void); + +/* + this function creates a mailimap_fetch_att structure to request + unique identifier of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_uid(void); + +/* + this function creates a mailimap_fetch_att structure to request + a given section of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section(struct mailimap_section * section); + +/* + this function creates a mailimap_fetch_att structure to request + a given section of a message without marking it as read +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section(struct mailimap_section * section); + +/* + this function creates a mailimap_fetch_att structure to request + a part of a section of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size); + +/* + this function creates a mailimap_fetch_att structure to request + a part of a section of a message without marking it as read +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE) of a message +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_all(void); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE BODY) +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_full(void); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE) +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fast(void); + +/* + this function creates a mailimap_fetch_type structure to request + the given fetch attribute +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att(struct mailimap_fetch_att * fetch_att); + +/* + this function creates a mailimap_fetch_type structure to request + the list of fetch attributes +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list(clist * fetch_att_list); + +/* + this function creates a mailimap_fetch_type structure +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list_empty(void); + +/* + this function adds a given fetch attribute to the mailimap_fetch + structure + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int +mailimap_fetch_type_new_fetch_att_list_add(struct mailimap_fetch_type * + fetch_type, + struct mailimap_fetch_att * + fetch_att); + +/* + this function creates a store attribute to set the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to silently set the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags_silent(struct mailimap_flag_list * + flags); + +/* + this function creates a store attribute to add the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to add silently the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags_silent(struct mailimap_flag_list * + flags); + +/* + this function creates a store attribute to remove the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to remove silently the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags_silent(struct mailimap_flag_list * + flags); + + +/* + this function creates a condition structure to match all messages +*/ + +struct mailimap_search_key * +mailimap_search_key_new_all(void); + +/* + this function creates a condition structure to match messages with Bcc field + + @param bcc this is the content of Bcc to match, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_bcc(char * sk_bcc); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +struct mailimap_search_key * +mailimap_search_key_new_before(struct mailimap_date * sk_before); + +/* + this function creates a condition structure to match messages with + message content + + @param body this is the content of the message to match, it should + be allocated with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_body(char * sk_body); + +/* + this function creates a condition structure to match messages with + Cc field + + + @param cc this is the content of Cc to match, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_cc(char * sk_cc); + +/* + this function creates a condition structure to match messages with + From field + + @param from this is the content of From to match, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_from(char * sk_from); + +/* + this function creates a condition structure to match messages with + a flag given by keyword +*/ + +struct mailimap_search_key * +mailimap_search_key_new_keyword(char * sk_keyword); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +struct mailimap_search_key * +mailimap_search_key_new_on(struct mailimap_date * sk_on); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +struct mailimap_search_key * +mailimap_search_key_new_since(struct mailimap_date * sk_since); + +/* + this function creates a condition structure to match messages with + Subject field + + @param subject this is the content of Subject to match, it should + be allocated with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_subject(char * sk_subject); + +/* + this function creates a condition structure to match messages with + message text part + + @param text this is the message text to match, it should + be allocated with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_text(char * sk_text); + +/* + this function creates a condition structure to match messages with + To field + + @param to this is the content of To to match, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_to(char * sk_to); + +/* + this function creates a condition structure to match messages with + no a flag given by unkeyword +*/ + +struct mailimap_search_key * +mailimap_search_key_new_unkeyword(char * sk_unkeyword); + +/* + this function creates a condition structure to match messages with + the given field + + @param header_name this is the name of the field to match, it + should be allocated with malloc() + + @param header_value this is the content, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_header(char * sk_header_name, char * sk_header_value); + + +/* + this function creates a condition structure to match messages with size +*/ + +struct mailimap_search_key * +mailimap_search_key_new_larger(uint32_t sk_larger); + +/* + this function creates a condition structure to match messages that + do not match the given condition +*/ + +struct mailimap_search_key * +mailimap_search_key_new_not(struct mailimap_search_key * sk_not); + +/* + this function creates a condition structure to match messages that + match one of the given conditions +*/ + +struct mailimap_search_key * +mailimap_search_key_new_or(struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +struct mailimap_search_key * +mailimap_search_key_new_sentbefore(struct mailimap_date * sk_sentbefore); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +struct mailimap_search_key * +mailimap_search_key_new_senton(struct mailimap_date * sk_senton); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +struct mailimap_search_key * +mailimap_search_key_new_sentsince(struct mailimap_date * sk_sentsince); + +/* + this function creates a condition structure to match messages with size +*/ + +struct mailimap_search_key * +mailimap_search_key_new_smaller(uint32_t sk_smaller); + +/* + this function creates a condition structure to match messages with unique + identifier +*/ + +struct mailimap_search_key * +mailimap_search_key_new_uid(struct mailimap_set * sk_uid); + +/* + this function creates a condition structure to match messages with number + or unique identifier (depending whether SEARCH or UID SEARCH is used) +*/ + +struct mailimap_search_key * +mailimap_search_key_new_set(struct mailimap_set * sk_set); + +/* + this function creates a condition structure to match messages that match + all the conditions given in the list +*/ + +struct mailimap_search_key * +mailimap_search_key_new_multiple(clist * sk_multiple); + + +/* + same as previous but the list is empty +*/ + +struct mailimap_search_key * +mailimap_search_key_new_multiple_empty(void); + +/* + this function adds a condition to the condition list + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int +mailimap_search_key_multiple_add(struct mailimap_search_key * keys, + struct mailimap_search_key * key_item); + + +/* + this function creates an empty list of flags +*/ + +struct mailimap_flag_list * +mailimap_flag_list_new_empty(void); + +/* + this function adds a flag to the list of flags + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimap_flag_list_add(struct mailimap_flag_list * flag_list, + struct mailimap_flag * f); + +/* + this function creates a \Answered flag +*/ + +struct mailimap_flag * mailimap_flag_new_answered(void); + +/* + this function creates a \Flagged flag +*/ + +struct mailimap_flag * mailimap_flag_new_flagged(void); + +/* + this function creates a \Deleted flag +*/ + +struct mailimap_flag * mailimap_flag_new_deleted(void); + +/* + this function creates a \Seen flag +*/ + +struct mailimap_flag * mailimap_flag_new_seen(void); + +/* + this function creates a \Draft flag +*/ + +struct mailimap_flag * mailimap_flag_new_draft(void); + +/* + this function creates a keyword flag + + @param flag_keyword this should be allocated with malloc() +*/ + +struct mailimap_flag * mailimap_flag_new_flag_keyword(char * flag_keyword); + + +/* + this function creates an extension flag + + @param flag_extension this should be allocated with malloc() +*/ + +struct mailimap_flag * mailimap_flag_new_flag_extension(char * flag_extension); + +/* + this function creates an empty list of status attributes +*/ + +struct mailimap_status_att_list * mailimap_status_att_list_new_empty(void); + +/* + this function adds status attributes to the list + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int +mailimap_status_att_list_add(struct mailimap_status_att_list * sa_list, + int status_att); + +/* return mailimap_section_part from a given mailimap_body */ + +int mailimap_get_section_part_from_body(struct mailimap_body * root_part, + struct mailimap_body * part, + struct mailimap_section_part ** result); + +#ifdef __cplusplus +} +#endif + +#endif |