+2002-08-30
+
+ * major refactoring for POP3.
+ * src/inc.[ch]: moved Pop3State, inc_pop3_state_new(),
+ inc_pop3_state_destroy(), inc_get_uidl_table(), and
+ inc_write_uidl_list() into pop.c.
+ Moved Pop3State::folder_table and Pop3State::inc_state into
+ IncSession.
+ inc_start()
+ inc_put_error(): added lockbusy state.
+ inc_pop3_session_do(): obtain inc_state from Pop3State::error_val.
+ inc_cancel(): don't terminate the automaton here but just set
+ the flags to prevent crash.
+ * src/pop.[ch]
+ pop3_getauth_pass_recv()
+ pop3_getauth_apop_recv(): check lockbusy state.
+ pop3_retr_recv(): check Pop3State::cancelled flag.
+ * src/automaton.[ch]: added 'cancelled' flag to Automaton.
+ automaton_input_cb(): terminate if cancelled flag is true.
+ * sylpheed.desktop: changed Type=Internet to Type=Application.
+ Added Categories=Application;Network;.
+
2002-08-29
* src/inc.[ch]
-2002-08-30 [alfons] 0.8.2claws16
+2002-08-31 [paul] 0.8.2claws17
+
+ * sync with 0.8.2cvs6
+ see ChangeLog 2002-08-30
+
+2002-08-31 [alfons] 0.8.2claws16
* src/folder.c
folder_destroy(): remove mailbox from folderlist even if it has
no destroy virtual
-2002-08-30 [alfons] 0.8.2claws15
+2002-08-31 [alfons] 0.8.2claws15
* src/folder.c
:%sno/if(/if (/gc
:%sno/for(/for (/gc
(being pedantic I know)
-2002-08-30 [alfons] 0.8.2claws14
+2002-08-31 [alfons] 0.8.2claws14
* src/folder.c
check for NULL pointers returned from folder->fetch_msginfo virtual
+2002-08-30
+
+ * ¼çÍ×¤Ê POP3 ¤Î¥ê¥Õ¥¡¥¯¥¿¥ê¥ó¥°¡£
+ * src/inc.[ch]: Pop3State, inc_pop3_state_new(),
+ inc_pop3_state_destroy(), inc_get_uidl_table(), ¤½¤·¤Æ
+ inc_write_uidl_list() ¤ò pop.c ¤Ë°Üư¡£
+ Pop3State::folder_table ¤È Pop3State::inc_state ¤ò IncSession
+ ¤Ë°Üư¡£
+ inc_start()
+ inc_put_error(): lockbusy ¾õÂÖ¤òÄɲá£
+ inc_pop3_session_do(): inc_state ¤ò Pop3State::error_val ¤«¤éÆÀ¤ë
+ ¤è¤¦¤Ë¤·¤¿¡£
+ inc_cancel(): ¤³¤³¤Ç automaton ¤ò terminate ¤»¤º¤Ë¥Õ¥é¥°¤ò¥»¥Ã¥È
+ ¤¹¤ë¤À¤±¤Ë¤·¤Æ¥¯¥é¥Ã¥·¥å¤ò²óÈò¡£
+ * src/pop.[ch]
+ pop3_getauth_pass_recv()
+ pop3_getauth_apop_recv(): lockbusy ¾õÂÖ¤ò¥Á¥§¥Ã¥¯¡£
+ pop3_retr_recv(): Pop3State::cancelled ¥Õ¥é¥°¤ò¥Á¥§¥Ã¥¯¡£
+ * src/automaton.[ch]: Automaton ¤Ë 'cancelled' ¥Õ¥é¥°¤òÄɲá£
+ automaton_input_cb(): cancelled ¥Õ¥é¥°¤¬¿¿¤Î¾ì¹ç terminate ¡£
+ * sylpheed.desktop: Type=Internet ¤ò Type=Application ¤Ë½¤Àµ¡£
+ Categories=Application;Network; ¤òÄɲá£
+
2002-08-29
* src/inc.[ch]
MICRO_VERSION=2
INTERFACE_AGE=0
BINARY_AGE=0
-EXTRA_VERSION=claws16
+EXTRA_VERSION=claws17
VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION$EXTRA_VERSION
dnl set $target
* passed file descriptor because we can't map that one back
* to the sockinfo */
sock = atm->help_sock;
- g_assert(sock->sock == dummy_source);
+ g_return_if_fail(sock->sock == dummy_source);
if (atm->timeout_tag > 0) {
gtk_timeout_remove(atm->timeout_tag);
gdk_input_remove(atm->tag);
atm->tag = 0;
+ if (atm->cancelled) {
+ atm->terminate(sock, data);
+ return;
+ }
+
if (atm->ui_func)
atm->ui_func(atm->data, atm->num);
next = atm->state[atm->num].handler(sock, atm->data);
if (atm->terminated)
return;
+ if (atm->cancelled) {
+ atm->terminate(sock, data);
+ return;
+ }
if (next >= 0 && next <= atm->max && next != atm->num) {
atm->num = next;
gint tag;
guint timeout_tag;
guint elapsed;
+ gboolean cancelled;
gboolean terminated;
gpointer data;
static IncSession *inc_session_new (PrefsAccount *account);
static void inc_session_destroy (IncSession *session);
-static Pop3State *inc_pop3_state_new (PrefsAccount *account);
-static void inc_pop3_state_destroy (Pop3State *state);
static gint inc_start (IncProgressDialog *inc_dialog);
static IncState inc_pop3_session_do (IncSession *session);
static gint pop3_automaton_terminate (SockInfo *source,
Automaton *atm);
-static GHashTable *inc_get_uidl_table (PrefsAccount *ac_prefs);
-static void inc_write_uidl_list (Pop3State *state);
-
static gboolean inc_pop3_recv_func (SockInfo *sock,
gint count,
gint read_bytes,
return NULL;
session = g_new0(IncSession, 1);
- session->pop3_state = inc_pop3_state_new(account);
- session->pop3_state->session = session;
+ session->pop3_state = pop3_state_new(account);
+ session->pop3_state->data = session;
+ session->folder_table = g_hash_table_new(NULL, NULL);
return session;
}
{
g_return_if_fail(session != NULL);
- inc_pop3_state_destroy(session->pop3_state);
+ pop3_state_destroy(session->pop3_state);
+ g_hash_table_destroy(session->folder_table);
g_free(session);
}
-static Pop3State *inc_pop3_state_new(PrefsAccount *account)
-{
- Pop3State *state;
-
- state = g_new0(Pop3State, 1);
-
- state->ac_prefs = account;
- state->folder_table = g_hash_table_new(NULL, NULL);
- state->uidl_todelete_list = NULL;
- state->uidl_table = inc_get_uidl_table(account);
- state->inc_state = INC_SUCCESS;
- state->current_time = time(NULL);
-
- return state;
-}
-
-static void inc_pop3_state_destroy(Pop3State *state)
-{
- gint n;
-
- g_hash_table_destroy(state->folder_table);
-
- 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_slist_free(state->uidl_todelete_list);
- g_free(state->greeting);
- g_free(state->user);
- g_free(state->pass);
- g_free(state->prev_folder);
-
- g_free(state);
-}
-
static gint inc_start(IncProgressDialog *inc_dialog)
{
IncSession *session;
gint num = 0;
gint error_num = 0;
gint new_msgs = 0;
+ gchar *msg;
gchar *fin_msg;
while (inc_dialog->queue_list != NULL) {
/* begin POP3 session */
inc_state = inc_pop3_session_do(session);
- if (inc_state == INC_SUCCESS) {
- gchar *msg;
-
+ switch (inc_state) {
+ case INC_SUCCESS:
if (pop3_state->cur_total_num > 0)
msg = g_strdup_printf
(_("Done (%d message(s) (%s) received)"),
gtk_clist_set_pixmap(clist, num, 0, okxpm, okxpmmask);
gtk_clist_set_text(clist, num, 2, msg);
g_free(msg);
- } else if (inc_state == INC_CANCEL) {
+ break;
+ case INC_CONNECT_ERROR:
+ gtk_clist_set_pixmap(clist, num, 0, errorxpm, errorxpmmask);
+ gtk_clist_set_text(clist, num, 2, _("Connection failed"));
+ break;
+ case INC_AUTH_FAILED:
+ gtk_clist_set_pixmap(clist, num, 0, errorxpm, errorxpmmask);
+ gtk_clist_set_text(clist, num, 2, _("Auth failed"));
+ break;
+ case INC_LOCKED:
+ gtk_clist_set_pixmap(clist, num, 0, errorxpm, errorxpmmask);
+ gtk_clist_set_text(clist, num, 2, _("Locked"));
+ break;
+ case INC_ERROR:
+ case INC_NOSPACE:
+ gtk_clist_set_pixmap(clist, num, 0, errorxpm, errorxpmmask);
+ gtk_clist_set_text(clist, num, 2, _("Error"));
+ break;
+ case INC_CANCEL:
gtk_clist_set_pixmap(clist, num, 0, okxpm, okxpmmask);
gtk_clist_set_text(clist, num, 2, _("Cancelled"));
- } else {
- gtk_clist_set_pixmap(clist, num, 0, errorxpm, errorxpmmask);
- if (inc_state == INC_CONNECT_ERROR)
- gtk_clist_set_text(clist, num, 2,
- _("Connection failed"));
- else if (inc_state == INC_AUTH_FAILED)
- gtk_clist_set_text(clist, num, 2,
- _("Auth failed"));
- else
- gtk_clist_set_text(clist, num, 2, _("Error"));
+ break;
+ default:
+ break;
}
-
+
if (pop3_state->error_val == PS_AUTHFAIL) {
if(!prefs_common.no_recv_err_panel) {
if((prefs_common.recv_dialog_mode == RECV_DIALOG_ALWAYS) ||
/* filter if enabled in prefs or move to inbox if not */
if(pop3_state->ac_prefs->filter_on_recv) {
filter_message_by_msginfo_with_inbox(global_processing, msginfo,
- pop3_state->folder_table,
+ session->folder_table,
inbox);
} else {
folder_item_move_msg(inbox, msginfo);
- g_hash_table_insert(pop3_state->folder_table, inbox,
+ g_hash_table_insert(session->folder_table, inbox,
GINT_TO_POINTER(1));
}
procmsg_msginfo_free(msginfo);
new_msgs += pop3_state->cur_total_num;
- folderview_update_item_foreach
- (pop3_state->folder_table, TRUE);
+ if (!prefs_common.scan_all_after_inc) {
+ folder_item_scan_foreach(session->folder_table);
+ folderview_update_item_foreach
+ (session->folder_table, TRUE);
+ }
if (pop3_state->error_val == PS_AUTHFAIL &&
pop3_state->ac_prefs->tmp_pass) {
pop3_state->ac_prefs->tmp_pass = NULL;
}
- inc_write_uidl_list(pop3_state);
+ pop3_write_uidl_list(pop3_state);
if (inc_state != INC_SUCCESS && inc_state != INC_CANCEL) {
error_num++;
}
pop3_automaton_terminate(NULL, atm);
automaton_destroy(atm);
+ session->inc_state = INC_CONNECT_ERROR;
return INC_CONNECT_ERROR;
}
!ssl_init_socket(sockinfo)) {
pop3_automaton_terminate(NULL, atm);
automaton_destroy(atm);
+ session->inc_state = INC_CONNECT_ERROR;
return INC_CONNECT_ERROR;
}
#endif
automaton_destroy(atm);
- return pop3_state->inc_state;
+ if (session->inc_state != INC_SUCCESS)
+ return session->inc_state;
+
+ switch (pop3_state->error_val) {
+ case PS_SUCCESS:
+ session->inc_state = INC_SUCCESS;
+ break;
+ case PS_AUTHFAIL:
+ session->inc_state = INC_AUTH_FAILED;
+ break;
+ case PS_IOERR:
+ session->inc_state = INC_NOSPACE;
+ break;
+ case PS_LOCKBUSY:
+ session->inc_state = INC_LOCKED;
+ break;
+ default:
+ session->inc_state = INC_ERROR;
+ break;
+ }
+
+ return session->inc_state;
}
static gint pop3_automaton_terminate(SockInfo *source, Automaton *atm)
return 0;
}
-static GHashTable *inc_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;
-}
-
-static void inc_write_uidl_list(Pop3State *state)
-{
- gchar *path;
- FILE *fp;
- Pop3MsgInfo *msg;
- gint n;
-
- if (!state->uidl_is_valid) return;
-
- 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;
- }
-
- 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);
-}
-
static gboolean inc_pop3_recv_func(SockInfo *sock, gint count, gint read_bytes,
gpointer data)
{
gchar buf[MSGBUFSIZE];
IncSession *session = (IncSession *)data;
Pop3State *state = session->pop3_state;
- IncProgressDialog *inc_dialog = session->data;
+ IncProgressDialog *inc_dialog = (IncProgressDialog *)session->data;
ProgressDialog *dialog = inc_dialog->dialog;
gint cur_total;
gchar *total_size;
(gfloat)cur_total / (gfloat)state->total_bytes);
GTK_EVENTS_FLUSH();
- if (state->inc_state == INC_CANCEL)
+ if (session->inc_state == INC_CANCEL)
return FALSE;
else
return TRUE;
void inc_progress_update(Pop3State *state, Pop3Phase phase)
{
gchar buf[MSGBUFSIZE];
- IncProgressDialog *inc_dialog = state->session->data;
+ IncSession *session = (IncSession *)state->data;
+ IncProgressDialog *inc_dialog = (IncProgressDialog *)session->data;
ProgressDialog *dialog = inc_dialog->dialog;
gchar *total_size;
{
FolderItem *inbox;
FolderItem *dropfolder;
+ IncSession *session = (IncSession *)state->data;
gint val;
gint msgnum;
}
val = GPOINTER_TO_INT(g_hash_table_lookup
- (state->folder_table, dropfolder));
+ (session->folder_table, dropfolder));
if (val == 0) {
folder_item_scan(dropfolder);
/* force updating */
if (FOLDER_IS_LOCAL(dropfolder->folder))
dropfolder->mtime = 0;
- g_hash_table_insert(state->folder_table, dropfolder,
+ g_hash_table_insert(session->folder_table, dropfolder,
GINT_TO_POINTER(1));
}
case INC_NOSPACE:
alertpanel_error(_("No disk space left."));
break;
+ case INC_LOCKED:
+ if (!prefs_common.no_recv_err_panel)
+ alertpanel_error(_("Mailbox is locked."));
+ break;
default:
break;
}
if (!sockinfo || session->atm->terminated == TRUE) return;
- session->pop3_state->inc_state = INC_CANCEL;
- pop3_automaton_terminate(sockinfo, session->atm);
- session->pop3_state->sockinfo = NULL;
+ session->pop3_state->cancelled = TRUE;
+ session->inc_state = INC_CANCEL;
+ session->atm->cancelled = TRUE;
+
+ log_message(_("Incorporation cancelled\n"));
}
gboolean inc_is_active(void)
typedef struct _IncProgressDialog IncProgressDialog;
typedef struct _IncSession IncSession;
-typedef struct _Pop3State Pop3State;
typedef enum
{
INC_SUCCESS,
INC_CONNECT_ERROR,
INC_AUTH_FAILED,
+ INC_LOCKED,
INC_ERROR,
INC_NOSPACE,
INC_CANCEL
{
Pop3State *pop3_state;
Automaton *atm;
-
- gpointer data;
-};
-
-struct _Pop3State
-{
- gboolean cancelled;
- PrefsAccount *ac_prefs;
- GHashTable *folder_table;
-
- gchar *prev_folder;
-
- SockInfo *sockinfo;
-
- gchar *greeting;
- gchar *user;
- gchar *pass;
- gint count;
- gint new;
- gint total_bytes;
- gint cur_msg;
- gint cur_total_num;
- gint cur_total_bytes;
- gint cur_total_recv_bytes;
-
- Pop3MsgInfo *msg;
-
- GHashTable *uidl_table;
- GSList *uidl_todelete_list;
-
- gboolean uidl_is_valid;
-
- time_t current_time;
-
- gint error_val;
IncState inc_state;
- IncSession *session;
+ GHashTable *folder_table; /* table of destination folders */
+
+ gpointer data;
};
#define TIMEOUT_ITV 200
#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;
}
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;
+}
#include <time.h>
#include "socket.h"
+#include "prefs_account.h"
typedef struct _Pop3MsgInfo Pop3MsgInfo;
+typedef struct _Pop3State Pop3State;
typedef enum {
POP3_GREETING_RECV,
guint deleted : 1;
};
+struct _Pop3State
+{
+ PrefsAccount *ac_prefs;
+
+ gchar *prev_folder;
+
+ SockInfo *sockinfo;
+
+ gchar *greeting;
+ gchar *user;
+ gchar *pass;
+ gint count;
+ gint new;
+ gint total_bytes;
+ gint cur_msg;
+ gint cur_total_num;
+ gint cur_total_bytes;
+ gint cur_total_recv_bytes;
+
+ Pop3MsgInfo *msg;
+
+ GHashTable *uidl_table;
+
+ gboolean uidl_is_valid;
+ gboolean cancelled;
+
+ time_t current_time;
+
+ gint error_val;
+
+ gpointer data;
+};
+
#define POPBUFSIZE 512
#define IDLEN 128
gint pop3_logout_send (SockInfo *sock, gpointer data);
gint pop3_logout_recv (SockInfo *sock, gpointer data);
+Pop3State *pop3_state_new (PrefsAccount *account);
+void pop3_state_destroy (Pop3State *state);
+GHashTable *pop3_get_uidl_table (PrefsAccount *account);
+gint pop3_write_uidl_list (Pop3State *state);
+
#endif /* __POP_H__ */