aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers/imap
diff options
context:
space:
mode:
authornobody <nobody@localhost>2002-09-09 04:06:00 +0800
committernobody <nobody@localhost>2002-09-09 04:06:00 +0800
commitd0a26db992188b442356758477be89a312c2d02e (patch)
treef331b9f21da123bbda93ab3bfcf732e77f764471 /camel/providers/imap
parent3abb7796bcc037301601780602f7de940d89ef32 (diff)
downloadgsoc2013-evolution-SODIPODI_0_25.tar.gz
gsoc2013-evolution-SODIPODI_0_25.tar.zst
gsoc2013-evolution-SODIPODI_0_25.zip
This commit was manufactured by cvs2svn to create tagSODIPODI_0_25
'SODIPODI_0_25'. svn path=/tags/SODIPODI_0_25/; revision=18015
Diffstat (limited to 'camel/providers/imap')
-rw-r--r--camel/providers/imap/.cvsignore11
-rw-r--r--camel/providers/imap/Makefile.am49
-rw-r--r--camel/providers/imap/camel-imap-command.c812
-rw-r--r--camel/providers/imap/camel-imap-command.h80
-rw-r--r--camel/providers/imap/camel-imap-folder.c2590
-rw-r--r--camel/providers/imap/camel-imap-folder.h90
-rw-r--r--camel/providers/imap/camel-imap-message-cache.c518
-rw-r--r--camel/providers/imap/camel-imap-message-cache.h109
-rw-r--r--camel/providers/imap/camel-imap-private.h76
-rw-r--r--camel/providers/imap/camel-imap-provider.c149
-rw-r--r--camel/providers/imap/camel-imap-search.c499
-rw-r--r--camel/providers/imap/camel-imap-search.h62
-rw-r--r--camel/providers/imap/camel-imap-store-summary.c519
-rw-r--r--camel/providers/imap/camel-imap-store-summary.h100
-rw-r--r--camel/providers/imap/camel-imap-store.c2607
-rw-r--r--camel/providers/imap/camel-imap-store.h146
-rw-r--r--camel/providers/imap/camel-imap-summary.c255
-rw-r--r--camel/providers/imap/camel-imap-summary.h79
-rw-r--r--camel/providers/imap/camel-imap-types.h39
-rw-r--r--camel/providers/imap/camel-imap-utils.c1156
-rw-r--r--camel/providers/imap/camel-imap-utils.h95
-rw-r--r--camel/providers/imap/camel-imap-wrapper.c226
-rw-r--r--camel/providers/imap/camel-imap-wrapper.h70
-rw-r--r--camel/providers/imap/libcamelimap.urls1
24 files changed, 0 insertions, 10338 deletions
diff --git a/camel/providers/imap/.cvsignore b/camel/providers/imap/.cvsignore
deleted file mode 100644
index 3fa8afaa38..0000000000
--- a/camel/providers/imap/.cvsignore
+++ /dev/null
@@ -1,11 +0,0 @@
-.deps
-Makefile
-Makefile.in
-.libs
-.deps
-*.lo
-*.la
-*.bb
-*.bbg
-*.da
-*.gcov
diff --git a/camel/providers/imap/Makefile.am b/camel/providers/imap/Makefile.am
deleted file mode 100644
index 469964a9a6..0000000000
--- a/camel/providers/imap/Makefile.am
+++ /dev/null
@@ -1,49 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-libcamelimapincludedir = $(includedir)/camel
-
-camel_provider_LTLIBRARIES = libcamelimap.la
-camel_provider_DATA = libcamelimap.urls
-
-INCLUDES = -I.. \
- -I$(srcdir)/.. \
- -I$(top_srcdir)/camel \
- -I$(top_srcdir)/intl \
- -I$(top_srcdir)/e-util \
- -I$(top_srcdir) \
- -I$(includedir) \
- $(CAMEL_CFLAGS) \
- $(GNOME_INCLUDEDIR) \
- $(GTK_INCLUDEDIR) \
- -DG_LOG_DOMAIN=\"camel-imap-provider\"
-
-libcamelimap_la_SOURCES = \
- camel-imap-command.c \
- camel-imap-folder.c \
- camel-imap-message-cache.c \
- camel-imap-provider.c \
- camel-imap-search.c \
- camel-imap-store.c \
- camel-imap-store-summary.c \
- camel-imap-summary.c \
- camel-imap-utils.c \
- camel-imap-wrapper.c
-
-libcamelimapinclude_HEADERS = \
- camel-imap-command.h \
- camel-imap-folder.h \
- camel-imap-message-cache.h \
- camel-imap-search.h \
- camel-imap-store.h \
- camel-imap-store-summary.h \
- camel-imap-summary.h \
- camel-imap-types.h \
- camel-imap-utils.h \
- camel-imap-wrapper.h
-
-libcamelimap_la_LDFLAGS = -avoid-version -module
-
-noinst_HEADERS = \
- camel-imap-private.h
-
-EXTRA_DIST = libcamelimap.urls
diff --git a/camel/providers/imap/camel-imap-command.c b/camel/providers/imap/camel-imap-command.c
deleted file mode 100644
index e3581c80af..0000000000
--- a/camel/providers/imap/camel-imap-command.c
+++ /dev/null
@@ -1,812 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-imap-command.c: IMAP command sending/parsing routines */
-
-/*
- * Authors:
- * Dan Winship <danw@ximian.com>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright 2000, 2001 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.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-#include "camel-imap-command.h"
-#include "camel-imap-utils.h"
-#include "camel-imap-folder.h"
-#include "camel-imap-store.h"
-#include "camel-imap-store-summary.h"
-#include "camel-imap-private.h"
-#include <camel/camel-exception.h>
-#include <camel/camel-private.h>
-#include <camel/camel-utf8.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,
- CamelException *ex);
-static char *imap_read_untagged (CamelImapStore *store, char *line,
- CamelException *ex);
-static char *imap_command_strdup_vprintf (CamelImapStore *store,
- const char *fmt, va_list ap);
-static char *imap_command_strdup_printf (CamelImapStore *store,
- const char *fmt, ...);
-
-/**
- * camel_imap_command:
- * @store: the IMAP store
- * @folder: The folder to perform the operation in (or %NULL if not
- * relevant).
- * @ex: a CamelException
- * @fmt: a sort of printf-style format string, followed by arguments
- *
- * This function calls camel_imap_command_start() to send the
- * command, then reads the complete response to it using
- * camel_imap_command_response() and returns a CamelImapResponse
- * structure.
- *
- * As a special case, if @fmt is %NULL, it will just select @folder
- * and return the response from doing so.
- *
- * See camel_imap_command_start() for details on @fmt.
- *
- * On success, the store's connect_lock will be locked. It will be freed
- * when you call camel_imap_response_free. (The lock is recursive, so
- * callers can grab and release it themselves if they need to run
- * multiple commands atomically.)
- *
- * Return value: %NULL if an error occurred (in which case @ex will
- * be set). Otherwise, a CamelImapResponse describing the server's
- * response, which the caller must free with camel_imap_response_free().
- **/
-CamelImapResponse *
-camel_imap_command (CamelImapStore *store, CamelFolder *folder,
- CamelException *ex, const char *fmt, ...)
-{
- va_list ap;
- char *cmd;
-
- CAMEL_SERVICE_LOCK (store, connect_lock);
-
- if (fmt) {
- va_start (ap, fmt);
- cmd = imap_command_strdup_vprintf (store, fmt, ap);
- va_end (ap);
- } else {
- if (store->current_folder) {
- camel_object_unref (CAMEL_OBJECT (store->current_folder));
- store->current_folder = NULL;
- }
- store->current_folder = folder;
- camel_object_ref (CAMEL_OBJECT (folder));
- cmd = imap_command_strdup_printf (store, "SELECT %F",
- folder->full_name);
- }
-
- if (!imap_command_start (store, folder, cmd, ex)) {
- g_free (cmd);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
- return NULL;
- }
- g_free (cmd);
-
- return imap_read_response (store, ex);
-}
-
-/**
- * camel_imap_command_start:
- * @store: the IMAP store
- * @folder: The folder to perform the operation in (or %NULL if not
- * relevant).
- * @ex: a CamelException
- * @fmt: a sort of printf-style format string, followed by arguments
- *
- * This function makes sure that @folder (if non-%NULL) is the
- * currently-selected folder on @store and then sends the IMAP command
- * specified by @fmt and the following arguments.
- *
- * @fmt can include the following %-escapes ONLY:
- * %s, %d, %%: as with printf
- * %S: an IMAP "string" (quoted string or literal)
- * %F: an IMAP folder name
- *
- * %S strings will be passed as literals if the server supports LITERAL+
- * and quoted strings otherwise. (%S does not support strings that
- * contain newlines.)
- *
- * %F will have the imap store's namespace prepended and then be processed
- * like %S.
- *
- * On success, the store's connect_lock will be locked. It will be
- * freed when %CAMEL_IMAP_RESPONSE_TAGGED or %CAMEL_IMAP_RESPONSE_ERROR
- * is returned from camel_imap_command_response(). (The lock is
- * recursive, so callers can grab and release it themselves if they
- * need to run multiple commands atomically.)
- *
- * Return value: %TRUE if the command was sent successfully, %FALSE if
- * an error occurred (in which case @ex will be set).
- **/
-gboolean
-camel_imap_command_start (CamelImapStore *store, CamelFolder *folder,
- CamelException *ex, const char *fmt, ...)
-{
- va_list ap;
- char *cmd;
- gboolean ok;
-
- va_start (ap, fmt);
- cmd = imap_command_strdup_vprintf (store, fmt, ap);
- va_end (ap);
-
- CAMEL_SERVICE_LOCK (store, connect_lock);
- ok = imap_command_start (store, folder, cmd, ex);
- g_free (cmd);
-
- if (!ok)
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
- return ok;
-}
-
-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;
- CamelException internal_ex;
-
- response = camel_imap_command (store, folder, ex, NULL);
- if (!response)
- return FALSE;
- camel_exception_init (&internal_ex);
- camel_imap_folder_selected (folder, response, &internal_ex);
- camel_imap_response_free (store, response);
- if (camel_exception_is_set (&internal_ex)) {
- camel_exception_xfer (ex, &internal_ex);
- return FALSE;
- }
- }
-
- /* Send the command */
-#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;
-}
-
-/**
- * camel_imap_command_continuation:
- * @store: the IMAP store
- * @cmd: buffer containing the response/request data
- * @cmdlen: command length
- * @ex: a CamelException
- *
- * This method is for sending continuing responses to the IMAP server
- * after camel_imap_command() or camel_imap_command_response() returns
- * a continuation response.
- *
- * This function assumes you have an exclusive lock on the imap stream.
- *
- * Return value: as for camel_imap_command(). On failure, the store's
- * connect_lock will be released.
- **/
-CamelImapResponse *
-camel_imap_command_continuation (CamelImapStore *store, const char *cmd,
- size_t cmdlen, CamelException *ex)
-{
- if (!camel_imap_store_connected (store, ex))
- return NULL;
-
- 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"));
- else
- camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- g_strerror (errno));
- camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
- return NULL;
- }
-
- return imap_read_response (store, ex);
-}
-
-/**
- * camel_imap_command_response:
- * @store: the IMAP store
- * @response: a pointer to pass back the response data in
- * @ex: a CamelException
- *
- * This reads a single tagged, untagged, or continuation response from
- * @store into *@response. The caller must free the string when it is
- * done with it.
- *
- * Return value: One of %CAMEL_IMAP_RESPONSE_CONTINUATION,
- * %CAMEL_IMAP_RESPONSE_UNTAGGED, %CAMEL_IMAP_RESPONSE_TAGGED, or
- * %CAMEL_IMAP_RESPONSE_ERROR. If either of the last two, @store's
- * command lock will be unlocked.
- **/
-CamelImapResponseType
-camel_imap_command_response (CamelImapStore *store, char **response,
- CamelException *ex)
-{
- CamelImapResponseType type;
- char *respbuf;
-
- if (camel_imap_store_readline (store, &respbuf, ex) < 0) {
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
- return CAMEL_IMAP_RESPONSE_ERROR;
- }
-
- switch (*respbuf) {
- case '*':
- if (!g_strncasecmp (respbuf, "* BYE", 5)) {
- /* Connection was lost, no more data to fetch */
- camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
- camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("Server unexpectedly disconnected: %s"),
- _("Unknown error")); /* g_strerror (104)); FIXME after 1.0 is released */
- store->connected = FALSE;
- g_free (respbuf);
- respbuf = NULL;
- type = CAMEL_IMAP_RESPONSE_ERROR;
- break;
- }
-
- /* Read the rest of the response. */
- type = CAMEL_IMAP_RESPONSE_UNTAGGED;
- respbuf = imap_read_untagged (store, respbuf, ex);
- if (!respbuf)
- type = CAMEL_IMAP_RESPONSE_ERROR;
-
- break;
- case '+':
- type = CAMEL_IMAP_RESPONSE_CONTINUATION;
- break;
- default:
- type = CAMEL_IMAP_RESPONSE_TAGGED;
- break;
- }
- *response = respbuf;
-
- if (type == CAMEL_IMAP_RESPONSE_ERROR ||
- type == CAMEL_IMAP_RESPONSE_TAGGED)
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
-
- return type;
-}
-
-CamelImapResponse *
-imap_read_response (CamelImapStore *store, CamelException *ex)
-{
- CamelImapResponse *response;
- CamelImapResponseType type;
- char *respbuf, *p;
-
- /* Get another lock so that when we reach the tagged
- * response and camel_imap_command_response unlocks,
- * we're still locked. This lock is owned by response
- * and gets unlocked when response is freed.
- */
- CAMEL_SERVICE_LOCK (store, connect_lock);
-
- response = g_new0 (CamelImapResponse, 1);
- if (store->current_folder && camel_disco_store_status (CAMEL_DISCO_STORE (store)) != CAMEL_DISCO_STORE_RESYNCING) {
- response->folder = store->current_folder;
- camel_object_ref (CAMEL_OBJECT (response->folder));
- }
-
- response->untagged = g_ptr_array_new ();
- while ((type = camel_imap_command_response (store, &respbuf, ex))
- == CAMEL_IMAP_RESPONSE_UNTAGGED)
- g_ptr_array_add (response->untagged, respbuf);
-
- if (type == CAMEL_IMAP_RESPONSE_ERROR) {
- camel_imap_response_free_without_processing (store, response);
- return NULL;
- }
-
- response->status = respbuf;
-
- /* Check for OK or continuation response. */
- if (*respbuf == '+')
- return response;
- p = strchr (respbuf, ' ');
- if (p && !g_strncasecmp (p, " OK", 3))
- return response;
-
- /* We should never get BAD, or anything else but +, OK, or NO
- * for that matter.
- */
- if (!p || g_strncasecmp (p, " NO", 3) != 0) {
- g_warning ("Unexpected response from IMAP server: %s",
- respbuf);
- camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("Unexpected response from IMAP "
- "server: %s"), respbuf);
- camel_imap_response_free_without_processing (store, response);
- return NULL;
- }
-
- p += 3;
- if (!*p++)
- p = NULL;
- camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("IMAP command failed: %s"),
- p ? p : _("Unknown error"));
- camel_imap_response_free_without_processing (store, response);
- return NULL;
-}
-
-/* Given a line that is the start of an untagged response, read and
- * return the complete response, which may include an arbitrary number
- * of literals.
- */
-static char *
-imap_read_untagged (CamelImapStore *store, char *line, CamelException *ex)
-{
- int fulllen, length, ldigits, nread, i;
- GPtrArray *data;
- GString *str;
- char *end, *p, *s, *d;
-
- p = strrchr (line, '{');
- if (!p)
- return line;
-
- data = g_ptr_array_new ();
- fulllen = 0;
-
- while (1) {
- str = g_string_new (line);
- g_free (line);
- fulllen += str->len;
- g_ptr_array_add (data, str);
-
- p = strrchr (str->str, '{');
- if (!p)
- break;
-
- length = strtoul (p + 1, &end, 10);
- if (*end != '}' || *(end + 1) || end == p + 1)
- break;
- ldigits = end - (p + 1);
-
- /* Read the literal */
- str = g_string_sized_new (length + 2);
- str->str[0] = '\n';
- 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"));
- else
- camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, g_strerror (errno));
- camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
- g_string_free (str, TRUE);
- goto lose;
- }
- if (nread < length) {
- camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("Server response ended too soon."));
- camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
- g_string_free (str, TRUE);
- goto lose;
- }
- str->str[length + 1] = '\0';
-
- /* Fix up the literal, turning CRLFs into LF. Also, if
- * we find any embedded NULs, strip them. This is
- * dubious, but:
- * - The IMAP grammar says you can't have NULs here
- * anyway, so this will not affect our behavior
- * against any completely correct server.
- * - WU-imapd 12.264 (at least) will cheerily pass
- * NULs along if they are embedded in the message
- */
-
- s = d = str->str + 1;
- end = str->str + 1 + length;
- while (s < end) {
- while (s < end && *s == '\0') {
- s++;
- length--;
- }
- if (*s == '\r' && *(s + 1) == '\n') {
- s++;
- length--;
- }
- *d++ = *s++;
- }
- *d = '\0';
- str->len = length + 1;
-
- /* p points to the "{" in the line that starts the
- * literal. The length of the CR-less response must be
- * less than or equal to the length of the response
- * with CRs, therefore overwriting the old value with
- * the new value cannot cause an overrun. However, we
- * don't want it to be shorter either, because then the
- * GString's length would be off...
- */
- sprintf (p, "{%0*d}", ldigits, length);
-
- fulllen += str->len;
- g_ptr_array_add (data, str);
-
- /* Read the next line. */
- if (camel_imap_store_readline (store, &line, ex) < 0)
- goto lose;
- }
-
- /* Now reassemble the data. */
- p = line = g_malloc (fulllen + 1);
- for (i = 0; i < data->len; i++) {
- str = data->pdata[i];
- memcpy (p, str->str, str->len);
- p += str->len;
- g_string_free (str, TRUE);
- }
- *p = '\0';
- g_ptr_array_free (data, TRUE);
- return line;
-
- lose:
- for (i = 0; i < data->len; i++)
- g_string_free (data->pdata[i], TRUE);
- g_ptr_array_free (data, TRUE);
- return NULL;
-}
-
-
-/**
- * camel_imap_response_free:
- * @store: the CamelImapStore the response is from
- * @response: a CamelImapResponse
- *
- * Frees all of the data in @response and processes any untagged
- * EXPUNGE and EXISTS responses in it. Releases @store's connect_lock.
- **/
-void
-camel_imap_response_free (CamelImapStore *store, CamelImapResponse *response)
-{
- int i, number, exists = 0;
- GArray *expunged = NULL;
- char *resp, *p;
-
- if (!response)
- return;
-
- for (i = 0; i < response->untagged->len; i++) {
- resp = response->untagged->pdata[i];
-
- if (response->folder) {
- /* Check if it's something we need to handle. */
- number = strtoul (resp + 2, &p, 10);
- if (!g_strcasecmp (p, " EXISTS")) {
- exists = number;
- } else if (!g_strcasecmp (p, " EXPUNGE")) {
- if (!expunged) {
- expunged = g_array_new (FALSE, FALSE,
- sizeof (int));
- }
- g_array_append_val (expunged, number);
- }
- }
- g_free (resp);
- }
-
- g_ptr_array_free (response->untagged, TRUE);
- g_free (response->status);
-
- if (response->folder) {
- if (exists > 0 || expunged) {
- /* Update the summary */
- camel_imap_folder_changed (response->folder,
- exists, expunged, NULL);
- if (expunged)
- g_array_free (expunged, TRUE);
- }
-
- camel_object_unref (CAMEL_OBJECT (response->folder));
- }
-
- g_free (response);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
-}
-
-/**
- * camel_imap_response_free_without_processing:
- * @store: the CamelImapStore the response is from.
- * @response: a CamelImapResponse:
- *
- * Frees all of the data in @response without processing any untagged
- * responses. Releases @store's command lock.
- **/
-void
-camel_imap_response_free_without_processing (CamelImapStore *store,
- CamelImapResponse *response)
-{
- if (!response)
- return;
-
- if (response->folder) {
- camel_object_unref (CAMEL_OBJECT (response->folder));
- response->folder = NULL;
- }
- camel_imap_response_free (store, response);
-}
-
-/**
- * camel_imap_response_extract:
- * @store: the store the response came from
- * @response: the response data returned from camel_imap_command
- * @type: the response type to extract
- * @ex: a CamelException
- *
- * This checks that @response contains a single untagged response of
- * type @type and returns just that response data. If @response
- * doesn't contain the right information, the function will set @ex
- * and return %NULL. Either way, @response will be freed and the
- * store's connect_lock released.
- *
- * Return value: the desired response string, which the caller must free.
- **/
-char *
-camel_imap_response_extract (CamelImapStore *store,
- CamelImapResponse *response,
- const char *type,
- CamelException *ex)
-{
- int len = strlen (type), i;
- char *resp;
-
- len = strlen (type);
-
- for (i = 0; i < response->untagged->len; i++) {
- resp = response->untagged->pdata[i];
- /* Skip "* ", and initial sequence number, if present */
- strtoul (resp + 2, &resp, 10);
- if (*resp == ' ')
- resp = (char *) imap_next_word (resp);
-
- if (!g_strncasecmp (resp, type, len))
- break;
- }
-
- if (i < response->untagged->len) {
- resp = response->untagged->pdata[i];
- g_ptr_array_remove_index (response->untagged, i);
- } else {
- resp = NULL;
- camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("IMAP server response did not contain "
- "%s information"), type);
- }
-
- camel_imap_response_free (store, response);
- return resp;
-}
-
-/**
- * camel_imap_response_extract_continuation:
- * @store: the store the response came from
- * @response: the response data returned from camel_imap_command
- * @ex: a CamelException
- *
- * This checks that @response contains a continuation response, and
- * returns just that data. If @response doesn't contain a continuation
- * response, the function will set @ex, release @store's connect_lock,
- * and return %NULL. Either way, @response will be freed.
- *
- * Return value: the desired response string, which the caller must free.
- **/
-char *
-camel_imap_response_extract_continuation (CamelImapStore *store,
- CamelImapResponse *response,
- CamelException *ex)
-{
- char *status;
-
- if (response->status && *response->status == '+') {
- status = response->status;
- response->status = NULL;
- camel_imap_response_free (store, response);
- return status;
- }
-
- camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("Unexpected OK response from IMAP server: %s"),
- response->status);
- camel_imap_response_free (store, response);
- return NULL;
-}
-
-static char *
-imap_command_strdup_vprintf (CamelImapStore *store, const char *fmt,
- va_list ap)
-{
- GPtrArray *args;
- const char *p, *start;
- char *out, *outptr, *string;
- int num, len, i, arglen;
-
- args = g_ptr_array_new ();
-
- /* Determine the length of the data */
- len = strlen (fmt);
- p = start = fmt;
- while (*p) {
- p = strchr (start, '%');
- if (!p)
- break;
-
- switch (*++p) {
- case 'd':
- num = va_arg (ap, int);
- g_ptr_array_add (args, GINT_TO_POINTER (num));
- start = p + 1;
- len += 10;
- break;
- case 's':
- string = va_arg (ap, char *);
- g_ptr_array_add (args, string);
- start = p + 1;
- len += strlen (string);
- break;
- case 'S':
- case 'F':
- string = va_arg (ap, char *);
- arglen = strlen (string);
- g_ptr_array_add (args, string);
- if (imap_is_atom (string)) {
- len += arglen;
- } else {
- if (store->capabilities & IMAP_CAPABILITY_LITERALPLUS)
- len += arglen + 15;
- else
- len += arglen * 2;
- }
- start = p + 1;
- break;
- case '%':
- start = p;
- break;
- default:
- g_warning ("camel-imap-command is not printf. I don't "
- "know what '%%%c' means.", *p);
- start = *p ? p + 1 : p;
- break;
- }
- }
-
- /* Now write out the string */
- outptr = out = g_malloc (len + 1);
- p = start = fmt;
- i = 0;
- while (*p) {
- p = strchr (start, '%');
- if (!p) {
- strcpy (outptr, start);
- break;
- } else {
- strncpy (outptr, start, p - start);
- outptr += p - start;
- }
-
- switch (*++p) {
- case 'd':
- num = GPOINTER_TO_INT (args->pdata[i++]);
- outptr += sprintf (outptr, "%d", num);
- break;
-
- case 's':
- string = args->pdata[i++];
- outptr += sprintf (outptr, "%s", string);
- break;
- case 'S':
- case 'F':
- string = args->pdata[i++];
- if (*p == 'F') {
- char *s = camel_imap_store_summary_full_from_path(store->summary, string);
- string = s?s:camel_utf8_utf7(string);
- }
-
- if (imap_is_atom (string)) {
- outptr += sprintf (outptr, "%s", string);
- } else {
- if (store->capabilities & IMAP_CAPABILITY_LITERALPLUS) {
- outptr += sprintf (outptr, "{%d+}\r\n%s", strlen (string), string);
- } else {
- char *quoted = imap_quote_string (string);
-
- outptr += sprintf (outptr, "%s", quoted);
- g_free (quoted);
- }
- }
-
- if (*p == 'F')
- g_free (string);
- break;
- default:
- *outptr++ = '%';
- *outptr++ = *p;
- }
-
- start = *p ? p + 1 : p;
- }
-
- return out;
-}
-
-static char *
-imap_command_strdup_printf (CamelImapStore *store, const char *fmt, ...)
-{
- va_list ap;
- char *result;
-
- va_start (ap, fmt);
- result = imap_command_strdup_vprintf (store, fmt, ap);
- va_end (ap);
-
- return result;
-}
diff --git a/camel/providers/imap/camel-imap-command.h b/camel/providers/imap/camel-imap-command.h
deleted file mode 100644
index 3539ac63d2..0000000000
--- a/camel/providers/imap/camel-imap-command.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-imap-command.h: IMAP command sending/parsing routines */
-
-/*
- * Authors:
- * Dan Winship <danw@ximian.com>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 2000, 2001 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_IMAP_COMMAND_H
-#define CAMEL_IMAP_COMMAND_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus }*/
-
-#include <glib.h>
-#include "camel-imap-types.h"
-
-typedef enum {
- CAMEL_IMAP_RESPONSE_ERROR,
- CAMEL_IMAP_RESPONSE_CONTINUATION,
- CAMEL_IMAP_RESPONSE_UNTAGGED,
- CAMEL_IMAP_RESPONSE_TAGGED
-} CamelImapResponseType;
-
-struct _CamelImapResponse {
- CamelFolder *folder;
- GPtrArray *untagged;
- char *status;
-};
-
-CamelImapResponse *camel_imap_command (CamelImapStore *store,
- CamelFolder *folder,
- CamelException *ex,
- const char *fmt, ...);
-CamelImapResponse *camel_imap_command_continuation (CamelImapStore *store,
- const char *cmd,
- size_t cmdlen,
- CamelException *ex);
-
-void camel_imap_response_free (CamelImapStore *store,
- CamelImapResponse *response);
-void camel_imap_response_free_without_processing (CamelImapStore *store,
- CamelImapResponse *response);
-char *camel_imap_response_extract (CamelImapStore *store,
- CamelImapResponse *response,
- const char *type,
- CamelException *ex);
-char *camel_imap_response_extract_continuation (CamelImapStore *store,
- CamelImapResponse *response,
- CamelException *ex);
-
-gboolean camel_imap_command_start (CamelImapStore *store,
- CamelFolder *folder,
- CamelException *ex,
- const char *fmt, ...);
-CamelImapResponseType camel_imap_command_response (CamelImapStore *store,
- char **respbuf,
- CamelException *ex);
-
-#endif /* CAMEL_IMAP_COMMAND_H */
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
deleted file mode 100644
index 1a2f5a79e9..0000000000
--- a/camel/providers/imap/camel-imap-folder.c
+++ /dev/null
@@ -1,2590 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-imap-folder.c: class for an imap folder */
-
-/*
- * Authors:
- * Dan Winship <danw@ximian.com>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 2000, 2001 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
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <ctype.h>
-
-#include "e-util/e-path.h"
-
-#include "camel-imap-folder.h"
-#include "camel-imap-command.h"
-#include "camel-imap-message-cache.h"
-#include "camel-imap-private.h"
-#include "camel-imap-search.h"
-#include "camel-imap-store.h"
-#include "camel-imap-summary.h"
-#include "camel-imap-utils.h"
-#include "camel-imap-wrapper.h"
-#include "camel-data-wrapper.h"
-#include "camel-disco-diary.h"
-#include "camel-exception.h"
-#include "camel-mime-filter-crlf.h"
-#include "camel-mime-filter-from.h"
-#include "camel-mime-message.h"
-#include "camel-mime-utils.h"
-#include "camel-multipart.h"
-#include "camel-multipart-signed.h"
-#include "camel-multipart-encrypted.h"
-#include "camel-operation.h"
-#include "camel-session.h"
-#include "camel-stream-buffer.h"
-#include "camel-stream-filter.h"
-#include "camel-stream-mem.h"
-#include "camel-stream.h"
-#include "string-utils.h"
-#include "camel-private.h"
-
-
-#define d(x) x
-
-/* set to -1 for infinite size */
-#define UID_SET_LIMIT (4096)
-
-
-#define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(o)))
-static CamelDiscoFolderClass *disco_folder_class = NULL;
-
-static void imap_finalize (CamelObject *object);
-static int imap_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args);
-
-static void imap_rescan (CamelFolder *folder, int exists, CamelException *ex);
-static void imap_refresh_info (CamelFolder *folder, CamelException *ex);
-static void imap_sync_online (CamelFolder *folder, CamelException *ex);
-static void imap_sync_offline (CamelFolder *folder, CamelException *ex);
-static void imap_expunge_uids_online (CamelFolder *folder, GPtrArray *uids, CamelException *ex);
-static void imap_expunge_uids_offline (CamelFolder *folder, GPtrArray *uids, CamelException *ex);
-static void imap_expunge_uids_resyncing (CamelFolder *folder, GPtrArray *uids, CamelException *ex);
-static void imap_cache_message (CamelDiscoFolder *disco_folder, const char *uid, CamelException *ex);
-static void imap_rename (CamelFolder *folder, const char *new);
-
-/* message manipulation */
-static CamelMimeMessage *imap_get_message (CamelFolder *folder, const gchar *uid,
- CamelException *ex);
-static void imap_append_online (CamelFolder *folder, CamelMimeMessage *message,
- const CamelMessageInfo *info, char **appended_uid,
- CamelException *ex);
-static void imap_append_offline (CamelFolder *folder, CamelMimeMessage *message,
- const CamelMessageInfo *info, char **appended_uid,
- CamelException *ex);
-static void imap_append_resyncing (CamelFolder *folder, CamelMimeMessage *message,
- const CamelMessageInfo *info, char **appended_uid,
- CamelException *ex);
-
-static void imap_transfer_online (CamelFolder *source, GPtrArray *uids,
- CamelFolder *dest, GPtrArray **transferred_uids,
- gboolean delete_originals,
- CamelException *ex);
-static void imap_transfer_offline (CamelFolder *source, GPtrArray *uids,
- CamelFolder *dest, GPtrArray **transferred_uids,
- gboolean delete_originals,
- CamelException *ex);
-static void imap_transfer_resyncing (CamelFolder *source, GPtrArray *uids,
- CamelFolder *dest, GPtrArray **transferred_uids,
- gboolean delete_originals,
- CamelException *ex);
-
-/* searching */
-static GPtrArray *imap_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex);
-static GPtrArray *imap_search_by_uids (CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex);
-static void imap_search_free (CamelFolder *folder, GPtrArray *uids);
-
-static void imap_thaw (CamelFolder *folder);
-
-static CamelObjectClass *parent_class;
-
-static GData *parse_fetch_response (CamelImapFolder *imap_folder, char *msg_att);
-
-static void
-camel_imap_folder_class_init (CamelImapFolderClass *camel_imap_folder_class)
-{
- CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_imap_folder_class);
- CamelDiscoFolderClass *camel_disco_folder_class = CAMEL_DISCO_FOLDER_CLASS (camel_imap_folder_class);
-
- disco_folder_class = CAMEL_DISCO_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_disco_folder_get_type ()));
-
- /* virtual method overload */
- ((CamelObjectClass *)camel_imap_folder_class)->getv = imap_getv;
-
- camel_folder_class->get_message = imap_get_message;
- camel_folder_class->rename = imap_rename;
- camel_folder_class->search_by_expression = imap_search_by_expression;
- camel_folder_class->search_by_uids = imap_search_by_uids;
- camel_folder_class->search_free = imap_search_free;
- camel_folder_class->thaw = imap_thaw;
-
- camel_disco_folder_class->refresh_info_online = imap_refresh_info;
- camel_disco_folder_class->sync_online = imap_sync_online;
- camel_disco_folder_class->sync_offline = imap_sync_offline;
- /* We don't sync flags at resync time: the online code will
- * deal with it eventually.
- */
- camel_disco_folder_class->sync_resyncing = imap_sync_offline;
- camel_disco_folder_class->expunge_uids_online = imap_expunge_uids_online;
- camel_disco_folder_class->expunge_uids_offline = imap_expunge_uids_offline;
- camel_disco_folder_class->expunge_uids_resyncing = imap_expunge_uids_resyncing;
- camel_disco_folder_class->append_online = imap_append_online;
- camel_disco_folder_class->append_offline = imap_append_offline;
- camel_disco_folder_class->append_resyncing = imap_append_resyncing;
- camel_disco_folder_class->transfer_online = imap_transfer_online;
- camel_disco_folder_class->transfer_offline = imap_transfer_offline;
- camel_disco_folder_class->transfer_resyncing = imap_transfer_resyncing;
- camel_disco_folder_class->cache_message = imap_cache_message;
-}
-
-static void
-camel_imap_folder_init (gpointer object, gpointer klass)
-{
- CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object);
- CamelFolder *folder = CAMEL_FOLDER (object);
-
- folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_DELETED |
- CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN;
-
- folder->folder_flags |= (CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY |
- CAMEL_FOLDER_HAS_SEARCH_CAPABILITY);
-
- imap_folder->priv = g_malloc0(sizeof(*imap_folder->priv));
-#ifdef ENABLE_THREADS
- imap_folder->priv->search_lock = e_mutex_new(E_MUTEX_SIMPLE);
- imap_folder->priv->cache_lock = e_mutex_new(E_MUTEX_REC);
-#endif
-
- imap_folder->need_rescan = TRUE;
-}
-
-CamelType
-camel_imap_folder_get_type (void)
-{
- static CamelType camel_imap_folder_type = CAMEL_INVALID_TYPE;
-
- if (camel_imap_folder_type == CAMEL_INVALID_TYPE) {
- parent_class = camel_disco_folder_get_type();
- camel_imap_folder_type =
- camel_type_register (parent_class, "CamelImapFolder",
- sizeof (CamelImapFolder),
- sizeof (CamelImapFolderClass),
- (CamelObjectClassInitFunc) camel_imap_folder_class_init,
- NULL,
- (CamelObjectInitFunc) camel_imap_folder_init,
- (CamelObjectFinalizeFunc) imap_finalize);
- }
-
- return camel_imap_folder_type;
-}
-
-CamelFolder *
-camel_imap_folder_new (CamelStore *parent, const char *folder_name,
- const char *folder_dir, CamelException *ex)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (parent);
- CamelFolder *folder;
- CamelImapFolder *imap_folder;
- const char *short_name;
- char *summary_file;
-
- if (camel_mkdir_hier (folder_dir, S_IRWXU) != 0) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Could not create directory %s: %s"),
- folder_dir, g_strerror (errno));
- return NULL;
- }
-
- folder = CAMEL_FOLDER (camel_object_new (camel_imap_folder_get_type ()));
- short_name = strrchr (folder_name, imap_store->dir_sep);
- if (short_name)
- short_name++;
- else
- short_name = folder_name;
- camel_folder_construct (folder, parent, folder_name, short_name);
-
- summary_file = g_strdup_printf ("%s/summary", folder_dir);
- folder->summary = camel_imap_summary_new (summary_file);
- g_free (summary_file);
- if (!folder->summary) {
- camel_object_unref (CAMEL_OBJECT (folder));
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Could not load summary for %s"),
- folder_name);
- return NULL;
- }
-
- imap_folder = CAMEL_IMAP_FOLDER (folder);
- imap_folder->cache = camel_imap_message_cache_new (folder_dir, folder->summary, ex);
- if (!imap_folder->cache) {
- camel_object_unref (CAMEL_OBJECT (folder));
- return NULL;
- }
-
- if ((imap_store->parameters & IMAP_PARAM_FILTER_INBOX) &&
- !g_strcasecmp (folder_name, "INBOX"))
- folder->folder_flags |= CAMEL_FOLDER_FILTER_RECENT;
-
- imap_folder->search = camel_imap_search_new(folder_dir);
-
- return folder;
-}
-
-/* Called with the store's connect_lock locked */
-void
-camel_imap_folder_selected (CamelFolder *folder, CamelImapResponse *response,
- CamelException *ex)
-{
- CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
- CamelImapSummary *imap_summary = CAMEL_IMAP_SUMMARY (folder->summary);
- unsigned long exists = 0, validity = 0, val, uid;
- CamelMessageInfo *info;
- GData *fetch_data;
- int i, count;
- char *resp;
-
- CAMEL_SERVICE_ASSERT_LOCKED (folder->parent_store, connect_lock);
-
- count = camel_folder_summary_count (folder->summary);
-
- for (i = 0; i < response->untagged->len; i++) {
- resp = response->untagged->pdata[i] + 2;
- if (!g_strncasecmp (resp, "FLAGS ", 6) &&
- !folder->permanent_flags) {
- resp += 6;
- folder->permanent_flags = imap_parse_flag_list (&resp);
- } else if (!g_strncasecmp (resp, "OK [PERMANENTFLAGS ", 19)) {
- resp += 19;
- folder->permanent_flags = imap_parse_flag_list (&resp);
- } else if (!g_strncasecmp (resp, "OK [UIDVALIDITY ", 16)) {
- validity = strtoul (resp + 16, NULL, 10);
- } else if (isdigit ((unsigned char)*resp)) {
- unsigned long num = strtoul (resp, &resp, 10);
-
- if (!g_strncasecmp (resp, " EXISTS", 7)) {
- exists = num;
- /* Remove from the response so nothing
- * else tries to interpret it.
- */
- g_free (response->untagged->pdata[i]);
- g_ptr_array_remove_index (response->untagged, i--);
- }
- }
- }
-
- if (camel_disco_store_status (CAMEL_DISCO_STORE (folder->parent_store)) == CAMEL_DISCO_STORE_RESYNCING) {
- if (validity != imap_summary->validity) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_SUMMARY_INVALID,
- _("Folder was destroyed and recreated on server."));
- return;
- }
-
- /* FIXME: find missing UIDs ? */
- return;
- }
-
- if (!imap_summary->validity)
- imap_summary->validity = validity;
- else if (validity != imap_summary->validity) {
- imap_summary->validity = validity;
- camel_folder_summary_clear (folder->summary);
- CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock);
- camel_imap_message_cache_clear (imap_folder->cache);
- CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
- imap_folder->need_rescan = FALSE;
- camel_imap_folder_changed (folder, exists, NULL, ex);
- return;
- }
-
- /* If we've lost messages, we have to rescan everything */
- if (exists < count)
- imap_folder->need_rescan = TRUE;
- else if (count != 0 && !imap_folder->need_rescan) {
- CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
-
- /* Similarly, if the UID of the highest message we
- * know about has changed, then that indicates that
- * messages have been both added and removed, so we
- * have to rescan to find the removed ones. (We pass
- * NULL for the folder since we know that this folder
- * is selected, and we don't want camel_imap_command
- * to worry about it.)
- */
- response = camel_imap_command (store, NULL, ex, "FETCH %d UID", count);
- if (!response)
- return;
- uid = 0;
- for (i = 0; i < response->untagged->len; i++) {
- resp = response->untagged->pdata[i];
- val = strtoul (resp + 2, &resp, 10);
- if (val == 0)
- continue;
- if (!g_strcasecmp (resp, " EXISTS")) {
- /* Another one?? */
- exists = val;
- continue;
- }
- if (uid != 0 || val != count || g_strncasecmp (resp, " FETCH (", 8) != 0)
- continue;
-
- fetch_data = parse_fetch_response (imap_folder, resp + 7);
- uid = strtoul (g_datalist_get_data (&fetch_data, "UID"), NULL, 10);
- g_datalist_clear (&fetch_data);
- }
- camel_imap_response_free_without_processing (store, response);
-
- info = camel_folder_summary_index (folder->summary, count - 1);
- val = strtoul (camel_message_info_uid (info), NULL, 10);
- camel_folder_summary_info_free (folder->summary, info);
- if (uid == 0 || uid != val)
- imap_folder->need_rescan = TRUE;
- }
-
- /* Now rescan if we need to */
- if (imap_folder->need_rescan) {
- imap_rescan (folder, exists, ex);
- return;
- }
-
- /* If we don't need to rescan completely, but new messages
- * have been added, find out about them.
- */
- if (exists > count)
- camel_imap_folder_changed (folder, exists, NULL, ex);
-
- /* And we're done. */
-}
-
-static void
-imap_finalize (CamelObject *object)
-{
- CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object);
-
- if (imap_folder->search)
- camel_object_unref (CAMEL_OBJECT (imap_folder->search));
- if (imap_folder->cache)
- camel_object_unref (CAMEL_OBJECT (imap_folder->cache));
-
-#ifdef ENABLE_THREADS
- e_mutex_destroy(imap_folder->priv->search_lock);
- e_mutex_destroy(imap_folder->priv->cache_lock);
-#endif
- g_free(imap_folder->priv);
-}
-
-static int
-imap_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args)
-{
- CamelFolder *folder = (CamelFolder *)object;
- int i, count=args->argc;
- guint32 tag;
-
- for (i=0;i<args->argc;i++) {
- CamelArgGet *arg = &args->argv[i];
-
- tag = arg->tag;
-
- switch (tag & CAMEL_ARG_TAG) {
- /* CamelObject args */
- case CAMEL_OBJECT_ARG_DESCRIPTION:
- if (folder->description == NULL) {
- CamelURL *uri = ((CamelService *)folder->parent_store)->url;
-
- /* what if the full name doesn't incclude /'s? does it matter? */
- folder->description = g_strdup_printf("%s@%s:%s", uri->user, uri->host, folder->full_name);
- }
- *arg->ca_str = folder->description;
- break;
- default:
- count--;
- continue;
- }
-
- arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE;
- }
-
- if (count)
- return ((CamelObjectClass *)parent_class)->getv(object, ex, args);
-
- return 0;
-}
-
-static void
-imap_rename (CamelFolder *folder, const char *new)
-{
- CamelImapFolder *imap_folder = (CamelImapFolder *)folder;
- CamelImapStore *imap_store = (CamelImapStore *)folder->parent_store;
- char *folder_dir, *summary_path;
- char *folders;
-
- folders = g_strconcat (imap_store->storage_path, "/folders", NULL);
- folder_dir = e_path_to_physical (folders, new);
- g_free (folders);
- summary_path = g_strdup_printf("%s/summary", folder_dir);
-
- CAMEL_IMAP_FOLDER_LOCK (folder, cache_lock);
- camel_imap_message_cache_set_path(imap_folder->cache, folder_dir);
- CAMEL_IMAP_FOLDER_UNLOCK (folder, cache_lock);
-
- camel_folder_summary_set_filename(folder->summary, summary_path);
-
- g_free(summary_path);
- g_free(folder_dir);
-
- ((CamelFolderClass *)disco_folder_class)->rename(folder, new);
-}
-
-static void
-imap_refresh_info (CamelFolder *folder, CamelException *ex)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (folder->parent_store);
- CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
- CamelImapResponse *response;
-
- if (camel_disco_store_status (CAMEL_DISCO_STORE (imap_store)) == CAMEL_DISCO_STORE_OFFLINE)
- return;
-
- if (camel_folder_is_frozen (folder)) {
- imap_folder->need_refresh = TRUE;
- return;
- }
-
- /* If the folder isn't selected, select it (which will force
- * a rescan if one is needed).
- * Also, if this is the INBOX, some servers (cryus) wont tell
- * us with a NOOP of new messages, so force a reselect which
- * should do it. */
- CAMEL_SERVICE_LOCK (imap_store, connect_lock);
- if (imap_store->current_folder != folder
- || strcasecmp(folder->full_name, "INBOX") == 0) {
- CAMEL_SERVICE_UNLOCK (imap_store, connect_lock);
- response = camel_imap_command (imap_store, folder, ex, NULL);
- if (response) {
- camel_imap_folder_selected (folder, response, NULL);
- camel_imap_response_free (imap_store, response);
- }
- return;
- }
- CAMEL_SERVICE_UNLOCK (imap_store, connect_lock);
-
- /* Otherwise, if we need a rescan, do it, and if not, just do
- * a NOOP to give the server a chance to tell us about new
- * messages.
- */
- if (imap_folder->need_rescan)
- imap_rescan (folder, camel_folder_summary_count (folder->summary), ex);
- else {
-#if 0
- /* on some servers need to CHECKpoint INBOX to recieve new messages?? */
- /* rfc2060 suggests this, but havent seen a server that requires it */
- if (strcasecmp(folder->full_name, "INBOX") == 0) {
- response = camel_imap_command (imap_store, folder, ex, "CHECK");
- camel_imap_response_free (imap_store, response);
- }
-#endif
- response = camel_imap_command (imap_store, folder, ex, "NOOP");
- camel_imap_response_free (imap_store, response);
- }
-}
-
-/* Called with the store's connect_lock locked */
-static void
-imap_rescan (CamelFolder *folder, int exists, CamelException *ex)
-{
- CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
- CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
- struct {
- char *uid;
- guint32 flags;
- } *new;
- char *resp;
- CamelImapResponseType type;
- int i, seq, summary_len, summary_got;
- CamelMessageInfo *info;
- CamelImapMessageInfo *iinfo;
- GArray *removed;
- gboolean ok;
- CamelFolderChangeInfo *changes = NULL;
-
- CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock);
- imap_folder->need_rescan = FALSE;
-
- summary_len = camel_folder_summary_count (folder->summary);
- if (summary_len == 0) {
- if (exists)
- camel_imap_folder_changed (folder, exists, NULL, ex);
- return;
- }
-
- /* Check UIDs and flags of all messages we already know of. */
- camel_operation_start (NULL, _("Scanning for changed messages"));
- info = camel_folder_summary_index (folder->summary, summary_len - 1);
- ok = camel_imap_command_start (store, folder, ex,
- "UID FETCH 1:%s (FLAGS)",
- camel_message_info_uid (info));
- camel_folder_summary_info_free (folder->summary, info);
- if (!ok) {
- camel_operation_end (NULL);
- return;
- }
-
- new = g_malloc0 (summary_len * sizeof (*new));
- summary_got = 0;
- while ((type = camel_imap_command_response (store, &resp, ex)) == CAMEL_IMAP_RESPONSE_UNTAGGED) {
- GData *data;
- char *uid;
- guint32 flags;
-
- data = parse_fetch_response (imap_folder, resp);
- g_free (resp);
- if (!data)
- continue;
-
- seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE"));
- uid = g_datalist_get_data (&data, "UID");
- flags = GPOINTER_TO_UINT (g_datalist_get_data (&data, "FLAGS"));
-
- if (!uid || !seq || seq > summary_len) {
- g_datalist_clear (&data);
- continue;
- }
-
- camel_operation_progress (NULL, ++summary_got * 100 / summary_len);
- new[seq - 1].uid = g_strdup (uid);
- new[seq - 1].flags = flags;
- g_datalist_clear (&data);
- }
-
- camel_operation_end (NULL);
- if (type == CAMEL_IMAP_RESPONSE_ERROR) {
- for (i = 0; i < summary_len && new[i].uid; i++)
- g_free (new[i].uid);
- g_free (new);
- return;
- }
-
- /* Free the final tagged response */
- g_free (resp);
-
- /* If we find a UID in the summary that doesn't correspond to
- * the UID in the folder, then either: (a) it's a real UID,
- * but the message was deleted on the server, or (b) it's a
- * fake UID, and needs to be removed from the summary in order
- * to sync up with the server. So either way, we remove it
- * from the summary.
- */
- removed = g_array_new (FALSE, FALSE, sizeof (int));
- for (i = 0; i < summary_len && new[i].uid; i++) {
- info = camel_folder_summary_index (folder->summary, i);
- iinfo = (CamelImapMessageInfo *)info;
-
- if (strcmp (camel_message_info_uid (info), new[i].uid) != 0) {
- camel_folder_summary_info_free(folder->summary, info);
- seq = i + 1;
- g_array_append_val (removed, seq);
- i--;
- summary_len--;
- continue;
- }
-
- /* Update summary flags */
- if (new[i].flags != iinfo->server_flags) {
- guint32 server_set, server_cleared;
-
- server_set = new[i].flags & ~iinfo->server_flags;
- server_cleared = iinfo->server_flags & ~new[i].flags;
-
- info->flags = (info->flags | server_set) & ~server_cleared;
- iinfo->server_flags = new[i].flags;
-
- if (changes == NULL)
- changes = camel_folder_change_info_new();
- camel_folder_change_info_change_uid(changes, new[i].uid);
- }
-
- camel_folder_summary_info_free (folder->summary, info);
- g_free (new[i].uid);
- }
-
- if (changes) {
- camel_object_trigger_event(CAMEL_OBJECT (folder), "folder_changed", changes);
- camel_folder_change_info_free(changes);
- }
-
- seq = i + 1;
-
- /* Free remaining memory. */
- while (i < summary_len && new[i].uid)
- g_free (new[i++].uid);
- g_free (new);
-
- /* Remove any leftover cached summary messages. (Yes, we
- * repeatedly add the same number to the removed array.
- * See RFC2060 7.4.1)
- */
-
- for (i = seq; i <= summary_len; i++)
- g_array_append_val (removed, seq);
-
- /* And finally update the summary. */
- camel_imap_folder_changed (folder, exists, removed, ex);
- g_array_free (removed, TRUE);
-}
-
-/* the max number of chars that an unsigned 32-bit int can be is 10 chars plus 1 for a possible : */
-#define UID_SET_FULL(setlen, maxlen) (maxlen > 0 ? setlen + 11 >= maxlen : FALSE)
-
-/* Find all messages in @folder with flags matching @flags and @mask.
- * If no messages match, returns %NULL. Otherwise, returns an array of
- * CamelMessageInfo and sets *@set to a message set corresponding the
- * UIDs of the matched messages (up to @UID_SET_LIMIT bytes). The
- * caller must free the infos, the array, and the set string.
- */
-static GPtrArray *
-get_matching (CamelFolder *folder, guint32 flags, guint32 mask, char **set)
-{
- GPtrArray *matches;
- CamelMessageInfo *info;
- int i, max, range;
- GString *gset;
-
- matches = g_ptr_array_new ();
- gset = g_string_new ("");
- max = camel_folder_summary_count (folder->summary);
- range = -1;
- for (i = 0; i < max && !UID_SET_FULL (gset->len, UID_SET_LIMIT); i++) {
- info = camel_folder_summary_index (folder->summary, i);
- if (!info)
- continue;
- if ((info->flags & mask) != flags) {
- camel_folder_summary_info_free (folder->summary, info);
- if (range != -1) {
- if (range != i - 1) {
- info = matches->pdata[matches->len - 1];
- g_string_sprintfa (gset, ":%s", camel_message_info_uid (info));
- }
- range = -1;
- }
- continue;
- }
-
- g_ptr_array_add (matches, info);
- if (range != -1)
- continue;
- range = i;
- if (gset->len)
- g_string_append_c (gset, ',');
- g_string_sprintfa (gset, "%s", camel_message_info_uid (info));
- }
-
- if (range != -1 && range != max - 1) {
- info = matches->pdata[matches->len - 1];
- g_string_sprintfa (gset, ":%s", camel_message_info_uid (info));
- }
-
- if (matches->len) {
- *set = gset->str;
- g_string_free (gset, FALSE);
- return matches;
- } else {
- g_string_free (gset, TRUE);
- g_ptr_array_free (matches, TRUE);
- return NULL;
- }
-}
-
-static void
-imap_sync_offline (CamelFolder *folder, CamelException *ex)
-{
- camel_folder_summary_save (folder->summary);
-}
-
-static void
-imap_sync_online (CamelFolder *folder, CamelException *ex)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
- CamelImapResponse *response = NULL;
- CamelMessageInfo *info;
- CamelException local_ex;
- GPtrArray *matches;
- char *set, *flaglist;
- gboolean unset;
- int i, j, max;
-
- camel_exception_init (&local_ex);
- CAMEL_SERVICE_LOCK (store, connect_lock);
-
- /* Find a message with changed flags, find all of the other
- * messages like it, sync them as a group, mark them as
- * updated, and continue.
- */
- max = camel_folder_summary_count (folder->summary);
- for (i = 0; i < max; i++) {
- info = camel_folder_summary_index (folder->summary, i);
- if (!info)
- continue;
- if (!(info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) {
- camel_folder_summary_info_free (folder->summary, info);
- continue;
- }
-
- /* Note: Cyrus is broken and will not accept an
- empty-set of flags so... if this is true then we
- want to unset the previously set flags.*/
- unset = !(info->flags & CAMEL_IMAP_SERVER_FLAGS);
-
- /* FIXME: since we don't know the previously set flags,
- if unset is TRUE then just unset all the flags? */
- flaglist = imap_create_flag_list (unset ? CAMEL_IMAP_SERVER_FLAGS : info->flags);
-
- /* Note: get_matching() uses UID_SET_LIMIT to limit
- the size of the uid-set string. We don't have to
- loop here to flush all the matching uids because
- they will be scooped up later by our parent loop (I
- think?). -- Jeff */
- matches = get_matching (folder, info->flags & (CAMEL_IMAP_SERVER_FLAGS | CAMEL_MESSAGE_FOLDER_FLAGGED),
- CAMEL_IMAP_SERVER_FLAGS | CAMEL_MESSAGE_FOLDER_FLAGGED, &set);
- camel_folder_summary_info_free (folder->summary, info);
-
- /* Note: to `unset' flags, use -FLAGS.SILENT (<flag list>) */
- response = camel_imap_command (store, folder, &local_ex,
- "UID STORE %s %sFLAGS.SILENT %s",
- set, unset ? "-" : "", flaglist);
- g_free (set);
- g_free (flaglist);
-
- if (response)
- camel_imap_response_free (store, response);
-
- if (!camel_exception_is_set (&local_ex)) {
- for (j = 0; j < matches->len; j++) {
- info = matches->pdata[j];
- info->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
- ((CamelImapMessageInfo*)info)->server_flags =
- info->flags & CAMEL_IMAP_SERVER_FLAGS;
- }
- camel_folder_summary_touch (folder->summary);
- }
-
- for (j = 0; j < matches->len; j++) {
- info = matches->pdata[j];
- camel_folder_summary_info_free (folder->summary, info);
- }
- g_ptr_array_free (matches, TRUE);
-
- /* We unlock here so that other threads can have a chance to grab the connect_lock */
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
-
- /* check for an exception */
- if (camel_exception_is_set (&local_ex)) {
- camel_exception_xfer (ex, &local_ex);
- return;
- }
-
- /* Re-lock the connect_lock */
- CAMEL_SERVICE_LOCK (store, connect_lock);
- }
-
- /* Save the summary */
- imap_sync_offline (folder, ex);
-
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
-}
-
-static void
-imap_expunge_uids_offline (CamelFolder *folder, GPtrArray *uids, CamelException *ex)
-{
- CamelFolderChangeInfo *changes;
- int i;
-
- changes = camel_folder_change_info_new ();
-
- for (i = 0; i < uids->len; i++) {
- camel_folder_summary_remove_uid (folder->summary, uids->pdata[i]);
- camel_folder_change_info_remove_uid (changes, uids->pdata[i]);
- /* We intentionally don't remove it from the cache because
- * the cached data may be useful in replaying a COPY later.
- */
- }
- camel_folder_summary_save (folder->summary);
-
- camel_disco_diary_log (CAMEL_DISCO_STORE (folder->parent_store)->diary,
- CAMEL_DISCO_DIARY_FOLDER_EXPUNGE, folder, uids);
-
- camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", changes);
- camel_folder_change_info_free (changes);
-}
-
-static void
-imap_expunge_uids_online (CamelFolder *folder, GPtrArray *uids, CamelException *ex)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
- CamelImapResponse *response;
- int uid = 0;
- char *set;
-
- CAMEL_SERVICE_LOCK (store, connect_lock);
-
- if ((store->capabilities & IMAP_CAPABILITY_UIDPLUS) == 0) {
- ((CamelFolderClass *)CAMEL_OBJECT_GET_CLASS(folder))->sync(folder, 0, ex);
- if (camel_exception_is_set(ex)) {
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
- return;
- }
- }
-
- while (uid < uids->len) {
- set = imap_uid_array_to_set (folder->summary, uids, uid, UID_SET_LIMIT, &uid);
- response = camel_imap_command (store, folder, ex,
- "UID STORE %s +FLAGS.SILENT \\Deleted",
- set);
- if (response)
- camel_imap_response_free (store, response);
- if (camel_exception_is_set (ex)) {
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
- g_free (set);
- return;
- }
-
- if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) {
- response = camel_imap_command (store, folder, ex,
- "UID EXPUNGE %s", set);
- } else
- response = camel_imap_command (store, folder, ex, "EXPUNGE");
-
- if (response)
- camel_imap_response_free (store, response);
- }
-
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
-}
-
-static int
-uid_compar (const void *va, const void *vb)
-{
- const char **sa = (const char **)va, **sb = (const char **)vb;
- unsigned long a, b;
-
- a = strtoul (*sa, NULL, 10);
- b = strtoul (*sb, NULL, 10);
- if (a < b)
- return -1;
- else if (a == b)
- return 0;
- else
- return 1;
-}
-
-static void
-imap_expunge_uids_resyncing (CamelFolder *folder, GPtrArray *uids, CamelException *ex)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
- GPtrArray *keep_uids, *mark_uids;
- CamelImapResponse *response;
- char *result;
-
- if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) {
- imap_expunge_uids_online (folder, uids, ex);
- return;
- }
-
- /* If we don't have UID EXPUNGE we need to avoid expunging any
- * of the wrong messages. So we search for deleted messages,
- * and any that aren't in our to-expunge list get temporarily
- * marked un-deleted.
- */
-
- CAMEL_SERVICE_LOCK (store, connect_lock);
-
- ((CamelFolderClass *)CAMEL_OBJECT_GET_CLASS(folder))->sync(folder, 0, ex);
- if (camel_exception_is_set(ex)) {
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
- return;
- }
-
- response = camel_imap_command (store, folder, ex, "UID SEARCH DELETED");
- if (!response) {
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
- return;
- }
- result = camel_imap_response_extract (store, response, "SEARCH", ex);
- if (!result) {
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
- return;
- }
-
- if (result[8] == ' ') {
- char *uid, *lasts = NULL;
- unsigned long euid, kuid;
- int ei, ki;
-
- keep_uids = g_ptr_array_new ();
- mark_uids = g_ptr_array_new ();
-
- /* Parse SEARCH response */
- for (uid = strtok_r (result + 9, " ", &lasts); uid; uid = strtok_r (NULL, " ", &lasts))
- g_ptr_array_add (keep_uids, uid);
- qsort (keep_uids->pdata, keep_uids->len,
- sizeof (void *), uid_compar);
-
- /* Fill in "mark_uids", empty out "keep_uids" as needed */
- for (ei = ki = 0; ei < uids->len; ei++) {
- euid = strtoul (uids->pdata[ei], NULL, 10);
-
- for (kuid = 0; ki < keep_uids->len; ki++) {
- kuid = strtoul (keep_uids->pdata[ki], NULL, 10);
-
- if (kuid >= euid)
- break;
- }
-
- if (euid == kuid)
- g_ptr_array_remove_index (keep_uids, ki);
- else
- g_ptr_array_add (mark_uids, uids->pdata[ei]);
- }
- } else {
- /* Empty SEARCH result, meaning nothing is marked deleted
- * on server.
- */
-
- keep_uids = NULL;
- mark_uids = uids;
- }
-
- /* Unmark messages to be kept */
-
- if (keep_uids) {
- char *uidset;
- int uid = 0;
-
- while (uid < keep_uids->len) {
- uidset = imap_uid_array_to_set (folder->summary, keep_uids, uid, UID_SET_LIMIT, &uid);
-
- response = camel_imap_command (store, folder, ex,
- "UID STORE %s -FLAGS.SILENT \\Deleted",
- uidset);
-
- g_free (uidset);
-
- if (!response) {
- g_ptr_array_free (keep_uids, TRUE);
- g_ptr_array_free (mark_uids, TRUE);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
- return;
- }
- camel_imap_response_free (store, response);
- }
- }
-
- /* Mark any messages that still need to be marked */
- if (mark_uids) {
- char *uidset;
- int uid = 0;
-
- while (uid < mark_uids->len) {
- uidset = imap_uid_array_to_set (folder->summary, mark_uids, uid, UID_SET_LIMIT, &uid);
-
- response = camel_imap_command (store, folder, ex,
- "UID STORE %s +FLAGS.SILENT \\Deleted",
- uidset);
-
- g_free (uidset);
-
- if (!response) {
- g_ptr_array_free (keep_uids, TRUE);
- g_ptr_array_free (mark_uids, TRUE);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
- return;
- }
- camel_imap_response_free (store, response);
- }
-
- if (mark_uids != uids)
- g_ptr_array_free (mark_uids, TRUE);
- }
-
- /* Do the actual expunging */
- response = camel_imap_command (store, folder, ex, "EXPUNGE");
- if (response)
- camel_imap_response_free (store, response);
-
- /* And fix the remaining messages if we mangled them */
- if (keep_uids) {
- char *uidset;
- int uid = 0;
-
- while (uid < keep_uids->len) {
- uidset = imap_uid_array_to_set (folder->summary, keep_uids, uid, UID_SET_LIMIT, &uid);
-
- /* Don't pass ex if it's already been set */
- response = camel_imap_command (store, folder,
- camel_exception_is_set (ex) ? NULL : ex,
- "UID STORE %s +FLAGS.SILENT \\Deleted",
- uidset);
-
- g_free (uidset);
- if (response)
- camel_imap_response_free (store, response);
- }
-
- g_ptr_array_free (keep_uids, TRUE);
- }
-
- /* now we can free this, now that we're done with keep_uids */
- g_free (result);
-
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
-}
-
-static gchar *
-get_temp_uid (void)
-{
- gchar *res;
-
- static int counter = 0;
- G_LOCK_DEFINE_STATIC (lock);
-
- G_LOCK (lock);
- res = g_strdup_printf ("tempuid-%lx-%d",
- (unsigned long) time (NULL),
- counter++);
- G_UNLOCK (lock);
-
- return res;
-}
-
-static void
-imap_append_offline (CamelFolder *folder, CamelMimeMessage *message,
- const CamelMessageInfo *info, char **appended_uid,
- CamelException *ex)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (folder->parent_store);
- CamelImapMessageCache *cache = CAMEL_IMAP_FOLDER (folder)->cache;
- CamelFolderChangeInfo *changes;
- char *uid;
-
- uid = get_temp_uid ();
-
- camel_imap_summary_add_offline (folder->summary, uid, message, info);
- CAMEL_IMAP_FOLDER_LOCK (folder, cache_lock);
- camel_imap_message_cache_insert_wrapper (cache, uid, "",
- CAMEL_DATA_WRAPPER (message), ex);
- CAMEL_IMAP_FOLDER_UNLOCK (folder, cache_lock);
-
- changes = camel_folder_change_info_new ();
- camel_folder_change_info_add_uid (changes, uid);
- camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed",
- changes);
- camel_folder_change_info_free (changes);
-
- camel_disco_diary_log (CAMEL_DISCO_STORE (imap_store)->diary,
- CAMEL_DISCO_DIARY_FOLDER_APPEND, folder, uid);
- if (appended_uid)
- *appended_uid = uid;
- else
- g_free (uid);
-}
-
-static CamelImapResponse *
-do_append (CamelFolder *folder, CamelMimeMessage *message,
- const CamelMessageInfo *info, char **uid,
- CamelException *ex)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
- CamelImapResponse *response;
- CamelStream *memstream;
- CamelMimeFilter *crlf_filter;
- CamelStreamFilter *streamfilter;
- GByteArray *ba;
- char *flagstr, *result, *end;
-
- /* create flag string param */
- if (info && info->flags)
- flagstr = imap_create_flag_list (info->flags);
- else
- flagstr = NULL;
-
- /* encode any 8bit parts so we avoid sending embedded nul-chars and such */
- camel_mime_message_encode_8bit_parts (message);
-
- /* FIXME: We could avoid this if we knew how big the message was. */
- memstream = camel_stream_mem_new ();
- ba = g_byte_array_new ();
- camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (memstream), ba);
-
- streamfilter = camel_stream_filter_new_with_stream (memstream);
- crlf_filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE,
- CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
- camel_stream_filter_add (streamfilter, crlf_filter);
- camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message),
- CAMEL_STREAM (streamfilter));
- camel_object_unref (CAMEL_OBJECT (streamfilter));
- camel_object_unref (CAMEL_OBJECT (crlf_filter));
- camel_object_unref (CAMEL_OBJECT (memstream));
-
- response = camel_imap_command (store, NULL, ex, "APPEND %F%s%s {%d}",
- folder->full_name, flagstr ? " " : "",
- flagstr ? flagstr : "", ba->len);
- g_free (flagstr);
-
- if (!response) {
- g_byte_array_free (ba, TRUE);
- return NULL;
- }
-
- result = camel_imap_response_extract_continuation (store, response, ex);
- if (!result) {
- g_byte_array_free (ba, TRUE);
- return NULL;
- }
- g_free (result);
-
- /* send the rest of our data - the mime message */
- response = camel_imap_command_continuation (store, ba->data, ba->len, ex);
- g_byte_array_free (ba, TRUE);
- if (!response)
- return response;
-
- if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) {
- *uid = strstrcase (response->status, "[APPENDUID ");
- if (*uid)
- *uid = strchr (*uid + 11, ' ');
- if (*uid) {
- *uid = g_strndup (*uid + 1, strcspn (*uid + 1, "]"));
- /* Make sure it's a number */
- if (strtoul (*uid, &end, 10) == 0 || *end) {
- g_free (*uid);
- *uid = NULL;
- }
- }
- } else
- *uid = NULL;
-
- return response;
-}
-
-static void
-imap_append_online (CamelFolder *folder, CamelMimeMessage *message,
- const CamelMessageInfo *info, char **appended_uid,
- CamelException *ex)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
- CamelImapResponse *response;
- char *uid;
- int count;
-
- count = camel_folder_summary_count (folder->summary);
- response = do_append (folder, message, info, &uid, ex);
- if (!response)
- return;
-
- if (uid) {
- /* Cache first, since freeing response may trigger a
- * summary update that will want this information.
- */
- CAMEL_IMAP_FOLDER_LOCK (folder, cache_lock);
- camel_imap_message_cache_insert_wrapper (
- CAMEL_IMAP_FOLDER (folder)->cache, uid,
- "", CAMEL_DATA_WRAPPER (message), ex);
- CAMEL_IMAP_FOLDER_UNLOCK (folder, cache_lock);
- if (appended_uid)
- *appended_uid = uid;
- else
- g_free (uid);
- } else if (appended_uid)
- *appended_uid = NULL;
-
- camel_imap_response_free (store, response);
-
- /* Make sure a "folder_changed" is emitted. */
- CAMEL_SERVICE_LOCK (store, connect_lock);
- if (store->current_folder != folder ||
- camel_folder_summary_count (folder->summary) == count)
- imap_refresh_info (folder, ex);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
-}
-
-static void
-imap_append_resyncing (CamelFolder *folder, CamelMimeMessage *message,
- const CamelMessageInfo *info, char **appended_uid,
- CamelException *ex)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
- CamelImapResponse *response;
- char *uid;
-
- response = do_append (folder, message, info, &uid, ex);
- if (!response)
- return;
-
- if (uid) {
- CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
- const char *olduid = camel_message_info_uid (info);
-
- CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock);
- camel_imap_message_cache_copy (imap_folder->cache, olduid,
- imap_folder->cache, uid, ex);
- CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
-
- if (appended_uid)
- *appended_uid = uid;
- else
- g_free (uid);
- } else if (appended_uid)
- *appended_uid = NULL;
-
- camel_imap_response_free (store, response);
-}
-
-
-static void
-imap_transfer_offline (CamelFolder *source, GPtrArray *uids,
- CamelFolder *dest, GPtrArray **transferred_uids,
- gboolean delete_originals, CamelException *ex)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store);
- CamelImapMessageCache *sc = CAMEL_IMAP_FOLDER (source)->cache;
- CamelImapMessageCache *dc = CAMEL_IMAP_FOLDER (dest)->cache;
- CamelFolderChangeInfo *changes;
- CamelMimeMessage *message;
- CamelMessageInfo *mi;
- char *uid, *destuid;
- int i;
-
- /* We grab the store's command lock first, and then grab the
- * source and destination cache_locks. This way we can't
- * deadlock in the case where we're simultaneously also trying
- * to copy messages in the other direction from another thread.
- */
- CAMEL_SERVICE_LOCK (store, connect_lock);
- CAMEL_IMAP_FOLDER_LOCK (source, cache_lock);
- CAMEL_IMAP_FOLDER_LOCK (dest, cache_lock);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
-
- if (transferred_uids) {
- *transferred_uids = g_ptr_array_new ();
- g_ptr_array_set_size (*transferred_uids, uids->len);
- }
-
- changes = camel_folder_change_info_new ();
-
- for (i = 0; i < uids->len; i++) {
- uid = uids->pdata[i];
-
- destuid = get_temp_uid ();
-
- mi = camel_folder_summary_uid (source->summary, uid);
- g_return_if_fail (mi != NULL);
-
- message = camel_folder_get_message (source, uid, NULL);
-
- if (message) {
- camel_imap_summary_add_offline (dest->summary, destuid, message, mi);
- camel_object_unref (CAMEL_OBJECT (message));
- } else
- camel_imap_summary_add_offline_uncached (dest->summary, destuid, mi);
-
- camel_imap_message_cache_copy (sc, uid, dc, destuid, ex);
- camel_folder_summary_info_free (source->summary, mi);
-
- camel_folder_change_info_add_uid (changes, destuid);
- if (transferred_uids)
- (*transferred_uids)->pdata[i] = destuid;
- else
- g_free (destuid);
-
- if (delete_originals)
- camel_folder_delete_message (source, uid);
- }
-
- CAMEL_IMAP_FOLDER_UNLOCK (dest, cache_lock);
- CAMEL_IMAP_FOLDER_UNLOCK (source, cache_lock);
-
- camel_object_trigger_event (CAMEL_OBJECT (dest), "folder_changed", changes);
- camel_folder_change_info_free (changes);
-
- camel_disco_diary_log (CAMEL_DISCO_STORE (store)->diary,
- CAMEL_DISCO_DIARY_FOLDER_TRANSFER,
- source, dest, uids, delete_originals);
-}
-
-static void
-handle_copyuid (CamelImapResponse *response, CamelFolder *source,
- CamelFolder *destination)
-{
- CamelImapMessageCache *scache = CAMEL_IMAP_FOLDER (source)->cache;
- CamelImapMessageCache *dcache = CAMEL_IMAP_FOLDER (destination)->cache;
- char *validity, *srcset, *destset;
- GPtrArray *src, *dest;
- int i;
-
- validity = strstrcase (response->status, "[COPYUID ");
- if (!validity)
- return;
- validity += 9;
- if (strtoul (validity, NULL, 10) !=
- CAMEL_IMAP_SUMMARY (destination->summary)->validity)
- return;
-
- srcset = strchr (validity, ' ');
- if (!srcset++)
- goto lose;
- destset = strchr (srcset, ' ');
- if (!destset++)
- goto lose;
-
- src = imap_uid_set_to_array (source->summary, srcset);
- dest = imap_uid_set_to_array (destination->summary, destset);
-
- if (src && dest && src->len == dest->len) {
- /* We don't have to worry about deadlocking on the
- * cache locks here, because we've got the store's
- * command lock too, so no one else could be here.
- */
- CAMEL_IMAP_FOLDER_LOCK (source, cache_lock);
- CAMEL_IMAP_FOLDER_LOCK (destination, cache_lock);
- for (i = 0; i < src->len; i++) {
- camel_imap_message_cache_copy (scache, src->pdata[i],
- dcache, dest->pdata[i],
- NULL);
- }
- CAMEL_IMAP_FOLDER_UNLOCK (source, cache_lock);
- CAMEL_IMAP_FOLDER_UNLOCK (destination, cache_lock);
-
- imap_uid_array_free (src);
- imap_uid_array_free (dest);
- return;
- }
-
- imap_uid_array_free (src);
- imap_uid_array_free (dest);
- lose:
- g_warning ("Bad COPYUID response from server");
-}
-
-static void
-do_copy (CamelFolder *source, GPtrArray *uids,
- CamelFolder *destination, CamelException *ex)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store);
- CamelImapResponse *response;
- char *uidset;
- int uid = 0;
-
- while (uid < uids->len && !camel_exception_is_set (ex)) {
- uidset = imap_uid_array_to_set (source->summary, uids, uid, UID_SET_LIMIT, &uid);
-
- response = camel_imap_command (store, source, ex, "UID COPY %s %F",
- uidset, destination->full_name);
-
- g_free (uidset);
-
- if (response && (store->capabilities & IMAP_CAPABILITY_UIDPLUS))
- handle_copyuid (response, source, destination);
-
- camel_imap_response_free (store, response);
- }
-}
-
-static void
-imap_transfer_online (CamelFolder *source, GPtrArray *uids,
- CamelFolder *dest, GPtrArray **transferred_uids,
- gboolean delete_originals, CamelException *ex)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store);
- int count, i;
-
- /* Sync message flags if needed. */
- imap_sync_online (source, ex);
- if (camel_exception_is_set (ex))
- return;
-
- count = camel_folder_summary_count (dest->summary);
-
- /* Now copy the messages */
- do_copy (source, uids, dest, ex);
- if (camel_exception_is_set (ex))
- return;
-
- /* Make the destination notice its new messages */
- CAMEL_SERVICE_LOCK (store, connect_lock);
- if (store->current_folder != dest ||
- camel_folder_summary_count (dest->summary) == count)
- camel_folder_refresh_info (dest, ex);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
-
- if (delete_originals) {
- for (i = 0; i < uids->len; i++)
- camel_folder_delete_message (source, uids->pdata[i]);
- }
-
- /* FIXME */
- if (transferred_uids)
- *transferred_uids = NULL;
-}
-
-static void
-imap_transfer_resyncing (CamelFolder *source, GPtrArray *uids,
- CamelFolder *dest, GPtrArray **transferred_uids,
- gboolean delete_originals, CamelException *ex)
-{
- CamelDiscoDiary *diary = CAMEL_DISCO_STORE (source->parent_store)->diary;
- GPtrArray *realuids;
- int first, i;
- const char *uid;
- CamelMimeMessage *message;
- CamelMessageInfo *info;
-
- /* This is trickier than append_resyncing, because some of
- * the messages we are copying may have been copied or
- * appended into @source while we were offline, in which case
- * if we don't have UIDPLUS, we won't know their real UIDs,
- * so we'll have to append them rather than copying.
- */
-
- realuids = g_ptr_array_new ();
-
- i = 0;
- while (i < uids->len) {
- /* Skip past real UIDs */
- for (first = i; i < uids->len; i++) {
- uid = uids->pdata[i];
-
- if (!isdigit ((unsigned char)*uid)) {
- uid = camel_disco_diary_uidmap_lookup (diary, uid);
- if (!uid)
- break;
- }
- g_ptr_array_add (realuids, (char *)uid);
-
- if (delete_originals)
- camel_folder_delete_message (source, uid);
- }
-
- /* If we saw any real UIDs, do a COPY */
- if (i != first) {
- do_copy (source, realuids, dest, ex);
- g_ptr_array_set_size (realuids, 0);
- if (i == uids->len || camel_exception_is_set (ex))
- break;
- }
-
- /* Deal with fake UIDs */
- while (i < uids->len &&
- !isdigit (*(unsigned char *)(uids->pdata[i])) &&
- !camel_exception_is_set (ex)) {
- uid = uids->pdata[i];
- message = camel_folder_get_message (source, uid, NULL);
- if (!message) {
- /* Message must have been expunged */
- continue;
- }
- info = camel_folder_get_message_info (source, uid);
- g_return_if_fail (info != NULL);
-
- imap_append_online (dest, message, info, NULL, ex);
- camel_folder_free_message_info (source, info);
- camel_object_unref (CAMEL_OBJECT (message));
- if (delete_originals)
- camel_folder_delete_message (source, uid);
- i++;
- }
- }
-
- g_ptr_array_free (realuids, FALSE);
-
- /* FIXME */
- if (transferred_uids)
- *transferred_uids = NULL;
-}
-
-static GPtrArray *
-imap_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex)
-{
- CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
- GPtrArray *matches, *summary;
-
- /* we could get around this by creating a new search object each time,
- but i doubt its worth it since any long operation would lock the
- command channel too */
- CAMEL_IMAP_FOLDER_LOCK(folder, search_lock);
-
- camel_folder_search_set_folder (imap_folder->search, folder);
- summary = camel_folder_get_summary(folder);
- camel_folder_search_set_summary(imap_folder->search, summary);
- matches = camel_folder_search_execute_expression (imap_folder->search, expression, ex);
-
- CAMEL_IMAP_FOLDER_UNLOCK(folder, search_lock);
-
- camel_folder_free_summary(folder, summary);
-
- return matches;
-}
-
-static GPtrArray *
-imap_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex)
-{
- CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER(folder);
- GPtrArray *summary, *matches;
- int i;
-
- /* NOTE: could get away without the search lock by creating a new
- search object each time */
-
- summary = g_ptr_array_new();
- for (i=0;i<uids->len;i++) {
- CamelMessageInfo *info;
-
- info = camel_folder_get_message_info(folder, uids->pdata[i]);
- if (info)
- g_ptr_array_add(summary, info);
- }
-
- if (summary->len == 0)
- return summary;
-
- CAMEL_IMAP_FOLDER_LOCK(folder, search_lock);
-
- camel_folder_search_set_folder(imap_folder->search, folder);
- camel_folder_search_set_summary(imap_folder->search, summary);
-
- matches = camel_folder_search_execute_expression(imap_folder->search, expression, ex);
-
- CAMEL_IMAP_FOLDER_UNLOCK(folder, search_lock);
-
- for (i=0;i<summary->len;i++)
- camel_folder_free_message_info(folder, summary->pdata[i]);
- g_ptr_array_free(summary, TRUE);
-
- return matches;
-}
-
-static void
-imap_search_free (CamelFolder *folder, GPtrArray *uids)
-{
- CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
-
- g_return_if_fail (imap_folder->search);
-
- CAMEL_IMAP_FOLDER_LOCK(folder, search_lock);
-
- camel_folder_search_free_result (imap_folder->search, uids);
-
- CAMEL_IMAP_FOLDER_UNLOCK(folder, search_lock);
-}
-
-static CamelMimeMessage *get_message (CamelImapFolder *imap_folder,
- const char *uid,
- const char *part_specifier,
- CamelMessageContentInfo *ci,
- CamelException *ex);
-
-struct _part_spec_stack {
- struct _part_spec_stack *parent;
- int part;
-};
-
-static void
-part_spec_push (struct _part_spec_stack **stack, int part)
-{
- struct _part_spec_stack *node;
-
- node = g_new (struct _part_spec_stack, 1);
- node->parent = *stack;
- node->part = part;
-
- *stack = node;
-}
-
-static int
-part_spec_pop (struct _part_spec_stack **stack)
-{
- struct _part_spec_stack *node;
- int part;
-
- g_return_val_if_fail (*stack != NULL, 0);
-
- node = *stack;
- *stack = node->parent;
-
- part = node->part;
- g_free (node);
-
- return part;
-}
-
-static char *
-content_info_get_part_spec (CamelMessageContentInfo *ci)
-{
- struct _part_spec_stack *stack = NULL;
- CamelMessageContentInfo *node;
- char *part_spec, *buf;
- size_t len = 1;
- int part;
-
- node = ci;
- while (node->parent) {
- CamelMessageContentInfo *child;
-
- /* FIXME: is this only supposed to apply if 'node' is a multipart? */
- if (node->parent->parent && header_content_type_is (node->parent->type, "message", "*")) {
- node = node->parent;
- continue;
- }
-
- child = node->parent->childs;
- for (part = 1; child; part++) {
- if (child == node)
- break;
-
- child = child->next;
- }
-
- part_spec_push (&stack, part);
-
- len += 2;
- while ((part = part / 10))
- len++;
-
- node = node->parent;
- }
-
- buf = part_spec = g_malloc (len);
- part_spec[0] = '\0';
-
- while (stack) {
- part = part_spec_pop (&stack);
- buf += sprintf (buf, "%d%s", part, stack ? "." : "");
- }
-
- return part_spec;
-}
-
-/* Fetch the contents of the MIME part indicated by @ci, which is part
- * of message @uid in @folder.
- */
-static CamelDataWrapper *
-get_content (CamelImapFolder *imap_folder, const char *uid,
- CamelMimePart *part, CamelMessageContentInfo *ci,
- CamelException *ex)
-{
- CamelDataWrapper *content = NULL;
- CamelStream *stream;
- char *part_spec;
-
- part_spec = content_info_get_part_spec (ci);
-
- /* There are three cases: multipart/signed, multipart, message/rfc822, and "other" */
- if (header_content_type_is (ci->type, "multipart", "signed")) {
- CamelMultipartSigned *body_mp;
- char *spec;
- int ret;
-
- /* Note: because we get the content parts uninterpreted anyway, we could potentially
- just use the normalmultipart code, except that multipart/signed wont let you yet! */
-
- body_mp = camel_multipart_signed_new ();
- /* need to set this so it grabs the boundary and other info about the signed type */
- /* we assume that part->content_type is more accurate/full than ci->type */
- camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (body_mp), part->content_type);
-
- spec = alloca (strlen (part_spec) + 6);
- sprintf (spec, part_spec[0] ? "%s.TEXT" : "TEXT", part_spec);
- g_free (part_spec);
-
- stream = camel_imap_folder_fetch_data (imap_folder, uid, spec, FALSE, ex);
- if (stream) {
- ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (body_mp), stream);
- camel_object_unref (CAMEL_OBJECT (stream));
- if (ret == -1) {
- camel_object_unref ((CamelObject *) body_mp);
- return NULL;
- }
- }
-
- return (CamelDataWrapper *) body_mp;
- } else if (header_content_type_is (ci->type, "multipart", "*")) {
- CamelMultipart *body_mp;
- char *child_spec;
- int speclen, num;
-
- if (header_content_type_is (ci->type, "multipart", "encrypted"))
- body_mp = (CamelMultipart *) camel_multipart_encrypted_new ();
- else
- body_mp = camel_multipart_new ();
-
- /* need to set this so it grabs the boundary and other info about the multipart */
- /* we assume that part->content_type is more accurate/full than ci->type */
- camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (body_mp), part->content_type);
-
- speclen = strlen (part_spec);
- child_spec = g_malloc (speclen + 17); /* dot + 10 + dot + MIME + nul */
- memcpy (child_spec, part_spec, speclen);
- if (speclen > 0)
- child_spec[speclen++] = '.';
- g_free (part_spec);
-
- ci = ci->childs;
- num = 1;
- while (ci) {
- sprintf (child_spec + speclen, "%d.MIME", num++);
- stream = camel_imap_folder_fetch_data (imap_folder, uid, child_spec, FALSE, ex);
- if (stream) {
- int ret;
-
- part = camel_mime_part_new ();
- ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (part), stream);
- camel_object_unref (CAMEL_OBJECT (stream));
- if (ret == -1) {
- camel_object_unref (CAMEL_OBJECT (part));
- camel_object_unref (CAMEL_OBJECT (body_mp));
- g_free (child_spec);
- return NULL;
- }
-
- content = get_content (imap_folder, uid, part, ci, ex);
- }
-
- if (!stream || !content) {
- camel_object_unref (CAMEL_OBJECT (body_mp));
- g_free (child_spec);
- return NULL;
- }
-
- camel_medium_set_content_object (CAMEL_MEDIUM (part), content);
- camel_object_unref (CAMEL_OBJECT (content));
- camel_multipart_add_part (body_mp, part);
- camel_object_unref (CAMEL_OBJECT (part));
-
- ci = ci->next;
- }
-
- g_free (child_spec);
-
- return (CamelDataWrapper *) body_mp;
- } else if (header_content_type_is (ci->type, "message", "rfc822")) {
- content = (CamelDataWrapper *) get_message (imap_folder, uid, part_spec, ci->childs, ex);
- g_free (part_spec);
- return content;
- } else {
- content = camel_imap_wrapper_new (imap_folder, ci->type, uid, *part_spec ? part_spec : "1", part);
- g_free (part_spec);
- return content;
- }
-}
-
-static CamelMimeMessage *
-get_message (CamelImapFolder *imap_folder, const char *uid,
- const char *part_spec, CamelMessageContentInfo *ci,
- CamelException *ex)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (CAMEL_FOLDER (imap_folder)->parent_store);
- CamelDataWrapper *content;
- CamelMimeMessage *msg;
- CamelStream *stream;
- char *section_text;
- int ret;
-
- section_text = g_strdup_printf ("%s%s%s", part_spec, *part_spec ? "." : "",
- store->server_level >= IMAP_LEVEL_IMAP4REV1 ? "HEADER" : "0");
- stream = camel_imap_folder_fetch_data (imap_folder, uid, section_text, FALSE, ex);
- g_free (section_text);
- if (!stream)
- return NULL;
-
- msg = camel_mime_message_new ();
- ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), stream);
- camel_object_unref (CAMEL_OBJECT (stream));
- if (ret == -1) {
- camel_object_unref (CAMEL_OBJECT (msg));
- return NULL;
- }
-
- content = get_content (imap_folder, uid, CAMEL_MIME_PART (msg), ci, ex);
- if (!content) {
- camel_object_unref (CAMEL_OBJECT (msg));
- return NULL;
- }
-
- camel_medium_set_content_object (CAMEL_MEDIUM (msg), content);
- camel_object_unref (CAMEL_OBJECT (content));
-
- return msg;
-}
-
-/* FIXME: I pulled this number out of my butt. */
-#define IMAP_SMALL_BODY_SIZE 5120
-
-static CamelMimeMessage *
-get_message_simple (CamelImapFolder *imap_folder, const char *uid,
- CamelStream *stream, CamelException *ex)
-{
- CamelMimeMessage *msg;
- CamelImapStore *imap_store =
- CAMEL_IMAP_STORE (CAMEL_FOLDER (imap_folder)->parent_store);
- int ret;
-
- if (!stream) {
- stream = camel_imap_folder_fetch_data (imap_folder, uid, "",
- FALSE, ex);
- if (!stream)
- return NULL;
- }
-
- msg = camel_mime_message_new ();
- ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg),
- stream);
- camel_object_unref (CAMEL_OBJECT (stream));
- if (ret == -1) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("Unable to retrieve message: %s"), strerror(errno));
- camel_object_unref (CAMEL_OBJECT (msg));
- return NULL;
- }
-
- /* FIXME, this shouldn't be done this way. */
- camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Source",
- imap_store->base_url);
- return msg;
-}
-
-static CamelMimeMessage *
-imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex)
-{
- CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
- CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
- CamelMessageInfo *mi;
- CamelMimeMessage *msg;
- CamelStream *stream = NULL;
-
- /* If the server doesn't support IMAP4rev1, or we already have
- * the whole thing cached, fetch it in one piece.
- */
- if (store->server_level < IMAP_LEVEL_IMAP4REV1 ||
- (stream = camel_imap_folder_fetch_data (imap_folder, uid, "", TRUE, NULL)))
- return get_message_simple (imap_folder, uid, stream, ex);
-
- /* If we're not actually connected and it's not in the cache,
- * that's as far as we can go.
- */
- if (camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex) == FALSE)
- return NULL;
-
- mi = camel_folder_summary_uid (folder->summary, uid);
- if (mi == NULL) {
- camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID,
- _("Cannot get message: %s\n %s"), uid, _("No such message"));
- return NULL;
- }
-
- /* If the message is small, fetch it in one piece. */
- if (mi->size < IMAP_SMALL_BODY_SIZE) {
- camel_folder_summary_info_free (folder->summary, mi);
- return get_message_simple (imap_folder, uid, NULL, ex);
- }
-
- /* For larger messages, fetch the structure and build a message
- * with offline parts. (We check mi->content->type rather than
- * mi->content because camel_folder_summary_info_new always creates
- * an empty content struct.)
- */
- if (!mi->content->type) {
- CamelImapResponse *response;
- GData *fetch_data = NULL;
- char *body, *found_uid;
- int i;
-
- if (camel_disco_store_status (CAMEL_DISCO_STORE (store)) == CAMEL_DISCO_STORE_OFFLINE) {
- camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("This message is not currently available"));
- return NULL;
- }
-
- response = camel_imap_command (store, folder, ex,
- "UID FETCH %s BODY", uid);
- if (!response) {
- camel_folder_summary_info_free (folder->summary, mi);
- return NULL;
- }
-
- for (i = 0, body = NULL; i < response->untagged->len; i++) {
- fetch_data = parse_fetch_response (imap_folder, response->untagged->pdata[i]);
- if (fetch_data) {
- found_uid = g_datalist_get_data (&fetch_data, "UID");
- body = g_datalist_get_data (&fetch_data, "BODY");
- if (found_uid && body && !strcmp (found_uid, uid))
- break;
- g_datalist_clear (&fetch_data);
- fetch_data = NULL;
- body = NULL;
- }
- }
-
- if (body)
- imap_parse_body ((const char **) &body, folder, mi->content);
-
- if (fetch_data)
- g_datalist_clear (&fetch_data);
-
- camel_imap_response_free (store, response);
-
- d(camel_content_info_dump (mi->content, 0));
-
- if (!mi->content->type) {
- /* FETCH returned OK, but we didn't parse a BODY
- * response. Courier will return invalid BODY
- * responses for invalidly MIMEd messages, so
- * fall back to fetching the entire thing and
- * let the mailer's "bad MIME" code handle it.
- */
- camel_folder_summary_info_free (folder->summary, mi);
- return get_message_simple (imap_folder, uid, NULL, ex);
- }
- }
-
- msg = get_message (imap_folder, uid, "", mi->content, ex);
- /* FIXME, this shouldn't be done this way. */
- camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Source",
- store->base_url);
- camel_folder_summary_info_free (folder->summary, mi);
-
- return msg;
-}
-
-static void
-imap_cache_message (CamelDiscoFolder *disco_folder, const char *uid,
- CamelException *ex)
-{
- CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (disco_folder);
- CamelStream *stream;
-
- stream = camel_imap_folder_fetch_data (imap_folder, uid, "", FALSE, ex);
- if (stream)
- camel_object_unref (CAMEL_OBJECT (stream));
-}
-
-/* We pretend that a FLAGS or RFC822.SIZE response is always exactly
- * 20 bytes long, and a BODY[HEADERS] response is always 2000 bytes
- * long. Since we know how many of each kind of response we're
- * expecting, we can find the total (pretend) amount of server traffic
- * to expect and then count off the responses as we read them to update
- * the progress bar.
- */
-#define IMAP_PRETEND_SIZEOF_FLAGS 20
-#define IMAP_PRETEND_SIZEOF_SIZE 20
-#define IMAP_PRETEND_SIZEOF_HEADERS 2000
-
-static void
-add_message_from_data (CamelFolder *folder, GPtrArray *messages,
- int first, GData *data)
-{
- CamelMimeMessage *msg;
- CamelStream *stream;
- CamelMessageInfo *mi;
- int seq;
-
- seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE"));
- if (seq < first)
- return;
- stream = g_datalist_get_data (&data, "BODY_PART_STREAM");
- if (!stream)
- return;
-
- if (seq - first >= messages->len)
- g_ptr_array_set_size (messages, seq - first + 1);
-
- msg = camel_mime_message_new ();
- if (camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), stream) == -1) {
- camel_object_unref (CAMEL_OBJECT (msg));
- return;
- }
-
- mi = camel_folder_summary_info_new_from_message (folder->summary, msg);
- camel_object_unref (CAMEL_OBJECT (msg));
-
- messages->pdata[seq - first] = mi;
-}
-
-static void
-imap_update_summary (CamelFolder *folder, int exists,
- CamelFolderChangeInfo *changes,
- CamelException *ex)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
- CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
- GPtrArray *fetch_data = NULL, *messages = NULL, *needheaders;
- guint32 flags, uidval, maxuid;
- int i, seq, first, size, got;
- CamelImapResponseType type;
- const char *header_spec;
- CamelMessageInfo *mi, *info;
- CamelStream *stream;
- char *uid, *resp;
- GData *data;
-
- CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock);
- if (store->server_level >= IMAP_LEVEL_IMAP4REV1)
- header_spec = "HEADER";
- else
- header_spec = "0";
-
- /* Figure out if any of the new messages are already cached (which
- * may be the case if we're re-syncing after disconnected operation).
- * If so, get their UIDs, FLAGS, and SIZEs. If not, get all that
- * and ask for the headers too at the same time.
- */
- seq = camel_folder_summary_count (folder->summary);
- first = seq + 1;
- if (seq > 0) {
- mi = camel_folder_summary_index (folder->summary, seq - 1);
- uidval = atoi (camel_message_info_uid (mi));
- camel_folder_summary_info_free (folder->summary, mi);
- } else
- uidval = 0;
-
- size = (exists - seq) * (IMAP_PRETEND_SIZEOF_FLAGS + IMAP_PRETEND_SIZEOF_SIZE);
- got = 0;
-
- maxuid = camel_imap_message_cache_max_uid (imap_folder->cache);
- if (uidval >= maxuid) {
- /* None of the new messages are cached */
- size += (exists - seq) * IMAP_PRETEND_SIZEOF_HEADERS;
- if (!camel_imap_command_start (store, folder, ex,
- "UID FETCH %d:* (FLAGS RFC822.SIZE BODY.PEEK[%s])",
- maxuid + 1, header_spec))
- return;
- camel_operation_start (NULL, _("Fetching summary information for new messages"));
- } else {
- if (!camel_imap_command_start (store, folder, ex,
- "UID FETCH %d:* (FLAGS RFC822.SIZE)",
- uidval + 1))
- return;
- camel_operation_start (NULL, _("Scanning for new messages"));
- }
-
- /* Parse the responses. We can't add a message to the summary
- * until we've gotten its headers, and there's no guarantee
- * the server will send the responses in a useful order...
- */
- fetch_data = g_ptr_array_new ();
- messages = g_ptr_array_new ();
- while ((type = camel_imap_command_response (store, &resp, ex)) ==
- CAMEL_IMAP_RESPONSE_UNTAGGED) {
- data = parse_fetch_response (imap_folder, resp);
- g_free (resp);
- if (!data)
- continue;
-
- seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE"));
- if (seq < first) {
- g_datalist_clear (&data);
- continue;
- }
-
- if (g_datalist_get_data (&data, "FLAGS"))
- got += IMAP_PRETEND_SIZEOF_FLAGS;
- if (g_datalist_get_data (&data, "RFC822.SIZE"))
- got += IMAP_PRETEND_SIZEOF_SIZE;
- stream = g_datalist_get_data (&data, "BODY_PART_STREAM");
- if (stream) {
- got += IMAP_PRETEND_SIZEOF_HEADERS;
-
- /* Use the stream now so we don't tie up many
- * many fds if we're fetching many many messages.
- */
- add_message_from_data (folder, messages, first, data);
- g_datalist_set_data (&data, "BODY_PART_STREAM", NULL);
- }
-
- camel_operation_progress (NULL, got * 100 / size);
- g_ptr_array_add (fetch_data, data);
- }
- camel_operation_end (NULL);
-
- if (type == CAMEL_IMAP_RESPONSE_ERROR)
- goto lose;
-
- /* Free the final tagged response */
- g_free (resp);
-
- /* Figure out which headers we still need to fetch. */
- needheaders = g_ptr_array_new ();
- size = got = 0;
- for (i = 0; i < fetch_data->len; i++) {
- data = fetch_data->pdata[i];
- if (g_datalist_get_data (&data, "BODY_PART_LEN"))
- continue;
-
- uid = g_datalist_get_data (&data, "UID");
- if (uid) {
- g_ptr_array_add (needheaders, uid);
- size += IMAP_PRETEND_SIZEOF_HEADERS;
- }
- }
-
- /* And fetch them */
- if (needheaders->len) {
- char *uidset;
- int uid = 0;
-
- qsort (needheaders->pdata, needheaders->len,
- sizeof (void *), uid_compar);
-
- camel_operation_start (NULL, _("Fetching summary information for new messages"));
-
- while (uid < needheaders->len) {
- uidset = imap_uid_array_to_set (folder->summary, needheaders, uid, UID_SET_LIMIT, &uid);
- if (!camel_imap_command_start (store, folder, ex,
- "UID FETCH %s BODY.PEEK[%s]",
- uidset, header_spec)) {
- g_ptr_array_free (needheaders, TRUE);
- camel_operation_end (NULL);
- g_free (uidset);
- goto lose;
- }
- g_free (uidset);
-
- while ((type = camel_imap_command_response (store, &resp, ex))
- == CAMEL_IMAP_RESPONSE_UNTAGGED) {
- data = parse_fetch_response (imap_folder, resp);
- g_free (resp);
- if (!data)
- continue;
-
- stream = g_datalist_get_data (&data, "BODY_PART_STREAM");
- if (stream) {
- add_message_from_data (folder, messages, first, data);
- got += IMAP_PRETEND_SIZEOF_HEADERS;
- camel_operation_progress (NULL, got * 100 / size);
- }
- g_datalist_clear (&data);
- }
-
- if (type == CAMEL_IMAP_RESPONSE_ERROR) {
- g_ptr_array_free (needheaders, TRUE);
- camel_operation_end (NULL);
- goto lose;
- }
- }
-
- g_ptr_array_free (needheaders, TRUE);
- camel_operation_end (NULL);
- }
-
- /* Now finish up summary entries (fix UIDs, set flags and size) */
- for (i = 0; i < fetch_data->len; i++) {
- data = fetch_data->pdata[i];
-
- seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE"));
- if (seq >= first + messages->len) {
- g_datalist_clear (&data);
- continue;
- }
-
- mi = messages->pdata[seq - first];
- if (mi == NULL) {
- CamelMessageInfo *pmi = NULL;
- int j;
-
- /* This is a kludge around a bug in Exchange
- * 5.5 that sometimes claims multiple messages
- * have the same UID. See bug #17694 for
- * details. The "solution" is to create a fake
- * message-info with the same details as the
- * previously valid message. Yes, the user
- * will have a clone in his/her message-list,
- * but at least we don't crash.
- */
-
- /* find the previous valid message info */
- for (j = seq - first - 1; j >= 0; j--) {
- pmi = messages->pdata[j];
- if (pmi != NULL)
- break;
- }
-
- if (pmi == NULL) {
- /* Server response is *really* fucked up,
- I guess we just pretend it never happened? */
- continue;
- }
-
- mi = camel_message_info_new ();
- camel_message_info_dup_to (pmi, mi);
- }
-
- uid = g_datalist_get_data (&data, "UID");
- if (uid)
- camel_message_info_set_uid (mi, g_strdup (uid));
- flags = GPOINTER_TO_INT (g_datalist_get_data (&data, "FLAGS"));
- if (flags) {
- ((CamelImapMessageInfo *)mi)->server_flags = flags;
- /* "or" them in with the existing flags that may
- * have been set by summary_info_new_from_message.
- */
- mi->flags |= flags;
- }
- size = GPOINTER_TO_INT (g_datalist_get_data (&data, "RFC822.SIZE"));
- if (size)
- mi->size = size;
-
- g_datalist_clear (&data);
- }
- g_ptr_array_free (fetch_data, TRUE);
-
- /* And add the entries to the summary, etc. */
- for (i = 0; i < messages->len; i++) {
- mi = messages->pdata[i];
- if (!mi) {
- g_warning ("No information for message %d", i + first);
- continue;
- }
- uid = (char *)camel_message_info_uid(mi);
- if (uid[0] == 0) {
- g_warning("Server provided no uid: message %d", i + first);
- continue;
- }
- info = camel_folder_summary_uid(folder->summary, uid);
- if (info) {
- g_warning("Message already present? %s", camel_message_info_uid(mi));
- camel_folder_summary_info_free(folder->summary, info);
- camel_folder_summary_info_free(folder->summary, mi);
- continue;
- }
-
- camel_folder_summary_add (folder->summary, mi);
- camel_folder_change_info_add_uid (changes, camel_message_info_uid (mi));
-
- if ((mi->flags & CAMEL_IMAP_MESSAGE_RECENT))
- camel_folder_change_info_recent_uid(changes, camel_message_info_uid (mi));
- }
- g_ptr_array_free (messages, TRUE);
-
- /* Kludge around Microsoft Exchange 5.5 IMAP - See bug #5348 for details */
- if (camel_folder_summary_count (folder->summary) != exists) {
- CamelImapStore *imap_store = (CamelImapStore *) folder->parent_store;
- CamelImapResponse *response;
-
- /* forget the currently selected folder */
- if (imap_store->current_folder) {
- camel_object_unref (CAMEL_OBJECT (imap_store->current_folder));
- imap_store->current_folder = NULL;
- }
-
- /* now re-select it and process the EXISTS response */
- response = camel_imap_command (imap_store, folder, ex, NULL);
- if (response) {
- camel_imap_folder_selected (folder, response, NULL);
- camel_imap_response_free (imap_store, response);
- }
- }
-
- return;
-
- lose:
- if (fetch_data) {
- for (i = 0; i < fetch_data->len; i++) {
- data = fetch_data->pdata[i];
- g_datalist_clear (&data);
- }
- g_ptr_array_free (fetch_data, TRUE);
- }
- if (messages) {
- for (i = 0; i < messages->len; i++) {
- if (messages->pdata[i])
- camel_folder_summary_info_free (folder->summary, messages->pdata[i]);
- }
- g_ptr_array_free (messages, TRUE);
- }
-}
-
-/* Called with the store's connect_lock locked */
-void
-camel_imap_folder_changed (CamelFolder *folder, int exists,
- GArray *expunged, CamelException *ex)
-{
- CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
- CamelFolderChangeInfo *changes;
- CamelMessageInfo *info;
- int len;
-
- CAMEL_SERVICE_ASSERT_LOCKED (folder->parent_store, connect_lock);
-
- changes = camel_folder_change_info_new ();
- if (expunged) {
- int i, id;
-
- for (i = 0; i < expunged->len; i++) {
- id = g_array_index (expunged, int, i);
- info = camel_folder_summary_index (folder->summary, id - 1);
- if (info == NULL) {
- /* FIXME: danw: does this mean that the summary is corrupt? */
- /* I guess a message that we never retrieved got expunged? */
- continue;
- }
-
- camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info));
- CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock);
- camel_imap_message_cache_remove (imap_folder->cache, camel_message_info_uid (info));
- CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
- camel_folder_summary_remove (folder->summary, info);
- camel_folder_summary_info_free(folder->summary, info);
- }
- }
-
- len = camel_folder_summary_count (folder->summary);
- if (exists > len)
- imap_update_summary (folder, exists, changes, ex);
-
- if (camel_folder_change_info_changed (changes))
- camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", changes);
-
- camel_folder_change_info_free (changes);
- camel_folder_summary_save (folder->summary);
-}
-
-static void
-imap_thaw (CamelFolder *folder)
-{
- CamelImapFolder *imap_folder;
-
- CAMEL_FOLDER_CLASS (disco_folder_class)->thaw (folder);
- if (camel_folder_is_frozen (folder))
- return;
-
- imap_folder = CAMEL_IMAP_FOLDER (folder);
- if (imap_folder->need_refresh) {
- imap_folder->need_refresh = FALSE;
- imap_refresh_info (folder, NULL);
- }
-}
-
-
-CamelStream *
-camel_imap_folder_fetch_data (CamelImapFolder *imap_folder, const char *uid,
- const char *section_text, gboolean cache_only,
- CamelException *ex)
-{
- CamelFolder *folder = CAMEL_FOLDER (imap_folder);
- CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
- CamelImapResponse *response;
- CamelStream *stream;
- GData *fetch_data;
- char *found_uid;
- int i;
-
- /* EXPUNGE responses have to modify the cache, which means
- * they have to grab the cache_lock while holding the
- * connect_lock. So we grab the connect_lock now, in case
- * we're going to need it below, since we can't grab it
- * after the cache_lock.
- */
- CAMEL_SERVICE_LOCK (store, connect_lock);
-
- CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock);
- stream = camel_imap_message_cache_get (imap_folder->cache, uid, section_text);
- if (!stream && (!strcmp (section_text, "HEADER") || !strcmp (section_text, "0")))
- stream = camel_imap_message_cache_get (imap_folder->cache, uid, "");
- if (stream || cache_only) {
- CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
- return stream;
- }
-
- if (camel_disco_store_status (CAMEL_DISCO_STORE (store)) == CAMEL_DISCO_STORE_OFFLINE) {
- camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("This message is not currently available"));
- CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
- return NULL;
- }
-
- if (store->server_level < IMAP_LEVEL_IMAP4REV1 && !*section_text) {
- response = camel_imap_command (store, folder, ex,
- "UID FETCH %s RFC822.PEEK",
- uid);
- } else {
- response = camel_imap_command (store, folder, ex,
- "UID FETCH %s BODY.PEEK[%s]",
- uid, section_text);
- }
- /* We won't need the connect_lock again after this. */
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
-
- if (!response) {
- CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
- return NULL;
- }
-
- for (i = 0; i < response->untagged->len; i++) {
- fetch_data = parse_fetch_response (imap_folder, response->untagged->pdata[i]);
- found_uid = g_datalist_get_data (&fetch_data, "UID");
- stream = g_datalist_get_data (&fetch_data, "BODY_PART_STREAM");
- if (found_uid && stream && !strcmp (uid, found_uid))
- break;
-
- g_datalist_clear (&fetch_data);
- stream = NULL;
- }
- camel_imap_response_free (store, response);
- CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
- if (!stream) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
- _("Could not find message body in FETCH response."));
- } else {
- camel_object_ref (CAMEL_OBJECT (stream));
- g_datalist_clear (&fetch_data);
- }
-
- return stream;
-}
-
-static GData *
-parse_fetch_response (CamelImapFolder *imap_folder, char *response)
-{
- GData *data = NULL;
- char *start, *part_spec = NULL, *body = NULL, *uid = NULL;
- gboolean header = FALSE;
- int body_len = 0;
-
- if (*response != '(') {
- long seq;
-
- if (*response != '*' || *(response + 1) != ' ')
- return NULL;
- seq = strtol (response + 2, &response, 10);
- if (seq == 0)
- return NULL;
- if (g_strncasecmp (response, " FETCH (", 8) != 0)
- return NULL;
- response += 7;
-
- g_datalist_set_data (&data, "SEQUENCE", GINT_TO_POINTER (seq));
- }
-
- do {
- /* Skip the initial '(' or the ' ' between elements */
- response++;
-
- if (!g_strncasecmp (response, "FLAGS ", 6)) {
- guint32 flags;
-
- response += 6;
- /* FIXME user flags */
- flags = imap_parse_flag_list (&response);
-
- g_datalist_set_data (&data, "FLAGS", GUINT_TO_POINTER (flags));
- } else if (!g_strncasecmp (response, "RFC822.SIZE ", 12)) {
- unsigned long size;
-
- response += 12;
- size = strtoul (response, &response, 10);
- g_datalist_set_data (&data, "RFC822.SIZE", GUINT_TO_POINTER (size));
- } else if (!g_strncasecmp (response, "BODY[", 5) ||
- !g_strncasecmp (response, "RFC822 ", 7)) {
- char *p;
-
- if (*response == 'B') {
- response += 5;
-
- if (!g_strncasecmp (response, "HEADER]", 7) || !g_strncasecmp (response, "0]", 2))
- header = TRUE;
-
- p = strchr (response, ']');
- if (!p || *(p + 1) != ' ')
- break;
- part_spec = g_strndup (response, p - response);
- response = p + 2;
- } else {
- part_spec = g_strdup ("");
- response += 7;
-
- if (!g_strncasecmp (response, "HEADER", 6))
- header = TRUE;
- }
-
- body = imap_parse_nstring ((const char **) &response, &body_len);
- if (!response) {
- g_free (part_spec);
- break;
- }
-
- if (!body)
- body = g_strdup ("");
- g_datalist_set_data_full (&data, "BODY_PART_SPEC", part_spec, g_free);
- g_datalist_set_data_full (&data, "BODY_PART_DATA", body, g_free);
- g_datalist_set_data (&data, "BODY_PART_LEN", GINT_TO_POINTER (body_len));
- } else if (!g_strncasecmp (response, "BODY ", 5) ||
- !g_strncasecmp (response, "BODYSTRUCTURE ", 14)) {
- response = strchr (response, ' ') + 1;
- start = response;
- imap_skip_list ((const char **) &response);
- g_datalist_set_data_full (&data, "BODY", g_strndup (start, response - start), g_free);
- } else if (!g_strncasecmp (response, "UID ", 4)) {
- int len;
-
- len = strcspn (response + 4, " )");
- uid = g_strndup (response + 4, len);
- g_datalist_set_data_full (&data, "UID", uid, g_free);
- response += 4 + len;
- } else {
- g_warning ("Unexpected FETCH response from server: (%s", response);
- break;
- }
- } while (response && *response != ')');
-
- if (!response || *response != ')') {
- g_datalist_clear (&data);
- return NULL;
- }
-
- if (uid && body) {
- CamelStream *stream;
-
- if (FALSE /*header*/) {
- g_free (part_spec);
- stream = camel_stream_mem_new_with_buffer (body, body_len);
- } else {
- CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock);
- stream = camel_imap_message_cache_insert (imap_folder->cache,
- uid, part_spec,
- body, body_len, NULL);
- CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock);
- }
-
- if (stream)
- g_datalist_set_data_full (&data, "BODY_PART_STREAM", stream,
- (GDestroyNotify) camel_object_unref);
- }
-
- return data;
-}
-
diff --git a/camel/providers/imap/camel-imap-folder.h b/camel/providers/imap/camel-imap-folder.h
deleted file mode 100644
index a49f7bd497..0000000000
--- a/camel/providers/imap/camel-imap-folder.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-imap-folder.h: class for an imap folder */
-
-/*
- * Authors:
- * Dan Winship <danw@ximian.com>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright (C) 2000, 2001 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_IMAP_FOLDER_H
-#define CAMEL_IMAP_FOLDER_H 1
-
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#include "camel-imap-types.h"
-#include <camel/camel-disco-folder.h>
-#include <camel/camel-folder-search.h>
-
-#define CAMEL_IMAP_FOLDER_TYPE (camel_imap_folder_get_type ())
-#define CAMEL_IMAP_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAP_FOLDER_TYPE, CamelImapFolder))
-#define CAMEL_IMAP_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAP_FOLDER_TYPE, CamelImapFolderClass))
-#define CAMEL_IS_IMAP_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAP_FOLDER_TYPE))
-
-struct _CamelImapFolder {
- CamelDiscoFolder parent_object;
-
- struct _CamelImapFolderPrivate *priv;
-
- gboolean need_rescan, need_refresh;
- CamelFolderSearch *search;
- CamelImapMessageCache *cache;
-};
-
-
-typedef struct {
- CamelDiscoFolderClass parent_class;
-
- /* Virtual methods */
-
-} CamelImapFolderClass;
-
-
-/* public methods */
-CamelFolder *camel_imap_folder_new (CamelStore *parent,
- const char *folder_name,
- const char *folder_dir,
- CamelException *ex);
-
-void camel_imap_folder_selected (CamelFolder *folder,
- CamelImapResponse *response,
- CamelException *ex);
-
-void camel_imap_folder_changed (CamelFolder *folder, int exists,
- GArray *expunged, CamelException *ex);
-
-CamelStream *camel_imap_folder_fetch_data (CamelImapFolder *imap_folder,
- const char *uid,
- const char *section_text,
- gboolean cache_only,
- CamelException *ex);
-
-/* Standard Camel function */
-CamelType camel_imap_folder_get_type (void);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CAMEL_IMAP_FOLDER_H */
diff --git a/camel/providers/imap/camel-imap-message-cache.c b/camel/providers/imap/camel-imap-message-cache.c
deleted file mode 100644
index 0701ca45e4..0000000000
--- a/camel/providers/imap/camel-imap-message-cache.c
+++ /dev/null
@@ -1,518 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-imap-message-cache.c: Class for an IMAP message cache */
-
-/*
- * Author:
- * Dan Winship <danw@ximian.com>
- *
- * Copyright (C) 2001 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/types.h>
-#include <dirent.h>
-#include <errno.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "camel-imap-message-cache.h"
-#include "camel-data-wrapper.h"
-#include "camel-exception.h"
-#include "camel-stream-fs.h"
-
-static void finalize (CamelImapMessageCache *cache);
-static void stream_finalize (CamelObject *stream, gpointer event_data, gpointer user_data);
-
-
-CamelType
-camel_imap_message_cache_get_type (void)
-{
- static CamelType camel_imap_message_cache_type = CAMEL_INVALID_TYPE;
-
- if (camel_imap_message_cache_type == CAMEL_INVALID_TYPE) {
- camel_imap_message_cache_type = camel_type_register (
- CAMEL_OBJECT_TYPE, "CamelImapMessageCache",
- sizeof (CamelImapMessageCache),
- sizeof (CamelImapMessageCacheClass),
- NULL,
- NULL,
- NULL,
- (CamelObjectFinalizeFunc) finalize);
- }
-
- return camel_imap_message_cache_type;
-}
-
-static void
-free_part (gpointer key, gpointer value, gpointer data)
-{
- if (value) {
- if (strchr (key, '.')) {
- camel_object_unhook_event (value, "finalize",
- stream_finalize, data);
- camel_object_unref (value);
- } else
- g_ptr_array_free (value, TRUE);
- }
- g_free (key);
-}
-
-static void
-finalize (CamelImapMessageCache *cache)
-{
- if (cache->path)
- g_free (cache->path);
- if (cache->parts) {
- g_hash_table_foreach (cache->parts, free_part, cache);
- g_hash_table_destroy (cache->parts);
- }
- if (cache->cached)
- g_hash_table_destroy (cache->cached);
-}
-
-static void
-cache_put (CamelImapMessageCache *cache, const char *uid, const char *key,
- CamelStream *stream)
-{
- char *hash_key;
- GPtrArray *subparts;
- gpointer okey, ostream;
- guint32 uidval;
-
- uidval = strtoul (uid, NULL, 10);
- if (uidval > cache->max_uid)
- cache->max_uid = uidval;
-
- subparts = g_hash_table_lookup (cache->parts, uid);
- if (!subparts) {
- subparts = g_ptr_array_new ();
- g_hash_table_insert (cache->parts, g_strdup (uid), subparts);
- }
-
- if (g_hash_table_lookup_extended (cache->parts, key, &okey, &ostream)) {
- if (ostream) {
- camel_object_unhook_event (ostream, "finalize",
- stream_finalize, cache);
- g_hash_table_remove (cache->cached, ostream);
- camel_object_unref (ostream);
- }
- hash_key = okey;
- } else {
- hash_key = g_strdup (key);
- g_ptr_array_add (subparts, hash_key);
- }
-
- g_hash_table_insert (cache->parts, hash_key, stream);
- g_hash_table_insert (cache->cached, stream, hash_key);
-
- if (stream) {
- camel_object_hook_event (CAMEL_OBJECT (stream), "finalize",
- stream_finalize, cache);
- }
-}
-
-/**
- * camel_imap_message_cache_new:
- * @path: directory to use for storage
- * @summary: CamelFolderSummary for the folder we are caching
- * @ex: a CamelException
- *
- * Return value: a new CamelImapMessageCache object using @path for
- * storage. If cache files already exist in @path, then any that do not
- * correspond to messages in @summary will be deleted.
- **/
-CamelImapMessageCache *
-camel_imap_message_cache_new (const char *path, CamelFolderSummary *summary,
- CamelException *ex)
-{
- CamelImapMessageCache *cache;
- DIR *dir;
- struct dirent *d;
- char *uid, *p;
- GPtrArray *deletes;
- CamelMessageInfo *info;
-
- dir = opendir (path);
- if (!dir) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Could not open cache directory: %s"),
- g_strerror (errno));
- return NULL;
- }
-
- cache = (CamelImapMessageCache *)camel_object_new (CAMEL_IMAP_MESSAGE_CACHE_TYPE);
- cache->path = g_strdup (path);
-
- cache->parts = g_hash_table_new (g_str_hash, g_str_equal);
- cache->cached = g_hash_table_new (NULL, NULL);
- deletes = g_ptr_array_new ();
- while ((d = readdir (dir))) {
- if (!isdigit (d->d_name[0]))
- continue;
-
- p = strchr (d->d_name, '.');
- if (p)
- uid = g_strndup (d->d_name, p - d->d_name);
- else
- uid = g_strdup (d->d_name);
-
- info = camel_folder_summary_uid (summary, uid);
- if (info) {
- camel_folder_summary_info_free (summary, info);
- cache_put (cache, uid, d->d_name, NULL);
- } else
- g_ptr_array_add (deletes, g_strdup_printf ("%s/%s", cache->path, d->d_name));
- g_free (uid);
- }
- closedir (dir);
-
- while (deletes->len) {
- unlink (deletes->pdata[0]);
- g_free (deletes->pdata[0]);
- g_ptr_array_remove_index_fast (deletes, 0);
- }
- g_ptr_array_free (deletes, TRUE);
-
- return cache;
-}
-
-/**
- * camel_imap_message_cache_max_uid:
- * @cache: the cache
- *
- * Return value: the largest (real) UID in the cache.
- **/
-guint32
-camel_imap_message_cache_max_uid (CamelImapMessageCache *cache)
-{
- return cache->max_uid;
-}
-
-/**
- * camel_imap_message_cache_set_path:
- * @cache:
- * @path:
- *
- * Set the path used for the message cache.
- **/
-void
-camel_imap_message_cache_set_path (CamelImapMessageCache *cache, const char *path)
-{
- g_free(cache->path);
- cache->path = g_strdup(path);
-}
-
-static void
-stream_finalize (CamelObject *stream, gpointer event_data, gpointer user_data)
-{
- CamelImapMessageCache *cache = user_data;
- char *key;
-
- key = g_hash_table_lookup (cache->cached, stream);
- if (!key)
- return;
- g_hash_table_remove (cache->cached, stream);
- g_hash_table_insert (cache->parts, key, NULL);
-}
-
-
-static CamelStream *
-insert_setup (CamelImapMessageCache *cache, const char *uid, const char *part_spec,
- char **path, char **key, CamelException *ex)
-{
- CamelStream *stream;
- int fd;
-
- *path = g_strdup_printf ("%s/%s.%s", cache->path, uid, part_spec);
- *key = strrchr (*path, '/') + 1;
- stream = g_hash_table_lookup (cache->parts, *key);
- if (stream)
- camel_object_unref (CAMEL_OBJECT (stream));
-
- fd = open (*path, O_RDWR | O_CREAT | O_TRUNC, 0600);
- if (fd == -1) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Failed to cache message %s: %s"),
- uid, g_strerror (errno));
- g_free (*path);
- return NULL;
- }
-
- return camel_stream_fs_new_with_fd (fd);
-}
-
-static CamelStream *
-insert_abort (char *path, CamelStream *stream)
-{
- unlink (path);
- g_free (path);
- camel_object_unref (CAMEL_OBJECT (stream));
- return NULL;
-}
-
-static CamelStream *
-insert_finish (CamelImapMessageCache *cache, const char *uid, char *path,
- char *key, CamelStream *stream)
-{
- camel_stream_flush (stream);
- camel_stream_reset (stream);
- cache_put (cache, uid, key, stream);
- g_free (path);
-
- return stream;
-}
-
-/**
- * camel_imap_message_cache_insert:
- * @cache: the cache
- * @uid: UID of the message data to cache
- * @part_spec: the IMAP part_spec of the data
- * @data: the data
- * @len: length of @data
- *
- * Caches the provided data into @cache.
- *
- * Return value: a CamelStream containing the cached data, which the
- * caller must unref.
- **/
-CamelStream *
-camel_imap_message_cache_insert (CamelImapMessageCache *cache, const char *uid,
- const char *part_spec, const char *data,
- int len, CamelException *ex)
-{
- char *path, *key;
- CamelStream *stream;
-
- stream = insert_setup (cache, uid, part_spec, &path, &key, ex);
- if (!stream)
- return NULL;
-
- if (camel_stream_write (stream, data, len) == -1) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Failed to cache message %s: %s"),
- uid, g_strerror (errno));
- return insert_abort (path, stream);
- }
-
- return insert_finish (cache, uid, path, key, stream);
-}
-
-/**
- * camel_imap_message_cache_insert_stream:
- * @cache: the cache
- * @uid: UID of the message data to cache
- * @part_spec: the IMAP part_spec of the data
- * @data_stream: the stream to cache
- *
- * Caches the provided data into @cache.
- **/
-void
-camel_imap_message_cache_insert_stream (CamelImapMessageCache *cache,
- const char *uid, const char *part_spec,
- CamelStream *data_stream, CamelException *ex)
-{
- char *path, *key;
- CamelStream *stream;
-
- stream = insert_setup (cache, uid, part_spec, &path, &key, ex);
- if (!stream)
- return;
-
- if (camel_stream_write_to_stream (data_stream, stream) == -1) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Failed to cache message %s: %s"),
- uid, g_strerror (errno));
- insert_abort (path, stream);
- } else {
- insert_finish (cache, uid, path, key, stream);
- camel_object_unref (CAMEL_OBJECT (stream));
- }
-}
-
-/**
- * camel_imap_message_cache_insert_wrapper:
- * @cache: the cache
- * @uid: UID of the message data to cache
- * @part_spec: the IMAP part_spec of the data
- * @wrapper: the wrapper to cache
- *
- * Caches the provided data into @cache.
- **/
-void
-camel_imap_message_cache_insert_wrapper (CamelImapMessageCache *cache,
- const char *uid, const char *part_spec,
- CamelDataWrapper *wrapper, CamelException *ex)
-{
- char *path, *key;
- CamelStream *stream;
-
- stream = insert_setup (cache, uid, part_spec, &path, &key, ex);
- if (!stream)
- return;
-
- if (camel_data_wrapper_write_to_stream (wrapper, stream) == -1) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Failed to cache message %s: %s"),
- uid, g_strerror (errno));
- insert_abort (path, stream);
- } else {
- insert_finish (cache, uid, path, key, stream);
- camel_object_unref (CAMEL_OBJECT (stream));
- }
-}
-
-
-/**
- * camel_imap_message_cache_get:
- * @cache: the cache
- * @uid: the UID of the data to get
- * @part_spec: the part_spec of the data to get
- *
- * Return value: a CamelStream containing the cached data (which the
- * caller must unref), or %NULL if that data is not cached.
- **/
-CamelStream *
-camel_imap_message_cache_get (CamelImapMessageCache *cache, const char *uid,
- const char *part_spec)
-{
- CamelStream *stream;
- char *path, *key;
-
- if (uid[0] == 0)
- return NULL;
-
- path = g_strdup_printf ("%s/%s.%s", cache->path, uid, part_spec);
- key = strrchr (path, '/') + 1;
- stream = g_hash_table_lookup (cache->parts, key);
- if (stream) {
- camel_stream_reset (CAMEL_STREAM (stream));
- camel_object_ref (CAMEL_OBJECT (stream));
- g_free (path);
- return stream;
- }
-
- stream = camel_stream_fs_new_with_name (path, O_RDONLY, 0);
- if (stream)
- cache_put (cache, uid, key, stream);
- g_free (path);
-
- return stream;
-}
-
-/**
- * camel_imap_message_cache_remove:
- * @cache: the cache
- * @uid: UID of the data to remove
- *
- * Removes all data associated with @uid from @cache.
- **/
-void
-camel_imap_message_cache_remove (CamelImapMessageCache *cache, const char *uid)
-{
- GPtrArray *subparts;
- char *key, *path;
- CamelObject *stream;
- int i;
-
- subparts = g_hash_table_lookup (cache->parts, uid);
- if (!subparts)
- return;
- for (i = 0; i < subparts->len; i++) {
- key = subparts->pdata[i];
- path = g_strdup_printf ("%s/%s", cache->path, key);
- unlink (path);
- g_free (path);
- stream = g_hash_table_lookup (cache->parts, key);
- if (stream) {
- camel_object_unhook_event (stream, "finalize",
- stream_finalize, cache);
- camel_object_unref (stream);
- g_hash_table_remove (cache->cached, stream);
- }
- g_hash_table_remove (cache->parts, key);
- g_free (key);
- }
- g_hash_table_remove (cache->parts, uid);
- g_ptr_array_free (subparts, TRUE);
-}
-
-static void
-add_uids (gpointer key, gpointer value, gpointer data)
-{
- if (!strchr (key, '.'))
- g_ptr_array_add (data, key);
-}
-
-/**
- * camel_imap_message_cache_clear:
- * @cache: the cache
- *
- * Removes all cached data from @cache.
- **/
-void
-camel_imap_message_cache_clear (CamelImapMessageCache *cache)
-{
- GPtrArray *uids;
- int i;
-
- uids = g_ptr_array_new ();
- g_hash_table_foreach (cache->parts, add_uids, uids);
-
- for (i = 0; i < uids->len; i++)
- camel_imap_message_cache_remove (cache, uids->pdata[i]);
- g_ptr_array_free (uids, TRUE);
-}
-
-
-/**
- * camel_imap_message_cache_copy:
- * @source: the source message cache
- * @source_uid: UID of a message in @source
- * @dest: the destination message cache
- * @dest_uid: UID of the message in @dest
- *
- * Copies all cached parts from @source_uid in @source to @dest_uid in
- * @destination.
- **/
-void
-camel_imap_message_cache_copy (CamelImapMessageCache *source,
- const char *source_uid,
- CamelImapMessageCache *dest,
- const char *dest_uid,
- CamelException *ex)
-{
- GPtrArray *subparts;
- CamelStream *stream;
- char *part;
- int i;
-
- subparts = g_hash_table_lookup (source->parts, source_uid);
- if (!subparts || !subparts->len)
- return;
-
- for (i = 0; i < subparts->len; i++) {
- part = strchr (subparts->pdata[i], '.');
- if (!part++)
- continue;
- stream = camel_imap_message_cache_get (source, source_uid, part);
- camel_imap_message_cache_insert_stream (dest, dest_uid, part, stream, ex);
- camel_object_unref (CAMEL_OBJECT (stream));
- }
-}
diff --git a/camel/providers/imap/camel-imap-message-cache.h b/camel/providers/imap/camel-imap-message-cache.h
deleted file mode 100644
index eb3f056b44..0000000000
--- a/camel/providers/imap/camel-imap-message-cache.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-imap-message-cache.h: Class for an IMAP message cache */
-
-/*
- * Author:
- * Dan Winship <danw@ximian.com>
- *
- * Copyright (C) 2001 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
- */
-
-
-#ifndef CAMEL_IMAP_MESSAGE_CACHE_H
-#define CAMEL_IMAP_MESSAGE_CACHE_H 1
-
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus }*/
-
-#include "camel-imap-types.h"
-#include "camel-folder.h"
-#include <camel/camel-folder-search.h>
-
-#define CAMEL_IMAP_MESSAGE_CACHE_TYPE (camel_imap_message_cache_get_type ())
-#define CAMEL_IMAP_MESSAGE_CACHE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAP_MESSAGE_CACHE_TYPE, CamelImapFolder))
-#define CAMEL_IMAP_MESSAGE_CACHE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAP_MESSAGE_CACHE_TYPE, CamelImapFolderClass))
-#define CAMEL_IS_IMAP_MESSAGE_CACHE(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAP_MESSAGE_CACHE_TYPE))
-
-struct _CamelImapMessageCache {
- CamelObject parent_object;
-
- char *path;
- GHashTable *parts, *cached;
- guint32 max_uid;
-};
-
-
-typedef struct {
- CamelFolderClass parent_class;
-
- /* Virtual methods */
-
-} CamelImapMessageCacheClass;
-
-
-/* public methods */
-CamelImapMessageCache *camel_imap_message_cache_new (const char *path,
- CamelFolderSummary *summ,
- CamelException *ex);
-
-void camel_imap_message_cache_set_path (CamelImapMessageCache *cache,
- const char *path);
-
-guint32 camel_imap_message_cache_max_uid (CamelImapMessageCache *cache);
-
-CamelStream *camel_imap_message_cache_insert (CamelImapMessageCache *cache,
- const char *uid,
- const char *part_spec,
- const char *data,
- int len,
- CamelException *ex);
-void camel_imap_message_cache_insert_stream (CamelImapMessageCache *cache,
- const char *uid,
- const char *part_spec,
- CamelStream *data_stream,
- CamelException *ex);
-void camel_imap_message_cache_insert_wrapper (CamelImapMessageCache *cache,
- const char *uid,
- const char *part_spec,
- CamelDataWrapper *wrapper,
- CamelException *ex);
-
-CamelStream *camel_imap_message_cache_get (CamelImapMessageCache *cache,
- const char *uid,
- const char *part_spec);
-void camel_imap_message_cache_remove (CamelImapMessageCache *cache,
- const char *uid);
-
-void camel_imap_message_cache_clear (CamelImapMessageCache *cache);
-
-void camel_imap_message_cache_copy (CamelImapMessageCache *source,
- const char *source_uid,
- CamelImapMessageCache *dest,
- const char *dest_uid,
- CamelException *ex);
-
-/* Standard Camel function */
-CamelType camel_imap_message_cache_get_type (void);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CAMEL_IMAP_MESSAGE_CACHE_H */
diff --git a/camel/providers/imap/camel-imap-private.h b/camel/providers/imap/camel-imap-private.h
deleted file mode 100644
index 0f80dbfd1c..0000000000
--- a/camel/providers/imap/camel-imap-private.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- * camel-imap-private.h: Private info for imap.
- *
- * Authors: Michael Zucchi <notzed@ximian.com>
- *
- * Copyright 1999, 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
- */
-
-#ifndef CAMEL_IMAP_PRIVATE_H
-#define CAMEL_IMAP_PRIVATE_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-/* need a way to configure and save this data, if this header is to
- be installed. For now, dont install it */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef ENABLE_THREADS
-#include "e-util/e-msgport.h"
-#endif
-
-struct _CamelImapFolderPrivate {
-#ifdef ENABLE_THREADS
- EMutex *search_lock; /* for locking the search object */
- EMutex *cache_lock; /* for locking the cache object */
-#endif
-};
-
-#ifdef ENABLE_THREADS
-#define CAMEL_IMAP_FOLDER_LOCK(f, l) (e_mutex_lock(((CamelImapFolder *)f)->priv->l))
-#define CAMEL_IMAP_FOLDER_UNLOCK(f, l) (e_mutex_unlock(((CamelImapFolder *)f)->priv->l))
-#else
-#define CAMEL_IMAP_FOLDER_LOCK(f, l)
-#define CAMEL_IMAP_FOLDER_UNLOCK(f, l)
-#endif
-
-struct _CamelImapWrapperPrivate {
-#ifdef ENABLE_THREADS
- GMutex *lock;
-#endif
-};
-
-#ifdef ENABLE_THREADS
-#define CAMEL_IMAP_WRAPPER_LOCK(f, l) (g_mutex_lock(((CamelImapWrapper *)f)->priv->l))
-#define CAMEL_IMAP_WRAPPER_UNLOCK(f, l) (g_mutex_unlock(((CamelImapWrapper *)f)->priv->l))
-#else
-#define CAMEL_IMAP_WRAPPER_LOCK(f, l)
-#define CAMEL_IMAP_WRAPPER_UNLOCK(f, l)
-#endif
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CAMEL_IMAP_PRIVATE_H */
-
diff --git a/camel/providers/imap/camel-imap-provider.c b/camel/providers/imap/camel-imap-provider.c
deleted file mode 100644
index 44e41a3d30..0000000000
--- a/camel/providers/imap/camel-imap-provider.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-imap-provider.c: imap provider registration code */
-
-/*
- * Authors: Jeffrey Stedfast <fejj@ximian.com>
- *
- * 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 <string.h>
-#include "camel-imap-store.h"
-#include "camel-provider.h"
-#include "camel-session.h"
-#include "camel-url.h"
-#include "camel-sasl.h"
-
-static void add_hash (guint *hash, char *s);
-static guint imap_url_hash (gconstpointer key);
-static gint check_equal (char *s1, char *s2);
-static gint imap_url_equal (gconstpointer a, gconstpointer b);
-
-CamelProviderConfEntry imap_conf_entries[] = {
- { CAMEL_PROVIDER_CONF_SECTION_START, "mailcheck", NULL,
- N_("Checking for new mail") },
- { CAMEL_PROVIDER_CONF_CHECKBOX, "check_all", NULL,
- N_("Check for new messages in all folders"), "1" },
- { CAMEL_PROVIDER_CONF_SECTION_END },
- { CAMEL_PROVIDER_CONF_SECTION_START, "folders", NULL,
- N_("Folders") },
- { CAMEL_PROVIDER_CONF_CHECKBOX, "use_lsub", NULL,
- N_("Show only subscribed folders"), "1" },
- { CAMEL_PROVIDER_CONF_CHECKBOX, "override_namespace", NULL,
- N_("Override server-supplied folder namespace"), "0" },
- { CAMEL_PROVIDER_CONF_ENTRY, "namespace", "override_namespace",
- N_("Namespace") },
- { CAMEL_PROVIDER_CONF_SECTION_END },
- { CAMEL_PROVIDER_CONF_CHECKBOX, "filter", NULL,
- N_("Apply filters to new messages in INBOX on this server"), "0" },
- { CAMEL_PROVIDER_CONF_END }
-};
-
-static CamelProvider imap_provider = {
- "imap",
- N_("IMAP"),
-
- N_("For reading and storing mail on IMAP servers."),
-
- "mail",
-
- CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE |
- CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_SUPPORTS_SSL,
-
- CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH,
-
- imap_conf_entries,
-
- /* ... */
-};
-
-CamelServiceAuthType camel_imap_password_authtype = {
- N_("Password"),
-
- N_("This option will connect to the IMAP server using a "
- "plaintext password."),
-
- "",
- TRUE
-};
-
-void
-camel_provider_module_init (CamelSession *session)
-{
- imap_provider.object_types[CAMEL_PROVIDER_STORE] =
- camel_imap_store_get_type ();
- imap_provider.url_hash = imap_url_hash;
- imap_provider.url_equal = imap_url_equal;
- imap_provider.authtypes = camel_sasl_authtype_list (FALSE);
- imap_provider.authtypes = g_list_prepend (imap_provider.authtypes,
- &camel_imap_password_authtype);
-
- camel_session_register_provider (session, &imap_provider);
-}
-
-static void
-add_hash (guint *hash, char *s)
-{
- if (s)
- *hash ^= g_str_hash(s);
-}
-
-static guint
-imap_url_hash (gconstpointer key)
-{
- const CamelURL *u = (CamelURL *)key;
- guint hash = 0;
-
- add_hash (&hash, u->user);
- add_hash (&hash, u->authmech);
- add_hash (&hash, u->host);
- hash ^= u->port;
-
- return hash;
-}
-
-static gint
-check_equal (char *s1, char *s2)
-{
- if (s1 == NULL) {
- if (s2 == NULL)
- return TRUE;
- else
- return FALSE;
- }
-
- if (s2 == NULL)
- return FALSE;
-
- return strcmp (s1, s2) == 0;
-}
-
-static gint
-imap_url_equal (gconstpointer a, gconstpointer b)
-{
- const CamelURL *u1 = a, *u2 = b;
-
- return check_equal (u1->user, u2->user)
- && check_equal (u1->authmech, u2->authmech)
- && check_equal (u1->host, u2->host)
- && u1->port == u2->port;
-}
diff --git a/camel/providers/imap/camel-imap-search.c b/camel/providers/imap/camel-imap-search.c
deleted file mode 100644
index c30fa5611e..0000000000
--- a/camel/providers/imap/camel-imap-search.c
+++ /dev/null
@@ -1,499 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-imap-search.c: IMAP folder search */
-
-/*
- * Authors:
- * Dan Winship <danw@ximian.com>
- * Michael Zucchi <notzed@ximian.com>
- *
- * Copyright 2000, 2001, 2002 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.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include "camel-imap-command.h"
-#include "camel-imap-folder.h"
-#include "camel-imap-store.h"
-#include "camel-imap-search.h"
-#include "camel-imap-private.h"
-#include "camel-imap-utils.h"
-#include "camel-imap-summary.h"
-
-#include "e-util/md5-utils.h" /* md5 hash building */
-#include "camel-mime-utils.h" /* base64 encoding */
-
-#include "camel-seekable-stream.h"
-#include "camel-search-private.h"
-
-#define d(x) x
-
-/*
- File is:
- BODY (as in body search)
- Last uid when search performed
- termcount: number of search terms
- matchcount: number of matches
- term0, term1 ...
- match0, match1, match2, ...
-*/
-
-/* size of in-memory cache */
-#define MATCH_CACHE_SIZE (32)
-
-/* Also takes care of 'endianness' file magic */
-#define MATCH_MARK (('B' << 24) | ('O' << 16) | ('D' << 8) | 'Y')
-
-/* on-disk header, in native endianness format, matches follow */
-struct _match_header {
- guint32 mark;
- guint32 validity; /* uidvalidity for this folder */
- guint32 lastuid;
- guint32 termcount;
- guint32 matchcount;
-};
-
-/* in-memory record */
-struct _match_record {
- struct _match_record *next;
- struct _match_record *prev;
-
- char hash[17];
-
- guint32 lastuid;
- guint32 validity;
-
- unsigned int termcount;
- char **terms;
- GArray *matches;
-};
-
-
-static void free_match(CamelImapSearch *is, struct _match_record *mr);
-static ESExpResult *imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
-
-static CamelFolderSearchClass *imap_search_parent_class;
-
-static void
-camel_imap_search_class_init (CamelImapSearchClass *camel_imap_search_class)
-{
- /* virtual method overload */
- CamelFolderSearchClass *camel_folder_search_class =
- CAMEL_FOLDER_SEARCH_CLASS (camel_imap_search_class);
-
- imap_search_parent_class = (CamelFolderSearchClass *)camel_type_get_global_classfuncs (camel_folder_search_get_type ());
-
- /* virtual method overload */
- camel_folder_search_class->body_contains = imap_body_contains;
-}
-
-static void
-camel_imap_search_init(CamelImapSearch *is)
-{
- e_dlist_init(&is->matches);
- is->matches_hash = g_hash_table_new(g_str_hash, g_str_equal);
- is->matches_count = 0;
- is->lastuid = 0;
-}
-
-static void
-camel_imap_search_finalise(CamelImapSearch *is)
-{
- struct _match_record *mr;
-
- while ( (mr = (struct _match_record *)e_dlist_remtail(&is->matches)) )
- free_match(is, mr);
- g_hash_table_destroy(is->matches_hash);
- if (is->cache)
- camel_object_unref((CamelObject *)is->cache);
-}
-
-CamelType
-camel_imap_search_get_type (void)
-{
- static CamelType camel_imap_search_type = CAMEL_INVALID_TYPE;
-
- if (camel_imap_search_type == CAMEL_INVALID_TYPE) {
- camel_imap_search_type = camel_type_register (
- CAMEL_FOLDER_SEARCH_TYPE, "CamelImapSearch",
- sizeof (CamelImapSearch),
- sizeof (CamelImapSearchClass),
- (CamelObjectClassInitFunc) camel_imap_search_class_init, NULL,
- (CamelObjectInitFunc) camel_imap_search_init,
- (CamelObjectFinalizeFunc) camel_imap_search_finalise);
- }
-
- return camel_imap_search_type;
-}
-
-/**
- * camel_imap_search_new:
- *
- * Return value: A new CamelImapSearch widget.
- **/
-CamelFolderSearch *
-camel_imap_search_new (const char *cachedir)
-{
- CamelFolderSearch *new = CAMEL_FOLDER_SEARCH (camel_object_new (camel_imap_search_get_type ()));
- CamelImapSearch *is = (CamelImapSearch *)new;
-
- camel_folder_search_construct (new);
-
- is->cache = camel_data_cache_new(cachedir, 0, NULL);
- if (is->cache) {
- /* Expire entries after 14 days of inactivity */
- camel_data_cache_set_expire_access(is->cache, 60*60*24*14);
- }
-
- return new;
-}
-
-
-static void
-hash_match(char hash[17], int argc, struct _ESExpResult **argv)
-{
- MD5Context ctx;
- unsigned char digest[16];
- unsigned int state = 0, save = 0;
- int i;
-
- md5_init(&ctx);
- for (i=0;i<argc;i++) {
- if (argv[i]->type == ESEXP_RES_STRING)
- md5_update(&ctx, argv[i]->value.string, strlen(argv[i]->value.string));
- }
- md5_final(&ctx, digest);
-
- base64_encode_close(digest, 12, FALSE, hash, &state, &save);
-
- for (i=0;i<16;i++) {
- if (hash[i] == '+')
- hash[i] = ',';
- if (hash[i] == '/')
- hash[i] = '_';
- }
-
- hash[16] = 0;
-}
-
-static int
-save_match(CamelImapSearch *is, struct _match_record *mr)
-{
- guint32 mark = MATCH_MARK;
- int ret = 0;
- struct _match_header header;
- CamelStream *stream;
-
- /* since its a cache, doesn't matter if it doesn't save, at least we have the in-memory cache
- for this session */
- if (is->cache == NULL)
- return -1;
-
- stream = camel_data_cache_add(is->cache, "search/body-contains", mr->hash, NULL);
- if (stream == NULL)
- return -1;
-
- d(printf("Saving search cache entry to '%s': %s\n", mr->hash, mr->terms[0]));
-
- /* we write the whole thing, then re-write the header magic, saves fancy sync code */
- memcpy(&header.mark, " ", 4);
- header.termcount = 0;
- header.matchcount = mr->matches->len;
- header.lastuid = mr->lastuid;
- header.validity = mr->validity;
-
- if (camel_stream_write(stream, (char *)&header, sizeof(header)) != sizeof(header)
- || camel_stream_write(stream, mr->matches->data, mr->matches->len*sizeof(guint32)) != mr->matches->len*sizeof(guint32)
- || camel_seekable_stream_seek((CamelSeekableStream *)stream, 0, CAMEL_STREAM_SET) == -1
- || camel_stream_write(stream, (char *)&mark, sizeof(mark)) != sizeof(mark)) {
- d(printf(" saving failed, removing cache entry\n"));
- camel_data_cache_remove(is->cache, "search/body-contains", mr->hash, NULL);
- ret = -1;
- }
-
- camel_object_unref((CamelObject *)stream);
- return ret;
-}
-
-static void
-free_match(CamelImapSearch *is, struct _match_record *mr)
-{
- int i;
-
- for (i=0;i<mr->termcount;i++)
- g_free(mr->terms[i]);
- g_free(mr->terms);
- g_array_free(mr->matches, TRUE);
- g_free(mr);
-}
-
-static struct _match_record *
-load_match(CamelImapSearch *is, char hash[17], int argc, struct _ESExpResult **argv)
-{
- struct _match_record *mr;
- CamelStream *stream = NULL;
- struct _match_header header;
- int i;
-
- mr = g_malloc0(sizeof(*mr));
- mr->matches = g_array_new(0, 0, sizeof(guint32));
- g_assert(strlen(hash) == 16);
- strcpy(mr->hash, hash);
- mr->terms = g_malloc0(sizeof(mr->terms[0]) * argc);
- for (i=0;i<argc;i++) {
- if (argv[i]->type == ESEXP_RES_STRING) {
- mr->termcount++;
- mr->terms[i] = g_strdup(argv[i]->value.string);
- }
- }
-
- d(printf("Loading search cache entry to '%s': %s\n", mr->hash, mr->terms[0]));
-
- memset(&header, 0, sizeof(header));
- if (is->cache)
- stream = camel_data_cache_get(is->cache, "search/body-contains", mr->hash, NULL);
- if (stream != NULL) {
- /* 'cause i'm gonna be lazy, i'm going to have the termcount == 0 for now,
- and not load or save them since i can't think of a nice way to do it, the hash
- should be sufficient to key it */
- /* This check should also handle endianness changes, we just throw away
- the data (its only a cache) */
- if (camel_stream_read(stream, (char *)&header, sizeof(header)) == sizeof(header)
- && header.validity == is->validity
- && header.mark == MATCH_MARK
- && header.termcount == 0) {
- d(printf(" found %d matches\n", header.matchcount));
- g_array_set_size(mr->matches, header.matchcount);
- camel_stream_read(stream, mr->matches->data, sizeof(guint32)*header.matchcount);
- } else {
- d(printf(" file format invalid/validity changed\n"));
- memset(&header, 0, sizeof(header));
- }
- camel_object_unref((CamelObject *)stream);
- } else {
- d(printf(" no cache entry found\n"));
- }
-
- mr->validity = header.validity;
- if (mr->validity != is->validity)
- mr->lastuid = 0;
- else
- mr->lastuid = header.lastuid;
-
- return mr;
-}
-
-static int
-sync_match(CamelImapSearch *is, struct _match_record *mr)
-{
- char *p, *result, *lasts = NULL;
- CamelImapResponse *response = NULL;
- guint32 uid;
- CamelFolder *folder = ((CamelFolderSearch *)is)->folder;
- CamelImapStore *store = (CamelImapStore *)folder->parent_store;
- struct _camel_search_words *words;
- GString *search;
- int i;
-
- if (mr->lastuid >= is->lastuid && mr->validity == is->validity)
- return 0;
-
- d(printf("updating match record for uid's %d:%d\n", mr->lastuid+1, is->lastuid));
-
- /* TODO: Handle multiple search terms */
-
- /* This handles multiple search words within a single term */
- words = camel_search_words_split(mr->terms[0]);
- search = g_string_new("");
- g_string_sprintfa(search, "UID %d:%d", mr->lastuid+1, is->lastuid);
- for (i=0;i<words->len;i++) {
- char *w = words->words[i]->word, c;
-
- g_string_sprintfa(search, " BODY \"");
- while ((c = *w++)) {
- if (c == '\\' || c == '"')
- g_string_append_c(search, '\\');
- g_string_append_c(search, c);
- }
- g_string_append_c(search, '"');
- }
- camel_search_words_free(words);
-
- /* We only try search using utf8 if its non us-ascii text? */
- if ((words->type & CAMEL_SEARCH_WORD_8BIT) && (store->capabilities & IMAP_CAPABILITY_utf8_search)) {
- response = camel_imap_command(store, folder, NULL,
- "UID SEARCH CHARSET UTF-8 %s", search->str);
- /* We can't actually tell if we got a NO response, so assume always */
- if (response == NULL)
- store->capabilities &= ~IMAP_CAPABILITY_utf8_search;
- }
- if (response == NULL)
- response = camel_imap_command (store, folder, NULL,
- "UID SEARCH %s", search->str);
- g_string_free(search, TRUE);
-
- if (!response)
- return -1;
- result = camel_imap_response_extract (store, response, "SEARCH", NULL);
- if (!result)
- return -1;
-
- p = result + sizeof ("* SEARCH");
- for (p = strtok_r (p, " ", &lasts); p; p = strtok_r (NULL, " ", &lasts)) {
- uid = strtoul(p, NULL, 10);
- g_array_append_vals(mr->matches, &uid, 1);
- }
- g_free(result);
-
- mr->validity = is->validity;
- mr->lastuid = is->lastuid;
- save_match(is, mr);
-
- return 0;
-}
-
-static struct _match_record *
-get_match(CamelImapSearch *is, int argc, struct _ESExpResult **argv)
-{
- char hash[17];
- struct _match_record *mr;
-
- hash_match(hash, argc, argv);
-
- mr = g_hash_table_lookup(is->matches_hash, hash);
- if (mr == NULL) {
- while (is->matches_count >= MATCH_CACHE_SIZE) {
- mr = (struct _match_record *)e_dlist_remtail(&is->matches);
- if (mr) {
- printf("expiring match '%s' (%s)\n", mr->hash, mr->terms[0]);
- g_hash_table_remove(is->matches_hash, mr->hash);
- free_match(is, mr);
- is->matches_count--;
- } else {
- is->matches_count = 0;
- }
- }
- mr = load_match(is, hash, argc, argv);
- g_hash_table_insert(is->matches_hash, mr->hash, mr);
- is->matches_count++;
- } else {
- e_dlist_remove((EDListNode *)mr);
- }
-
- e_dlist_addhead(&is->matches, (EDListNode *)mr);
-
- /* what about offline mode? */
- /* We could cache those results too, or should we cache them elsewhere? */
- sync_match(is, mr);
-
- return mr;
-}
-
-static ESExpResult *
-imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (s->folder->parent_store);
- CamelImapSearch *is = (CamelImapSearch *)s;
- char *uid;
- ESExpResult *r;
- CamelMessageInfo *info;
- GHashTable *uid_hash = NULL;
- GPtrArray *array;
- int i, j;
- struct _match_record *mr;
- guint32 uidn, *uidp;
-
- d(printf("Performing body search '%s'\n", argv[0]->value.string));
-
- /* TODO: Cache offline searches too? */
-
- /* If offline, search using the parent class, which can handle this manually */
- if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), NULL))
- return imap_search_parent_class->body_contains(f, argc, argv, s);
-
- /* optimise the match "" case - match everything */
- if (argc == 1 && argv[0]->value.string[0] == '\0') {
- if (s->current) {
- r = e_sexp_result_new(f, ESEXP_RES_BOOL);
- r->value.bool = TRUE;
- } else {
- r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR);
- r->value.ptrarray = g_ptr_array_new ();
- for (i = 0; i < s->summary->len; i++) {
- info = g_ptr_array_index(s->summary, i);
- g_ptr_array_add(r->value.ptrarray, (char *)camel_message_info_uid(info));
- }
- }
- } else if (argc == 0 || s->summary->len == 0) {
- /* nothing to match case, do nothing (should be handled higher up?) */
- if (s->current) {
- r = e_sexp_result_new(f, ESEXP_RES_BOOL);
- r->value.bool = FALSE;
- } else {
- r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR);
- r->value.ptrarray = g_ptr_array_new ();
- }
- } else {
- int truth = FALSE;
-
- /* setup lastuid/validity for synchronising */
- info = g_ptr_array_index(s->summary, s->summary->len-1);
- is->lastuid = strtoul(camel_message_info_uid(info), NULL, 10);
- is->validity = ((CamelImapSummary *)(s->folder->summary))->validity;
-
- mr = get_match(is, argc, argv);
-
- if (s->current) {
- uidn = strtoul(camel_message_info_uid(s->current), NULL, 10);
- uidp = (guint32 *)mr->matches->data;
- j = mr->matches->len;
- for (i=0;i<j && !truth;i++)
- truth = *uidp++ == uidn;
- r = e_sexp_result_new(f, ESEXP_RES_BOOL);
- r->value.bool = truth;
- } else {
- r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR);
- array = r->value.ptrarray = g_ptr_array_new();
-
- /* We use a hash to map the uid numbers to uid strings as required by the search api */
- /* We use the summary's strings so we dont need to alloc more */
- uid_hash = g_hash_table_new(NULL, NULL);
- for (i = 0; i < s->summary->len; i++) {
- info = s->summary->pdata[i];
- uid = (char *)camel_message_info_uid(info);
- uidn = strtoul(uid, NULL, 10);
- g_hash_table_insert(uid_hash, (void *)uidn, uid);
- }
-
- uidp = (guint32 *)mr->matches->data;
- j = mr->matches->len;
- for (i=0;i<j && !truth;i++) {
- uid = g_hash_table_lookup(uid_hash, (void *)*uidp++);
- if (uid)
- g_ptr_array_add(array, uid);
- }
-
- g_hash_table_destroy(uid_hash);
- }
- }
-
- return r;
-}
diff --git a/camel/providers/imap/camel-imap-search.h b/camel/providers/imap/camel-imap-search.h
deleted file mode 100644
index 7664c4c2ed..0000000000
--- a/camel/providers/imap/camel-imap-search.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-imap-search.h: IMAP folder search */
-
-/*
- * Authors:
- * Dan Winship <danw@ximian.com>
- *
- * 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.
- *
- */
-
-#ifndef _CAMEL_IMAP_SEARCH_H
-#define _CAMEL_IMAP_SEARCH_H
-
-#include <camel/camel-folder-search.h>
-#include <e-util/e-msgport.h>
-#include <camel/camel-data-cache.h>
-
-#define CAMEL_IMAP_SEARCH_TYPE (camel_imap_search_get_type ())
-#define CAMEL_IMAP_SEARCH(obj) CAMEL_CHECK_CAST (obj, camel_imap_search_get_type (), CamelImapSearch)
-#define CAMEL_IMAP_SEARCH_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imap_search_get_type (), CamelImapSearchClass)
-#define CAMEL_IS_IMAP_SEARCH(obj) CAMEL_CHECK_TYPE (obj, camel_imap_search_get_type ())
-
-typedef struct _CamelImapSearchClass CamelImapSearchClass;
-
-struct _CamelImapSearch {
- CamelFolderSearch parent;
-
- guint32 lastuid; /* current 'last uid' for the folder */
- guint32 validity; /* validity of the current folder */
-
- CamelDataCache *cache; /* disk-cache for searches */
-
- /* cache of body search matches */
- unsigned int matches_count;
- EDList matches;
- GHashTable *matches_hash;
-};
-
-struct _CamelImapSearchClass {
- CamelFolderSearchClass parent_class;
-
-};
-
-CamelType camel_imap_search_get_type (void);
-CamelFolderSearch *camel_imap_search_new (const char *cachedir);
-
-#endif /* ! _CAMEL_IMAP_SEARCH_H */
diff --git a/camel/providers/imap/camel-imap-store-summary.c b/camel/providers/imap/camel-imap-store-summary.c
deleted file mode 100644
index 4ba5bb9b68..0000000000
--- a/camel/providers/imap/camel-imap-store-summary.c
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- * Copyright (C) 2002 Ximian Inc.
- *
- * Authors: Michael Zucchi <notzed@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 <unistd.h>
-#include <ctype.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-#include "camel-imap-store-summary.h"
-
-#include "camel-file-utils.h"
-
-#include "hash-table-utils.h"
-#include "e-util/md5-utils.h"
-#include "e-util/e-memory.h"
-
-#include "camel-private.h"
-#include "camel-utf8.h"
-
-#define d(x)
-#define io(x) /* io debug */
-
-#define CAMEL_IMAP_STORE_SUMMARY_VERSION_0 (0)
-
-#define CAMEL_IMAP_STORE_SUMMARY_VERSION (0)
-
-#define _PRIVATE(o) (((CamelImapStoreSummary *)(o))->priv)
-
-static int summary_header_load(CamelStoreSummary *, FILE *);
-static int summary_header_save(CamelStoreSummary *, FILE *);
-
-/*static CamelStoreInfo * store_info_new(CamelStoreSummary *, const char *);*/
-static CamelStoreInfo * store_info_load(CamelStoreSummary *, FILE *);
-static int store_info_save(CamelStoreSummary *, FILE *, CamelStoreInfo *);
-static void store_info_free(CamelStoreSummary *, CamelStoreInfo *);
-
-static const char *store_info_string(CamelStoreSummary *, const CamelStoreInfo *, int);
-static void store_info_set_string(CamelStoreSummary *, CamelStoreInfo *, int, const char *);
-
-static void camel_imap_store_summary_class_init (CamelImapStoreSummaryClass *klass);
-static void camel_imap_store_summary_init (CamelImapStoreSummary *obj);
-static void camel_imap_store_summary_finalise (CamelObject *obj);
-
-static CamelStoreSummaryClass *camel_imap_store_summary_parent;
-
-static void
-camel_imap_store_summary_class_init (CamelImapStoreSummaryClass *klass)
-{
- CamelStoreSummaryClass *ssklass = (CamelStoreSummaryClass *)klass;
-
- ssklass->summary_header_load = summary_header_load;
- ssklass->summary_header_save = summary_header_save;
-
- /*ssklass->store_info_new = store_info_new;*/
- ssklass->store_info_load = store_info_load;
- ssklass->store_info_save = store_info_save;
- ssklass->store_info_free = store_info_free;
-
- ssklass->store_info_string = store_info_string;
- ssklass->store_info_set_string = store_info_set_string;
-}
-
-static void
-camel_imap_store_summary_init (CamelImapStoreSummary *s)
-{
- /*struct _CamelImapStoreSummaryPrivate *p;
-
- p = _PRIVATE(s) = g_malloc0(sizeof(*p));*/
-
- ((CamelStoreSummary *)s)->store_info_size = sizeof(CamelImapStoreInfo);
- s->version = CAMEL_IMAP_STORE_SUMMARY_VERSION;
-}
-
-static void
-camel_imap_store_summary_finalise (CamelObject *obj)
-{
- /*struct _CamelImapStoreSummaryPrivate *p;*/
- /*CamelImapStoreSummary *s = (CamelImapStoreSummary *)obj;*/
-
- /*p = _PRIVATE(obj);
- g_free(p);*/
-}
-
-CamelType
-camel_imap_store_summary_get_type (void)
-{
- static CamelType type = CAMEL_INVALID_TYPE;
-
- if (type == CAMEL_INVALID_TYPE) {
- camel_imap_store_summary_parent = (CamelStoreSummaryClass *)camel_store_summary_get_type();
- type = camel_type_register((CamelType)camel_imap_store_summary_parent, "CamelImapStoreSummary",
- sizeof (CamelImapStoreSummary),
- sizeof (CamelImapStoreSummaryClass),
- (CamelObjectClassInitFunc) camel_imap_store_summary_class_init,
- NULL,
- (CamelObjectInitFunc) camel_imap_store_summary_init,
- (CamelObjectFinalizeFunc) camel_imap_store_summary_finalise);
- }
-
- return type;
-}
-
-/**
- * camel_imap_store_summary_new:
- *
- * Create a new CamelImapStoreSummary object.
- *
- * Return value: A new CamelImapStoreSummary widget.
- **/
-CamelImapStoreSummary *
-camel_imap_store_summary_new (void)
-{
- CamelImapStoreSummary *new = CAMEL_IMAP_STORE_SUMMARY ( camel_object_new (camel_imap_store_summary_get_type ()));
-
- return new;
-}
-
-/**
- * camel_imap_store_summary_full_name:
- * @s:
- * @path:
- *
- * Retrieve a summary item by full name.
- *
- * A referenced to the summary item is returned, which may be
- * ref'd or free'd as appropriate.
- *
- * Return value: The summary item, or NULL if the @full_name name
- * is not available.
- * It must be freed using camel_store_summary_info_free().
- **/
-CamelImapStoreInfo *
-camel_imap_store_summary_full_name(CamelImapStoreSummary *s, const char *full_name)
-{
- int count, i;
- CamelImapStoreInfo *info;
-
- count = camel_store_summary_count((CamelStoreSummary *)s);
- for (i=0;i<count;i++) {
- info = (CamelImapStoreInfo *)camel_store_summary_index((CamelStoreSummary *)s, i);
- if (info) {
- if (strcmp(info->full_name, full_name) == 0)
- return info;
- camel_store_summary_info_free((CamelStoreSummary *)s, (CamelStoreInfo *)info);
- }
- }
-
- return NULL;
-}
-
-char *
-camel_imap_store_summary_full_to_path(CamelImapStoreSummary *s, const char *full_name, char dir_sep)
-{
- char *path, *p;
- int c;
- const char *f;
-
- if (dir_sep != '/') {
- p = path = alloca(strlen(full_name)*3+1);
- f = full_name;
- while ( (c = *f++ & 0xff) ) {
- if (c == dir_sep)
- *p++ = '/';
- else if (c == '/' || c == '%')
- p += sprintf(p, "%%%02X", c);
- else
- *p++ = c;
- }
- *p = 0;
- } else
- path = (char *)full_name;
-
- return camel_utf7_utf8(path);
-}
-
-static guint32 hexnib(guint32 c)
-{
- if (c >= '0' && c <= '9')
- return c-'0';
- else if (c>='A' && c <= 'Z')
- return c-'A'+10;
- else
- return 0;
-}
-
-char *
-camel_imap_store_summary_path_to_full(CamelImapStoreSummary *s, const char *path, char dir_sep)
-{
- unsigned char *full, *f;
- guint32 c, v = 0;
- const char *p;
- int state=0;
- char *subpath, *last = NULL;
- CamelStoreInfo *si;
-
- /* check to see if we have a subpath of path already defined */
- subpath = alloca(strlen(path)+1);
- strcpy(subpath, path);
- do {
- si = camel_store_summary_path((CamelStoreSummary *)s, subpath);
- if (si == NULL) {
- last = strrchr(subpath, '/');
- if (last)
- *last = 0;
- }
- } while (si == NULL && last);
-
- /* path is already present, use the raw version we have */
- if (si && strlen(subpath) == strlen(path)) {
- f = g_strdup(camel_imap_store_info_full_name(s, si));
- camel_store_summary_info_free((CamelStoreSummary *)s, si);
- return f;
- }
-
- f = full = alloca(strlen(path)*2+1);
- if (si)
- p = path + strlen(subpath);
- else
- p = path;
- while ( (c = camel_utf8_getc((const unsigned char **)&p)) ) {
- switch(state) {
- case 0:
- if (c == '%')
- state = 1;
- else {
- if (c == '/')
- c = dir_sep;
- camel_utf8_putc(&f, c);
- }
- break;
- case 1:
- state = 2;
- v = hexnib(c)<<4;
- break;
- case 2:
- state = 0;
- v |= hexnib(c);
- camel_utf8_putc(&f, v);
- break;
- }
- }
- camel_utf8_putc(&f, c);
-
- /* merge old path part if required */
- f = camel_utf8_utf7(full);
- if (si) {
- full = g_strdup_printf("%s%s", camel_imap_store_info_full_name(s, si), f);
- g_free(f);
- camel_store_summary_info_free((CamelStoreSummary *)s, si);
- f = full;
- }
-
- return f;
-}
-
-CamelImapStoreInfo *
-camel_imap_store_summary_add_from_full(CamelImapStoreSummary *s, const char *full_name, char dir_sep)
-{
- CamelImapStoreInfo *info;
- char *pathu8;
-
- d(printf("adding full name '%s' '%c'\n", full_name, dir_sep));
-
- info = camel_imap_store_summary_full_name(s, full_name);
- if (info) {
- camel_store_summary_info_free((CamelStoreSummary *)s, (CamelStoreInfo *)info);
- d(printf(" already there\n"));
- return info;
- }
-
- pathu8 = camel_imap_store_summary_full_to_path(s, full_name, dir_sep);
-
- info = (CamelImapStoreInfo *)camel_store_summary_add_from_path((CamelStoreSummary *)s, pathu8);
- if (info) {
- d(printf(" '%s' -> '%s'\n", pathu8, full_name));
- camel_store_info_set_string((CamelStoreSummary *)s, (CamelStoreInfo *)info, CAMEL_IMAP_STORE_INFO_FULL_NAME, full_name);
- } else
- d(printf(" failed\n"));
-
- return info;
-}
-
-/* should this be const? */
-char *
-camel_imap_store_summary_full_from_path(CamelImapStoreSummary *s, const char *path)
-{
- CamelImapStoreInfo *si;
-
- si = (CamelImapStoreInfo *)camel_store_summary_path((CamelStoreSummary *)s, path);
-
- d(printf("looking up path %s -> %s\n", path, si?si->full_name:"not found"));
-
- if (si)
- return g_strdup(si->full_name);
-
- return NULL;
-}
-
-/* TODO: this api needs some more work */
-CamelImapStoreNamespace *camel_imap_store_summary_namespace_new(CamelImapStoreSummary *s, const char *full_name, char dir_sep)
-{
- CamelImapStoreNamespace *ns;
-
- ns = g_malloc0(sizeof(*ns));
- ns->full_name = g_strdup(full_name);
- ns->sep = dir_sep;
- ns->path = camel_imap_store_summary_full_to_path(s, full_name, dir_sep);
-
- return ns;
-}
-
-void camel_imap_store_summary_namespace_set(CamelImapStoreSummary *s, CamelImapStoreNamespace *ns)
-{
- static void namespace_clear(CamelStoreSummary *s);
-
- namespace_clear((CamelStoreSummary *)s);
- s->namespace = ns;
- camel_store_summary_touch((CamelStoreSummary *)s);
-}
-
-static void
-namespace_free(CamelStoreSummary *s, CamelImapStoreNamespace *ns)
-{
- g_free(ns->path);
- g_free(ns->full_name);
- g_free(ns);
-}
-
-static void
-namespace_clear(CamelStoreSummary *s)
-{
- CamelImapStoreSummary *is = (CamelImapStoreSummary *)s;
-
- if (is->namespace)
- namespace_free(s, is->namespace);
- is->namespace = NULL;
-}
-
-static CamelImapStoreNamespace *
-namespace_load(CamelStoreSummary *s, FILE *in)
-{
- CamelImapStoreNamespace *ns;
- guint32 sep = '/';
-
- ns = g_malloc0(sizeof(*ns));
- if (camel_file_util_decode_string(in, &ns->path) == -1
- || camel_file_util_decode_string(in, &ns->full_name) == -1
- || camel_file_util_decode_uint32(in, &sep) == -1) {
- namespace_free(s, ns);
- ns = NULL;
- } else {
- ns->sep = sep;
- }
-
- return ns;
-}
-
-static int
-namespace_save(CamelStoreSummary *s, FILE *in, CamelImapStoreNamespace *ns)
-{
- if (camel_file_util_encode_string(in, ns->path) == -1
- || camel_file_util_encode_string(in, ns->full_name) == -1
- || camel_file_util_encode_uint32(in, (guint32)ns->sep) == -1)
- return -1;
-
- return 0;
-}
-
-static int
-summary_header_load(CamelStoreSummary *s, FILE *in)
-{
- CamelImapStoreSummary *is = (CamelImapStoreSummary *)s;
- gint32 version, capabilities, count;
-
- namespace_clear(s);
-
- if (camel_imap_store_summary_parent->summary_header_load((CamelStoreSummary *)s, in) == -1
- || camel_file_util_decode_fixed_int32(in, &version) == -1)
- return -1;
-
- is->version = version;
-
- if (version < CAMEL_IMAP_STORE_SUMMARY_VERSION_0) {
- g_warning("Store summary header version too low");
- return -1;
- }
-
- /* note file format can be expanded to contain more namespaces, but only 1 at the moment */
- if (camel_file_util_decode_fixed_int32(in, &capabilities) == -1
- || camel_file_util_decode_fixed_int32(in, &count) == -1
- || count > 1)
- return -1;
-
- is->capabilities = capabilities;
- if (count == 1) {
- if ((is->namespace = namespace_load(s, in)) == NULL)
- return -1;
- }
-
- return 0;
-}
-
-static int
-summary_header_save(CamelStoreSummary *s, FILE *out)
-{
- CamelImapStoreSummary *is = (CamelImapStoreSummary *)s;
- guint32 count;
-
- count = is->namespace?1:0;
-
- /* always write as latest version */
- if (camel_imap_store_summary_parent->summary_header_save((CamelStoreSummary *)s, out) == -1
- || camel_file_util_encode_fixed_int32(out, CAMEL_IMAP_STORE_SUMMARY_VERSION) == -1
- || camel_file_util_encode_fixed_int32(out, is->capabilities) == -1
- || camel_file_util_encode_fixed_int32(out, count) == -1)
- return -1;
-
- if (is->namespace && namespace_save(s, out, is->namespace) == -1)
- return -1;
-
- return 0;
-}
-
-static CamelStoreInfo *
-store_info_load(CamelStoreSummary *s, FILE *in)
-{
- CamelImapStoreInfo *mi;
-
- mi = (CamelImapStoreInfo *)camel_imap_store_summary_parent->store_info_load(s, in);
- if (mi) {
- if (camel_file_util_decode_string(in, &mi->full_name) == -1) {
- camel_store_summary_info_free(s, (CamelStoreInfo *)mi);
- mi = NULL;
- }
- }
-
- return (CamelStoreInfo *)mi;
-}
-
-static int
-store_info_save(CamelStoreSummary *s, FILE *out, CamelStoreInfo *mi)
-{
- CamelImapStoreInfo *isi = (CamelImapStoreInfo *)mi;
-
- if (camel_imap_store_summary_parent->store_info_save(s, out, mi) == -1
- || camel_file_util_encode_string(out, isi->full_name) == -1)
- return -1;
-
- return 0;
-}
-
-static void
-store_info_free(CamelStoreSummary *s, CamelStoreInfo *mi)
-{
- CamelImapStoreInfo *isi = (CamelImapStoreInfo *)mi;
-
- g_free(isi->full_name);
- camel_imap_store_summary_parent->store_info_free(s, mi);
-}
-
-static const char *
-store_info_string(CamelStoreSummary *s, const CamelStoreInfo *mi, int type)
-{
- CamelImapStoreInfo *isi = (CamelImapStoreInfo *)mi;
-
- /* FIXME: Locks? */
-
- g_assert (mi != NULL);
-
- switch (type) {
- case CAMEL_IMAP_STORE_INFO_FULL_NAME:
- return isi->full_name;
- default:
- return camel_imap_store_summary_parent->store_info_string(s, mi, type);
- }
-}
-
-static void
-store_info_set_string(CamelStoreSummary *s, CamelStoreInfo *mi, int type, const char *str)
-{
- CamelImapStoreInfo *isi = (CamelImapStoreInfo *)mi;
-
- g_assert(mi != NULL);
-
- switch(type) {
- case CAMEL_IMAP_STORE_INFO_FULL_NAME:
- d(printf("Set full name %s -> %s\n", isi->full_name, str));
- CAMEL_STORE_SUMMARY_LOCK(s, summary_lock);
- g_free(isi->full_name);
- isi->full_name = g_strdup(str);
- CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock);
- break;
- default:
- camel_imap_store_summary_parent->store_info_set_string(s, mi, type, str);
- break;
- }
-}
diff --git a/camel/providers/imap/camel-imap-store-summary.h b/camel/providers/imap/camel-imap-store-summary.h
deleted file mode 100644
index 013283b5c1..0000000000
--- a/camel/providers/imap/camel-imap-store-summary.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2002 Ximian Inc.
- *
- * Authors: Michael Zucchi <notzed@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.
- */
-
-
-#ifndef _CAMEL_IMAP_STORE_SUMMARY_H
-#define _CAMEL_IMAP_STORE_SUMMARY_H
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#include <camel/camel-object.h>
-#include <camel/camel-store-summary.h>
-
-#define CAMEL_IMAP_STORE_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_imap_store_summary_get_type (), CamelImapStoreSummary)
-#define CAMEL_IMAP_STORE_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imap_store_summary_get_type (), CamelImapStoreSummaryClass)
-#define CAMEL_IS_IMAP_STORE_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_imap_store_summary_get_type ())
-
-typedef struct _CamelImapStoreSummary CamelImapStoreSummary;
-typedef struct _CamelImapStoreSummaryClass CamelImapStoreSummaryClass;
-
-typedef struct _CamelImapStoreInfo CamelImapStoreInfo;
-
-enum {
- CAMEL_IMAP_STORE_INFO_FULL_NAME = CAMEL_STORE_INFO_LAST,
- CAMEL_IMAP_STORE_INFO_LAST,
-};
-
-struct _CamelImapStoreInfo {
- CamelStoreInfo info;
- char *full_name;
-};
-
-typedef struct _CamelImapStoreNamespace CamelImapStoreNamespace;
-
-struct _CamelImapStoreNamespace {
- char *path; /* display path */
- char *full_name; /* real name */
- char sep; /* directory separator */
-};
-
-struct _CamelImapStoreSummary {
- CamelStoreSummary summary;
-
- struct _CamelImapStoreSummaryPrivate *priv;
-
- /* header info */
- guint32 version; /* version of base part of file */
- guint32 capabilities;
- CamelImapStoreNamespace *namespace; /* eventually to be a list */
-};
-
-struct _CamelImapStoreSummaryClass {
- CamelStoreSummaryClass summary_class;
-};
-
-CamelType camel_imap_store_summary_get_type (void);
-CamelImapStoreSummary *camel_imap_store_summary_new (void);
-
-/* TODO: this api needs some more work */
-CamelImapStoreNamespace *camel_imap_store_summary_namespace_new(CamelImapStoreSummary *s, const char *full_name, char dir_sep);
-void camel_imap_store_summary_namespace_set(CamelImapStoreSummary *s, CamelImapStoreNamespace *ns);
-
-/* converts to/from utf8 canonical nasmes */
-char *camel_imap_store_summary_full_to_path(CamelImapStoreSummary *s, const char *full_name, char dir_sep);
-char *camel_imap_store_summary_path_to_full(CamelImapStoreSummary *s, const char *path, char dir_sep);
-
-CamelImapStoreInfo *camel_imap_store_summary_full_name(CamelImapStoreSummary *s, const char *full_name);
-CamelImapStoreInfo *camel_imap_store_summary_add_from_full(CamelImapStoreSummary *s, const char *full_name, char dir_sep);
-
-/* a convenience lookup function. always use this if path known */
-char *camel_imap_store_summary_full_from_path(CamelImapStoreSummary *s, const char *path);
-
-/* helper macro's */
-#define camel_imap_store_info_full_name(s, i) (camel_store_info_string((CamelStoreSummary *)s, (const CamelStoreInfo *)i, CAMEL_IMAP_STORE_INFO_FULL_NAME))
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* ! _CAMEL_IMAP_STORE_SUMMARY_H */
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
deleted file mode 100644
index af4192e0c6..0000000000
--- a/camel/providers/imap/camel-imap-store.c
+++ /dev/null
@@ -1,2607 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-imap-store.c : class for an imap store */
-
-/*
- * Authors:
- * Dan Winship <danw@ximian.com>
- * Jeffrey Stedfast <fejj@ximian.com>
- *
- * Copyright 2000, 2001 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.
- *
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include "e-util/e-path.h"
-
-#include "camel-imap-store.h"
-#include "camel-imap-store-summary.h"
-#include "camel-imap-folder.h"
-#include "camel-imap-utils.h"
-#include "camel-imap-command.h"
-#include "camel-imap-summary.h"
-#include "camel-imap-message-cache.h"
-#include "camel-disco-diary.h"
-#include "camel-file-utils.h"
-#include "camel-folder.h"
-#include "camel-exception.h"
-#include "camel-session.h"
-#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 "camel-utf8.h"
-#include "string-utils.h"
-
-#include "camel-imap-private.h"
-#include "camel-private.h"
-
-#define d(x)
-
-/* Specified in RFC 2060 */
-#define IMAP_PORT 143
-#define SIMAP_PORT 993
-
-
-extern int camel_verbose_debug;
-
-static CamelDiscoStoreClass *parent_class = NULL;
-
-static char imap_tag_prefix = 'A';
-
-static void construct (CamelService *service, CamelSession *session,
- CamelProvider *provider, CamelURL *url,
- CamelException *ex);
-
-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);
-static gboolean imap_disconnect_online (CamelService *service, gboolean clean, CamelException *ex);
-static gboolean imap_disconnect_offline (CamelService *service, gboolean clean, CamelException *ex);
-static void imap_noop (CamelStore *store, CamelException *ex);
-static GList *query_auth_types (CamelService *service, CamelException *ex);
-static guint hash_folder_name (gconstpointer key);
-static gint compare_folder_name (gconstpointer a, gconstpointer b);
-static CamelFolder *get_folder_online (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex);
-static CamelFolder *get_folder_offline (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex);
-static CamelFolderInfo *create_folder (CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex);
-static void delete_folder (CamelStore *store, const char *folder_name, CamelException *ex);
-static void rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex);
-static CamelFolderInfo *get_folder_info_online (CamelStore *store,
- const char *top,
- guint32 flags,
- CamelException *ex);
-static CamelFolderInfo *get_folder_info_offline (CamelStore *store,
- const char *top,
- guint32 flags,
- CamelException *ex);
-static gboolean folder_subscribed (CamelStore *store, const char *folder_name);
-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 get_folders_online (CamelImapStore *imap_store, const char *pattern,
- GPtrArray *folders, gboolean lsub, CamelException *ex);
-
-
-static void imap_folder_effectively_unsubscribed(CamelImapStore *imap_store, const char *folder_name, CamelException *ex);
-static gboolean imap_check_folder_still_extant (CamelImapStore *imap_store, const char *full_name, CamelException *ex);
-static void imap_forget_folder(CamelImapStore *imap_store, const char *folder_name, CamelException *ex);
-static void imap_set_server_level (CamelImapStore *store);
-
-static void
-camel_imap_store_class_init (CamelImapStoreClass *camel_imap_store_class)
-{
- CamelObjectClass *camel_object_class =
- CAMEL_OBJECT_CLASS (camel_imap_store_class);
- CamelServiceClass *camel_service_class =
- CAMEL_SERVICE_CLASS (camel_imap_store_class);
- CamelStoreClass *camel_store_class =
- CAMEL_STORE_CLASS (camel_imap_store_class);
- CamelDiscoStoreClass *camel_disco_store_class =
- CAMEL_DISCO_STORE_CLASS (camel_imap_store_class);
-
- 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;
- camel_store_class->create_folder = create_folder;
- camel_store_class->delete_folder = delete_folder;
- camel_store_class->rename_folder = rename_folder;
- camel_store_class->free_folder_info = camel_store_free_folder_info_full;
- camel_store_class->folder_subscribed = folder_subscribed;
- camel_store_class->subscribe_folder = subscribe_folder;
- camel_store_class->unsubscribe_folder = unsubscribe_folder;
- camel_store_class->noop = imap_noop;
-
- 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;
- camel_disco_store_class->disconnect_online = imap_disconnect_online;
- camel_disco_store_class->disconnect_offline = imap_disconnect_offline;
- camel_disco_store_class->get_folder_online = get_folder_online;
- camel_disco_store_class->get_folder_offline = get_folder_offline;
- camel_disco_store_class->get_folder_resyncing = get_folder_online;
- camel_disco_store_class->get_folder_info_online = get_folder_info_online;
- camel_disco_store_class->get_folder_info_offline = get_folder_info_offline;
- camel_disco_store_class->get_folder_info_resyncing = get_folder_info_online;
-}
-
-static gboolean
-free_key (gpointer key, gpointer value, gpointer user_data)
-{
- g_free (key);
- return TRUE;
-}
-
-static void
-camel_imap_store_finalize (CamelObject *object)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (object);
-
- /* This frees current_folder, folders, authtypes, streams, and namespace. */
- camel_service_disconnect((CamelService *)imap_store, TRUE, NULL);
-
- if (imap_store->summary) {
- camel_store_summary_save((CamelStoreSummary *)imap_store->summary);
- camel_object_unref(imap_store->summary);
- }
-
- 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_thread_destroy (imap_store->async_thread);
-#endif
-}
-
-#ifdef ENABLE_THREADS
-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);
-}
-
-static void async_received(EThread *et, EMsg *em, void *data)
-{
- CamelImapStore *imap_store = data;
- CamelImapMsg *msg = (CamelImapMsg *)em;
-
- if (msg->receive)
- msg->receive(imap_store, msg);
-}
-
-CamelImapMsg *camel_imap_msg_new(void (*receive)(CamelImapStore *store, struct _CamelImapMsg *m),
- void (*free)(CamelImapStore *store, struct _CamelImapMsg *m),
- size_t size)
-{
- CamelImapMsg *msg;
-
- g_assert(size >= sizeof(*msg));
-
- msg = g_malloc0(size);
- msg->receive = receive;
- msg->free = free;
-
- return msg;
-}
-
-void camel_imap_msg_queue(CamelImapStore *store, CamelImapMsg *msg)
-{
- e_thread_put(store->async_thread, (EMsg *)msg);
-}
-
-#endif
-
-static void
-camel_imap_store_init (gpointer object, gpointer klass)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (object);
-
- imap_store->istream = NULL;
- imap_store->ostream = NULL;
-
- imap_store->dir_sep = '\0';
- imap_store->current_folder = NULL;
- imap_store->connected = FALSE;
-
- imap_store->tag_prefix = imap_tag_prefix++;
- if (imap_tag_prefix > 'Z')
- imap_tag_prefix = 'A';
-
-#ifdef ENABLE_THREADS
- imap_store->async_thread = e_thread_new(E_THREAD_QUEUE);
- e_thread_set_msg_destroy(imap_store->async_thread, async_destroy, imap_store);
- e_thread_set_msg_received(imap_store->async_thread, async_received, imap_store);
-#endif /* ENABLE_THREADS */
-}
-
-CamelType
-camel_imap_store_get_type (void)
-{
- static CamelType camel_imap_store_type = CAMEL_INVALID_TYPE;
-
- if (camel_imap_store_type == CAMEL_INVALID_TYPE) {
- camel_imap_store_type =
- camel_type_register (CAMEL_DISCO_STORE_TYPE,
- "CamelImapStore",
- sizeof (CamelImapStore),
- sizeof (CamelImapStoreClass),
- (CamelObjectClassInitFunc) camel_imap_store_class_init,
- NULL,
- (CamelObjectInitFunc) camel_imap_store_init,
- (CamelObjectFinalizeFunc) camel_imap_store_finalize);
- }
-
- return camel_imap_store_type;
-}
-
-static void
-construct (CamelService *service, CamelSession *session,
- CamelProvider *provider, CamelURL *url,
- CamelException *ex)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (service);
- CamelStore *store = CAMEL_STORE (service);
- char *tmp;
- CamelURL *summary_url;
-
- CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex);
- if (camel_exception_is_set (ex))
- return;
-
- imap_store->storage_path = camel_session_get_storage_path (session, service, ex);
- if (!imap_store->storage_path)
- return;
-
- /* FIXME */
- imap_store->base_url = camel_url_to_string (service->url, (CAMEL_URL_HIDE_PASSWORD |
- CAMEL_URL_HIDE_PARAMS |
- CAMEL_URL_HIDE_AUTH));
-
- imap_store->parameters = 0;
- if (camel_url_get_param (url, "use_lsub"))
- store->flags |= CAMEL_STORE_SUBSCRIPTIONS;
- if (camel_url_get_param (url, "namespace")) {
- imap_store->parameters |= IMAP_PARAM_OVERRIDE_NAMESPACE;
- g_free(imap_store->namespace);
- imap_store->namespace = g_strdup (camel_url_get_param (url, "namespace"));
- }
- if (camel_url_get_param (url, "check_all"))
- imap_store->parameters |= IMAP_PARAM_CHECK_ALL;
- if (camel_url_get_param (url, "filter")) {
- imap_store->parameters |= IMAP_PARAM_FILTER_INBOX;
- store->flags |= CAMEL_STORE_FILTER_INBOX;
- }
-
- /* setup/load the store summary */
- tmp = alloca(strlen(imap_store->storage_path)+32);
- sprintf(tmp, "%s/.ev-store-summary", imap_store->storage_path);
- imap_store->summary = camel_imap_store_summary_new();
- camel_store_summary_set_filename((CamelStoreSummary *)imap_store->summary, tmp);
- summary_url = camel_url_new(imap_store->base_url, NULL);
- camel_store_summary_set_uri_base((CamelStoreSummary *)imap_store->summary, summary_url);
- camel_url_free(summary_url);
- if (camel_store_summary_load((CamelStoreSummary *)imap_store->summary) == 0) {
- CamelImapStoreSummary *is = imap_store->summary;
-
- if (is->namespace) {
- /* if namespace has changed, clear folder list */
- if (imap_store->namespace && strcmp(imap_store->namespace, is->namespace->full_name) != 0) {
- camel_store_summary_clear((CamelStoreSummary *)is);
- } else {
- imap_store->namespace = g_strdup(is->namespace->full_name);
- imap_store->dir_sep = is->namespace->sep;
- store->dir_sep = is->namespace->sep;
- }
- }
-
- imap_store->capabilities = is->capabilities;
- imap_set_server_level(imap_store);
- }
-}
-
-static int
-imap_setv (CamelObject *object, CamelException *ex, CamelArgV *args)
-{
- CamelImapStore *store = (CamelImapStore *) object;
- guint32 tag, flags;
- 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_IMAP_STORE_ARG_FIRST ||
- (tag & CAMEL_ARG_TAG) >= CAMEL_IMAP_STORE_ARG_FIRST + 100)
- continue;
-
- if (tag == CAMEL_IMAP_STORE_NAMESPACE) {
- if (strcmp (store->namespace, args->argv[i].ca_str) != 0) {
- g_free (store->namespace);
- store->namespace = g_strdup (args->argv[i].ca_str);
- /* the current imap code will need to do a reconnect for this to take effect */
- /*reconnect = TRUE;*/
- }
- } else if (tag == CAMEL_IMAP_STORE_OVERRIDE_NAMESPACE) {
- flags = args->argv[i].ca_int ? IMAP_PARAM_OVERRIDE_NAMESPACE : 0;
- flags |= (store->parameters & ~IMAP_PARAM_OVERRIDE_NAMESPACE);
-
- if (store->parameters != flags) {
- store->parameters = flags;
- /* the current imap code will need to do a reconnect for this to take effect */
- /*reconnect = TRUE;*/
- }
- } else if (tag == CAMEL_IMAP_STORE_CHECK_ALL) {
- flags = args->argv[i].ca_int ? IMAP_PARAM_CHECK_ALL : 0;
- flags |= (store->parameters & ~IMAP_PARAM_CHECK_ALL);
- store->parameters = flags;
- /* no need to reconnect for this option to take effect... */
- } else if (tag == CAMEL_IMAP_STORE_FILTER_INBOX) {
- flags = args->argv[i].ca_int ? IMAP_PARAM_FILTER_INBOX : 0;
- flags |= (store->parameters & ~IMAP_PARAM_FILTER_INBOX);
- store->parameters = flags;
- /* no need to reconnect for this option to take effect... */
- } else {
- /* error?? */
- continue;
- }
-
- /* let our parent know that we've handled this arg */
- camel_argv_ignore (args, i);
- }
-
- /* FIXME: if we need to reconnect for a change to take affect,
- we need to do it here... or, better yet, somehow chain it
- up to CamelService's setv implementation. */
-
- return CAMEL_OBJECT_CLASS (parent_class)->setv (object, ex, args);
-}
-
-static int
-imap_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args)
-{
- CamelImapStore *store = (CamelImapStore *) object;
- 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_IMAP_STORE_ARG_FIRST ||
- (tag & CAMEL_ARG_TAG) >= CAMEL_IMAP_STORE_ARG_FIRST + 100)
- continue;
-
- switch (tag) {
- case CAMEL_IMAP_STORE_NAMESPACE:
- /* get the username */
- *args->argv[i].ca_str = store->namespace;
- break;
- case CAMEL_IMAP_STORE_OVERRIDE_NAMESPACE:
- /* get the auth mechanism */
- *args->argv[i].ca_int = store->parameters & IMAP_PARAM_OVERRIDE_NAMESPACE ? TRUE : FALSE;
- break;
- case CAMEL_IMAP_STORE_CHECK_ALL:
- /* get the hostname */
- *args->argv[i].ca_int = store->parameters & IMAP_PARAM_CHECK_ALL ? TRUE : FALSE;
- break;
- case CAMEL_IMAP_STORE_FILTER_INBOX:
- /* get the port */
- *args->argv[i].ca_int = store->parameters & IMAP_PARAM_FILTER_INBOX ? TRUE : FALSE;
- break;
- default:
- /* error? */
- }
- }
-
- 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
-imap_set_server_level (CamelImapStore *store)
-{
- if (store->capabilities & IMAP_CAPABILITY_IMAP4REV1) {
- store->server_level = IMAP_LEVEL_IMAP4REV1;
- store->capabilities |= IMAP_CAPABILITY_STATUS;
- } else if (store->capabilities & IMAP_CAPABILITY_IMAP4)
- store->server_level = IMAP_LEVEL_IMAP4;
- else
- store->server_level = IMAP_LEVEL_UNKNOWN;
-}
-
-static struct {
- const char *name;
- guint32 flag;
-} capabilities[] = {
- { "IMAP4", IMAP_CAPABILITY_IMAP4 },
- { "IMAP4REV1", IMAP_CAPABILITY_IMAP4REV1 },
- { "STATUS", IMAP_CAPABILITY_STATUS },
- { "NAMESPACE", IMAP_CAPABILITY_NAMESPACE },
- { "UIDPLUS", IMAP_CAPABILITY_UIDPLUS },
- { "LITERAL+", IMAP_CAPABILITY_LITERALPLUS },
- { "STARTTLS", IMAP_CAPABILITY_STARTTLS },
- { NULL, 0 }
-};
-
-
-static gboolean
-imap_get_capability (CamelService *service, CamelException *ex)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (service);
- CamelImapResponse *response;
- char *result, *capa, *lasts;
- int i;
-
- CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock);
-
- /* Find out the IMAP capabilities */
- /* We assume we have utf8 capable search until a failed search tells us otherwise */
- store->capabilities = IMAP_CAPABILITY_utf8_search;
- store->authtypes = g_hash_table_new (g_str_hash, g_str_equal);
- response = camel_imap_command (store, NULL, ex, "CAPABILITY");
- if (!response)
- return FALSE;
- 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;
- capa = strtok_r (NULL, " ", &lasts)) {
- if (!strncmp (capa, "AUTH=", 5)) {
- g_hash_table_insert (store->authtypes,
- g_strdup (capa + 5),
- GINT_TO_POINTER (1));
- continue;
- }
- for (i = 0; capabilities[i].name; i++) {
- if (g_strcasecmp (capa, capabilities[i].name) == 0) {
- store->capabilities |= capabilities[i].flag;
- break;
- }
- }
- }
- g_free (result);
-
- imap_set_server_level (store);
-
- if (store->summary->capabilities != store->capabilities) {
- store->summary->capabilities = store->capabilities;
- camel_store_summary_touch((CamelStoreSummary *)store->summary);
- camel_store_summary_save((CamelStoreSummary *)store->summary);
- }
-
- 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));
-
- camel_object_unref (CAMEL_OBJECT (tcp_stream));
-
- 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_readline (store, &buf, ex) < 0) {
- 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;
- }
-
- store->connected = FALSE;
- return FALSE;
- }
- g_free (buf);
-
- /* get the imap server capabilities */
- if (!imap_get_capability (service, ex)) {
- 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;
- }
-
- store->connected = FALSE;
- 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");
- if (response)
- 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 *
-query_auth_types (CamelService *service, CamelException *ex)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (service);
- CamelServiceAuthType *authtype;
- GList *sasl_types, *t, *next;
- gboolean connected;
-
- if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex))
- return NULL;
-
- CAMEL_SERVICE_LOCK (store, connect_lock);
- connected = connect_to_server_wrapper (service, ex);
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
- if (!connected)
- return NULL;
-
- 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);
- }
- }
-
- return g_list_prepend (sasl_types, &camel_imap_password_authtype);
-}
-
-/* folder_name is path name */
-static CamelFolderInfo *
-imap_build_folder_info(CamelImapStore *imap_store, const char *folder_name)
-{
- CamelURL *url;
- const char *name;
- CamelFolderInfo *fi;
-
- fi = g_malloc0(sizeof(*fi));
-
- fi->full_name = g_strdup(folder_name);
- fi->unread_message_count = 0;
-
- url = camel_url_new (imap_store->base_url, NULL);
- g_free (url->path);
- url->path = g_strdup_printf ("/%s", folder_name);
- fi->url = camel_url_to_string (url, CAMEL_URL_HIDE_ALL);
- camel_url_free(url);
- fi->path = g_strdup_printf("/%s", folder_name);
- name = strrchr (fi->path, '/');
- if (name)
- name++;
- else
- name = fi->path;
-
- fi->name = g_strdup (name);
-
- return fi;
-}
-
-static void
-imap_folder_effectively_unsubscribed(CamelImapStore *imap_store,
- const char *folder_name, CamelException *ex)
-{
- CamelFolderInfo *fi;
- CamelStoreInfo *si;
-
- si = camel_store_summary_path((CamelStoreSummary *)imap_store->summary, folder_name);
- if (si) {
- if (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) {
- si->flags &= ~CAMEL_STORE_INFO_FOLDER_SUBSCRIBED;
- camel_store_summary_touch((CamelStoreSummary *)imap_store->summary);
- camel_store_summary_save((CamelStoreSummary *)imap_store->summary);
- }
- camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si);
- }
-
- if (imap_store->renaming) {
- /* we don't need to emit a "folder_unsubscribed" signal
- if we are in the process of renaming folders, so we
- are done here... */
- return;
-
- }
-
- fi = imap_build_folder_info(imap_store, folder_name);
- camel_object_trigger_event (CAMEL_OBJECT (imap_store), "folder_unsubscribed", fi);
- camel_folder_info_free (fi);
-}
-
-static void
-imap_forget_folder (CamelImapStore *imap_store, const char *folder_name, CamelException *ex)
-{
- CamelFolderSummary *summary;
- CamelImapMessageCache *cache;
- char *summary_file;
- char *journal_file;
- char *folder_dir, *storage_path;
- CamelFolderInfo *fi;
- const char *name;
-
- name = strrchr (folder_name, imap_store->dir_sep);
- if (name)
- name++;
- else
- name = folder_name;
-
- storage_path = g_strdup_printf ("%s/folders", imap_store->storage_path);
- folder_dir = e_path_to_physical (storage_path, folder_name);
- g_free (storage_path);
- if (access (folder_dir, F_OK) != 0) {
- g_free (folder_dir);
- goto event;
- }
-
- summary_file = g_strdup_printf ("%s/summary", folder_dir);
- summary = camel_imap_summary_new (summary_file);
- if (!summary) {
- g_free (summary_file);
- g_free (folder_dir);
- goto event;
- }
-
- cache = camel_imap_message_cache_new (folder_dir, summary, ex);
- if (cache)
- camel_imap_message_cache_clear (cache);
-
- camel_object_unref (CAMEL_OBJECT (cache));
- camel_object_unref (CAMEL_OBJECT (summary));
-
- unlink (summary_file);
- g_free (summary_file);
-
- journal_file = g_strdup_printf ("%s/summary", folder_dir);
- unlink (journal_file);
- g_free (journal_file);
-
- rmdir (folder_dir);
- g_free (folder_dir);
-
- event:
-
- camel_store_summary_remove_path((CamelStoreSummary *)imap_store->summary, folder_name);
- camel_store_summary_save((CamelStoreSummary *)imap_store->summary);
-
- fi = imap_build_folder_info(imap_store, folder_name);
- camel_object_trigger_event (CAMEL_OBJECT (imap_store), "folder_deleted", fi);
- camel_folder_info_free (fi);
-}
-
-static gboolean
-imap_check_folder_still_extant (CamelImapStore *imap_store, const char *full_name,
- CamelException *ex)
-{
- CamelImapResponse *response;
-
- response = camel_imap_command (imap_store, NULL, ex, "LIST \"\" %S",
- full_name);
-
- if (response) {
- gboolean stillthere = FALSE;
-
- if (response->untagged->len)
- stillthere = TRUE;
-
- camel_imap_response_free_without_processing (imap_store, response);
-
- if (stillthere)
- return TRUE;
- }
-
- /* either LIST command was rejected or it gave no results,
- * we can be sure that the folder is gone. */
-
- camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID,
- _("The folder %s no longer exists"),
- full_name);
- return FALSE;
-}
-
-static void
-copy_folder(char *key, CamelFolder *folder, GPtrArray *out)
-{
- g_ptr_array_add(out, folder);
- camel_object_ref((CamelObject *)folder);
-}
-
-/* This is a little 'hack' to avoid the deadlock conditions that would otherwise
- ensue when calling camel_folder_refresh_info from inside a lock */
-/* NB: on second thougts this is probably not entirely safe, but it'll do for now */
-/* No, its definetly not safe. So its been changed to copy the folders first */
-/* the alternative is to:
- make the camel folder->lock recursive (which should probably be done)
- or remove it from camel_folder_refresh_info, and use another locking mechanism */
-/* also see get_folder_info_online() for the same hack repeated */
-static void
-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++) {
- 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);
-
- if (camel_exception_is_set (ex) &&
- imap_check_folder_still_extant (store, folder->full_name, ex) == FALSE) {
- gchar *namedup;
-
- /* the folder was deleted (may happen when we come back online
- * after being offline */
-
- namedup = g_strdup (folder->full_name);
- camel_object_unref((CamelObject *)folder);
- imap_folder_effectively_unsubscribed (store, namedup, ex);
- imap_forget_folder (store, namedup, ex);
- camel_exception_clear (ex);
- g_free (namedup);
- } else
- camel_object_unref((CamelObject *)folder);
- }
-
- g_ptr_array_free (folders, TRUE);
-}
-
-static gboolean
-try_auth (CamelImapStore *store, const char *mech, CamelException *ex)
-{
- CamelSasl *sasl;
- CamelImapResponse *response;
- char *resp;
- char *sasl_resp;
-
- CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock);
-
- response = camel_imap_command (store, NULL, ex, "AUTHENTICATE %s", mech);
- if (!response)
- return FALSE;
-
- sasl = camel_sasl_new ("imap", mech, CAMEL_SERVICE (store));
- while (!camel_sasl_authenticated (sasl)) {
- resp = camel_imap_response_extract_continuation (store, response, ex);
- if (!resp)
- goto lose;
-
- sasl_resp = camel_sasl_challenge_base64 (sasl, imap_next_word (resp), ex);
- g_free (resp);
- if (camel_exception_is_set (ex))
- goto break_and_lose;
-
- response = camel_imap_command_continuation (store, sasl_resp, strlen (sasl_resp), ex);
- g_free (sasl_resp);
- if (!response)
- goto lose;
- }
-
- resp = camel_imap_response_extract_continuation (store, response, NULL);
- if (resp) {
- /* Oops. SASL claims we're done, but the IMAP server
- * doesn't think so...
- */
- g_free (resp);
- goto lose;
- }
-
- camel_object_unref (CAMEL_OBJECT (sasl));
-
- return TRUE;
-
- break_and_lose:
- /* Get the server out of "waiting for continuation data" mode. */
- response = camel_imap_command_continuation (store, "*", 1, NULL);
- if (response)
- camel_imap_response_free (store, response);
-
- lose:
- if (!camel_exception_is_set (ex)) {
- camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
- _("Bad authentication response from server."));
- }
-
- camel_object_unref (CAMEL_OBJECT (sasl));
-
- return FALSE;
-}
-
-static gboolean
-imap_auth_loop (CamelService *service, CamelException *ex)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (service);
- CamelSession *session = camel_service_get_session (service);
- CamelServiceAuthType *authtype = NULL;
- CamelImapResponse *response;
- char *errbuf = NULL;
- gboolean authenticated = FALSE;
-
- CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock);
-
- if (service->url->authmech) {
- if (!g_hash_table_lookup (store->authtypes, service->url->authmech)) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
- _("IMAP server %s does not support requested "
- "authentication type %s"),
- service->url->host,
- service->url->authmech);
- return FALSE;
- }
-
- authtype = camel_sasl_authtype (service->url->authmech);
- if (!authtype) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
- _("No support for authentication type %s"),
- 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 */
- camel_session_forget_password (
- session, service, "password", 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 : "",
- service->url->user,
- service->url->host);
- service->url->passwd =
- camel_session_get_password (
- session, prompt, TRUE,
- service, "password", 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_wrapper (service, ex))
- return FALSE;
- }
-
- if (authtype)
- authenticated = try_auth (store, authtype->authproto, ex);
- else {
- response = camel_imap_command (store, NULL, ex,
- "LOGIN %S %S",
- service->url->user,
- service->url->passwd);
- if (response) {
- camel_imap_response_free (store, response);
- authenticated = TRUE;
- }
- }
- 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;
-}
-
-static gboolean
-can_work_offline (CamelDiscoStore *disco_store)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (disco_store);
-
- return camel_store_summary_count((CamelStoreSummary *)store->summary) != 0;
-}
-
-static gboolean
-imap_connect_online (CamelService *service, CamelException *ex)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (service);
- CamelDiscoStore *disco_store = CAMEL_DISCO_STORE (service);
- CamelImapResponse *response;
- struct _namespaces *namespaces;
- char *result, *name, *path;
- int i;
- size_t len;
- CamelImapStoreNamespace *ns;
-
- CAMEL_SERVICE_LOCK (store, connect_lock);
- if (!connect_to_server_wrapper (service, ex) ||
- !imap_auth_loop (service, ex)) {
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
- camel_service_disconnect (service, TRUE, NULL);
- return FALSE;
- }
-
- /* 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;
-
- /* new code... */
- namespaces = imap_parse_namespace_response (result);
- imap_namespaces_destroy (namespaces);
- /* end new code */
-
- name = strstrcase (result, "NAMESPACE ((");
- if (name) {
- char *sep;
-
- name += 12;
- store->namespace = imap_parse_string ((const char **) &name, &len);
- if (name && *name++ == ' ') {
- sep = imap_parse_string ((const char **) &name, &len);
- if (sep) {
- store->dir_sep = *sep;
- ((CamelStore *)store)->dir_sep = store->dir_sep;
- g_free (sep);
- }
- }
- }
- g_free (result);
- }
-
- if (!store->namespace)
- store->namespace = g_strdup ("");
-
- if (!store->dir_sep) {
- if (store->server_level >= IMAP_LEVEL_IMAP4REV1) {
- /* This idiom means "tell me the hierarchy separator
- * for the given path, even if that path doesn't exist.
- */
- response = camel_imap_command (store, NULL, ex,
- "LIST %S \"\"",
- store->namespace);
- } else {
- /* Plain IMAP4 doesn't have that idiom, so we fall back
- * to "tell me about this folder", which will fail if
- * the folder doesn't exist (eg, if namespace is "").
- */
- response = camel_imap_command (store, NULL, ex,
- "LIST \"\" %S",
- store->namespace);
- }
- if (!response)
- goto done;
-
- result = camel_imap_response_extract (store, response, "LIST", NULL);
- if (result) {
- imap_parse_list_response (store, result, NULL, &store->dir_sep, NULL);
- g_free (result);
- }
- if (!store->dir_sep) {
- store->dir_sep = '/'; /* Guess */
- ((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) {
- gchar *tmp;
-
- tmp = g_strdup_printf ("%s%c", store->namespace, store->dir_sep);
- g_free (store->namespace);
- store->namespace = tmp;
- }
-
- ns = camel_imap_store_summary_namespace_new(store->summary, store->namespace, store->dir_sep);
- camel_imap_store_summary_namespace_set(store->summary, ns);
-
- if (CAMEL_STORE (store)->flags & CAMEL_STORE_SUBSCRIPTIONS) {
- GPtrArray *folders;
-
- /* this pre-fills the summary, and checks that lsub is useful */
- folders = g_ptr_array_new();
- get_folders_online(store, "*", folders, TRUE, ex);
- for (i=0;i<folders->len;i++) {
- CamelFolderInfo *fi = folders->pdata[i];
-
- if (fi->flags & (CAMEL_IMAP_FOLDER_MARKED | CAMEL_IMAP_FOLDER_UNMARKED))
- store->capabilities |= IMAP_CAPABILITY_useful_lsub;
- camel_folder_info_free(fi);
- }
- g_ptr_array_free(folders, TRUE);
- }
-
- path = g_strdup_printf ("%s/journal", store->storage_path);
- disco_store->diary = camel_disco_diary_new (disco_store, path, ex);
- g_free (path);
-
- done:
- /* save any changes we had */
- camel_store_summary_save((CamelStoreSummary *)store->summary);
-
- CAMEL_SERVICE_UNLOCK (store, connect_lock);
-
- if (camel_exception_is_set (ex))
- camel_service_disconnect (service, TRUE, NULL);
- else if (camel_disco_diary_empty (disco_store->diary))
- imap_store_refresh_folders (store, ex);
-
- return !camel_exception_is_set (ex);
-}
-
-static gboolean
-imap_connect_offline (CamelService *service, CamelException *ex)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (service);
- CamelDiscoStore *disco_store = CAMEL_DISCO_STORE (service);
- char *path;
-
- 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;
-
- imap_store_refresh_folders (store, ex);
-
- store->connected = !camel_exception_is_set (ex);
- return store->connected;
-}
-
-static gboolean
-imap_disconnect_offline (CamelService *service, gboolean clean, CamelException *ex)
-{
- 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->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;
-}
-
-static gboolean
-imap_disconnect_online (CamelService *service, gboolean clean, CamelException *ex)
-{
- 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;
-}
-
-
-static gboolean
-imap_summary_is_dirty (CamelFolderSummary *summary)
-{
- CamelMessageInfo *info;
- int max, i;
-
- max = camel_folder_summary_count (summary);
- for (i = 0; i < max; i++) {
- info = camel_folder_summary_index (summary, i);
- if (info && (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED))
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-imap_noop (CamelStore *store, CamelException *ex)
-{
- CamelImapStore *imap_store = (CamelImapStore *) store;
- CamelDiscoStore *disco = (CamelDiscoStore *) store;
- CamelImapResponse *response;
- CamelFolder *current_folder;
-
- if (camel_disco_store_status (disco) != CAMEL_DISCO_STORE_ONLINE)
- return;
-
- CAMEL_SERVICE_LOCK (imap_store, connect_lock);
-
- current_folder = imap_store->current_folder;
- if (current_folder && imap_summary_is_dirty (current_folder->summary)) {
- /* let's sync the flags instead */
- camel_folder_sync (current_folder, FALSE, ex);
- } else {
- response = camel_imap_command (imap_store, NULL, ex, "NOOP");
- if (response)
- camel_imap_response_free (imap_store, response);
- }
-
- CAMEL_SERVICE_UNLOCK (imap_store, connect_lock);
-}
-
-static guint
-hash_folder_name (gconstpointer key)
-{
- if (g_strcasecmp (key, "INBOX") == 0)
- return g_str_hash ("INBOX");
- else
- return g_str_hash (key);
-}
-
-static gint
-compare_folder_name (gconstpointer a, gconstpointer b)
-{
- gconstpointer aname = a, bname = b;
-
- if (g_strcasecmp (a, "INBOX") == 0)
- aname = "INBOX";
- if (g_strcasecmp (b, "INBOX") == 0)
- bname = "INBOX";
- return g_str_equal (aname, bname);
-}
-
-static CamelFolder *
-no_such_folder (const char *name, CamelException *ex)
-{
- camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
- _("No such folder %s"), name);
- return NULL;
-}
-
-static int
-get_folder_status (CamelImapStore *imap_store, const char *folder_name, const char *type)
-{
- CamelImapResponse *response;
- char *status, *p;
- int out;
-
- /* FIXME: we assume the server is STATUS-capable */
-
- response = camel_imap_command (imap_store, NULL, NULL,
- "STATUS %F (%s)",
- folder_name,
- type);
-
- if (!response) {
- CamelException ex;
-
- camel_exception_init (&ex);
- if (imap_check_folder_still_extant (imap_store, folder_name, &ex) == FALSE) {
- imap_folder_effectively_unsubscribed (imap_store, folder_name, &ex);
- imap_forget_folder (imap_store, folder_name, &ex);
- }
- camel_exception_clear (&ex);
- return -1;
- }
-
- status = camel_imap_response_extract (imap_store, response,
- "STATUS", NULL);
- if (!status)
- return -1;
-
- p = strstrcase (status, type);
- if (p)
- out = strtoul (p + strlen (type), NULL, 10);
- else
- out = -1;
-
- g_free (status);
- return out;
-}
-
-static CamelFolder *
-get_folder_online (CamelStore *store, const char *folder_name,
- guint32 flags, CamelException *ex)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
- CamelImapResponse *response;
- CamelFolder *new_folder;
- char *folder_dir, *storage_path;
-
- if (!camel_imap_store_connected (imap_store, ex))
- return NULL;
-
- if (!g_strcasecmp (folder_name, "INBOX"))
- folder_name = "INBOX";
-
- /* Lock around the whole lot to check/create atomically */
- CAMEL_SERVICE_LOCK (imap_store, connect_lock);
- if (imap_store->current_folder) {
- camel_object_unref (CAMEL_OBJECT (imap_store->current_folder));
- imap_store->current_folder = NULL;
- }
- response = camel_imap_command (imap_store, NULL, NULL, "SELECT %F", folder_name);
- if (!response) {
- char *folder_real;
-
- if (!flags & CAMEL_STORE_FOLDER_CREATE) {
- CAMEL_SERVICE_UNLOCK (imap_store, connect_lock);
- return no_such_folder (folder_name, ex);
- }
-
- folder_real = camel_imap_store_summary_path_to_full(imap_store->summary, folder_name, store->dir_sep);
-
- response = camel_imap_command (imap_store, NULL, ex, "CREATE %S", folder_real);
-
- if (response) {
- camel_imap_store_summary_add_from_full(imap_store->summary, folder_real, store->dir_sep);
-
- camel_imap_response_free (imap_store, response);
-
- response = camel_imap_command (imap_store, NULL, NULL, "SELECT %F", folder_name);
- }
- g_free(folder_real);
- if (!response) {
- CAMEL_SERVICE_UNLOCK (imap_store, connect_lock);
- return NULL;
- }
- }
-
- storage_path = g_strdup_printf("%s/folders", imap_store->storage_path);
- folder_dir = e_path_to_physical (storage_path, folder_name);
- g_free(storage_path);
- new_folder = camel_imap_folder_new (store, folder_name, folder_dir, ex);
- g_free (folder_dir);
- if (new_folder) {
- CamelException local_ex;
-
- imap_store->current_folder = new_folder;
- camel_object_ref (CAMEL_OBJECT (new_folder));
- camel_exception_init (&local_ex);
- camel_imap_folder_selected (new_folder, response, &local_ex);
-
- if (camel_exception_is_set (&local_ex)) {
- camel_exception_xfer (ex, &local_ex);
- camel_object_unref (CAMEL_OBJECT (imap_store->current_folder));
- imap_store->current_folder = NULL;
- camel_object_unref (CAMEL_OBJECT (new_folder));
- new_folder = NULL;
- }
- }
- camel_imap_response_free_without_processing (imap_store, response);
-
- CAMEL_SERVICE_UNLOCK (imap_store, connect_lock);
-
- return new_folder;
-}
-
-static CamelFolder *
-get_folder_offline (CamelStore *store, const char *folder_name,
- guint32 flags, CamelException *ex)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
- CamelFolder *new_folder;
- char *folder_dir, *storage_path;
-
- if (!imap_store->connected &&
- !camel_service_connect (CAMEL_SERVICE (store), ex))
- return NULL;
-
- if (!g_strcasecmp (folder_name, "INBOX"))
- folder_name = "INBOX";
-
- storage_path = g_strdup_printf("%s/folders", imap_store->storage_path);
- folder_dir = e_path_to_physical (storage_path, folder_name);
- g_free(storage_path);
- if (!folder_dir || access (folder_dir, F_OK) != 0) {
- g_free (folder_dir);
- camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
- _("No such folder %s"), folder_name);
- return NULL;
- }
-
- new_folder = camel_imap_folder_new (store, folder_name, folder_dir, ex);
- g_free (folder_dir);
-
- return new_folder;
-}
-
-static void
-delete_folder (CamelStore *store, const char *folder_name, CamelException *ex)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
- CamelImapResponse *response;
-
- if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex))
- return;
-
- /* make sure this folder isn't currently SELECTed */
- response = camel_imap_command (imap_store, NULL, ex, "SELECT INBOX");
- if (response) {
- camel_imap_response_free_without_processing (imap_store, response);
-
- CAMEL_SERVICE_LOCK (imap_store, connect_lock);
-
- if (imap_store->current_folder)
- camel_object_unref (CAMEL_OBJECT (imap_store->current_folder));
- /* no need to actually create a CamelFolder for INBOX */
- imap_store->current_folder = NULL;
-
- CAMEL_SERVICE_UNLOCK (imap_store, connect_lock);
- } else
- return;
-
- response = camel_imap_command (imap_store, NULL, ex, "DELETE %F",
- folder_name);
-
- if (response) {
- camel_imap_response_free (imap_store, response);
- imap_forget_folder (imap_store, folder_name, ex);
- }
-}
-
-static void
-manage_subscriptions (CamelStore *store, const char *old_name, gboolean subscribe)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
- CamelStoreInfo *si;
- int olen = strlen(old_name);
- const char *path;
- int i, count;
-
- count = camel_store_summary_count((CamelStoreSummary *)imap_store->summary);
- for (i=0;i<count;i++) {
- si = camel_store_summary_index((CamelStoreSummary *)imap_store->summary, i);
- if (si) {
- path = camel_store_info_path(imap_store->summary, si);
- if (strncmp(path, old_name, olen) == 0) {
- if (subscribe)
- subscribe_folder(store, path, NULL);
- else
- unsubscribe_folder(store, path, NULL);
- }
- camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si);
- }
- }
-}
-
-static void
-rename_folder_info (CamelImapStore *imap_store, const char *old_name, const char *new_name)
-{
- int i, count;
- CamelStoreInfo *si;
- int olen = strlen(old_name);
- const char *path;
- char *npath, *nfull;
-
- count = camel_store_summary_count((CamelStoreSummary *)imap_store->summary);
- for (i=0;i<count;i++) {
- si = camel_store_summary_index((CamelStoreSummary *)imap_store->summary, i);
- if (si == NULL)
- continue;
- path = camel_store_info_path(imap_store->summary, si);
- if (strncmp(path, old_name, olen) == 0) {
- if (strlen(path) > olen)
- npath = g_strdup_printf("%s/%s", new_name, path+olen+1);
- else
- npath = g_strdup(new_name);
- nfull = camel_imap_store_summary_path_to_full(imap_store->summary, npath, imap_store->dir_sep);
-
- /* workaround for broken server (courier uses '.') that doesn't rename
- subordinate folders as required by rfc 2060 */
- if (imap_store->dir_sep == '.') {
- CamelImapResponse *response;
-
- response = camel_imap_command (imap_store, NULL, NULL, "RENAME %F %S", path, nfull);
- if (response)
- camel_imap_response_free (imap_store, response);
- }
-
- camel_store_info_set_string((CamelStoreSummary *)imap_store->summary, si, CAMEL_STORE_INFO_PATH, npath);
- camel_store_info_set_string((CamelStoreSummary *)imap_store->summary, si, CAMEL_IMAP_STORE_INFO_FULL_NAME, nfull);
-
- camel_store_summary_touch((CamelStoreSummary *)imap_store->summary);
- g_free(nfull);
- g_free(npath);
- }
- camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si);
- }
-}
-
-static void
-rename_folder (CamelStore *store, const char *old_name, const char *new_name_in, CamelException *ex)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
- CamelImapResponse *response;
- char *oldpath, *newpath, *storage_path, *new_name;
-
- if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex))
- return;
-
- /* make sure this folder isn't currently SELECTed - it's
- actually possible to rename INBOX but if you do another
- INBOX will immediately be created by the server */
- response = camel_imap_command (imap_store, NULL, ex, "SELECT INBOX");
- if (response) {
- camel_imap_response_free_without_processing (imap_store, response);
-
- CAMEL_SERVICE_LOCK (imap_store, connect_lock);
-
- if (imap_store->current_folder)
- camel_object_unref (CAMEL_OBJECT (imap_store->current_folder));
- /* no need to actually create a CamelFolder for INBOX */
- imap_store->current_folder = NULL;
-
- CAMEL_SERVICE_UNLOCK (imap_store, connect_lock);
- } else
- return;
-
- imap_store->renaming = TRUE;
-
- if (store->flags & CAMEL_STORE_SUBSCRIPTIONS)
- manage_subscriptions(store, old_name, FALSE);
-
- new_name = camel_imap_store_summary_path_to_full(imap_store->summary, new_name_in, store->dir_sep);
- response = camel_imap_command (imap_store, NULL, ex, "RENAME %F %S", old_name, new_name);
-
- if (!response) {
- if (store->flags & CAMEL_STORE_SUBSCRIPTIONS)
- manage_subscriptions(store, old_name, TRUE);
- g_free(new_name);
- imap_store->renaming = FALSE;
- return;
- }
-
- camel_imap_response_free (imap_store, response);
-
- /* rename summary, and handle broken server */
- rename_folder_info(imap_store, old_name, new_name_in);
-
- if (store->flags & CAMEL_STORE_SUBSCRIPTIONS)
- manage_subscriptions(store, new_name_in, TRUE);
-
- storage_path = g_strdup_printf("%s/folders", imap_store->storage_path);
- oldpath = e_path_to_physical (storage_path, old_name);
- newpath = e_path_to_physical (storage_path, new_name_in);
- g_free(storage_path);
-
- /* So do we care if this didn't work? Its just a cache? */
- if (rename (oldpath, newpath) == -1) {
- g_warning ("Could not rename message cache '%s' to '%s': %s: cache reset",
- oldpath, newpath, strerror (errno));
- }
-
- g_free (oldpath);
- g_free (newpath);
- g_free(new_name);
-
- imap_store->renaming = FALSE;
-}
-
-static CamelFolderInfo *
-create_folder (CamelStore *store, const char *parent_name,
- const char *folder_name, CamelException *ex)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
- char *full_name, *resp, *thisone, *parent_real, *real_name;
- CamelImapResponse *response;
- CamelException internal_ex;
- CamelFolderInfo *root = NULL;
- gboolean need_convert;
- int i = 0, flags;
-
- if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex))
- return NULL;
- if (!parent_name)
- parent_name = "";
-
- if (strchr (folder_name, imap_store->dir_sep)) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_PATH,
- _("The folder name \"%s\" is invalid because "
- "it containes the character \"%c\""),
- folder_name, imap_store->dir_sep);
- return NULL;
- }
-
- /* check if the parent allows inferiors */
-
- /* FIXME: use storesummary directly */
- parent_real = camel_imap_store_summary_full_from_path(imap_store->summary, parent_name);
- if (parent_real == NULL) {
- camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_STATE,
- _("Unknown parent folder: %s"), parent_name);
- return NULL;
- }
-
- need_convert = FALSE;
- response = camel_imap_command (imap_store, NULL, ex, "LIST \"\" %S",
- parent_real);
- if (!response) /* whoa, this is bad */ {
- g_free(parent_real);
- return NULL;
- }
-
- /* FIXME: does not handle unexpected circumstances very well */
- for (i = 0; i < response->untagged->len; i++) {
- resp = response->untagged->pdata[i];
-
- if (!imap_parse_list_response (imap_store, resp, &flags, NULL, &thisone))
- continue;
-
- if (strcmp (thisone, parent_name) == 0) {
- if (flags & CAMEL_FOLDER_NOINFERIORS)
- need_convert = TRUE;
- break;
- }
- }
-
- camel_imap_response_free (imap_store, response);
-
- camel_exception_init (&internal_ex);
-
- /* if not, check if we can delete it and recreate it */
- if (need_convert) {
- char *name;
-
- if (get_folder_status (imap_store, parent_name, "MESSAGES")) {
- camel_exception_set (ex, CAMEL_EXCEPTION_FOLDER_INVALID_STATE,
- _("The parent folder is not allowed to contain subfolders"));
- g_free(parent_real);
- return NULL;
- }
-
- /* delete the old parent and recreate it */
- delete_folder (store, parent_name, &internal_ex);
- if (camel_exception_is_set (&internal_ex)) {
- camel_exception_xfer (ex, &internal_ex);
- return NULL;
- }
-
- /* add the dirsep to the end of parent_name */
- name = g_strdup_printf ("%s%c", parent_real, imap_store->dir_sep);
- response = camel_imap_command (imap_store, NULL, ex, "CREATE %S",
- name);
- g_free (name);
-
- if (!response) {
- g_free(parent_real);
- return NULL;
- } else
- camel_imap_response_free (imap_store, response);
-
- root = imap_build_folder_info(imap_store, parent_name);
- }
-
- /* ok now we can create the folder */
- real_name = camel_imap_store_summary_path_to_full(imap_store->summary, folder_name, store->dir_sep);
- full_name = imap_concat (imap_store, parent_real, real_name);
- g_free(real_name);
- response = camel_imap_command (imap_store, NULL, ex, "CREATE %S", full_name);
-
- if (response) {
- CamelImapStoreInfo *si;
- CamelFolderInfo *fi;
-
- camel_imap_response_free (imap_store, response);
-
- si = camel_imap_store_summary_add_from_full(imap_store->summary, full_name, store->dir_sep);
- camel_store_summary_save((CamelStoreSummary *)imap_store->summary);
- fi = imap_build_folder_info(imap_store, camel_store_info_path(imap_store->summary, si));
- if (root) {
- root->child = fi;
- fi->parent = root;
- } else {
- root = fi;
- }
- camel_object_trigger_event (CAMEL_OBJECT (store), "folder_created", root);
- } else if (root) {
- /* need to re-recreate the folder we just deleted */
- camel_object_trigger_event (CAMEL_OBJECT (store), "folder_created", root);
- camel_folder_info_free(root);
- root = NULL;
- }
-
- g_free (full_name);
- g_free(parent_real);
-
- return root;
-}
-
-static CamelFolderInfo *
-parse_list_response_as_folder_info (CamelImapStore *imap_store,
- const char *response)
-{
- CamelFolderInfo *fi;
- int flags, i;
- char sep, *dir, *name = NULL, *path;
- CamelURL *url;
-
- if (!imap_parse_list_response (imap_store, response, &flags, &sep, &dir))
- return NULL;
-
- /* FIXME: should use imap_build_folder_info, note the differences with param setting tho */
- path = camel_utf7_utf8(dir);
-
- /* hack: pokes in value from any list response */
- camel_imap_store_summary_add_from_full(imap_store->summary, dir, sep?sep:'/');
-
- if (sep && (name = strrchr(path, sep))) {
- if (!*++name) {
- g_free(dir);
- g_free(path);
- return NULL;
- }
- } else
- name = path;
-
- fi = g_new0 (CamelFolderInfo, 1);
- fi->flags = flags;
- /*fi->full_name = dir;*/
- fi->name = g_strdup(name);
- fi->path = g_strdup_printf("/%s", path);
-
- if (sep && sep != '/') {
- for (i=0;fi->path[i];i++)
- if (fi->path[i] == sep)
- fi->path[i] = '/';
- }
- fi->full_name = g_strdup(fi->path+1);
-
- url = camel_url_new (imap_store->base_url, NULL);
- g_free (url->path);
- url->path = g_strdup_printf ("/%s", fi->full_name);
-
- if (flags & CAMEL_FOLDER_NOSELECT || fi->name[0] == 0)
- camel_url_set_param (url, "noselect", "yes");
- fi->url = camel_url_to_string (url, 0);
- camel_url_free (url);
-
- /* FIXME: redundant */
- if (flags & CAMEL_IMAP_FOLDER_UNMARKED)
- fi->unread_message_count = -1;
-
- return fi;
-}
-
-/* this is used when lsub doesn't provide very useful information */
-static GPtrArray *
-get_subscribed_folders (CamelImapStore *imap_store, const char *top, CamelException *ex)
-{
- GPtrArray *names, *folders;
- int i, toplen = strlen (top);
- CamelStoreInfo *si;
- CamelImapResponse *response;
- CamelFolderInfo *fi;
- char *result;
-
- folders = g_ptr_array_new ();
- names = g_ptr_array_new ();
- for (i=0;(si = camel_store_summary_index((CamelStoreSummary *)imap_store->summary, i));i++) {
- if (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED)
- g_ptr_array_add(names, (char *)camel_imap_store_info_full_name(imap_store->summary, si));
- camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si);
- }
-
- if (names->len == 0)
- g_ptr_array_add (names, "INBOX");
-
- for (i = 0; i < names->len; i++) {
- response = camel_imap_command (imap_store, NULL, ex,
- "LIST \"\" %S",
- names->pdata[i]);
- if (!response)
- break;
-
- result = camel_imap_response_extract (imap_store, response, "LIST", NULL);
- if (!result) {
- camel_store_summary_remove_path((CamelStoreSummary *)imap_store->summary, names->pdata[i]);
- g_ptr_array_remove_index_fast (names, i);
- i--;
- continue;
- }
-
- fi = parse_list_response_as_folder_info (imap_store, result);
- if (!fi)
- continue;
-
- if (strncmp (top, fi->full_name, toplen) != 0) {
- camel_folder_info_free (fi);
- continue;
- }
-
- g_ptr_array_add (folders, fi);
- }
-
- g_ptr_array_free (names, TRUE);
-
- return folders;
-}
-
-static int imap_match_pattern(char dir_sep, const char *pattern, const char *name)
-{
- char p, n;
-
- p = *pattern++;
- n = *name++;
- while (n && p) {
- if (n == p) {
- p = *pattern++;
- n = *name++;
- } else if (p == '%') {
- if (n != dir_sep) {
- n = *name++;
- } else {
- p = *pattern++;
- }
- } else if (p == '*') {
- return TRUE;
- } else
- return FALSE;
- }
-
- return n == 0 && (p == '%' || p == 0);
-}
-
-static void
-get_folders_online (CamelImapStore *imap_store, const char *pattern,
- GPtrArray *folders, gboolean lsub, CamelException *ex)
-{
- CamelImapResponse *response;
- CamelFolderInfo *fi;
- char *list;
- int i, count;
- GHashTable *present;
- CamelStoreInfo *si;
-
- response = camel_imap_command (imap_store, NULL, ex,
- "%s \"\" %S", lsub ? "LSUB" : "LIST",
- pattern);
- if (!response)
- return;
-
- present = g_hash_table_new(g_str_hash, g_str_equal);
- for (i = 0; i < response->untagged->len; i++) {
- list = response->untagged->pdata[i];
- fi = parse_list_response_as_folder_info (imap_store, list);
- if (fi) {
- g_ptr_array_add(folders, fi);
- g_hash_table_insert(present, fi->full_name, fi);
- }
- }
- camel_imap_response_free (imap_store, response);
-
- /* update our summary to match the server */
- count = camel_store_summary_count((CamelStoreSummary *)imap_store->summary);
- for (i=0;i<count;i++) {
- si = camel_store_summary_index((CamelStoreSummary *)imap_store->summary, i);
- if (si == NULL)
- continue;
-
- if (imap_match_pattern(((CamelStore *)imap_store)->dir_sep, pattern, camel_imap_store_info_full_name(imap_store->summary, si))) {
- if (g_hash_table_lookup(present, camel_store_info_path(imap_store->summary, si)) != NULL) {
- if (lsub && (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) == 0) {
- si->flags |= CAMEL_STORE_INFO_FOLDER_SUBSCRIBED;
- camel_store_summary_touch((CamelStoreSummary *)imap_store->summary);
- }
- } else {
- if (lsub) {
- if (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) {
- si->flags &= ~CAMEL_STORE_INFO_FOLDER_SUBSCRIBED;
- camel_store_summary_touch((CamelStoreSummary *)imap_store->summary);
- }
- } else {
- camel_store_summary_remove((CamelStoreSummary *)imap_store->summary, si);
- count--;
- i--;
- }
- }
- }
- camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si);
- }
- g_hash_table_destroy(present);
-}
-
-#if 1
-static void
-dumpfi(CamelFolderInfo *fi)
-{
- int depth;
- CamelFolderInfo *n = fi;
-
- if (fi == NULL)
- return;
-
- depth = 0;
- while (n->parent) {
- depth++;
- n = n->parent;
- }
-
- while (fi) {
- printf("%-40s %-30s %*s\n", fi->path, fi->full_name, depth*2+strlen(fi->url), fi->url);
- if (fi->child)
- dumpfi(fi->child);
- fi = fi->sibling;
- }
-}
-#endif
-
-static void
-get_folder_counts(CamelImapStore *imap_store, CamelFolderInfo *fi, CamelException *ex)
-{
- GSList *q;
-
- /* non-recursive breath first search */
-
- q = g_slist_append(NULL, fi);
-
- while (q) {
- fi = q->data;
- q = g_slist_remove_link(q, q);
-
- while (fi) {
- /* ignore noselect folders, and check only inbox if we only check inbox */
- if ((fi->flags & CAMEL_FOLDER_NOSELECT) == 0
- && ( (imap_store->parameters & IMAP_PARAM_CHECK_ALL)
- || strcasecmp(fi->full_name, "inbox") == 0) ) {
-
- CAMEL_SERVICE_LOCK (imap_store, connect_lock);
- /* For the current folder, poke it to check for new
- * messages and then report that number, rather than
- * doing a STATUS command.
- */
- if (imap_store->current_folder && strcmp(imap_store->current_folder->full_name, fi->full_name) == 0) {
- /* we bypass the folder locking otherwise we can deadlock. we use the command lock for
- any operations anyway so this is 'safe'. See comment above imap_store_refresh_folders() for info */
- CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(imap_store->current_folder))->refresh_info(imap_store->current_folder, ex);
- fi->unread_message_count = camel_folder_get_unread_message_count (imap_store->current_folder);
- } else
- fi->unread_message_count = get_folder_status (imap_store, fi->full_name, "UNSEEN");
-
- CAMEL_SERVICE_UNLOCK (imap_store, connect_lock);
- } else {
- fi->unread_message_count = -1;
- }
-
- if (fi->child)
- q = g_slist_append(q, fi->child);
- fi = fi->sibling;
- }
- }
-}
-
-/* imap needs to treat inbox case insensitive */
-/* we'll assume the names are normalised already */
-static guint folder_hash(const void *ap)
-{
- const char *a = ap;
-
- if (strcasecmp(a, "INBOX") == 0)
- a = "INBOX";
-
- return g_str_hash(a);
-}
-
-static int folder_eq(const void *ap, const void *bp)
-{
- const char *a = ap;
- const char *b = bp;
-
- if (strcasecmp(a, "INBOX") == 0)
- a = "INBOX";
- if (strcasecmp(b, "INBOX") == 0)
- b = "INBOX";
-
- return g_str_equal(a, b);
-}
-
-static GPtrArray *
-get_folders(CamelStore *store, const char *top, guint32 flags, CamelException *ex)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
- GSList *p = NULL;
- GHashTable *infos;
- int i;
- GPtrArray *folders, *folders_out;
- CamelFolderInfo *fi;
- char *name;
- int depth = 0;
- int haveinbox = 0;
- static int imap_max_depth = 0;
-
- if (!camel_imap_store_connected (imap_store, ex))
- return NULL;
-
- /* allow megalomaniacs to override the max of 10 */
- if (imap_max_depth == 0) {
- name = getenv("CAMEL_IMAP_MAX_DEPTH");
- if (name) {
- imap_max_depth = atoi (name);
- imap_max_depth = MIN (MAX (imap_max_depth, 0), 2);
- } else
- imap_max_depth = 10;
- }
-
- infos = g_hash_table_new(folder_hash, folder_eq);
-
- /* get starting point & strip trailing '/' */
- if (top[0] == 0) {
- if (imap_store->namespace) {
- top = imap_store->namespace;
- i = strlen(top)-1;
- name = g_malloc(i+2);
- strcpy(name, top);
- while (i>0 && name[i] == store->dir_sep)
- name[i--] = 0;
- } else
- name = g_strdup("");
- } else {
- name = camel_imap_store_summary_full_from_path(imap_store->summary, top);
- if (name == NULL)
- name = camel_imap_store_summary_path_to_full(imap_store->summary, top, store->dir_sep);
- }
-
- d(printf("\n\nList '%s' %s\n", name, flags&CAMEL_STORE_FOLDER_INFO_RECURSIVE?"RECURSIVE":"NON-RECURSIVE"));
-
- folders_out = g_ptr_array_new();
- folders = g_ptr_array_new();
-
- /* first get working list of names */
- get_folders_online (imap_store, name[0]?name:"%", folders, flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, ex);
- if (camel_exception_is_set(ex))
- goto fail;
- for (i=0; i<folders->len && !haveinbox; i++) {
- fi = folders->pdata[i];
- haveinbox = (strcasecmp(fi->full_name, "INBOX")) == 0;
- }
-
- if (!haveinbox && top == imap_store->namespace) {
- get_folders_online(imap_store, "INBOX", folders, flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, ex);
- if (camel_exception_is_set(ex))
- goto fail;
- }
-
- for (i=0; i<folders->len; i++)
- p = g_slist_prepend(p, folders->pdata[i]);
-
- g_ptr_array_set_size(folders, 0);
-
- /* p is a reversed list of pending folders for the next level, q is the list of folders for this */
- while (p) {
- GSList *q = g_slist_reverse(p);
-
- p = NULL;
- while (q) {
- fi = q->data;
-
- q = g_slist_remove_link(q, q);
- g_ptr_array_add(folders_out, fi);
-
- d(printf("Checking folder '%s'\n", fi->full_name));
-
- /* First if we're not recursive mode on the top level, and we know it has or doesn't
- or can't have children, no need to go further - a bit ugly */
- if ( top == imap_store->namespace
- && (flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) == 0
- && (fi->flags & (CAMEL_FOLDER_CHILDREN|CAMEL_IMAP_FOLDER_NOCHILDREN|CAMEL_FOLDER_NOINFERIORS)) != 0) {
- /* do nothing */
- }
- /* Otherwise, if this has (or might have) children, scan it */
- else if ( (fi->flags & (CAMEL_IMAP_FOLDER_NOCHILDREN|CAMEL_FOLDER_NOINFERIORS)) == 0
- || (fi->flags & CAMEL_FOLDER_CHILDREN) != 0) {
- char *n, *real;
-
- real = camel_imap_store_summary_full_from_path(imap_store->summary, fi->full_name);
- n = imap_concat(imap_store, real?real:fi->full_name, "%");
- get_folders_online(imap_store, n, folders, flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, ex);
- g_free(n);
- g_free(real);
-
- if (folders->len > 0)
- fi->flags |= CAMEL_FOLDER_CHILDREN;
-
- for (i=0;i<folders->len;i++) {
- fi = folders->pdata[i];
- if (g_hash_table_lookup(infos, fi->full_name) == NULL) {
- g_hash_table_insert(infos, fi->full_name, fi);
- if ((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) && depth<imap_max_depth)
- p = g_slist_prepend(p, fi);
- else
- g_ptr_array_add(folders_out, fi);
- } else {
- camel_folder_info_free(fi);
- }
- }
- g_ptr_array_set_size(folders, 0);
- }
- }
- depth++;
- }
-
- g_ptr_array_free(folders, TRUE);
- g_hash_table_destroy(infos);
- g_free(name);
-
- return folders_out;
-fail:
- g_ptr_array_free(folders, TRUE);
- g_ptr_array_free(folders_out, TRUE);
- g_hash_table_destroy(infos);
- g_free(name);
-
- return NULL;
-}
-
-static CamelFolderInfo *
-get_folder_info_online (CamelStore *store, const char *top, guint32 flags, CamelException *ex)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
- GPtrArray *folders;
- CamelFolderInfo *tree;
-
- if (top == NULL)
- top = "";
-
- if ((flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED)
- && !(imap_store->capabilities & IMAP_CAPABILITY_useful_lsub)
- && (imap_store->parameters & IMAP_PARAM_CHECK_ALL))
- folders = get_subscribed_folders(imap_store, top, ex);
- else
- folders = get_folders(store, top, flags, ex);
-
- if (folders == NULL)
- return NULL;
-
- /* note the weird top stuff, it is so a namespace based list "" is properly tree-ised */
- tree = camel_folder_info_build(folders, top[0] == 0 && imap_store->namespace?"":top, '/', TRUE);
- g_ptr_array_free(folders, TRUE);
-
- if (!(flags & CAMEL_STORE_FOLDER_INFO_FAST))
- get_folder_counts(imap_store, tree, ex);
-
- dumpfi(tree);
- camel_store_summary_save((CamelStoreSummary *)imap_store->summary);
-
- return tree;
-}
-
-static gboolean
-get_one_folder_offline (const char *physical_path, const char *path, gpointer data)
-{
- GPtrArray *folders = data;
- CamelImapStore *imap_store = folders->pdata[0];
- CamelFolderInfo *fi;
- CamelStoreInfo *si;
-
- if (*path != '/')
- return TRUE;
-
- /* folder_info_build will insert parent nodes as necessary and mark
- * them as noselect, which is information we actually don't have at
- * the moment. So let it do the right thing by bailing out if it's
- * not a folder we're explicitly interested in.
- */
-
- si = camel_store_summary_path((CamelStoreSummary *)imap_store->summary, path+1);
- if (si) {
- if ((((CamelStore *)imap_store)->flags & CAMEL_STORE_SUBSCRIPTIONS) == 0
- || si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) {
- fi = imap_build_folder_info(imap_store, path+1);
- g_ptr_array_add (folders, fi);
- }
- camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si);
- }
-
- return TRUE;
-}
-
-static CamelFolderInfo *
-get_folder_info_offline (CamelStore *store, const char *top,
- guint32 flags, CamelException *ex)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
- CamelFolderInfo *fi;
- GPtrArray *folders;
- char *storage_path;
-
- if (!imap_store->connected &&
- !camel_service_connect (CAMEL_SERVICE (store), ex))
- return NULL;
-
- if ((store->flags & CAMEL_STORE_SUBSCRIPTIONS) &&
- !(flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED)) {
- camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex);
- return NULL;
- }
-
- /* FIXME: obey other flags */
-
- folders = g_ptr_array_new ();
-
- /* A kludge to avoid having to pass a struct to the callback */
- g_ptr_array_add (folders, imap_store);
- storage_path = g_strdup_printf("%s/folders", imap_store->storage_path);
- if (!e_path_find_folders (storage_path, get_one_folder_offline, folders)) {
- camel_disco_store_check_online (CAMEL_DISCO_STORE (imap_store), ex);
- fi = NULL;
- } else {
- g_ptr_array_remove_index_fast (folders, 0);
- fi = camel_folder_info_build (folders, "", '/', TRUE);
- }
- g_free(storage_path);
-
- g_ptr_array_free (folders, TRUE);
- return fi;
-}
-
-static gboolean
-folder_subscribed (CamelStore *store, const char *folder_name)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
- CamelStoreInfo *si;
- int truth = FALSE;
-
- si = camel_store_summary_path((CamelStoreSummary *)imap_store->summary, folder_name);
- if (si) {
- truth = (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) != 0;
- camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si);
- }
-
- return truth;
-}
-
-/* Note: folder_name must match a folder as listed with get_folder_info() -> full_name */
-static void
-subscribe_folder (CamelStore *store, const char *folder_name,
- CamelException *ex)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
- CamelImapResponse *response;
- CamelFolderInfo *fi;
- CamelStoreInfo *si;
-
- if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex))
- return;
- if (!camel_imap_store_connected (imap_store, ex))
- return;
-
- response = camel_imap_command (imap_store, NULL, ex,
- "SUBSCRIBE %F", folder_name);
- if (!response)
- return;
- camel_imap_response_free (imap_store, response);
-
- si = camel_store_summary_path((CamelStoreSummary *)imap_store->summary, folder_name);
- if (si) {
- if ((si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) == 0) {
- si->flags |= CAMEL_STORE_INFO_FOLDER_SUBSCRIBED;
- camel_store_summary_touch((CamelStoreSummary *)imap_store->summary);
- camel_store_summary_save((CamelStoreSummary *)imap_store->summary);
- }
- camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si);
- }
-
- if (imap_store->renaming) {
- /* we don't need to emit a "folder_subscribed" signal
- if we are in the process of renaming folders, so we
- are done here... */
- return;
- }
-
- fi = imap_build_folder_info(imap_store, folder_name);
- camel_object_trigger_event (CAMEL_OBJECT (store), "folder_subscribed", fi);
- camel_folder_info_free (fi);
-}
-
-static void
-unsubscribe_folder (CamelStore *store, const char *folder_name,
- CamelException *ex)
-{
- CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
- CamelImapResponse *response;
-
- if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex))
- return;
- if (!camel_imap_store_connected (imap_store, ex))
- return;
-
- response = camel_imap_command (imap_store, NULL, ex,
- "UNSUBSCRIBE %F", folder_name);
- if (!response)
- return;
- camel_imap_response_free (imap_store, response);
-
- imap_folder_effectively_unsubscribed (imap_store, folder_name, ex);
-}
-
-#if 0
-static gboolean
-folder_flags_have_changed (CamelFolder *folder)
-{
- CamelMessageInfo *info;
- int i, max;
-
- max = camel_folder_summary_count (folder->summary);
- for (i = 0; i < max; i++) {
- info = camel_folder_summary_index (folder->summary, i);
- if (!info)
- continue;
- if (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-#endif
-
-
-gboolean
-camel_imap_store_connected (CamelImapStore *store, CamelException *ex)
-{
- if (store->istream == NULL || !store->connected)
- return camel_service_connect (CAMEL_SERVICE (store), ex);
- return TRUE;
-}
-
-
-/* FIXME: please god, when will the hurting stop? Thus function is so
- fucking broken it's not even funny. */
-ssize_t
-camel_imap_store_readline (CamelImapStore *store, char **dest, CamelException *ex)
-{
- CamelStreamBuffer *stream;
- char linebuf[1024];
- GByteArray *ba;
- ssize_t nread;
-
- 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);
-
- ba = g_byte_array_new ();
- while ((nread = camel_stream_buffer_gets (stream, linebuf, sizeof (linebuf))) > 0) {
- g_byte_array_append (ba, linebuf, nread);
- if (linebuf[nread - 1] == '\n')
- break;
- }
-
- if (nread <= 0) {
- 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);
- g_byte_array_free (ba, TRUE);
- return -1;
- }
-
- if (camel_verbose_debug) {
- fprintf (stderr, "received: ");
- fwrite (ba->data, 1, ba->len, stderr);
- }
-
- /* camel-imap-command.c:imap_read_untagged expects the CRLFs
- to be stripped off and be nul-terminated *sigh* */
- nread = ba->len - 1;
- ba->data[nread] = '\0';
- if (ba->data[nread - 1] == '\r') {
- ba->data[nread - 1] = '\0';
- nread--;
- }
-
- *dest = ba->data;
- g_byte_array_free (ba, FALSE);
-
- return nread;
-}
diff --git a/camel/providers/imap/camel-imap-store.h b/camel/providers/imap/camel-imap-store.h
deleted file mode 100644
index 38df1880a0..0000000000
--- a/camel/providers/imap/camel-imap-store.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-imap-store.h : class for an imap store */
-
-/*
- * Authors: Jeffrey Stedfast <fejj@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_IMAP_STORE_H
-#define CAMEL_IMAP_STORE_H 1
-
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
-
-#include "camel-imap-types.h"
-#include <camel/camel-disco-store.h>
-
-#ifdef ENABLE_THREADS
-#include <e-util/e-msgport.h>
-
-typedef struct _CamelImapMsg CamelImapMsg;
-
-struct _CamelImapMsg {
- EMsg msg;
-
- void (*receive)(CamelImapStore *store, struct _CamelImapMsg *m);
- void (*free)(CamelImapStore *store, struct _CamelImapMsg *m);
-};
-
-CamelImapMsg *camel_imap_msg_new(void (*receive)(CamelImapStore *store, struct _CamelImapMsg *m),
- void (*free)(CamelImapStore *store, struct _CamelImapMsg *m),
- size_t size);
-void camel_imap_msg_queue(CamelImapStore *store, CamelImapMsg *msg);
-
-#endif
-
-#define CAMEL_IMAP_STORE_TYPE (camel_imap_store_get_type ())
-#define CAMEL_IMAP_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAP_STORE_TYPE, CamelImapStore))
-#define CAMEL_IMAP_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAP_STORE_TYPE, CamelImapStoreClass))
-#define CAMEL_IS_IMAP_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAP_STORE_TYPE))
-
-enum {
- CAMEL_IMAP_STORE_ARG_FIRST = CAMEL_DISCO_STORE_ARG_FIRST + 100,
- CAMEL_IMAP_STORE_ARG_NAMESPACE,
- CAMEL_IMAP_STORE_ARG_OVERRIDE_NAMESPACE,
- CAMEL_IMAP_STORE_ARG_CHECK_ALL,
- CAMEL_IMAP_STORE_ARG_FILTER_INBOX
-};
-
-#define CAMEL_IMAP_STORE_NAMESPACE (CAMEL_IMAP_STORE_ARG_NAMESPACE | CAMEL_ARG_STR)
-#define CAMEL_IMAP_STORE_OVERRIDE_NAMESPACE (CAMEL_IMAP_STORE_ARG_OVERRIDE_NAMESPACE | CAMEL_ARG_INT)
-#define CAMEL_IMAP_STORE_CHECK_ALL (CAMEL_IMAP_STORE_ARG_CHECK_ALL | CAMEL_ARG_INT)
-#define CAMEL_IMAP_STORE_FILTER_INBOX (CAMEL_IMAP_STORE_ARG_FILTER_INBOX | CAMEL_ARG_INT)
-
-/* CamelFolderInfo flags */
-#define CAMEL_IMAP_FOLDER_MARKED (1<<16)
-#define CAMEL_IMAP_FOLDER_UNMARKED (1<<17)
-#define CAMEL_IMAP_FOLDER_NOCHILDREN (1<<18)
-
-
-typedef enum {
- IMAP_LEVEL_UNKNOWN,
- IMAP_LEVEL_IMAP4,
- IMAP_LEVEL_IMAP4REV1
-} CamelImapServerLevel;
-
-#define IMAP_CAPABILITY_IMAP4 (1 << 0)
-#define IMAP_CAPABILITY_IMAP4REV1 (1 << 1)
-#define IMAP_CAPABILITY_STATUS (1 << 2)
-#define IMAP_CAPABILITY_NAMESPACE (1 << 3)
-#define IMAP_CAPABILITY_UIDPLUS (1 << 4)
-#define IMAP_CAPABILITY_LITERALPLUS (1 << 5)
-#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)
-#define IMAP_PARAM_FILTER_INBOX (1 << 2)
-
-struct _CamelImapStore {
- CamelDiscoStore parent_object;
-
- CamelStream *istream;
- CamelStream *ostream;
-
- struct _CamelImapStoreSummary *summary;
-
- /* Information about the command channel / connection status */
- gboolean connected;
- char tag_prefix;
- guint32 command;
- CamelFolder *current_folder;
-
- /* Information about the server */
- CamelImapServerLevel server_level;
- guint32 capabilities, parameters;
- char *namespace, dir_sep, *base_url, *storage_path;
- GHashTable *authtypes;
-
- gboolean renaming;
-
-#ifdef ENABLE_THREADS
- EThread *async_thread;
-#endif
-};
-
-
-typedef struct {
- CamelDiscoStoreClass parent_class;
-
-} CamelImapStoreClass;
-
-
-/* Standard Camel function */
-CamelType camel_imap_store_get_type (void);
-
-
-gboolean camel_imap_store_connected (CamelImapStore *store, CamelException *ex);
-
-ssize_t camel_imap_store_readline (CamelImapStore *store, char **dest, CamelException *ex);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CAMEL_IMAP_STORE_H */
diff --git a/camel/providers/imap/camel-imap-summary.c b/camel/providers/imap/camel-imap-summary.c
deleted file mode 100644
index dba1134fa1..0000000000
--- a/camel/providers/imap/camel-imap-summary.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2000 Ximian Inc.
- *
- * Authors:
- * Michael Zucchi <notzed@ximian.com>
- * Dan Winship <danw@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/stat.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "camel-imap-summary.h"
-#include "camel-file-utils.h"
-
-#define CAMEL_IMAP_SUMMARY_VERSION (0x300)
-
-static int summary_header_load (CamelFolderSummary *, FILE *);
-static int summary_header_save (CamelFolderSummary *, FILE *);
-
-static CamelMessageInfo *message_info_load (CamelFolderSummary *s, FILE *in);
-static int message_info_save (CamelFolderSummary *s, FILE *out,
- CamelMessageInfo *info);
-static CamelMessageContentInfo *content_info_load (CamelFolderSummary *s, FILE *in);
-static int content_info_save (CamelFolderSummary *s, FILE *out,
- CamelMessageContentInfo *info);
-
-static void camel_imap_summary_class_init (CamelImapSummaryClass *klass);
-static void camel_imap_summary_init (CamelImapSummary *obj);
-
-static CamelFolderSummaryClass *camel_imap_summary_parent;
-
-CamelType
-camel_imap_summary_get_type (void)
-{
- static CamelType type = CAMEL_INVALID_TYPE;
-
- if (type == CAMEL_INVALID_TYPE) {
- type = camel_type_register(
- camel_folder_summary_get_type(), "CamelImapSummary",
- sizeof (CamelImapSummary),
- sizeof (CamelImapSummaryClass),
- (CamelObjectClassInitFunc) camel_imap_summary_class_init,
- NULL,
- (CamelObjectInitFunc) camel_imap_summary_init,
- NULL);
- }
-
- return type;
-}
-
-static void
-camel_imap_summary_class_init (CamelImapSummaryClass *klass)
-{
- CamelFolderSummaryClass *cfs_class = (CamelFolderSummaryClass *) klass;
-
- camel_imap_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS (camel_type_get_global_classfuncs (camel_folder_summary_get_type()));
-
- cfs_class->summary_header_load = summary_header_load;
- cfs_class->summary_header_save = summary_header_save;
- cfs_class->message_info_load = message_info_load;
- cfs_class->message_info_save = message_info_save;
- cfs_class->content_info_load = content_info_load;
- cfs_class->content_info_save = content_info_save;
-}
-
-static void
-camel_imap_summary_init (CamelImapSummary *obj)
-{
- CamelFolderSummary *s = (CamelFolderSummary *)obj;
-
- /* subclasses need to set the right instance data sizes */
- s->message_info_size = sizeof(CamelImapMessageInfo);
- s->content_info_size = sizeof(CamelImapMessageContentInfo);
-
- /* and a unique file version */
- s->version += CAMEL_IMAP_SUMMARY_VERSION;
-}
-
-/**
- * camel_imap_summary_new:
- * @filename: the file to store the summary in.
- *
- * This will create a new CamelImapSummary object and read in the
- * summary data from disk, if it exists.
- *
- * Return value: A new CamelImapSummary object.
- **/
-CamelFolderSummary *
-camel_imap_summary_new (const char *filename)
-{
- CamelFolderSummary *summary = CAMEL_FOLDER_SUMMARY (
- camel_object_new (camel_imap_summary_get_type ()));
-
- camel_folder_summary_set_build_content (summary, TRUE);
- camel_folder_summary_set_filename (summary, filename);
-
- if (camel_folder_summary_load (summary) == -1) {
- camel_folder_summary_clear (summary);
- camel_folder_summary_touch (summary);
- }
-
- return summary;
-}
-
-
-static int
-summary_header_load (CamelFolderSummary *s, FILE *in)
-{
- CamelImapSummary *ims = CAMEL_IMAP_SUMMARY (s);
-
- if (camel_imap_summary_parent->summary_header_load (s, in) == -1)
- return -1;
-
- return camel_file_util_decode_uint32 (in, &ims->validity);
-}
-
-static int
-summary_header_save (CamelFolderSummary *s, FILE *out)
-{
- CamelImapSummary *ims = CAMEL_IMAP_SUMMARY(s);
-
- if (camel_imap_summary_parent->summary_header_save (s, out) == -1)
- return -1;
-
- return camel_file_util_encode_uint32 (out, ims->validity);
-}
-
-
-static CamelMessageInfo *
-message_info_load (CamelFolderSummary *s, FILE *in)
-{
- CamelMessageInfo *info;
- CamelImapMessageInfo *iinfo;
-
- info = camel_imap_summary_parent->message_info_load (s, in);
- if (info) {
- iinfo = (CamelImapMessageInfo *)info;
-
- if (camel_file_util_decode_uint32 (in, &iinfo->server_flags) == -1)
- goto error;
- }
-
- return info;
-error:
- camel_folder_summary_info_free (s, info);
- return NULL;
-}
-
-static int
-message_info_save (CamelFolderSummary *s, FILE *out, CamelMessageInfo *info)
-{
- CamelImapMessageInfo *iinfo = (CamelImapMessageInfo *)info;
-
- if (camel_imap_summary_parent->message_info_save (s, out, info) == -1)
- return -1;
-
- return camel_file_util_encode_uint32 (out, iinfo->server_flags);
-}
-
-
-static CamelMessageContentInfo *
-content_info_load (CamelFolderSummary *s, FILE *in)
-{
- if (fgetc (in))
- return camel_imap_summary_parent->content_info_load (s, in);
- else
- return camel_folder_summary_content_info_new (s);
-}
-
-static int
-content_info_save (CamelFolderSummary *s, FILE *out,
- CamelMessageContentInfo *info)
-{
- if (info->type) {
- fputc (1, out);
- return camel_imap_summary_parent->content_info_save (s, out, info);
- } else
- return fputc (0, out);
-}
-
-void
-camel_imap_summary_add_offline (CamelFolderSummary *summary, const char *uid,
- CamelMimeMessage *message,
- const CamelMessageInfo *info)
-{
- CamelMessageInfo *mi;
- CamelFlag *flag;
- CamelTag *tag;
-
- /* Create summary entry */
- mi = camel_folder_summary_info_new_from_message (summary, message);
-
- /* Copy flags 'n' tags */
- mi->flags = info->flags;
- flag = info->user_flags;
- while (flag) {
- camel_flag_set (&mi->user_flags, flag->name, TRUE);
- flag = flag->next;
- }
- tag = info->user_tags;
- while (tag) {
- camel_tag_set (&mi->user_tags, tag->name, tag->value);
- tag = tag->next;
- }
-
- /* Set uid and add to summary */
- camel_message_info_set_uid (mi, g_strdup (uid));
- camel_folder_summary_add (summary, mi);
-}
-
-void
-camel_imap_summary_add_offline_uncached (CamelFolderSummary *summary, const char *uid,
- const CamelMessageInfo *info)
-{
- CamelMessageInfo *mi;
- CamelMessageContentInfo *ci;
-
- /* Create summary entry */
- mi = camel_folder_summary_info_new (summary);
- ci = camel_folder_summary_content_info_new (summary);
-
- camel_message_info_dup_to (info, mi);
- mi->content = ci;
-
- /* copy our private fields */
- ((CamelImapMessageInfo *)mi)->server_flags =
- ((CamelImapMessageInfo *)info)->server_flags;
-
- /* Set uid and add to summary */
- camel_message_info_set_uid (mi, g_strdup (uid));
- camel_folder_summary_add (summary, mi);
-}
diff --git a/camel/providers/imap/camel-imap-summary.h b/camel/providers/imap/camel-imap-summary.h
deleted file mode 100644
index 817e884408..0000000000
--- a/camel/providers/imap/camel-imap-summary.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2000 Ximian Inc.
- *
- * Authors:
- * Michael Zucchi <notzed@ximian.com>
- * Dan Winship <danw@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.
- */
-
-#ifndef _CAMEL_IMAP_SUMMARY_H
-#define _CAMEL_IMAP_SUMMARY_H
-
-#include "camel-imap-types.h"
-#include <camel/camel-folder-summary.h>
-#include <camel/camel-exception.h>
-
-#define CAMEL_IMAP_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_imap_summary_get_type (), CamelImapSummary)
-#define CAMEL_IMAP_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imap_summary_get_type (), CamelImapSummaryClass)
-#define CAMEL_IS_IMAP_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_imap_summary_get_type ())
-
-#define CAMEL_IMAP_SERVER_FLAGS (CAMEL_MESSAGE_ANSWERED | \
- CAMEL_MESSAGE_DELETED | \
- CAMEL_MESSAGE_DRAFT | \
- CAMEL_MESSAGE_FLAGGED | \
- CAMEL_MESSAGE_SEEN)
-
-#define CAMEL_IMAP_MESSAGE_RECENT (1 << 8)
-
-typedef struct _CamelImapSummaryClass CamelImapSummaryClass;
-
-typedef struct _CamelImapMessageContentInfo {
- CamelMessageContentInfo info;
-
-} CamelImapMessageContentInfo;
-
-typedef struct _CamelImapMessageInfo {
- CamelMessageInfo info;
-
- guint32 server_flags;
-} CamelImapMessageInfo;
-
-struct _CamelImapSummary {
- CamelFolderSummary parent;
-
- guint32 validity;
-};
-
-struct _CamelImapSummaryClass {
- CamelFolderSummaryClass parent_class;
-
-};
-
-CamelType camel_imap_summary_get_type (void);
-CamelFolderSummary *camel_imap_summary_new (const char *filename);
-
-void camel_imap_summary_add_offline (CamelFolderSummary *summary,
- const char *uid,
- CamelMimeMessage *message,
- const CamelMessageInfo *info);
-
-void camel_imap_summary_add_offline_uncached (CamelFolderSummary *summary,
- const char *uid,
- const CamelMessageInfo *info);
-
-#endif /* ! _CAMEL_IMAP_SUMMARY_H */
-
diff --git a/camel/providers/imap/camel-imap-types.h b/camel/providers/imap/camel-imap-types.h
deleted file mode 100644
index c5ea41acff..0000000000
--- a/camel/providers/imap/camel-imap-types.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-imap-types.h: IMAP types */
-
-/*
- * Copyright (C) 2001 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_IMAP_TYPES_H
-#define CAMEL_IMAP_TYPES_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus }*/
-
-#include "camel-types.h"
-
-typedef struct _CamelImapFolder CamelImapFolder;
-typedef struct _CamelImapMessageCache CamelImapMessageCache;
-typedef struct _CamelImapResponse CamelImapResponse;
-typedef struct _CamelImapSearch CamelImapSearch;
-typedef struct _CamelImapStore CamelImapStore;
-typedef struct _CamelImapSummary CamelImapSummary;
-
-#endif /* CAMEL_IMAP_TYPES_H */
diff --git a/camel/providers/imap/camel-imap-utils.c b/camel/providers/imap/camel-imap-utils.c
deleted file mode 100644
index fc507398db..0000000000
--- a/camel/providers/imap/camel-imap-utils.c
+++ /dev/null
@@ -1,1156 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Authors: Jeffrey Stedfast <fejj@ximian.com>
- *
- * 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 <ctype.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <errno.h>
-
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#endif
-
-#include "camel-imap-utils.h"
-#include "camel-imap-summary.h"
-#include "camel-imap-store.h"
-#include "camel-folder.h"
-#include "camel-utf8.h"
-
-#define d(x) x
-
-const char *
-imap_next_word (const char *buf)
-{
- const char *word;
-
- /* skip over current word */
- word = buf;
- while (*word && *word != ' ')
- word++;
-
- /* skip over white space */
- while (*word && *word == ' ')
- word++;
-
- return word;
-}
-
-
-static void
-imap_namespace_destroy (struct _namespace *namespace)
-{
- struct _namespace *node, *next;
-
- node = namespace;
- while (node) {
- next = node->next;
- g_free (node->prefix);
- g_free (node);
- node = next;
- }
-}
-
-void
-imap_namespaces_destroy (struct _namespaces *namespaces)
-{
- if (namespaces) {
- imap_namespace_destroy (namespaces->personal);
- imap_namespace_destroy (namespaces->other);
- imap_namespace_destroy (namespaces->shared);
- g_free (namespaces);
- }
-}
-
-static gboolean
-imap_namespace_decode (const char **in, struct _namespace **namespace)
-{
- struct _namespace *list, *tail, *node;
- const char *inptr;
- char *astring;
- size_t len;
-
- inptr = *in;
-
- list = NULL;
- tail = (struct _namespace *) &list;
-
- if (g_strncasecmp (inptr, "NIL", 3) != 0) {
- if (*inptr++ != '(')
- goto exception;
-
- while (*inptr && *inptr != ')') {
- if (*inptr++ != '(')
- goto exception;
-
- node = g_new (struct _namespace, 1);
- node->next = NULL;
-
- /* get the namespace prefix */
- astring = imap_parse_astring (&inptr, &len);
- if (!astring) {
- g_free (node);
- goto exception;
- }
-
- /* decode IMAP's modified UTF-7 into UTF-8 */
- node->prefix = imap_mailbox_decode (astring, len);
- g_free (astring);
- if (!node->prefix) {
- g_free (node);
- goto exception;
- }
-
- tail->next = node;
- tail = node;
-
- /* get the namespace directory delimiter */
- inptr = imap_next_word (inptr);
-
- if (!g_strncasecmp (inptr, "NIL", 3)) {
- inptr = imap_next_word (inptr);
- node->delim = '\0';
- } else if (*inptr++ == '"') {
- if (*inptr == '\\')
- inptr++;
-
- node->delim = *inptr++;
-
- if (*inptr++ != '"')
- goto exception;
- } else
- goto exception;
-
- if (*inptr == ' ') {
- /* parse extra flags... for now we
- don't save them, but in the future
- we may want to? */
- while (*inptr == ' ')
- inptr++;
-
- while (*inptr && *inptr != ')') {
- /* this should be a QSTRING or ATOM */
- inptr = imap_next_word (inptr);
- if (*inptr == '(') {
- /* skip over the param list */
- imap_skip_list (&inptr);
- }
-
- while (*inptr == ' ')
- inptr++;
- }
- }
-
- if (*inptr++ != ')')
- goto exception;
-
- /* there shouldn't be spaces according to the
- ABNF grammar, but we all know how closely
- people follow specs */
- while (*inptr == ' ')
- inptr++;
- }
-
- if (*inptr == ')')
- inptr++;
- } else {
- inptr += 3;
- }
-
- *in = inptr;
- *namespace = list;
-
- return TRUE;
-
- exception:
-
- /* clean up any namespaces we may have allocated */
- imap_namespace_destroy (list);
-
- return FALSE;
-}
-
-static void
-namespace_dump (struct _namespace *namespace)
-{
- struct _namespace *node;
-
- if (namespace) {
- printf ("(");
- node = namespace;
- while (node) {
- printf ("(\"%s\" ", node->prefix);
- if (node->delim)
- printf ("\"%c\")", node->delim);
- else
- printf ("NUL)");
-
- node = node->next;
- if (node)
- printf (" ");
- }
-
- printf (")");
- } else {
- printf ("NIL");
- }
-}
-
-static void
-namespaces_dump (struct _namespaces *namespaces)
-{
- printf ("namespace dump: ");
- namespace_dump (namespaces->personal);
- printf (" ");
- namespace_dump (namespaces->other);
- printf (" ");
- namespace_dump (namespaces->shared);
- printf ("\n");
-}
-
-struct _namespaces *
-imap_parse_namespace_response (const char *response)
-{
- struct _namespaces *namespaces;
- const char *inptr;
-
- printf ("parsing: %s\n", response);
-
- if (*response != '*')
- return NULL;
-
- inptr = imap_next_word (response);
- if (g_strncasecmp (inptr, "NAMESPACE", 9) != 0)
- return NULL;
-
- inptr = imap_next_word (inptr);
-
- namespaces = g_new (struct _namespaces, 1);
- namespaces->personal = NULL;
- namespaces->other = NULL;
- namespaces->shared = NULL;
-
- if (!imap_namespace_decode (&inptr, &namespaces->personal))
- goto exception;
-
- if (*inptr != ' ')
- goto exception;
-
- while (*inptr == ' ')
- inptr++;
-
- if (!imap_namespace_decode (&inptr, &namespaces->other))
- goto exception;
-
- if (*inptr != ' ')
- goto exception;
-
- while (*inptr == ' ')
- inptr++;
-
- if (!imap_namespace_decode (&inptr, &namespaces->shared))
- goto exception;
-
- namespaces_dump (namespaces);
-
- return namespaces;
-
- exception:
-
- imap_namespaces_destroy (namespaces);
-
- return NULL;
-}
-
-/**
- * imap_parse_list_response:
- * @store: the IMAP store whose list response we're parsing
- * @buf: the LIST or LSUB response
- * @flags: a pointer to a variable to store the flags in, or %NULL
- * @sep: a pointer to a variable to store the hierarchy separator in, or %NULL
- * @folder: a pointer to a variable to store the folder name in, or %NULL
- *
- * Parses a LIST or LSUB response and returns the desired parts of it.
- * If @folder is non-%NULL, its value must be freed by the caller.
- *
- * Return value: whether or not the response was successfully parsed.
- **/
-gboolean
-imap_parse_list_response (CamelImapStore *store, const char *buf, int *flags, char *sep, char **folder)
-{
- gboolean is_lsub = FALSE;
- const char *word;
- size_t len;
-
- if (*buf != '*')
- return FALSE;
-
- word = imap_next_word (buf);
- if (g_strncasecmp (word, "LIST", 4) && g_strncasecmp (word, "LSUB", 4))
- return FALSE;
-
- /* check if we are looking at an LSUB response */
- if (word[1] == 'S' || word[1] == 's')
- is_lsub = TRUE;
-
- /* get the flags */
- word = imap_next_word (word);
- if (*word != '(')
- return FALSE;
-
- if (flags)
- *flags = 0;
-
- word++;
- while (*word != ')') {
- len = strcspn (word, " )");
- if (flags) {
- if (!g_strncasecmp (word, "\\NoInferiors", len))
- *flags |= CAMEL_FOLDER_NOINFERIORS;
- else if (!g_strncasecmp (word, "\\NoSelect", len))
- *flags |= CAMEL_FOLDER_NOSELECT;
- else if (!g_strncasecmp (word, "\\Marked", len))
- *flags |= CAMEL_IMAP_FOLDER_MARKED;
- else if (!g_strncasecmp (word, "\\Unmarked", len))
- *flags |= CAMEL_IMAP_FOLDER_UNMARKED;
- else if (!g_strncasecmp (word, "\\HasChildren", len))
- *flags |= CAMEL_FOLDER_CHILDREN;
- else if (!g_strncasecmp (word, "\\HasNoChildren", len))
- *flags |= CAMEL_IMAP_FOLDER_NOCHILDREN;
- }
-
- word += len;
- while (*word == ' ')
- word++;
- }
-
- /* get the directory separator */
- word = imap_next_word (word);
- if (!strncmp (word, "NIL", 3)) {
- if (sep)
- *sep = '\0';
- } else if (*word++ == '"') {
- if (*word == '\\')
- word++;
- if (sep)
- *sep = *word;
- word++;
- if (*word++ != '"')
- return FALSE;
- } else
- return FALSE;
-
- if (folder) {
- char *astring, *mailbox;
-
- /* get the folder name */
- word = imap_next_word (word);
- astring = imap_parse_astring (&word, &len);
- if (!astring)
- return FALSE;
-
- *folder = astring;
-#if 0
- mailbox = imap_mailbox_decode (astring, strlen (astring));
- g_free (astring);
- if (!mailbox)
- return FALSE;
-
- /* Kludge around Courier imap's LSUB response for INBOX when it
- * isn't subscribed to.
- *
- * Ignore any \Noselect flags for INBOX when parsing
- * an LSUB response to work around the following response:
- *
- * * LSUB (\Noselect \HasChildren) "." "INBOX"
- *
- * Fixes bug #28929 (albeight in a very dodgy way imho, but what
- * can ya do when ya got the ignorance of marketing breathing
- * down your neck?)
- */
- if (is_lsub && flags && !strcasecmp (mailbox, "INBOX"))
- *flags &= ~CAMEL_FOLDER_NOSELECT;
-
- *folder = mailbox;
-#endif
- }
-
- return TRUE;
-}
-
-
-/**
- * imap_parse_folder_name:
- * @store:
- * @folder_name:
- *
- * Return an array of folder paths representing the folder heirarchy.
- * For example:
- * Full/Path/"to / from"/Folder
- * Results in:
- * Full, Full/Path, Full/Path/"to / from", Full/Path/"to / from"/Folder
- **/
-char **
-imap_parse_folder_name (CamelImapStore *store, const char *folder_name)
-{
- GPtrArray *heirarchy;
- char **paths;
- const char *p;
-
- p = folder_name;
- if (*p == store->dir_sep)
- p++;
-
- heirarchy = g_ptr_array_new ();
-
- while (*p) {
- if (*p == '"') {
- p++;
- while (*p && *p != '"')
- p++;
- if (*p)
- p++;
- continue;
- }
-
- if (*p == store->dir_sep)
- g_ptr_array_add (heirarchy, g_strndup (folder_name, p - folder_name));
-
- p++;
- }
-
- g_ptr_array_add (heirarchy, g_strdup (folder_name));
- g_ptr_array_add (heirarchy, NULL);
-
- paths = (char **) heirarchy->pdata;
- g_ptr_array_free (heirarchy, FALSE);
-
- return paths;
-}
-
-char *
-imap_create_flag_list (guint32 flags)
-{
- GString *gstr;
- char *flag_list;
-
- gstr = g_string_new ("(");
-
- if (flags & CAMEL_MESSAGE_ANSWERED)
- g_string_append (gstr, "\\Answered ");
- if (flags & CAMEL_MESSAGE_DELETED)
- g_string_append (gstr, "\\Deleted ");
- if (flags & CAMEL_MESSAGE_DRAFT)
- g_string_append (gstr, "\\Draft ");
- if (flags & CAMEL_MESSAGE_FLAGGED)
- g_string_append (gstr, "\\Flagged ");
- if (flags & CAMEL_MESSAGE_SEEN)
- g_string_append (gstr, "\\Seen ");
-
- if (gstr->str[gstr->len - 1] == ' ')
- gstr->str[gstr->len - 1] = ')';
- else
- g_string_append_c (gstr, ')');
-
- flag_list = gstr->str;
- g_string_free (gstr, FALSE);
- return flag_list;
-}
-
-guint32
-imap_parse_flag_list (char **flag_list_p)
-{
- char *flag_list = *flag_list_p;
- guint32 flags = 0;
- int len;
-
- if (*flag_list++ != '(') {
- *flag_list_p = NULL;
- return 0;
- }
-
- while (*flag_list && *flag_list != ')') {
- len = strcspn (flag_list, " )");
- if (!g_strncasecmp (flag_list, "\\Answered", len))
- flags |= CAMEL_MESSAGE_ANSWERED;
- else if (!g_strncasecmp (flag_list, "\\Deleted", len))
- flags |= CAMEL_MESSAGE_DELETED;
- else if (!g_strncasecmp (flag_list, "\\Draft", len))
- flags |= CAMEL_MESSAGE_DRAFT;
- else if (!g_strncasecmp (flag_list, "\\Flagged", len))
- flags |= CAMEL_MESSAGE_FLAGGED;
- else if (!g_strncasecmp (flag_list, "\\Seen", len))
- flags |= CAMEL_MESSAGE_SEEN;
- else if (!g_strncasecmp (flag_list, "\\Recent", len))
- flags |= CAMEL_IMAP_MESSAGE_RECENT;
-
- flag_list += len;
- if (*flag_list == ' ')
- flag_list++;
- }
-
- if (*flag_list++ != ')') {
- *flag_list_p = NULL;
- return 0;
- }
-
- *flag_list_p = flag_list;
- return flags;
-}
-
-/*
- From rfc2060
-
-ATOM_CHAR ::= <any CHAR except atom_specials>
-
-atom_specials ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards /
- quoted_specials
-
-CHAR ::= <any 7-bit US-ASCII character except NUL,
- 0x01 - 0x7f>
-
-CTL ::= <any ASCII control character and DEL,
- 0x00 - 0x1f, 0x7f>
-
-SPACE ::= <ASCII SP, space, 0x20>
-
-list_wildcards ::= "%" / "*"
-
-quoted_specials ::= <"> / "\"
-*/
-
-static unsigned char imap_atom_specials[256] = {
-/* 00 */0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/* 10 */0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/* 20 */0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,
-/* 30 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 40 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 50 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
-/* 60 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 70 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-#define imap_is_atom_char(c) ((imap_atom_specials[(c)&0xff] & 0x01) != 0)
-
-gboolean
-imap_is_atom(const char *in)
-{
- register unsigned char c;
- register const char *p = in;
-
- while ((c = (unsigned char)*p)) {
- if (!imap_is_atom_char(c))
- return FALSE;
- p++;
- }
-
- /* check for empty string */
- return p!=in;
-}
-
-/**
- * imap_parse_string_generic:
- * @str_p: a pointer to a string
- * @len: a pointer to a size_t to return the length in
- * @type: type of string (#IMAP_STRING, #IMAP_ASTRING, or #IMAP_NSTRING)
- * to parse.
- *
- * This parses an IMAP "string" (quoted string or literal), "nstring"
- * (NIL or string), or "astring" (atom or string) starting at *@str_p.
- * On success, *@str_p will point to the first character after the end
- * of the string, and *@len will contain the length of the returned
- * string. On failure, *@str_p will be set to %NULL.
- *
- * This assumes that the string is in the form returned by
- * camel_imap_command(): that line breaks are indicated by LF rather
- * than CRLF.
- *
- * Return value: the parsed string, or %NULL if a NIL or no string
- * was parsed. (In the former case, *@str_p will be %NULL; in the
- * latter, it will point to the character after the NIL.)
- **/
-char *
-imap_parse_string_generic (const char **str_p, size_t *len, int type)
-{
- const char *str = *str_p;
- char *out;
-
- if (!str)
- return NULL;
- else if (*str == '"') {
- char *p;
- size_t size;
-
- str++;
- size = strcspn (str, "\"") + 1;
- p = out = g_malloc (size);
-
- /* a quoted string cannot be broken into multiple lines */
- while (*str && *str != '"' && *str != '\n') {
- if (*str == '\\')
- str++;
- *p++ = *str++;
- if (p - out == size) {
- out = g_realloc (out, size * 2);
- p = out + size;
- size *= 2;
- }
- }
- if (*str != '"') {
- *str_p = NULL;
- g_free (out);
- return NULL;
- }
- *p = '\0';
- *str_p = str + 1;
- *len = strlen (out);
- return out;
- } else if (*str == '{') {
- *len = strtoul (str + 1, (char **)&str, 10);
- if (*str++ != '}' || *str++ != '\n' || strlen (str) < *len) {
- *str_p = NULL;
- return NULL;
- }
-
- out = g_strndup (str, *len);
- *str_p = str + *len;
- return out;
- } else if (type == IMAP_NSTRING && !g_strncasecmp (str, "nil", 3)) {
- *str_p += 3;
- *len = 0;
- return NULL;
- } else if (type == IMAP_ASTRING && imap_is_atom_char ((unsigned char)*str)) {
- while (imap_is_atom_char ((unsigned char) *str))
- str++;
-
- *len = str - *str_p;
- out = g_strndup (*str_p, *len);
- *str_p += *len;
- return out;
- } else {
- *str_p = NULL;
- return NULL;
- }
-}
-
-static inline void
-skip_char (const char **in, char ch)
-{
- if (*in && **in == ch)
- *in = *in + 1;
- else
- *in = NULL;
-}
-
-/* Skip atom, string, or number */
-static void
-skip_asn (const char **str_p)
-{
- const char *str = *str_p;
-
- if (!str)
- return;
- else if (*str == '"') {
- while (*++str && *str != '"') {
- if (*str == '\\') {
- str++;
- if (!*str)
- break;
- }
- }
- if (*str == '"')
- *str_p = str + 1;
- else
- *str_p = NULL;
- } else if (*str == '{') {
- unsigned long len;
-
- len = strtoul (str + 1, (char **) &str, 10);
- if (*str != '}' || *(str + 1) != '\n' ||
- strlen (str + 2) < len) {
- *str_p = NULL;
- return;
- }
- *str_p = str + 2 + len;
- } else {
- /* We assume the string is well-formed and don't
- * bother making sure it's a valid atom.
- */
- while (*str && *str != ')' && *str != ' ')
- str++;
- *str_p = str;
- }
-}
-
-void
-imap_skip_list (const char **str_p)
-{
- skip_char (str_p, '(');
- while (*str_p && **str_p != ')') {
- if (**str_p == '(')
- imap_skip_list (str_p);
- else
- skip_asn (str_p);
- if (*str_p && **str_p == ' ')
- skip_char (str_p, ' ');
- }
- skip_char (str_p, ')');
-}
-
-static void
-parse_params (const char **parms_p, CamelContentType *type)
-{
- const char *parms = *parms_p;
- char *name, *value;
- int len;
-
- if (!g_strncasecmp (parms, "nil", 3)) {
- *parms_p += 3;
- return;
- }
-
- if (*parms++ != '(') {
- *parms_p = NULL;
- return;
- }
-
- while (parms && *parms != ')') {
- name = imap_parse_nstring (&parms, &len);
- skip_char (&parms, ' ');
- value = imap_parse_nstring (&parms, &len);
-
- if (name && value)
- header_content_type_set_param (type, name, value);
- g_free (name);
- g_free (value);
-
- if (parms && *parms == ' ')
- parms++;
- }
-
- if (!parms || *parms++ != ')') {
- *parms_p = NULL;
- return;
- }
- *parms_p = parms;
-}
-
-/**
- * imap_parse_body:
- * @body_p: pointer to the start of an IMAP "body"
- * @folder: an imap folder
- * @ci: a CamelMessageContentInfo to fill in
- *
- * This fills in @ci with data from *@body_p. On success *@body_p
- * will point to the character after the body. On failure, it will be
- * set to %NULL and @ci will be unchanged.
- **/
-void
-imap_parse_body (const char **body_p, CamelFolder *folder,
- CamelMessageContentInfo *ci)
-{
- const char *body = *body_p;
- CamelMessageContentInfo *child;
- CamelContentType *type;
- size_t len;
-
- if (!body || *body++ != '(') {
- *body_p = NULL;
- return;
- }
-
- if (*body == '(') {
- /* multipart */
- GPtrArray *children;
- char *subtype;
- int i;
-
- /* Parse the child body parts */
- children = g_ptr_array_new ();
- while (body && *body == '(') {
- child = camel_folder_summary_content_info_new (folder->summary);
- g_ptr_array_add (children, child);
- imap_parse_body (&body, folder, child);
- if (!body)
- break;
- child->parent = ci;
- }
- skip_char (&body, ' ');
-
- /* Parse the multipart subtype */
- subtype = imap_parse_string (&body, &len);
-
- /* If there is a parse error, abort. */
- if (!body) {
- for (i = 0; i < children->len; i++) {
- child = children->pdata[i];
- camel_folder_summary_content_info_free (folder->summary, child);
- }
- g_ptr_array_free (children, TRUE);
- *body_p = NULL;
- return;
- }
-
- g_strdown (subtype);
- ci->type = header_content_type_new ("multipart", subtype);
- g_free (subtype);
-
- /* Chain the children. */
- ci->childs = children->pdata[0];
- ci->size = 0;
- for (i = 0; i < children->len - 1; i++) {
- child = children->pdata[i];
- child->next = children->pdata[i + 1];
- ci->size += child->size;
- }
- g_ptr_array_free (children, TRUE);
- } else {
- /* single part */
- char *main_type, *subtype;
- char *id, *description, *encoding;
- guint32 size = 0;
-
- main_type = imap_parse_string (&body, &len);
- skip_char (&body, ' ');
- subtype = imap_parse_string (&body, &len);
- skip_char (&body, ' ');
- if (!body) {
- g_free (main_type);
- g_free (subtype);
- *body_p = NULL;
- return;
- }
- g_strdown (main_type);
- g_strdown (subtype);
- type = header_content_type_new (main_type, subtype);
- g_free (main_type);
- g_free (subtype);
- parse_params (&body, type);
- skip_char (&body, ' ');
-
- id = imap_parse_nstring (&body, &len);
- skip_char (&body, ' ');
- description = imap_parse_nstring (&body, &len);
- skip_char (&body, ' ');
- encoding = imap_parse_string (&body, &len);
- skip_char (&body, ' ');
- if (body)
- size = strtoul (body, (char **) &body, 10);
-
- child = NULL;
- if (header_content_type_is (type, "message", "rfc822")) {
- skip_char (&body, ' ');
- imap_skip_list (&body); /* envelope */
- skip_char (&body, ' ');
- child = camel_folder_summary_content_info_new (folder->summary);
- imap_parse_body (&body, folder, child);
- if (!body)
- camel_folder_summary_content_info_free (folder->summary, child);
- skip_char (&body, ' ');
- if (body)
- strtoul (body, (char **) &body, 10);
- child->parent = ci;
- } else if (header_content_type_is (type, "text", "*")) {
- if (body)
- strtoul (body, (char **) &body, 10);
- }
-
- if (body) {
- ci->type = type;
- ci->id = id;
- ci->description = description;
- ci->encoding = encoding;
- ci->size = size;
- ci->childs = child;
- } else {
- header_content_type_unref (type);
- g_free (id);
- g_free (description);
- g_free (encoding);
- }
- }
-
- if (!body || *body++ != ')') {
- *body_p = NULL;
- return;
- }
-
- *body_p = body;
-}
-
-/**
- * imap_quote_string:
- * @str: the string to quote, which must not contain CR or LF
- *
- * Return value: an IMAP "quoted" corresponding to the string, which
- * the caller must free.
- **/
-char *
-imap_quote_string (const char *str)
-{
- const char *p;
- char *quoted, *q;
- int len;
-
- g_assert (strchr (str, '\r') == NULL);
-
- len = strlen (str);
- p = str;
- while ((p = strpbrk (p, "\"\\"))) {
- len++;
- p++;
- }
-
- quoted = q = g_malloc (len + 3);
- *q++ = '"';
- for (p = str; *p; ) {
- if (strchr ("\"\\", *p))
- *q++ = '\\';
- *q++ = *p++;
- }
- *q++ = '"';
- *q = '\0';
-
- return quoted;
-}
-
-
-static inline unsigned long
-get_summary_uid_numeric (CamelFolderSummary *summary, int index)
-{
- CamelMessageInfo *info;
- unsigned long uid;
-
- info = camel_folder_summary_index (summary, index);
- uid = strtoul (camel_message_info_uid (info), NULL, 10);
- camel_folder_summary_info_free (summary, info);
- return uid;
-}
-
-/* the max number of chars that an unsigned 32-bit int can be is 10 chars plus 1 for a possible : */
-#define UID_SET_FULL(setlen, maxlen) (maxlen > 0 ? setlen + 11 >= maxlen : FALSE)
-
-/**
- * imap_uid_array_to_set:
- * @summary: summary for the folder the UIDs come from
- * @uids: a (sorted) array of UIDs
- * @uid: uid index to start at
- * @maxlen: max length of the set string (or -1 for infinite)
- * @lastuid: index offset of the last uid used
- *
- * Creates an IMAP "set" up to @maxlen bytes long, covering the listed
- * UIDs starting at index @uid and not covering any UIDs that are in
- * @summary but not in @uids. It doesn't actually require that all (or
- * any) of the UIDs be in @summary.
- *
- * After calling, @lastuid will be set the index of the first uid
- * *not* included in the returned set string.
- *
- * Return value: the set, which the caller must free with g_free()
- **/
-char *
-imap_uid_array_to_set (CamelFolderSummary *summary, GPtrArray *uids, int uid, ssize_t maxlen, int *lastuid)
-{
- unsigned long last_uid, next_summary_uid, this_uid;
- gboolean range = FALSE;
- int si, scount;
- GString *gset;
- char *set;
-
- g_return_val_if_fail (uids->len > uid, NULL);
-
- gset = g_string_new (uids->pdata[uid]);
- last_uid = strtoul (uids->pdata[uid], NULL, 10);
- next_summary_uid = 0;
- scount = camel_folder_summary_count (summary);
-
- for (uid++, si = 0; uid < uids->len && !UID_SET_FULL (gset->len, maxlen); uid++) {
- /* Find the next UID in the summary after the one we
- * just wrote out.
- */
- for ( ; last_uid >= next_summary_uid && si < scount; si++)
- next_summary_uid = get_summary_uid_numeric (summary, si);
- if (last_uid >= next_summary_uid)
- next_summary_uid = (unsigned long) -1;
-
- /* Now get the next UID from @uids */
- this_uid = strtoul (uids->pdata[uid], NULL, 10);
- if (this_uid == next_summary_uid || this_uid == last_uid + 1)
- range = TRUE;
- else {
- if (range) {
- g_string_sprintfa (gset, ":%lu", last_uid);
- range = FALSE;
- }
- g_string_sprintfa (gset, ",%lu", this_uid);
- }
-
- last_uid = this_uid;
- }
-
- if (range)
- g_string_sprintfa (gset, ":%lu", last_uid);
-
- *lastuid = uid;
-
- set = gset->str;
- g_string_free (gset, FALSE);
-
- return set;
-}
-
-/**
- * imap_uid_set_to_array:
- * @summary: summary for the folder the UIDs come from
- * @uids: a pointer to the start of an IMAP "set" of UIDs
- *
- * Fills an array with the UIDs corresponding to @uids and @summary.
- * There can be text after the uid set in @uids, which will be
- * ignored.
- *
- * If @uids specifies a range of UIDs that extends outside the range
- * of @summary, the function will assume that all of the "missing" UIDs
- * do exist.
- *
- * Return value: the array of uids, which the caller must free with
- * imap_uid_array_free(). (Or %NULL if the uid set can't be parsed.)
- **/
-GPtrArray *
-imap_uid_set_to_array (CamelFolderSummary *summary, const char *uids)
-{
- GPtrArray *arr;
- char *p, *q;
- unsigned long uid, suid;
- int si, scount;
-
- arr = g_ptr_array_new ();
- scount = camel_folder_summary_count (summary);
-
- p = (char *)uids;
- si = 0;
- do {
- uid = strtoul (p, &q, 10);
- if (p == q)
- goto lose;
- g_ptr_array_add (arr, g_strndup (p, q - p));
-
- if (*q == ':') {
- /* Find the summary entry for the UID after the one
- * we just saw.
- */
- while (++si < scount) {
- suid = get_summary_uid_numeric (summary, si);
- if (suid > uid)
- break;
- }
- if (si >= scount)
- suid = uid + 1;
-
- uid = strtoul (q + 1, &p, 10);
- if (p == q + 1)
- goto lose;
-
- /* Add each summary UID until we find one
- * larger than the end of the range
- */
- while (suid <= uid) {
- g_ptr_array_add (arr, g_strdup_printf ("%lu", suid));
- if (++si < scount)
- suid = get_summary_uid_numeric (summary, si);
- else
- suid++;
- }
- } else
- p = q;
- } while (*p++ == ',');
-
- return arr;
-
- lose:
- g_warning ("Invalid uid set %s", uids);
- imap_uid_array_free (arr);
- return NULL;
-}
-
-/**
- * imap_uid_array_free:
- * @arr: an array returned from imap_uid_set_to_array()
- *
- * Frees @arr
- **/
-void
-imap_uid_array_free (GPtrArray *arr)
-{
- int i;
-
- for (i = 0; i < arr->len; i++)
- g_free (arr->pdata[i]);
- g_ptr_array_free (arr, TRUE);
-}
-
-char *
-imap_concat (CamelImapStore *imap_store, const char *prefix, const char *suffix)
-{
- size_t len;
-
- len = strlen (prefix);
- if (len == 0 || prefix[len - 1] == imap_store->dir_sep)
- return g_strdup_printf ("%s%s", prefix, suffix);
- else
- return g_strdup_printf ("%s%c%s", prefix, imap_store->dir_sep, suffix);
-}
-
-char *
-imap_mailbox_encode (const unsigned char *in, size_t inlen)
-{
- char *buf;
-
- buf = alloca(inlen+1);
- memcpy(buf, in, inlen);
- buf[inlen] = 0;
-
- return camel_utf8_utf7(buf);
-}
-
-char *
-imap_mailbox_decode (const unsigned char *in, size_t inlen)
-{
- char *buf;
-
- buf = alloca(inlen+1);
- memcpy(buf, in, inlen);
- buf[inlen] = 0;
-
- return camel_utf7_utf8(buf);
-}
diff --git a/camel/providers/imap/camel-imap-utils.h b/camel/providers/imap/camel-imap-utils.h
deleted file mode 100644
index e8f570137f..0000000000
--- a/camel/providers/imap/camel-imap-utils.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Authors: Jeffrey Stedfast <fejj@ximian.com>
- *
- * 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.
- *
- */
-
-#ifndef CAMEL_IMAP_UTILS_H
-#define CAMEL_IMAP_UTILS_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus }*/
-
-#include <sys/types.h>
-
-#include "camel-folder-summary.h"
-#include "camel-imap-types.h"
-
-const char *imap_next_word (const char *buf);
-
-struct _namespace {
- struct _namespace *next;
- char *prefix;
- char delim;
-};
-
-struct _namespaces {
- struct _namespace *personal;
- struct _namespace *other;
- struct _namespace *shared;
-};
-
-void imap_namespaces_destroy (struct _namespaces *namespaces);
-struct _namespaces *imap_parse_namespace_response (const char *response);
-
-gboolean imap_parse_list_response (CamelImapStore *store, const char *buf, int *flags,
- char *sep, char **folder);
-
-char **imap_parse_folder_name (CamelImapStore *store, const char *folder_name);
-
-char *imap_create_flag_list (guint32 flags);
-guint32 imap_parse_flag_list (char **flag_list);
-
-
-enum { IMAP_STRING, IMAP_NSTRING, IMAP_ASTRING };
-
-char *imap_parse_string_generic (const char **str_p, size_t *len, int type);
-
-#define imap_parse_string(str_p, len_p) \
- imap_parse_string_generic (str_p, len_p, IMAP_STRING)
-#define imap_parse_nstring(str_p, len_p) \
- imap_parse_string_generic (str_p, len_p, IMAP_NSTRING)
-#define imap_parse_astring(str_p, len_p) \
- imap_parse_string_generic (str_p, len_p, IMAP_ASTRING)
-
-void imap_parse_body (const char **body_p, CamelFolder *folder,
- CamelMessageContentInfo *ci);
-
-gboolean imap_is_atom (const char *in);
-char *imap_quote_string (const char *str);
-
-void imap_skip_list (const char **str_p);
-
-char *imap_uid_array_to_set (CamelFolderSummary *summary, GPtrArray *uids, int uid, ssize_t maxlen, int *lastuid);
-GPtrArray *imap_uid_set_to_array (CamelFolderSummary *summary, const char *uids);
-void imap_uid_array_free (GPtrArray *arr);
-
-char *imap_concat (CamelImapStore *imap_store, const char *prefix, const char *suffix);
-char *imap_namespace_concat (CamelImapStore *store, const char *name);
-
-char *imap_mailbox_encode (const unsigned char *in, size_t inlen);
-char *imap_mailbox_decode (const unsigned char *in, size_t inlen);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CAMEL_IMAP_UTILS_H */
diff --git a/camel/providers/imap/camel-imap-wrapper.c b/camel/providers/imap/camel-imap-wrapper.c
deleted file mode 100644
index 8559203c16..0000000000
--- a/camel/providers/imap/camel-imap-wrapper.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; -*- */
-/* camel-imap-wrapper.c: data wrapper for offline IMAP data */
-
-/*
- * Author: Dan Winship <danw@ximian.com>
- *
- * 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 <errno.h>
-#include <string.h>
-
-#include "camel-imap-folder.h"
-#include "camel-imap-wrapper.h"
-#include "camel-imap-private.h"
-#include "camel-exception.h"
-#include "camel-stream-filter.h"
-#include "camel-mime-filter-basic.h"
-#include "camel-mime-filter-crlf.h"
-#include "camel-mime-filter-charset.h"
-#include "camel-mime-part.h"
-
-static CamelDataWrapperClass *parent_class = NULL;
-
-/* Returns the class for a CamelDataWrapper */
-#define CDW_CLASS(so) CAMEL_DATA_WRAPPER_CLASS (CAMEL_OBJECT_GET_CLASS(so))
-
-static int write_to_stream (CamelDataWrapper *imap_wrapper, CamelStream *stream);
-
-static void
-camel_imap_wrapper_class_init (CamelImapWrapperClass *camel_imap_wrapper_class)
-{
- CamelDataWrapperClass *camel_data_wrapper_class =
- CAMEL_DATA_WRAPPER_CLASS (camel_imap_wrapper_class);
-
- parent_class = CAMEL_DATA_WRAPPER_CLASS (camel_type_get_global_classfuncs (camel_data_wrapper_get_type ()));
-
- /* virtual method override */
- camel_data_wrapper_class->write_to_stream = write_to_stream;
-}
-
-static void
-camel_imap_wrapper_finalize (CamelObject *object)
-{
- CamelImapWrapper *imap_wrapper = CAMEL_IMAP_WRAPPER (object);
-
- if (imap_wrapper->folder)
- camel_object_unref (CAMEL_OBJECT (imap_wrapper->folder));
- if (imap_wrapper->uid)
- g_free (imap_wrapper->uid);
- if (imap_wrapper->part)
- g_free (imap_wrapper->part_spec);
-
-#ifdef ENABLE_THREADS
- g_mutex_free (imap_wrapper->priv->lock);
-#endif
- g_free (imap_wrapper->priv);
-}
-
-static void
-camel_imap_wrapper_init (gpointer object, gpointer klass)
-{
- CamelImapWrapper *imap_wrapper = CAMEL_IMAP_WRAPPER (object);
-
- imap_wrapper->priv = g_new0 (struct _CamelImapWrapperPrivate, 1);
-#ifdef ENABLE_THREADS
- imap_wrapper->priv->lock = g_mutex_new ();
-#endif
-}
-
-CamelType
-camel_imap_wrapper_get_type (void)
-{
- static CamelType camel_imap_wrapper_type = CAMEL_INVALID_TYPE;
-
- if (camel_imap_wrapper_type == CAMEL_INVALID_TYPE) {
- camel_imap_wrapper_type = camel_type_register (
- CAMEL_DATA_WRAPPER_TYPE, "CamelImapWrapper",
- sizeof (CamelImapWrapper),
- sizeof (CamelImapWrapperClass),
- (CamelObjectClassInitFunc) camel_imap_wrapper_class_init,
- NULL,
- (CamelObjectInitFunc) camel_imap_wrapper_init,
- (CamelObjectFinalizeFunc) camel_imap_wrapper_finalize);
- }
-
- return camel_imap_wrapper_type;
-}
-
-
-static void
-imap_wrapper_hydrate (CamelImapWrapper *imap_wrapper, CamelStream *stream)
-{
- CamelDataWrapper *data_wrapper = CAMEL_DATA_WRAPPER (imap_wrapper);
- CamelStreamFilter *filterstream;
- CamelMimeFilter *filter;
- CamelContentType *ct;
-
- filterstream = camel_stream_filter_new_with_stream (stream);
-
- /* FIXME: lame. We already have code to do all this shit in camel-mime-part-utils.c */
- switch (camel_mime_part_get_encoding (imap_wrapper->part)) {
- case CAMEL_MIME_PART_ENCODING_BASE64:
- filter = (CamelMimeFilter *)camel_mime_filter_basic_new_type (CAMEL_MIME_FILTER_BASIC_BASE64_DEC);
- camel_stream_filter_add (filterstream, filter);
- break;
- case CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE:
- filter = (CamelMimeFilter *)camel_mime_filter_basic_new_type (CAMEL_MIME_FILTER_BASIC_QP_DEC);
- camel_stream_filter_add (filterstream, filter);
- break;
- case CAMEL_MIME_PART_ENCODING_UUENCODE:
- filter = (CamelMimeFilter *)camel_mime_filter_basic_new_type (CAMEL_MIME_FILTER_BASIC_UU_DEC);
- camel_stream_filter_add (filterstream, filter);
- break;
- default:
- filter = NULL;
- }
-
- ct = camel_mime_part_get_content_type (imap_wrapper->part);
- if (header_content_type_is (ct, "text", "*")) {
- const char *charset;
-
- /* If we just did B64/QP/UU, need to also do CRLF->LF */
- if (filter) {
- filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_DECODE,
- CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY);
- camel_stream_filter_add (filterstream, filter);
- }
-
- charset = header_content_type_param (ct, "charset");
- if (charset && !(strcasecmp (charset, "us-ascii") == 0
- || strcasecmp (charset, "utf-8") == 0)) {
- filter = (CamelMimeFilter *)camel_mime_filter_charset_new_convert (charset, "UTF-8");
- if (filter)
- camel_stream_filter_add (filterstream, filter);
- }
- }
-
- data_wrapper->stream = CAMEL_STREAM (filterstream);
- data_wrapper->offline = FALSE;
-
- camel_object_unref (CAMEL_OBJECT (imap_wrapper->folder));
- imap_wrapper->folder = NULL;
- g_free (imap_wrapper->uid);
- imap_wrapper->uid = NULL;
- g_free (imap_wrapper->part_spec);
- imap_wrapper->part = NULL;
-}
-
-
-static int
-write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
-{
- CamelImapWrapper *imap_wrapper = CAMEL_IMAP_WRAPPER (data_wrapper);
-
- CAMEL_IMAP_WRAPPER_LOCK (imap_wrapper, lock);
- if (data_wrapper->offline) {
- CamelStream *datastream;
-
- datastream = camel_imap_folder_fetch_data (
- imap_wrapper->folder, imap_wrapper->uid,
- imap_wrapper->part_spec, FALSE, NULL);
- if (!datastream) {
- CAMEL_IMAP_WRAPPER_UNLOCK (imap_wrapper, lock);
- errno = ENETUNREACH;
- return -1;
- }
-
- imap_wrapper_hydrate (imap_wrapper, datastream);
- camel_object_unref (CAMEL_OBJECT (datastream));
- }
- CAMEL_IMAP_WRAPPER_UNLOCK (imap_wrapper, lock);
-
- return parent_class->write_to_stream (data_wrapper, stream);
-}
-
-
-CamelDataWrapper *
-camel_imap_wrapper_new (CamelImapFolder *imap_folder, CamelContentType *type,
- const char *uid, const char *part_spec,
- CamelMimePart *part)
-{
- CamelImapWrapper *imap_wrapper;
- CamelStream *stream;
-
- imap_wrapper = (CamelImapWrapper *)camel_object_new(camel_imap_wrapper_get_type());
-
- camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (imap_wrapper), type);
- ((CamelDataWrapper *)imap_wrapper)->offline = TRUE;
-
- imap_wrapper->folder = imap_folder;
- camel_object_ref (CAMEL_OBJECT (imap_folder));
- imap_wrapper->uid = g_strdup (uid);
- imap_wrapper->part_spec = g_strdup (part_spec);
-
- /* Don't ref this, it's our parent. */
- imap_wrapper->part = part;
-
- /* Try the cache. */
- stream = camel_imap_folder_fetch_data (imap_folder, uid, part_spec,
- TRUE, NULL);
- if (stream) {
- imap_wrapper_hydrate (imap_wrapper, stream);
- camel_object_unref (CAMEL_OBJECT (stream));
- }
-
- return (CamelDataWrapper *)imap_wrapper;
-}
diff --git a/camel/providers/imap/camel-imap-wrapper.h b/camel/providers/imap/camel-imap-wrapper.h
deleted file mode 100644
index 4f7ca5097a..0000000000
--- a/camel/providers/imap/camel-imap-wrapper.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-imap-wrapper.h: data wrapper for offline IMAP data */
-
-/*
- * 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
- */
-
-
-#ifndef CAMEL_IMAP_WRAPPER_H
-#define CAMEL_IMAP_WRAPPER_H 1
-
-
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus }*/
-
-#include <camel/camel-data-wrapper.h>
-#include "camel-imap-types.h"
-
-#define CAMEL_IMAP_WRAPPER_TYPE (camel_imap_wrapper_get_type ())
-#define CAMEL_IMAP_WRAPPER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAP_WRAPPER_TYPE, CamelImapWrapper))
-#define CAMEL_IMAP_WRAPPER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAP_WRAPPER_TYPE, CamelImapWrapperClass))
-#define CAMEL_IS_IMAP_WRAPPER(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAP_WRAPPER_TYPE))
-
-typedef struct
-{
- CamelDataWrapper parent_object;
-
- struct _CamelImapWrapperPrivate *priv;
-
- CamelImapFolder *folder;
- char *uid, *part_spec;
- CamelMimePart *part;
-} CamelImapWrapper;
-
-typedef struct {
- CamelDataWrapperClass parent_class;
-
-} CamelImapWrapperClass;
-
-/* Standard Camel function */
-CamelType camel_imap_wrapper_get_type (void);
-
-/* Constructor */
-CamelDataWrapper *camel_imap_wrapper_new (CamelImapFolder *imap_folder,
- CamelContentType *type,
- const char *uid,
- const char *part_spec,
- CamelMimePart *part);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* CAMEL_DATA_WRAPPER_H */
diff --git a/camel/providers/imap/libcamelimap.urls b/camel/providers/imap/libcamelimap.urls
deleted file mode 100644
index c301c0ffac..0000000000
--- a/camel/providers/imap/libcamelimap.urls
+++ /dev/null
@@ -1 +0,0 @@
-imap