Removed from the build. Glory glory hallelujah.
2002-05-22 Jeffrey Stedfast <fejj@ximian.com> * camel-remote-store.c: Removed from the build. Glory glory hallelujah. * camel-disco-store.c: Updated to inherit from CamelStore rather than CamelRemoteStore. * providers/imap/camel-imap-command.c (imap_command_start): Don't use the camel-remote-store shit to send a string. Just use camel_stream_printf for chrissakes. * providers/imap/camel-imap-store.c: Updated to not depend on CamelRemoteStore and to handle STARTTLS. (imap_disconnect_online): Unref the streams. (imap_keepalive): Removed. (camel_imap_store_connected): New function to replace camel_remote_store_connected(). (camel_imap_store_finalize): Unref the streams. (camel_imap_store_recv_line): New function to replace camel_remote_store_recv_line(). (imap_get_capability): Renamed from connect_to_server (connect_to_server): New function to try and connect to the server. (connect_to_server_wrapper): New wrapper function around connect_to_server that takes the ssl modes into consideration. (query_auth_types): Don't bother calling our parent's implementation of query_auth_types() since CamelDiscoStore doesn't have any anyway. (imap_get_name): New method to implement CamelService::get_name svn path=/trunk/; revision=16975
This commit is contained in:
committed by
Jeffrey Stedfast
parent
e7ad5d121b
commit
a9fc56de69
@ -1,3 +1,34 @@
|
||||
2002-05-22 Jeffrey Stedfast <fejj@ximian.com>
|
||||
|
||||
* camel-remote-store.c: Removed from the build. Glory glory
|
||||
hallelujah.
|
||||
|
||||
* camel-disco-store.c: Updated to inherit from
|
||||
CamelStore rather than CamelRemoteStore.
|
||||
|
||||
* providers/imap/camel-imap-command.c (imap_command_start): Don't
|
||||
use the camel-remote-store shit to send a string. Just use
|
||||
camel_stream_printf for chrissakes.
|
||||
|
||||
* providers/imap/camel-imap-store.c: Updated to not depend on
|
||||
CamelRemoteStore and to handle STARTTLS.
|
||||
(imap_disconnect_online): Unref the streams.
|
||||
(imap_keepalive): Removed.
|
||||
(camel_imap_store_connected): New function to replace
|
||||
camel_remote_store_connected().
|
||||
(camel_imap_store_finalize): Unref the streams.
|
||||
(camel_imap_store_recv_line): New function to replace
|
||||
camel_remote_store_recv_line().
|
||||
(imap_get_capability): Renamed from connect_to_server
|
||||
(connect_to_server): New function to try and connect to the
|
||||
server.
|
||||
(connect_to_server_wrapper): New wrapper function around
|
||||
connect_to_server that takes the ssl modes into consideration.
|
||||
(query_auth_types): Don't bother calling our parent's
|
||||
implementation of query_auth_types() since CamelDiscoStore doesn't
|
||||
have any anyway.
|
||||
(imap_get_name): New method to implement CamelService::get_name
|
||||
|
||||
2002-05-18 Not Zed <NotZed@Ximian.com>
|
||||
|
||||
* camel-search-private.c (camel_utf8_getc): If we get an invalid
|
||||
|
||||
@ -73,7 +73,6 @@ libcamel_la_SOURCES = \
|
||||
camel-smime-context.c \
|
||||
camel-smime-utils.c \
|
||||
camel-provider.c \
|
||||
camel-remote-store.c \
|
||||
camel-sasl.c \
|
||||
camel-sasl-anonymous.c \
|
||||
camel-sasl-cram-md5.c \
|
||||
@ -170,7 +169,6 @@ libcamelinclude_HEADERS = \
|
||||
camel-smime-context.h \
|
||||
camel-smime-utils.h \
|
||||
camel-provider.h \
|
||||
camel-remote-store.h \
|
||||
camel-sasl.h \
|
||||
camel-sasl-anonymous.h \
|
||||
camel-sasl-cram-md5.h \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* camel-disco-store.c: abstract class for a disconnectable remote store */
|
||||
/* camel-disco-store.c: abstract class for a disconnectable store */
|
||||
|
||||
/*
|
||||
* Authors: Dan Winship <danw@ximian.com>
|
||||
@ -22,6 +22,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
@ -33,7 +34,7 @@
|
||||
|
||||
#define CDS_CLASS(o) (CAMEL_DISCO_STORE_CLASS (CAMEL_OBJECT_GET_CLASS (o)))
|
||||
|
||||
static CamelRemoteStoreClass *parent_class = NULL;
|
||||
static CamelStoreClass *parent_class = NULL;
|
||||
|
||||
static void disco_construct (CamelService *service, CamelSession *session,
|
||||
CamelProvider *provider, CamelURL *url,
|
||||
@ -64,7 +65,7 @@ camel_disco_store_class_init (CamelDiscoStoreClass *camel_disco_store_class)
|
||||
CamelStoreClass *camel_store_class =
|
||||
CAMEL_STORE_CLASS (camel_disco_store_class);
|
||||
|
||||
parent_class = CAMEL_REMOTE_STORE_CLASS (camel_type_get_global_classfuncs (camel_remote_store_get_type ()));
|
||||
parent_class = CAMEL_STORE_CLASS (camel_type_get_global_classfuncs (camel_store_get_type ()));
|
||||
|
||||
/* virtual method definition */
|
||||
camel_disco_store_class->set_status = set_status;
|
||||
@ -87,10 +88,11 @@ CamelType
|
||||
camel_disco_store_get_type (void)
|
||||
{
|
||||
static CamelType camel_disco_store_type = CAMEL_INVALID_TYPE;
|
||||
|
||||
|
||||
if (camel_disco_store_type == CAMEL_INVALID_TYPE) {
|
||||
camel_disco_store_type = camel_type_register (
|
||||
CAMEL_REMOTE_STORE_TYPE, "CamelDiscoStore",
|
||||
CAMEL_STORE_TYPE,
|
||||
"CamelDiscoStore",
|
||||
sizeof (CamelDiscoStore),
|
||||
sizeof (CamelDiscoStoreClass),
|
||||
(CamelObjectClassInitFunc) camel_disco_store_class_init,
|
||||
@ -98,7 +100,7 @@ camel_disco_store_get_type (void)
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
return camel_disco_store_type;
|
||||
}
|
||||
|
||||
|
||||
@ -29,9 +29,9 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#pragma }
|
||||
#endif /* __cplusplus }*/
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include "camel-remote-store.h"
|
||||
#include <camel/camel-store.h>
|
||||
|
||||
#define CAMEL_DISCO_STORE_TYPE (camel_disco_store_get_type ())
|
||||
#define CAMEL_DISCO_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_DISCO_STORE_TYPE, CamelDiscoStore))
|
||||
@ -39,7 +39,7 @@ extern "C" {
|
||||
#define CAMEL_IS_DISCO_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_DISCO_STORE_TYPE))
|
||||
|
||||
enum {
|
||||
CAMEL_DISCO_STORE_ARG_FIRST = CAMEL_REMOTE_STORE_ARG_FIRST + 100,
|
||||
CAMEL_DISCO_STORE_ARG_FIRST = CAMEL_STORE_ARG_FIRST + 100,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@ -49,7 +49,7 @@ typedef enum {
|
||||
} CamelDiscoStoreStatus;
|
||||
|
||||
struct _CamelDiscoStore {
|
||||
CamelRemoteStore parent_object;
|
||||
CamelStore parent_object;
|
||||
|
||||
CamelDiscoStoreStatus status;
|
||||
CamelDiscoDiary *diary;
|
||||
@ -57,7 +57,7 @@ struct _CamelDiscoStore {
|
||||
|
||||
|
||||
typedef struct {
|
||||
CamelRemoteStoreClass parent_class;
|
||||
CamelStoreClass parent_class;
|
||||
|
||||
void (*set_status) (CamelDiscoStore *,
|
||||
CamelDiscoStoreStatus,
|
||||
|
||||
@ -1,634 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* camel-remote-store.c : class for an remote store */
|
||||
|
||||
/*
|
||||
* Authors: Peter Williams <peterw@ximian.com>
|
||||
* based on camel-imap-provider.c
|
||||
*
|
||||
* Copyright 2000 Ximian, Inc. (www.ximian.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "camel-remote-store.h"
|
||||
#include "camel-folder.h"
|
||||
#include "camel-exception.h"
|
||||
#include "camel-session.h"
|
||||
#include "camel-stream.h"
|
||||
#include "camel-stream-buffer.h"
|
||||
#include "camel-tcp-stream.h"
|
||||
#include "camel-tcp-stream-raw.h"
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
#include "camel-tcp-stream-ssl.h"
|
||||
#endif
|
||||
|
||||
#include "camel-url.h"
|
||||
#include "string-utils.h"
|
||||
|
||||
#include "camel-private.h"
|
||||
#include "camel-operation.h"
|
||||
|
||||
#define d(x) x
|
||||
#if d(!)0
|
||||
extern gboolean camel_verbose_debug;
|
||||
#endif
|
||||
|
||||
#define CSRVC(obj) (CAMEL_SERVICE_CLASS (CAMEL_OBJECT_GET_CLASS (obj)))
|
||||
#define CSTRC(obj) (CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS (obj)))
|
||||
#define CRSC(obj) (CAMEL_REMOTE_STORE_CLASS (CAMEL_OBJECT_GET_CLASS (obj)))
|
||||
|
||||
static CamelStoreClass *parent_class = NULL;
|
||||
|
||||
static void remote_construct (CamelService *service, CamelSession *session,
|
||||
CamelProvider *provider, CamelURL *url,
|
||||
CamelException *ex);
|
||||
static gboolean remote_connect (CamelService *service, CamelException *ex);
|
||||
static gboolean remote_disconnect (CamelService *service, gboolean clean, CamelException *ex);
|
||||
static GList *remote_query_auth_types(CamelService *service, CamelException *ex);
|
||||
static char *remote_get_name (CamelService *service, gboolean brief);
|
||||
static gint remote_send_string (CamelRemoteStore *store, CamelException *ex,
|
||||
char *fmt, va_list ap);
|
||||
static gint remote_send_stream (CamelRemoteStore *store, CamelStream *stream,
|
||||
CamelException *ex);
|
||||
static gint remote_recv_line (CamelRemoteStore *store, char **dest,
|
||||
CamelException *ex);
|
||||
|
||||
static int remote_store_setv (CamelObject *object, CamelException *ex, CamelArgV *args);
|
||||
static int remote_store_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args);
|
||||
|
||||
static void
|
||||
camel_remote_store_class_init (CamelRemoteStoreClass *camel_remote_store_class)
|
||||
{
|
||||
/* virtual method overload */
|
||||
CamelObjectClass *camel_object_class =
|
||||
CAMEL_OBJECT_CLASS (camel_remote_store_class);
|
||||
CamelServiceClass *camel_service_class =
|
||||
CAMEL_SERVICE_CLASS (camel_remote_store_class);
|
||||
|
||||
parent_class = CAMEL_STORE_CLASS (camel_type_get_global_classfuncs (camel_store_get_type ()));
|
||||
|
||||
/* virtual method overload */
|
||||
camel_object_class->setv = remote_store_setv;
|
||||
camel_object_class->getv = remote_store_getv;
|
||||
|
||||
camel_service_class->construct = remote_construct;
|
||||
camel_service_class->connect = remote_connect;
|
||||
camel_service_class->disconnect = remote_disconnect;
|
||||
camel_service_class->query_auth_types = remote_query_auth_types;
|
||||
camel_service_class->get_name = remote_get_name;
|
||||
|
||||
camel_remote_store_class->send_string = remote_send_string;
|
||||
camel_remote_store_class->send_stream = remote_send_stream;
|
||||
camel_remote_store_class->recv_line = remote_recv_line;
|
||||
camel_remote_store_class->keepalive = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
camel_remote_store_init (CamelObject *object)
|
||||
{
|
||||
CamelRemoteStore *remote_store = CAMEL_REMOTE_STORE (object);
|
||||
|
||||
remote_store->istream = NULL;
|
||||
remote_store->ostream = NULL;
|
||||
remote_store->timeout_id = 0;
|
||||
|
||||
remote_store->priv = g_malloc0(sizeof(*remote_store->priv));
|
||||
#ifdef ENABLE_THREADS
|
||||
remote_store->priv->stream_lock = e_mutex_new(E_MUTEX_REC);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
camel_remote_store_finalise (CamelObject *object)
|
||||
{
|
||||
CamelRemoteStore *remote_store = CAMEL_REMOTE_STORE (object);
|
||||
CamelService *service = CAMEL_SERVICE (object);
|
||||
|
||||
if (service->status == CAMEL_SERVICE_CONNECTED) {
|
||||
CamelException ex;
|
||||
|
||||
camel_exception_init (&ex);
|
||||
camel_service_disconnect (service, TRUE, &ex);
|
||||
if (camel_exception_is_set (&ex)) {
|
||||
g_warning ("camel_remote_store_finalize: silent disconnect failure: %s",
|
||||
camel_exception_get_description (&ex));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_THREADS
|
||||
e_mutex_destroy (remote_store->priv->stream_lock);
|
||||
#endif
|
||||
g_free (remote_store->priv);
|
||||
}
|
||||
|
||||
|
||||
CamelType
|
||||
camel_remote_store_get_type (void)
|
||||
{
|
||||
static CamelType camel_remote_store_type = CAMEL_INVALID_TYPE;
|
||||
|
||||
if (camel_remote_store_type == CAMEL_INVALID_TYPE) {
|
||||
camel_remote_store_type =
|
||||
camel_type_register (CAMEL_STORE_TYPE, "CamelRemoteStore",
|
||||
sizeof (CamelRemoteStore),
|
||||
sizeof (CamelRemoteStoreClass),
|
||||
(CamelObjectClassInitFunc) camel_remote_store_class_init,
|
||||
NULL,
|
||||
(CamelObjectInitFunc) camel_remote_store_init,
|
||||
(CamelObjectFinalizeFunc) camel_remote_store_finalise);
|
||||
}
|
||||
|
||||
return camel_remote_store_type;
|
||||
}
|
||||
|
||||
static int
|
||||
remote_store_setv (CamelObject *object, CamelException *ex, CamelArgV *args)
|
||||
{
|
||||
CamelService *service = (CamelService *) object;
|
||||
CamelURL *url = service->url;
|
||||
guint32 tag;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < args->argc; i++) {
|
||||
tag = args->argv[i].tag;
|
||||
|
||||
/* make sure this arg wasn't already handled */
|
||||
if (tag & CAMEL_ARG_IGNORE)
|
||||
continue;
|
||||
|
||||
/* make sure this is an arg we're supposed to handle */
|
||||
if ((tag & CAMEL_ARG_TAG) <= CAMEL_REMOTE_STORE_ARG_FIRST ||
|
||||
(tag & CAMEL_ARG_TAG) >= CAMEL_REMOTE_STORE_ARG_FIRST + 100)
|
||||
continue;
|
||||
|
||||
if (tag == CAMEL_REMOTE_STORE_SSL) {
|
||||
/* set the ssl mode */
|
||||
camel_url_set_param (url, "use_ssl", args->argv[i].ca_str);
|
||||
} else {
|
||||
/* error? */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* let our parent know that we've handled this arg */
|
||||
camel_argv_ignore (args, i);
|
||||
}
|
||||
|
||||
return CAMEL_OBJECT_CLASS (parent_class)->setv (object, ex, args);
|
||||
}
|
||||
|
||||
static int
|
||||
remote_store_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args)
|
||||
{
|
||||
CamelService *service = (CamelService *) object;
|
||||
CamelURL *url = service->url;
|
||||
guint32 tag;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < args->argc; i++) {
|
||||
tag = args->argv[i].tag;
|
||||
|
||||
/* make sure this is an arg we're supposed to handle */
|
||||
if ((tag & CAMEL_ARG_TAG) <= CAMEL_REMOTE_STORE_ARG_FIRST ||
|
||||
(tag & CAMEL_ARG_TAG) >= CAMEL_REMOTE_STORE_ARG_FIRST + 100)
|
||||
continue;
|
||||
|
||||
if (tag == CAMEL_REMOTE_STORE_SSL) {
|
||||
/* get the ssl mode */
|
||||
*args->argv[i].ca_str = (char *) camel_url_get_param (url, "use_ssl");
|
||||
} else {
|
||||
/* error? */
|
||||
}
|
||||
}
|
||||
|
||||
return CAMEL_OBJECT_CLASS (parent_class)->getv (object, ex, args);
|
||||
}
|
||||
|
||||
static void
|
||||
remote_construct (CamelService *service, CamelSession *session,
|
||||
CamelProvider *provider, CamelURL *url,
|
||||
CamelException *ex)
|
||||
{
|
||||
CamelRemoteStore *remote_store = CAMEL_REMOTE_STORE (service);
|
||||
|
||||
CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex);
|
||||
|
||||
if (camel_url_get_param (url, "use_ssl"))
|
||||
remote_store->use_ssl = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Auth stuff... for now, nothing, but might eventually add SSH tunneling
|
||||
*/
|
||||
|
||||
static GList *
|
||||
remote_query_auth_types (CamelService *service, CamelException *ex)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GList *
|
||||
camel_remote_store_authtype_list (void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
remote_get_name (CamelService *service, gboolean brief)
|
||||
{
|
||||
if (brief)
|
||||
return g_strdup_printf (_("%s server %s"),
|
||||
service->provider->name,
|
||||
service->url->host);
|
||||
else {
|
||||
return g_strdup_printf (_("%s service for %s on %s"),
|
||||
service->provider->name,
|
||||
service->url->user,
|
||||
service->url->host);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
timeout_cb (gpointer data)
|
||||
{
|
||||
CamelRemoteStore *store = CAMEL_REMOTE_STORE(data);
|
||||
|
||||
CRSC (data)->keepalive(store);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
remote_connect (CamelService *service, CamelException *ex)
|
||||
{
|
||||
CamelRemoteStore *store = CAMEL_REMOTE_STORE (service);
|
||||
CamelStream *tcp_stream;
|
||||
struct hostent *h;
|
||||
gint ret, port;
|
||||
|
||||
h = camel_service_gethost (service, ex);
|
||||
if (!h)
|
||||
return FALSE;
|
||||
|
||||
if (service->url->port)
|
||||
port = service->url->port;
|
||||
else if (store->use_ssl)
|
||||
port = store->default_ssl_port;
|
||||
else
|
||||
port = store->default_port;
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
if (store->use_ssl) {
|
||||
tcp_stream = camel_tcp_stream_ssl_new (service, service->url->host);
|
||||
} else {
|
||||
tcp_stream = camel_tcp_stream_raw_new ();
|
||||
}
|
||||
#else
|
||||
tcp_stream = camel_tcp_stream_raw_new ();
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
ret = camel_tcp_stream_connect (CAMEL_TCP_STREAM (tcp_stream), h, port);
|
||||
camel_free_host(h);
|
||||
if (ret == -1) {
|
||||
if (errno == EINTR)
|
||||
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
|
||||
_("Connection cancelled"));
|
||||
else
|
||||
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
|
||||
_("Could not connect to %s (port %d): %s"),
|
||||
service->url->host ? service->url->host : _("(unknown host)"),
|
||||
port, g_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* parent class connect initialization */
|
||||
if (CAMEL_SERVICE_CLASS (parent_class)->connect (service, ex) == FALSE)
|
||||
return FALSE;
|
||||
|
||||
store->ostream = tcp_stream;
|
||||
store->istream = camel_stream_buffer_new (tcp_stream, CAMEL_STREAM_BUFFER_READ);
|
||||
|
||||
/* Add a timeout so that we can hopefully prevent getting disconnected */
|
||||
/* (Only if the implementation supports it) */
|
||||
if (CRSC (store)->keepalive) {
|
||||
CamelSession *session = camel_service_get_session (CAMEL_SERVICE (store));
|
||||
|
||||
store->timeout_id = camel_session_register_timeout (session, 10 * 60 * 1000,
|
||||
timeout_cb,
|
||||
store);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sync_remote_folder (gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
CamelFolder *folder = CAMEL_FOLDER (value);
|
||||
|
||||
if (!camel_exception_is_set ((CamelException *) data))
|
||||
camel_folder_sync (folder, FALSE, (CamelException *) data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
remote_disconnect (CamelService *service, gboolean clean, CamelException *ex)
|
||||
{
|
||||
CamelRemoteStore *store = CAMEL_REMOTE_STORE (service);
|
||||
|
||||
if (store->timeout_id) {
|
||||
camel_session_remove_timeout (camel_service_get_session (CAMEL_SERVICE (store)),
|
||||
store->timeout_id);
|
||||
store->timeout_id = 0;
|
||||
}
|
||||
|
||||
if (!CAMEL_SERVICE_CLASS (parent_class)->disconnect (service, clean, ex))
|
||||
return FALSE;
|
||||
|
||||
if (store->istream) {
|
||||
camel_object_unref (CAMEL_OBJECT (store->istream));
|
||||
store->istream = NULL;
|
||||
}
|
||||
|
||||
if (store->ostream) {
|
||||
camel_object_unref (CAMEL_OBJECT (store->ostream));
|
||||
store->ostream = NULL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gint
|
||||
remote_send_string (CamelRemoteStore *store, CamelException *ex, char *fmt, va_list ap)
|
||||
{
|
||||
gchar *cmdbuf;
|
||||
|
||||
/* Check for connectedness. Failed (or cancelled) operations will
|
||||
* close the connection. */
|
||||
if (!camel_remote_store_connected (store, ex))
|
||||
return -1;
|
||||
|
||||
/* create the command */
|
||||
cmdbuf = g_strdup_vprintf (fmt, ap);
|
||||
|
||||
#if d(!)0
|
||||
if (camel_verbose_debug) {
|
||||
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 if (strstr (cmdbuf, "LOGIN {"))
|
||||
fprintf (stderr, "sending : ------ LOGIN {N+} ....\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) {
|
||||
if (errno == EINTR)
|
||||
camel_exception_set(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled"));
|
||||
else
|
||||
camel_exception_set(ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, strerror(errno));
|
||||
g_free (cmdbuf);
|
||||
|
||||
camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
|
||||
return -1;
|
||||
}
|
||||
g_free (cmdbuf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME: All of these functions need an api overhaul, they're not like
|
||||
any other functions, anywhere in the world ... */
|
||||
|
||||
/**
|
||||
* camel_remote_store_send_string: Writes a string to the server
|
||||
* @store: a CamelRemoteStore
|
||||
* @ex: a CamelException
|
||||
* @fmt: the printf-style format to use for creating the string to send
|
||||
* @...: the arguments to the printf string @fmt
|
||||
* Return value: 0 on success, nonzero on error
|
||||
*
|
||||
* Formats the string and sends it to the server.
|
||||
**/
|
||||
|
||||
gint
|
||||
camel_remote_store_send_string (CamelRemoteStore *store, CamelException *ex,
|
||||
char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
gint ret;
|
||||
|
||||
g_return_val_if_fail (CAMEL_IS_REMOTE_STORE (store), -1);
|
||||
g_return_val_if_fail (fmt, -1);
|
||||
|
||||
va_start (ap, fmt);
|
||||
CAMEL_REMOTE_STORE_LOCK(store, stream_lock);
|
||||
ret = CRSC (store)->send_string (store, ex, fmt, ap);
|
||||
CAMEL_REMOTE_STORE_UNLOCK(store, stream_lock);
|
||||
va_end (ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gint
|
||||
remote_send_stream (CamelRemoteStore *store, CamelStream *stream, CamelException *ex)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Check for connectedness. Failed (or cancelled) operations will
|
||||
* close the connection. */
|
||||
|
||||
if (!camel_remote_store_connected (store, ex))
|
||||
return -1;
|
||||
|
||||
d(fprintf (stderr, "(sending stream)\n"));
|
||||
|
||||
ret = camel_stream_write_to_stream (stream, store->ostream);
|
||||
if (ret == -1) {
|
||||
if (errno == EINTR)
|
||||
camel_exception_set(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled"));
|
||||
else
|
||||
camel_exception_set(ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, strerror(errno));
|
||||
|
||||
camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_remote_store_send_stream: Writes a CamelStream to the server
|
||||
* @store: a CamelRemoteStore
|
||||
* @stream: the stream to write
|
||||
* @ex: a CamelException
|
||||
* Return value: 0 on success, nonzero on error
|
||||
*
|
||||
* Sends the stream to the server.
|
||||
**/
|
||||
|
||||
gint
|
||||
camel_remote_store_send_stream (CamelRemoteStore *store, CamelStream *stream, CamelException *ex)
|
||||
{
|
||||
int ret;
|
||||
|
||||
g_return_val_if_fail (CAMEL_IS_REMOTE_STORE (store), -1);
|
||||
g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
|
||||
|
||||
CAMEL_REMOTE_STORE_LOCK(store, stream_lock);
|
||||
|
||||
ret = CRSC (store)->send_stream (store, stream, ex);
|
||||
|
||||
CAMEL_REMOTE_STORE_UNLOCK(store, stream_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
remote_recv_line (CamelRemoteStore *store, char **dest, CamelException *ex)
|
||||
{
|
||||
CamelStreamBuffer *stream;
|
||||
char *buf;
|
||||
|
||||
*dest = NULL;
|
||||
|
||||
/* Check for connectedness. Failed (or cancelled) operations will
|
||||
* close the connection. We can't expect a read to have any
|
||||
* meaning if we reconnect, so always set an exception.
|
||||
*/
|
||||
|
||||
if (!camel_remote_store_connected (store, ex)) {
|
||||
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_NOT_CONNECTED,
|
||||
g_strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
stream = CAMEL_STREAM_BUFFER (store->istream);
|
||||
|
||||
buf = camel_stream_buffer_read_line (stream);
|
||||
|
||||
if (buf == NULL) {
|
||||
if (errno == EINTR)
|
||||
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled"));
|
||||
else
|
||||
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
|
||||
_("Server unexpectedly disconnected: %s"),
|
||||
g_strerror (errno));
|
||||
|
||||
camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*dest = buf;
|
||||
|
||||
#if d(!)0
|
||||
if (camel_verbose_debug)
|
||||
fprintf (stderr, "received: %s\n", *dest);
|
||||
#endif
|
||||
|
||||
return strlen (*dest);
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_remote_store_recv_line: Reads a line from the server
|
||||
* @store: a CamelRemoteStore
|
||||
* @dest: a pointer that will be set to the location of a buffer
|
||||
* holding the server's response
|
||||
* @ex: a CamelException
|
||||
* Return value: -1 on error, otherwise the length read.
|
||||
*
|
||||
* Reads a line from the server (terminated by \n or \r\n).
|
||||
**/
|
||||
|
||||
gint
|
||||
camel_remote_store_recv_line (CamelRemoteStore *store, char **dest,
|
||||
CamelException *ex)
|
||||
{
|
||||
int ret;
|
||||
|
||||
g_return_val_if_fail (CAMEL_IS_REMOTE_STORE (store), -1);
|
||||
g_return_val_if_fail (dest, -1);
|
||||
|
||||
CAMEL_REMOTE_STORE_LOCK(store, stream_lock);
|
||||
|
||||
ret = CRSC (store)->recv_line (store, dest, ex);
|
||||
|
||||
CAMEL_REMOTE_STORE_UNLOCK(store, stream_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
CAMEL_STORE_LOCK(store, cache_lock);
|
||||
|
||||
g_hash_table_foreach (CAMEL_STORE (store)->folders, refresh_folder_info, ex);
|
||||
|
||||
CAMEL_STORE_UNLOCK(store, cache_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* camel_remote_store_connected:
|
||||
* @store: a CamelRemoteStore
|
||||
* @ex: a CamelException
|
||||
*
|
||||
* Ensure that the remote store is connected.
|
||||
*
|
||||
* Return value: Whether or not it is connected
|
||||
**/
|
||||
gboolean
|
||||
camel_remote_store_connected (CamelRemoteStore *store, CamelException *ex)
|
||||
{
|
||||
if (store->istream == NULL)
|
||||
return camel_service_connect (CAMEL_SERVICE (store), ex);
|
||||
return TRUE;
|
||||
}
|
||||
@ -1,93 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* camel-remote-store.h : class for a remote store */
|
||||
|
||||
/*
|
||||
* Authors: Peter Williams <peterw@ximian.com>
|
||||
*
|
||||
* Copyright (C) 2000 Ximian, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* 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 CAMEL_REMOTE_STORE_H
|
||||
#define CAMEL_REMOTE_STORE_H 1
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#pragma }
|
||||
#endif /* __cplusplus }*/
|
||||
|
||||
#include <camel/camel-store.h>
|
||||
|
||||
#define CAMEL_REMOTE_STORE_TYPE (camel_remote_store_get_type ())
|
||||
#define CAMEL_REMOTE_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_REMOTE_STORE_TYPE, CamelRemoteStore))
|
||||
#define CAMEL_REMOTE_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_REMOTE_STORE_TYPE, CamelRemoteStoreClass))
|
||||
#define CAMEL_IS_REMOTE_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_REMOTE_STORE_TYPE))
|
||||
|
||||
|
||||
enum {
|
||||
CAMEL_REMOTE_STORE_ARG_FIRST = CAMEL_STORE_ARG_FIRST + 100,
|
||||
CAMEL_REMOTE_STORE_ARG_SSL,
|
||||
};
|
||||
|
||||
#define CAMEL_REMOTE_STORE_SSL (CAMEL_REMOTE_STORE_ARG_SSL | CAMEL_ARG_STR)
|
||||
|
||||
typedef struct {
|
||||
CamelStore parent_object;
|
||||
struct _CamelRemoteStorePrivate *priv;
|
||||
|
||||
CamelStream *istream, *ostream;
|
||||
guint timeout_id, default_port, default_ssl_port;
|
||||
gboolean use_ssl;
|
||||
} CamelRemoteStore;
|
||||
|
||||
|
||||
typedef struct {
|
||||
CamelStoreClass parent_class;
|
||||
|
||||
gint (*send_string) (CamelRemoteStore *store, CamelException *ex,
|
||||
char *fmt, va_list ap);
|
||||
gint (*send_stream) (CamelRemoteStore *store, CamelStream *stream,
|
||||
CamelException *ex);
|
||||
gint (*recv_line) (CamelRemoteStore *store, char **dest,
|
||||
CamelException *ex);
|
||||
void (*keepalive) (CamelRemoteStore *store);
|
||||
} CamelRemoteStoreClass;
|
||||
|
||||
|
||||
/* Standard Camel function */
|
||||
CamelType camel_remote_store_get_type (void);
|
||||
|
||||
/* FIXME: All of these i/o functions need an api overhaul, they're not like
|
||||
any other functions, anywhere in the world ... */
|
||||
|
||||
/* Extra public functions */
|
||||
GList *camel_remote_store_authtype_list (void);
|
||||
|
||||
gint camel_remote_store_send_string (CamelRemoteStore *store, CamelException *ex,
|
||||
char *fmt, ...);
|
||||
gint camel_remote_store_send_stream (CamelRemoteStore *store, CamelStream *stream,
|
||||
CamelException *ex);
|
||||
gint camel_remote_store_recv_line (CamelRemoteStore *store, char **dest,
|
||||
CamelException *ex);
|
||||
void camel_remote_store_refresh_folders (CamelRemoteStore *store,
|
||||
CamelException *ex);
|
||||
gboolean camel_remote_store_connected (CamelRemoteStore *store, CamelException *ex);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* CAMEL_REMOTE_STORE_H */
|
||||
@ -40,6 +40,10 @@
|
||||
#include "camel-imap-private.h"
|
||||
#include <camel/camel-exception.h>
|
||||
|
||||
#define d(x) x
|
||||
|
||||
extern int camel_verbose_debug;
|
||||
|
||||
static gboolean imap_command_start (CamelImapStore *store, CamelFolder *folder,
|
||||
const char *cmd, CamelException *ex);
|
||||
CamelImapResponse *imap_read_response (CamelImapStore *store,
|
||||
@ -170,6 +174,8 @@ static gboolean
|
||||
imap_command_start (CamelImapStore *store, CamelFolder *folder,
|
||||
const char *cmd, CamelException *ex)
|
||||
{
|
||||
ssize_t nwritten;
|
||||
|
||||
/* Check for current folder */
|
||||
if (folder && folder != store->current_folder) {
|
||||
CamelImapResponse *response;
|
||||
@ -188,10 +194,39 @@ imap_command_start (CamelImapStore *store, CamelFolder *folder,
|
||||
}
|
||||
|
||||
/* Send the command */
|
||||
return camel_remote_store_send_string (CAMEL_REMOTE_STORE (store), ex,
|
||||
"%c%.5d %s\r\n",
|
||||
store->tag_prefix,
|
||||
store->command++, cmd) != -1;
|
||||
#if d(!)0
|
||||
if (camel_verbose_debug) {
|
||||
const char *mask;
|
||||
|
||||
if (!strncmp ("LOGIN \"", cmd, 7))
|
||||
mask = "LOGIN \"xxx\" xxx";
|
||||
else if (!strncmp ("LOGIN {", cmd, 7))
|
||||
mask = "LOGIN {N+}\r\nxxx {N+}\r\nxxx";
|
||||
else if (!strncmp ("LOGIN ", cmd, 6))
|
||||
mask = "LOGIN xxx xxx";
|
||||
else
|
||||
mask = cmd;
|
||||
|
||||
fprintf (stderr, "sending : %c%.5d %s\r\n", store->tag_prefix, store->command, mask);
|
||||
}
|
||||
#endif
|
||||
|
||||
nwritten = camel_stream_printf (store->ostream, "%c%.5d %s\r\n",
|
||||
store->tag_prefix, store->command++, cmd);
|
||||
|
||||
if (nwritten == -1) {
|
||||
if (errno == EINTR)
|
||||
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
|
||||
_("Operation cancelled"));
|
||||
else
|
||||
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
|
||||
g_strerror (errno));
|
||||
|
||||
camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -205,7 +240,7 @@ imap_command_start (CamelImapStore *store, CamelFolder *folder,
|
||||
* after camel_imap_command() or camel_imap_command_response() returns
|
||||
* a continuation response.
|
||||
*
|
||||
* This function assumes you have an exclusive lock on the remote stream.
|
||||
* This function assumes you have an exclusive lock on the imap stream.
|
||||
*
|
||||
* Return value: as for camel_imap_command(). On failure, the store's
|
||||
* command_lock will be released.
|
||||
@ -214,15 +249,11 @@ CamelImapResponse *
|
||||
camel_imap_command_continuation (CamelImapStore *store, const char *cmd,
|
||||
size_t cmdlen, CamelException *ex)
|
||||
{
|
||||
CamelStream *stream;
|
||||
|
||||
if (!camel_remote_store_connected (CAMEL_REMOTE_STORE (store), ex))
|
||||
if (!camel_imap_store_connected (store, ex))
|
||||
return NULL;
|
||||
|
||||
stream = CAMEL_REMOTE_STORE (store)->ostream;
|
||||
|
||||
if (camel_stream_write (stream, cmd, cmdlen) == -1 ||
|
||||
camel_stream_write (stream, "\r\n", 2) == -1) {
|
||||
if (camel_stream_write (store->ostream, cmd, cmdlen) == -1 ||
|
||||
camel_stream_write (store->ostream, "\r\n", 2) == -1) {
|
||||
if (errno == EINTR)
|
||||
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
|
||||
_("Operation cancelled"));
|
||||
@ -259,8 +290,7 @@ camel_imap_command_response (CamelImapStore *store, char **response,
|
||||
CamelImapResponseType type;
|
||||
char *respbuf;
|
||||
|
||||
if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store),
|
||||
&respbuf, ex) < 0) {
|
||||
if (camel_imap_store_recv_line (store, &respbuf, ex) < 0) {
|
||||
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
|
||||
return CAMEL_IMAP_RESPONSE_ERROR;
|
||||
}
|
||||
@ -402,8 +432,7 @@ imap_read_untagged (CamelImapStore *store, char *line, CamelException *ex)
|
||||
/* Read the literal */
|
||||
str = g_string_sized_new (length + 2);
|
||||
str->str[0] = '\n';
|
||||
nread = camel_stream_read (CAMEL_REMOTE_STORE (store)->istream,
|
||||
str->str + 1, length);
|
||||
nread = camel_stream_read (store->istream, str->str + 1, length);
|
||||
if (nread == -1) {
|
||||
if (errno == EINTR)
|
||||
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled"));
|
||||
@ -464,8 +493,7 @@ imap_read_untagged (CamelImapStore *store, char *line, CamelException *ex)
|
||||
g_ptr_array_add (data, str);
|
||||
|
||||
/* Read the next line. */
|
||||
if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store),
|
||||
&line, ex) < 0)
|
||||
if (camel_imap_store_recv_line (store, &line, ex) < 0)
|
||||
goto lose;
|
||||
}
|
||||
|
||||
|
||||
@ -93,8 +93,7 @@ camel_provider_module_init (CamelSession *session)
|
||||
camel_imap_store_get_type ();
|
||||
imap_provider.url_hash = imap_url_hash;
|
||||
imap_provider.url_equal = imap_url_equal;
|
||||
imap_provider.authtypes = g_list_concat (camel_remote_store_authtype_list (),
|
||||
camel_sasl_authtype_list (FALSE));
|
||||
imap_provider.authtypes = camel_sasl_authtype_list (FALSE);
|
||||
imap_provider.authtypes = g_list_prepend (imap_provider.authtypes,
|
||||
&camel_imap_password_authtype);
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
@ -50,6 +51,8 @@
|
||||
#include "camel-stream.h"
|
||||
#include "camel-stream-buffer.h"
|
||||
#include "camel-stream-fs.h"
|
||||
#include "camel-tcp-stream-raw.h"
|
||||
#include "camel-tcp-stream-ssl.h"
|
||||
#include "camel-url.h"
|
||||
#include "camel-sasl.h"
|
||||
#include "string-utils.h"
|
||||
@ -57,11 +60,16 @@
|
||||
#include "camel-imap-private.h"
|
||||
#include "camel-private.h"
|
||||
|
||||
#define d(x) x
|
||||
|
||||
/* Specified in RFC 2060 */
|
||||
#define IMAP_PORT 143
|
||||
#define SIMAP_PORT 993
|
||||
|
||||
extern int camel_verbose_debug;
|
||||
|
||||
static CamelDiscoStoreClass *parent_class = NULL;
|
||||
|
||||
static CamelDiscoStoreClass *disco_store_class = NULL;
|
||||
static CamelRemoteStoreClass *remote_store_class = NULL;
|
||||
static char imap_tag_prefix = 'A';
|
||||
|
||||
static void construct (CamelService *service, CamelSession *session,
|
||||
@ -71,6 +79,8 @@ static void construct (CamelService *service, CamelSession *session,
|
||||
static int imap_setv (CamelObject *object, CamelException *ex, CamelArgV *args);
|
||||
static int imap_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args);
|
||||
|
||||
static char *imap_get_name (CamelService *service, gboolean brief);
|
||||
|
||||
static gboolean can_work_offline (CamelDiscoStore *disco_store);
|
||||
static gboolean imap_connect_online (CamelService *service, CamelException *ex);
|
||||
static gboolean imap_connect_offline (CamelService *service, CamelException *ex);
|
||||
@ -97,7 +107,6 @@ static void subscribe_folder (CamelStore *store, const char *folder_name,
|
||||
CamelException *ex);
|
||||
static void unsubscribe_folder (CamelStore *store, const char *folder_name,
|
||||
CamelException *ex);
|
||||
static void imap_keepalive (CamelRemoteStore *store);
|
||||
|
||||
|
||||
static void get_folders_online (CamelImapStore *imap_store, const char *pattern,
|
||||
@ -112,20 +121,18 @@ camel_imap_store_class_init (CamelImapStoreClass *camel_imap_store_class)
|
||||
CAMEL_SERVICE_CLASS (camel_imap_store_class);
|
||||
CamelStoreClass *camel_store_class =
|
||||
CAMEL_STORE_CLASS (camel_imap_store_class);
|
||||
CamelRemoteStoreClass *camel_remote_store_class =
|
||||
CAMEL_REMOTE_STORE_CLASS (camel_imap_store_class);
|
||||
CamelDiscoStoreClass *camel_disco_store_class =
|
||||
CAMEL_DISCO_STORE_CLASS (camel_imap_store_class);
|
||||
|
||||
disco_store_class = CAMEL_DISCO_STORE_CLASS (camel_type_get_global_classfuncs (camel_disco_store_get_type ()));
|
||||
remote_store_class = CAMEL_REMOTE_STORE_CLASS (camel_type_get_global_classfuncs (camel_remote_store_get_type ()));
|
||||
|
||||
|
||||
parent_class = CAMEL_DISCO_STORE_CLASS (camel_type_get_global_classfuncs (camel_disco_store_get_type ()));
|
||||
|
||||
/* virtual method overload */
|
||||
camel_object_class->setv = imap_setv;
|
||||
camel_object_class->getv = imap_getv;
|
||||
|
||||
camel_service_class->construct = construct;
|
||||
camel_service_class->query_auth_types = query_auth_types;
|
||||
camel_service_class->get_name = imap_get_name;
|
||||
|
||||
camel_store_class->hash_folder_name = hash_folder_name;
|
||||
camel_store_class->compare_folder_name = compare_folder_name;
|
||||
@ -136,9 +143,7 @@ camel_imap_store_class_init (CamelImapStoreClass *camel_imap_store_class)
|
||||
camel_store_class->folder_subscribed = folder_subscribed;
|
||||
camel_store_class->subscribe_folder = subscribe_folder;
|
||||
camel_store_class->unsubscribe_folder = unsubscribe_folder;
|
||||
|
||||
camel_remote_store_class->keepalive = imap_keepalive;
|
||||
|
||||
|
||||
camel_disco_store_class->can_work_offline = can_work_offline;
|
||||
camel_disco_store_class->connect_online = imap_connect_online;
|
||||
camel_disco_store_class->connect_offline = imap_connect_offline;
|
||||
@ -163,18 +168,24 @@ static void
|
||||
camel_imap_store_finalize (CamelObject *object)
|
||||
{
|
||||
CamelImapStore *imap_store = CAMEL_IMAP_STORE (object);
|
||||
|
||||
|
||||
if (imap_store->istream)
|
||||
camel_object_unref (CAMEL_OBJECT (imap_store->istream));
|
||||
|
||||
if (imap_store->ostream)
|
||||
camel_object_unref (CAMEL_OBJECT (imap_store->ostream));
|
||||
|
||||
/* This frees current_folder, folders, authtypes, and namespace. */
|
||||
imap_disconnect_offline (CAMEL_SERVICE (object), FALSE, NULL);
|
||||
|
||||
|
||||
if (imap_store->base_url)
|
||||
g_free (imap_store->base_url);
|
||||
if (imap_store->storage_path)
|
||||
g_free (imap_store->storage_path);
|
||||
|
||||
|
||||
#ifdef ENABLE_THREADS
|
||||
e_mutex_destroy (imap_store->priv->command_lock);
|
||||
e_thread_destroy(imap_store->async_thread);
|
||||
e_thread_destroy (imap_store->async_thread);
|
||||
#endif
|
||||
g_free (imap_store->priv);
|
||||
}
|
||||
@ -184,11 +195,11 @@ static void async_destroy(EThread *et, EMsg *em, void *data)
|
||||
{
|
||||
CamelImapStore *imap_store = data;
|
||||
CamelImapMsg *msg = (CamelImapMsg *)em;
|
||||
|
||||
|
||||
if (msg->free)
|
||||
msg->free(imap_store, msg);
|
||||
|
||||
g_free(msg);
|
||||
msg->free (imap_store, msg);
|
||||
|
||||
g_free (msg);
|
||||
}
|
||||
|
||||
static void async_received(EThread *et, EMsg *em, void *data)
|
||||
@ -225,11 +236,10 @@ void camel_imap_msg_queue(CamelImapStore *store, CamelImapMsg *msg)
|
||||
static void
|
||||
camel_imap_store_init (gpointer object, gpointer klass)
|
||||
{
|
||||
CamelRemoteStore *remote_store = CAMEL_REMOTE_STORE (object);
|
||||
CamelImapStore *imap_store = CAMEL_IMAP_STORE (object);
|
||||
|
||||
remote_store->default_port = 143;
|
||||
remote_store->default_ssl_port = 993;
|
||||
imap_store->istream = NULL;
|
||||
imap_store->ostream = NULL;
|
||||
|
||||
imap_store->dir_sep = '\0';
|
||||
imap_store->current_folder = NULL;
|
||||
@ -256,7 +266,8 @@ camel_imap_store_get_type (void)
|
||||
|
||||
if (camel_imap_store_type == CAMEL_INVALID_TYPE) {
|
||||
camel_imap_store_type =
|
||||
camel_type_register (CAMEL_DISCO_STORE_TYPE, "CamelImapStore",
|
||||
camel_type_register (CAMEL_DISCO_STORE_TYPE,
|
||||
"CamelImapStore",
|
||||
sizeof (CamelImapStore),
|
||||
sizeof (CamelImapStoreClass),
|
||||
(CamelObjectClassInitFunc) camel_imap_store_class_init,
|
||||
@ -276,7 +287,7 @@ construct (CamelService *service, CamelSession *session,
|
||||
CamelImapStore *imap_store = CAMEL_IMAP_STORE (service);
|
||||
CamelStore *store = CAMEL_STORE (service);
|
||||
|
||||
CAMEL_SERVICE_CLASS (disco_store_class)->construct (service, session, provider, url, ex);
|
||||
CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex);
|
||||
if (camel_exception_is_set (ex))
|
||||
return;
|
||||
|
||||
@ -362,7 +373,7 @@ imap_setv (CamelObject *object, CamelException *ex, CamelArgV *args)
|
||||
we need to do it here... or, better yet, somehow chain it
|
||||
up to CamelService's setv implementation. */
|
||||
|
||||
return CAMEL_OBJECT_CLASS (disco_store_class)->setv (object, ex, args);
|
||||
return CAMEL_OBJECT_CLASS (parent_class)->setv (object, ex, args);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -402,7 +413,17 @@ imap_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args)
|
||||
}
|
||||
}
|
||||
|
||||
return CAMEL_OBJECT_CLASS (disco_store_class)->getv (object, ex, args);
|
||||
return CAMEL_OBJECT_CLASS (parent_class)->getv (object, ex, args);
|
||||
}
|
||||
|
||||
static char *
|
||||
imap_get_name (CamelService *service, gboolean brief)
|
||||
{
|
||||
if (brief)
|
||||
return g_strdup_printf (_("IMAP server %s"), service->url->host);
|
||||
else
|
||||
return g_strdup_printf (_("IMAP service for %s on %s"),
|
||||
service->url->user, service->url->host);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -427,29 +448,20 @@ static struct {
|
||||
{ "NAMESPACE", IMAP_CAPABILITY_NAMESPACE },
|
||||
{ "UIDPLUS", IMAP_CAPABILITY_UIDPLUS },
|
||||
{ "LITERAL+", IMAP_CAPABILITY_LITERALPLUS },
|
||||
{ "STARTTLS", IMAP_CAPABILITY_STARTTLS },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
/* we have remote-store:connect_lock by now */
|
||||
|
||||
static gboolean
|
||||
connect_to_server (CamelService *service, CamelException *ex)
|
||||
imap_get_capability (CamelService *service, CamelException *ex)
|
||||
{
|
||||
CamelImapStore *store = CAMEL_IMAP_STORE (service);
|
||||
CamelImapResponse *response;
|
||||
char *result, *buf, *capa, *lasts;
|
||||
char *result, *capa, *lasts;
|
||||
int i;
|
||||
|
||||
|
||||
CAMEL_IMAP_STORE_ASSERT_LOCKED (store, command_lock);
|
||||
|
||||
store->command = 0;
|
||||
|
||||
/* Read the greeting, if any. FIXME: deal with PREAUTH */
|
||||
if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (service),
|
||||
&buf, ex) < 0) {
|
||||
return FALSE;
|
||||
}
|
||||
g_free (buf);
|
||||
store->connected = TRUE;
|
||||
|
||||
/* Find out the IMAP capabilities */
|
||||
/* We assume we have utf8 capable search until a failed search tells us otherwise */
|
||||
@ -461,7 +473,7 @@ connect_to_server (CamelService *service, CamelException *ex)
|
||||
result = camel_imap_response_extract (store, response, "CAPABILITY ", ex);
|
||||
if (!result)
|
||||
return FALSE;
|
||||
|
||||
|
||||
/* Skip over "* CAPABILITY ". */
|
||||
capa = result + 13;
|
||||
for (capa = strtok_r (capa, " ", &lasts); capa;
|
||||
@ -480,12 +492,217 @@ connect_to_server (CamelService *service, CamelException *ex)
|
||||
}
|
||||
}
|
||||
g_free (result);
|
||||
|
||||
|
||||
imap_set_server_level (store);
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
enum {
|
||||
USE_SSL_NEVER,
|
||||
USE_SSL_ALWAYS,
|
||||
USE_SSL_WHEN_POSSIBLE
|
||||
};
|
||||
|
||||
static gboolean
|
||||
connect_to_server (CamelService *service, int ssl_mode, int try_starttls, CamelException *ex)
|
||||
{
|
||||
CamelImapStore *store = (CamelImapStore *) service;
|
||||
CamelImapResponse *response;
|
||||
CamelStream *tcp_stream;
|
||||
struct hostent *h;
|
||||
int clean_quit;
|
||||
int port, ret;
|
||||
char *buf;
|
||||
|
||||
h = camel_service_gethost (service, ex);
|
||||
if (!h)
|
||||
return FALSE;
|
||||
|
||||
port = service->url->port ? service->url->port : 143;
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
if (ssl_mode != USE_SSL_NEVER) {
|
||||
if (try_starttls)
|
||||
tcp_stream = camel_tcp_stream_ssl_new_raw (service, service->url->host);
|
||||
else {
|
||||
port = service->url->port ? service->url->port : 993;
|
||||
tcp_stream = camel_tcp_stream_ssl_new (service, service->url->host);
|
||||
}
|
||||
} else {
|
||||
tcp_stream = camel_tcp_stream_raw_new ();
|
||||
}
|
||||
#else
|
||||
tcp_stream = camel_tcp_stream_raw_new ();
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
ret = camel_tcp_stream_connect (CAMEL_TCP_STREAM (tcp_stream), h, port);
|
||||
camel_free_host (h);
|
||||
if (ret == -1) {
|
||||
if (errno == EINTR)
|
||||
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
|
||||
_("Connection cancelled"));
|
||||
else
|
||||
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
|
||||
_("Could not connect to %s (port %d): %s"),
|
||||
service->url->host, port, g_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
store->ostream = tcp_stream;
|
||||
store->istream = camel_stream_buffer_new (tcp_stream, CAMEL_STREAM_BUFFER_READ);
|
||||
|
||||
store->connected = TRUE;
|
||||
store->command = 0;
|
||||
|
||||
/* Read the greeting, if any. FIXME: deal with PREAUTH */
|
||||
if (camel_imap_store_recv_line (store, &buf, ex) < 0) {
|
||||
camel_object_unref (CAMEL_OBJECT (store->istream));
|
||||
camel_object_unref (CAMEL_OBJECT (store->ostream));
|
||||
store->istream = NULL;
|
||||
store->ostream = NULL;
|
||||
store->connected = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
g_free (buf);
|
||||
|
||||
/* get the imap server capabilities */
|
||||
if (!imap_get_capability (service, ex)) {
|
||||
camel_object_unref (CAMEL_OBJECT (store->istream));
|
||||
camel_object_unref (CAMEL_OBJECT (store->ostream));
|
||||
store->istream = NULL;
|
||||
store->ostream = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
if (ssl_mode == USE_SSL_WHEN_POSSIBLE) {
|
||||
if (store->capabilities & IMAP_CAPABILITY_STARTTLS)
|
||||
goto starttls;
|
||||
} else if (ssl_mode == USE_SSL_ALWAYS) {
|
||||
if (try_starttls) {
|
||||
if (store->capabilities & IMAP_CAPABILITY_STARTTLS) {
|
||||
/* attempt to toggle STARTTLS mode */
|
||||
goto starttls;
|
||||
} else {
|
||||
/* server doesn't support STARTTLS, abort */
|
||||
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
|
||||
_("Failed to connect to IMAP server %s in secure mode: %s"),
|
||||
service->url->host, _("SSL/TLS extension not supported."));
|
||||
/* we have the possibility of quitting cleanly here */
|
||||
clean_quit = TRUE;
|
||||
goto exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
return TRUE;
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
starttls:
|
||||
|
||||
/* as soon as we send a STARTTLS command, all hope is lost of a clean QUIT if problems arise */
|
||||
clean_quit = FALSE;
|
||||
|
||||
response = camel_imap_command (store, NULL, ex, "STARTTLS");
|
||||
if (!response) {
|
||||
camel_object_unref (CAMEL_OBJECT (store->istream));
|
||||
camel_object_unref (CAMEL_OBJECT (store->ostream));
|
||||
store->istream = store->ostream = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
camel_imap_response_free_without_processing (store, response);
|
||||
|
||||
/* Okay, now toggle SSL/TLS mode */
|
||||
if (camel_tcp_stream_ssl_enable_ssl (CAMEL_TCP_STREAM_SSL (tcp_stream)) == -1) {
|
||||
camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
|
||||
_("Failed to connect to IMAP server %s in secure mode: %s"),
|
||||
service->url->host, _("SSL negotiations failed"));
|
||||
goto exception;
|
||||
}
|
||||
|
||||
/* rfc2595, section 4 states that after a successful STLS
|
||||
command, the client MUST discard prior CAPA responses */
|
||||
if (!imap_get_capability (service, ex)) {
|
||||
camel_object_unref (CAMEL_OBJECT (store->istream));
|
||||
camel_object_unref (CAMEL_OBJECT (store->ostream));
|
||||
store->istream = NULL;
|
||||
store->ostream = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
exception:
|
||||
if (clean_quit) {
|
||||
/* try to disconnect cleanly */
|
||||
response = camel_imap_command (store, NULL, ex, "LOGOUT");
|
||||
camel_imap_response_free_without_processing (store, response);
|
||||
}
|
||||
|
||||
camel_object_unref (CAMEL_OBJECT (store->istream));
|
||||
camel_object_unref (CAMEL_OBJECT (store->ostream));
|
||||
store->istream = NULL;
|
||||
store->ostream = NULL;
|
||||
|
||||
return FALSE;
|
||||
#endif /* HAVE_SSL */
|
||||
}
|
||||
|
||||
static struct {
|
||||
char *value;
|
||||
int mode;
|
||||
} ssl_options[] = {
|
||||
{ "", USE_SSL_ALWAYS },
|
||||
{ "always", USE_SSL_ALWAYS },
|
||||
{ "when-possible", USE_SSL_WHEN_POSSIBLE },
|
||||
{ "never", USE_SSL_NEVER },
|
||||
{ NULL, USE_SSL_NEVER },
|
||||
};
|
||||
|
||||
static gboolean
|
||||
connect_to_server_wrapper (CamelService *service, CamelException *ex)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
const char *use_ssl;
|
||||
int i, ssl_mode;
|
||||
|
||||
use_ssl = camel_url_get_param (service->url, "use_ssl");
|
||||
if (use_ssl) {
|
||||
for (i = 0; ssl_options[i].value; i++)
|
||||
if (!strcmp (ssl_options[i].value, use_ssl))
|
||||
break;
|
||||
ssl_mode = ssl_options[i].mode;
|
||||
} else
|
||||
ssl_mode = USE_SSL_NEVER;
|
||||
|
||||
if (ssl_mode == USE_SSL_ALWAYS) {
|
||||
/* First try the ssl port */
|
||||
if (!connect_to_server (service, ssl_mode, FALSE, ex)) {
|
||||
if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_SERVICE_UNAVAILABLE) {
|
||||
/* The ssl port seems to be unavailable, lets try STARTTLS */
|
||||
camel_exception_clear (ex);
|
||||
return connect_to_server (service, ssl_mode, TRUE, ex);
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
} else if (ssl_mode == USE_SSL_WHEN_POSSIBLE) {
|
||||
/* If the server supports STARTTLS, use it */
|
||||
return connect_to_server (service, ssl_mode, TRUE, ex);
|
||||
} else {
|
||||
/* User doesn't care about SSL */
|
||||
return connect_to_server (service, ssl_mode, FALSE, ex);
|
||||
}
|
||||
#else
|
||||
return connect_to_server (service, USE_SSL_NEVER, FALSE, ex);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern CamelServiceAuthType camel_imap_password_authtype;
|
||||
|
||||
static GList *
|
||||
@ -493,35 +710,30 @@ query_auth_types (CamelService *service, CamelException *ex)
|
||||
{
|
||||
CamelImapStore *store = CAMEL_IMAP_STORE (service);
|
||||
CamelServiceAuthType *authtype;
|
||||
GList *types, *sasl_types, *t, *next;
|
||||
GList *sasl_types, *t, *next;
|
||||
gboolean connected;
|
||||
|
||||
|
||||
if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex))
|
||||
return NULL;
|
||||
|
||||
|
||||
CAMEL_IMAP_STORE_LOCK (store, command_lock);
|
||||
connected = CAMEL_SERVICE_CLASS (remote_store_class)->connect (service, ex) && connect_to_server (service, ex);
|
||||
connected = connect_to_server_wrapper (service, ex);
|
||||
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
|
||||
if (!connected)
|
||||
return NULL;
|
||||
|
||||
types = CAMEL_SERVICE_CLASS (disco_store_class)->query_auth_types (service, ex);
|
||||
if (camel_exception_is_set (ex))
|
||||
return types;
|
||||
|
||||
|
||||
sasl_types = camel_sasl_authtype_list (FALSE);
|
||||
for (t = sasl_types; t; t = next) {
|
||||
authtype = t->data;
|
||||
next = t->next;
|
||||
|
||||
|
||||
if (!g_hash_table_lookup (store->authtypes, authtype->authproto)) {
|
||||
sasl_types = g_list_remove_link (sasl_types, t);
|
||||
g_list_free_1 (t);
|
||||
}
|
||||
}
|
||||
types = g_list_concat (types, sasl_types);
|
||||
|
||||
return g_list_prepend (types, &camel_imap_password_authtype);
|
||||
|
||||
return g_list_prepend (sasl_types, &camel_imap_password_authtype);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -539,25 +751,26 @@ copy_folder(char *key, CamelFolder *folder, GPtrArray *out)
|
||||
make the camel folder->lock recursive (which should probably be done)
|
||||
or remove it from camel_folder_refresh_info, and use another locking mechanism */
|
||||
static void
|
||||
imap_store_refresh_folders (CamelRemoteStore *store, CamelException *ex)
|
||||
imap_store_refresh_folders (CamelImapStore *store, CamelException *ex)
|
||||
{
|
||||
GPtrArray *folders;
|
||||
int i;
|
||||
|
||||
|
||||
folders = g_ptr_array_new();
|
||||
CAMEL_STORE_LOCK(store, cache_lock);
|
||||
g_hash_table_foreach (CAMEL_STORE (store)->folders, (GHFunc)copy_folder, folders);
|
||||
CAMEL_STORE_UNLOCK(store, cache_lock);
|
||||
|
||||
for (i=0;i<folders->len;i++) {
|
||||
|
||||
for (i = 0; i <folders->len; i++) {
|
||||
CamelFolder *folder = folders->pdata[i];
|
||||
|
||||
|
||||
CAMEL_IMAP_FOLDER (folder)->need_rescan = TRUE;
|
||||
if (!camel_exception_is_set(ex))
|
||||
CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(folder))->refresh_info(folder, ex);
|
||||
camel_object_unref((CamelObject *)folder);
|
||||
}
|
||||
g_ptr_array_free(folders, TRUE);
|
||||
|
||||
g_ptr_array_free (folders, TRUE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -630,9 +843,9 @@ imap_auth_loop (CamelService *service, CamelException *ex)
|
||||
CamelImapResponse *response;
|
||||
char *errbuf = NULL;
|
||||
gboolean authenticated = FALSE;
|
||||
|
||||
|
||||
CAMEL_IMAP_STORE_ASSERT_LOCKED (store, command_lock);
|
||||
|
||||
|
||||
if (service->url->authmech) {
|
||||
if (!g_hash_table_lookup (store->authtypes, service->url->authmech)) {
|
||||
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
|
||||
@ -642,7 +855,7 @@ imap_auth_loop (CamelService *service, CamelException *ex)
|
||||
service->url->authmech);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
authtype = camel_sasl_authtype (service->url->authmech);
|
||||
if (!authtype) {
|
||||
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
|
||||
@ -650,14 +863,14 @@ imap_auth_loop (CamelService *service, CamelException *ex)
|
||||
service->url->authmech);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (!authtype->need_password) {
|
||||
authenticated = try_auth (store, authtype->authproto, ex);
|
||||
if (!authenticated)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
while (!authenticated) {
|
||||
if (errbuf) {
|
||||
/* We need to un-cache the password before prompting again */
|
||||
@ -666,10 +879,10 @@ imap_auth_loop (CamelService *service, CamelException *ex)
|
||||
g_free (service->url->passwd);
|
||||
service->url->passwd = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (!service->url->passwd) {
|
||||
char *prompt;
|
||||
|
||||
|
||||
prompt = g_strdup_printf (_("%sPlease enter the IMAP "
|
||||
"password for %s@%s"),
|
||||
errbuf ? errbuf : "",
|
||||
@ -682,22 +895,22 @@ imap_auth_loop (CamelService *service, CamelException *ex)
|
||||
g_free (prompt);
|
||||
g_free (errbuf);
|
||||
errbuf = NULL;
|
||||
|
||||
|
||||
if (!service->url->passwd) {
|
||||
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
|
||||
_("You didn't enter a password."));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!store->connected) {
|
||||
/* Some servers (eg, courier) will disconnect on
|
||||
* a bad password. So reconnect here.
|
||||
*/
|
||||
if (!connect_to_server (service, ex))
|
||||
if (!connect_to_server_wrapper (service, ex))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (authtype)
|
||||
authenticated = try_auth (store, authtype->authproto, ex);
|
||||
else {
|
||||
@ -713,14 +926,14 @@ imap_auth_loop (CamelService *service, CamelException *ex)
|
||||
if (!authenticated) {
|
||||
if (camel_exception_get_id(ex) == CAMEL_EXCEPTION_USER_CANCEL)
|
||||
return FALSE;
|
||||
|
||||
|
||||
errbuf = g_strdup_printf (_("Unable to authenticate "
|
||||
"to IMAP server.\n%s\n\n"),
|
||||
camel_exception_get_description (ex));
|
||||
camel_exception_clear (ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -732,7 +945,7 @@ can_work_offline (CamelDiscoStore *disco_store)
|
||||
CamelImapStore *store = CAMEL_IMAP_STORE (disco_store);
|
||||
char *path;
|
||||
gboolean can;
|
||||
|
||||
|
||||
path = g_strdup_printf ("%s/storeinfo", store->storage_path);
|
||||
can = access (path, F_OK) == 0;
|
||||
g_free (path);
|
||||
@ -750,32 +963,32 @@ imap_connect_online (CamelService *service, CamelException *ex)
|
||||
FILE *storeinfo;
|
||||
int i, flags;
|
||||
size_t len;
|
||||
|
||||
|
||||
CAMEL_IMAP_STORE_LOCK (store, command_lock);
|
||||
if (!connect_to_server (service, ex) ||
|
||||
if (!connect_to_server_wrapper (service, ex) ||
|
||||
!imap_auth_loop (service, ex)) {
|
||||
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
|
||||
camel_service_disconnect (service, TRUE, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
path = g_strdup_printf ("%s/storeinfo", store->storage_path);
|
||||
storeinfo = fopen (path, "w");
|
||||
if (!storeinfo)
|
||||
g_warning ("Could not open storeinfo %s", path);
|
||||
g_free (path);
|
||||
|
||||
|
||||
/* Write header and capabilities */
|
||||
camel_file_util_encode_uint32 (storeinfo, IMAP_STOREINFO_VERSION);
|
||||
camel_file_util_encode_uint32 (storeinfo, store->capabilities);
|
||||
|
||||
|
||||
/* Get namespace and hierarchy separator */
|
||||
if ((store->capabilities & IMAP_CAPABILITY_NAMESPACE) &&
|
||||
!(store->parameters & IMAP_PARAM_OVERRIDE_NAMESPACE)) {
|
||||
response = camel_imap_command (store, NULL, ex, "NAMESPACE");
|
||||
if (!response)
|
||||
goto done;
|
||||
|
||||
|
||||
result = camel_imap_response_extract (store, response, "NAMESPACE", ex);
|
||||
if (!result)
|
||||
goto done;
|
||||
@ -788,7 +1001,7 @@ imap_connect_online (CamelService *service, CamelException *ex)
|
||||
name = strstrcase (result, "NAMESPACE ((");
|
||||
if (name) {
|
||||
char *sep;
|
||||
|
||||
|
||||
name += 12;
|
||||
store->namespace = imap_parse_string ((const char **) &name, &len);
|
||||
if (name && *name++ == ' ') {
|
||||
@ -835,7 +1048,7 @@ imap_connect_online (CamelService *service, CamelException *ex)
|
||||
((CamelStore *)store)->dir_sep = store->dir_sep;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* canonicalize the namespace to end with dir_sep */
|
||||
len = strlen (store->namespace);
|
||||
if (len && store->namespace[len - 1] != store->dir_sep) {
|
||||
@ -845,11 +1058,11 @@ imap_connect_online (CamelService *service, CamelException *ex)
|
||||
g_free (store->namespace);
|
||||
store->namespace = tmp;
|
||||
}
|
||||
|
||||
|
||||
/* Write namespace/separator out */
|
||||
camel_file_util_encode_string (storeinfo, store->namespace);
|
||||
camel_file_util_encode_uint32 (storeinfo, store->dir_sep);
|
||||
|
||||
|
||||
if (CAMEL_STORE (store)->flags & CAMEL_STORE_SUBSCRIPTIONS) {
|
||||
/* Get subscribed folders */
|
||||
response = camel_imap_command (store, NULL, ex, "LSUB \"\" \"*\"");
|
||||
@ -872,19 +1085,20 @@ imap_connect_online (CamelService *service, CamelException *ex)
|
||||
}
|
||||
camel_imap_response_free (store, response);
|
||||
}
|
||||
|
||||
|
||||
path = g_strdup_printf ("%s/journal", store->storage_path);
|
||||
disco_store->diary = camel_disco_diary_new (disco_store, path, ex);
|
||||
g_free (path);
|
||||
|
||||
|
||||
done:
|
||||
fclose (storeinfo);
|
||||
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
|
||||
|
||||
|
||||
if (camel_exception_is_set (ex))
|
||||
camel_service_disconnect (service, TRUE, NULL);
|
||||
else
|
||||
imap_store_refresh_folders (CAMEL_REMOTE_STORE (store), ex);
|
||||
imap_store_refresh_folders (store, ex);
|
||||
|
||||
return !camel_exception_is_set (ex);
|
||||
}
|
||||
|
||||
@ -896,13 +1110,13 @@ imap_connect_offline (CamelService *service, CamelException *ex)
|
||||
char *buf, *name, *path;
|
||||
FILE *storeinfo;
|
||||
guint32 tmp;
|
||||
|
||||
|
||||
path = g_strdup_printf ("%s/journal", store->storage_path);
|
||||
disco_store->diary = camel_disco_diary_new (disco_store, path, ex);
|
||||
g_free (path);
|
||||
if (!disco_store->diary)
|
||||
return FALSE;
|
||||
|
||||
|
||||
path = g_strdup_printf ("%s/storeinfo", store->storage_path);
|
||||
storeinfo = fopen (path, "r");
|
||||
g_free (path);
|
||||
@ -912,20 +1126,20 @@ imap_connect_offline (CamelService *service, CamelException *ex)
|
||||
if (tmp != IMAP_STOREINFO_VERSION) {
|
||||
if (storeinfo)
|
||||
fclose (storeinfo);
|
||||
|
||||
/* We know we're offline, so this will have to set ex
|
||||
|
||||
/* We know we're offline, so this will have to set @ex
|
||||
* and return FALSE.
|
||||
*/
|
||||
return camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex);
|
||||
}
|
||||
|
||||
|
||||
camel_file_util_decode_uint32 (storeinfo, &store->capabilities);
|
||||
imap_set_server_level (store);
|
||||
camel_file_util_decode_string (storeinfo, &store->namespace);
|
||||
camel_file_util_decode_uint32 (storeinfo, &tmp);
|
||||
store->dir_sep = tmp;
|
||||
((CamelStore *)store)->dir_sep = tmp;
|
||||
|
||||
|
||||
/* Get subscribed folders */
|
||||
store->subscribed_folders = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
while (camel_file_util_decode_string (storeinfo, &buf) == 0) {
|
||||
@ -937,10 +1151,10 @@ imap_connect_offline (CamelService *service, CamelException *ex)
|
||||
GINT_TO_POINTER (1));
|
||||
g_free (buf);
|
||||
}
|
||||
|
||||
|
||||
fclose (storeinfo);
|
||||
imap_store_refresh_folders (CAMEL_REMOTE_STORE (store), ex);
|
||||
|
||||
imap_store_refresh_folders (store, ex);
|
||||
|
||||
store->connected = !camel_exception_is_set (ex);
|
||||
return store->connected;
|
||||
}
|
||||
@ -950,37 +1164,37 @@ imap_disconnect_offline (CamelService *service, gboolean clean, CamelException *
|
||||
{
|
||||
CamelImapStore *store = CAMEL_IMAP_STORE (service);
|
||||
CamelDiscoStore *disco = CAMEL_DISCO_STORE (service);
|
||||
|
||||
|
||||
store->connected = FALSE;
|
||||
if (store->current_folder) {
|
||||
camel_object_unref (CAMEL_OBJECT (store->current_folder));
|
||||
store->current_folder = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (store->subscribed_folders) {
|
||||
g_hash_table_foreach_remove (store->subscribed_folders,
|
||||
free_key, NULL);
|
||||
g_hash_table_destroy (store->subscribed_folders);
|
||||
store->subscribed_folders = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (store->authtypes) {
|
||||
g_hash_table_foreach_remove (store->authtypes,
|
||||
free_key, NULL);
|
||||
g_hash_table_destroy (store->authtypes);
|
||||
store->authtypes = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (store->namespace && !(store->parameters & IMAP_PARAM_OVERRIDE_NAMESPACE)) {
|
||||
g_free (store->namespace);
|
||||
store->namespace = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (disco->diary) {
|
||||
camel_object_unref (CAMEL_OBJECT (disco->diary));
|
||||
disco->diary = NULL;
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -989,13 +1203,24 @@ imap_disconnect_online (CamelService *service, gboolean clean, CamelException *e
|
||||
{
|
||||
CamelImapStore *store = CAMEL_IMAP_STORE (service);
|
||||
CamelImapResponse *response;
|
||||
|
||||
|
||||
if (store->connected && clean) {
|
||||
response = camel_imap_command (store, NULL, NULL, "LOGOUT");
|
||||
camel_imap_response_free (store, response);
|
||||
}
|
||||
|
||||
if (store->istream) {
|
||||
camel_object_unref (CAMEL_OBJECT (store->istream));
|
||||
store->istream = NULL;
|
||||
}
|
||||
|
||||
if (store->ostream) {
|
||||
camel_object_unref (CAMEL_OBJECT (store->ostream));
|
||||
store->ostream = NULL;
|
||||
}
|
||||
|
||||
imap_disconnect_offline (service, clean, ex);
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1069,7 +1294,7 @@ get_folder_online (CamelStore *store, const char *folder_name,
|
||||
CamelFolder *new_folder;
|
||||
char *folder_dir;
|
||||
|
||||
if (!camel_remote_store_connected (CAMEL_REMOTE_STORE (store), ex))
|
||||
if (!camel_imap_store_connected (imap_store, ex))
|
||||
return NULL;
|
||||
|
||||
if (!g_strcasecmp (folder_name, "INBOX"))
|
||||
@ -1630,7 +1855,7 @@ get_folder_info_online (CamelStore *store, const char *top,
|
||||
CamelFolderInfo *fi, *tree;
|
||||
int i;
|
||||
|
||||
if (!camel_remote_store_connected (CAMEL_REMOTE_STORE (store), ex))
|
||||
if (!camel_imap_store_connected (imap_store, ex))
|
||||
return NULL;
|
||||
|
||||
name = top;
|
||||
@ -1859,7 +2084,7 @@ subscribe_folder (CamelStore *store, const char *folder_name,
|
||||
|
||||
if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex))
|
||||
return;
|
||||
if (!camel_remote_store_connected (CAMEL_REMOTE_STORE (store), ex))
|
||||
if (!camel_imap_store_connected (imap_store, ex))
|
||||
return;
|
||||
|
||||
response = camel_imap_command (imap_store, NULL, ex,
|
||||
@ -1913,7 +2138,7 @@ unsubscribe_folder (CamelStore *store, const char *folder_name,
|
||||
|
||||
if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex))
|
||||
return;
|
||||
if (!camel_remote_store_connected (CAMEL_REMOTE_STORE (store), ex))
|
||||
if (!camel_imap_store_connected (imap_store, ex))
|
||||
return;
|
||||
|
||||
response = camel_imap_command (imap_store, NULL, ex,
|
||||
@ -1952,6 +2177,7 @@ unsubscribe_folder (CamelStore *store, const char *folder_name,
|
||||
camel_folder_info_free (fi);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static gboolean
|
||||
folder_flags_have_changed (CamelFolder *folder)
|
||||
{
|
||||
@ -1970,32 +2196,63 @@ folder_flags_have_changed (CamelFolder *folder)
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
imap_keepalive (CamelRemoteStore *store)
|
||||
|
||||
gboolean
|
||||
camel_imap_store_connected (CamelImapStore *store, CamelException *ex)
|
||||
{
|
||||
CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
|
||||
CamelImapResponse *response;
|
||||
CamelException *ex;
|
||||
if (store->istream == NULL || !store->connected)
|
||||
return camel_service_connect (CAMEL_SERVICE (store), ex);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* FIXME: should this check to see if we are online? */
|
||||
|
||||
/* FIXME: please god, when will the hurting stop? Thus function is so
|
||||
fucking broken it's not even funny. */
|
||||
int
|
||||
camel_imap_store_recv_line (CamelImapStore *store, char **dest, CamelException *ex)
|
||||
{
|
||||
CamelStreamBuffer *stream;
|
||||
char *buf;
|
||||
|
||||
/* Note: the idea here is to sync the flags of our currently
|
||||
selected folder if there have been changes... */
|
||||
ex = camel_exception_new();
|
||||
if (imap_store->current_folder && folder_flags_have_changed (imap_store->current_folder)) {
|
||||
camel_folder_sync (imap_store->current_folder, FALSE, ex);
|
||||
camel_exception_clear(ex);
|
||||
g_return_val_if_fail (CAMEL_IS_IMAP_STORE (store), -1);
|
||||
g_return_val_if_fail (dest, -1);
|
||||
|
||||
*dest = NULL;
|
||||
|
||||
/* Check for connectedness. Failed (or cancelled) operations will
|
||||
* close the connection. We can't expect a read to have any
|
||||
* meaning if we reconnect, so always set an exception.
|
||||
*/
|
||||
|
||||
if (!camel_imap_store_connected (store, ex)) {
|
||||
camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_NOT_CONNECTED,
|
||||
g_strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
stream = CAMEL_STREAM_BUFFER (store->istream);
|
||||
|
||||
buf = camel_stream_buffer_read_line (stream);
|
||||
|
||||
if (buf == NULL) {
|
||||
if (errno == EINTR)
|
||||
camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled"));
|
||||
else
|
||||
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
|
||||
_("Server unexpectedly disconnected: %s"),
|
||||
g_strerror (errno));
|
||||
|
||||
camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ...but we also want to NOOP so that we get an untagged response. */
|
||||
*dest = buf;
|
||||
|
||||
CAMEL_IMAP_STORE_LOCK (store, command_lock);
|
||||
#if d(!)0
|
||||
if (camel_verbose_debug)
|
||||
fprintf (stderr, "received: %s\n", *dest);
|
||||
#endif
|
||||
|
||||
response = camel_imap_command (imap_store, NULL, ex, "NOOP");
|
||||
camel_imap_response_free (imap_store, response);
|
||||
|
||||
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
|
||||
|
||||
camel_exception_free(ex);
|
||||
return strlen (*dest);
|
||||
}
|
||||
|
||||
@ -84,8 +84,9 @@ typedef enum {
|
||||
#define IMAP_CAPABILITY_NAMESPACE (1 << 3)
|
||||
#define IMAP_CAPABILITY_UIDPLUS (1 << 4)
|
||||
#define IMAP_CAPABILITY_LITERALPLUS (1 << 5)
|
||||
#define IMAP_CAPABILITY_useful_lsub (1 << 6)
|
||||
#define IMAP_CAPABILITY_utf8_search (1 << 7)
|
||||
#define IMAP_CAPABILITY_STARTTLS (1 << 6)
|
||||
#define IMAP_CAPABILITY_useful_lsub (1 << 7)
|
||||
#define IMAP_CAPABILITY_utf8_search (1 << 8)
|
||||
|
||||
#define IMAP_PARAM_OVERRIDE_NAMESPACE (1 << 0)
|
||||
#define IMAP_PARAM_CHECK_ALL (1 << 1)
|
||||
@ -95,6 +96,9 @@ struct _CamelImapStore {
|
||||
CamelDiscoStore parent_object;
|
||||
struct _CamelImapStorePrivate *priv;
|
||||
|
||||
CamelStream *istream;
|
||||
CamelStream *ostream;
|
||||
|
||||
/* Information about the command channel / connection status */
|
||||
gboolean connected;
|
||||
char tag_prefix;
|
||||
@ -124,6 +128,11 @@ typedef struct {
|
||||
/* Standard Camel function */
|
||||
CamelType camel_imap_store_get_type (void);
|
||||
|
||||
|
||||
gboolean camel_imap_store_connected (CamelImapStore *store, CamelException *ex);
|
||||
|
||||
int camel_imap_store_recv_line (CamelImapStore *store, char **dest, CamelException *ex);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
Reference in New Issue
Block a user