sync with 0.8.2cvs6
authorPaul Mangan <paul@claws-mail.org>
Sat, 31 Aug 2002 09:41:45 +0000 (09:41 +0000)
committerPaul Mangan <paul@claws-mail.org>
Sat, 31 Aug 2002 09:41:45 +0000 (09:41 +0000)
ChangeLog
ChangeLog.claws
ChangeLog.jp
configure.in
src/automaton.c
src/automaton.h
src/inc.c
src/inc.h
src/pop.c
src/pop.h

index 5f4adfa..8aa0ff5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+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]
index ebf14f9..846d14c 100644 (file)
@@ -1,17 +1,22 @@
-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
index 0e5ea3f..acb22f6 100644 (file)
@@ -1,3 +1,26 @@
+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]
index cb39e45..898f855 100644 (file)
@@ -8,7 +8,7 @@ MINOR_VERSION=8
 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
index 2ddb198..d6f0808 100644 (file)
@@ -55,7 +55,7 @@ void automaton_input_cb(gpointer data, gint dummy_source,
         * 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);
@@ -65,12 +65,21 @@ void automaton_input_cb(gpointer data, gint dummy_source,
        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;
index 41910cd..17e0fb8 100644 (file)
@@ -46,6 +46,7 @@ struct _Automaton
        gint tag;
        guint timeout_tag;
        guint elapsed;
+       gboolean cancelled;
        gboolean terminated;
 
        gpointer data;
index a3a2938..5ec3804 100644 (file)
--- a/src/inc.c
+++ b/src/inc.c
@@ -90,16 +90,11 @@ static void inc_progress_dialog_destroy     (IncProgressDialog      *inc_dialog);
 
 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,
@@ -430,8 +425,9 @@ static IncSession *inc_session_new(PrefsAccount *account)
                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;
 }
