-rw-r--r-- | libetpan/src/data-types/mailstream_helper.c | 11 | ||||
-rw-r--r-- | libetpan/src/driver/implementation/pop3/pop3driver.c | 8 | ||||
-rw-r--r-- | libetpan/src/low-level/imap/mailimap_parser.c | 22 | ||||
-rw-r--r-- | libetpan/src/low-level/maildir/maildir.c | 17 | ||||
-rw-r--r-- | libetpan/src/low-level/mh/mailmh.c | 3 | ||||
-rw-r--r-- | libetpan/src/low-level/pop3/mailpop3.c | 7 |
6 files changed, 59 insertions, 9 deletions
diff --git a/libetpan/src/data-types/mailstream_helper.c b/libetpan/src/data-types/mailstream_helper.c index 2f0b9ae..f0ddf51 100644 --- a/libetpan/src/data-types/mailstream_helper.c +++ b/libetpan/src/data-types/mailstream_helper.c @@ -1,486 +1,493 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2005 - DINH Viet Hoa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the libEtPan! project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * $Id$ */ #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) - break; + 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 inline 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 (length == 0) { fix_eol = 1; break; } if (* line == '\n') { line ++; count ++; length --; break; } else { fix_eol = 1; break; } } else if (* line == '\n') { line ++; count ++; length --; fix_eol = 1; break; } line ++; length --; count ++; } 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; } static inline int send_data_crlf(mailstream * s, const char * message, size_t size, int quoted, 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; if (quoted) { if (current[0] == '.') if (mailstream_write(s, ".", 1) == -1) goto err; } 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; } return 0; err: return -1; } int mailstream_send_data_crlf(mailstream * s, const char * message, size_t size, size_t progr_rate, progress_function * progr_fun) { return send_data_crlf(s, message, size, 0, progr_rate, progr_fun); } int mailstream_send_data(mailstream * s, const char * message, size_t size, size_t progr_rate, progress_function * progr_fun) { if (send_data_crlf(s, message, size, 1, progr_rate, progr_fun) == -1) goto err; if (mailstream_write(s, "\r\n.\r\n", 5) == -1) goto err; if (mailstream_flush(s) == -1) goto err; return 0; err: return -1; } static inline ssize_t get_data_size(const char * line, size_t length, size_t * result) { int fix_eol; const char * start; size_t count; size_t fixed_count; start = line; fix_eol = 0; count = 0; fixed_count = 0; while (1) { if (length == 0) break; if (* line == '\r') { line ++; count ++; length --; if (length == 0) { fix_eol = 1; fixed_count ++; break; } if (* line == '\n') { line ++; count ++; length --; break; } else { fix_eol = 1; fixed_count ++; break; } } else if (* line == '\n') { line ++; count ++; length --; fix_eol = 1; fixed_count ++; break; } line ++; length --; count ++; } * result = count + fixed_count; return count; } size_t mailstream_get_data_crlf_size(const char * message, size_t size) { diff --git a/libetpan/src/driver/implementation/pop3/pop3driver.c b/libetpan/src/driver/implementation/pop3/pop3driver.c index ea69923..6cc6a9a 100644 --- a/libetpan/src/driver/implementation/pop3/pop3driver.c +++ b/libetpan/src/driver/implementation/pop3/pop3driver.c @@ -1,388 +1,394 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2005 - DINH Viet Hoa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the libEtPan! project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * $Id$ */ #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; + //LR + int ret; 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; } - mailpop3_list(get_pop3_session(session), &msg_tab); + // LR 2 lines + ret = pop3driver_pop3_error_to_mail_error(r); + if ( ret == MAIL_NO_ERROR ) + mailpop3_list(get_pop3_session(session), &msg_tab); + // LR return pop3driver_pop3_error_to_mail_error(r); } 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/libetpan/src/low-level/imap/mailimap_parser.c b/libetpan/src/low-level/imap/mailimap_parser.c index ab4db67..071891c 100644 --- a/libetpan/src/low-level/imap/mailimap_parser.c +++ b/libetpan/src/low-level/imap/mailimap_parser.c @@ -2018,770 +2018,788 @@ mailimap_body_ext_1part_parse(mailstream * fd, MMAPString * buffer, 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; uint32_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; + // LR start + // accept NIL and set type to utf8 + int ret = r; + r = mailimap_char_parse(fd, buffer, &cur_token, 'N'); + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_char_parse(fd, buffer, &cur_token, 'I'); + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_char_parse(fd, buffer, &cur_token, 'L'); + if (r == MAILIMAP_NO_ERROR) { + type = 4; + ret = MAILIMAP_NO_ERROR; + value = NULL; + } + } + } + if ( ret != MAILIMAP_NO_ERROR ) { + res = ret; + goto err; + } + // LR end } } else { res = r; goto err; } body_fld_enc = mailimap_body_fld_enc_new(type, value); if (body_fld_enc == NULL) { res = MAILIMAP_ERROR_MEMORY; goto value_free; } * result = body_fld_enc; * index = cur_token; return MAILIMAP_NO_ERROR; value_free: if (value) mailimap_string_free(value); err: return res; } /* body-fld-id = nstring */ static int mailimap_body_fld_id_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_nstring_parse(fd, buffer, index, result, NULL, progr_rate, progr_fun); } /* body-fld-lang = nstring / "(" string *(SP string) ")" */ /* "(" string *(SP string) ")" */ static int mailimap_body_fld_lang_list_parse(mailstream * fd, MMAPString * buffer, size_t * index, clist ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; clist * list; int r; int res; cur_token = * index; r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } list = clist_new(); if (list == NULL) { res = MAILIMAP_ERROR_MEMORY; goto err; } while (1) { char * elt; r = mailimap_string_parse(fd, buffer, &cur_token, &elt, NULL, progr_rate, progr_fun); if (r != MAILIMAP_ERROR_PARSE) break; else if (r == MAILIMAP_NO_ERROR) { r = clist_append(list, elt); if (r < 0) { mailimap_string_free(elt); res = r; goto list_free; } } else { res = r; goto list_free; } } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto list_free; } * index = cur_token; * result = list; return MAILIMAP_NO_ERROR; list_free: clist_foreach(list, (clist_func) mailimap_string_free, NULL); clist_free(list); err: return res; } /* body-fld-lang = nstring / "(" string *(SP string) ")" */ static int mailimap_body_fld_lang_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_fld_lang ** result, size_t progr_rate, progress_function * progr_fun) { char * value; clist * list; struct mailimap_body_fld_lang * fld_lang; int type; int r; int res; size_t cur_token; cur_token = * index; value = NULL; list = NULL; type = MAILIMAP_BODY_FLD_LANG_ERROR; /* XXX - removes a gcc warning */ r = mailimap_nstring_parse(fd, buffer, &cur_token, &value, NULL, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_BODY_FLD_LANG_SINGLE; if (r == MAILIMAP_ERROR_PARSE) { r = mailimap_body_fld_lang_list_parse(fd, buffer, &cur_token, &list, progr_rate, progr_fun); if (r == MAILIMAP_NO_ERROR) type = MAILIMAP_BODY_FLD_LANG_LIST; } if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } fld_lang = mailimap_body_fld_lang_new(type, value, list); if (fld_lang == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * index = cur_token; * result = fld_lang; return MAILIMAP_NO_ERROR; free: if (value) mailimap_nstring_free(value); if (list) { clist_foreach(list, (clist_func) mailimap_string_free, NULL); clist_free(list); } err: return res; } /* body-fld-lines = number */ static int mailimap_body_fld_lines_parse(mailstream * fd, MMAPString * buffer, size_t * index, uint32_t * result) { return mailimap_number_parse(fd, buffer, index, result); } /* body-fld-md5 = nstring */ static int mailimap_body_fld_md5_parse(mailstream * fd, MMAPString * buffer, size_t * index, char ** result, size_t progr_rate, progress_function * progr_fun) { return mailimap_nstring_parse(fd, buffer, index, result, NULL, progr_rate, progr_fun); } /* body-fld-octets = number */ static int mailimap_body_fld_octets_parse(mailstream * fd, MMAPString * buffer, size_t * index, uint32_t * result) { return mailimap_number_parse(fd, buffer, index, result); } /* body-fld-param = "(" string SP string *(SP string SP string) ")" / nil */ /* string SP string */ static int mailimap_single_body_fld_param_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_single_body_fld_param ** result, size_t progr_rate, progress_function * progr_fun) { struct mailimap_single_body_fld_param * param; char * name; char * value; size_t cur_token; int r; int res; cur_token = * index; name = NULL; value = NULL; r = mailimap_string_parse(fd, buffer, &cur_token, &name, NULL, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_space_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_name; } r = mailimap_string_parse(fd, buffer, &cur_token, &value, NULL, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto free_name; } param = mailimap_single_body_fld_param_new(name, value); if (param == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free_value; } * result = param; * index = cur_token; return MAILIMAP_NO_ERROR; free_value: mailimap_string_free(name); free_name: mailimap_string_free(value); err: return res; } /* body-fld-param = "(" string SP string *(SP string SP string) ")" / nil */ static int mailimap_body_fld_param_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_fld_param ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; clist * param_list; struct mailimap_body_fld_param * fld_param; int r; int res; param_list = NULL; cur_token = * index; r = mailimap_nil_parse(fd, buffer, &cur_token); if (r == MAILIMAP_NO_ERROR) { * result = NULL; * index = cur_token; return MAILIMAP_NO_ERROR; } if (r != MAILIMAP_ERROR_PARSE) { res = r; goto err; } r = mailimap_oparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, ¶m_list, (mailimap_struct_parser *) mailimap_single_body_fld_param_parse, (mailimap_struct_destructor *) mailimap_single_body_fld_param_free, progr_rate, progr_fun); if (r != MAILIMAP_NO_ERROR) { res = r; goto err; } r = mailimap_cparenth_parse(fd, buffer, &cur_token); if (r != MAILIMAP_NO_ERROR) { res = r; goto free; } fld_param = mailimap_body_fld_param_new(param_list); if (fld_param == NULL) { res = MAILIMAP_ERROR_MEMORY; goto free; } * index = cur_token; * result = fld_param; return MAILIMAP_NO_ERROR; free: clist_foreach(param_list, (clist_func) mailimap_single_body_fld_param_free, NULL); clist_free(param_list); err: return res; } /* body-type-1part = (body-type-basic / body-type-msg / body-type-text) [SP body-ext-1part] */ static int mailimap_body_type_1part_parse(mailstream * fd, MMAPString * buffer, size_t * index, struct mailimap_body_type_1part ** result, size_t progr_rate, progress_function * progr_fun) { size_t cur_token; struct mailimap_body_type_1part * body_type_1part; struct mailimap_body_type_basic * body_type_basic; struct mailimap_body_type_msg * body_type_msg; struct mailimap_body_type_text * body_type_text; struct mailimap_body_ext_1part * body_ext_1part; int type; size_t final_token; int r; int res; cur_token = * index; body_type_basic = NULL; body_type_msg = NULL; body_type_text = NULL; body_ext_1part = NULL; type = MAILIMAP_BODY_TYPE_1PART_ERROR; /* XXX - removes a gcc warning */ diff --git a/libetpan/src/low-level/maildir/maildir.c b/libetpan/src/low-level/maildir/maildir.c index 98b9f87..e81625d 100644 --- a/libetpan/src/low-level/maildir/maildir.c +++ b/libetpan/src/low-level/maildir/maildir.c @@ -1,534 +1,547 @@ /* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2005 - DINH Viet Hoa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the libEtPan! project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * $Id$ */ #include "maildir.h" #include <string.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <dirent.h> #include <time.h> #include <sys/stat.h> #include <sys/mman.h> #include <errno.h> #include <fcntl.h> #ifdef LIBETPAN_SYSTEM_BASENAME #include <libgen.h> #endif /* We suppose the maildir mailbox remains on one unique filesystem. */ struct maildir * maildir_new(const char * path) { struct maildir * md; md = malloc(sizeof(* md)); if (md == NULL) goto err; md->mdir_counter = 0; md->mdir_mtime_new = (time_t) -1; md->mdir_mtime_cur = (time_t) -1; md->mdir_pid = getpid(); gethostname(md->mdir_hostname, sizeof(md->mdir_hostname)); strncpy(md->mdir_path, path, sizeof(md->mdir_path)); md->mdir_path[PATH_MAX - 1] = '\0'; md->mdir_msg_list = carray_new(128); if (md->mdir_msg_list == NULL) goto free; md->mdir_msg_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE); if (md->mdir_msg_hash == NULL) goto free_msg_list; return md; free_msg_list: carray_free(md->mdir_msg_list); free: free(md); err: return NULL; } static void maildir_flush(struct maildir * md, int msg_new); void maildir_free(struct maildir * md) { maildir_flush(md, 0); maildir_flush(md, 1); chash_free(md->mdir_msg_hash); carray_free(md->mdir_msg_list); free(md); } #define MAX_TRY_ALLOC 32 static char * maildir_get_new_message_filename(struct maildir * md, char * tmpfile) { char filename[PATH_MAX]; char basename[PATH_MAX]; int k; time_t now; + //LR + struct stat f_stat; int got_file; int r; got_file = 0; now = time(NULL); k = 0; while (k < MAX_TRY_ALLOC) { snprintf(basename, sizeof(basename), "%lu.%u_%u.%s", (unsigned long) now, md->mdir_pid, md->mdir_counter, md->mdir_hostname); snprintf(filename, sizeof(filename), "%s/tmp/%s", md->mdir_path, basename); - + + // LR changed following lines + if ( stat( filename, &f_stat ) == -1 ) { + char * dup_filename; + + dup_filename = strdup(filename); + if (dup_filename == NULL) { + //unlink(filename); + return NULL; + } + rename (tmpfile,dup_filename ); +#if 0 if (link(tmpfile, filename) == 0) { got_file = 1; unlink(tmpfile); } else if (errno == EXDEV) { unlink(tmpfile); return NULL; } else if (errno == EPERM) { r = rename(tmpfile, filename); if (r < 0) { unlink(tmpfile); return NULL; } got_file = 1; } if (got_file) { char * dup_filename; dup_filename = strdup(filename); if (dup_filename == NULL) { unlink(filename); return NULL; } - +#endif md->mdir_counter ++; return dup_filename; } md->mdir_counter ++; k ++; } return NULL; } static void msg_free(struct maildir_msg * msg) { free(msg->msg_uid); free(msg->msg_filename); free(msg); } /* msg_new() filename is given without path */ static struct maildir_msg * msg_new(char * filename, int new_msg) { struct maildir_msg * msg; char * p; int flags; size_t uid_len; char * begin_uid; /* name of file : xxx-xxx_xxx-xxx:2,SRFT */ msg = malloc(sizeof(* msg)); if (msg == NULL) goto err; msg->msg_filename = strdup(filename); if (msg->msg_filename == NULL) goto free; begin_uid = filename; uid_len = strlen(begin_uid); flags = 0; p = strstr(filename, ":2,"); if (p != NULL) { uid_len = p - begin_uid; p += 3; /* parse flags */ while (* p != '\0') { switch (* p) { case 'S': flags |= MAILDIR_FLAG_SEEN; break; case 'R': flags |= MAILDIR_FLAG_REPLIED; break; case 'F': flags |= MAILDIR_FLAG_FLAGGED; break; case 'T': flags |= MAILDIR_FLAG_TRASHED; break; } p ++; } } if (new_msg) flags |= MAILDIR_FLAG_NEW; msg->msg_flags = flags; msg->msg_uid = malloc(uid_len + 1); if (msg->msg_uid == NULL) goto free_filename; strncpy(msg->msg_uid, begin_uid, uid_len); msg->msg_uid[uid_len] = '\0'; return msg; free_filename: free(msg->msg_filename); free: free(msg); err: return NULL; } static void maildir_flush(struct maildir * md, int msg_new) { unsigned int i; i = 0; while (i < carray_count(md->mdir_msg_list)) { struct maildir_msg * msg; int delete; msg = carray_get(md->mdir_msg_list, i); if (msg_new) { delete = 0; if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) delete = 1; } else { delete = 1; if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) delete = 0; } if (delete) { chashdatum key; key.data = msg->msg_uid; key.len = strlen(msg->msg_uid); chash_delete(md->mdir_msg_hash, &key, NULL); carray_delete(md->mdir_msg_list, i); msg_free(msg); } else { i ++; } } } static int add_message(struct maildir * md, char * filename, int is_new) { struct maildir_msg * msg; chashdatum key; chashdatum value; unsigned int i; int res; int r; msg = msg_new(filename, is_new); if (msg == NULL) { res = MAILDIR_ERROR_MEMORY; goto err; } r = carray_add(md->mdir_msg_list, msg, &i); if (r < 0) { res = MAILDIR_ERROR_MEMORY; goto free_msg; } key.data = msg->msg_uid; key.len = strlen(msg->msg_uid); value.data = msg; value.len = 0; r = chash_set(md->mdir_msg_hash, &key, &value, NULL); if (r < 0) { res = MAILDIR_ERROR_MEMORY; goto delete; } return MAILDIR_NO_ERROR; delete: carray_delete(md->mdir_msg_list, i); free_msg: msg_free(msg); err: return res; } static int add_directory(struct maildir * md, char * path, int is_new) { DIR * d; struct dirent * entry; int res; int r; #if 0 char filename[PATH_MAX]; #endif d = opendir(path); if (d == NULL) { res = MAILDIR_ERROR_DIRECTORY; goto err; } while ((entry = readdir(d)) != NULL) { #if 0 struct stat stat_info; snprintf(filename, sizeof(filename), "%s/%s", path, entry->d_name); r = stat(filename, &stat_info); if (r < 0) continue; if (S_ISDIR(stat_info.st_mode)) continue; #endif if (entry->d_name[0] == '.') continue; r = add_message(md, entry->d_name, is_new); if (r != MAILDIR_NO_ERROR) { /* ignore errors */ } } closedir(d); return MAILDIR_NO_ERROR; err: return res; } int maildir_update(struct maildir * md) { struct stat stat_info; char path_new[PATH_MAX]; char path_cur[PATH_MAX]; char path_maildirfolder[PATH_MAX]; int r; int res; int changed; snprintf(path_new, sizeof(path_new), "%s/new", md->mdir_path); snprintf(path_cur, sizeof(path_cur), "%s/cur", md->mdir_path); changed = 0; /* did new/ changed ? */ r = stat(path_new, &stat_info); if (r < 0) { res = MAILDIR_ERROR_DIRECTORY; goto free; } if (md->mdir_mtime_new != stat_info.st_mtime) { md->mdir_mtime_new = stat_info.st_mtime; changed = 1; } /* did cur/ changed ? */ r = stat(path_cur, &stat_info); if (r < 0) { res = MAILDIR_ERROR_DIRECTORY; goto free; } if (md->mdir_mtime_cur != stat_info.st_mtime) { md->mdir_mtime_cur = stat_info.st_mtime; changed = 1; } if (changed) { carray_set_size(md->mdir_msg_list, 0); chash_clear(md->mdir_msg_hash); maildir_flush(md, 1); /* messages in new */ r = add_directory(md, path_new, 1); if (r != MAILDIR_NO_ERROR) { res = r; goto free; } maildir_flush(md, 0); /* messages in cur */ r = add_directory(md, path_cur, 0); if (r != MAILDIR_NO_ERROR) { res = r; goto free; } } snprintf(path_maildirfolder, sizeof(path_maildirfolder), "%s/maildirfolder", md->mdir_path); if (stat(path_maildirfolder, &stat_info) == -1) { int fd; fd = creat(path_maildirfolder, S_IRUSR | S_IWUSR); if (fd != -1) close(fd); } return MAILDIR_NO_ERROR; free: maildir_flush(md, 0); maildir_flush(md, 1); md->mdir_mtime_cur = (time_t) -1; md->mdir_mtime_new = (time_t) -1; return res; } #ifndef LIBETPAN_SYSTEM_BASENAME static char * libetpan_basename(char * filename) { char * next; char * p; p = filename; next = strchr(p, '/'); while (next != NULL) { p = next; next = strchr(p + 1, '/'); } if (p == filename) return filename; else return p + 1; } #else #define libetpan_basename(a) basename(a) #endif int maildir_message_add_uid(struct maildir * md, const char * message, size_t size, char * uid, size_t max_uid_len) { char path_new[PATH_MAX]; char tmpname[PATH_MAX]; int fd; int r; char * mapping; char * delivery_tmp_name; char * delivery_tmp_basename; char delivery_new_name[PATH_MAX]; char * delivery_new_basename; int res; struct stat stat_info; r = maildir_update(md); if (r != MAILDIR_NO_ERROR) { res = r; goto err; } /* write to tmp/ with a classic temporary file */ snprintf(tmpname, sizeof(tmpname), "%s/tmp/etpan-maildir-XXXXXX", md->mdir_path); fd = mkstemp(tmpname); if (fd < 0) { res = MAILDIR_ERROR_FILE; goto err; } r = ftruncate(fd, size); if (r < 0) { res = MAILDIR_ERROR_FILE; goto close; } mapping = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (mapping == MAP_FAILED) { res = MAILDIR_ERROR_FILE; goto close; } memcpy(mapping, message, size); msync(mapping, size, MS_SYNC); munmap(mapping, size); close(fd); diff --git a/libetpan/src/low-level/mh/mailmh.c b/libetpan/src/low-level/mh/mailmh.c index 42cab9d..f8c694d 100644 --- a/libetpan/src/low-level/mh/mailmh.c +++ b/libetpan/src/low-level/mh/mailmh.c @@ -539,451 +539,454 @@ int mailmh_folder_remove_subfolder(struct mailmh_folder * folder) key.data = folder->fl_filename; key.len = strlen(folder->fl_filename); r = chash_get(parent->fl_subfolders_hash, &key, &data); if (r < 0) return MAILMH_ERROR_FOLDER; chash_delete(parent->fl_subfolders_hash, &key, NULL); carray_delete_fast(parent->fl_subfolders_tab, folder->fl_array_index); mailmh_folder_free(folder); return MAILMH_NO_ERROR; } int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder, struct mailmh_folder * dst_folder, const char * new_name) { int r; struct mailmh_folder * folder; struct mailmh_folder * parent; char * new_foldername; parent = src_folder->fl_parent; if (parent == NULL) return MAILMH_ERROR_RENAME; new_foldername = malloc(strlen(dst_folder->fl_filename) + 2 + strlen(new_name)); if (new_foldername == NULL) return MAILMH_ERROR_MEMORY; strcpy(new_foldername, dst_folder->fl_filename); strcat(new_foldername, MAIL_DIR_SEPARATOR_S); strcat(new_foldername, new_name); r = rename(src_folder->fl_filename, new_foldername); free(new_foldername); if (r < 0) return MAILMH_ERROR_RENAME; r = mailmh_folder_remove_subfolder(src_folder); if (r != MAILMH_NO_ERROR) return r; folder = mailmh_folder_new(dst_folder, new_name); if (folder == NULL) return MAILMH_ERROR_MEMORY; r = carray_add(parent->fl_subfolders_tab, folder, NULL); if (r < 0) { mailmh_folder_free(folder); return MAILMH_ERROR_MEMORY; } return MAILMH_NO_ERROR; } #define MAX_TRY_ALLOC 32 /* initial file MUST be in the same directory */ static int mailmh_folder_alloc_msg(struct mailmh_folder * folder, char * filename, uint32_t * result) { uint32_t max; uint32_t k; char * new_filename; size_t len; int got_file; int r; len = strlen(folder->fl_filename) + 20; new_filename = malloc(len); if (new_filename == NULL) return MAILMH_ERROR_MEMORY; max = folder->fl_max_index + 1; got_file = 0; k = 0; while (k < MAX_TRY_ALLOC) { snprintf(new_filename, len, "%s%c%lu", folder->fl_filename, MAIL_DIR_SEPARATOR, (unsigned long) (max + k)); if (link(filename, new_filename) == 0) { unlink(filename); } else if (errno == EXDEV) { free(filename); return MAILMH_ERROR_FOLDER; } else if (errno == EPERM) { rename(filename, new_filename); got_file = 1; } if (got_file) { free(new_filename); if (k > MAX_TRY_ALLOC / 2) { r = mailmh_folder_update(folder); /* ignore errors */ } * result = max + k; folder->fl_max_index = max + k; return MAILMH_NO_ERROR; } k ++; } free(new_filename); return MAILMH_ERROR_FOLDER; } int mailmh_folder_get_message_filename(struct mailmh_folder * folder, uint32_t index, char ** result) { char * filename; int len; #if 0 r = mailmh_folder_update(folder); if (r != MAILMH_NO_ERROR) return r; #endif len = strlen(folder->fl_filename) + 20; filename = malloc(len); if (filename == NULL) return MAILMH_ERROR_MEMORY; snprintf(filename, len, "%s%c%lu", folder->fl_filename, MAIL_DIR_SEPARATOR, (unsigned long) index); * result = filename; return MAILMH_NO_ERROR;; } int mailmh_folder_get_message_fd(struct mailmh_folder * folder, uint32_t index, int flags, int * result) { char * filename; int fd; int r; #if 0 r = mailmh_folder_update(folder); if (r != MAILMH_NO_ERROR) return r; #endif r = mailmh_folder_get_message_filename(folder, index, &filename); if (r != MAILMH_NO_ERROR) return r; fd = open(filename, flags); free(filename); if (fd == -1) return MAILMH_ERROR_MSG_NOT_FOUND; * result = fd; return MAILMH_NO_ERROR; } int mailmh_folder_get_message_size(struct mailmh_folder * folder, uint32_t index, size_t * result) { int r; char * filename; struct stat buf; r = mailmh_folder_get_message_filename(folder, index, &filename); if (r != MAILMH_NO_ERROR) return r; r = stat(filename, &buf); free(filename); if (r < 0) return MAILMH_ERROR_FILE; * result = buf.st_size; return MAILMH_NO_ERROR; } int mailmh_folder_add_message_uid(struct mailmh_folder * folder, const char * message, size_t size, uint32_t * pindex) { char * tmpname; int fd; size_t namesize; size_t left; ssize_t res; struct mailmh_msg_info * msg_info; uint32_t index; int error; int r; unsigned int array_index; struct stat buf; chashdatum key; chashdatum data; #if 0 r = mailmh_folder_update(folder); if (r != MAILMH_NO_ERROR) { error = r; goto err; } #endif namesize = strlen(folder->fl_filename) + 20; tmpname = malloc(namesize); snprintf(tmpname, namesize, "%s%ctmpXXXXXX", folder->fl_filename, MAIL_DIR_SEPARATOR); fd = mkstemp(tmpname); if (fd < 0) { error = MAILMH_ERROR_FILE; goto free; } left = size; while (left > 0) { res = write(fd, message, left); if (res == -1) { close(fd); error = MAILMH_ERROR_FILE; goto free; } left -= res; } close(fd); r = stat(tmpname, &buf); if (r < 0) { error = MAILMH_ERROR_FILE; goto free; } r = mailmh_folder_alloc_msg(folder, tmpname, &index); if (r != MAILMH_NO_ERROR) { unlink(tmpname); error = MAILMH_ERROR_COULD_NOT_ALLOC_MSG; goto free; } free(tmpname); msg_info = mailmh_msg_info_new(index, size, buf.st_mtime); if (msg_info == NULL) { mailmh_folder_remove_message(folder, index); error = MAILMH_ERROR_MEMORY; goto err; } r = carray_add(folder->fl_msgs_tab, msg_info, &array_index); if (r < 0) { mailmh_folder_remove_message(folder, index); mailmh_msg_info_free(msg_info); error = MAILMH_ERROR_MEMORY; goto err; } msg_info->msg_array_index = array_index; #if 0 r = cinthash_add(folder->fl_msgs_hash, index, msg_info); #endif key.data = &index; key.len = sizeof(index); data.data = msg_info; data.len = 0; if (pindex != NULL) * pindex = index; r = chash_set(folder->fl_msgs_hash, &key, &data, NULL); if (r < 0) { carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); mailmh_msg_info_free(msg_info); error = MAILMH_ERROR_MEMORY; goto err; } return MAILMH_NO_ERROR; free: free(tmpname); err: return error; } int mailmh_folder_add_message(struct mailmh_folder * folder, const char * message, size_t size) { return mailmh_folder_add_message_uid(folder, message, size, NULL); } int mailmh_folder_add_message_file_uid(struct mailmh_folder * folder, int fd, uint32_t * pindex) { char * message; struct stat buf; int r; #if 0 r = mailmh_folder_update(folder); if (r != MAILMH_NO_ERROR) return r; #endif if (fstat(fd, &buf) == -1) return MAILMH_ERROR_FILE; message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (message == MAP_FAILED) return MAILMH_ERROR_FILE; r = mailmh_folder_add_message_uid(folder, message, buf.st_size, pindex); munmap(message, buf.st_size); return r; } int mailmh_folder_add_message_file(struct mailmh_folder * folder, int fd) { return mailmh_folder_add_message_file_uid(folder, fd, NULL); } int mailmh_folder_remove_message(struct mailmh_folder * folder, uint32_t index) { char * filename; struct mailmh_msg_info * msg_info; int res; int r; chashdatum key; chashdatum data; #if 0 r = mailmh_folder_update(folder); if (r != MAILMH_NO_ERROR) { res = r; goto err; } #endif r = mailmh_folder_get_message_filename(folder, index, &filename); if (filename == NULL) { res = r; goto err; } if (unlink(filename) == -1) { res = MAILMH_ERROR_FILE; goto free; } key.data = &index; key.len = sizeof(index); r = chash_get(folder->fl_msgs_hash, &key, &data); #if 0 msg_info = cinthash_find(folder->fl_msgs_hash, index); #endif if (r == 0) { msg_info = data.data; carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); #if 0 cinthash_remove(folder->fl_msgs_hash, index); #endif chash_delete(folder->fl_msgs_hash, &key, NULL); } + // LR memory leak fixed + mailmh_msg_info_free( msg_info ); + free(filename); return MAILMH_NO_ERROR; free: free(filename); err: return res; } int mailmh_folder_move_message(struct mailmh_folder * dest_folder, struct mailmh_folder * src_folder, uint32_t index) { int fd; char * filename; int r; #if 0 r = mailmh_folder_update(dest_folder); if (r != MAILMH_NO_ERROR) return r; r = mailmh_folder_update(src_folder); if (r != MAILMH_NO_ERROR) return r; #endif /* move on the same filesystem */ r = mailmh_folder_get_message_filename(src_folder, index, &filename); if (r != MAILMH_NO_ERROR) return r; r = mailmh_folder_alloc_msg(dest_folder, filename, &index); free(filename); if (r == MAILMH_NO_ERROR) return MAILMH_NO_ERROR; /* move on the different filesystems */ r = mailmh_folder_get_message_fd(src_folder, index, O_RDONLY, &fd); if (r != MAILMH_NO_ERROR) return r; r = mailmh_folder_add_message_file(dest_folder, fd); if (r != MAILMH_NO_ERROR) { close(fd); return r; } close(fd); r = mailmh_folder_remove_message(src_folder, index); return MAILMH_NO_ERROR; } unsigned int mailmh_folder_get_message_number(struct mailmh_folder * folder) { unsigned int i; unsigned int count; count = 0; for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) if (carray_get(folder->fl_msgs_tab, i) != NULL) count ++; return count; } diff --git a/libetpan/src/low-level/pop3/mailpop3.c b/libetpan/src/low-level/pop3/mailpop3.c index 6f77a3a..bca62d5 100644 --- a/libetpan/src/low-level/pop3/mailpop3.c +++ b/libetpan/src/low-level/pop3/mailpop3.c @@ -127,770 +127,773 @@ mailpop3_msg_info_tab_find_msg(carray * msg_tab, unsigned int index) 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; + 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, unsigned int 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; } |