Cleanup of lots of exception handling ; bugfixes
authorPeter Williams <peterw@src.gnome.org>
Tue, 5 Sep 2000 20:08:09 +0000 (20:08 +0000)
committerPeter Williams <peterw@src.gnome.org>
Tue, 5 Sep 2000 20:08:09 +0000 (20:08 +0000)
camel/ChangeLog
camel/camel-remote-store.c
camel/camel-remote-store.h
camel/camel.c
camel/providers/imap/camel-imap-folder.c
camel/providers/imap/camel-imap-store.c
camel/providers/imap/camel-imap-store.h
camel/providers/nntp/camel-nntp-store.c
camel/providers/pop3/camel-pop3-folder.c
camel/providers/pop3/camel-pop3-store.c
camel/providers/pop3/camel-pop3-store.h

index 53a99e5..b8ee78a 100644 (file)
@@ -1,3 +1,19 @@
+2000-09-05  Peter Williams  <peterw@helixcode.com>
+
+       * providers/imap/camel-imap-store.c (imap_folder_exists): Don't free the
+       result on error; the exception will have the relevant info.
+
+       * providers/imap/camel-imap-folder.c (camel_imap_folder_new): Check for
+       exceptions here.
+
+       * providers/imap/camel-imap-store.c (imap_connect): Check the exception
+       on the refresh_folders call.
+
+       * providers/imap/camel-imap-store.h: Clean up some now-unused fields.
+
+       * camel.c (camel_init): Call unicode_init again, now that libunicode
+       will not initialize itself twice.
+
 2000-09-02  Lauris Kaplinski  <lauris@helixcode.com>
 
        * camel-folder-search (search_header_contains): Use e_utf8_strstrcase
@@ -7,6 +23,59 @@
        * providers/imap/camel-imap-utils.c: Removed some unused
        functions.
 
+2000-09-01  Peter Williams  <peterw@helixcode.com>
+
+       * providers/nntp/camel-nntp-store.c (camel_nntp_command): Initialize
+       the statically-allocated CamelException so that it doesn't contain
+       junk data that camel_exception_set() may try to free.
+       (camel_nntp_store_get_extensions): Same.
+       (camel_nntp_store_get_overview_fmt): Same.
+
+       * providers/pop3/camel-pop3-store.c (camel_pop3_command): Typo
+       fix (if (*ret) -> if (ret)).
+
+       * providers/pop3/camel-pop3-store.c (pop3_connect): Set the
+       port # back to what was specified ASAP, so that the hash of
+       the URL doesn't change (which causes a failure in
+       service_cache_remove that leads to a segfault).
+
+       * providers/imap/camel-imap-store.c (imap_connect): Clear the 
+       exception after a failed LOGIN so that it doesn't pass through
+       to the upper level and make mail think that the login failed.
+
+       * providers/pop3/camel-pop3-store.c (pop3_connect): As above.
+
+2000-08-31  Peter Williams  <peterw@helixcode.com>
+
+       * providers/pop3/camel-pop3-store.c (camel_pop3_store_get_type):
+       Implement POP3 with the CamelRemoteStore now.
+       (connect_to_server): Hack this a bit to get KPOP to work. Obey
+       the new connection semantics of the remote store (implicitly).
+       (query_auth_types_connected): Clear exceptions after attempts
+       to connect; the code at the bottom will catch hard errors.
+       Use camel_service_connect.
+       (camel_pop3_command): Take a CamelException; now, when an error
+       occurs, ret is set to NULL and the exception passes back the
+       appropriate information.
+       (pop3_get_response): Same as above.
+       (pop3_try_authenticate): Give camel_pop3_command its exception
+       and handle it properly.
+       (pop3_connect): Call the parent classfuncs. Don't disconnect
+       on error (done for us).
+
+       * providers/pop3/camel-pop3-folder.c: Obey the camel_pop3_command
+       semantics.
+
+       * camel-remote-store.c (remote_query_auth_types_connected): Don't
+       warn; just return NULL.
+       (remote_query_auth_types_generic): Same.
+       (remote_send_string): Filter out passwords in debugging output.
+
+       * providers/pop3/camel-pop3-store.c (camel_pop3_store_init): Also
+       set the ALLOW_AUTH flag.
+
+       * providers/imap/camel-imap-store.c (camel_imap_store_init): Same.
+
 2000-08-31  Chris Toshok  <toshok@helixcode.com>
 
        * providers/nntp/camel-nntp-store.c (camel_nntp_store_class_init):
index d11fd0b..afbd3a7 100644 (file)
@@ -149,8 +149,8 @@ camel_remote_store_get_type (void)
 static CamelServiceAuthType password_authtype = {
        "SSH Tunneling",
        
-       "This option will connect to the REMOTE server using a "
-       "plaintext password.",
+       "This option will connect to the server using a "
+       "SSH tunnel.",
        
        "",
        TRUE
@@ -160,14 +160,12 @@ static CamelServiceAuthType password_authtype = {
 static GList *
 remote_query_auth_types_connected (CamelService *service, CamelException *ex)
 {
-       g_warning ("remote::query_auth_types_connected: not implemented. Defaulting.");
-       return CSRVC (service)->query_auth_types_generic (service, ex);
+       return NULL;
 }
 
 static GList *
 remote_query_auth_types_generic (CamelService *service, CamelException *ex)
 {
-       g_warning ("remote::query_auth_types_generic: not implemented. Defaulting.");
        return NULL;
 }
 
@@ -192,14 +190,6 @@ remote_get_name (CamelService *service, gboolean brief)
        }
 }
 