@@ -440,49 +436,11 @@ static void inc_session_destroy(IncSession *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;
@@ -492,6 +450,7 @@ static gint inc_start(IncProgressDialog *inc_dialog)
        gint num = 0;
        gint error_num = 0;
        gint new_msgs = 0;
+       gchar *msg;
        gchar *fin_msg;
 
        while (inc_dialog->queue_list != NULL) {
@@ -537,9 +496,8 @@ static gint inc_start(IncProgressDialog *inc_dialog)
                /* 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)"),
@@ -550,21 +508,32 @@ static gint inc_start(IncProgressDialog *inc_dialog)
                        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) ||
@@ -606,11 +575,11 @@ static gint inc_start(IncProgressDialog *inc_dialog)
                                /* 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);
@@ -621,8 +590,11 @@ static gint inc_start(IncProgressDialog *inc_dialog)
 
                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) {
@@ -630,7 +602,7 @@ static gint inc_start(IncProgressDialog *inc_dialog)
                        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++;
@@ -771,6 +743,7 @@ static IncState inc_pop3_session_do(IncSession *session)
                }
                pop3_automaton_terminate(NULL, atm);
                automaton_destroy(atm);
+               session->inc_state = INC_CONNECT_ERROR;
                return INC_CONNECT_ERROR;
        }
 
@@ -779,6 +752,7 @@ static IncState inc_pop3_session_do(IncSession *session)
            !ssl_init_socket(sockinfo)) {
                pop3_automaton_terminate(NULL, atm);
                automaton_destroy(atm);
+               session->inc_state = INC_CONNECT_ERROR;
                return INC_CONNECT_ERROR;
        }
 #endif
@@ -811,7 +785,28 @@ static IncState inc_pop3_session_do(IncSession *session)
 
        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)
@@ -834,92 +829,13 @@ 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;
@@ -943,7 +859,7 @@ static gboolean inc_pop3_recv_func(SockInfo *sock, gint count, gint read_bytes,
                 (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;
@@ -952,7 +868,8 @@ static gboolean inc_pop3_recv_func(SockInfo *sock, gint count, gint read_bytes,
 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;
 
@@ -1030,6 +947,7 @@ gint inc_drop_message(const gchar *file, Pop3State *state)
 {
        FolderItem *inbox;
        FolderItem *dropfolder;
+       IncSession *session = (IncSession *)state->data;
        gint val;
        gint msgnum;
 
@@ -1064,13 +982,13 @@ gint inc_drop_message(const gchar *file, Pop3State *state)
        }
 
        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));
        }
        
@@ -1094,6 +1012,10 @@ static void inc_put_error(IncState istate)
        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;
        }
@@ -1116,9 +1038,11 @@ static void inc_cancel(IncProgressDialog *dialog)
 
        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)
index 1ee99e0..f900931 100644 (file)
--- a/src/inc.h
+++ b/src/inc.h
 
 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
@@ -63,44 +63,11 @@ struct _IncSession
 {
        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
index fce679e..1eafedf 100644 (file)
--- a/src/pop.c
+++ b/src/pop.c
@@ -28,6 +28,7 @@
 #include <ctype.h>
 #include <unistd.h>
 #include <time.h>
+#include <errno.h>
 
 #include "intl.h"
 #include "pop.h"
@@ -92,8 +93,9 @@ gint pop3_greeting_recv(SockInfo *sock, gpointer data)
 {
        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)
@@ -104,7 +106,7 @@ gint pop3_greeting_recv(SockInfo *sock, gpointer data)
                else
                        return POP3_GETAUTH_USER_SEND;
        } else {
-               state->inc_state = INC_ERROR;
+               state->error_val = ok;
                return -1;
        }
 }
@@ -125,7 +127,6 @@ gint pop3_stls_recv(SockInfo *sock, gpointer data)
        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)
@@ -134,11 +135,10 @@ gint pop3_stls_recv(SockInfo *sock, gpointer data)
                        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;
        }
 }
@@ -164,7 +164,6 @@ gint pop3_getauth_user_recv(SockInfo *sock, gpointer data)
        else {
                log_warning(_("error occurred on authentication\n"));
                state->error_val = PS_AUTHFAIL;
-               state->inc_state = INC_AUTH_FAILED;
                return -1;
        }
 }
@@ -183,13 +182,17 @@ gint pop3_getauth_pass_send(SockInfo *sock, gpointer data)
 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;
        }
 }
@@ -208,14 +211,12 @@ gint pop3_getauth_apop_send(SockInfo *sock, gpointer data)
                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;
        }
 
@@ -233,13 +234,17 @@ gint pop3_getauth_apop_send(SockInfo *sock, gpointer data)
 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;
        }
 }
@@ -262,7 +267,6 @@ gint pop3_getrange_stat_recv(SockInfo *sock, gpointer data)
                    != 2) {
                        log_warning(_("POP3 protocol error\n"));
                        state->error_val = PS_PROTOCOL;
-                       state->inc_state = INC_ERROR;
                        return -1;
                } else {
                        if (state->count == 0) {
@@ -276,9 +280,10 @@ gint pop3_getrange_stat_recv(SockInfo *sock, gpointer data)
                        }
                }
        } 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;
        }
 }
@@ -301,7 +306,6 @@ gint pop3_getrange_last_recv(SockInfo *sock, gpointer data)
                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)
@@ -377,7 +381,6 @@ gint pop3_getrange_uidl_recv(SockInfo *sock, gpointer data)
        if (len < 0) {
                log_error(_("Socket error\n"));
                state->error_val = PS_SOCKET;
-               state->inc_state = INC_ERROR;
                return -1;
        }
 
@@ -416,7 +419,6 @@ gint pop3_getsize_list_recv(SockInfo *sock, gpointer data)
                if (buf[0] == '.') break;
                if (sscanf(buf, "%u %u", &num, &size) != 2) {
                        state->error_val = PS_PROTOCOL;
-                       state->inc_state = INC_ERROR;
                        return -1;
                }
 
@@ -429,7 +431,6 @@ gint pop3_getsize_list_recv(SockInfo *sock, gpointer data)
        if (len < 0) {
                log_error(_("Socket error\n"));
                state->error_val = PS_SOCKET;
-               state->inc_state = INC_ERROR;
                return -1;
        }
 
@@ -468,7 +469,7 @@ gint pop3_top_recv(SockInfo *sock, gpointer data)
        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;
        }
 
@@ -500,15 +501,15 @@ gint pop3_retr_recv(SockInfo *sock, gpointer data)
                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;
                }
 
@@ -533,9 +534,10 @@ gint pop3_retr_recv(SockInfo *sock, gpointer data)
                } 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;
        }
 }
@@ -568,9 +570,10 @@ gint pop3_delete_recv(SockInfo *sock, gpointer data)
                } 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;
        }
 }
@@ -585,9 +588,10 @@ gint pop3_logout_send(SockInfo *sock, gpointer data)
 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;
 }
@@ -808,3 +812,123 @@ gboolean pop3_sd_get_next(Pop3State *state)
                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;
+}
index 25f1557..b755ec5 100644 (file)
--- a/src/pop.h
+++ b/src/pop.h
 #include <time.h>
 
 #include "socket.h"
+#include "prefs_account.h"
 
 typedef struct _Pop3MsgInfo    Pop3MsgInfo;
+typedef struct _Pop3State      Pop3State;
 
 typedef enum {
        POP3_GREETING_RECV,
@@ -72,6 +74,39 @@ struct _Pop3MsgInfo
        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
 
@@ -125,4 +160,9 @@ gint pop3_delete_recv               (SockInfo *sock, gpointer data);
 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__ */