#include <ctype.h>
#include <unistd.h>
#include <time.h>
+#include <errno.h>
#include "intl.h"
#include "pop.h"
{
Pop3State *state = (Pop3State *)data;
gchar buf[POPBUFSIZE];
+ gint ok;
- if (pop3_ok(sock, buf) == PS_SUCCESS) {
+ if ((ok = pop3_ok(sock, buf)) == PS_SUCCESS) {
state->greeting = g_strdup(buf);
#if USE_SSL
if (state->ac_prefs->ssl_pop == SSL_STARTTLS)
else
return POP3_GETAUTH_USER_SEND;
} else {
- state->inc_state = INC_ERROR;
+ state->error_val = ok;
return -1;
}
}
if ((ok = pop3_ok(sock, NULL)) == PS_SUCCESS) {
if (!ssl_init_socket_with_method(sock, SSL_METHOD_TLSv1)) {
state->error_val = PS_SOCKET;
- state->inc_state = INC_ERROR;
return -1;
}
if (state->ac_prefs->protocol == A_APOP)
return POP3_GETAUTH_USER_SEND;
} else if (ok == PS_PROTOCOL) {
log_warning(_("can't start TLS session\n"));
- state->error_val = PS_PROTOCOL;
- state->inc_state = INC_ERROR;
+ state->error_val = ok;
return POP3_LOGOUT_SEND;
} else {
- state->inc_state = INC_ERROR;
+ state->error_val = ok;
return -1;
}
}
else {
log_warning(_("error occurred on authentication\n"));
state->error_val = PS_AUTHFAIL;
- state->inc_state = INC_AUTH_FAILED;
return -1;
}
}
gint pop3_getauth_pass_recv(SockInfo *sock, gpointer data)
{
Pop3State *state = (Pop3State *)data;
+ gint ok;
- if (pop3_ok(sock, NULL) == PS_SUCCESS)
+ if ((ok = pop3_ok(sock, NULL)) == PS_SUCCESS)
return POP3_GETRANGE_STAT_SEND;
- else {
+ else if (ok == PS_LOCKBUSY) {
+ log_warning(_("mailbox is locked\n"));
+ state->error_val = ok;
+ return -1;
+ } else {
log_warning(_("error occurred on authentication\n"));
state->error_val = PS_AUTHFAIL;
- state->inc_state = INC_AUTH_FAILED;
return -1;
}
}
log_warning(_("Required APOP timestamp not found "
"in greeting\n"));
state->error_val = PS_PROTOCOL;
- state->inc_state = INC_ERROR;
return -1;
}
if ((end = strchr(start, '>')) == NULL || end == start + 1) {
log_warning(_("Timestamp syntax error in greeting\n"));
state->error_val = PS_PROTOCOL;
- state->inc_state = INC_ERROR;
return -1;
}
gint pop3_getauth_apop_recv(SockInfo *sock, gpointer data)
{
Pop3State *state = (Pop3State *)data;
+ gint ok;
- if (pop3_ok(sock, NULL) == PS_SUCCESS)
+ if ((ok = pop3_ok(sock, NULL)) == PS_SUCCESS)
return POP3_GETRANGE_STAT_SEND;
- else {
+ else if (ok == PS_LOCKBUSY) {
+ log_warning(_("mailbox is locked\n"));
+ state->error_val = ok;
+ return -1;
+ } else {
log_warning(_("error occurred on authentication\n"));
state->error_val = PS_AUTHFAIL;
- state->inc_state = INC_AUTH_FAILED;
return -1;
}
}
!= 2) {
log_warning(_("POP3 protocol error\n"));
state->error_val = PS_PROTOCOL;
- state->inc_state = INC_ERROR;
return -1;
} else {
if (state->count == 0) {
}
}
} else if (ok == PS_PROTOCOL) {
+ state->error_val = ok;
return POP3_LOGOUT_SEND;
} else {
- state->inc_state = INC_ERROR;
+ state->error_val = ok;
return -1;
}
}
if (sscanf(buf, "%d", &last) == 0) {
log_warning(_("POP3 protocol error\n"));
state->error_val = PS_PROTOCOL;
- state->inc_state = INC_ERROR;
return -1;
} else {
if (state->count == last)
if (len < 0) {
log_error(_("Socket error\n"));
state->error_val = PS_SOCKET;
- state->inc_state = INC_ERROR;
return -1;
}
if (buf[0] == '.') break;
if (sscanf(buf, "%u %u", &num, &size) != 2) {
state->error_val = PS_PROTOCOL;
- state->inc_state = INC_ERROR;
return -1;
}
if (len < 0) {
log_error(_("Socket error\n"));
state->error_val = PS_SOCKET;
- state->inc_state = INC_ERROR;
return -1;
}
filename = g_strdup_printf("%s%i", path, state->cur_msg);
if (recv_write_to_file(sock, filename) < 0) {
- state->inc_state = INC_NOSPACE;
+ state->error_val = PS_IOERR;
return -1;
}
file = get_tmp_file();
if (recv_write_to_file(sock, file) < 0) {
g_free(file);
- if (state->inc_state == INC_SUCCESS)
- state->inc_state = INC_NOSPACE;
+ if (!state->cancelled)
+ state->error_val = PS_IOERR;
return -1;
}
drop_ok = inc_drop_message(file, state);
g_free(file);
if (drop_ok < 0) {
- state->inc_state = INC_ERROR;
+ state->error_val = PS_ERROR;
return -1;
}
} else
return POP3_LOGOUT_SEND;
} else if (ok == PS_PROTOCOL) {
+ state->error_val = ok;
return POP3_LOGOUT_SEND;
} else {
- state->inc_state = INC_ERROR;
+ state->error_val = ok;
return -1;
}
}
} else
return POP3_LOGOUT_SEND;
} else if (ok == PS_PROTOCOL) {
+ state->error_val = ok;
return POP3_LOGOUT_SEND;
} else {
- state->inc_state = INC_ERROR;
+ state->error_val = ok;
return -1;
}
}
gint pop3_logout_recv(SockInfo *sock, gpointer data)
{
Pop3State *state = (Pop3State *)data;
+ gint ok;
- if (pop3_ok(sock, NULL) != PS_SUCCESS)
- state->inc_state = INC_ERROR;
+ if ((ok = pop3_ok(sock, NULL)) != PS_SUCCESS)
+ state->error_val = ok;
return -1;
}
switch (cur_state) {
case POP3_GETRANGE_UIDL_RECV:
switch (session) {
+ case STYPE_POP_BEFORE_SMTP:
+ goto_state = POP3_LOGOUT_SEND;
+ break;
case STYPE_DOWNLOAD:
case STYPE_DELETE:
case STYPE_PREVIEW_ALL:
return FALSE;
}
}
+
+Pop3State *pop3_state_new(PrefsAccount *account)
+{
+ Pop3State *state;
+
+ g_return_val_if_fail(account != NULL, NULL);
+
+ state = g_new0(Pop3State, 1);
+
+ state->ac_prefs = account;
+ state->uidl_table = pop3_get_uidl_table(account);
+ state->current_time = time(NULL);
+ state->error_val = PS_SUCCESS;
+
+ return state;
+}
+
+void pop3_state_destroy(Pop3State *state)
+{
+ gint n;
+
+ g_return_if_fail(state != NULL);
+
+ for (n = 1; n <= state->count; n++)
+ g_free(state->msg[n].uidl);
+ g_free(state->msg);
+
+ if (state->uidl_table) {
+ hash_free_strings(state->uidl_table);
+ g_hash_table_destroy(state->uidl_table);
+ }
+
+ g_free(state->greeting);
+ g_free(state->user);
+ g_free(state->pass);
+ g_free(state->prev_folder);
+
+ g_free(state);
+}
+
+GHashTable *pop3_get_uidl_table(PrefsAccount *ac_prefs)
+{
+ GHashTable *table;
+ gchar *path;
+ FILE *fp;
+ gchar buf[IDLEN + 3];
+ gchar uidl[IDLEN + 3];
+ time_t recv_time;
+ time_t now;
+
+ path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+ "uidl", G_DIR_SEPARATOR_S, ac_prefs->recv_server,
+ "-", ac_prefs->userid, NULL);
+ if ((fp = fopen(path, "rb")) == NULL) {
+ if (ENOENT != errno) FILE_OP_ERROR(path, "fopen");
+ g_free(path);
+ path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+ "uidl-", ac_prefs->recv_server,
+ "-", ac_prefs->userid, NULL);
+ if ((fp = fopen(path, "rb")) == NULL) {
+ if (ENOENT != errno) FILE_OP_ERROR(path, "fopen");
+ g_free(path);
+ return NULL;
+ }
+ }
+ g_free(path);
+
+ table = g_hash_table_new(g_str_hash, g_str_equal);
+
+ now = time(NULL);
+
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ strretchomp(buf);
+ recv_time = 0;
+ if (sscanf(buf, "%s\t%ld", uidl, &recv_time) != 2) {
+ if (sscanf(buf, "%s", uidl) != 1)
+ continue;
+ else
+ recv_time = now;
+ }
+ if (recv_time == 0)
+ recv_time = 1;
+ g_hash_table_insert(table, g_strdup(uidl),
+ GINT_TO_POINTER(recv_time));
+ }
+
+ fclose(fp);
+ return table;
+}
+
+gint pop3_write_uidl_list(Pop3State *state)
+{
+ gchar *path;
+ FILE *fp;
+ Pop3MsgInfo *msg;
+ gint n;
+
+ if (!state->uidl_is_valid) return 0;
+
+ path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
+ "uidl", G_DIR_SEPARATOR_S,
+ state->ac_prefs->recv_server,
+ "-", state->ac_prefs->userid, NULL);
+ if ((fp = fopen(path, "wb")) == NULL) {
+ FILE_OP_ERROR(path, "fopen");
+ g_free(path);
+ return -1;
+ }
+
+ for (n = 1; n <= state->count; n++) {
+ msg = &state->msg[n];
+ if (msg->uidl && msg->received && !msg->deleted)
+ fprintf(fp, "%s\t%ld\n", msg->uidl, msg->recv_time);
+ }
+
+ if (fclose(fp) == EOF) FILE_OP_ERROR(path, "fclose");
+ g_free(path);
+
+ return 0;
+}