-static void
-refresh_folder_info (gpointer key, gpointer value, gpointer data)
-{
-       CamelFolder *folder = CAMEL_FOLDER (value);
-       
-       camel_folder_refresh_info (folder, (CamelException *) data);
-}
-
 static gboolean
 timeout_cb (gpointer data)
 {
@@ -277,9 +267,6 @@ remote_connect (CamelService *service, CamelException *ex)
                                                                    store);
        }
        
-       /* Let's make sure that any of our folders are brought up to speed */
-       g_hash_table_foreach (CAMEL_STORE (store)->folders, refresh_folder_info, ex);
-       
        return TRUE;
 }
 
@@ -333,8 +320,15 @@ remote_send_string (CamelRemoteStore *store, CamelException *ex, char *fmt, va_l
        
        /* create the command */
        cmdbuf = g_strdup_vprintf (fmt, ap);
-       
-       d(fprintf (stderr, "sending : %s", cmdbuf));
+
+#if d(!)0
+       if (strncmp (cmdbuf, "PASS ", 5) == 0)
+               fprintf (stderr, "sending : PASS xxxx\n");
+       else if (strstr (cmdbuf, "LOGIN \""))
+               fprintf (stderr, "sending : ---- LOGIN \"xxxx\" \"xxxx\"\n");
+       else
+               fprintf (stderr, "sending : %s", cmdbuf);
+#endif
        
        if (camel_stream_printf (store->ostream, "%s", cmdbuf) == -1) {
                CamelException dex;
@@ -493,3 +487,26 @@ camel_remote_store_recv_line (CamelRemoteStore *store, char **dest,
        
        return CRSC (store)->recv_line (store, dest, ex);
 }
+
+static void
+refresh_folder_info (gpointer key, gpointer value, gpointer data)
+{
+       CamelFolder *folder = CAMEL_FOLDER (value);
+       
+       camel_folder_refresh_info (folder, (CamelException *) data);
+}
+
+/**
+ * camel_remote_store_refresh_folders: Refresh the folders that I
+ * contain
+ * @store: a CamelRemoteStore
+ * @ex: a CamelException
+ *
+ * Refreshes the folders listed in the folders hashtable.
+ **/
+
+void
+camel_remote_store_refresh_folders (CamelRemoteStore *store, CamelException *ex)
+{
+       g_hash_table_foreach (CAMEL_STORE (store)->folders, refresh_folder_info, ex);
+}      
index 627b012..4530c22 100644 (file)
@@ -69,7 +69,8 @@ gint camel_remote_store_send_stream (CamelRemoteStore *store, CamelStream *strea
                                     CamelException *ex);
 gint camel_remote_store_recv_line (CamelRemoteStore *store, char **dest,
                                   CamelException *ex);
-
+void camel_remote_store_refresh_folders (CamelRemoteStore *store, 
+                                        CamelException *ex);
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index dd46295..0121c10 100644 (file)
@@ -40,8 +40,7 @@ camel_init(void)
 #endif /* G_THREADS_ENABLED */
 #endif /* ENABLE_THREADS */
 
-       /* Taken care of by e-util/e-unicode.c */
-       /*unicode_init ();*/
+       unicode_init ();
 
        return 0;
 }
index c4c26db..5b55f6b 100644 (file)
@@ -191,11 +191,21 @@ camel_imap_folder_new (CamelStore *parent, char *folder_name, CamelException *ex
        
        CF_CLASS (folder)->init (folder, parent, NULL, folder_name, dir_sep, FALSE, ex);
        
+       if (camel_exception_is_set (ex)) {
+               camel_object_unref (CAMEL_OBJECT (folder));
+               return NULL;
+       }
+
        if (!strcmp (folder_name, url->path + 1))
                folder->can_hold_messages = FALSE;
        
        CF_CLASS (folder)->refresh_info (folder, ex);
 
+       if (camel_exception_is_set (ex)) {
+               camel_object_unref (CAMEL_OBJECT (folder));
+               return NULL;
+       }
+
        return folder;
 }
 
index 820c245..5ffdd51 100644 (file)
@@ -95,7 +95,8 @@ camel_imap_store_init (gpointer object, gpointer klass)
        
        service->url_flags |= (CAMEL_SERVICE_URL_NEED_USER |
                               CAMEL_SERVICE_URL_NEED_HOST |
-                              CAMEL_SERVICE_URL_ALLOW_PATH);
+                              CAMEL_SERVICE_URL_ALLOW_PATH |
+                              CAMEL_SERVICE_URL_ALLOW_AUTH);
        
        imap_store->dir_sep = g_strdup ("/"); /*default*/
        imap_store->current_folder = NULL;
@@ -231,6 +232,7 @@ imap_connect (CamelService *service, CamelException *ex)
                        errbuf = g_strdup_printf ("Unable to authenticate to IMAP server.\n"
                                                  "%s\n\n",
                                                  camel_exception_get_description (ex));
