sync with 0.8.11cvs11
authorPaul Mangan <paul@claws-mail.org>
Tue, 25 Mar 2003 08:29:02 +0000 (08:29 +0000)
committerPaul Mangan <paul@claws-mail.org>
Tue, 25 Mar 2003 08:29:02 +0000 (08:29 +0000)
17 files changed:
ChangeLog
ChangeLog.claws
ChangeLog.jp
configure.ac
src/Makefile.am
src/automaton.c [deleted file]
src/automaton.h [deleted file]
src/common/defs.h
src/common/session.c
src/common/session.h
src/common/smtp.c
src/imap.c
src/inc.c
src/inc.h
src/news.c
src/pop.c
src/pop.h

index 7f4566c..b5b2c78 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,51 @@
+2003-03-25
+
+       * src/automaton.[ch]: removed.
+       * src/session.c: removed some of the debug output.
+       * src/smtp.c: smtp_session_recv_msg(): workaround in case server
+         returns EHLO-style response to HELO command.
+         Ignore all multiline responses except for EHLO since they are
+         allowed for any command.
+
+2003-03-25
+
+       * src/session.[ch]
+         src/pop.c: fixed retrieval of messages which contain dot-escaped
+         lines.
+         session_recv_data(): added a flag for unescape.
+         session_recv_data_from_sock_unescape(): new. It receives message
+         for each line and unescapes dot-escaped lines.
+         Removed the previous workaround.
+       * src/defs.h: decreased UI_REFRESH_INTERVAL to 40 msec.
+
+2003-03-25
+
+       * src/pop.[ch]: workaround for brekage of retrieval when given size
+         and actual one is different.
+
+2003-03-24
+
+       * src/pop.c: pop3_retr_eom_recv(): ignore invalid end of message
+         since some servers sometimes return incorrect message size.
+       * src/news.c: news_session_new(): zero clear NNTPSession object.
+         Don't initialize Session::sock with nntp_sock->sock to prevent
+         double-free of SockInfo.
+       * src/imap.c: zero clear IMAPSession object.
+         imap_cmd_append(): don't close SockInfo.
+
+2003-03-22
+
+       * src/pop.c: pop3_session_recv_msg(): fixed STLS.
+
+2003-03-22
+
+       * src/inc.[ch]
+         src/pop.[ch]: reimplemented using new I/O system.
+       * src/session.[ch]: session_recv_data(): new.
+         session_send_data_to_sock()
+         session_recv_data_from_sock(): decreased the frequency of progress
+         notification.
+
 2003-03-22
 
        * src/smtp.c: smtp_auth_recv(): fixed CRAM-MD5 authentication.
index 62174f8..5540f3c 100644 (file)
@@ -1,3 +1,10 @@
+2003-03-25 [paul]      0.8.11claws44
+
+       * sync with 0.8.11cvs11
+               see ChangeLog 2003-03-24 and 2003-03-25
+               
+       Note: Selective Download is broken.
+               
 2003-03-22 [christoph] 0.8.11claws43
 
        * src/folder.c
index 1c977ca..8a8cf42 100644 (file)
@@ -1,3 +1,51 @@
+2003-03-25
+
+       * src/automaton.[ch]: ºï½ü¡£
+       * src/session.c: ¥Ç¥Ð¥Ã¥°½ÐÎϤò¤¤¤¯¤é¤«ºï½ü¡£
+       * src/smtp.c: smtp_session_recv_msg(): ¥µ¡¼¥Ð¤¬ HELO ¥³¥Þ¥ó¥É¤ËÂФ·¤Æ
+         EHLO ¥¹¥¿¥¤¥ë¤Î±þÅú¤òÊÖ¤·¤¿¤È¤­¤Î¤¿¤á¤ÎÂн衣
+         EHLO ¤ò½ü¤¤¤ÆÁ´¤Æ¤ÎÊ£¿ô¹Ô±þÅú¤ò̵»ë¤¹¤ë¤è¤¦¤Ë¤·¤¿(¤¢¤é¤æ¤ë¥³¥Þ¥ó¥É
+         ¤ËÂФ·¤Æµö²Ä¤µ¤ì¤Æ¤¤¤ë¤¿¤á)¡£
+
+2003-03-25
+
+       * src/session.[ch]
+         src/pop.c: ¥É¥Ã¥È¤Ç¥¨¥¹¥±¡¼¥×¤µ¤ì¤Æ¤¤¤ë¹Ô¤ò¤â¤Ä¥á¥Ã¥»¡¼¥¸¤Î¼õ¿®¤ò
+         ½¤Àµ¡£
+         session_recv_data(): ¥¨¥¹¥±¡¼¥×²ò½ü¤Î¥Õ¥é¥°¤òÄɲá£
+         session_recv_data_from_sock_unescape(): ¿·µ¬¡£¥á¥Ã¥»¡¼¥¸¤ò¹ÔËè¤Ë
+         ¼õ¿®¤·¡¢¥É¥Ã¥È¤Ç¥¨¥¹¥±¡¼¥×¤µ¤ì¤Æ¤¤¤ë¹Ô¤ò¥¨¥¹¥±¡¼¥×²ò½ü¤¹¤ë¡£
+         °ÊÁ°¤ÎÂнè¤òºï½ü¡£
+       * src/defs.h: UI_REFRESH_INTERVAL ¤ò 40 msec ¤Ë¸º¾¯¡£
+
+2003-03-25
+
+       * src/pop.[ch]: Í¿¤¨¤é¤ì¤¿¥µ¥¤¥º¤È¼ÂºÝ¤Î¥µ¥¤¥º¤¬°Û¤Ê¤ë¾ì¹ç¤Ë¼õ¿®¤Ë
+         ¼ºÇÔ¤¹¤ëÌäÂê¤Ø¤ÎÂн衣
+
+2003-03-24
+
+       * src/pop.c: pop3_retr_eom_recv(): ¤¢¤ë¥µ¡¼¥Ð¤Ï»þ¡¹Àµ¤·¤¯¤Ê¤¤
+         ¥á¥Ã¥»¡¼¥¸¥µ¥¤¥º¤òÊÖ¤¹¤¿¤á¡¢Ìµ¸ú¤Ê¥á¥Ã¥»¡¼¥¸½ªÃ¼¤ò̵»ë¤¹¤ë¤è¤¦¤Ë
+         ¤·¤¿¡£
+       * src/news.c: news_session_new(): NNTPSession ¥ª¥Ö¥¸¥§¥¯¥È¤ò¥¼¥í
+         ¥¯¥ê¥¢¤¹¤ë¤è¤¦¤Ë¤·¤¿¡£ SockInfo ¤ÎÆó½Å³«Êü¤òËɤ°¤¿¤á¡¢
+         Session::sock ¤ò nntp_sock->sock ¤Ç½é´ü²½¤·¤Ê¤¤¤è¤¦¤Ë¤·¤¿¡£
+       * src/imap.c: IMAPSession ¥ª¥Ö¥¸¥§¥¯¥È¤ò¥¼¥í¥¯¥ê¥¢¤¹¤ë¤è¤¦¤Ë¤·¤¿¡£
+         imap_cmd_append(): SockInfo ¤òÊĤ¸¤Ê¤¤¤è¤¦¤Ë¤·¤¿¡£
+
+2003-03-22
+
+       * src/pop.c: pop3_session_recv_msg(): STLS ¤ò½¤Àµ¡£
+
+2003-03-22
+
+       * src/inc.[ch]
+         src/pop.[ch]: ¿· I/O ¥·¥¹¥Æ¥à¤ò»È¤Ã¤ÆºÆ¼ÂÁõ¡£
+       * src/session.[ch]: session_recv_msg(): ¿·µ¬¡£
+         session_send_data_to_sock()
+         session_recv_data_from_sock(): ¿ÊĽÄÌÃΤÎÉÑÅÙ¤ò²¼¤²¤¿¡£
+
 2003-03-22
 
        * src/smtp.c: smtp_auth_recv(): CRAM-MD5 Ç§¾Ú¤ò½¤Àµ¡£
index c5d0f91..2d9f254 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=8
 MICRO_VERSION=11
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=claws43
+EXTRA_VERSION=claws44
 VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION$EXTRA_VERSION
 
 dnl set $target
index 85386d7..d2f649b 100644 (file)
@@ -82,7 +82,6 @@ sylpheed_SOURCES = \
        codeconv.c codeconv.h \
        unmime.c unmime.h \
        ssl_manager.c ssl_manager.h \
-       automaton.c automaton.h \
        pop.c pop.h \
        mh.c mh.h \
        mbox.c mbox.h \
diff --git a/src/automaton.c b/src/automaton.c
deleted file mode 100644 (file)
index b71a5fb..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2002 Hiroyuki Yamamoto
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <glib.h>
-#include <gdk/gdk.h>
-#include <gtk/gtkmain.h>
-
-#include "automaton.h"
-
-Automaton *automaton_create(gint num)
-{
-       Automaton *atm;
-
-       g_return_val_if_fail(num > 0, NULL);
-
-       atm = g_new0(Automaton, 1);
-       atm->max = num - 1;
-       atm->state = g_new0(AtmState, num);
-
-       return atm;
-}
-
-void automaton_destroy(Automaton *atm)
-{
-       if (!atm) return;
-
-       g_free(atm->state);
-       g_free(atm);
-}
-
-gboolean automaton_input_cb(GIOChannel *channel,
-                       GIOCondition condition,
-                       gpointer data)
-{
-       Automaton *atm = (Automaton *)data;
-       SockInfo *sock;
-       gint next;
-
-       /* We get out sockinfo from the atm context and not from the
-        * passed file descriptor because we can't map that one back
-        * to the sockinfo */
-       sock = atm->help_sock;
-       g_return_val_if_fail(sock->sock == g_io_channel_unix_get_fd(channel), TRUE);
-
-       if (atm->timeout_tag > 0) {
-               gtk_timeout_remove(atm->timeout_tag);
-               atm->timeout_tag = 0;
-               atm->elapsed = 0;
-       }
-       gdk_input_remove(atm->tag);
-       atm->tag = 0;
-
-       if (atm->cancelled) {
-               atm->terminate(sock, data);
-               return TRUE;
-       }
-
-       if (atm->ui_func)
-               atm->ui_func(atm->data, atm->num);
-       next = atm->state[atm->num].handler(sock, atm->data);
-
-       if (atm->terminated)
-               return TRUE;
-       if (atm->cancelled) {
-               atm->terminate(sock, data);
-               return TRUE;
-       }
-
-       if (next >= 0 && next <= atm->max && next != atm->num) {
-               atm->num = next;
-               atm->tag = sock_input_add(sock,
-                                         atm->state[atm->num].condition,       
-                                         automaton_input_cb,
-                                         data);
-       } else {
-               atm->terminate(sock, data);
-       }
-
-       return TRUE;
-}
diff --git a/src/automaton.h b/src/automaton.h
deleted file mode 100644 (file)
index 97be9ff..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2002 Hiroyuki Yamamoto
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __AUTOMATON_H__
-#define __AUTOMATON_H__
-
-#include <glib.h>
-
-#include "socket.h"
-
-typedef struct _AtmState       AtmState;
-typedef struct _Automaton      Automaton;
-
-typedef gint   (*AtmHandler)   (SockInfo       *source,
-                                gpointer        data);
-typedef void   (*AtmUIFunc)    (gpointer        data,
-                                gint            state);
-
-struct _AtmState
-{
-       GIOCondition     condition;
-       gint (*handler) (SockInfo       *source,
-                        gpointer        data);
-};
-
-struct _Automaton
-{
-       gint max;
-       gint num;
-       gint tag;
-       guint timeout_tag;
-       guint elapsed;
-       gboolean cancelled;
-       gboolean terminated;
-
-       gpointer data;
-       AtmState *state;
-
-       gint (*terminate)       (SockInfo       *source,
-                                gpointer        data);
-
-       AtmUIFunc ui_func;
-
-       SockInfo *help_sock;
-};
-
-Automaton *automaton_create    (gint                    num);
-void automaton_destroy         (Automaton              *atm);
-gboolean automaton_input_cb    (GIOChannel             *channel,
-                                GIOCondition            condition,
-                                gpointer                data);
-
-#endif /* __AUTOMATON_H__ */
index 7b3ff35..f036613 100644 (file)
@@ -99,7 +99,7 @@
 #define FOLDER_SPACING                 4
 #define MAX_ENTRY_LENGTH               8191
 #define COLOR_DIM                      35000
-#define UI_REFRESH_INTERVAL            50000   /* usec */
+#define UI_REFRESH_INTERVAL            40000   /* usec */
 #define SESSION_TIMEOUT                        60      /* sec */
 #define MAX_HISTORY_SIZE               16
 
