summaryrefslogtreecommitdiffabout
path: root/kmicromail/libetpan/pop3/mailpop3.c
Side-by-side diff
Diffstat (limited to 'kmicromail/libetpan/pop3/mailpop3.c') (more/less context) (ignore whitespace changes)
-rw-r--r--kmicromail/libetpan/pop3/mailpop3.c5
1 files changed, 4 insertions, 1 deletions
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
@@ -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)
+ 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;
}