+                       camel_exception_clear (ex);
                } else {
                        g_message ("IMAP Service sucessfully authenticated user %s", service->url->user);
                        authenticated = TRUE;
@@ -280,8 +282,10 @@ imap_connect (CamelService *service, CamelException *ex)
        }
        
        g_free (result);
-       
-       return TRUE;
+
+       camel_remote_store_refresh_folders (CAMEL_REMOTE_STORE (store), ex);
+
+       return ! camel_exception_is_set (ex);
 }
 
 static gboolean
@@ -336,7 +340,6 @@ imap_folder_exists (CamelFolder *folder, CamelException *ex)
                                              &result, ex, "EXAMINE %s", folder_path);
        
        if (status != CAMEL_IMAP_OK) {
-               g_free (result);
                g_free (folder_path);
                return FALSE;
        }
@@ -439,6 +442,9 @@ get_folder (CamelStore *store, const char *folder_name, gboolean create, CamelEx
        
        new_folder = camel_imap_folder_new (store, folder_path, ex);
        
+       if (camel_exception_is_set (ex))
+               return NULL;
+
        /* this is the top-level dir, we already know it exists - it has to! */
        if (!strcmp (folder_name, dir_sep))
                return new_folder;
index 7aa911f..2b946f0 100644 (file)
@@ -50,7 +50,6 @@ typedef struct {
        CamelRemoteStore parent_object; 
        
        CamelFolder *current_folder;
-       CamelStream *istream, *ostream;
        
        guint32 command;
        
@@ -58,8 +57,6 @@ typedef struct {
        gboolean has_status_capability;
        
        gchar *dir_sep;
-       
-       guint timeout_id;
 } CamelImapStore;
 
 
index 521b802..75b8ef9 100644 (file)
@@ -66,6 +66,8 @@ camel_nntp_store_get_extensions (CamelNNTPStore *store)
                gboolean done = FALSE;
                CamelException ex;
 
+               camel_exception_init (&ex);
+
                while (!done) {
                        char *line;
 
@@ -118,6 +120,8 @@ camel_nntp_store_get_overview_fmt (CamelNNTPStore *store)
        gboolean done = FALSE;
        CamelException ex;
 
+       camel_exception_init (&ex);
+
        status = camel_nntp_command (store, NULL,
                                     "LIST OVERVIEW.FMT");
 
@@ -407,6 +411,8 @@ camel_nntp_command (CamelNNTPStore *store, char **ret, char *fmt, ...)
        char *real_fmt;
        CamelException ex;
 
+       camel_exception_init (&ex);
+
        real_fmt = g_strdup_printf ("%s\r\n", fmt);
 
        va_start (ap, fmt);
index 43c8d9a..f7a86a7 100644 (file)
@@ -134,24 +134,22 @@ pop3_refresh_info (CamelFolder *folder, CamelException *ex)
        CamelPop3Folder *pop3_folder = (CamelPop3Folder *) folder;
        CamelPop3Store *pop3_store = CAMEL_POP3_STORE (folder->parent_store);
 
-       status = camel_pop3_command (pop3_store, &data, "STAT");
-       if (status != CAMEL_POP3_OK) {
-               CamelService *service = CAMEL_SERVICE (pop3_store);
-               camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
-                                     "Could not get message count from POP "
-                                     "server %s: %s.", service->url->host,
-                                     data ? data : "Unknown error");
-               g_free (data);
+       status = camel_pop3_command (pop3_store, &data, ex, "STAT");
+       if (status != CAMEL_POP3_OK)
                return;
-       }
 
        count = atoi (data);
        g_free (data);
 
        if (pop3_store->supports_uidl != FALSE) {
-               status = camel_pop3_command (pop3_store, NULL, "UIDL");
-               if (status != CAMEL_POP3_OK)
+               status = camel_pop3_command (pop3_store, NULL, ex, "UIDL");
+               switch (status) {
+               case CAMEL_POP3_ERR:
                        pop3_store->supports_uidl = FALSE;
+                       break;
+               case CAMEL_POP3_FAIL:
+                       return;
+               }
        }
 
        if (pop3_store->supports_uidl == FALSE) {
@@ -198,16 +196,10 @@ pop3_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
 
        for (i = 0; i < pop3_folder->uids->len; i++) {
                if (pop3_folder->flags[i] & CAMEL_MESSAGE_DELETED) {
-                       status = camel_pop3_command (pop3_store, &resp,
+                       status = camel_pop3_command (pop3_store, &resp, ex,
                                                     "DELE %d", i + 1);
-                       if (status != CAMEL_POP3_OK) {
-                               camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
-                                                     "Unable to sync folder"
-                                                     "%s%s", resp ? ": " : "",
-                                                     resp ? resp : "");
-                               g_free (resp);
+                       if (status != CAMEL_POP3_OK)
                                return;
-                       }
                }
        }
 
@@ -276,17 +268,9 @@ pop3_get_message (CamelFolder *folder, const char *uid, CamelException *ex)
        }
 
        status = camel_pop3_command (CAMEL_POP3_STORE (folder->parent_store),
-                                    &result, "RETR %d", num);
-       if (status != CAMEL_POP3_OK) {
-               CamelService *service = CAMEL_SERVICE (folder->parent_store);
-               camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
-                                     "Could not retrieve message from POP "
-                                     "server %s: %s.", service->url->host,
-                                     status == CAMEL_POP3_ERR ? result :
-                                     "Unknown error");
-               g_free (result);
+                                    &result, ex, "RETR %d", num);
+       if (status != CAMEL_POP3_OK)
                return NULL;
-       }
        g_free (result);
 
        body = camel_pop3_command_get_additional_data (CAMEL_POP3_STORE (folder->parent_store), ex);