index fefb9f1..a47c17b 100644 (file)
@@ -32,6 +32,7 @@
 #include <unistd.h>
 #include <sys/signal.h>
 #include <sys/wait.h>
+#include <sys/time.h>
 
 #include "session.h"
 #include "utils.h"
@@ -49,6 +50,9 @@ static gint session_send_data_to_sock         (Session        *session,
 static guchar *session_recv_data_from_sock     (Session        *session,
                                                 guint           size);
 
+static guchar *session_recv_data_from_sock_unescape    (Session *session,
+                                                        guint    size);
+
 gboolean session_parent_input_cb       (GIOChannel     *source,
                                         GIOCondition    condition,
                                         gpointer        data);
@@ -266,6 +270,8 @@ gint session_send_msg(Session *session, SessionMsgType type, const gchar *msg)
                prefix = "MESSAGE"; break;
        case SESSION_MSG_SEND_DATA:
                prefix = "SENDDATA"; break;
+       case SESSION_MSG_RECV_DATA:
+               prefix = "RECVDATA"; break;
        case SESSION_MSG_CONTROL:
                prefix = "CONTROL"; break;
        case SESSION_MSG_ERROR:
@@ -275,7 +281,7 @@ gint session_send_msg(Session *session, SessionMsgType type, const gchar *msg)
        }
 
        str = g_strdup_printf("%s %s\n", prefix, msg);
-       g_print("%s: sending message: %s", session->child_pid == 0 ? "child" : "parent", str);
+       /* g_print("%s: sending message: %s", session->child_pid == 0 ? "child" : "parent", str); */
        size = strlen(str);
 
        while (size > 0) {
@@ -375,6 +381,18 @@ gint session_send_data(Session *session, const guchar *data, guint size)
        return 0;
 }
 
