-rw-r--r-- | kmicromail/libetpan/generic/pop3driver.c | 7 | ||||
-rw-r--r-- | kmicromail/libetpan/pop3/mailpop3.c | 5 | ||||
-rw-r--r-- | kmicromail/libetpan/tools/mailstream_helper.c | 9 |
3 files changed, 17 insertions, 4 deletions
diff --git a/kmicromail/libetpan/generic/pop3driver.c b/kmicromail/libetpan/generic/pop3driver.c index 375879e..475dfcc 100644 --- a/kmicromail/libetpan/generic/pop3driver.c +++ b/kmicromail/libetpan/generic/pop3driver.c @@ -1,388 +1,391 @@ /* * 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 "pop3driver.h" #include <string.h> #include <stdlib.h> #include "pop3driver_message.h" #include "maildriver_tools.h" #include "pop3driver_tools.h" #include "mailmessage.h" static int pop3driver_initialize(mailsession * session); static void pop3driver_uninitialize(mailsession * session); static int pop3driver_parameters(mailsession * session, int id, void * value); static int pop3driver_connect_stream(mailsession * session, mailstream * s); static int pop3driver_starttls(mailsession * session); static int pop3driver_login(mailsession * session, char * userid, char * password); static int pop3driver_logout(mailsession * session); static int pop3driver_noop(mailsession * session); static int pop3driver_status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen); static int pop3driver_messages_number(mailsession * session, char * mb, uint32_t * result); static int pop3driver_remove_message(mailsession * session, uint32_t num); static int pop3driver_get_messages_list(mailsession * session, struct mailmessage_list ** result); static int pop3driver_get_message(mailsession * session, uint32_t num, mailmessage ** result); static mailsession_driver local_pop3_session_driver = { .sess_name = "pop3", .sess_initialize = pop3driver_initialize, .sess_uninitialize = pop3driver_uninitialize, .sess_parameters = pop3driver_parameters, .sess_connect_stream = pop3driver_connect_stream, .sess_connect_path = NULL, .sess_starttls = pop3driver_starttls, .sess_login = pop3driver_login, .sess_logout = pop3driver_logout, .sess_noop = pop3driver_noop, .sess_build_folder_name = NULL, .sess_create_folder = NULL, .sess_delete_folder = NULL, .sess_rename_folder = NULL, .sess_check_folder = NULL, .sess_examine_folder = NULL, .sess_select_folder = NULL, .sess_expunge_folder = NULL, .sess_status_folder = pop3driver_status_folder, .sess_messages_number = pop3driver_messages_number, .sess_recent_number = pop3driver_messages_number, .sess_unseen_number = pop3driver_messages_number, .sess_list_folders = NULL, .sess_lsub_folders = NULL, .sess_subscribe_folder = NULL, .sess_unsubscribe_folder = NULL, .sess_append_message = NULL, .sess_append_message_flags = NULL, .sess_copy_message = NULL, .sess_move_message = NULL, .sess_get_messages_list = pop3driver_get_messages_list, .sess_get_envelopes_list = maildriver_generic_get_envelopes_list, .sess_remove_message = pop3driver_remove_message, #if 0 .sess_search_messages = maildriver_generic_search_messages, #endif .sess_get_message = pop3driver_get_message, .sess_get_message_by_uid = NULL, }; mailsession_driver * pop3_session_driver = &local_pop3_session_driver; static inline struct pop3_session_state_data * get_data(mailsession * session) { return session->sess_data; } static mailpop3 * get_pop3_session(mailsession * session) { return get_data(session)->pop3_session; } static int pop3driver_initialize(mailsession * session) { struct pop3_session_state_data * data; mailpop3 * pop3; pop3 = mailpop3_new(0, NULL); if (session == NULL) goto err; data = malloc(sizeof(* data)); if (data == NULL) goto free; data->pop3_session = pop3; data->pop3_auth_type = POP3DRIVER_AUTH_TYPE_PLAIN; session->sess_data = data; return MAIL_NO_ERROR; free: mailpop3_free(pop3); err: return MAIL_ERROR_MEMORY; } static void pop3driver_uninitialize(mailsession * session) { struct pop3_session_state_data * data; data = get_data(session); mailpop3_free(data->pop3_session); free(data); session->sess_data = data; } static int pop3driver_connect_stream(mailsession * session, mailstream * s) { int r; r = mailpop3_connect(get_pop3_session(session), s); switch (r) { case MAILPOP3_NO_ERROR: return MAIL_NO_ERROR_NON_AUTHENTICATED; default: return pop3driver_pop3_error_to_mail_error(r); } } static int pop3driver_starttls(mailsession * session) { int r; int fd; mailstream_low * low; mailstream_low * new_low; mailpop3 * pop3; pop3 = get_pop3_session(session); r = mailpop3_stls(pop3); switch (r) { case MAILPOP3_NO_ERROR: break; default: return pop3driver_pop3_error_to_mail_error(r); } low = mailstream_get_low(pop3->pop3_stream); fd = mailstream_low_get_fd(low); if (fd == -1) return MAIL_ERROR_STREAM; new_low = mailstream_low_ssl_open(fd); if (new_low == NULL) return MAIL_ERROR_STREAM; mailstream_low_free(low); mailstream_set_low(pop3->pop3_stream, new_low); return MAIL_NO_ERROR; } static int pop3driver_parameters(mailsession * session, int id, void * value) { struct pop3_session_state_data * data; data = get_data(session); switch (id) { case POP3DRIVER_SET_AUTH_TYPE: { int * param; param = value; data->pop3_auth_type = * param; return MAIL_NO_ERROR; } } return MAIL_ERROR_INVAL; } static int pop3driver_login(mailsession * session, char * userid, char * password) { int r; carray * msg_tab; struct pop3_session_state_data * data; data = get_data(session); switch (data->pop3_auth_type) { case POP3DRIVER_AUTH_TYPE_TRY_APOP: r = mailpop3_login_apop(get_pop3_session(session), userid, password); if (r != MAILPOP3_NO_ERROR) r = mailpop3_login(get_pop3_session(session), userid, password); break; case POP3DRIVER_AUTH_TYPE_APOP: r = mailpop3_login_apop(get_pop3_session(session), userid, password); break; default: case POP3DRIVER_AUTH_TYPE_PLAIN: r = mailpop3_login(get_pop3_session(session), userid, password); break; } - + // LR 2 lines + int ret = pop3driver_pop3_error_to_mail_error(r); + if ( ret == MAIL_NO_ERROR ) mailpop3_list(get_pop3_session(session), &msg_tab); - return pop3driver_pop3_error_to_mail_error(r); + // LR + return ret; } static int pop3driver_logout(mailsession * session) { int r; r = mailpop3_quit(get_pop3_session(session)); return pop3driver_pop3_error_to_mail_error(r); } static int pop3driver_noop(mailsession * session) { int r; r = mailpop3_noop(get_pop3_session(session)); return pop3driver_pop3_error_to_mail_error(r); } static int pop3driver_status_folder(mailsession * session, char * mb, uint32_t * result_messages, uint32_t * result_recent, uint32_t * result_unseen) { uint32_t count; int r; r = pop3driver_messages_number(session, mb, &count); if (r != MAIL_NO_ERROR) return r; * result_messages = count; * result_recent = count; * result_unseen = count; return MAIL_NO_ERROR; } static int pop3driver_messages_number(mailsession * session, char * mb, uint32_t * result) { carray * msg_tab; mailpop3_list(get_pop3_session(session), &msg_tab); * result = carray_count(msg_tab) - get_pop3_session(session)->pop3_deleted_count; return MAIL_NO_ERROR; } /* messages operations */ static int pop3driver_remove_message(mailsession * session, uint32_t num) { mailpop3 * pop3; int r; pop3 = get_pop3_session(session); r = mailpop3_dele(pop3, num); switch (r) { case MAILPOP3_ERROR_BAD_STATE: return MAIL_ERROR_BAD_STATE; case MAILPOP3_ERROR_NO_SUCH_MESSAGE: return MAIL_ERROR_MSG_NOT_FOUND; case MAILPOP3_ERROR_STREAM: return MAIL_ERROR_STREAM; case MAILPOP3_NO_ERROR: return MAIL_NO_ERROR; default: return MAIL_ERROR_REMOVE; } } static int pop3driver_get_messages_list(mailsession * session, struct mailmessage_list ** result) { mailpop3 * pop3; pop3 = get_pop3_session(session); return pop3_get_messages_list(pop3, session, pop3_message_driver, result); } static int pop3driver_get_message(mailsession * session, uint32_t num, mailmessage ** result) { mailmessage * msg_info; int r; msg_info = mailmessage_new(); if (msg_info == NULL) return MAIL_ERROR_MEMORY; r = mailmessage_init(msg_info, session, pop3_message_driver, num, 0); if (r != MAIL_NO_ERROR) { mailmessage_free(msg_info); return r; } * result = msg_info; return MAIL_NO_ERROR; } diff --git a/kmicromail/libetpan/pop3/mailpop3.c b/kmicromail/libetpan/pop3/mailpop3.c index 28fafe9..691b07a 100644 --- a/kmicromail/libetpan/pop3/mailpop3.c +++ b/kmicromail/libetpan/pop3/mailpop3.c @@ -1,1230 +1,1233 @@ /* * 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) + if (r != RESPONSE_OK) { + // LR + fprintf(stderr,"POP3 login error. Response from server:\n%s\n",response ); 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; } diff --git a/kmicromail/libetpan/tools/mailstream_helper.c b/kmicromail/libetpan/tools/mailstream_helper.c index 146f955..92f4ffe 100644 --- a/kmicromail/libetpan/tools/mailstream_helper.c +++ b/kmicromail/libetpan/tools/mailstream_helper.c @@ -1,383 +1,390 @@ /* * 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_helper.h" #include <string.h> #include <stdio.h> #include "mail.h" static void remove_trailing_eol(MMAPString * mmapstr) { if (mmapstr->str[mmapstr->len - 1] == '\n') { mmapstr->len --; mmapstr->str[mmapstr->len] = '\0'; } if (mmapstr->str[mmapstr->len - 1] == '\r') { mmapstr->len --; mmapstr->str[mmapstr->len] = '\0'; } } char * mailstream_read_line(mailstream * stream, MMAPString * line) { if (mmap_string_assign(line, "") == NULL) return NULL; return mailstream_read_line_append(stream, line); } static char * mailstream_read_len_append(mailstream * stream, MMAPString * line, size_t i) { size_t cur_size; cur_size = line->len; if (mmap_string_set_size(line, line->len + i) == NULL) return NULL; if (mailstream_read(stream, line->str + cur_size, i) < 0) return NULL; return line->str; } char * mailstream_read_line_append(mailstream * stream, MMAPString * line) { if (stream == NULL) return NULL; do { if (stream->read_buffer_len > 0) { size_t i; i = 0; while (i < stream->read_buffer_len) { if (stream->read_buffer[i] == '\n') return mailstream_read_len_append(stream, line, i + 1); i++; } if (mailstream_read_len_append(stream, line, stream->read_buffer_len) == NULL) return NULL; } else { ssize_t r; r = mailstream_feed_read_buffer(stream); if (r == -1) return NULL; - if (r == 0) + if (r == 0) { + // LR + // this avoids a memory access violation later when trying + // to remove_trailing_eol from a null string + if ( line->len == 0 ) + return NULL; + else break; } } + } while (1); return line->str; } char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line) { if (!mailstream_read_line(stream, line)) return NULL; remove_trailing_eol(line); return line->str; } int mailstream_is_end_multiline(const char * line) { if (line[0] != '.') return FALSE; if (line[1] != 0) return FALSE; return TRUE; } #if 1 char * mailstream_read_multiline(mailstream * s, size_t size, MMAPString * stream_buffer, MMAPString * multiline_buffer, size_t progr_rate, progress_function * progr_fun) { size_t count; char * line; size_t last; if (mmap_string_assign(multiline_buffer, "") == NULL) return NULL; count = 0; last = 0; while ((line = mailstream_read_line_remove_eol(s, stream_buffer)) != NULL) { if (mailstream_is_end_multiline(line)) return multiline_buffer->str; if (line[0] == '.') { if (mmap_string_append(multiline_buffer, line + 1) == NULL) return NULL; } else { if (mmap_string_append(multiline_buffer, line) == NULL) return NULL; } if (mmap_string_append(multiline_buffer, "\r\n") == NULL) return NULL; count += strlen(line); if ((size != 0) && (progr_rate != 0) && (progr_fun != NULL)) if (count - last >= progr_rate) { (* progr_fun)(count, size); last = count; } } return NULL; } #else /* high speed but don't replace the line break with '\n' and neither remove the '.' */ static gboolean end_of_multiline(const char * str, gint len) { gint index; index = len - 1; if (str[index] != '\n') return FALSE; if (index == 0) return FALSE; index --; if (str[index] == '\r') { index --; if (index == 0) return FALSE; } if (str[index] != '.') return FALSE; if (index == 0) return FALSE; index--; if (str[index] != '\n') return FALSE; return TRUE; } char * mailstream_read_multiline(mailstream * stream, size_t size, MMAPString * stream_buffer, MMAPString * line, size_t progr_rate, progress_function * progr_fun) { if (stream == NULL) return NULL; mmap_string_assign(line, ""); do { if (stream->read_buffer_len > 0) { size_t i; i = 0; while (i < stream->read_buffer_len) { if (end_of_multiline(stream->read_buffer, i + 1)) return mailstream_read_len_append(stream, line, i + 1); i++; } if (mailstream_read_len_append(stream, line, stream->read_buffer_len) == NULL) return NULL; if (end_of_multiline(line->str, line->len)) return line->str; } else if (mailstream_feed_read_buffer(stream) == -1) return NULL; } while (1); return line->str; } #endif static ssize_t send_data_line(mailstream * s, const char * line, size_t length) { int fix_eol; const char * start; size_t count; start = line; fix_eol = 0; count = 0; while (1) { if (length == 0) break; if (* line == '\r') { line ++; count ++; length --; if (* line == '\n') { line ++; count ++; length --; break; } } if (* line == '\n') { line ++; count ++; length --; fix_eol = 1; break; } line ++; length --; count ++; } if (start[0] == '.') if (mailstream_write(s, ".", 1) == -1) goto err; if (fix_eol) { if (mailstream_write(s, start, count - 1) == -1) goto err; if (mailstream_write(s, "\r\n", 2) == -1) goto err; } else { if (mailstream_write(s, start, count) == -1) goto err; } #if 0 while (* line != '\n') { if (* line == '\r') pos = line; if (* line == '\0') return line; if (mailstream_write(s, line, 1) == -1) goto err; line ++; } if (pos + 1 == line) { if (mailstream_write(s, line, 1) == -1) goto err; } else { if (mailstream_write(s, "\r\n", 2) == -1) goto err; } line ++; #endif return count; err: return -1; } int mailstream_send_data(mailstream * s, const char * message, size_t size, size_t progr_rate, progress_function * progr_fun) { const char * current; size_t count; size_t last; size_t remaining; count = 0; last = 0; current = message; remaining = size; while (remaining > 0) { ssize_t length; length = send_data_line(s, current, remaining); if (length < 0) goto err; current += length; count += length; if ((progr_rate != 0) && (progr_fun != NULL)) if (count - last >= progr_rate) { (* progr_fun)(count, size); last = count; } remaining -= length; } if (mailstream_write(s, "\r\n.\r\n", 5) == -1) goto err; if (mailstream_flush(s) == -1) goto err; return 0; err: return -1; } |