Diffstat (limited to 'kmicromail/libetpan/pop3/mailpop3.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | kmicromail/libetpan/pop3/mailpop3.c | 1230 |
1 files changed, 1230 insertions, 0 deletions
diff --git a/kmicromail/libetpan/pop3/mailpop3.c b/kmicromail/libetpan/pop3/mailpop3.c new file mode 100644 index 0000000..28fafe9 --- a/dev/null +++ b/kmicromail/libetpan/pop3/mailpop3.c @@ -0,0 +1,1230 @@ +/* + * 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$ + */ + +/* + POP3 Protocol + + RFC 1734 + RFC 1939 + RFC 2449 + + */ + +#include "mailpop3.h" +#include <stdio.h> +#include <string.h> +#include "md5.h" +#include "mail.h" +#include <stdlib.h> + + + + +enum { + POP3_STATE_DISCONNECTED, + POP3_STATE_AUTHORIZATION, + POP3_STATE_TRANSACTION +}; + + + +/* + mailpop3_msg_info structure +*/ + +static struct mailpop3_msg_info * +mailpop3_msg_info_new(unsigned int index, uint32_t size, char * uidl) +{ + struct mailpop3_msg_info * msg; + + msg = malloc(sizeof(* msg)); + if (msg == NULL) + return NULL; + msg->msg_index = index; + msg->msg_size = size; + msg->msg_deleted = FALSE; + msg->msg_uidl = uidl; + + return msg; +} + +static void mailpop3_msg_info_free(struct mailpop3_msg_info * msg) +{ + if (msg->msg_uidl != NULL) + free(msg->msg_uidl); + free(msg); +} + +static void mailpop3_msg_info_tab_free(carray * msg_tab) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(msg_tab) ; i++) { + struct mailpop3_msg_info * msg; + + msg = carray_get(msg_tab, i); + mailpop3_msg_info_free(msg); + } + carray_free(msg_tab); +} + +static void mailpop3_msg_info_tab_reset(carray * msg_tab) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(msg_tab) ; i++) { + struct mailpop3_msg_info * msg; + msg = carray_get(msg_tab, i); + msg->msg_deleted = FALSE; + } +} + +static inline struct mailpop3_msg_info * +mailpop3_msg_info_tab_find_msg(carray * msg_tab, unsigned int index) +{ + struct mailpop3_msg_info * msg; + + if (index == 0) + return NULL; + + if (index > carray_count(msg_tab)) + return NULL; + + msg = carray_get(msg_tab, index - 1); + + return msg; +} + + + +int mailpop3_get_msg_info(mailpop3 * f, unsigned int index, + struct mailpop3_msg_info ** result) +{ + carray * tab; + struct mailpop3_msg_info * info; + + mailpop3_list(f, &tab); + + if (tab == NULL) + return MAILPOP3_ERROR_BAD_STATE; + + info = mailpop3_msg_info_tab_find_msg(tab, index); + if (info == NULL) + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + + * result = info; + + return MAILPOP3_NO_ERROR; +} + + +/* + mailpop3_capa +*/ + +struct mailpop3_capa * mailpop3_capa_new(char * name, clist * param) +{ + struct mailpop3_capa * capa; + + capa = malloc(sizeof(* capa)); + if (capa == NULL) + return NULL; + capa->cap_name = name; + capa->cap_param = param; + + return capa; +} + + +void mailpop3_capa_free(struct mailpop3_capa * capa) +{ + clist_foreach(capa->cap_param, (clist_func) free, NULL); + clist_free(capa->cap_param); + free(capa->cap_name); + free(capa); +} + +/* + mailpop3 structure +*/ + +mailpop3 * mailpop3_new(size_t progr_rate, progress_function * progr_fun) +{ + mailpop3 * f; + + f = malloc(sizeof(* f)); + if (f == NULL) + goto err; + + f->pop3_timestamp = NULL; + f->pop3_response = NULL; + + f->pop3_stream = NULL; + + f->pop3_progr_rate = progr_rate; + f->pop3_progr_fun = progr_fun; + + f->pop3_stream_buffer = mmap_string_new(""); + if (f->pop3_stream_buffer == NULL) + goto free_f; + + f->pop3_response_buffer = mmap_string_new(""); + if (f->pop3_response_buffer == NULL) + goto free_stream_buffer; + + f->pop3_msg_tab = NULL; + f->pop3_deleted_count = 0; + f->pop3_state = POP3_STATE_DISCONNECTED; + + return f; + + free_stream_buffer: + mmap_string_free(f->pop3_stream_buffer); + free_f: + free(f); + err: + return NULL; +} + + + +void mailpop3_free(mailpop3 * f) +{ + if (f->pop3_stream) + mailpop3_quit(f); + + mmap_string_free(f->pop3_response_buffer); + mmap_string_free(f->pop3_stream_buffer); + + free(f); +} + + + + + + + + + + + +/* + operations on mailpop3 structure +*/ + +#define RESPONSE_OK 0 +#define RESPONSE_ERR -1 + +static int send_command(mailpop3 * f, char * command); + +static char * read_line(mailpop3 * f); + +static char * read_multiline(mailpop3 * f, size_t size, + MMAPString * multiline_buffer); + +static int parse_response(mailpop3 * f, char * response); + + +/* get the timestamp in the connection response */ + +#define TIMESTAMP_START '<' +#define TIMESTAMP_END '>' + +static char * mailpop3_get_timestamp(char * response) +{ + char * begin_timestamp; + char * end_timestamp; + char * timestamp; + int len_timestamp; + + if (response == NULL) + return NULL; + + begin_timestamp = strchr(response, TIMESTAMP_START); + + end_timestamp = NULL; + if (begin_timestamp != NULL) { + end_timestamp = strchr(begin_timestamp, TIMESTAMP_END); + if (end_timestamp == NULL) + begin_timestamp = NULL; + } + + if (!begin_timestamp) + return NULL; + + len_timestamp = end_timestamp - begin_timestamp + 1; + + timestamp = malloc(len_timestamp + 1); + if (timestamp == NULL) + return NULL; + strncpy(timestamp, begin_timestamp, len_timestamp); + timestamp[len_timestamp] = '\0'; + + return timestamp; +} + +/* + connect a stream to the mailpop3 structure +*/ + +int mailpop3_connect(mailpop3 * f, mailstream * s) +{ + char * response; + int r; + char * timestamp; + + if (f->pop3_state != POP3_STATE_DISCONNECTED) + return MAILPOP3_ERROR_BAD_STATE; + + f->pop3_stream = s; + + response = read_line(f); + + r = parse_response(f, response); + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_UNAUTHORIZED; + + f->pop3_state = POP3_STATE_AUTHORIZATION; + + timestamp = mailpop3_get_timestamp(f->pop3_response); + if (timestamp != NULL) + f->pop3_timestamp = timestamp; + + return MAILPOP3_NO_ERROR; +} + + +/* + disconnect from a pop3 server +*/ + +int mailpop3_quit(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + char * response; + int r; + int res; + + if ((f->pop3_state != POP3_STATE_AUTHORIZATION) + && (f->pop3_state != POP3_STATE_TRANSACTION)) { + res = MAILPOP3_ERROR_BAD_STATE; + goto close; + } + + snprintf(command, POP3_STRING_SIZE, "QUIT\r\n"); + r = send_command(f, command); + if (r == -1) { + res = MAILPOP3_ERROR_STREAM; + goto close; + } + + response = read_line(f); + if (response == NULL) { + res = MAILPOP3_ERROR_STREAM; + goto close; + } + parse_response(f, response); + + res = MAILPOP3_NO_ERROR; + + close: + mailstream_close(f->pop3_stream); + + if (f->pop3_timestamp != NULL) { + free(f->pop3_timestamp); + f->pop3_timestamp = NULL; + } + + f->pop3_stream = NULL; + if (f->pop3_msg_tab != NULL) { + mailpop3_msg_info_tab_free(f->pop3_msg_tab); + f->pop3_msg_tab = NULL; + } + + f->pop3_state = POP3_STATE_DISCONNECTED; + + return res; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +int mailpop3_apop(mailpop3 * f, + const char * user, const char * password) +{ + char command[POP3_STRING_SIZE]; + MD5_CTX md5context; + unsigned char md5digest[16]; + char md5string[33]; + char * cmd_ptr; + int r; + int i; + char * response; + + if (f->pop3_state != POP3_STATE_AUTHORIZATION) + return MAILPOP3_ERROR_BAD_STATE; + + if (f->pop3_timestamp == NULL) + return MAILPOP3_ERROR_APOP_NOT_SUPPORTED; + + /* calculate md5 sum */ + + MD5Init(&md5context); + MD5Update(&md5context, f->pop3_timestamp, strlen (f->pop3_timestamp)); + MD5Update(&md5context, password, strlen (password)); + MD5Final(md5digest, &md5context); + + cmd_ptr = md5string; + for(i = 0 ; i < 16 ; i++, cmd_ptr += 2) + snprintf(cmd_ptr, 3, "%02x", md5digest[i]); + * cmd_ptr = 0; + + /* send apop command */ + + snprintf(command, POP3_STRING_SIZE, "APOP %s %s\r\n", user, md5string); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_DENIED; + + f->pop3_state = POP3_STATE_TRANSACTION; + + return MAILPOP3_NO_ERROR; +} + +int mailpop3_user(mailpop3 * f, const char * user) +{ + char command[POP3_STRING_SIZE]; + int r; + char * response; + + if (f->pop3_state != POP3_STATE_AUTHORIZATION) + return MAILPOP3_ERROR_BAD_STATE; + + /* send user command */ + + snprintf(command, POP3_STRING_SIZE, "USER %s\r\n", user); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_BAD_USER; + + return MAILPOP3_NO_ERROR; +} + +int mailpop3_pass(mailpop3 * f, const char * password) +{ + char command[POP3_STRING_SIZE]; + int r; + char * response; + + if (f->pop3_state != POP3_STATE_AUTHORIZATION) + return MAILPOP3_ERROR_BAD_STATE; + + /* send password command */ + + snprintf(command, POP3_STRING_SIZE, "PASS %s\r\n", password); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_BAD_PASSWORD; + + f->pop3_state = POP3_STATE_TRANSACTION; + + return MAILPOP3_NO_ERROR; +} + +static int read_list(mailpop3 * f, carray ** result); + + + +static int read_uidl(mailpop3 * f, carray * msg_tab); + + + +static int mailpop3_do_uidl(mailpop3 * f, carray * msg_tab) +{ + char command[POP3_STRING_SIZE]; + int r; + char * response; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + /* send list command */ + + snprintf(command, POP3_STRING_SIZE, "UIDL\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_CANT_LIST; + + r = read_uidl(f, msg_tab); + if (r != MAILPOP3_NO_ERROR) + return r; + + return MAILPOP3_NO_ERROR; +} + + + +static int mailpop3_do_list(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + int r; + carray * msg_tab; + char * response; + + if (f->pop3_msg_tab != NULL) { + mailpop3_msg_info_tab_free(f->pop3_msg_tab); + f->pop3_msg_tab = NULL; + } + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + /* send list command */ + + snprintf(command, POP3_STRING_SIZE, "LIST\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_CANT_LIST; + + r = read_list(f, &msg_tab); + if (r != MAILPOP3_NO_ERROR) + return r; + + f->pop3_msg_tab = msg_tab; + f->pop3_deleted_count = 0; + + mailpop3_do_uidl(f, msg_tab); + + return MAILPOP3_NO_ERROR; +} + + + +static void mailpop3_list_if_needed(mailpop3 * f) +{ + if (f->pop3_msg_tab == NULL) + mailpop3_do_list(f); +} + +/* + mailpop3_list +*/ + +void mailpop3_list(mailpop3 * f, carray ** result) +{ + mailpop3_list_if_needed(f); + * result = f->pop3_msg_tab; +} + +static inline struct mailpop3_msg_info * +find_msg(mailpop3 * f, unsigned int index) +{ + mailpop3_list_if_needed(f); + + if (f->pop3_msg_tab == NULL) + return NULL; + + return mailpop3_msg_info_tab_find_msg(f->pop3_msg_tab, index); +} + + + + + + + + +static void mailpop3_multiline_response_free(char * str) +{ + mmap_string_unref(str); +} + +void mailpop3_top_free(char * str) +{ + mailpop3_multiline_response_free(str); +} + +void mailpop3_retr_free(char * str) +{ + mailpop3_multiline_response_free(str); +} + +/* + mailpop3_retr + + message content in (* result) is still there until the + next retrieve or top operation on the mailpop3 structure +*/ + +static int +mailpop3_get_content(mailpop3 * f, struct mailpop3_msg_info * msginfo, + char ** result, size_t * result_len) +{ + char * response; + char * result_multiline; + MMAPString * buffer; + int r; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + + buffer = mmap_string_new(""); + if (buffer == NULL) + return MAILPOP3_ERROR_MEMORY; + + result_multiline = read_multiline(f, msginfo->msg_size, buffer); + if (result_multiline == NULL) { + mmap_string_free(buffer); + return MAILPOP3_ERROR_STREAM; + } + else { + r = mmap_string_ref(buffer); + if (r < 0) { + mmap_string_free(buffer); + return MAILPOP3_ERROR_MEMORY; + } + + * result = result_multiline; + * result_len = buffer->len; + return MAILPOP3_NO_ERROR; + } +} + +int mailpop3_retr(mailpop3 * f, unsigned int index, char ** result, + size_t * result_len) +{ + char command[POP3_STRING_SIZE]; + struct mailpop3_msg_info * msginfo; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + msginfo = find_msg(f, index); + + if (msginfo == NULL) { + f->pop3_response = NULL; + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + } + + snprintf(command, POP3_STRING_SIZE, "RETR %i\r\n", index); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + return mailpop3_get_content(f, msginfo, result, result_len); +} + +int mailpop3_top(mailpop3 * f, unsigned int index, + uint32_t count, char ** result, + size_t * result_len) +{ + char command[POP3_STRING_SIZE]; + struct mailpop3_msg_info * msginfo; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + msginfo = find_msg(f, index); + + if (msginfo == NULL) { + f->pop3_response = NULL; + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + } + + snprintf(command, POP3_STRING_SIZE, "TOP %i %i\r\n", index, count); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + return mailpop3_get_content(f, msginfo, result, result_len); +} + +int mailpop3_dele(mailpop3 * f, unsigned int index) +{ + char command[POP3_STRING_SIZE]; + struct mailpop3_msg_info * msginfo; + char * response; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + msginfo = find_msg(f, index); + + if (msginfo == NULL) { + f->pop3_response = NULL; + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + } + + snprintf(command, POP3_STRING_SIZE, "DELE %i\r\n", index); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + + msginfo->msg_deleted = TRUE; + f->pop3_deleted_count ++; + + return MAILPOP3_NO_ERROR; +} + +int mailpop3_noop(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + char * response; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + snprintf(command, POP3_STRING_SIZE, "NOOP\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + parse_response(f, response); + + return MAILPOP3_NO_ERROR; +} + +int mailpop3_rset(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + char * response; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + snprintf(command, POP3_STRING_SIZE, "RSET\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + parse_response(f, response); + + if (f->pop3_msg_tab != NULL) { + mailpop3_msg_info_tab_reset(f->pop3_msg_tab); + f->pop3_deleted_count = 0; + } + + return MAILPOP3_NO_ERROR; +} + + + +static int read_capa_resp(mailpop3 * f, clist ** result); + +int mailpop3_capa(mailpop3 * f, clist ** result) +{ + clist * capa_list; + char command[POP3_STRING_SIZE]; + int r; + char * response; + + snprintf(command, POP3_STRING_SIZE, "CAPA\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_CAPA_NOT_SUPPORTED; + + r = read_capa_resp(f, &capa_list); + if (r != MAILPOP3_NO_ERROR) + return r; + + * result = capa_list; + + return MAILPOP3_NO_ERROR; +} + +void mailpop3_capa_resp_free(clist * capa_list) +{ + clist_foreach(capa_list, (clist_func) mailpop3_capa_free, NULL); + clist_free(capa_list); +} + +int mailpop3_stls(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + int r; + char * response; + + snprintf(command, POP3_STRING_SIZE, "STLS\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_STLS_NOT_SUPPORTED; + + return MAILPOP3_NO_ERROR; +} + + + + + + + + + + + + + + + + + + + + + + + + +#define RESP_OK_STR "+OK" +#define RESP_ERR_STR "-ERR" + + +static int parse_space(char ** line) +{ + char * p; + + p = * line; + + while ((* p == ' ') || (* p == '\t')) + p ++; + + if (p != * line) { + * line = p; + return TRUE; + } + else + return FALSE; +} + +static char * cut_token(char * line) +{ + char * p; + char * p_tab; + char * p_space; + + p = line; + + p_space = strchr(line, ' '); + p_tab = strchr(line, '\t'); + if (p_tab == NULL) + p = p_space; + else if (p_space == NULL) + p = p_tab; + else { + if (p_tab < p_space) + p = p_tab; + else + p = p_space; + } + if (p == NULL) + return NULL; + * p = 0; + p ++; + + return p; +} + + +static int parse_response(mailpop3 * f, char * response) +{ + char * msg; + + if (response == NULL) { + f->pop3_response = NULL; + return RESPONSE_ERR; + } + + if (strncmp(response, RESP_OK_STR, strlen(RESP_OK_STR)) == 0) { + + if (response[strlen(RESP_OK_STR)] == ' ') + msg = response + strlen(RESP_OK_STR) + 1; + else + msg = response + strlen(RESP_OK_STR); + + if (mmap_string_assign(f->pop3_response_buffer, msg)) + f->pop3_response = f->pop3_response_buffer->str; + else + f->pop3_response = NULL; + + return RESPONSE_OK; + } + else if (strncmp(response, RESP_ERR_STR, strlen(RESP_ERR_STR)) == 0) { + + if (response[strlen(RESP_ERR_STR)] == ' ') + msg = response + strlen(RESP_ERR_STR) + 1; + else + msg = response + strlen(RESP_ERR_STR); + + if (mmap_string_assign(f->pop3_response_buffer, msg)) + f->pop3_response = f->pop3_response_buffer->str; + else + f->pop3_response = NULL; + } + + f->pop3_response = NULL; + return RESPONSE_ERR; +} + + + + + + + +static int read_list(mailpop3 * f, carray ** result) +{ + unsigned int index; + uint32_t size; + carray * msg_tab; + struct mailpop3_msg_info * msg; + char * line; + + msg_tab = carray_new(128); + if (msg_tab == NULL) + goto err; + + while (1) { + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + index = strtol(line, &line, 10); + + if (!parse_space(&line)) + continue; + + size = strtol(line, &line, 10); + + msg = mailpop3_msg_info_new(index, size, NULL); + if (msg == NULL) + goto free_list; + + if (carray_count(msg_tab) < index) { + int r; + + r = carray_set_size(msg_tab, index); + if (r == -1) + goto free_list; + } + + carray_set(msg_tab, index - 1, msg); + } + + * result = msg_tab; + + return MAILPOP3_NO_ERROR; + + free_list: + mailpop3_msg_info_tab_free(msg_tab); + err: + return MAILPOP3_ERROR_STREAM; +} + + + +static int read_uidl(mailpop3 * f, carray * msg_tab) +{ + unsigned int index; + struct mailpop3_msg_info * msg; + char * line; + + while (1) { + char * uidl; + + line = read_line(f); + if (line == NULL) + goto err; + + if (mailstream_is_end_multiline(line)) + break; + + index = strtol(line, &line, 10); + + if (!parse_space(&line)) + continue; + + uidl = strdup(line); + if (uidl == NULL) + continue; + + if (index > carray_count(msg_tab)) { + free(uidl); + continue; + } + + msg = carray_get(msg_tab, index - 1); + if (msg == NULL) { + free(uidl); + continue; + } + + msg->msg_uidl = uidl; + } + + return MAILPOP3_NO_ERROR; + + err: + return MAILPOP3_ERROR_STREAM; +} + + + +static int read_capa_resp(mailpop3 * f, clist ** result) +{ + char * line; + int res; + clist * list; + int r; + char * name; + clist * param_list; + + list = clist_new(); + if (list == NULL) { + res = MAILPOP3_NO_ERROR; + goto err; + } + + while (1) { + char * next_token; + char * param; + struct mailpop3_capa * capa; + + line = read_line(f); + if (line == NULL) { + res = MAILPOP3_ERROR_STREAM; + goto free_list; + } + + if (mailstream_is_end_multiline(line)) + break; + + next_token = cut_token(line); + name = strdup(line); + if (name == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_list; + } + + param_list = clist_new(); + if (param_list == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_capa_name; + } + + while (next_token != NULL) { + line = next_token; + next_token = cut_token(line); + param = strdup(line); + if (param == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_param_list; + } + r = clist_append(param_list, param); + if (r < 0) { + free(param); + res = MAILPOP3_ERROR_MEMORY; + goto free_param_list; + } + } + + capa = mailpop3_capa_new(name, param_list); + if (capa == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_param_list; + } + + r = clist_append(list, capa); + if (r < 0) { + mailpop3_capa_free(capa); + res = MAILPOP3_ERROR_MEMORY; + goto free_list; + } + } + + * result = list; + + return MAILPOP3_NO_ERROR; + + free_param_list: + clist_foreach(param_list, (clist_func) free, NULL); + clist_free(param_list); + free_capa_name: + free(name); + free_list: + clist_foreach(list, (clist_func) mailpop3_capa_free, NULL); + clist_free(list); + err: + return res; +} + + + +static char * read_line(mailpop3 * f) +{ + return mailstream_read_line_remove_eol(f->pop3_stream, f->pop3_stream_buffer); +} + +static char * read_multiline(mailpop3 * f, size_t size, + MMAPString * multiline_buffer) +{ + return mailstream_read_multiline(f->pop3_stream, size, + f->pop3_stream_buffer, multiline_buffer, + f->pop3_progr_rate, f->pop3_progr_fun); +} + +static int send_command(mailpop3 * f, char * command) +{ + ssize_t r; + + r = mailstream_write(f->pop3_stream, command, strlen(command)); + if (r == -1) + return -1; + + r = mailstream_flush(f->pop3_stream); + if (r == -1) + return -1; + + return 0; +} |