+gint session_recv_data(Session *session, guint size, gboolean unescape_dot)
+{
+       if (unescape_dot) {
+               gchar buf[BUFFSIZE];
+
+               g_snprintf(buf, sizeof(buf), "%d UNESCAPE", size);
+               session_send_msg(session, SESSION_MSG_RECV_DATA, buf);
+       } else
+               session_send_msg(session, SESSION_MSG_RECV_DATA, itos(size));
+       return 0;
+}
+
 static guchar *session_read_data(Session *session, guint size)
 {
        guchar *data;
@@ -413,8 +431,11 @@ static gint session_send_data_to_sock(Session *session, const guchar *data,
        guint left = size;
        gchar buf[BUFFSIZE];
        gchar *msg;
+       struct timeval tv_prev, tv_cur;
+
+       gettimeofday(&tv_prev, NULL);
 
-       while (left > 0) {
+       while (1) {
                bytes_written = sock_write(session->sock, cur,
                                           MIN(left, MAX_CHUNK_SIZE));
                if (bytes_written <= 0)
@@ -422,13 +443,19 @@ static gint session_send_data_to_sock(Session *session, const guchar *data,
                left -= bytes_written;
                cur += bytes_written;
                total_write_len += bytes_written;
-               if (left > 0) {
+               if (left == 0)
+                       break;
+
+               gettimeofday(&tv_cur, NULL);
+               if (tv_cur.tv_sec - tv_prev.tv_sec > 0 ||
+                   tv_cur.tv_usec - tv_prev.tv_usec > UI_REFRESH_INTERVAL) {
                        g_snprintf(buf, sizeof(buf), "DATASENDINPROG %d %d",
                                   total_write_len, size);
                        session_send_msg(session, SESSION_MSG_CONTROL, buf);
                        if ((msg = session_recv_msg(session)) == NULL)
                                return -1;
                        g_free(msg);
+                       gettimeofday(&tv_prev, NULL);
                }
        }
 
@@ -444,10 +471,13 @@ static guchar *session_recv_data_from_sock(Session *session, guint size)
        guint left = size;
        gchar buf[BUFFSIZE];
        gchar *msg;
+       struct timeval tv_prev, tv_cur;
+
+       gettimeofday(&tv_prev, NULL);
 
        cur = data = g_malloc(size);
 
-       while (left > 0) {
+       while (1) {
                bytes_read = sock_read(session->sock, cur, left);
                if (bytes_read <= 0) {
                        g_free(data);
@@ -457,14 +487,79 @@ static guchar *session_recv_data_from_sock(Session *session, guint size)
                left -= bytes_read;
                cur += bytes_read;
                total_read_len += bytes_read;
-               g_snprintf(buf, sizeof(buf), "DATARECVINPROG %d %d",
-                          total_read_len, size);
-               session_send_msg(session, SESSION_MSG_CONTROL, buf);
-               if ((msg = session_recv_msg(session)) == NULL) {
+               if (left == 0)
+                       break;
+
+               gettimeofday(&tv_cur, NULL);
+               if (tv_cur.tv_sec - tv_prev.tv_sec > 0 ||
+                   tv_cur.tv_usec - tv_prev.tv_usec > UI_REFRESH_INTERVAL) {
+                       g_snprintf(buf, sizeof(buf), "DATARECVINPROG %d %d",
+                                  total_read_len, size);
+                       session_send_msg(session, SESSION_MSG_CONTROL, buf);
+                       if ((msg = session_recv_msg(session)) == NULL) {
+                               g_free(data);
+                               return NULL;
+                       }
+                       g_free(msg);
+                       gettimeofday(&tv_prev, NULL);
+               }
+       }
+
+       return data;
+}
+
+static guchar *session_recv_data_from_sock_unescape(Session *session,
+                                                   guint size)
+{
+       guchar *data;
+       guchar *cur;
+       gint bytes_read;
+       gint total_read_len = 0;
+       guint left = size;
+       gchar buf[BUFFSIZE];
+       gchar *msg;
+       struct timeval tv_prev, tv_cur;
+
+       gettimeofday(&tv_prev, NULL);
+
+       cur = data = g_malloc(size);
+
+       while (1) {
+               bytes_read = sock_gets(session->sock, buf, sizeof(buf));
+               if (bytes_read <= 0) {
                        g_free(data);
                        return NULL;
                }
-               g_free(msg);
+
+               if (buf[0] == '.' && buf[1] == '.') {
+                       bytes_read--;
+                       if (left < bytes_read)
+                               bytes_read = left;
+                       memcpy(cur, buf + 1, bytes_read);
+               } else {
+                       if (left < bytes_read)
+                               bytes_read = left;
+                       memcpy(cur, buf, bytes_read);
+               }
+               left -= bytes_read;
+               cur += bytes_read;
+               total_read_len += bytes_read;
+               if (left == 0)
+                       break;
+
+               gettimeofday(&tv_cur, NULL);
+               if (tv_cur.tv_sec - tv_prev.tv_sec > 0 ||
+                   tv_cur.tv_usec - tv_prev.tv_usec > UI_REFRESH_INTERVAL) {
+                       g_snprintf(buf, sizeof(buf), "DATARECVINPROG %d %d",
+                                  total_read_len, size);
+                       session_send_msg(session, SESSION_MSG_CONTROL, buf);
+                       if ((msg = session_recv_msg(session)) == NULL) {
+                               g_free(data);
+                               return NULL;
+                       }
+                       g_free(msg);
+                       gettimeofday(&tv_prev, NULL);
+               }
        }
 
        return data;
@@ -507,13 +602,12 @@ gboolean session_parent_input_cb(GIOChannel *source, GIOCondition condition,
        case SESSION_MSG_NORMAL:
                msg_data = msg + strlen("MESSAGE ");
                ret = session->recv_msg(session, msg_data);
-               if (ret <= 0)
-                       session->recv_msg_notify(session, msg_data,
-                                                session->recv_msg_notify_data);
-               else
+               session->recv_msg_notify(session, msg_data,
+                                        session->recv_msg_notify_data);
+               if (ret > 0)
                        session_send_msg(session, SESSION_MSG_CONTROL,
                                         "CONTINUE");
-               if (ret < 0) {
+               else if (ret < 0) {
                        session->state = SESSION_ERROR;
                        g_free(msg);
                        return FALSE;
@@ -529,8 +623,18 @@ gboolean session_parent_input_cb(GIOChannel *source, GIOCondition condition,
                        g_free(msg);
                        return FALSE;
                }
-               session->recv_data_finished(session, recv_data, size);
+               ret = session->recv_data_finished(session, recv_data, size);
                g_free(recv_data);
+               session->recv_data_notify(session, size,
+                                         session->recv_data_notify_data);
+               if (ret > 0)
+                       session_send_msg(session, SESSION_MSG_CONTROL,
+                                        "CONTINUE");
+               else if (ret < 0) {
+                       session->state = SESSION_ERROR;
+                       g_free(msg);
+                       return FALSE;
+               }
                break;
        case SESSION_MSG_RECV_DATA:
                break;
@@ -660,7 +764,11 @@ gboolean session_child_input(Session *session)
                msg_data = msg + strlen("RECVDATA ");
                size = atoi(msg_data);
                session->state = SESSION_RECV;
-               recv_data = session_recv_data_from_sock(session, size);
+               if (strstr(msg_data, "UNESCAPE") != NULL)
+                       recv_data = session_recv_data_from_sock_unescape
+                               (session, size);
+               else
+                       recv_data = session_recv_data_from_sock(session, size);
                if (!recv_data) {
                        session_send_msg(session, SESSION_MSG_ERROR,
                                         "receiving data failed.");
index f846e5f..6988148 100644 (file)
@@ -162,6 +162,9 @@ gint session_send_msg       (Session        *session,
 gint session_send_data (Session        *session,
                         const guchar   *data,
                         guint           size);
+gint session_recv_data (Session        *session,
+                        guint           size,
+                        gboolean        unescape_dot);
 
 #if USE_OPENSSL
 gint session_start_tls (Session        *session);
index 0a77904..a58b5dc 100644 (file)
@@ -431,6 +431,10 @@ static gint smtp_session_recv_msg(Session *session, const gchar *msg)
                return -1;
        }
 
+       /* ignore all multiline responses except for EHLO */
+       if (cont && smtp_session->state != SMTP_EHLO)
+               return 1;
+
        switch (smtp_session->state) {
        case SMTP_READY:
        case SMTP_CONNECTED:
index 9454fd5..6cb9b7f 100644 (file)
@@ -555,7 +555,7 @@ Session *imap_session_new(const PrefsAccount *account)
        log_message("IMAP connection is %s-authenticated\n",
                    (is_preauth) ? "pre" : "un");
 
-       session = g_new(IMAPSession, 1);
+       session = g_new0(IMAPSession, 1);
        session_init(SESSION(session));
        SESSION(session)->type             = SESSION_IMAP;
        SESSION(session)->server           = g_strdup(account->recv_server);
@@ -2777,7 +2777,6 @@ static gint imap_cmd_append(IMAPSession *session, const gchar *destfolder,
                strretchomp(buf);
                if (sock_puts(SESSION(session)->sock, buf) < 0) {
                        fclose(fp);
-                       sock_close(SESSION(session)->sock);
                        return -1;
                }
        }
@@ -2785,7 +2784,6 @@ static gint imap_cmd_append(IMAPSession *session, const gchar *destfolder,
        if (ferror(fp)) {
                FILE_OP_ERROR(file, "fgets");
                fclose(fp);
-               sock_close(SESSION(session)->sock);
                return -1;
        }
 
index 9fa12c2..3e70ad4 100644 (file)
--- a/src/inc.c
+++ b/src/inc.c
@@ -61,7 +61,6 @@
 #include "progressdialog.h"
 #include "inputdialog.h"
 #include "alertpanel.h"
-#include "automaton.h"
 #include "folder.h"
 #include "filtering.h"
 #include "selective_download.h"
@@ -93,12 +92,16 @@ static IncSession *inc_session_new  (PrefsAccount           *account);
 static void inc_session_destroy                (IncSession             *session);
 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 gboolean inc_pop3_recv_func     (SockInfo       *sock,
-                                        gint            count,
-                                        gint            read_bytes,
+static gint inc_recv_data_progressive  (Session        *session,
+                                        guint           cur_len,
+                                        guint           total_len,
+                                        gpointer        data);
+static gint inc_recv_data_finished     (Session        *session,
+                                        guint           len,
+                                        gpointer        data);
+static gint inc_recv_message           (Session        *session,
+                                        const gchar    *msg,
                                         gpointer        data);
 
 static void inc_put_error              (IncState        istate);
@@ -357,12 +360,13 @@ void inc_all_account_mail(MainWindow *mainwin, gboolean notify)
        inc_dialog->mainwin = mainwin;
        for (list = queue_list; list != NULL; list = list->next) {
                IncSession *session = list->data;
+               Pop3Session *pop3_session = POP3_SESSION(session->session);
                gchar *text[3];
 
                session->data = inc_dialog;
 
                text[0] = NULL;
-               text[1] = session->pop3_state->ac_prefs->account_name;
+               text[1] = pop3_session->ac_prefs->account_name;
                text[2] = _("Standby");
                gtk_clist_append(GTK_CLIST(inc_dialog->dialog->clist), text);
        }
@@ -451,8 +455,8 @@ static IncSession *inc_session_new(PrefsAccount *account)
                return NULL;
 
        session = g_new0(IncSession, 1);
-       session->pop3_state = pop3_state_new(account);
-       session->pop3_state->data = session;
+       session->session = pop3_session_new(account);
+       session->session->data = session;
 
        return session;
 }
@@ -461,7 +465,7 @@ static void inc_session_destroy(IncSession *session)
 {
        g_return_if_fail(session != NULL);
 
-       pop3_state_destroy(session->pop3_state);
+       session_destroy(session->session);
        g_free(session);
 }
 
@@ -469,7 +473,7 @@ static gint inc_start(IncProgressDialog *inc_dialog)
 {
        IncSession *session;
        GtkCList *clist = GTK_CLIST(inc_dialog->dialog->clist);
-       Pop3State *pop3_state;
+       Pop3Session *pop3_session;
        IncState inc_state;
        gint num = 0;
        gint error_num = 0;
@@ -482,33 +486,34 @@ static gint inc_start(IncProgressDialog *inc_dialog)
 
        while (inc_dialog->queue_list != NULL) {
                session = inc_dialog->queue_list->data;
-               pop3_state = session->pop3_state;
+               pop3_session = POP3_SESSION(session->session);
 
                inc_progress_dialog_clear(inc_dialog);
 
                gtk_clist_moveto(clist, num, -1, 1.0, 0.0);
 
-               pop3_state->user = g_strdup(pop3_state->ac_prefs->userid);
-               if (pop3_state->ac_prefs->passwd)
-                       pop3_state->pass =
-                               g_strdup(pop3_state->ac_prefs->passwd);
-               else if (pop3_state->ac_prefs->tmp_pass)
-                       pop3_state->pass =
-                               g_strdup(pop3_state->ac_prefs->tmp_pass);
+               pop3_session->user = g_strdup(pop3_session->ac_prefs->userid);
+               if (pop3_session->ac_prefs->passwd)
+                       pop3_session->pass =
+                               g_strdup(pop3_session->ac_prefs->passwd);
+               else if (pop3_session->ac_prefs->tmp_pass)
+                       pop3_session->pass =
+                               g_strdup(pop3_session->ac_prefs->tmp_pass);
                else {
                        gchar *pass;
 
                        pass = input_dialog_query_password
-                               (pop3_state->ac_prefs->recv_server,
-                                pop3_state->user);
+                               (pop3_session->ac_prefs->recv_server,
+                                pop3_session->user);
 
                        if (inc_dialog->mainwin && inc_dialog->show_dialog)
                                manage_window_focus_in
                                        (inc_dialog->mainwin->window,
                                         NULL, NULL);
                        if (pass) {
-                               pop3_state->ac_prefs->tmp_pass = g_strdup(pass);
-                               pop3_state->pass = pass;
+                               pop3_session->ac_prefs->tmp_pass =
+                                       g_strdup(pass);
+                               pop3_session->pass = pass;
                        } else {
                                inc_session_destroy(session);
                                inc_dialog->queue_list = g_list_remove
@@ -520,16 +525,23 @@ static gint inc_start(IncProgressDialog *inc_dialog)
                gtk_clist_set_pixmap(clist, num, 0, currentxpm, currentxpmmask);
                gtk_clist_set_text(clist, num, 2, _("Retrieving"));
 
+               session_set_recv_message_notify(session->session,
+                                               inc_recv_message, session);
+               session_set_recv_data_progressive_notify
+                       (session->session, inc_recv_data_progressive, session);
+               session_set_recv_data_notify(session->session,
+                                            inc_recv_data_finished, session);
+
                /* begin POP3 session */
                inc_state = inc_pop3_session_do(session);
 
                switch (inc_state) {
                case INC_SUCCESS:
-                       if (pop3_state->cur_total_num > 0)
+                       if (pop3_session->cur_total_num > 0)
                                msg = g_strdup_printf
                                        (_("Done (%d message(s) (%s) received)"),
-                                        pop3_state->cur_total_num,
-                                        to_human_readable(pop3_state->cur_total_recv_bytes));
+                                        pop3_session->cur_total_num,
+                                        to_human_readable(pop3_session->cur_total_recv_bytes));
                        else
                                msg = g_strdup_printf(_("Done (no new messages)"));
                        gtk_clist_set_pixmap(clist, num, 0, okxpm, okxpmmask);
@@ -563,7 +575,7 @@ static gint inc_start(IncProgressDialog *inc_dialog)
                        break;
                }
                
-               if (pop3_state->error_val == PS_AUTHFAIL) {
+               if (pop3_session->error_val == PS_AUTHFAIL) {
                        if(!prefs_common.no_recv_err_panel) {
                                if((prefs_common.recv_dialog_mode == RECV_DIALOG_ALWAYS) ||
                                    ((prefs_common.recv_dialog_mode == RECV_DIALOG_ACTIVE) && focus_window)) {
@@ -571,16 +583,16 @@ static gint inc_start(IncProgressDialog *inc_dialog)
                                }
                                alertpanel_error
                                        (_("Authorization for %s on %s failed"),
-                                        pop3_state->user,
-                                        pop3_state->ac_prefs->recv_server);
+                                        pop3_session->user,
+                                        pop3_session->ac_prefs->recv_server);
                        }
                }
 
                /* CLAWS: perform filtering actions on dropped message */
                /* CLAWS: get default inbox (perhaps per account) */
-               if (pop3_state->ac_prefs->inbox) {
+               if (pop3_session->ac_prefs->inbox) {
                        /* CLAWS: get destination folder / mailbox */
-                       inbox = folder_find_item_from_identifier(pop3_state->ac_prefs->inbox);
+                       inbox = folder_find_item_from_identifier(pop3_session->ac_prefs->inbox);
                        if (!inbox)
                                inbox = folder_get_default_inbox();
                } else
@@ -602,7 +614,7 @@ static gint inc_start(IncProgressDialog *inc_dialog)
                        
                        if (!hooks_invoke(MAIL_FILTERING_HOOKLIST, &mail_filtering_data)) {
                                /* filter if enabled in prefs or move to inbox if not */
-                               if(global_processing && pop3_state->ac_prefs->filter_on_recv) {
+                               if(global_processing && pop3_session->ac_prefs->filter_on_recv) {
                                        filter_message_by_msginfo_with_inbox(global_processing, msginfo,
                                                                             inbox);
                                } else {
@@ -616,15 +628,15 @@ static gint inc_start(IncProgressDialog *inc_dialog)
                folder_item_update_thaw();
 
 
-               new_msgs += pop3_state->cur_total_num;
+               new_msgs += pop3_session->cur_total_num;
 
-               if (pop3_state->error_val == PS_AUTHFAIL &&
-                   pop3_state->ac_prefs->tmp_pass) {
-                       g_free(pop3_state->ac_prefs->tmp_pass);
-                       pop3_state->ac_prefs->tmp_pass = NULL;
+               if (pop3_session->error_val == PS_AUTHFAIL &&
+                   pop3_session->ac_prefs->tmp_pass) {
+                       g_free(pop3_session->ac_prefs->tmp_pass);
+                       pop3_session->ac_prefs->tmp_pass = NULL;
                }
 
-               pop3_write_uidl_list(pop3_state);
+               pop3_write_uidl_list(pop3_session);
 
                if (inc_state != INC_SUCCESS && inc_state != INC_CANCEL) {
                        error_num++;
@@ -686,67 +698,29 @@ static gint inc_start(IncProgressDialog *inc_dialog)
 
 static IncState inc_pop3_session_do(IncSession *session)
 {
-       Pop3State *pop3_state = session->pop3_state;
+       Pop3Session *pop3_session = POP3_SESSION(session->session);
        IncProgressDialog *inc_dialog = (IncProgressDialog *)session->data;
-       Automaton *atm;
-       SockInfo *sockinfo = NULL;
-       gint i;
        gchar *server;
        gushort port;
        gchar *buf;
-       static AtmHandler handlers[] = {
-               pop3_greeting_recv      ,
-#if USE_OPENSSL
-               pop3_stls_send          , pop3_stls_recv,
-#endif
-               pop3_getauth_user_send  , pop3_getauth_user_recv,
-               pop3_getauth_pass_send  , pop3_getauth_pass_recv,
-               pop3_getauth_apop_send  , pop3_getauth_apop_recv,
-               pop3_getrange_stat_send , pop3_getrange_stat_recv,
-               pop3_getrange_last_send , pop3_getrange_last_recv,
-               pop3_getrange_uidl_send , pop3_getrange_uidl_recv,
-               pop3_getsize_list_send  , pop3_getsize_list_recv,
-               pop3_top_send           , pop3_top_recv,
-               pop3_retr_send          , pop3_retr_recv,
-               pop3_delete_send        , pop3_delete_recv,
-               pop3_logout_send        , pop3_logout_recv
-       };
 
        debug_print("getting new messages of account %s...\n",
-                   pop3_state->ac_prefs->account_name);
-
-       pop3_state->ac_prefs->last_pop_login_time = time(NULL);
-       atm = automaton_create(N_POP3_PHASE);
-
-       session->atm = atm;
-       atm->data = pop3_state;
+                   pop3_session->ac_prefs->account_name);
 
        buf = g_strdup_printf(_("%s: Retrieving new messages"),
-                             pop3_state->ac_prefs->recv_server);
+                             pop3_session->ac_prefs->recv_server);
        gtk_window_set_title(GTK_WINDOW(inc_dialog->dialog->window), buf);
        g_free(buf);
 
-       for (i = POP3_GREETING_RECV; i < N_POP3_PHASE; i++)
-               atm->state[i].handler = handlers[i];
-       atm->state[POP3_GREETING_RECV].condition = (G_IO_IN | G_IO_HUP | G_IO_ERR);
-       for (i = POP3_GREETING_RECV + 1; i < N_POP3_PHASE; ) {
-               atm->state[i++].condition = (G_IO_OUT | G_IO_ERR);
-               atm->state[i++].condition = (G_IO_IN | G_IO_HUP | G_IO_ERR);
-       }
-
-       atm->terminate = (AtmHandler)pop3_automaton_terminate;
-       atm->ui_func = (AtmUIFunc)inc_progress_update;
-
-       atm->num = POP3_GREETING_RECV;
-
-       server = pop3_state->ac_prefs->recv_server;
+       server = pop3_session->ac_prefs->recv_server;
 #if USE_OPENSSL
-       port = pop3_state->ac_prefs->set_popport ?
-               pop3_state->ac_prefs->popport :
-               pop3_state->ac_prefs->ssl_pop == SSL_TUNNEL ? 995 : 110;
+       port = pop3_session->ac_prefs->set_popport ?
+               pop3_session->ac_prefs->popport :
+               pop3_session->ac_prefs->ssl_pop == SSL_TUNNEL ? 995 : 110;
+       SESSION(pop3_session)->ssl_type = pop3_session->ac_prefs->ssl_pop;
 #else
-       port = pop3_state->ac_prefs->set_popport ?
-               pop3_state->ac_prefs->popport : 110;
+       port = pop3_session->ac_prefs->set_popport ?
+               pop3_session->ac_prefs->popport : 110;
 #endif
 
        statusbar_verbosity_set(TRUE);
@@ -757,11 +731,9 @@ static IncState inc_pop3_session_do(IncSession *session)
        g_free(buf);
        GTK_EVENTS_FLUSH();
 
-       sockinfo = sock_connect(server, port);
-
        statusbar_verbosity_set(FALSE);
 
-       if (sockinfo == NULL) {
+       if (session_connect(SESSION(pop3_session), server, port) < 0) {
                log_warning(_("Can't connect to POP3 server: %s:%d\n"),
                            server, port);
                if(!prefs_common.no_recv_err_panel) {
@@ -773,228 +745,164 @@ static IncState inc_pop3_session_do(IncSession *session)
                                         server, port);
                        manage_window_focus_out(inc_dialog->dialog->window, NULL, NULL);
                }
-               pop3_automaton_terminate(NULL, atm);
-               automaton_destroy(atm);
                session->inc_state = INC_CONNECT_ERROR;
                return INC_CONNECT_ERROR;
        }
 
-#if USE_OPENSSL
-       if (pop3_state->ac_prefs->ssl_pop == SSL_TUNNEL &&
-           !ssl_init_socket(sockinfo)) {
-               pop3_automaton_terminate(sockinfo, atm);
-               automaton_destroy(atm);
-               session->inc_state = INC_CONNECT_ERROR;
-               return INC_CONNECT_ERROR;
-       }
-#endif
-
-       /* :WK: Hmmm, with the later sock_gdk_input, we have 2 references
-        * to the sock structure - implement a reference counter?? */
-       pop3_state->sockinfo = sockinfo;
-       atm->help_sock = sockinfo;
-
        statusbar_verbosity_set(TRUE);
-       /* oha: this messes up inc_progress update:
-          disabling this would avoid the label "Retrieve Header"
-          being overwritten by "Retrieve Message"
-          Setting inc_pop3_recv_func is not necessary
-          since atm already handles the progress dialog ui
-          just fine.
-       */
-       recv_set_ui_func(inc_pop3_recv_func, session);
-
-       atm->tag = sock_input_add(sockinfo,
-                                 atm->state[atm->num].condition,
-                                 automaton_input_cb, atm);
-
-       while (!atm->terminated && !atm->cancelled)
+
+       while (SESSION(pop3_session)->state != SESSION_DISCONNECTED &&
+              SESSION(pop3_session)->state != SESSION_ERROR)
                gtk_main_iteration();
 
-       if (!atm->terminated)
-               pop3_automaton_terminate(sockinfo, atm);
 
        statusbar_verbosity_set(FALSE);
-       /* oha: see above */
-       recv_set_ui_func(NULL, NULL);
-
-       automaton_destroy(atm);
-
-       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_IO_ERROR;
-               break;
-       case PS_SOCKET:
-               session->inc_state = INC_SOCKET_ERROR;
-               break;
-       case PS_LOCKBUSY:
-               session->inc_state = INC_LOCKED;
-               break;
-       default:
-               session->inc_state = INC_ERROR;
-               break;
+       if (session->inc_state == INC_SUCCESS) {
+               switch (pop3_session->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_IO_ERROR;
+                       break;
+               case PS_SOCKET:
+                       session->inc_state = INC_SOCKET_ERROR;
+                       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)
-{
-       if (atm->terminated) return 0;
-
-       if (atm->tag > 0) {
-               gdk_input_remove(atm->tag);
-               atm->tag = 0;
-       }
-       if (atm->timeout_tag > 0) {
-               gtk_timeout_remove(atm->timeout_tag);
-               atm->timeout_tag = 0;
-       }
-       if (source)
-               sock_close(source);
-
-       atm->terminated = TRUE;
-
-       return 0;
-}
-
-static gboolean inc_pop3_recv_func(SockInfo *sock, gint count, gint read_bytes,
-                                  gpointer data)
+static gint inc_recv_data_progressive(Session *session, guint cur_len,
+                                     guint total_len, gpointer data)
 {
        gchar buf[MSGBUFSIZE];
-       IncSession *session = (IncSession *)data;
-       Pop3State *state = session->pop3_state;
-       IncProgressDialog *inc_dialog = (IncProgressDialog *)session->data;
+       IncSession *inc_session = (IncSession *)data;
+       Pop3Session *pop3_session = POP3_SESSION(session);
+       IncProgressDialog *inc_dialog = (IncProgressDialog *)inc_session->data;
        ProgressDialog *dialog = inc_dialog->dialog;
        gint cur_total;
        gchar *total_size;
 
-       cur_total = state->cur_total_bytes + read_bytes;
-       if (cur_total > state->total_bytes)
-               cur_total = state->total_bytes;
+       cur_total = pop3_session->cur_total_bytes + cur_len;
+       if (cur_total > pop3_session->total_bytes)
+               cur_total = pop3_session->total_bytes;
 
-       Xstrdup_a(total_size, to_human_readable(state->total_bytes),
+       Xstrdup_a(total_size, to_human_readable(pop3_session->total_bytes),
                  return FALSE);
        g_snprintf(buf, sizeof(buf),
                   _("Retrieving message (%d / %d) (%s / %s)"),
-                  state->cur_msg, state->count,
+                  pop3_session->cur_msg, pop3_session->count,
                   to_human_readable(cur_total), total_size);
        progress_dialog_set_label(dialog, buf);
-
        progress_dialog_set_percentage
-               (dialog, (gfloat)cur_total / (gfloat)state->total_bytes);
+               (dialog, (gfloat)cur_total / (gfloat)pop3_session->total_bytes);
        if (inc_dialog->mainwin)
                gtk_progress_bar_update
                        (GTK_PROGRESS_BAR(inc_dialog->mainwin->progressbar),
-                        (gfloat)cur_total / (gfloat)state->total_bytes);
+                        (gfloat)cur_total / (gfloat)pop3_session->total_bytes);
        GTK_EVENTS_FLUSH();
 
-       if (session->inc_state == INC_CANCEL)
-               return FALSE;
-       else
-               return TRUE;
+       return 0;
+}
+
+static gint inc_recv_data_finished(Session *session, guint len, gpointer data)
+{
+       inc_recv_data_progressive(session, 0, len, data);
+       return 0;
 }
 
-void inc_progress_update(Pop3State *state, Pop3Phase phase)
+static gint inc_recv_message(Session *session, const gchar *msg, gpointer data)
 {
        gchar buf[MSGBUFSIZE];
-       IncSession *session = (IncSession *)state->data;
-       IncProgressDialog *inc_dialog = (IncProgressDialog *)session->data;
+       IncSession *inc_session = (IncSession *)data;
+       Pop3Session *pop3_session = POP3_SESSION(session);
+       IncProgressDialog *inc_dialog = (IncProgressDialog *)inc_session->data;
        ProgressDialog *dialog = inc_dialog->dialog;
-       gchar *total_size;
 
-       switch (phase) {
-       case POP3_GREETING_RECV:
+       switch (pop3_session->state) {
+       case POP3_GREETING:
                break;
-       case POP3_GETAUTH_USER_SEND:
-       case POP3_GETAUTH_PASS_SEND:
-       case POP3_GETAUTH_APOP_SEND:
+       case POP3_GETAUTH_USER:
+       case POP3_GETAUTH_PASS:
+       case POP3_GETAUTH_APOP:
                progress_dialog_set_label(dialog, _("Authenticating..."));
                break;
-       case POP3_GETRANGE_STAT_SEND:
+       case POP3_GETRANGE_STAT:
                progress_dialog_set_label
                        (dialog, _("Getting the number of new messages (STAT)..."));
                break;
-       case POP3_GETRANGE_LAST_SEND:
+       case POP3_GETRANGE_LAST:
                progress_dialog_set_label
                        (dialog, _("Getting the number of new messages (LAST)..."));
                break;
-       case POP3_GETRANGE_UIDL_SEND:
+       case POP3_GETRANGE_UIDL:
                progress_dialog_set_label
                        (dialog, _("Getting the number of new messages (UIDL)..."));
                break;
-       case POP3_GETSIZE_LIST_SEND:
+       case POP3_GETSIZE_LIST:
                progress_dialog_set_label
                        (dialog, _("Getting the size of messages (LIST)..."));
                break;
-       case POP3_TOP_SEND:
+       case POP3_TOP:
                g_snprintf(buf, sizeof(buf),
                           _("Retrieving header (%d / %d)"),
-                          state->cur_msg, state->count);
+                          pop3_session->cur_msg, pop3_session->count);
                progress_dialog_set_label (dialog, buf);
                progress_dialog_set_percentage
                        (dialog,
-                        (gfloat)(state->cur_msg) /
-                        (gfloat)(state->count));
+                        (gfloat)(pop3_session->cur_msg) /
+                        (gfloat)(pop3_session->count));
                if (inc_dialog->mainwin)
                        gtk_progress_bar_update 
                                (GTK_PROGRESS_BAR(inc_dialog->mainwin->progressbar),
-                                (gfloat)(state->cur_msg) /
-                                (gfloat)(state->count));
+                                (gfloat)(pop3_session->cur_msg) /
+                                (gfloat)(pop3_session->count));
                break;
-       case POP3_RETR_SEND:
-               Xstrdup_a(total_size, to_human_readable(state->total_bytes), return);
-               g_snprintf(buf, sizeof(buf),
-                          _("Retrieving message (%d / %d) (%s / %s)"),
-                          state->cur_msg, state->count,
-                          to_human_readable(state->cur_total_bytes),
-                          total_size);
-               progress_dialog_set_label(dialog, buf);
-               progress_dialog_set_percentage
-                       (dialog,
-                        (gfloat)(state->cur_total_bytes) /
-                        (gfloat)(state->total_bytes));
-               if (inc_dialog->mainwin)
-                       gtk_progress_bar_update
-                               (GTK_PROGRESS_BAR(inc_dialog->mainwin->progressbar),
-                                (gfloat)(state->cur_total_bytes) /
-                                (gfloat)(state->total_bytes));
+       case POP3_RETR:
+               inc_recv_data_progressive
+                       (session, 0,
+                        pop3_session->msg[pop3_session->cur_msg].size, data);
                break;
-       case POP3_DELETE_SEND:
-               if (state->msg[state->cur_msg].recv_time < state->current_time) {
+       case POP3_DELETE:
+               if (pop3_session->msg[pop3_session->cur_msg].recv_time <
+                       pop3_session->current_time) {
                        g_snprintf(buf, sizeof(buf), _("Deleting message %d"),
-                                  state->cur_msg);
+                                  pop3_session->cur_msg);
                        progress_dialog_set_label(dialog, buf);
                }
                break;
-       case POP3_LOGOUT_SEND:
+       case POP3_LOGOUT:
                progress_dialog_set_label(dialog, _("Quitting"));
                break;
        default:
                break;
        }
+
+       return 0;
 }
 
-gint inc_drop_message(const gchar *file, Pop3State *state)
+gint inc_drop_message(const gchar *file, Pop3Session *session)
 {
        FolderItem *inbox;
        FolderItem *dropfolder;
        gint msgnum;
+       IncSession *inc_session = (IncSession *)(SESSION(session)->data);
+       gint val;
 
-       /* CLAWS: get default inbox (perhaps per account) */
-       if (state->ac_prefs->inbox) {
-               /* CLAWS: get destination folder / mailbox */
+       if (session->ac_prefs->inbox) {
                inbox = folder_find_item_from_identifier
-                       (state->ac_prefs->inbox);
+                       (session->ac_prefs->inbox);
                if (!inbox)
                        inbox = folder_get_default_inbox();
        } else
@@ -1045,7 +953,6 @@ static void inc_put_error(IncState istate)
 static void inc_cancel(IncProgressDialog *dialog)
 {
        IncSession *session;
-       SockInfo *sockinfo;
 
        g_return_if_fail(dialog != NULL);
 
@@ -1055,13 +962,9 @@ static void inc_cancel(IncProgressDialog *dialog)
        }
 
        session = dialog->queue_list->data;
-       sockinfo = session->pop3_state->sockinfo;
-
-       if (!sockinfo || session->atm->terminated == TRUE) return;
 
-       session->pop3_state->cancelled = TRUE;
+       session->session->state = SESSION_DISCONNECTED;
        session->inc_state = INC_CANCEL;
-       session->atm->cancelled = TRUE;
 
        log_message(_("Incorporation cancelled\n"));
 }
index ddb441b..71917c6 100644 (file)
--- a/src/inc.h
+++ b/src/inc.h
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2002 Hiroyuki Yamamoto
+ * Copyright (C) 1999-2003 Hiroyuki Yamamoto
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -30,9 +30,8 @@
 #include "mainwindow.h"
 #include "progressdialog.h"
 #include "prefs_account.h"
+#include "session.h"
 #include "pop.h"
-#include "automaton.h"
-#include "socket.h"
 
 #define MAIL_FILTERING_HOOKLIST "mail_filtering_hooklist"
 
@@ -66,8 +65,7 @@ struct _IncProgressDialog
 
 struct _IncSession
 {
-       Pop3State *pop3_state;
-       Automaton *atm;
+       Session *session;
        IncState inc_state;
 
        gpointer data;
@@ -87,10 +85,9 @@ void inc_all_account_mail    (MainWindow     *mainwin,
 void inc_selective_download     (MainWindow    *mainwin, 
                                 PrefsAccount   *acc,
                                 gint            session);
-void inc_progress_update       (Pop3State      *state,
-                                Pop3Phase       phase);
+void inc_progress_update       (Pop3Session    *session);
 gint inc_drop_message          (const gchar    *file,
-                                Pop3State      *state);
+                                Pop3Session    *session);
 
 void inc_pop_before_smtp       (PrefsAccount   *acc);
 
index ef266cd..84577b4 100644 (file)
@@ -213,17 +213,17 @@ static Session *news_session_new(const gchar *server, gushort port,
        if (nntp_sock == NULL)
                return NULL;
 
-       session = g_new(NNTPSession, 1);
+       session = g_new0(NNTPSession, 1);
        session_init(SESSION(session));
        SESSION(session)->type             = SESSION_NEWS;
        SESSION(session)->server           = g_strdup(server);
-       session->nntp_sock                 = nntp_sock;
-       SESSION(session)->sock             = nntp_sock->sock;
+       SESSION(session)->sock             = NULL;
        SESSION(session)->data             = NULL;
 
        SESSION(session)->destroy          = news_session_destroy;
 
-       session->group = NULL;
+       session->nntp_sock                 = nntp_sock;
+       session->group                     = NULL;
 
        return SESSION(session);
 }
@@ -232,7 +232,6 @@ void news_session_destroy(Session *session)
 {
        nntp_close(NNTP_SESSION(session)->nntp_sock);
        NNTP_SESSION(session)->nntp_sock = NULL;
-       session->sock = NULL;
 
        g_free(NNTP_SESSION(session)->group);
 }
@@ -469,7 +468,8 @@ GSList *news_get_group_list(Folder *folder)
                        g_free(filename);
                        return NULL;
                }
-               if (recv_write_to_file(SESSION(session)->sock, filename) < 0) {
+               if (recv_write_to_file
+                       (session->nntp_sock->sock, filename) < 0) {
                        log_warning("can't retrieve newsgroup list\n");
                        session_destroy(SESSION(session));
                        REMOTE_FOLDER(folder)->session = NULL;
index 87c5631..09de1e1 100644 (file)
--- a/src/pop.c
+++ b/src/pop.c
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2002 Hiroyuki Yamamoto
+ * Copyright (C) 1999-2003 Hiroyuki Yamamoto
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 #include "intl.h"
 #include "pop.h"
-#include "socket.h"
 #include "md5.h"
 #include "prefs_account.h"
 #include "utils.h"
 #include "inc.h"
 #include "recv.h"
+/* disable sd
 #include "selective_download.h"
+*/
 #include "log.h"
+
+static gint pop3_greeting_recv         (Pop3Session *session,
+                                        const gchar *msg);
+static gint pop3_getauth_user_send     (Pop3Session *session);
+static gint pop3_getauth_pass_send     (Pop3Session *session);
+static gint pop3_getauth_apop_send     (Pop3Session *session);
 #if USE_OPENSSL
-#  include "ssl.h"
+static gint pop3_stls_send             (Pop3Session *session);
+static gint pop3_stls_recv             (Pop3Session *session);
 #endif
-
-#define LOOKUP_NEXT_MSG()                                                      \
-{                                                                              \
-       Pop3MsgInfo *msg;                                                       \
-       PrefsAccount *ac = state->ac_prefs;                                     \
-       gint size;                                                              \
-       gboolean size_limit_over;                                               \
-                                                                               \
-       for (;;) {                                                              \
-               msg = &state->msg[state->cur_msg];                              \
-               size = msg->size;                                               \
-               size_limit_over =                                               \
-                   (ac->enable_size_limit &&                                   \
-                    ac->size_limit > 0 &&                                      \
-                    size > ac->size_limit * 1024);                             \
-                                                                               \
-               if (ac->rmmail &&                                               \
-                   msg->recv_time != RECV_TIME_NONE &&                         \
-                   msg->recv_time != RECV_TIME_KEEP &&                         \
-                   state->current_time - msg->recv_time >=                     \
-                   ac->msg_leave_time * 24 * 60 * 60) {                        \
-                       log_print(_("POP3: Deleting expired message %d\n"),     \
-                                 state->cur_msg);                              \
-                       return POP3_DELETE_SEND;                                \
-               }                                                               \
-                                                                               \
-               if (size_limit_over)                                            \
-                       log_print(_("POP3: Skipping message %d (%d bytes)\n"),  \
-                                 state->cur_msg, size);                        \
-                                                                               \
-               if (size == 0 || msg->received || size_limit_over) {            \
-                       state->cur_total_bytes += size;                         \
-                       if (state->cur_msg == state->count)                     \
-                               return POP3_LOGOUT_SEND;                        \
-                       else                                                    \
-                               state->cur_msg++;                               \
-               } else                                                          \
-                       break;                                                  \
-       }                                                                       \
-}
-
-static gint pop3_ok(SockInfo *sock, gchar *argbuf);
-static void pop3_gen_send(SockInfo *sock, const gchar *format, ...);
-static gint pop3_gen_recv(SockInfo *sock, gchar *buf, gint size);
+static gint pop3_getrange_stat_send    (Pop3Session *session);
+static gint pop3_getrange_stat_recv    (Pop3Session *session,
+                                        const gchar *msg);
+static gint pop3_getrange_last_send    (Pop3Session *session);
+static gint pop3_getrange_last_recv    (Pop3Session *session,
+                                        const gchar *msg);
+static gint pop3_getrange_uidl_send    (Pop3Session *session);
+static gint pop3_getrange_uidl_recv    (Pop3Session *session,
+                                        const gchar *msg);
+static gint pop3_getsize_list_send     (Pop3Session *session);
+static gint pop3_getsize_list_recv     (Pop3Session *session,
+                                        const gchar *msg);
+static gint pop3_retr_send             (Pop3Session *session);
+static gint pop3_retr_recv             (Pop3Session *session,
+                                        const gchar *data,
+                                        guint        len);
+static gint pop3_retr_eom_recv         (Pop3Session *session,
+                                        const gchar *msg);
+static gint pop3_delete_send           (Pop3Session *session);
+static gint pop3_delete_recv           (Pop3Session *session);
+static gint pop3_logout_send           (Pop3Session *session);
+
+static void pop3_gen_send              (Pop3Session    *session,
+                                        const gchar    *format, ...);
+
+static void pop3_session_destroy       (Session        *session);
+
+static gint pop3_write_msg_to_file     (const gchar    *file,
+                                        const gchar    *data,
+                                        guint           len);
+
+static Pop3State pop3_lookup_next      (Pop3Session    *session);
+static gint pop3_ok                    (Pop3Session    *session,
+                                        const gchar    *msg);
+
+static gint pop3_session_recv_msg              (Session        *session,
+                                                const gchar    *msg);
+static gint pop3_session_recv_data_finished    (Session        *session,
+                                                guchar         *data,
+                                                guint           len);
+/* disable sd
 static gboolean pop3_sd_get_next (Pop3State *state);
 static void pop3_sd_new_header(Pop3State *state);
 gboolean pop3_sd_state(Pop3State *state, gint cur_state, guint *next_state);
-
-gint pop3_greeting_recv(SockInfo *sock, gpointer data)
+*/
+static gint pop3_greeting_recv(Pop3Session *session, const gchar *msg)
 {
-       Pop3State *state = (Pop3State *)data;
-       gchar buf[POPBUFSIZE];
-       gint ok;
+       session->state = POP3_GREETING;
 
-       if ((ok = pop3_ok(sock, buf)) == PS_SUCCESS) {
-               state->greeting = g_strdup(buf);
-#if USE_OPENSSL
-               if (state->ac_prefs->ssl_pop == SSL_STARTTLS)
-                       return POP3_STLS_SEND;
-#endif
-               if (state->ac_prefs->protocol == A_APOP)
-                       return POP3_GETAUTH_APOP_SEND;
-               else
-                       return POP3_GETAUTH_USER_SEND;
-       } else {
-               state->error_val = ok;
-               return -1;
-       }
+       session->greeting = g_strdup(msg);
+       return PS_SUCCESS;
 }
 
 #if USE_OPENSSL
-gint pop3_stls_send(SockInfo *sock, gpointer data)
+static gint pop3_stls_send(Pop3Session *session)
 {
-       pop3_gen_send(sock, "STLS");
-
-       return POP3_STLS_RECV;
+       session->state = POP3_STLS;
+       pop3_gen_send(session, "STLS");
+       return PS_SUCCESS;
 }
 
-gint pop3_stls_recv(SockInfo *sock, gpointer data)
+static gint pop3_stls_recv(Pop3Session *session)
 {
-       Pop3State *state = (Pop3State *)data;
-       gint ok;
-
-       if ((ok = pop3_ok(sock, NULL)) == PS_SUCCESS) {
-               if (!ssl_init_socket_with_method(sock, SSL_METHOD_TLSv1)) {
-                       state->error_val = PS_SOCKET;
-                       return -1;
-               }
-               if (state->ac_prefs->protocol == A_APOP)
-                       return POP3_GETAUTH_APOP_SEND;
-               else
-                       return POP3_GETAUTH_USER_SEND;
-       } else if (ok == PS_PROTOCOL) {
-               log_warning(_("can't start TLS session\n"));
-               state->error_val = ok;
-               return POP3_LOGOUT_SEND;
-       } else {
-               state->error_val = ok;
+       if (session_start_tls(SESSION(session)) < 0) {
+               session->error_val = PS_SOCKET;
                return -1;
        }
+       return PS_SUCCESS;
 }
 #endif /* USE_OPENSSL */
 
-gint pop3_getauth_user_send(SockInfo *sock, gpointer data)
-{
-       Pop3State *state = (Pop3State *)data;
-
-       g_return_val_if_fail(state->user != NULL, -1);
-
-       pop3_gen_send(sock, "USER %s", state->user);
-
-       return POP3_GETAUTH_USER_RECV;
-}
-
-gint pop3_getauth_user_recv(SockInfo *sock, gpointer data)
+static gint pop3_getauth_user_send(Pop3Session *session)
 {
-       Pop3State *state = (Pop3State *)data;
+       g_return_val_if_fail(session->user != NULL, -1);
 
-       if (pop3_ok(sock, NULL) == PS_SUCCESS)
-               return POP3_GETAUTH_PASS_SEND;
-       else {
-               log_warning(_("error occurred on authentication\n"));
-               state->error_val = PS_AUTHFAIL;
-               return -1;
-       }
+       session->state = POP3_GETAUTH_USER;
+       pop3_gen_send(session, "USER %s", session->user);
+       return PS_SUCCESS;
 }
 
-gint pop3_getauth_pass_send(SockInfo *sock, gpointer data)
+static gint pop3_getauth_pass_send(Pop3Session *session)
 {
-       Pop3State *state = (Pop3State *)data;
+       g_return_val_if_fail(session->pass != NULL, -1);
 
-       g_return_val_if_fail(state->pass != NULL, -1);
-
-       pop3_gen_send(sock, "PASS %s", state->pass);
-
-       return POP3_GETAUTH_PASS_RECV;
+       session->state = POP3_GETAUTH_PASS;
+       pop3_gen_send(session, "PASS %s", session->pass);
+       return PS_SUCCESS;
 }
 
-gint pop3_getauth_pass_recv(SockInfo *sock, gpointer data)
+static gint pop3_getauth_apop_send(Pop3Session *session)
 {
-       Pop3State *state = (Pop3State *)data;
-       gint ok;
-
-       if ((ok = pop3_ok(sock, NULL)) == PS_SUCCESS)
-               return POP3_GETRANGE_STAT_SEND;
-       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;
-               return -1;
-       }
-}
-
-gint pop3_getauth_apop_send(SockInfo *sock, gpointer data)
-{
-       Pop3State *state = (Pop3State *)data;
        gchar *start, *end;
        gchar *apop_str;
        gchar md5sum[33];
 
-       g_return_val_if_fail(state->user != NULL, -1);
-       g_return_val_if_fail(state->pass != NULL, -1);
+       g_return_val_if_fail(session->user != NULL, -1);
+       g_return_val_if_fail(session->pass != NULL, -1);
 
-       if ((start = strchr(state->greeting, '<')) == NULL) {
+       session->state = POP3_GETAUTH_APOP;
+
+       if ((start = strchr(session->greeting, '<')) == NULL) {
                log_warning(_("Required APOP timestamp not found "
                              "in greeting\n"));
-               state->error_val = PS_PROTOCOL;
+               session->error_val = PS_PROTOCOL;
                return -1;
        }
 
        if ((end = strchr(start, '>')) == NULL || end == start + 1) {
                log_warning(_("Timestamp syntax error in greeting\n"));
-               state->error_val = PS_PROTOCOL;
+               session->error_val = PS_PROTOCOL;
                return -1;
        }
 
        *(end + 1) = '\0';
 
-       apop_str = g_strconcat(start, state->pass, NULL);
+       apop_str = g_strconcat(start, session->pass, NULL);
        md5_hex_digest(md5sum, apop_str);
        g_free(apop_str);
 
-       pop3_gen_send(sock, "APOP %s %s", state->user, md5sum);
-
-       return POP3_GETAUTH_APOP_RECV;
-}
+       pop3_gen_send(session, "APOP %s %s", session->user, md5sum);
 
-gint pop3_getauth_apop_recv(SockInfo *sock, gpointer data)
-{
-       Pop3State *state = (Pop3State *)data;
-       gint ok;
-
-       if ((ok = pop3_ok(sock, NULL)) == PS_SUCCESS)
-               return POP3_GETRANGE_STAT_SEND;
-       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;
-               return -1;
-       }
+       return PS_SUCCESS;
 }
 
-gint pop3_getrange_stat_send(SockInfo *sock, gpointer data)
+static gint pop3_getrange_stat_send(Pop3Session *session)
 {
-       pop3_gen_send(sock, "STAT");
-
-       return POP3_GETRANGE_STAT_RECV;
+       session->state = POP3_GETRANGE_STAT;
+       pop3_gen_send(session, "STAT");
+       return PS_SUCCESS;
 }
 
-gint pop3_getrange_stat_recv(SockInfo *sock, gpointer data)
+static gint pop3_getrange_stat_recv(Pop3Session *session, const gchar *msg)
 {
-       Pop3State *state = (Pop3State *)data;
-       gchar buf[POPBUFSIZE + 1];
-       gint ok;
-
-       if ((ok = pop3_ok(sock, buf)) == PS_SUCCESS) {
-               if (sscanf(buf, "%d %d", &state->count, &state->total_bytes)
-                   != 2) {
-                       log_warning(_("POP3 protocol error\n"));
-                       state->error_val = PS_PROTOCOL;
-                       return -1;
+       if (sscanf(msg, "%d %d", &session->count, &session->total_bytes) != 2) {
+               log_warning(_("POP3 protocol error\n"));
+               session->error_val = PS_PROTOCOL;
+               return -1;
+       } else {
+               if (session->count == 0) {
+                       session->uidl_is_valid = TRUE;
                } else {
-                       if (state->count == 0) {
-                               state->uidl_is_valid = TRUE;
-                               return POP3_LOGOUT_SEND;
-                       } else {
-                               state->msg = g_new0
-                                       (Pop3MsgInfo, state->count + 1);
-                               state->cur_msg = 1;
-                               return POP3_GETRANGE_UIDL_SEND;
-                       }
+                       session->msg = g_new0(Pop3MsgInfo, session->count + 1);
+                       session->cur_msg = 1;
                }
-       } else if (ok == PS_PROTOCOL) {
-               state->error_val = ok;
-               return POP3_LOGOUT_SEND;
-       } else {
-               state->error_val = ok;
-               return -1;
        }
+
+       return PS_SUCCESS;
 }
 
-gint pop3_getrange_last_send(SockInfo *sock, gpointer data)
+static gint pop3_getrange_last_send(Pop3Session *session)
 {
-       pop3_gen_send(sock, "LAST");
-
-       return POP3_GETRANGE_LAST_RECV;
+       session->state = POP3_GETRANGE_LAST;
+       pop3_gen_send(session, "LAST");
+       return PS_SUCCESS;
 }
 
-gint pop3_getrange_last_recv(SockInfo *sock, gpointer data)
+static gint pop3_getrange_last_recv(Pop3Session *session, const gchar *msg)
 {
-       Pop3State *state = (Pop3State *)data;
-       gchar buf[POPBUFSIZE + 1];
+       gint last;
 
-       if (pop3_ok(sock, buf) == PS_SUCCESS) {
-               gint last;
+       if (sscanf(msg, "%d", &last) == 0) {
+               log_warning(_("POP3 protocol error\n"));
+               session->error_val = PS_PROTOCOL;
+               return -1;
+       } else {
+               if (session->count > last)
+                       session->cur_msg = last + 1;
+               else
+                       session->cur_msg = 0;
+       }
 
-               if (sscanf(buf, "%d", &last) == 0) {
-                       log_warning(_("POP3 protocol error\n"));
-                       state->error_val = PS_PROTOCOL;
-                       return -1;
-               } else {
-                       if (state->count == last)
-                               return POP3_LOGOUT_SEND;
-                       else {
-                               state->cur_msg = last + 1;
-                               return POP3_GETSIZE_LIST_SEND;
-                       }
-               }
-       } else
-               return POP3_GETSIZE_LIST_SEND;
+       return PS_SUCCESS;
 }
 
-gint pop3_getrange_uidl_send(SockInfo *sock, gpointer data)
+static gint pop3_getrange_uidl_send(Pop3Session *session)
 {
-       pop3_gen_send(sock, "UIDL");
-
-       return POP3_GETRANGE_UIDL_RECV;
+       session->state = POP3_GETRANGE_UIDL;
+       pop3_gen_send(session, "UIDL");
+       return PS_SUCCESS;
 }
 
-gint pop3_getrange_uidl_recv(SockInfo *sock, gpointer data)
+static gint pop3_getrange_uidl_recv(Pop3Session *session, const gchar *msg)
 {
-       Pop3State *state = (Pop3State *)data;
-       gboolean new = FALSE;
-       gboolean get_all = FALSE;
-       gchar buf[POPBUFSIZE];
        gchar id[IDLEN + 1];
-       gint len;
+       gint num;
+       time_t recv_time;
        gint next_state;
 
-       if (!state->uidl_table) new = TRUE;
-#if 0
-       if (state->ac_prefs->getall ||
-           (state->ac_prefs->rmmail && state->ac_prefs->msg_leave_time == 0))
-#endif
-       if (state->ac_prefs->getall)
-               get_all = TRUE;
-
-       if (pop3_ok(sock, NULL) != PS_SUCCESS) {
-               /* UIDL is not supported */
-               if (pop3_sd_state(state, POP3_GETRANGE_UIDL_RECV, &next_state))
-                       return next_state;
-
-               if (!get_all)
-                       return POP3_GETRANGE_LAST_SEND;
-               else
-                       return POP3_GETSIZE_LIST_SEND;
+       if (msg[0] == '.') {
+               session->uidl_is_valid = TRUE;
+               return PS_SUCCESS;
        }
 
-       while ((len = sock_gets(sock, buf, sizeof(buf))) > 0) {
-               gint num;
-               time_t recv_time;
-
-               if (buf[0] == '.') break;
-               if (sscanf(buf, "%d %" Xstr(IDLEN) "s", &num, id) != 2)
-                       continue;
-               if (num <= 0 || num > state->count) continue;
+       if (sscanf(msg, "%d %" Xstr(IDLEN) "s", &num, id) != 2)
+               return -1;
+       if (num <= 0 || num > session->count)
+               return -1;
 
-               state->msg[num].uidl = g_strdup(id);
+       session->msg[num].uidl = g_strdup(id);
 
-               if (!state->uidl_table) continue;
+       if (!session->uidl_table)
+               return PS_CONTINUE;
 
-               recv_time = (time_t)g_hash_table_lookup(state->uidl_table, id);
-               state->msg[num].recv_time = recv_time;
+       recv_time = (time_t)g_hash_table_lookup(session->uidl_table, id);
+       session->msg[num].recv_time = recv_time;
 
-               if (!get_all && recv_time != RECV_TIME_NONE)
-                       state->msg[num].received = TRUE;
+       if (!session->ac_prefs->getall && recv_time != RECV_TIME_NONE)
+               session->msg[num].received = TRUE;
 
-               if (new == FALSE &&
-                   (get_all || recv_time == RECV_TIME_NONE ||
-                    state->ac_prefs->rmmail)) {
-                       state->cur_msg = num;
-                       new = TRUE;
-               }
+       if (!session->new_msg_exist &&
+           (session->ac_prefs->getall || recv_time == RECV_TIME_NONE ||
+            session->ac_prefs->rmmail)) {
+               session->cur_msg = num;
+               session->new_msg_exist = TRUE;
        }
 
-       if (len < 0) {
-               log_error(_("Socket error\n"));
-               state->error_val = PS_SOCKET;
-               return -1;
-       }
-
-       state->uidl_is_valid = TRUE;
+/* disable sd
        if (pop3_sd_state(state, POP3_GETRANGE_UIDL_RECV, &next_state))
                return next_state;
-
-       if (new == TRUE)
-               return POP3_GETSIZE_LIST_SEND;
-       else
-               return POP3_LOGOUT_SEND;
+*/
+       return PS_CONTINUE;
 }
 
-gint pop3_getsize_list_send(SockInfo *sock, gpointer data)
+static gint pop3_getsize_list_send(Pop3Session *session)
 {
-       pop3_gen_send(sock, "LIST");
-
-       return POP3_GETSIZE_LIST_RECV;
+       session->state = POP3_GETSIZE_LIST;
+       pop3_gen_send(session, "LIST");
+       return PS_SUCCESS;
 }
 
-gint pop3_getsize_list_recv(SockInfo *sock, gpointer data)
+static gint pop3_getsize_list_recv(Pop3Session *session, const gchar *msg)
 {
-       Pop3State *state = (Pop3State *)data;
-       gchar buf[POPBUFSIZE];
-       gint len;
+       guint num, size;
        gint next_state;
 
-       if (pop3_ok(sock, NULL) != PS_SUCCESS) return POP3_LOGOUT_SEND;
-
-       state->cur_total_bytes = 0;
-       state->cur_total_recv_bytes = 0;
-
-       while ((len = sock_gets(sock, buf, sizeof(buf))) > 0) {
-               guint num, size;
-
-               if (buf[0] == '.') break;
-               if (sscanf(buf, "%u %u", &num, &size) != 2) {
-                       state->error_val = PS_PROTOCOL;
-                       return -1;
-               }
-
-               if (num > 0 && num <= state->count)
-                       state->msg[num].size = size;
-               if (num > 0 && num < state->cur_msg)
-                       state->cur_total_bytes += size;
-       }
+       if (msg[0] == '.')
+               return PS_SUCCESS;
 
-       if (len < 0) {
-               log_error(_("Socket error\n"));
-               state->error_val = PS_SOCKET;
+       if (sscanf(msg, "%u %u", &num, &size) != 2) {
+               session->error_val = PS_PROTOCOL;
                return -1;
        }
 
+       if (num > 0 && num <= session->count)
+               session->msg[num].size = size;
+       if (num > 0 && num < session->cur_msg)
+               session->cur_total_bytes += size;
+
+/* disable sd
        if (pop3_sd_state(state, POP3_GETSIZE_LIST_RECV, &next_state))
                return next_state;
-
-       LOOKUP_NEXT_MSG();
-       return POP3_RETR_SEND;
+*/
+       return PS_CONTINUE;
 }
+/* disable sd 
 gint pop3_top_send(SockInfo *sock, gpointer data)
 {
        Pop3State *state = (Pop3State *)data;
@@ -492,168 +351,83 @@ gint pop3_top_recv(SockInfo *sock, gpointer data)
        } else
                return POP3_LOGOUT_SEND;
 }
-
-gint pop3_retr_send(SockInfo *sock, gpointer data)
+*/
+static gint pop3_retr_send(Pop3Session *session)
 {
-       Pop3State *state = (Pop3State *)data;
-
-       pop3_gen_send(sock, "RETR %d", state->cur_msg);
-
-       return POP3_RETR_RECV;
+       session->state = POP3_RETR;
+       pop3_gen_send(session, "RETR %d", session->cur_msg);
+       return PS_SUCCESS;
 }
 
-gint pop3_retr_recv(SockInfo *sock, gpointer data)
+static gint pop3_retr_recv(Pop3Session *session, const gchar *data, guint len)
 {
-       Pop3State *state = (Pop3State *)data;
        gchar *file;
-       gint ok, drop_ok;
+       gint drop_ok;
        gint next_state;
-       gint write_val;
-       if ((ok = pop3_ok(sock, NULL)) == PS_SUCCESS) {
-               file = get_tmp_file();
-               if ((write_val = recv_write_to_file(sock, file)) < 0) {
-                       g_free(file);
-                       if (!state->cancelled)
-                               state->error_val = 
-                                       (write_val == -1 ? PS_IOERR : PS_SOCKET);
-                       return -1;
-               }
 
-               /* drop_ok: 0: success 1: don't receive -1: error */
-               drop_ok = inc_drop_message(file, state);
+       file = get_tmp_file();
+       if (pop3_write_msg_to_file(file, data, len) < 0) {
                g_free(file);
-               if (drop_ok < 0) {
-                       state->error_val = PS_ERROR;
-                       return -1;
-               }
-
-               if (pop3_sd_state(state, POP3_RETR_RECV, &next_state))
-                       return next_state;
-       
-               state->cur_total_bytes += state->msg[state->cur_msg].size;
-               state->cur_total_recv_bytes += state->msg[state->cur_msg].size;
-               state->cur_total_num++;
-
-               state->msg[state->cur_msg].received = TRUE;
-               state->msg[state->cur_msg].recv_time =
-                       drop_ok == 1 ? RECV_TIME_KEEP : state->current_time;
-
-               if (drop_ok == 0 && state->ac_prefs->rmmail &&
-                   state->ac_prefs->msg_leave_time == 0)
-                       return POP3_DELETE_SEND;
-
-               if (state->cur_msg < state->count) {
-                       state->cur_msg++;
-                       LOOKUP_NEXT_MSG();
-                       return POP3_RETR_SEND;
-               } else
-                       return POP3_LOGOUT_SEND;
-       } else if (ok == PS_PROTOCOL) {
-               state->error_val = ok;
-               return POP3_LOGOUT_SEND;
-       } else {
-               state->error_val = ok;
+               session->error_val = PS_IOERR;
                return -1;
        }
-}
 
-gint pop3_delete_send(SockInfo *sock, gpointer data)
-{
-       Pop3State *state = (Pop3State *)data;
+       /* drop_ok: 0: success 1: don't receive -1: error */
+       drop_ok = inc_drop_message(file, session);
+       g_free(file);
+       if (drop_ok < 0) {
+               session->error_val = PS_ERROR;
+               return -1;
+       }
+/* disable sd
+       if (pop3_sd_state(state, POP3_RETR_RECV, &next_state))
+               return next_state;
+*/     
+       session->cur_total_bytes += session->msg[session->cur_msg].size;
+       session->cur_total_recv_bytes += session->msg[session->cur_msg].size;
+       session->cur_total_num++;
 
-       pop3_gen_send(sock, "DELE %d", state->cur_msg);
+       session->msg[session->cur_msg].received = TRUE;
+       session->msg[session->cur_msg].recv_time =
+               drop_ok == 1 ? RECV_TIME_KEEP : session->current_time;
 
-       return POP3_DELETE_RECV;
+       return PS_SUCCESS;
 }
 
-gint pop3_delete_recv(SockInfo *sock, gpointer data)
+static gint pop3_retr_eom_recv(Pop3Session *session, const gchar *msg)
 {
-       Pop3State *state = (Pop3State *)data;
-       gint next_state;
-       gint ok;
-
-       if ((ok = pop3_ok(sock, NULL)) == PS_SUCCESS) {
-               state->msg[state->cur_msg].deleted = TRUE;
-               
-               if (pop3_sd_state(state, POP3_DELETE_RECV, &next_state))
-                       return next_state;      
-
-               if (state->cur_msg < state->count) {
-                       state->cur_msg++;
-                       LOOKUP_NEXT_MSG();
-                       return POP3_RETR_SEND;
-               } else
-                       return POP3_LOGOUT_SEND;
-       } else if (ok == PS_PROTOCOL) {
-               state->error_val = ok;
-               return POP3_LOGOUT_SEND;
-       } else {
-               state->error_val = ok;
-               return -1;
+       if (msg[0] == '.' && msg[1] == '\0')
+               return PS_SUCCESS;
+       else {
+               g_warning("pop3_retr_eom_recv(): "
+                         "invalid end of message: '%s'.\n"
+                         "Maybe given size and actual one is different?\n",
+                         msg);
+               return PS_PROTOCOL;
        }
 }
 
-gint pop3_logout_send(SockInfo *sock, gpointer data)
+static gint pop3_delete_send(Pop3Session *session)
 {
-       pop3_gen_send(sock, "QUIT");
-
-       return POP3_LOGOUT_RECV;
+       session->state = POP3_DELETE;
+       pop3_gen_send(session, "DELE %d", session->cur_msg);
+       return PS_SUCCESS;
 }
 
-gint pop3_logout_recv(SockInfo *sock, gpointer data)
+static gint pop3_delete_recv(Pop3Session *session)
 {
-       Pop3State *state = (Pop3State *)data;
-       gint ok;
-
-       if ((ok = pop3_ok(sock, NULL)) != PS_SUCCESS)
-               state->error_val = ok;
-
-       return -1;
+       session->msg[session->cur_msg].deleted = TRUE;
+       return PS_SUCCESS;
 }
 
-static gint pop3_ok(SockInfo *sock, gchar *argbuf)
+static gint pop3_logout_send(Pop3Session *session)
 {
-       gint ok;
-       gchar buf[POPBUFSIZE + 1];
-       gchar *bufp;
-
-       if ((ok = pop3_gen_recv(sock, buf, sizeof(buf))) == PS_SUCCESS) {
-               bufp = buf;
-               if (*bufp == '+' || *bufp == '-')
-                       bufp++;
-               else
-                       return PS_PROTOCOL;
-
-               while (isalpha(*bufp))
-                       bufp++;
-
-               if (*bufp)
-                       *(bufp++) = '\0';
-
-               if (!strcmp(buf, "+OK"))
-                       ok = PS_SUCCESS;
-               else if (!strncmp(buf, "-ERR", 4)) {
-                       if (strstr(bufp, "lock") ||
-                                strstr(bufp, "Lock") ||
-                                strstr(bufp, "LOCK") ||
-                                strstr(bufp, "wait"))
-                               ok = PS_LOCKBUSY;
-                       else
-                               ok = PS_PROTOCOL;
-
-                       if (*bufp)
-                               fprintf(stderr, "POP3: %s\n", bufp);
-               } else
-                       ok = PS_PROTOCOL;
-
-               if (argbuf)
-                       strcpy(argbuf, bufp);
-       }
-
-       return ok;
+       session->state = POP3_LOGOUT;
+       pop3_gen_send(session, "QUIT");
+       return PS_SUCCESS;
 }
 
-static void pop3_gen_send(SockInfo *sock, const gchar *format, ...)
+static void pop3_gen_send(Pop3Session *session, const gchar *format, ...)
 {
        gchar buf[POPBUFSIZE + 1];
        va_list args;
@@ -667,22 +441,9 @@ static void pop3_gen_send(SockInfo *sock, const gchar *format, ...)
        else
                log_print("POP3> %s\n", buf);
 
-       strcat(buf, "\r\n");
-       sock_write_all(sock, buf, strlen(buf));
-}
-
-static gint pop3_gen_recv(SockInfo *sock, gchar *buf, gint size)
-{
-       if (sock_gets(sock, buf, size) < 0) {
-               return PS_SOCKET;
-       } else {
-               strretchomp(buf);
-               log_print("POP3< %s\n", buf);
-
-               return PS_SUCCESS;
-       }
+       session_send_msg(SESSION(session), SESSION_MSG_NORMAL, buf);
 }
-
+/* disable sd
 static void pop3_sd_new_header(Pop3State *state)
 {
        HeaderItems *new_msg;
@@ -831,44 +592,56 @@ gboolean pop3_sd_get_next(Pop3State *state)
                return FALSE;
        }
 }
-
-Pop3State *pop3_state_new(PrefsAccount *account)
+*/
+Session *pop3_session_new(PrefsAccount *account)
 {
-       Pop3State *state;
+       Pop3Session *session;
 
        g_return_val_if_fail(account != NULL, NULL);
 
-       state = g_new0(Pop3State, 1);
+       session = g_new0(Pop3Session, 1);
+
+       SESSION(session)->type = SESSION_POP3;
+       SESSION(session)->server = NULL;
+       SESSION(session)->port = 0;
+       SESSION(session)->sock = NULL;
+       SESSION(session)->state = SESSION_READY;
+       SESSION(session)->data = NULL;
+
+       SESSION(session)->recv_msg = pop3_session_recv_msg;
+       SESSION(session)->recv_data_finished = pop3_session_recv_data_finished;
+       SESSION(session)->send_data_finished = NULL;
 
-       state->ac_prefs = account;
-       state->uidl_table = pop3_get_uidl_table(account);
-       state->current_time = time(NULL);
-       state->error_val = PS_SUCCESS;
+       SESSION(session)->destroy = pop3_session_destroy;
 
-       return state;
+       session->state = POP3_READY;
+       session->ac_prefs = account;
+       session->uidl_table = pop3_get_uidl_table(account);
+       session->current_time = time(NULL);
+       session->error_val = PS_SUCCESS;
+
+       return SESSION(session);
 }
 
-void pop3_state_destroy(Pop3State *state)
+static void pop3_session_destroy(Session *session)
 {
+       Pop3Session *pop3_session = POP3_SESSION(session);
        gint n;
 
-       g_return_if_fail(state != NULL);
+       g_return_if_fail(session != NULL);
 
-       for (n = 1; n <= state->count; n++)
-               g_free(state->msg[n].uidl);
-       g_free(state->msg);
+       for (n = 1; n <= pop3_session->count; n++)
+               g_free(pop3_session->msg[n].uidl);
+       g_free(pop3_session->msg);
 
-       if (state->uidl_table) {
-               hash_free_strings(state->uidl_table);
-               g_hash_table_destroy(state->uidl_table);
+       if (pop3_session->uidl_table) {
+               hash_free_strings(pop3_session->uidl_table);
+               g_hash_table_destroy(pop3_session->uidl_table);
        }
 
-       g_free(state->greeting);
-       g_free(state->user);
-       g_free(state->pass);
-       g_free(state->prev_folder);
-
-       g_free(state);
+       g_free(pop3_session->greeting);
+       g_free(pop3_session->user);
+       g_free(pop3_session->pass);
 }
 
 GHashTable *pop3_get_uidl_table(PrefsAccount *ac_prefs)
@@ -921,27 +694,27 @@ GHashTable *pop3_get_uidl_table(PrefsAccount *ac_prefs)
        return table;
 }
 
-gint pop3_write_uidl_list(Pop3State *state)
+gint pop3_write_uidl_list(Pop3Session *session)
 {
        gchar *path;
        FILE *fp;
        Pop3MsgInfo *msg;
        gint n;
 
-       if (!state->uidl_is_valid) return 0;
+       if (!session->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);
+                          session->ac_prefs->recv_server,
+                          "-", session->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];
+       for (n = 1; n <= session->count; n++) {
+               msg = &session->msg[n];
                if (msg->uidl && msg->received && !msg->deleted)
                        fprintf(fp, "%s\t%ld\n", msg->uidl, msg->recv_time);
        }
@@ -951,3 +724,300 @@ gint pop3_write_uidl_list(Pop3State *state)
 
        return 0;
 }
+
+static gint pop3_write_msg_to_file(const gchar *file, const gchar *data,
+                                  guint len)
+{
+       FILE *fp;
+       const gchar *prev, *cur;
+
+       g_return_val_if_fail(file != NULL, -1);
+
+       if ((fp = fopen(file, "wb")) == NULL) {
+               FILE_OP_ERROR(file, "fopen");
+               return -1;
+       }
+
+       if (change_file_mode_rw(fp, file) < 0)
+               FILE_OP_ERROR(file, "chmod");
+
+       /* +------------------+----------------+--------------------------+ *
+        * ^data              ^prev            ^cur             data+len-1^ */
+
+       prev = data;
+       while ((cur = memchr(prev, '\r', len - (prev - data))) != NULL) {
+               if ((cur > prev && fwrite(prev, cur - prev, 1, fp) < 1) ||
+                   fputc('\n', fp) == EOF) {
+                       FILE_OP_ERROR(file, "fwrite");
+                       g_warning("can't write to file: %s\n", file);
+                       fclose(fp);
+                       unlink(file);
+                       return -1;
+               }
+
+               if (cur == data + len - 1) {
+                       prev = cur + 1;
+                       break;
+               }
+
+               if (*(cur + 1) == '\n')
+                       prev = cur + 2;
+               else
+                       prev = cur + 1;
+
+               if (prev - data >= len)
+                       break;
+       }
+
+       if (prev - data < len &&
+           fwrite(prev, len - (prev - data), 1, fp) < 1) {
+               FILE_OP_ERROR(file, "fwrite");
+               g_warning("can't write to file: %s\n", file);
+               fclose(fp);
+               unlink(file);
+               return -1;
+       }
+       if (data[len - 1] != '\r' && data[len - 1] != '\n') {
+               if (fputc('\n', fp) == EOF) {
+                       FILE_OP_ERROR(file, "fputc");
+                       g_warning("can't write to file: %s\n", file);
+                       fclose(fp);
+                       unlink(file);
+                       return -1;
+               }
+       }
+
+       if (fclose(fp) == EOF) {
+               FILE_OP_ERROR(file, "fclose");
+               unlink(file);
+               return -1;
+       }
+
+       return 0;
+}
+
+static Pop3State pop3_lookup_next(Pop3Session *session)
+{
+       Pop3MsgInfo *msg;
+       PrefsAccount *ac = session->ac_prefs;
+       gint size;
+       gboolean size_limit_over;
+
+       for (;;) {
+               msg = &session->msg[session->cur_msg];
+               size = msg->size;
+               size_limit_over =
+                   (ac->enable_size_limit &&
+                    ac->size_limit > 0 &&
+                    size > ac->size_limit * 1024);
+
+               if (ac->rmmail &&
+                   msg->recv_time != RECV_TIME_NONE &&
+                   msg->recv_time != RECV_TIME_KEEP &&
+                   session->current_time - msg->recv_time >=
+                   ac->msg_leave_time * 24 * 60 * 60) {
+                       log_print(_("POP3: Deleting expired message %d\n"),
+                                 session->cur_msg);
+                       pop3_delete_send(session);
+                       return POP3_DELETE;
+               }
+
+               if (size_limit_over)
+                       log_print
+                               (_("POP3: Skipping message %d (%d bytes)\n"),
+                                 session->cur_msg, size);
+
+               if (size == 0 || msg->received || size_limit_over) {
+                       session->cur_total_bytes += size;
+                       if (session->cur_msg == session->count) {
+                               pop3_logout_send(session);
+                               return POP3_LOGOUT;
+                       } else
+                               session->cur_msg++;
+               } else
+                       break;
+       }
+
+       pop3_retr_send(session);
+       return POP3_RETR;
+}
+
+static gint pop3_ok(Pop3Session *session, const gchar *msg)
+{
+       gint ok;
+
+       if (!strncmp(msg, "+OK", 3))
+               ok = PS_SUCCESS;
+       else if (!strncmp(msg, "-ERR", 4)) {
+               if (strstr(msg + 4, "lock") ||
+                   strstr(msg + 4, "Lock") ||
+                   strstr(msg + 4, "LOCK") ||
+                   strstr(msg + 4, "wait"))
+                       ok = PS_LOCKBUSY;
+               else
+                       ok = PS_PROTOCOL;
+
+               fprintf(stderr, "POP3: %s\n", msg);
+       } else
+               ok = PS_PROTOCOL;
+
+       return ok;
+}
+
+static gint pop3_session_recv_msg(Session *session, const gchar *msg)
+{
+       Pop3Session *pop3_session = POP3_SESSION(session);
+       gint val;
+       const gchar *body;
+
+       body = msg;
+       if (pop3_session->state != POP3_GETRANGE_UIDL_RECV &&
+           pop3_session->state != POP3_GETSIZE_LIST_RECV &&
+           pop3_session->state != POP3_RETR_EOM) {
+               log_print("POP3< %s\n", msg);
+               val = pop3_ok(pop3_session, msg);
+               if (val != PS_SUCCESS) {
+                       pop3_session->state = POP3_ERROR;
+                       pop3_session->error_val = val;
+                       return -1;
+               }
+
+               if (*body == '+' || *body == '-')
+                       body++;
+               while (isalpha(*body))
+                       body++;
+               while (isspace(*body))
+                       body++;
+       }
+
+       switch (pop3_session->state) {
+       case POP3_READY:
+       case POP3_GREETING:
+               pop3_greeting_recv(pop3_session, body);
+#if USE_OPENSSL
+               if (pop3_session->ac_prefs->ssl_pop == SSL_STARTTLS)
+                       pop3_stls_send(pop3_session);
+               else
+#endif
+               if (pop3_session->ac_prefs->protocol == A_APOP)
+                       pop3_getauth_apop_send(pop3_session);
+               else
+                       pop3_getauth_user_send(pop3_session);
+               break;
+#if USE_OPENSSL
+       case POP3_STLS:
+               if (pop3_stls_recv(pop3_session) != PS_SUCCESS)
+                       return -1;
+               if (pop3_session->ac_prefs->protocol == A_APOP)
+                       pop3_getauth_apop_send(pop3_session);
+               else
+                       pop3_getauth_user_send(pop3_session);
+               break;
+#endif
+       case POP3_GETAUTH_USER:
+               pop3_getauth_pass_send(pop3_session);
+               break;
+       case POP3_GETAUTH_PASS:
+       case POP3_GETAUTH_APOP:
+               pop3_getrange_stat_send(pop3_session);
+               break;
+       case POP3_GETRANGE_STAT:
+               if (pop3_getrange_stat_recv(pop3_session, body) < 0)
+                       return -1;
+               if (pop3_session->count > 0)
+                       pop3_getrange_uidl_send(pop3_session);
+               else
+                       pop3_logout_send(pop3_session);
+               break;
+       case POP3_GETRANGE_LAST:
+               if (pop3_getrange_last_recv(pop3_session, body) < 0)
+                       return -1;
+               if (pop3_session->cur_msg > 0)
+                       pop3_getsize_list_send(pop3_session);
+               else
+                       pop3_logout_send(pop3_session);
+               break;
+       case POP3_GETRANGE_UIDL:
+               pop3_session->state = POP3_GETRANGE_UIDL_RECV;
+               return 1;
+       case POP3_GETRANGE_UIDL_RECV:
+               val = pop3_getrange_uidl_recv(pop3_session, body);
+               if (val == PS_CONTINUE)
+                       return 1;
+               else if (val == PS_SUCCESS) {
+                       if (pop3_session->new_msg_exist)
+                               pop3_getsize_list_send(pop3_session);
+                       else
+                               pop3_logout_send(pop3_session);
+               } else
+                       return -1;
+               break;
+       case POP3_GETSIZE_LIST:
+               pop3_session->state = POP3_GETSIZE_LIST_RECV;
+               return 1;
+       case POP3_GETSIZE_LIST_RECV:
+               val = pop3_getsize_list_recv(pop3_session, body);
+               if (val == PS_CONTINUE)
+                       return 1;
+               else if (val == PS_SUCCESS) {
+                       if (pop3_lookup_next(pop3_session) == POP3_ERROR)
+                               return -1;
+               } else
+                       return -1;
+               break;
+       case POP3_RETR:
+               pop3_session->state = POP3_RETR_RECV;
+               session_recv_data
+                       (session,
+                        pop3_session->msg[pop3_session->cur_msg].size, TRUE);
+               break;
+       case POP3_RETR_EOM:
+               if (pop3_retr_eom_recv(pop3_session, body) != PS_SUCCESS)
+                       return -1;
+               if (pop3_session->ac_prefs->rmmail &&
+                   pop3_session->ac_prefs->msg_leave_time == 0)
+                       pop3_delete_send(pop3_session);
+               else if (pop3_session->cur_msg == pop3_session->count)
+                       pop3_logout_send(pop3_session);
+               else {
+                       pop3_session->cur_msg++;
+                       if (pop3_lookup_next(pop3_session) == POP3_ERROR)
+                               return -1;
+               }
+               break;
+       case POP3_DELETE:
+               pop3_delete_recv(pop3_session);
+               if (pop3_session->cur_msg == pop3_session->count)
+                       pop3_logout_send(pop3_session);
+               else {
+                       pop3_session->cur_msg++;
+                       if (pop3_lookup_next(pop3_session) == POP3_ERROR)
+                               return -1;
+               }
+               break;
+       case POP3_LOGOUT:
+               session_disconnect(session);
+               break;
+       case POP3_ERROR:
+       default:
+               return -1;
+       }
+
+       return 0;
+}
+
+static gint pop3_session_recv_data_finished(Session *session, guchar *data,
+                                           guint len)
+{
+       Pop3Session *pop3_session = POP3_SESSION(session);
+
+       if (len == 0)
+               return -1;
+
+       if (pop3_retr_recv(pop3_session, data, len) < 0)
+               return -1;
+
+       pop3_session->state = POP3_RETR_EOM;
+
+       return 1;
+}
index 85e27db..08a8abd 100644 (file)
--- a/src/pop.h
+++ b/src/pop.h
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2002 Hiroyuki Yamamoto
+ * Copyright (C) 1999-2003 Hiroyuki Yamamoto
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include <glib.h>
 #include <time.h>
 
-#include "socket.h"
+#include "session.h"
 #include "prefs_account.h"
 
 typedef struct _Pop3MsgInfo    Pop3MsgInfo;
-typedef struct _Pop3State      Pop3State;
+typedef struct _Pop3Session    Pop3Session;
+
+#define POP3_SESSION(obj)      ((Pop3Session *)obj)
 
 typedef enum {
-       POP3_GREETING_RECV,
+       POP3_READY,
+       POP3_GREETING,
 #if USE_OPENSSL
-       POP3_STLS_SEND,
-       POP3_STLS_RECV,
+       POP3_STLS,
 #endif
-       POP3_GETAUTH_USER_SEND,
-       POP3_GETAUTH_USER_RECV,
-       POP3_GETAUTH_PASS_SEND,
-       POP3_GETAUTH_PASS_RECV,
-       POP3_GETAUTH_APOP_SEND,
-       POP3_GETAUTH_APOP_RECV,
-       POP3_GETRANGE_STAT_SEND,
-       POP3_GETRANGE_STAT_RECV,
-       POP3_GETRANGE_LAST_SEND,
-       POP3_GETRANGE_LAST_RECV,
-       POP3_GETRANGE_UIDL_SEND,
+       POP3_GETAUTH_USER,
+       POP3_GETAUTH_PASS,
+       POP3_GETAUTH_APOP,
+       POP3_GETRANGE_STAT,
+       POP3_GETRANGE_LAST,
+       POP3_GETRANGE_UIDL,
        POP3_GETRANGE_UIDL_RECV,
-       POP3_GETSIZE_LIST_SEND,
+       POP3_GETSIZE_LIST,
        POP3_GETSIZE_LIST_RECV,
-       POP3_TOP_SEND,                   
-       POP3_TOP_RECV,                    
-       POP3_RETR_SEND,
+       POP3_RETR,
+       POP3_TOP,                   
        POP3_RETR_RECV,
-       POP3_DELETE_SEND,
-       POP3_DELETE_RECV,
-       POP3_LOGOUT_SEND,
-       POP3_LOGOUT_RECV,
+       POP3_RETR_EOM,
+       POP3_DELETE,
+       POP3_LOGOUT,
+       POP3_ERROR,
 
-       N_POP3_PHASE
-} Pop3Phase;
+       N_POP3_STATE
+} Pop3State;
 
 typedef enum {
        RECV_TIME_NONE     = 0,
@@ -80,19 +76,19 @@ struct _Pop3MsgInfo
        guint deleted  : 1;
 };
 
-struct _Pop3State
+struct _Pop3Session
 {
-       PrefsAccount *ac_prefs;
+       Session session;
 
+       Pop3State state;
        gchar *prev_folder;
 
-       SockInfo *sockinfo;
+       PrefsAccount *ac_prefs;
 
        gchar *greeting;
        gchar *user;
        gchar *pass;
        gint count;
-       gint new;
        gint total_bytes;
        gint cur_msg;
        gint cur_total_num;
@@ -103,8 +99,8 @@ struct _Pop3State
 
        GHashTable *uidl_table;
 
+       gboolean new_msg_exist;
        gboolean uidl_is_valid;
-       gboolean cancelled;
 
        time_t current_time;
 
@@ -138,37 +134,10 @@ struct _Pop3State
 #define                PS_RETAINED     26      /* message retained (internal use) */
 #define                PS_TRUNCATED    27      /* headers incomplete (internal use) */
 
-gint pop3_greeting_recv                (SockInfo *sock, gpointer data);
-gint pop3_getauth_user_send    (SockInfo *sock, gpointer data);
-gint pop3_getauth_user_recv    (SockInfo *sock, gpointer data);
-gint pop3_getauth_pass_send    (SockInfo *sock, gpointer data);
-gint pop3_getauth_pass_recv    (SockInfo *sock, gpointer data);
-gint pop3_getauth_apop_send    (SockInfo *sock, gpointer data);
-gint pop3_getauth_apop_recv    (SockInfo *sock, gpointer data);
-#if USE_OPENSSL
-gint pop3_stls_send            (SockInfo *sock, gpointer data);
-gint pop3_stls_recv            (SockInfo *sock, gpointer data);
-#endif
-gint pop3_getrange_stat_send   (SockInfo *sock, gpointer data);
-gint pop3_getrange_stat_recv   (SockInfo *sock, gpointer data);
-gint pop3_getrange_last_send   (SockInfo *sock, gpointer data);
-gint pop3_getrange_last_recv   (SockInfo *sock, gpointer data);
-gint pop3_getrange_uidl_send   (SockInfo *sock, gpointer data);
-gint pop3_getrange_uidl_recv   (SockInfo *sock, gpointer data);
-gint pop3_getsize_list_send    (SockInfo *sock, gpointer data);
-gint pop3_getsize_list_recv    (SockInfo *sock, gpointer data);
-gint pop3_top_send              (SockInfo *sock, gpointer data);
-gint pop3_top_recv              (SockInfo *sock, gpointer data);
-gint pop3_retr_send            (SockInfo *sock, gpointer data);
-gint pop3_retr_recv            (SockInfo *sock, gpointer data);
-gint pop3_delete_send          (SockInfo *sock, gpointer data);
-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);
+#define                PS_CONTINUE     128
+
+Session *pop3_session_new      (PrefsAccount   *account);
 GHashTable *pop3_get_uidl_table        (PrefsAccount   *account);
-gint pop3_write_uidl_list      (Pop3State      *state);
+gint pop3_write_uidl_list      (Pop3Session    *session);
 
 #endif /* __POP_H__ */