[evolution-data-server/gnome-2-30] Bug 621236 - Add imap-over-custom-command support for imapx
- From: David Woodhouse <dwmw2 src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/gnome-2-30] Bug 621236 - Add imap-over-custom-command support for imapx
- Date: Fri, 11 Jun 2010 14:23:14 +0000 (UTC)
commit 406588bf1cfcbe650019ce2e8babd56459ee5955
Author: David Woodhouse <David Woodhouse intel com>
Date: Thu Jun 10 20:22:13 2010 +0100
Bug 621236 - Add imap-over-custom-command support for imapx
camel/camel-stream-process.h | 4 +-
camel/providers/imapx/camel-imapx-provider.c | 6 +-
camel/providers/imapx/camel-imapx-server.c | 178 +++++++++++++++++++++++++-
camel/providers/imapx/camel-imapx-server.h | 1 +
4 files changed, 184 insertions(+), 5 deletions(-)
---
diff --git a/camel/camel-stream-process.h b/camel/camel-stream-process.h
index 68fa101..6abb280 100644
--- a/camel/camel-stream-process.h
+++ b/camel/camel-stream-process.h
@@ -19,8 +19,8 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef _CAMEL_STREAM_NULL_H
-#define _CAMEL_STREAM_NULL_H
+#ifndef _CAMEL_STREAM_PROCESS_H
+#define _CAMEL_STREAM_PROCESS_H
#include <camel/camel-stream.h>
diff --git a/camel/providers/imapx/camel-imapx-provider.c b/camel/providers/imapx/camel-imapx-provider.c
index 48136d4..b6b927d 100644
--- a/camel/providers/imapx/camel-imapx-provider.c
+++ b/camel/providers/imapx/camel-imapx-provider.c
@@ -49,15 +49,17 @@ CamelProviderConfEntry imapx_conf_entries[] = {
{ CAMEL_PROVIDER_CONF_CHECKBOX, "check_lsub", NULL,
N_("Ch_eck for new messages in subscribed folders"), "0" },
{ CAMEL_PROVIDER_CONF_SECTION_END },
-#if 0
+#ifndef G_OS_WIN32
{ CAMEL_PROVIDER_CONF_SECTION_START, "cmdsection", NULL,
N_("Connection to Server") },
{ CAMEL_PROVIDER_CONF_CHECKBOX, "use_command", NULL,
N_("_Use custom command to connect to server"), "0" },
{ CAMEL_PROVIDER_CONF_ENTRY, "command", "use_command",
- N_("Command:"), "ssh -C -l %u %h exec /usr/sbin/imapd" },
+ N_("Command:"), "ssh -C -l %u %h exec /usr/sbin/dovecot --exec-mail imap" },
+#if 0
{ CAMEL_PROVIDER_CONF_CHECKSPIN, "cachedconn", NULL,
N_("Numbe_r of cached connections to use"), "y:1:5:7" },
+#endif
{ CAMEL_PROVIDER_CONF_SECTION_END },
#endif
{ CAMEL_PROVIDER_CONF_SECTION_START, "folders", NULL,
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index fb1c4a9..4dc284b 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -34,6 +34,9 @@
#include "camel/camel-private.h"
#include <camel/camel-tcp-stream-ssl.h>
#include <camel/camel-tcp-stream-raw.h>
+#ifndef G_OS_WIN32
+#include <camel/camel-stream-process.h>
+#endif
#include <camel/camel-db.h>
#include <camel/camel-sasl.h>
@@ -2104,6 +2107,147 @@ imapx_select (CamelIMAPXServer *is, CamelFolder *folder, gboolean forced, CamelE
imapx_command_start (is, ic);
}
+#ifndef G_OS_WIN32
+
+/* Using custom commands to connect to IMAP servers is not supported on Win32 */
+
+static gboolean
+connect_to_server_process (CamelIMAPXServer *is, const gchar *cmd, CamelException *ex)
+{
+ CamelIMAPXCommand *ic;
+ CamelStream *cmd_stream;
+ gint ret, i = 0;
+ gchar *buf;
+ gchar *cmd_copy;
+ gchar *full_cmd;
+ gchar *child_env[7];
+ guchar *buffer = NULL;
+ guint len;
+
+ /* Put full details in the environment, in case the connection
+ program needs them */
+ buf = camel_url_to_string(is->url, 0);
+ child_env[i++] = g_strdup_printf("URL=%s", buf);
+ g_free(buf);
+
+ child_env[i++] = g_strdup_printf("URLHOST=%s", is->url->host);
+ if (is->url->port)
+ child_env[i++] = g_strdup_printf("URLPORT=%d", is->url->port);
+ if (is->url->user)
+ child_env[i++] = g_strdup_printf("URLUSER=%s", is->url->user);
+ if (is->url->passwd)
+ child_env[i++] = g_strdup_printf("URLPASSWD=%s", is->url->passwd);
+ if (is->url->path)
+ child_env[i++] = g_strdup_printf("URLPATH=%s", is->url->path);
+ child_env[i] = NULL;
+
+ /* Now do %h, %u, etc. substitution in cmd */
+ buf = cmd_copy = g_strdup(cmd);
+
+ full_cmd = g_strdup("");
+
+ for (;;) {
+ gchar *pc;
+ gchar *tmp;
+ gchar *var;
+ gint len;
+
+ pc = strchr(buf, '%');
+ ignore:
+ if (!pc) {
+ tmp = g_strdup_printf("%s%s", full_cmd, buf);
+ g_free(full_cmd);
+ full_cmd = tmp;
+ break;
+ }
+
+ len = pc - buf;
+
+ var = NULL;
+
+ switch (pc[1]) {
+ case 'h':
+ var = is->url->host;
+ break;
+ case 'u':
+ var = is->url->user;
+ break;
+ }
+ if (!var) {
+ /* If there wasn't a valid %-code, with an actual
+ variable to insert, pretend we didn't see the % */
+ pc = strchr(pc + 1, '%');
+ goto ignore;
+ }
+ tmp = g_strdup_printf("%s%.*s%s", full_cmd, len, buf, var);
+ g_free(full_cmd);
+ full_cmd = tmp;
+ buf = pc + 2;
+ }
+
+ g_free(cmd_copy);
+
+ cmd_stream = camel_stream_process_new ();
+
+ ret = camel_stream_process_connect (CAMEL_STREAM_PROCESS(cmd_stream),
+ full_cmd, (const gchar **)child_env);
+
+ while (i)
+ g_free(child_env[--i]);
+
+ 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 with command \"%s\": %s"),
+ full_cmd, g_strerror (errno));
+
+ camel_object_unref (cmd_stream);
+ g_free (full_cmd);
+ return FALSE;
+ }
+ g_free (full_cmd);
+
+ is->stream = (CamelIMAPXStream *) camel_imapx_stream_new(cmd_stream);
+ camel_object_unref(cmd_stream);
+ is->is_process_stream = TRUE;
+
+ camel_imapx_stream_gets (is->stream, &buffer, &len);
+ e(printf("Got greeting '%.*s'\n", len, buffer));
+
+ if (!buffer) {
+ camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+ "No response from server.\n");
+ return FALSE;
+ } else if (!strncmp((gchar *)buffer, "* PREAUTH", 9)) {
+ is->state = IMAPX_AUTHENTICATED;
+ } else if (strncmp((gchar *)buffer, "* OK", 4)) {
+ camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+ "Unrecognised greeting from server: %.*s\n",
+ len, buffer);
+ return FALSE;
+ }
+
+ ic = camel_imapx_command_new("CAPABILITY", NULL, "CAPABILITY");
+ imapx_command_run(is, ic);
+
+ if (camel_exception_is_set (ic->ex) || ic->status->result != IMAPX_OK) {
+ if (!camel_exception_is_set (ic->ex))
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, "%s", ic->status->text);
+ else
+ camel_exception_xfer (ex, ic->ex);
+
+ camel_imapx_command_free(ic);
+ return FALSE;
+ }
+ camel_imapx_command_free(ic);
+
+ return TRUE;
+}
+#endif /* !G_OS_WIN32 */
+
gboolean
imapx_connect_to_server (CamelIMAPXServer *is, CamelException *ex)
{
@@ -2121,6 +2265,15 @@ imapx_connect_to_server (CamelIMAPXServer *is, CamelException *ex)
struct addrinfo *ai, hints = { 0 };
CamelIMAPXCommand *ic;
+#ifndef G_OS_WIN32
+ const gchar *command;
+
+ if (camel_url_get_param(is->url, "use_command") &&
+ (command = camel_url_get_param(is->url, "command"))) {
+ connect_to_server_process(is, command, ex);
+ goto exit;
+ }
+#endif
if (is->url->port) {
serv = g_alloca(16);
sprintf((gchar *) serv, "%d", is->url->port);
@@ -2282,6 +2435,9 @@ imapx_reconnect (CamelIMAPXServer *is, CamelException *ex)
if (camel_exception_is_set (ex))
goto exception;
+ if (is->state == IMAPX_AUTHENTICATED)
+ break;
+
if (service->url->passwd == NULL) {
gchar *base_prompt;
gchar *full_prompt;
@@ -3722,8 +3878,28 @@ imapx_parser_thread (gpointer d)
errno = EINTR;
}
#endif
+#ifndef G_OS_WIN32
+ if (is->is_process_stream) {
+ GPollFD fds[2] = { {0, 0, 0}, {0, 0, 0} };
+ gint res;
+
+ fds[0].fd = ((CamelStreamProcess *)is->stream->source)->sockfd;
+ fds[0].events = G_IO_IN;
+ fds[1].fd = camel_operation_cancel_fd (op);
+ fds[1].events = G_IO_IN;
+ res = g_poll(fds, 2, 1000*30);
+ if (res == -1)
+ g_usleep(1) /* ?? */ ;
+ else if (res == 0)
+ /* timed out */;
+ else if (fds[0].revents & G_IO_IN) {
+ parse_contents (is, &ex);
+ } else if (fds[1].revents & G_IO_IN)
+ errno = EINTR;
+ }
+#endif
- if (!is->is_ssl_stream) {
+ if (!is->is_ssl_stream && !is->is_process_stream) {
GPollFD fds[2] = { {0, 0, 0}, {0, 0, 0} };
gint res;
diff --git a/camel/providers/imapx/camel-imapx-server.h b/camel/providers/imapx/camel-imapx-server.h
index 037d653..f385e9a 100644
--- a/camel/providers/imapx/camel-imapx-server.h
+++ b/camel/providers/imapx/camel-imapx-server.h
@@ -52,6 +52,7 @@ struct _CamelIMAPXServer {
struct _CamelIMAPXStream *stream;
struct _capability_info *cinfo;
gboolean is_ssl_stream;
+ gboolean is_process_stream;
CamelIMAPXNamespaceList *nsl;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]