index 6ee7361..f27c373 100644 (file)
 #include <unistd.h>
 #include <errno.h>
 
+#ifdef HAVE_KRB4
+/* Specified nowhere */
+#define KPOP_PORT 1109
+
+#include <krb.h>
+
+#ifdef NEED_KRB_SENDAUTH_PROTO
+extern int krb_sendauth(long options, int fd, KTEXT ticket, char *service,
+                       char *inst, char *realm, unsigned KRB4_32 checksum,
+                       MSG_DAT *msg_data, CREDENTIALS *cred,
+                       Key_schedule schedule, struct sockaddr_in *laddr,
+                       struct sockaddr_in *faddr, char *version);
+#endif
+#endif
+
 #include "camel-pop3-store.h"
 #include "camel-pop3-folder.h"
 #include "camel-stream-buffer.h"
 /* Specified in RFC 1939 */
 #define POP3_PORT 110
 
-#ifdef HAVE_KRB4
-/* Specified nowhere */
-#define KPOP_PORT 1109
-
-#include <krb.h>
-#endif
-
-static CamelServiceClass *service_class = NULL;
+static CamelRemoteStoreClass *parent_class = NULL;
 
 static void finalize (CamelObject *object);
 
@@ -64,8 +72,6 @@ static gboolean pop3_connect (CamelService *service, CamelException *ex);
 static gboolean pop3_disconnect (CamelService *service, CamelException *ex);
 static GList *query_auth_types_connected (CamelService *service, CamelException *ex);
 static GList *query_auth_types_generic (CamelService *service, CamelException *ex);
-static void free_auth_types (CamelService *service, GList *authtypes);
-static char *get_name (CamelService *service, gboolean brief);
 
 static CamelFolder *get_folder (CamelStore *store, const char *folder_name, 
                                gboolean create, CamelException *ex);
@@ -73,7 +79,7 @@ static char *get_folder_name (CamelStore *store, const char *folder_name,
                              CamelException *ex);
 static char *get_root_folder_name (CamelStore *store, CamelException *ex);
 
-static int pop3_get_response (CamelPop3Store *store, char **ret);
+static int pop3_get_response (CamelPop3Store *store, char **ret, CamelException *ex);
 
 
 static void
@@ -83,16 +89,18 @@ camel_pop3_store_class_init (CamelPop3StoreClass *camel_pop3_store_class)
                CAMEL_SERVICE_CLASS (camel_pop3_store_class);
        CamelStoreClass *camel_store_class =
                CAMEL_STORE_CLASS (camel_pop3_store_class);
-       
-       service_class = CAMEL_SERVICE_CLASS(camel_type_get_global_classfuncs (camel_service_get_type ()));
+       /*CamelRemoteStoreClass *camel_remote_store_class =
+        *      CAMEL_STORE_CLASS (camel_pop3_store_class);
+        */
+
+       parent_class = CAMEL_REMOTE_STORE_CLASS(camel_type_get_global_classfuncs 
+                                               (camel_remote_store_get_type ()));
 
        /* virtual method overload */
-       camel_service_class->connect = pop3_connect;
-       camel_service_class->disconnect = pop3_disconnect;
        camel_service_class->query_auth_types_connected = query_auth_types_connected;
        camel_service_class->query_auth_types_generic = query_auth_types_generic;
-       camel_service_class->free_auth_types = free_auth_types;
-       camel_service_class->get_name = get_name;
+       camel_service_class->connect = pop3_connect;
+       camel_service_class->disconnect = pop3_disconnect;
 
        camel_store_class->get_folder = get_folder;
        camel_store_class->get_folder_name = get_folder_name;
@@ -106,7 +114,8 @@ camel_pop3_store_init (gpointer object, gpointer klass)
 {
        CamelService *service = CAMEL_SERVICE (object);
 
-       service->url_flags = (CAMEL_SERVICE_URL_NEED_USER | CAMEL_SERVICE_URL_NEED_HOST);
+       service->url_flags |= (CAMEL_SERVICE_URL_NEED_USER | CAMEL_SERVICE_URL_NEED_HOST |
+                              CAMEL_SERVICE_URL_ALLOW_AUTH);
 }
 
 CamelType
@@ -115,7 +124,7 @@ camel_pop3_store_get_type (void)
        static CamelType camel_pop3_store_type = CAMEL_INVALID_TYPE;
 
        if (!camel_pop3_store_type) {
-               camel_pop3_store_type = camel_type_register (CAMEL_STORE_TYPE, "CamelPop3Store",
+               camel_pop3_store_type = camel_type_register (CAMEL_REMOTE_STORE_TYPE, "CamelPop3Store",
                                                             sizeof (CamelPop3Store),
                                                             sizeof (CamelPop3StoreClass),
                                                             (CamelObjectClassInitFunc) camel_pop3_store_class_init,
@@ -131,12 +140,6 @@ static void
 finalize (CamelObject *object)
 {
        CamelPop3Store *pop3_store = CAMEL_POP3_STORE (object);
-       /*CamelException ex;*/
-
-       /*camel_exception_init (&ex);
-        *pop3_disconnect (CAMEL_SERVICE (object), &ex);
-        *camel_exception_clear (&ex);
-        */
 
        if (pop3_store->apop_timestamp)
                g_free (pop3_store->apop_timestamp);
@@ -176,41 +179,15 @@ static CamelServiceAuthType kpop_authtype = {
 #endif
 
 static gboolean
-connect_to_server (CamelService *service, gboolean real, CamelException *ex)
+connect_to_server (CamelService *service, /*gboolean real, */CamelException *ex)
 {
        CamelPop3Store *store = CAMEL_POP3_STORE (service);
-       struct hostent *h;
-       struct sockaddr_in sin;
-       int fd, status;
        char *buf, *apoptime, *apopend;
+       gint status;
 #ifdef HAVE_KRB4
        gboolean kpop = (service->url->port == KPOP_PORT);
 #endif
 
-       h = camel_service_gethost (service, ex);
-       if (!h)
-               return FALSE;
-
-       sin.sin_family = h->h_addrtype;
-       if (service->url->port)
-               sin.sin_port = htons (service->url->port);
-       else
-               sin.sin_port = htons (POP3_PORT);
-       memcpy (&sin.sin_addr, h->h_addr, sizeof (sin.sin_addr));
-
-       fd = socket (h->h_addrtype, SOCK_STREAM, 0);
-       if (fd == -1 ||
-           connect (fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
-               if (real) {
-                       camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
-                                             "Could not connect to %s: %s",
-                                             h->h_name, g_strerror(errno));
-               }
-               if (fd > -1)
-                       close (fd);
-               return FALSE;
-       }
-
 #ifdef HAVE_KRB4
        if (kpop) {
                KTEXT_ST ticket_st;
@@ -218,25 +195,30 @@ connect_to_server (CamelService *service, gboolean real, CamelException *ex)
                CREDENTIALS cred;
                Key_schedule schedule;
                char *hostname;
+               struct hostent *h;
+               int fd;
 
                /* Need to copy hostname, because krb_realmofhost will
                 * call gethostbyname as well, and gethostbyname uses
                 * static storage.
                 */
+               h = camel_service_gethost (service, ex);
                hostname = g_strdup (h->h_name);
+
+               fd = CAMEL_STREAM_FS (CAMEL_REMOTE_STORE (service)->ostream)->fd;
+
                status = krb_sendauth (0, fd, &ticket_st, "pop", hostname,
                                       krb_realmofhost (hostname), 0,
                                       &msg_data, &cred, schedule,
                                       NULL, NULL, "KPOPV0.1");
                g_free (hostname);
                if (status != KSUCCESS) {
-                       if (real) {
+                       /*if (real) {*/
                                camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
                                                      "Could not authenticate "
                                                      "to KPOP server: %s",
                                                      krb_err_txt[status]);
-                       }
-                       close (fd);
+                               /*}*/
                        return FALSE;
                }
 
@@ -245,22 +227,10 @@ connect_to_server (CamelService *service, gboolean real, CamelException *ex)
        }
 #endif /* HAVE_KRB4 */
 
-       store->ostream = camel_stream_fs_new_with_fd (fd);
-       store->istream = camel_stream_buffer_new (store->ostream,
-                                                 CAMEL_STREAM_BUFFER_READ);
-
        /* Read the greeting, check status */
-       status = pop3_get_response (store, &buf);
-       if (status != CAMEL_POP3_OK) {
-               camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
-                                     "%s: %s", status == CAMEL_POP3_ERR ?
-                                     "Error connecting to POP server" :
-                                     "Error reading greeting from POP server",
-                                     buf);
-               g_free (buf);
-               pop3_disconnect (service, ex);
+       status = pop3_get_response (store, &buf, ex);
+       if (status != CAMEL_POP3_OK)
                return FALSE;
-       }
 
        apoptime = strchr (buf, '<');
        apopend = apoptime ? strchr (apoptime, '>') : NULL;
@@ -277,20 +247,14 @@ connect_to_server (CamelService *service, gboolean real, CamelException *ex)
        store->supports_uidl = -1;
        store->expires = -1;
 
-       /* good enough for us */
-       service->connected = TRUE;
-
-       status = camel_pop3_command (store, NULL, "CAPA");
+       status = camel_pop3_command (store, NULL, ex, "CAPA");
        if (status == CAMEL_POP3_OK) {
                char *p;
                int len;
 
                buf = camel_pop3_command_get_additional_data (store, ex);
-               if (camel_exception_is_set (ex)) {
-                       pop3_disconnect (service, ex);
-                       service->connected = FALSE;
+               if (camel_exception_is_set (ex))
                        return FALSE;
-               }
 
                p = buf;
                while (*p) {
@@ -332,24 +296,32 @@ query_auth_types_connected (CamelService *service, CamelException *ex)
        int saved_port;
 #endif
 
-       if (service->url && !service->url->empty) {
-               passwd = connect_to_server (service, FALSE, ex);
-               if (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE)
-                       return NULL;
-               apop = store->apop_timestamp != NULL;
-               if (passwd)
-                       pop3_disconnect (service, ex);
+       ret = CAMEL_SERVICE_CLASS (parent_class)->query_auth_types_connected (service, ex);
+
+       passwd = camel_service_connect (service, ex);
+       /*ignore the exception here; the server may just not support passwd */
+       /*if (camel_exception_is_set (ex) != CAMEL_EXCEPTION_NONE)*/
+       /*return NULL;*/
+       
+       /* should we check apop too? */
+       apop = store->apop_timestamp != NULL;
+       if (passwd)
+               camel_service_disconnect (service, ex);
+       camel_exception_clear (ex);
+
 #ifdef HAVE_KRB4
-               saved_port = service->url->port;
-               service->url->port = KPOP_PORT;
-               kpop = connect_to_server (service, FALSE, ex);
-               service->url->port = saved_port;
-               if (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE)
-                       return NULL;
-               if (kpop)
-                       pop3_disconnect (service, ex);
+       saved_port = service->url->port;
+       service->url->port = KPOP_PORT;
+       kpop = camel_service_connect (service, ex);
+       service->url->port = saved_port;
+       /*ignore the exception here; the server may just not support kpop */
+       /*if (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE)*/
+       /*return NULL;*/
+
+       if (kpop)
+               camel_service_disconnect (service, ex);
+       camel_exception_clear (ex);
 #endif
-       }
 
        if (passwd)
                ret = g_list_append (ret, &password_authtype);
@@ -383,25 +355,6 @@ query_auth_types_generic (CamelService *service, CamelException *ex)
        return ret;
 }
 
-static void
-free_auth_types (CamelService *service, GList *authtypes)
-{
-       g_list_free (authtypes);
-}
-
-static char *
-get_name (CamelService *service, gboolean brief)
-{
-       if (brief)
-               return g_strdup_printf ("POP server %s", service->url->host);
-       else {
-               return g_strdup_printf ("POP service for %s on %s",
-                                       service->url->user,
-                                       service->url->host);
-       }
-}
-
-
 /**
  * camel_pop3_store_expunge:
  * @store: the store
@@ -414,8 +367,8 @@ get_name (CamelService *service, gboolean brief)
 void
 camel_pop3_store_expunge (CamelPop3Store *store, CamelException *ex)
 {
-       camel_pop3_command (store, NULL, "QUIT");
-       pop3_disconnect (CAMEL_SERVICE (store), ex);
+       /*camel_pop3_command (store, NULL, ex, "QUIT");*/
+       /*camel_service_disconnect (CAMEL_SERVICE (store), ex);*/
 }
 
 
@@ -449,20 +402,23 @@ pop3_try_authenticate (CamelService *service, gboolean kpop,
        }
 
        if (!service->url->authmech || kpop) {
-               status = camel_pop3_command (store, &msg, "USER %s",
+               status = camel_pop3_command (store, &msg, ex, "USER %s",
                                             service->url->user);
-               if (status != CAMEL_POP3_OK) {
+               switch (status) {
+               case CAMEL_POP3_ERR:
                        camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
                                              "Unable to connect to POP "
                                              "server.\nError sending "
                                              "username: %s",
                                              msg ? msg : "(Unknown)");
                        g_free (msg);
+                       /*fallll*/
+               case CAMEL_POP3_FAIL:
                        return FALSE;
                }
                g_free (msg);
 
-               status = camel_pop3_command (store, &msg, "PASS %s",
+               status = camel_pop3_command (store, &msg, ex, "PASS %s",
                                             service->url->passwd);
        } else if (!strcmp (service->url->authmech, "+APOP")
                   && store->apop_timestamp) {
@@ -477,7 +433,7 @@ pop3_try_authenticate (CamelService *service, gboolean kpop,
                for (s = md5sum, d = md5asc; d < md5asc + 32; s++, d += 2)
                        sprintf (d, "%.2x", *s);
 
-               status = camel_pop3_command (store, &msg, "APOP %s %s",
+               status = camel_pop3_command (store, &msg, ex, "APOP %s %s",
                                             service->url->user, md5asc);
        } else {
                camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
@@ -487,12 +443,12 @@ pop3_try_authenticate (CamelService *service, gboolean kpop,
                return FALSE;
        }
 
-       if (status != CAMEL_POP3_OK) {
+       if (status == CAMEL_POP3_ERR) {
                camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
                                      "Unable to connect to POP server.\n"
                                      "Error sending password: %s",
                                      msg ? msg : "(Unknown)");
-       }
+       } /*if status == camel_pop3_fail, ex will be set*/
 
        g_free (msg);
        return camel_exception_is_set (ex);
@@ -503,17 +459,42 @@ pop3_connect (CamelService *service, CamelException *ex)
 {
        char *errbuf = NULL;
        gboolean tryagain, kpop = FALSE;
+       gboolean res;
 
 #ifdef HAVE_KRB4
+       gboolean set_port = FALSE;
+
        kpop = (service->url->authmech &&
                !strcmp (service->url->authmech, "+KPOP"));
 
-       if (kpop && service->url->port == 0)
+       if (kpop && service->url->port == 0) {
+               set_port = TRUE;
                service->url->port = KPOP_PORT;
+       }
+#endif
+
+       res = CAMEL_SERVICE_CLASS (parent_class)->connect (service, ex);
+
+#ifdef HAVE_KRB4
+       /* This is veeery nasty. When we set the port, we're changing the
+        * hash value of our URL. service_cache_remove() gets called when
+        * we're done checking the mail, but the hash table lookup fails
+        * because the url port has changed. Then, a finalized instance of
+        * the CamelService is stuck in the hash table, and the next time
+        * we try to look up the service, with a URL of port 0, we look
+        * up the freed service and a segfault results.
+        */
+
+       if (kpop && set_port)
+               service->url->port = 0;
 #endif
 
+       if (res == FALSE)
+               return FALSE;
+
        d(printf ("POP3: Connecting to %s\n", service->url->host));
-       if (!connect_to_server (service, TRUE, ex))
+       /*FIXME integrate these functions */
+       if (!connect_to_server (service, ex))
                return FALSE;
 
        camel_exception_clear (ex);
@@ -522,6 +503,7 @@ pop3_connect (CamelService *service, CamelException *ex)
                        errbuf = g_strdup_printf (
                                "%s\n\n",
                                camel_exception_get_description (ex));
+                       camel_exception_clear (ex);
 
                        /* Uncache the password before prompting again. */
                        camel_session_query_authenticator (
@@ -536,13 +518,10 @@ pop3_connect (CamelService *service, CamelException *ex)
                g_free (errbuf);
        } while (tryagain);
 
-       if (camel_exception_is_set (ex)) {
-               pop3_disconnect (service, NULL);
-               service->connected = FALSE;
+       if (camel_exception_is_set (ex))
                return FALSE;
-       }
 
-       return service_class->connect (service, ex);
+       return TRUE;
 }
 
 static gboolean
@@ -550,25 +529,12 @@ pop3_disconnect (CamelService *service, CamelException *ex)
 {
        CamelPop3Store *store = CAMEL_POP3_STORE (service);
 
-       if (!service_class->disconnect (service, ex))
+       camel_pop3_command (store, NULL, ex, "QUIT");
+
+       if (!CAMEL_SERVICE_CLASS (parent_class)->disconnect (service, ex))
                return FALSE;
 
        d(printf ("POP3: Disconnecting from %s\n", service->url->host));
-
-       if (store->ostream) {
-               camel_object_unref (CAMEL_OBJECT (store->ostream));
-               store->ostream = NULL;
-       }
-       if (store->istream) {
-               camel_object_unref (CAMEL_OBJECT (store->istream));
-               store->istream = NULL;
-       }
-
-       if (store->apop_timestamp) {
-               g_free (store->apop_timestamp);
-               store->apop_timestamp = NULL;
-       }
-
        return TRUE;
 }
 
@@ -576,14 +542,6 @@ static CamelFolder *
 get_folder (CamelStore *store, const char *folder_name,
            gboolean create, CamelException *ex)
 {
-       /* CamelService *service = CAMEL_SERVICE (store);
-        *
-        *      if (!camel_service_is_connected (service)) {
-        *      if (!camel_service_connect (service, ex))
-        *              return NULL;
-        *}
-        */
-
        return camel_pop3_folder_new (store, ex);
 }
 
@@ -628,45 +586,16 @@ get_root_folder_name (CamelStore *store, CamelException *ex)
  * result of the command.)
  **/
 int
-camel_pop3_command (CamelPop3Store *store, char **ret, char *fmt, ...)
+camel_pop3_command (CamelPop3Store *store, char **ret, CamelException *ex, char *fmt, ...)
 {
        char *cmdbuf;
        va_list ap;
 
-       /* Check for connectedness. Failed (or cancelled) operations will
-        * close the connection. */
-       if (CAMEL_SERVICE (store)->connected == FALSE) {
-               CamelException ex;
-
-               d(g_message ("pop3: disconnected, reconnecting."));
-               camel_exception_init (&ex);
-               CAMEL_SERVICE_CLASS (CAMEL_OBJECT_GET_CLASS (store))->connect (store, &ex);
-               if (camel_exception_is_set (&ex)) {
-                       camel_exception_clear (&ex);
-                       return CAMEL_POP3_FAIL;
-               }
-               camel_exception_clear (&ex);
-       }
-
-       if (!store->ostream) {
-               /*CamelException ex;
-                *
-                *camel_exception_init (&ex);
-                *if (!camel_service_connect (CAMEL_SERVICE (store), &ex)) {
-                *      if (ret)
-                *              *ret = g_strdup (camel_exception_get_description (&ex));
-                *      camel_exception_clear (&ex);
-                */
-
-               return CAMEL_POP3_FAIL;
-               /*}*/
-       }
-
        va_start (ap, fmt);
        cmdbuf = g_strdup_vprintf (fmt, ap);
        va_end (ap);
 
-#if d(!)0
+#if 0 /*remote-store prints output now*/
        if (!strncmp (cmdbuf, "PASS", 4))
                printf ("POP3: >>> PASS xxx\n");
        else
@@ -674,33 +603,29 @@ camel_pop3_command (CamelPop3Store *store, char **ret, char *fmt, ...)
 #endif
 
        /* Send the command */
-       if (camel_stream_printf (store->ostream, "%s\r\n", cmdbuf) == -1) {
+       if (camel_remote_store_send_string (CAMEL_REMOTE_STORE (store), ex, "%s\r\n", cmdbuf) < 0) {
                g_free (cmdbuf);
-               if (*ret)
-                       *ret = g_strdup (g_strerror (errno));
-               d(printf ("POP3: !!! %s\n", g_strerror (errno)));
+               if (ret)
+                       *ret = NULL;
                return CAMEL_POP3_FAIL;
        }
        g_free (cmdbuf);
 
-       return pop3_get_response (store, ret);
+       return pop3_get_response (store, ret, ex);
 }
 
 static int
-pop3_get_response (CamelPop3Store *store, char **ret)
+pop3_get_response (CamelPop3Store *store, char **ret, CamelException *ex)
 {
        char *respbuf;
        int status;
 
-       respbuf = camel_stream_buffer_read_line (
-               CAMEL_STREAM_BUFFER (store->istream));
-       if (respbuf == NULL) {
+       if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store), &respbuf, ex) < 0) {
                if (ret)
-                       *ret = g_strdup (g_strerror (errno));
-               d(printf ("POP3: !!! %s\n", g_strerror (errno)));
+                       *ret = NULL;
+               d(printf ("POP3: !!! %s\n", camel_exception_get_description (ex)));
                return CAMEL_POP3_FAIL;
        }
-       d(printf ("POP3: <<< %s\n", respbuf));
 
        if (!strncmp (respbuf, "+OK", 3))
                status = CAMEL_POP3_OK;
@@ -739,15 +664,13 @@ pop3_get_response (CamelPop3Store *store, char **ret)
 char *
 camel_pop3_command_get_additional_data (CamelPop3Store *store, CamelException *ex)
 {
-       CamelStreamBuffer *stream = CAMEL_STREAM_BUFFER (store->istream);
        GPtrArray *data;
        char *buf, *p;
        int i, len = 0, status = CAMEL_POP3_OK;
 
        data = g_ptr_array_new ();
        while (1) {
-               buf = camel_stream_buffer_read_line (stream);
-               if (!buf) {
+               if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store), &buf, ex) < 0) {
                        status = CAMEL_POP3_FAIL;
                        break;
                }
@@ -758,7 +681,9 @@ camel_pop3_command_get_additional_data (CamelPop3Store *store, CamelException *e
                g_ptr_array_add (data, buf);
                len += strlen (buf) + 1;
        }
-       g_free (buf);
+       
+       if (buf)
+               g_free (buf);
 
        if (status == CAMEL_POP3_OK) {
                buf = g_malloc0 (len + 1);
@@ -769,7 +694,7 @@ camel_pop3_command_get_additional_data (CamelPop3Store *store, CamelException *e
                        datap = (char *) data->pdata[i];
                        ptr = (*datap == '.') ? datap + 1 : datap;
                        len = strlen (ptr);
-#if d(!)0
+#if 0 /*remote store prints stuff now */
                        if (i == data->len - 1)
                                printf ("POP3: <<<<<< %s\n", ptr);
                        else if (i == 0)
index f5e447d..cfa28f3 100644 (file)
@@ -34,7 +34,7 @@ extern "C" {
 #endif /* __cplusplus }*/
 
 #include "camel-types.h"
-#include "camel-store.h"
+#include "camel-remote-store.h"
 
 #define CAMEL_POP3_STORE_TYPE     (camel_pop3_store_get_type ())
 #define CAMEL_POP3_STORE(obj)     (CAMEL_CHECK_CAST((obj), CAMEL_POP3_STORE_TYPE, CamelPop3Store))
@@ -43,9 +43,8 @@ extern "C" {
 
 
 typedef struct {
-       CamelStore parent_object;
+       CamelRemoteStore parent_object;
 
-       CamelStream *istream, *ostream;
        char *apop_timestamp, *implementation;
        gboolean supports_top, supports_uidl, expires;
        int login_delay;
@@ -55,7 +54,7 @@ typedef struct {
 
 
 typedef struct {
-       CamelStoreClass parent_class;
+       CamelRemoteStoreClass parent_class;
 
 } CamelPop3StoreClass;
 
@@ -65,7 +64,7 @@ void camel_pop3_store_expunge (CamelPop3Store *store, CamelException *ex);
 
 /* support functions */
 enum { CAMEL_POP3_OK, CAMEL_POP3_ERR, CAMEL_POP3_FAIL };
-int camel_pop3_command (CamelPop3Store *store, char **ret, char *fmt, ...);
+int camel_pop3_command (CamelPop3Store *store, char **ret, CamelException *ex, char *fmt, ...);
 char *camel_pop3_command_get_additional_data (CamelPop3Store *store,
                                              CamelException *ex);