From c8a180bc595585c7efad6a608e01cd25d68412e0 Mon Sep 17 00:00:00 2001 From: nobody Date: Fri, 2 Mar 2001 01:33:29 +0000 Subject: This commit was manufactured by cvs2svn to create tag 'GIDE_BEFORE_BONOBO'. svn path=/tags/GIDE_BEFORE_BONOBO/; revision=8485 --- camel/providers/imap/.cvsignore | 11 - camel/providers/imap/Makefile.am | 52 -- camel/providers/imap/camel-imap-command.c | 578 -------------- camel/providers/imap/camel-imap-command.h | 59 -- camel/providers/imap/camel-imap-folder.c | 1152 ---------------------------- camel/providers/imap/camel-imap-folder.h | 83 -- camel/providers/imap/camel-imap-private.h | 88 --- camel/providers/imap/camel-imap-provider.c | 113 --- camel/providers/imap/camel-imap-search.c | 151 ---- camel/providers/imap/camel-imap-search.h | 51 -- camel/providers/imap/camel-imap-store.c | 1135 --------------------------- camel/providers/imap/camel-imap-store.h | 90 --- camel/providers/imap/camel-imap-summary.c | 215 ------ camel/providers/imap/camel-imap-summary.h | 70 -- camel/providers/imap/camel-imap-types.h | 39 - camel/providers/imap/camel-imap-utils.c | 568 -------------- camel/providers/imap/camel-imap-utils.h | 62 -- camel/providers/imap/camel-imap-wrapper.c | 234 ------ camel/providers/imap/camel-imap-wrapper.h | 70 -- camel/providers/imap/libcamelimap.urls | 1 - 20 files changed, 4822 deletions(-) delete mode 100644 camel/providers/imap/.cvsignore delete mode 100644 camel/providers/imap/Makefile.am delete mode 100644 camel/providers/imap/camel-imap-command.c delete mode 100644 camel/providers/imap/camel-imap-command.h delete mode 100644 camel/providers/imap/camel-imap-folder.c delete mode 100644 camel/providers/imap/camel-imap-folder.h delete mode 100644 camel/providers/imap/camel-imap-private.h delete mode 100644 camel/providers/imap/camel-imap-provider.c delete mode 100644 camel/providers/imap/camel-imap-search.c delete mode 100644 camel/providers/imap/camel-imap-search.h delete mode 100644 camel/providers/imap/camel-imap-store.c delete mode 100644 camel/providers/imap/camel-imap-store.h delete mode 100644 camel/providers/imap/camel-imap-summary.c delete mode 100644 camel/providers/imap/camel-imap-summary.h delete mode 100644 camel/providers/imap/camel-imap-types.h delete mode 100644 camel/providers/imap/camel-imap-utils.c delete mode 100644 camel/providers/imap/camel-imap-utils.h delete mode 100644 camel/providers/imap/camel-imap-wrapper.c delete mode 100644 camel/providers/imap/camel-imap-wrapper.h delete mode 100644 camel/providers/imap/libcamelimap.urls (limited to 'camel/providers/imap') 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 39e160c879..0000000000 --- a/camel/providers/imap/Makefile.am +++ /dev/null @@ -1,52 +0,0 @@ -## Process this file with automake to produce Makefile.in - -libcamelimapincludedir = $(includedir)/camel - - -providerdir = $(pkglibdir)/camel-providers/$(VERSION) - -provider_LTLIBRARIES = libcamelimap.la -provider_DATA = libcamelimap.urls - -INCLUDES = -I.. \ - -I$(srcdir)/.. \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/libibex \ - -I$(top_srcdir)/e-util \ - -I$(top_srcdir) \ - -I$(includedir) \ - $(GTK_INCLUDEDIR) \ - -DG_LOG_DOMAIN=\"camel-imap-provider\" - -libcamelimap_la_SOURCES = \ - camel-imap-command.c \ - camel-imap-folder.c \ - camel-imap-provider.c \ - camel-imap-search.c \ - camel-imap-store.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-search.h \ - camel-imap-store.h \ - camel-imap-summary.h \ - camel-imap-types.h \ - camel-imap-utils.h \ - camel-imap-wrapper.h - -libcamelimap_la_LDFLAGS = -version-info 0:0:0 - -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 8a713cde8b..0000000000 --- a/camel/providers/imap/camel-imap-command.c +++ /dev/null @@ -1,578 +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 - * Jeffrey Stedfast - * - * Copyright 2000 Helix Code, Inc. (www.helixcode.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#include - -#include -#include -#include -#include - -#include "camel-imap-command.h" -#include "camel-imap-utils.h" -#include "camel-imap-folder.h" -#include "camel-imap-store.h" -#include - -static char *imap_read_untagged (CamelImapStore *store, char *line, - CamelException *ex); -static CamelImapResponse *imap_read_response (CamelImapStore *store, - CamelException *ex); -static char *imap_command_strdup_vprintf (CamelImapStore *store, - const char *fmt, va_list ap); - -/** - * camel_imap_command: Send a command to a IMAP server and get a response - * @store: the IMAP store - * @folder: The folder to perform the operation in (or %NULL if not - * relevant). - * @ex: a CamelException - * @fmt: an 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. It then reads the - * server's response(s) and parses the final result. - * - * As a special case, if @fmt is %NULL, it will just select @folder - * and return the response from doing so. - * - * @fmt can include the following %-escapes ONLY: - * %s, %d, %%: as with printf - * %S: an IMAP "string" (quoted string or literal) - * - * %S strings will be passed as literals if the server supports LITERAL+ - * and quoted strings otherwise. (%S does not support strings that - * contain newlines.) - * - * This function assumes you have an exclusive lock on the command - * channel/stream. - * - * 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, ...) -{ - gchar *cmdbuf; - va_list ap; - - /* Check for current folder */ - if (folder && (!fmt || folder != store->current_folder)) { - CamelImapResponse *response; - - store->current_folder = NULL; - response = camel_imap_command (store, NULL, ex, "SELECT %S", - folder->full_name); - if (!response) - return NULL; - store->current_folder = folder; - - if (!fmt) - return response; - - camel_imap_folder_selected (folder, response, ex); - camel_imap_response_free (response); - } - - /* Send the command */ - va_start (ap, fmt); - cmdbuf = imap_command_strdup_vprintf (store, fmt, ap); - va_end (ap); - - camel_remote_store_send_string (CAMEL_REMOTE_STORE (store), ex, - "A%.5d %s\r\n", store->command++, - cmdbuf); - g_free (cmdbuf); - if (camel_exception_is_set (ex)) - return NULL; - - /* Read the response. */ - return imap_read_response (store, ex); -} - -/** - * camel_imap_command_continuation: Send more command data to the IMAP server - * @store: the IMAP store - * @ex: a CamelException - * @cmdbuf: buffer containing the response/request data - * - * This method is for sending continuing responses to the IMAP server - * after camel_imap_command returns a CAMEL_IMAP_PLUS response. - * - * This function assumes you have an exclusive lock on the remote stream. - * - * Return value: as for camel_imap_command() - **/ -CamelImapResponse * -camel_imap_command_continuation (CamelImapStore *store, CamelException *ex, - const char *cmdbuf) -{ - if (camel_remote_store_send_string (CAMEL_REMOTE_STORE (store), ex, - "%s\r\n", cmdbuf) < 0) - return NULL; - - return imap_read_response (store, ex); -} - -/* Read the response to an IMAP command. */ -static CamelImapResponse * -imap_read_response (CamelImapStore *store, CamelException *ex) -{ - CamelImapResponse *response; - int number, exists = 0; - GArray *expunged = NULL; - char *respbuf, *retcode, *word, *p; - - /* Read first line */ - if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store), - &respbuf, ex) < 0) - return NULL; - - response = g_new0 (CamelImapResponse, 1); - response->untagged = g_ptr_array_new (); - - /* Check for untagged data */ - while (!strncmp (respbuf, "* ", 2)) { - /* Read the rest of the response if it is multi-line. */ - respbuf = imap_read_untagged (store, respbuf, ex); - if (camel_exception_is_set (ex)) - break; - - /* If it starts with a number, we might deal with - * it ourselves. - */ - word = imap_next_word (respbuf); - number = strtoul (word, &p, 10); - if (p != word && store->current_folder) { - word = imap_next_word (p); - if (!g_strcasecmp (word, "EXISTS")) { - exists = number; - g_free (respbuf); - goto next; - } else if (!g_strcasecmp (word, "EXPUNGE")) { - if (!expunged) { - expunged = g_array_new (FALSE, FALSE, - sizeof (int)); - } - g_array_append_val (expunged, number); - g_free (respbuf); - goto next; - } - } else { - if (!g_strncasecmp (word, "BYE", 3)) { - /* connection was lost, no more data to fetch */ - store->connected = FALSE; - g_free (respbuf); - respbuf = NULL; - break; - } - } - - g_ptr_array_add (response->untagged, respbuf); - next: - if (camel_remote_store_recv_line ( - CAMEL_REMOTE_STORE (store), &respbuf, ex) < 0) - break; - } - - /* Update the summary */ - if (store->current_folder && (exists > 0 || expunged)) { - camel_imap_folder_changed (store->current_folder, exists, - expunged, NULL); - } - if (expunged) - g_array_free (expunged, TRUE); - - if (!respbuf || camel_exception_is_set (ex)) { - camel_imap_response_free (response); - return NULL; - } - - response->status = respbuf; - - /* Check for OK or continuation response. */ - if (!strncmp (respbuf, "+ ", 2)) - return response; - retcode = imap_next_word (respbuf); - if (!strncmp (retcode, "OK", 2)) - return response; - - /* We should never get BAD, or anything else but +, OK, or NO - * for that matter. - */ - if (strncmp (retcode, "NO", 2) != 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 (response); - return NULL; - } - - retcode = imap_next_word (retcode); - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("IMAP command failed: %s"), - retcode ? retcode : _("Unknown error")); - camel_imap_response_free (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 (CAMEL_REMOTE_STORE (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, strerror(errno)); - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); - goto lose; - } - if (nread < length) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Server response ended too soon.")); - camel_service_disconnect (CAMEL_SERVICE (store), - FALSE, NULL); - 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 - * - The only cause of embedded NULs we've seen is an - * Evolution base64-encoder bug that sometimes - * inserts a NUL into the last line when it - * shouldn't. - */ - - 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_remote_store_recv_line (CAMEL_REMOTE_STORE (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: - * response: a CamelImapResponse: - * - * Frees all of the data in @response. - **/ -void -camel_imap_response_free (CamelImapResponse *response) -{ - int i; - - if (!response) - return; - for (i = 0; i < response->untagged->len; i++) - g_free (response->untagged->pdata[i]); - g_ptr_array_free (response->untagged, TRUE); - g_free (response->status); - g_free (response); -} - -/** - * camel_imap_response_extract: - * @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. - * - * Return value: the desired response string, which the caller must free. - **/ -char * -camel_imap_response_extract (CamelImapResponse *response, const char *type, - CamelException *ex) -{ - int len = strlen (type), i; - char *resp; - - 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 = imap_next_word (resp); - - if (!g_strncasecmp (resp, type, len)) - break; - - g_free (response->untagged->pdata[i]); - } - - if (i < response->untagged->len) { - resp = response->untagged->pdata[i]; - for (i++; i < response->untagged->len; i++) - g_free (response->untagged->pdata[i]); - } else { - resp = NULL; - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("IMAP server response did not contain " - "%s information"), type); - } - - g_ptr_array_free (response->untagged, TRUE); - g_free (response->status); - g_free (response); - return resp; -} - -/** - * camel_imap_response_extract_continuation: - * @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 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 (CamelImapResponse *response, - CamelException *ex) -{ - char *status; - - if (response->status && !strncmp (response->status, "+ ", 2)) { - status = response->status; - response->status = NULL; - camel_imap_response_free (response); - return status; - } - - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Unexpected OK response from IMAP server: %s"), - response->status); - camel_imap_response_free (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, *op, *string; - int num, len, i; - - 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': - string = va_arg (ap, char *); - g_ptr_array_add (args, string); - if (store->capabilities & IMAP_CAPABILITY_LITERALPLUS) - len += strlen (string) + 15; - else - len += strlen (string) * 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 */ - op = out = g_malloc (len + 1); - p = start = fmt; - i = 0; - while (*p) { - p = strchr (start, '%'); - if (!p) { - strcpy (op, start); - break; - } else { - strncpy (op, start, p - start); - op += p - start; - } - - switch (*++p) { - case 'd': - num = GPOINTER_TO_INT (args->pdata[i++]); - op += sprintf (op, "%d", num); - break; - - case 's': - string = args->pdata[i++]; - op += sprintf (op, "%s", string); - break; - - case 'S': - string = args->pdata[i++]; - if (store->capabilities & IMAP_CAPABILITY_LITERALPLUS) { - op += sprintf (op, "{%d+}\r\n%s", - strlen (string), string); - } else { - char *quoted = imap_quote_string (string); - op += sprintf (op, "%s", quoted); - g_free (quoted); - } - break; - - default: - *op++ = '%'; - *op++ = *p; - } - - start = *p ? p + 1 : p; - } - - return out; -} diff --git a/camel/providers/imap/camel-imap-command.h b/camel/providers/imap/camel-imap-command.h deleted file mode 100644 index a7d3c3eae9..0000000000 --- a/camel/providers/imap/camel-imap-command.h +++ /dev/null @@ -1,59 +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 - * Jeffrey Stedfast - * - * Copyright (C) 2000 Helix Code, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_IMAP_COMMAND_H -#define CAMEL_IMAP_COMMAND_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-imap-types.h" -#include - -struct _CamelImapResponse { - GPtrArray *untagged; - char *status; -}; - -CamelImapResponse *camel_imap_command (CamelImapStore *store, - CamelFolder *folder, - CamelException *ex, - const char *fmt, ...); -CamelImapResponse *camel_imap_command_continuation (CamelImapStore *store, - CamelException *ex, - const char *cmdbuf); - -void camel_imap_response_free (CamelImapResponse *response); -char *camel_imap_response_extract (CamelImapResponse *response, - const char *type, - CamelException *ex); -char *camel_imap_response_extract_continuation (CamelImapResponse *response, - 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 cf91bceb12..0000000000 --- a/camel/providers/imap/camel-imap-folder.c +++ /dev/null @@ -1,1152 +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: Jeffrey Stedfast - * - * Copyright (C) 2000 Helix Code, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "camel-imap-folder.h" -#include "camel-imap-command.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 "string-utils.h" -#include "camel-stream.h" -#include "camel-stream-fs.h" -#include "camel-stream-mem.h" -#include "camel-stream-buffer.h" -#include "camel-data-wrapper.h" -#include "camel-mime-message.h" -#include "camel-stream-filter.h" -#include "camel-mime-filter-from.h" -#include "camel-mime-filter-crlf.h" -#include "camel-exception.h" -#include "camel-mime-utils.h" -#include "camel-imap-private.h" -#include "camel-multipart.h" -#include "camel-operation.h" - -#define d(x) x - -#define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(o))) - -static CamelFolderClass *parent_class = NULL; - -static void imap_finalize (CamelObject *object); -static void imap_rescan (CamelFolder *folder, int exists, CamelException *ex); -static void imap_refresh_info (CamelFolder *folder, CamelException *ex); -static void imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex); -static const char *imap_get_full_name (CamelFolder *folder); -static void imap_expunge (CamelFolder *folder, CamelException *ex); - -/* message manipulation */ -static CamelMimeMessage *imap_get_message (CamelFolder *folder, const gchar *uid, - CamelException *ex); -static void imap_append_message (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, CamelException *ex); -static void imap_copy_message_to (CamelFolder *source, const char *uid, - CamelFolder *destination, CamelException *ex); -static void imap_move_message_to (CamelFolder *source, const char *uid, - CamelFolder *destination, CamelException *ex); - -/* summary info */ -static void imap_update_summary (CamelFolder *folder, int first, int last, - CamelFolderChangeInfo *changes, - CamelException *ex); - -/* searching */ -static GPtrArray *imap_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex); -static void imap_search_free (CamelFolder *folder, GPtrArray *uids); - -static void -camel_imap_folder_class_init (CamelImapFolderClass *camel_imap_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_imap_folder_class); - - parent_class = CAMEL_FOLDER_CLASS(camel_type_get_global_classfuncs (camel_folder_get_type ())); - - /* virtual method definition */ - - /* virtual method overload */ - camel_folder_class->refresh_info = imap_refresh_info; - camel_folder_class->sync = imap_sync; - camel_folder_class->expunge = imap_expunge; - camel_folder_class->get_full_name = imap_get_full_name; - - camel_folder_class->get_message = imap_get_message; - camel_folder_class->append_message = imap_append_message; - camel_folder_class->copy_message_to = imap_copy_message_to; - camel_folder_class->move_message_to = imap_move_message_to; - - camel_folder_class->search_by_expression = imap_search_by_expression; - camel_folder_class->search_free = imap_search_free; -} - -static void -camel_imap_folder_init (gpointer object, gpointer klass) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object); - CamelFolder *folder = CAMEL_FOLDER (object); - - folder->has_summary_capability = TRUE; - folder->has_search_capability = TRUE; - - imap_folder->priv = g_malloc0(sizeof(*imap_folder->priv)); -#ifdef ENABLE_THREADS - imap_folder->priv->search_lock = g_mutex_new(); -#endif -} - -CamelType -camel_imap_folder_get_type (void) -{ - static CamelType camel_imap_folder_type = CAMEL_INVALID_TYPE; - - if (camel_imap_folder_type == CAMEL_INVALID_TYPE) { - camel_imap_folder_type = - camel_type_register (CAMEL_FOLDER_TYPE, "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 *short_name, const char *summary_file, - CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (parent); - CamelFolder *folder = CAMEL_FOLDER (camel_object_new (camel_imap_folder_get_type ())); - CamelImapResponse *response; - char *resp; - guint32 validity = 0; - int i, exists = 0; - - camel_folder_construct (folder, parent, folder_name, short_name); - - CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); - response = camel_imap_command (imap_store, folder, ex, NULL); - CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); - - if (!response) { - camel_object_unref ((CamelObject *)folder); - return NULL; - } - - for (i = 0; i < response->untagged->len; i++) { - resp = response->untagged->pdata[i] + 2; - if (!g_strncasecmp (resp, "FLAGS ", 6)) { - 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; - } - } - camel_imap_response_free (response); - - folder->summary = camel_imap_summary_new (summary_file, validity); - 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; - } - - CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); - imap_rescan (folder, exists, ex); - CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); - if (camel_exception_is_set (ex)) { - camel_object_unref (CAMEL_OBJECT (folder)); - return NULL; - } - - return folder; -} - -/* Called with the store's command_lock locked */ -void -camel_imap_folder_selected (CamelFolder *folder, CamelImapResponse *response, - CamelException *ex) -{ - unsigned long exists = 0, val, uid; - CamelMessageInfo *info; - int i, count; - char *resp; - - for (i = 0; i < response->untagged->len; i++) { - resp = response->untagged->pdata[i] + 2; - - exists = strtoul (resp, &resp, 10); - if (!g_strncasecmp (resp, " EXISTS", 7)) - break; - } - if (i == response->untagged->len) { - g_warning ("Server response did not include EXISTS info"); - return; - } - - count = camel_folder_summary_count (folder->summary); - - /* If we've lost messages, we have to rescan everything */ - if (exists < count) { - imap_rescan (folder, exists, ex); - return; - } - - if (count != 0) { - /* 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 (CAMEL_IMAP_STORE (folder->parent_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 != count || g_strncasecmp (resp, " FETCH (", 8) != 0) - continue; - resp = e_strstrcase (resp, "UID "); - if (!resp) - continue; - uid = strtoul (resp + 4, NULL, 10); - break; - } - camel_imap_response_free (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_rescan (folder, exists, ex); - return; - } - } - - /* OK. So now we know that no messages have been expunged. Whew. - * Now see if messages have been added. - */ - 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 ((CamelObject *)imap_folder->search); - -#ifdef ENABLE_THREADS - g_mutex_free(imap_folder->priv->search_lock); -#endif - g_free(imap_folder->priv); -} - -static void -imap_refresh_info (CamelFolder *folder, CamelException *ex) -{ - CAMEL_IMAP_STORE_LOCK (folder->parent_store, command_lock); - imap_rescan (folder, camel_folder_summary_count (folder->summary), ex); - CAMEL_IMAP_STORE_UNLOCK (folder->parent_store, command_lock); -} - -/* Called with the store's command_lock locked */ -static void -imap_rescan (CamelFolder *folder, int exists, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response; - struct { - char *uid; - guint32 flags; - } *new = NULL; - char *resp, *p, *flags; - const char *uid; - int i, j, seq, summary_len; - CamelMessageInfo *info; - CamelImapMessageInfo *iinfo; - GArray *removed; - - camel_operation_start(NULL, _("Scanning IMAP folder")); - - /* Get UIDs and flags of all messages. */ - if (exists > 0) { - response = camel_imap_command (store, folder, ex, - "FETCH 1:%d (UID FLAGS)", - exists); - if (!response) - return; - - new = g_malloc0 (exists * sizeof (*new)); - for (i = 0; i < response->untagged->len; i++) { - resp = response->untagged->pdata[i]; - - seq = strtoul (resp + 2, &resp, 10); - if (g_strncasecmp (resp, " FETCH ", 7) != 0) - continue; - - uid = e_strstrcase (resp, "UID "); - if (uid) { - uid += 4; - strtoul (uid, &p, 10); - new[seq - 1].uid = g_strndup (uid, p - uid); - } - - flags = e_strstrcase (resp, "FLAGS "); - if (flags) { - flags += 6; - new[seq - 1].flags = imap_parse_flag_list (&flags); - } - } - camel_imap_response_free (response); - } - - /* If we find a UID in the summary that doesn't correspond to - * the UID in the folder, that it means the message was - * deleted on the server, so we remove it from the summary. - */ - removed = g_array_new (FALSE, FALSE, sizeof (int)); - summary_len = camel_folder_summary_count (folder->summary); - for (i = 0; i < summary_len && i < exists; i++) { - int pc = (i*100)/MIN(summary_len, exists); - - camel_operation_progress(NULL, pc); - - /* Shouldn't happen, but... */ - if (!new[i].uid) - continue; - - info = camel_folder_summary_index (folder->summary, i); - iinfo = (CamelImapMessageInfo *)info; - - if (strcmp (camel_message_info_uid (info), new[i].uid) != 0) { - 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; - - camel_object_trigger_event (CAMEL_OBJECT (folder), - "message_changed", - g_strdup (new[i].uid)); - } - - camel_folder_summary_info_free(folder->summary, info); - - g_free (new[i].uid); - } - - /* Remove any leftover cached summary messages. */ - for (j = i + 1; j < summary_len; j++) { - seq = j - removed->len; - g_array_append_val (removed, seq); - } - - /* Free remaining memory. */ - while (i < exists) - g_free (new[i++].uid); - g_free (new); - - /* And finally update the summary. */ - camel_imap_folder_changed (folder, exists, removed, ex); - g_array_free (removed, TRUE); - - camel_operation_end(NULL); -} - -/* 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. 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; 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 (CamelFolder *folder, gboolean expunge, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response; - CamelMessageInfo *info; - GPtrArray *matches; - char *set, *flaglist; - int i, j, max; - - max = camel_folder_summary_count (folder->summary); - - /* If we're expunging then we don't need to be precise about the - * flags of deleted messages. Just add \Deleted to anything that - * should have it. - */ - if (expunge && (matches = get_matching (folder, CAMEL_MESSAGE_DELETED, - CAMEL_MESSAGE_DELETED, &set))) { - for (i = 0; i < matches->len; i++) { - info = matches->pdata[i]; - info->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED; - camel_folder_summary_info_free (folder->summary, info); - } - g_ptr_array_free (matches, TRUE); - camel_folder_summary_touch (folder->summary); - - CAMEL_IMAP_STORE_LOCK (store, command_lock); - response = camel_imap_command (store, folder, ex, - "UID STORE %s +FLAGS.SILENT \\Deleted", - set); - CAMEL_IMAP_STORE_UNLOCK (store, command_lock); - g_free (set); - if (response) - camel_imap_response_free (response); - if (camel_exception_is_set (ex)) - return; - } - - /* OK, now, 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. - */ - 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; - } - - flaglist = imap_create_flag_list (info->flags); - 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); - - CAMEL_IMAP_STORE_LOCK (store, command_lock); - response = camel_imap_command (store, folder, ex, - "UID STORE %s FLAGS.SILENT %s", - set, flaglist); - CAMEL_IMAP_STORE_UNLOCK (store, command_lock); - g_free (set); - g_free (flaglist); - if (response) - camel_imap_response_free (response); - if (!camel_exception_is_set (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); - - if (camel_exception_is_set (ex)) - return; - } - - if (expunge) { - CAMEL_IMAP_STORE_LOCK(store, command_lock); - response = camel_imap_command (store, folder, ex, "EXPUNGE"); - CAMEL_IMAP_STORE_UNLOCK(store, command_lock); - camel_imap_response_free (response); - } - - camel_folder_summary_save (folder->summary); - - camel_operation_end(NULL); -} - -static void -imap_expunge (CamelFolder *folder, CamelException *ex) -{ - imap_sync (folder, TRUE, ex); -} - -static const char * -imap_get_full_name (CamelFolder *folder) -{ - CamelURL *url = ((CamelService *)folder->parent_store)->url; - int len; - - if (!url->path || !*url->path || !strcmp (url->path, "/")) - return folder->full_name; - len = strlen (url->path + 1); - if (!strncmp (url->path + 1, folder->full_name, len) && - strlen (folder->full_name) > len + 1) - return folder->full_name + len + 1; - return folder->full_name; -} - -static void -imap_append_message (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response; - CamelStream *memstream; - CamelMimeFilter *crlf_filter; - CamelStreamFilter *streamfilter; - GByteArray *ba; - char *flagstr, *result; - - /* create flag string param */ - if (info && info->flags) - flagstr = imap_create_flag_list (info->flags); - else - flagstr = NULL; - - /* 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)); - - CAMEL_IMAP_STORE_LOCK(store, command_lock); - response = camel_imap_command (store, NULL, ex, "APPEND %S%s%s {%d}", - folder->full_name, flagstr ? " " : "", - flagstr ? flagstr : "", ba->len); - g_free (flagstr); - - if (!response) { - g_byte_array_free (ba, TRUE); - CAMEL_IMAP_STORE_UNLOCK(store, command_lock); - return; - } - result = camel_imap_response_extract_continuation (response, ex); - if (!result) { - g_byte_array_free (ba, TRUE); - CAMEL_IMAP_STORE_UNLOCK(store, command_lock); - return; - } - g_free (result); - - /* send the rest of our data - the mime message */ - g_byte_array_append (ba, "\0", 3); - response = camel_imap_command_continuation (store, ex, ba->data); - g_byte_array_free (ba, TRUE); - CAMEL_IMAP_STORE_UNLOCK(store, command_lock); - if (!response) - return; - camel_imap_response_free (response); -} - -static void -imap_copy_message_to (CamelFolder *source, const char *uid, - CamelFolder *destination, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store); - CamelImapResponse *response; - CamelMessageInfo *mi; - - mi = camel_folder_summary_uid (source->summary, uid); - g_return_if_fail (mi != NULL); - - /* Sync message flags if needed. */ - if (mi->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) { - char *flaglist; - - flaglist = imap_create_flag_list (mi->flags); - CAMEL_IMAP_STORE_LOCK (store, command_lock); - response = camel_imap_command (store, source, ex, - "UID STORE %s FLAGS.SILENT %s", - camel_message_info_uid (mi), - flaglist); - CAMEL_IMAP_STORE_UNLOCK (store, command_lock); - g_free (flaglist); - if (camel_exception_is_set (ex)) { - camel_folder_summary_info_free (source->summary, mi); - return; - } - camel_imap_response_free (response); - - mi->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED; - ((CamelImapMessageInfo *)mi)->server_flags = - mi->flags & CAMEL_IMAP_SERVER_FLAGS; - } - camel_folder_summary_info_free (source->summary, mi); - - if (camel_exception_is_set (ex)) - return; - - /* Now copy it */ - CAMEL_IMAP_STORE_LOCK(store, command_lock); - response = camel_imap_command (store, source, ex, "UID COPY %s %S", - uid, destination->full_name); - CAMEL_IMAP_STORE_UNLOCK(store, command_lock); - - if (camel_exception_is_set (ex)) - return; - - camel_imap_response_free (response); - - /* Force the destination folder to notice its new messages. */ - response = camel_imap_command (store, destination, NULL, "NOOP"); - camel_imap_response_free (response); - } - -static void -imap_move_message_to (CamelFolder *source, const char *uid, - CamelFolder *destination, CamelException *ex) -{ - imap_copy_message_to (source, uid, destination, ex); - if (camel_exception_is_set (ex)) - return; - - camel_folder_delete_message (source, uid); -} - -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); - - if (!imap_folder->search) - imap_folder->search = camel_imap_search_new (); - - 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 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); -} - -/* parse a header response (starting after the first ' ' after - * *@headers_p) and construct a content-free CamelMedium from it. - */ -static CamelMedium * -parse_headers (char **headers_p, CamelType medium_type) -{ - CamelMedium *medium; - CamelStream *stream; - char *headers; - int len; - - *headers_p = strchr (*headers_p, ' '); - if (!*headers_p) - return FALSE; - (*headers_p)++; - - headers = imap_parse_nstring (headers_p, &len); - if (!headers) - return FALSE; - stream = camel_stream_mem_new_with_buffer (headers, len); - g_free (headers); - - medium = CAMEL_MEDIUM (camel_object_new (medium_type)); - camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (medium), stream); - camel_object_unref (CAMEL_OBJECT (stream)); - - return medium; -} - -static CamelMedium * -fetch_medium (CamelFolder *folder, const char *uid, const char *section_text, - CamelType type, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response; - CamelMedium *medium; - char *result, *p; - - CAMEL_IMAP_STORE_LOCK (store, command_lock); - 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); - } - CAMEL_IMAP_STORE_UNLOCK (store, command_lock); - if (!response) - return NULL; - - /* FIXME: there could be multiple lines of FETCH response. */ - result = camel_imap_response_extract (response, "FETCH", ex); - if (!result) - return NULL; - - - if (store->server_level < IMAP_LEVEL_IMAP4REV1 && !*section_text) - p = e_strstrcase (result, "RFC822"); - else - p = e_strstrcase (result, "BODY"); - - if (p) - medium = parse_headers (&p, type); - else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not find message body in FETCH " - "response.")); - medium = NULL; - } - g_free (result); - - return medium; -} - -static CamelMimeMessage *get_message (CamelFolder *folder, const char *uid, - const char *part_specifier, - CamelMessageContentInfo *ci, - CamelException *ex); - -/* Fetch the contents of the MIME part indicated by @ci, which is part - * of message @uid in @folder. - */ -static CamelDataWrapper * -get_content (CamelFolder *folder, const char *uid, const char *part_spec, - CamelMimePart *part, CamelMessageContentInfo *ci, - CamelException *ex) -{ - char *child_spec; - - /* There are three cases: multipart, message/rfc822, and "other" */ - - if (header_content_type_is (ci->type, "multipart", "*")) { - CamelMultipart *body_mp; - CamelDataWrapper *content; - int speclen, num; - - body_mp = camel_multipart_new (); - camel_data_wrapper_set_mime_type_field ( - CAMEL_DATA_WRAPPER (body_mp), ci->type); - camel_multipart_set_boundary (body_mp, NULL); - - speclen = strlen (part_spec); - child_spec = g_malloc (speclen + 15); - memcpy (child_spec, part_spec, speclen); - if (speclen > 0) - child_spec[speclen++] = '.'; - - ci = ci->childs; - num = 1; - while (ci) { - sprintf (child_spec + speclen, "%d.MIME", num++); - part = (CamelMimePart *)fetch_medium (folder, uid, child_spec, CAMEL_MIME_PART_TYPE, ex); - *(strchr (child_spec + speclen, '.')) = '\0'; - if (part) - content = get_content (folder, uid, child_spec, part, ci, ex); - if (!part || !content) { - g_free (child_spec); - camel_object_unref (CAMEL_OBJECT (part)); - camel_object_unref (CAMEL_OBJECT (body_mp)); - 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")) { - return (CamelDataWrapper *) - get_message (folder, uid, part_spec, ci->childs, ex); - } else { - CamelDataWrapper *content; - - if (!ci->parent || header_content_type_is (ci->parent->type, "message", "rfc822")) - child_spec = g_strdup_printf ("%s%s1", part_spec, *part_spec ? "." : ""); - else - child_spec = g_strdup (part_spec); - content = camel_imap_wrapper_new (folder, ci->type, uid, child_spec, part); - g_free (child_spec); - return content; - } -} - -static CamelMimeMessage * -get_message (CamelFolder *folder, const char *uid, const char *part_spec, - CamelMessageContentInfo *ci, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelDataWrapper *content; - CamelMimeMessage *msg; - char *section_text; - - section_text = g_strdup_printf ("%s%s%s", part_spec, *part_spec ? "." : "", - store->server_level >= IMAP_LEVEL_IMAP4REV1 ? "HEADER" : "0"); - msg = (CamelMimeMessage *)fetch_medium (folder, uid, section_text, CAMEL_MIME_MESSAGE_TYPE, ex); - g_free (section_text); - if (!msg) - return NULL; - - content = get_content (folder, uid, part_spec, 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 * -imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex) -{ - CamelMessageInfo *mi; - CamelMimeMessage *msg; - - mi = camel_folder_summary_uid (folder->summary, uid); - g_return_val_if_fail (mi != NULL, NULL); - - /* Fetch small messages directly. */ - if (mi->size < IMAP_SMALL_BODY_SIZE) { - camel_folder_summary_info_free (folder->summary, mi); - return (CamelMimeMessage *)fetch_medium (folder, uid, "", CAMEL_MIME_MESSAGE_TYPE, 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) { - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response; - char *result, *p; - - CAMEL_IMAP_STORE_LOCK (store, command_lock); - response = camel_imap_command (store, folder, ex, - "UID FETCH %s BODY", uid); - CAMEL_IMAP_STORE_UNLOCK (store, command_lock); - if (!response) { - camel_folder_summary_info_free (folder->summary, mi); - return NULL; - } - /* FIXME, wrong */ - result = camel_imap_response_extract (response, "FETCH", ex); - if (!result) { - camel_folder_summary_info_free (folder->summary, mi); - return NULL; - } - - p = e_strstrcase (result, "BODY "); - if (p) { - p += 5; - imap_parse_body (&p, folder, mi->content); - } - g_free (result); - if (!mi->content->type) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not find message body in FETCH response.")); - camel_folder_summary_info_free (folder->summary, mi); - return NULL; - } - } - - msg = get_message (folder, uid, "", mi->content, ex); - camel_folder_summary_info_free (folder->summary, mi); - - return msg; -} - -static const char * -imap_protocol_get_summary_specifier (CamelImapStore *store) -{ - if (store->server_level >= IMAP_LEVEL_IMAP4REV1) - return "UID FLAGS RFC822.SIZE BODY.PEEK[HEADER]"; - else - return "UID FLAGS RFC822.SIZE RFC822.HEADER"; -} - -static void -imap_update_summary (CamelFolder *folder, int first, int last, - CamelFolderChangeInfo *changes, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response; - GPtrArray *headers, *messages; - const char *summary_specifier; - char *p, *uid; - int i, seq, count; - CamelMimeMessage *msg; - CamelMessageInfo *mi; - guint32 flags, size; - - summary_specifier = imap_protocol_get_summary_specifier (store); - /* We already have the command lock */ - if (first == last) { - response = camel_imap_command (store, folder, ex, - "FETCH %d (%s)", first, - summary_specifier); - } else { - response = camel_imap_command (store, folder, ex, - "FETCH %d:%d (%s)", first, - last, summary_specifier); - } - - if (!response) - return; - - count = camel_folder_summary_count (folder->summary); - messages = g_ptr_array_new (); - g_ptr_array_set_size (messages, last - first + 1); - headers = response->untagged; - for (i = 0; i < headers->len; i++) { - p = headers->pdata[i]; - if (*p++ != '*' || *p++ != ' ') - continue; - seq = strtoul (p, &p, 10); - if (!seq || seq < count) - continue; - if (g_strncasecmp (p, " FETCH (", 8) != 0) - continue; - p += 8; - - mi = messages->pdata[seq - first]; - flags = size = 0; - uid = NULL; - while (p && *p != ')') { - if (*p == ' ') - p++; - if (!g_strncasecmp (p, "FLAGS ", 6)) { - p += 6; - /* FIXME user flags */ - flags = imap_parse_flag_list (&p); - } else if (!g_strncasecmp (p, "RFC822.SIZE ", 12)) { - size = strtoul (p + 12, &p, 10); - } else if (!g_strncasecmp (p, "UID ", 4)) { - uid = p + 4; - strtoul (uid, &p, 10); - uid = g_strndup (uid, p - uid); - } else if (!g_strncasecmp (p, "BODY[HEADER", 11) || - !g_strncasecmp (p, "RFC822.HEADER", 13)) { - msg = (CamelMimeMessage *) parse_headers (&p, CAMEL_MIME_MESSAGE_TYPE); - mi = camel_folder_summary_info_new_from_message (folder->summary, msg); - camel_object_unref (CAMEL_OBJECT (msg)); - } else { - g_warning ("Waiter, I did not order this %.*s", - (int)strcspn (p, " \n"), p); - p = NULL; - } - } - - /* Ideally we got everything on one line, but if we - * we didn't, and we didn't get the body yet, then we - * have to postpone this line for later. - */ - if (mi == NULL) { - p = headers->pdata[i]; - g_ptr_array_remove_index (headers, i); - g_ptr_array_add (headers, p); - continue; - } - - messages->pdata[seq - first] = mi; - if (uid) - camel_message_info_set_uid (mi, uid); - if (flags) - mi->flags = flags; - if (size) - mi->size = size; - } - camel_imap_response_free (response); - - for (i = 0; i < messages->len; i++) { - mi = messages->pdata[i]; - camel_folder_summary_add (folder->summary, mi); - camel_folder_change_info_add_uid (changes, camel_message_info_uid (mi)); - } - g_ptr_array_free (messages, TRUE); -} - -/* Called with the store's command_lock locked */ -void -camel_imap_folder_changed (CamelFolder *folder, int exists, - GArray *expunged, CamelException *ex) -{ - CamelFolderChangeInfo *changes; - CamelMessageInfo *info; - int len; - - 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); - camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info)); - 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, len + 1, 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); -} diff --git a/camel/providers/imap/camel-imap-folder.h b/camel/providers/imap/camel-imap-folder.h deleted file mode 100644 index a943189f5a..0000000000 --- a/camel/providers/imap/camel-imap-folder.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-folder.h : Abstract class for an imap folder */ - -/* - * Author: - * Jeffrey Stedfast - * - * Copyright (C) 2000 Helix Code, Inc. (www.helixcode.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_IMAP_FOLDER_H -#define CAMEL_IMAP_FOLDER_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-imap-types.h" -#include "camel-folder.h" -#include - -#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 { - CamelFolder parent_object; - - struct _CamelImapFolderPrivate *priv; - - CamelFolderSearch *search; -}; - - -typedef struct { - CamelFolderClass parent_class; - - /* Virtual methods */ - -} CamelImapFolderClass; - - -/* public methods */ -CamelFolder *camel_imap_folder_new (CamelStore *parent, - const char *folder_name, - const char *short_name, - const char *summary_file, - 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); - -/* 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-private.h b/camel/providers/imap/camel-imap-private.h deleted file mode 100644 index c7af3ee5e6..0000000000 --- a/camel/providers/imap/camel-imap-private.h +++ /dev/null @@ -1,88 +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 - * - * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef 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 */ - -#include "config.h" - -#ifdef ENABLE_THREADS -#include "e-util/e-msgport.h" -#endif - -struct _CamelImapStorePrivate { -#ifdef ENABLE_THREADS - EMutex *command_lock; /* for locking the command stream for a complete operation */ -#endif -}; - -#ifdef ENABLE_THREADS -#define CAMEL_IMAP_STORE_LOCK(f, l) (e_mutex_lock(((CamelImapStore *)f)->priv->l)) -#define CAMEL_IMAP_STORE_UNLOCK(f, l) (e_mutex_unlock(((CamelImapStore *)f)->priv->l)) -#else -#define CAMEL_IMAP_STORE_LOCK(f, l) -#define CAMEL_IMAP_STORE_UNLOCK(f, l) -#endif - -struct _CamelImapFolderPrivate { -#ifdef ENABLE_THREADS - GMutex *search_lock; /* for locking the search object */ -#endif -}; - -#ifdef ENABLE_THREADS -#define CAMEL_IMAP_FOLDER_LOCK(f, l) (g_mutex_lock(((CamelImapFolder *)f)->priv->l)) -#define CAMEL_IMAP_FOLDER_UNLOCK(f, l) (g_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 9b962df5f4..0000000000 --- a/camel/providers/imap/camel-imap-provider.c +++ /dev/null @@ -1,113 +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 - * - * Copyright 2000 Helix Code, Inc. (www.helixcode.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#include "config.h" -#include "camel-imap-store.h" -#include "camel-provider.h" -#include "camel-session.h" -#include "camel-url.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); - -static CamelProvider imap_provider = { - "imap", - N_("IMAPv4"), - - N_("For reading and storing mail on IMAP servers."), - - "mail", - - CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE | - CAMEL_PROVIDER_IS_STORAGE, - - CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | - CAMEL_URL_ALLOW_PATH | CAMEL_URL_ALLOW_AUTH, - - { 0, 0 }, - - NULL -}; - -void -camel_provider_module_init (CamelSession *session) -{ - imap_provider.object_types[CAMEL_PROVIDER_STORE] = - camel_imap_store_get_type(); - - imap_provider.service_cache = g_hash_table_new (imap_url_hash, imap_url_equal); - - 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 06cf4a8d30..0000000000 --- a/camel/providers/imap/camel-imap-search.c +++ /dev/null @@ -1,151 +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 - * - * Copyright 2000 Helix Code, Inc. (www.helixcode.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#include - -#include - -#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" - -static ESExpResult * -imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, - CamelFolderSearch *s); - -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); - - /* virtual method overload */ - camel_folder_search_class->body_contains = imap_body_contains; -} - -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, NULL, NULL); - } - - return camel_imap_search_type; -} - -static ESExpResult * -imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, - CamelFolderSearch *s) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (s->folder->parent_store); - char *value = argv[0]->value.string; - CamelImapResponse *response; - char *result, *p, *lasts = NULL, *real_uid; - const char *uid = ""; - ESExpResult *r; - CamelMessageInfo *info; - GHashTable *uid_hash = NULL; - - CAMEL_IMAP_STORE_LOCK(store, command_lock); - - if (s->current) { - uid = camel_message_info_uid (s->current); - r = e_sexp_result_new(f, ESEXP_RES_BOOL); - r->value.bool = FALSE; - response = camel_imap_command (store, s->folder, NULL, - "UID SEARCH UID %s BODY \"%s\"", - uid, value); - } else { - r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR); - r->value.ptrarray = g_ptr_array_new (); - response = camel_imap_command (store, s->folder, NULL, - "UID SEARCH BODY \"%s\"", - value); - } - - CAMEL_IMAP_STORE_UNLOCK(store, command_lock); - - if (!response) - return r; - result = camel_imap_response_extract (response, "SEARCH", NULL); - if (!result) - return r; - - p = result + sizeof ("* SEARCH"); - for (p = strtok_r (p, " ", &lasts); p; p = strtok_r (NULL, " ", &lasts)) { - if (s->current) { - if (!strcmp (uid, p)) { - r->value.bool = TRUE; - break; - } - } else { - /* if we need to setup a hash of summary items, this way we get - access to the summary memory which is locked for the duration of - the search, and wont vanish on us */ - if (uid_hash == NULL) { - int i; - - uid_hash = g_hash_table_new(g_str_hash, g_str_equal); - for (i=0;isummary->len;i++) { - info = s->summary->pdata[i]; - g_hash_table_insert(uid_hash, (char *)camel_message_info_uid(info), info); - } - } - if (g_hash_table_lookup_extended(uid_hash, p, (void *)&real_uid, (void *)&info)) - g_ptr_array_add (r->value.ptrarray, real_uid); - } - } - - /* we could probably cache this globally, but its probably not worth it */ - if (uid_hash) - g_hash_table_destroy(uid_hash); - - return r; -} - -/** - * camel_imap_search_new: - * - * Return value: A new CamelImapSearch widget. - **/ -CamelFolderSearch * -camel_imap_search_new (void) -{ - CamelFolderSearch *new = CAMEL_FOLDER_SEARCH (camel_object_new (camel_imap_search_get_type ())); - - camel_folder_search_construct (new); - return new; -} diff --git a/camel/providers/imap/camel-imap-search.h b/camel/providers/imap/camel-imap-search.h deleted file mode 100644 index 97fd6cd6c4..0000000000 --- a/camel/providers/imap/camel-imap-search.h +++ /dev/null @@ -1,51 +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 - * - * Copyright 2000 Helix Code, Inc. (www.helixcode.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef _CAMEL_IMAP_SEARCH_H -#define _CAMEL_IMAP_SEARCH_H - -#include - -#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; - -}; - -struct _CamelImapSearchClass { - CamelFolderSearchClass parent_class; - -}; - -guint camel_imap_search_get_type (void); -CamelFolderSearch *camel_imap_search_new (void); - -#endif /* ! _CAMEL_IMAP_SEARCH_H */ diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c deleted file mode 100644 index a924c4dab7..0000000000 --- a/camel/providers/imap/camel-imap-store.c +++ /dev/null @@ -1,1135 +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: Jeffrey Stedfast - * - * Copyright 2000 Helix Code, Inc. (www.helixcode.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#include - -#include -#include -#include -#include -#include - -#include - -#include "camel-imap-store.h" -#include "camel-imap-folder.h" -#include "camel-imap-utils.h" -#include "camel-imap-command.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-url.h" -#include "camel-sasl.h" -#include "string-utils.h" - -#include "camel-imap-private.h" -#include "camel-private.h" - -#define d(x) x - -/* Specified in RFC 2060 */ -#define IMAP_PORT 143 - -static CamelRemoteStoreClass *remote_store_class = NULL; - -static gboolean imap_connect (CamelService *service, CamelException *ex); -static gboolean imap_disconnect (CamelService *service, gboolean clean, CamelException *ex); -static GList *query_auth_types (CamelService *service, gboolean connect, CamelException *ex); -static guint hash_folder_name (gconstpointer key); -static gint compare_folder_name (gconstpointer a, gconstpointer b); -static CamelFolder *get_folder (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 CamelFolderInfo *get_folder_info (CamelStore *store, const char *top, - gboolean fast, gboolean recursive, - gboolean subscribed_only, - 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 imap_keepalive (CamelRemoteStore *store); - -static void -camel_imap_store_class_init (CamelImapStoreClass *camel_imap_store_class) -{ - /* virtual method overload */ - CamelServiceClass *camel_service_class = - CAMEL_SERVICE_CLASS (camel_imap_store_class); - CamelStoreClass *camel_store_class = - CAMEL_STORE_CLASS (camel_imap_store_class); - CamelRemoteStoreClass *camel_remote_store_class = - CAMEL_REMOTE_STORE_CLASS (camel_imap_store_class); - - remote_store_class = CAMEL_REMOTE_STORE_CLASS(camel_type_get_global_classfuncs - (camel_remote_store_get_type ())); - - /* virtual method overload */ - camel_service_class->query_auth_types = query_auth_types; - camel_service_class->connect = imap_connect; - camel_service_class->disconnect = imap_disconnect; - - camel_store_class->hash_folder_name = hash_folder_name; - camel_store_class->compare_folder_name = compare_folder_name; - camel_store_class->get_folder = get_folder; - camel_store_class->create_folder = create_folder; - camel_store_class->get_folder_info = get_folder_info; - 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_remote_store_class->keepalive = imap_keepalive; -} - -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); - - if (imap_store->subscribed_folders) { - g_hash_table_foreach_remove (imap_store->subscribed_folders, - free_key, NULL); - g_hash_table_destroy (imap_store->subscribed_folders); - } - if (imap_store->authtypes) { - g_hash_table_foreach_remove (imap_store->authtypes, - free_key, NULL); - g_hash_table_destroy (imap_store->authtypes); - } - if (imap_store->namespace) - g_free (imap_store->namespace); -#ifdef ENABLE_THREADS - e_mutex_destroy(imap_store->priv->command_lock); -#endif - g_free(imap_store->priv); -} - -static void -camel_imap_store_init (gpointer object, gpointer klass) -{ - CamelRemoteStore *remote_store = CAMEL_REMOTE_STORE (object); - CamelImapStore *imap_store = CAMEL_IMAP_STORE (object); - CamelStore *store = CAMEL_STORE (object); - - remote_store->default_port = 143; - - imap_store->dir_sep = '\0'; - imap_store->current_folder = NULL; - - store->flags = CAMEL_STORE_SUBSCRIPTIONS; - - imap_store->connected = FALSE; - imap_store->subscribed_folders = NULL; - - imap_store->priv = g_malloc0(sizeof(*imap_store->priv)); -#ifdef ENABLE_THREADS - imap_store->priv->command_lock = e_mutex_new(E_MUTEX_REC); -#endif -} - -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_REMOTE_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 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 }, - { NULL, 0 } -}; - -/* we have remote-store:connect_lock by now */ -static gboolean -connect_to_server (CamelService *service, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelImapResponse *response; - char *result, *buf, *capa, *lasts; - int i; - - if (!CAMEL_SERVICE_CLASS (remote_store_class)->connect (service, ex)) - return FALSE; - - store->command = 0; - - /* Read the greeting, if any. FIXME: deal with PREAUTH */ - if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (service), - &buf, ex) < 0) { - return FALSE; - } - g_free (buf); - store->connected = TRUE; - - /* Find out the IMAP capabilities */ - store->capabilities = 0; - 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 (response, "CAPABILITY", ex); - if (!result) - return FALSE; - - /* Skip over "* CAPABILITY". */ - capa = imap_next_word (result + 2); - - 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); - - 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; - - return TRUE; -} - -static CamelServiceAuthType password_authtype = { - N_("Password"), - - N_("This option will connect to the IMAP server using a " - "plaintext password."), - - "", - TRUE -}; - -static GList * -query_auth_types (CamelService *service, gboolean connect, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelServiceAuthType *authtype; - GList *types, *sasl_types, *t; - - if (connect && !connect_to_server (service, ex)) - return NULL; - - types = CAMEL_SERVICE_CLASS (remote_store_class)->query_auth_types (service, connect, ex); - - sasl_types = camel_sasl_authtype_list (); - if (connect) { - for (t = types; t; t = t->next) { - authtype = t->data; - - if (!g_hash_table_lookup (store->authtypes, authtype->authproto)) { - g_list_remove_link (types, t); - g_list_free_1 (t); - } - } - } - types = g_list_concat (types, sasl_types); - - return g_list_prepend (types, &password_authtype); -} - -/* call refresh folder directly, bypassing the folder lock */ -static void -refresh_folder_info (gpointer key, gpointer value, gpointer data) -{ - CamelFolder *folder = CAMEL_FOLDER (value); - - CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(folder))->refresh_info(folder, data); -} - -/* 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 */ -/* 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 */ -static void -imap_store_refresh_folders (CamelRemoteStore *store, CamelException *ex) -{ - CAMEL_STORE_LOCK(store, cache_lock); - - g_hash_table_foreach (CAMEL_STORE (store)->folders, refresh_folder_info, ex); - - CAMEL_STORE_UNLOCK(store, cache_lock); -} - -static gboolean -try_auth (CamelImapStore *store, const char *mech, CamelException *ex) -{ - CamelSasl *sasl; - CamelImapResponse *response; - char *resp; - char *sasl_resp; - - sasl = camel_sasl_new ("imap", mech, CAMEL_SERVICE (store)); - - sasl_resp = camel_sasl_challenge_base64 (sasl, NULL, ex); - - CAMEL_IMAP_STORE_LOCK (store, command_lock); - response = camel_imap_command (store, NULL, ex, "AUTHENTICATE %s%s%s", - mech, sasl_resp ? " " : "", - sasl_resp ? sasl_resp : ""); - if (!response) - goto lose; - - while (!camel_sasl_authenticated (sasl)) { - resp = camel_imap_response_extract_continuation (response, ex); - if (!resp) - goto lose; - - sasl_resp = camel_sasl_challenge_base64 (sasl, resp + 2, ex); - g_free (resp); - if (camel_exception_is_set (ex)) - goto break_and_lose; - - response = camel_imap_command_continuation (store, ex, sasl_resp); - g_free (sasl_resp); - if (!response) - goto lose; - } - - resp = camel_imap_response_extract_continuation (response, NULL); - if (resp) { - /* Oops. SASL claims we're done, but the IMAP server - * doesn't think so... - */ - g_free (resp); - goto lose; - } - - CAMEL_IMAP_STORE_UNLOCK (store, command_lock); - return TRUE; - - break_and_lose: - /* Get the server out of "waiting for continuation data" mode. */ - response = camel_imap_command_continuation (store, NULL, "*"); - if (response) - camel_imap_response_free (response); - - lose: - if (!camel_exception_is_set (ex)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Bad authentication response from server.")); - } - CAMEL_IMAP_STORE_UNLOCK (store, command_lock); - return FALSE; -} - -static gboolean -imap_connect (CamelService *service, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelSession *session = camel_service_get_session (service); - char *result, *errbuf = NULL, *name; - CamelImapResponse *response; - gboolean authenticated = FALSE; - int len, i, flags; - CamelServiceAuthType *authtype = NULL; - - if (connect_to_server (service, ex) == 0) - return FALSE; - - 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); - camel_service_disconnect (service, TRUE, NULL); - 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); - camel_service_disconnect (service, TRUE, NULL); - return FALSE; - } - - if (!authtype->need_password) { - authenticated = try_auth (store, authtype->authproto, ex); - if (!authenticated) { - camel_service_disconnect (service, TRUE, NULL); - return FALSE; - } - } - } - - while (!authenticated) { - if (errbuf) { - /* We need to un-cache the password before prompting again */ - camel_session_query_authenticator ( - session, CAMEL_AUTHENTICATOR_TELL, NULL, - TRUE, 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_query_authenticator ( - session, CAMEL_AUTHENTICATOR_ASK, - 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."); - camel_service_disconnect (service, TRUE, NULL); - return FALSE; - } - } - - if (authtype) - authenticated = try_auth (store, authtype->authproto, ex); - else { - CAMEL_IMAP_STORE_LOCK(store, command_lock); - response = camel_imap_command (store, NULL, ex, - "LOGIN %S %S", - service->url->user, - service->url->passwd); - CAMEL_IMAP_STORE_UNLOCK(store, command_lock); - if (response) { - camel_imap_response_free (response); - authenticated = TRUE; - } - } - if (!authenticated) { - errbuf = g_strdup_printf (_("Unable to authenticate " - "to IMAP server.\n%s\n\n"), - camel_exception_get_description (ex)); - camel_exception_clear (ex); - } - } - - /* Get subscribed folders */ - CAMEL_IMAP_STORE_LOCK (store, command_lock); - response = camel_imap_command (store, NULL, ex, "LSUB \"\" \"*\""); - CAMEL_IMAP_STORE_UNLOCK (store, command_lock); - if (!response) - return FALSE; - store->subscribed_folders = g_hash_table_new (g_str_hash, g_str_equal); - for (i = 0; i < response->untagged->len; i++) { - result = response->untagged->pdata[i]; - if (!imap_parse_list_response (result, &flags, NULL, &name)) - continue; - if (flags & (IMAP_LIST_FLAG_MARKED | IMAP_LIST_FLAG_UNMARKED)) - store->useful_lsub = TRUE; - if (flags & IMAP_LIST_FLAG_NOSELECT) { - g_free (name); - continue; - } - g_hash_table_insert (store->subscribed_folders, name, - GINT_TO_POINTER (1)); - } - camel_imap_response_free (response); - - /* Get namespace and hierarchy separator */ - if (service->url->path && strlen (service->url->path) > 1) - store->namespace = g_strdup (service->url->path + 1); - else if (store->capabilities & IMAP_CAPABILITY_NAMESPACE) { - CAMEL_IMAP_STORE_LOCK (store, command_lock); - response = camel_imap_command (store, NULL, ex, "NAMESPACE"); - CAMEL_IMAP_STORE_UNLOCK (store, command_lock); - if (!response) - return FALSE; - - result = camel_imap_response_extract (response, "NAMESPACE", ex); - if (!result) - return FALSE; - - name = e_strstrcase (result, "NAMESPACE (("); - if (name) { - char *sep; - - name += 12; - store->namespace = imap_parse_string (&name, &len); - if (name && *name++ == ' ') { - sep = imap_parse_string (&name, &len); - if (sep) { - store->dir_sep = *sep; - g_free (sep); - } - } - } - g_free (result); - } - if (!store->namespace) - store->namespace = g_strdup (""); - - if (!store->dir_sep) { - CAMEL_IMAP_STORE_LOCK(store, command_lock); - 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); - } - CAMEL_IMAP_STORE_UNLOCK(store, command_lock); - - if (!response) - return FALSE; - - result = camel_imap_response_extract (response, "LIST", NULL); - if (result) { - imap_parse_list_response (result, NULL, &store->dir_sep, NULL); - g_free (result); - } - if (!store->dir_sep) - store->dir_sep = '/'; /* Guess */ - } - - /* Generate base URL */ - store->base_url = camel_url_to_string (service->url, FALSE); - len = strlen (store->base_url); - if (service->url->path) - store->base_url[len - strlen (service->url->path) + 1] = '\0'; - else { - store->base_url = g_realloc (store->base_url, len + 2); - store->base_url[len] = '/'; - store->base_url[len + 1] = '\0'; - } - - /* Find our storage path. */ - if (!store->storage_path) { - store->storage_path = - camel_session_get_storage_path (session, service, ex); - if (camel_exception_is_set (ex)) - return FALSE; - } - - imap_store_refresh_folders (CAMEL_REMOTE_STORE (store), ex); - - return !camel_exception_is_set (ex); -} - -static gboolean -imap_disconnect (CamelService *service, gboolean clean, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelImapResponse *response; - - if (store->connected && clean) { - /* send the logout command */ - - /* NB: this lock probably isn't required */ - CAMEL_IMAP_STORE_LOCK(store, command_lock); - response = camel_imap_command (store, NULL, ex, "LOGOUT"); - CAMEL_IMAP_STORE_UNLOCK(store, command_lock); - camel_imap_response_free (response); - } - store->connected = FALSE; - store->current_folder = NULL; - - if (store->subscribed_folders) { - g_hash_table_foreach_remove (store->subscribed_folders, - free_key, NULL); - g_hash_table_destroy (store->subscribed_folders); - store->subscribed_folders = NULL; - } - - if (store->namespace) { - g_free (store->namespace); - store->namespace = NULL; - } - - return CAMEL_SERVICE_CLASS (remote_store_class)->disconnect (service, clean, ex); -} - -/* NOTE: Must have imap_store::command_lock before calling this */ -static gboolean -imap_folder_exists (CamelImapStore *store, const char *folder_name, - gboolean *selectable, char **short_name, - CamelException *ex) -{ - CamelImapResponse *response; - char *result, sep; - int flags; - - if (!g_strcasecmp (folder_name, "INBOX")) { - if (selectable) - *selectable = TRUE; - if (short_name) - *short_name = g_strdup ("INBOX"); - return TRUE; - } - - response = camel_imap_command (store, NULL, ex, "LIST \"\" %S", - folder_name); - if (!response) - return FALSE; - result = camel_imap_response_extract (response, "LIST", ex); - if (!result) - return FALSE; - - if (!imap_parse_list_response (result, &flags, &sep, NULL)) - return FALSE; - - if (selectable) - *selectable = !(flags & IMAP_LIST_FLAG_NOSELECT); - if (short_name) { - *short_name = strrchr (folder_name, sep); - if (*short_name) - *short_name = g_strdup (*short_name + 1); - else - *short_name = g_strdup (folder_name); - } - - return TRUE; -} - -/* NOTE: Must have imap_store::command_lock before calling this */ -static gboolean -imap_create (CamelImapStore *store, const char *folder_name, - CamelException *ex) -{ - CamelImapResponse *response; - - response = camel_imap_command (store, NULL, ex, "CREATE %S", - folder_name); - camel_imap_response_free (response); - - return !camel_exception_is_set (ex); -} - -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 * -get_folder (CamelStore *store, const char *folder_name, guint32 flags, - CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelFolder *new_folder = NULL; - char *short_name, *summary_file, *p; - gboolean selectable; - - if (!camel_remote_store_connected (CAMEL_REMOTE_STORE (store), ex)) - return NULL; - - /* lock around the whole lot to check/create atomically */ - CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); - if (!imap_folder_exists (imap_store, folder_name, - &selectable, &short_name, ex)) { - if ((flags & CAMEL_STORE_FOLDER_CREATE) == 0 - || (!imap_create (imap_store, folder_name, ex)) - || (!imap_folder_exists (imap_store, folder_name, - &selectable, &short_name, ex))) { - CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); - return NULL; - } - } - CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); - - if (!selectable) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - "%s is not a selectable folder", - folder_name); - g_free (short_name); - return NULL; - } - - summary_file = g_strdup_printf ("%s/%s/#summary", - imap_store->storage_path, - folder_name); - p = strrchr (summary_file, '/'); - *p = '\0'; - if (e_mkdir_hier (summary_file, S_IRWXU) == 0) { - *p = '/'; - new_folder = camel_imap_folder_new (store, folder_name, - short_name, summary_file, - ex); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create directory %s: %s"), - summary_file, g_strerror (errno)); - } - g_free (summary_file); - g_free (short_name); - - if (camel_exception_is_set (ex)) - return NULL; - - return new_folder; -} - -static char * -imap_concat (CamelImapStore *imap_store, const char *prefix, const char *suffix) -{ - int 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); -} - -static CamelFolderInfo * -create_folder (CamelStore *store, const char *parent_name, - const char *folder_name, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelFolderInfo *fi; - char *full_name; - - if (!parent_name) - parent_name = imap_store->namespace; - full_name = imap_concat (imap_store, parent_name, folder_name); - - imap_create (imap_store, full_name, ex); - if (camel_exception_is_set (ex)) { - g_free (full_name); - return NULL; - } - - fi = get_folder_info (store, full_name, FALSE, FALSE, FALSE, ex); - g_free (full_name); - - return fi; -} - -static CamelFolderInfo * -parse_list_response_as_folder_info (CamelImapStore *imap_store, - const char *response) -{ - CamelFolderInfo *fi; - int flags; - char sep, *dir, *name = NULL; - - if (!imap_parse_list_response (response, &flags, &sep, &dir)) - return NULL; - - if (sep) { - name = strrchr (dir, sep); - if (name && !*++name) { - g_free (dir); - return NULL; - } - } - - fi = g_new0 (CamelFolderInfo, 1); - fi->full_name = dir; - if (sep && name) - fi->name = g_strdup (name); - else - fi->name = g_strdup (dir); - if (!(flags & IMAP_LIST_FLAG_NOSELECT)) - fi->url = g_strdup_printf ("%s%s", imap_store->base_url, dir); - if (!(flags & IMAP_LIST_FLAG_UNMARKED)) - fi->unread_message_count = -1; - - return fi; -} - -static void -copy_folder_name (gpointer name, gpointer key, gpointer array) -{ - g_ptr_array_add (array, name); -} - -static void -get_subscribed_folders_by_hand (CamelImapStore *imap_store, const char *top, - GPtrArray *folders, CamelException *ex) -{ - GPtrArray *names; - CamelImapResponse *response; - CamelFolderInfo *fi; - char *result; - int i, toplen = strlen (top); - - names = g_ptr_array_new (); - g_hash_table_foreach (imap_store->subscribed_folders, - copy_folder_name, names); - - for (i = 0; i < names->len; i++) { - CAMEL_IMAP_STORE_LOCK (imap_store, command_lock); - response = camel_imap_command (imap_store, NULL, ex, - "LIST \"\" %S", - names->pdata[i]); - CAMEL_IMAP_STORE_UNLOCK (imap_store, command_lock); - - if (!response) { - g_ptr_array_free (names, TRUE); - return; - } - result = camel_imap_response_extract (response, "LIST", NULL); - if (!result) { - g_hash_table_remove (imap_store->subscribed_folders, - names->pdata[i]); - g_free (names->pdata[i]); - g_ptr_array_remove_index_fast (names, 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); -} - -static void -get_folders (CamelImapStore *imap_store, const char *pattern, - GPtrArray *folders, gboolean lsub, CamelException *ex) -{ - CamelImapResponse *response; - CamelFolderInfo *fi; - char *list; - int i; - - CAMEL_IMAP_STORE_LOCK (imap_store, command_lock); - response = camel_imap_command (imap_store, NULL, ex, - "%s \"\" %S", lsub ? "LSUB" : "LIST", - pattern); - CAMEL_IMAP_STORE_UNLOCK (imap_store, command_lock); - if (!response) - return; - - 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) - continue; - g_ptr_array_add (folders, fi); - } - camel_imap_response_free (response); -} - -static CamelFolderInfo * -get_folder_info (CamelStore *store, const char *top, gboolean fast, - gboolean recursive, gboolean subscribed_only, - CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - gboolean need_inbox = FALSE; - CamelImapResponse *response; - GPtrArray *folders; - const char *name, *p; - char *pattern, *status; - CamelFolderInfo *fi; - int i; - - if (!camel_remote_store_connected (CAMEL_REMOTE_STORE (store), ex)) - return NULL; - - /* Sync flag changes to the server so it has the same ideas about - * read/unread as we do. - */ - camel_store_sync (store, ex); - if (camel_exception_is_set (ex)) - return NULL; - - name = top; - if (!name) { - need_inbox = TRUE; - name = imap_store->namespace; - } - - folders = g_ptr_array_new (); - - get_folders (imap_store, name, folders, FALSE, ex); - if (camel_exception_is_set (ex)) - return NULL; - if (folders->len) { - fi = folders->pdata[0]; - if (!fi->url) - g_ptr_array_remove_index (folders, 0); - } - - if (subscribed_only && !imap_store->useful_lsub) - get_subscribed_folders_by_hand (imap_store, name, folders, ex); - else { - pattern = imap_concat (imap_store, name, recursive ? "*" : "%"); - get_folders (imap_store, pattern, folders, subscribed_only, ex); - g_free (pattern); - } - if (camel_exception_is_set (ex)) { - for (i = 0; i < folders->len; i++) - camel_folder_info_free (folders->pdata[i]); - g_ptr_array_free (folders, TRUE); - return NULL; - } - - /* Add INBOX, if necessary */ - if (need_inbox) { - for (i = 0; i < folders->len; i++) { - fi = folders->pdata[i]; - if (!g_strcasecmp (fi->full_name, "INBOX")) { - need_inbox = FALSE; - break; - } - } - } - if (need_inbox) { - fi = g_new0 (CamelFolderInfo, 1); - fi->full_name = g_strdup ("INBOX"); - fi->name = g_strdup ("INBOX"); - fi->url = g_strdup_printf ("%sINBOX", imap_store->base_url); - fi->unread_message_count = -1; - - g_ptr_array_add (folders, fi); - } - - if (!fast) { - /* Get unread counts */ - for (i = 0; i < folders->len; i++) { - fi = folders->pdata[i]; - if (!fi->url || fi->unread_message_count != -1) - continue; - - /* UW will give cached data for the currently - * selected folder. Grr. Well, I guess this - * also potentially saves us one IMAP command. - */ - if (imap_store->current_folder && - !strcmp (imap_store->current_folder->full_name, - fi->full_name)) { - fi->unread_message_count = camel_folder_get_unread_message_count (imap_store->current_folder); - continue; - } - - CAMEL_IMAP_STORE_LOCK (imap_store, command_lock); - response = camel_imap_command (imap_store, NULL, NULL, - "STATUS %S (UNSEEN)", - fi->full_name); - CAMEL_IMAP_STORE_UNLOCK (imap_store, command_lock); - if (!response) - continue; - status = camel_imap_response_extract (response, "STATUS", NULL); - if (!status) - continue; - - p = e_strstrcase (status, "UNSEEN"); - if (p) - fi->unread_message_count = strtoul (p + 6, NULL, 10); - g_free (status); - } - } - - /* And assemble. */ - fi = camel_folder_info_build (folders, name, imap_store->dir_sep, TRUE); - 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); - - g_return_val_if_fail (imap_store->subscribed_folders != NULL, FALSE); - - return g_hash_table_lookup (imap_store->subscribed_folders, - folder_name) != NULL; -} - -static void -subscribe_folder (CamelStore *store, const char *folder_name, - CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelImapResponse *response; - - if (!camel_remote_store_connected (CAMEL_REMOTE_STORE (store), ex)) - return; - - CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); - response = camel_imap_command (imap_store, NULL, ex, - "SUBSCRIBE %S", folder_name); - CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); - if (response) { - CamelFolderInfo *fi; - char *name; - - g_hash_table_insert (imap_store->subscribed_folders, - g_strdup (folder_name), - GUINT_TO_POINTER (1)); - - name = strrchr (folder_name, imap_store->dir_sep); - if (name) - name++; - - fi = g_new0 (CamelFolderInfo, 1); - fi->full_name = g_strdup (folder_name); - fi->name = g_strdup (name); - fi->url = g_strdup_printf ("%s%s", imap_store->base_url, folder_name); - fi->unread_message_count = -1; - - camel_object_trigger_event (CAMEL_OBJECT (store), - "folder_created", fi); - - camel_folder_info_free (fi); - } - camel_imap_response_free (response); -} - -static void -unsubscribe_folder (CamelStore *store, const char *folder_name, - CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelImapResponse *response; - gpointer key, value; - - if (!camel_remote_store_connected (CAMEL_REMOTE_STORE (store), ex)) - return; - - CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); - response = camel_imap_command (imap_store, NULL, ex, - "UNSUBSCRIBE %S", folder_name); - CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); - if (response) { - CamelFolderInfo *fi; - char *name; - - g_hash_table_lookup_extended (imap_store->subscribed_folders, - folder_name, &key, &value); - g_hash_table_remove (imap_store->subscribed_folders, - folder_name); - g_free (key); - - name = strrchr (folder_name, imap_store->dir_sep); - if (name) - name++; - - fi = g_new0 (CamelFolderInfo, 1); - fi->full_name = g_strdup (folder_name); - fi->name = g_strdup (name); - fi->url = g_strdup_printf ("%s%s", imap_store->base_url, folder_name); - fi->unread_message_count = -1; - - camel_object_trigger_event (CAMEL_OBJECT (store), - "folder_deleted", fi); - - camel_folder_info_free (fi); - } - camel_imap_response_free (response); -} - -static void -imap_keepalive (CamelRemoteStore *store) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelImapResponse *response; - - CAMEL_IMAP_STORE_LOCK(imap_store, command_lock); - response = camel_imap_command (imap_store, NULL, NULL, "NOOP"); - CAMEL_IMAP_STORE_UNLOCK(imap_store, command_lock); - camel_imap_response_free (response); -} diff --git a/camel/providers/imap/camel-imap-store.h b/camel/providers/imap/camel-imap-store.h deleted file mode 100644 index 3792e92872..0000000000 --- a/camel/providers/imap/camel-imap-store.h +++ /dev/null @@ -1,90 +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 - * - * Copyright (C) 2000 Helix Code, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_IMAP_STORE_H -#define CAMEL_IMAP_STORE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-imap-types.h" -#include "camel-remote-store.h" - -#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)) - -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) - -struct _CamelImapStore { - CamelRemoteStore parent_object; - struct _CamelImapStorePrivate *priv; - - CamelFolder *current_folder; - - guint32 command; - - CamelImapServerLevel server_level; - guint32 capabilities; - GHashTable *authtypes; - - char *namespace, dir_sep, *storage_path, *base_url; - - gboolean connected; - - GHashTable *subscribed_folders; - gboolean useful_lsub; -}; - - -typedef struct { - CamelRemoteStoreClass parent_class; - -} CamelImapStoreClass; - - -/* Standard Camel function */ -CamelType camel_imap_store_get_type (void); - -#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 66228649bc..0000000000 --- a/camel/providers/imap/camel-imap-summary.c +++ /dev/null @@ -1,215 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000 Helix Code Inc. - * - * Authors: - * Michael Zucchi - * Dan Winship - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include "camel-imap-summary.h" -#include - -#include -#include -#include -#include -#include -#include - -#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. - * @validity: the current UIDVALIDITY value of the folder - * - * This will create a new CamelImapSummary object and read in the - * summary data from disk, if it exists and has the right UIDVALIDITY - * value. - * - * Return value: A new CamelImapSummary object. - **/ -CamelFolderSummary * -camel_imap_summary_new (const char *filename, guint32 validity) -{ - CamelFolderSummary *summary = CAMEL_FOLDER_SUMMARY ( - camel_object_new (camel_imap_summary_get_type ())); - CamelImapSummary *imap_summary = (CamelImapSummary *)summary; - - camel_folder_summary_set_build_content (summary, TRUE); - camel_folder_summary_set_filename (summary, filename); - - if (camel_folder_summary_load (summary) == -1) { - if (errno == ENOENT) { - imap_summary->validity = validity; - return summary; - } else { - /* FIXME: are there error conditions where this won't work? */ - camel_folder_summary_clear (summary); - camel_folder_summary_touch (summary); - - return summary; - } - } - - if (imap_summary->validity != validity) { - camel_folder_summary_clear (summary); - imap_summary->validity = validity; - } - - 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_folder_summary_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_folder_summary_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_folder_summary_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_folder_summary_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); -} diff --git a/camel/providers/imap/camel-imap-summary.h b/camel/providers/imap/camel-imap-summary.h deleted file mode 100644 index 7ad1e3f4e8..0000000000 --- a/camel/providers/imap/camel-imap-summary.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2000 Helix Code Inc. - * - * Authors: - * Michael Zucchi - * Dan Winship - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef _CAMEL_IMAP_SUMMARY_H -#define _CAMEL_IMAP_SUMMARY_H - -#include "camel-imap-types.h" -#include -#include - -#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) - -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; - -}; - -guint camel_imap_summary_get_type (void); -CamelFolderSummary *camel_imap_summary_new (const char *filename, - guint32 validity); - -#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 af5d8b8c77..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 Helix Code, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_IMAP_TYPES_H -#define CAMEL_IMAP_TYPES_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-types.h" - -typedef struct _CamelImapResponse CamelImapResponse; -typedef struct _CamelImapFolder CamelImapFolder; -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 8116f12386..0000000000 --- a/camel/providers/imap/camel-imap-utils.c +++ /dev/null @@ -1,568 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2000 Helix Code, Inc. (www.helixcode.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - -#include -#include -#include -#include - -#include "camel-imap-utils.h" -#include "camel-imap-summary.h" -#include "camel-folder.h" - -#define d(x) x - -char * -imap_next_word (const char *buf) -{ - char *word; - - /* skip over current word */ - for (word = (char *)buf; *word && *word != ' '; word++); - - /* skip over white space */ - for ( ; *word && *word == ' '; word++); - - return word; -} - -/** - * imap_parse_list_response: - * @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 (const char *buf, int *flags, char *sep, char **folder) -{ - char *word; - int len; - - if (*buf != '*') - return FALSE; - - word = imap_next_word (buf); - if (g_strncasecmp (word, "LIST", 4) && g_strncasecmp (word, "LSUB", 4)) - return FALSE; - - /* 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 |= IMAP_LIST_FLAG_NOINFERIORS; - else if (!g_strncasecmp (word, "\\Noselect", len)) - *flags |= IMAP_LIST_FLAG_NOSELECT; - else if (!g_strncasecmp (word, "\\Marked", len)) - *flags |= IMAP_LIST_FLAG_MARKED; - else if (!g_strncasecmp (word, "\\Unmarked", len)) - *flags |= IMAP_LIST_FLAG_UNMARKED; - } - - 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) { - /* get the folder name */ - word = imap_next_word (word); - *folder = imap_parse_astring (&word, &len); - return *folder != NULL; - } - - return TRUE; -} - -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; - - flag_list += len; - if (*flag_list == ' ') - flag_list++; - } - - if (*flag_list++ != ')') { - *flag_list_p = NULL; - return 0; - } - - *flag_list_p = flag_list; - return flags; -} - -static char imap_atom_specials[128] = { - 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, - 1, 0, 1, 0, 0, 1, 0, 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, 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, 1, 0, 0, 0, 0, -}; -#define imap_is_atom_char(ch) (isascii (ch) && !imap_atom_specials[ch]) - -/** - * imap_parse_string_generic: - * @str_p: a pointer to a string - * @len: a pointer to an int 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 (char **str_p, int *len, int type) -{ - char *str = *str_p; - char *out; - - if (!str) - return NULL; - else if (*str == '"') { - char *p; - int size; - - str++; - size = strcspn (str, "\"") + 1; - p = out = g_malloc (size); - - while (*str && *str != '"') { - 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; - str = g_strndup (*str_p, *len); - *str_p += *len; - return str; - } else { - *str_p = NULL; - return NULL; - } -} - -static inline void -skip_char (char **str_p, char ch) -{ - if (*str_p && **str_p == ch) - *str_p = *str_p + 1; - else - *str_p = NULL; -} - -/* Skip atom, string, or number */ -static void -skip_asn (char **str_p) -{ - 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, &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; - } -} - -static void -skip_list (char **str_p) -{ - skip_char (str_p, '('); - while (*str_p && **str_p != ')') { - if (**str_p == '(') - 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 (char **parms_p, CamelContentType *type) -{ - char *parms = *parms_p, *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 filles 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 (char **body_p, CamelFolder *folder, - CamelMessageContentInfo *ci) -{ - char *body = *body_p; - CamelMessageContentInfo *child; - CamelContentType *type; - int len; - - if (*body++ != '(') { - *body_p = NULL; - return; - } - - if (*body == '(') { - /* multipart */ - GPtrArray *children; - char *subtype; - int i; - - /* Parse the child body parts */ - children = g_ptr_array_new (); - i = 0; - 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; - - 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, &body, 10); - - child = NULL; - if (header_content_type_is (type, "message", "rfc822")) { - skip_char (&body, ' '); - 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, &body, 10); - } else if (header_content_type_is (type, "text", "*")) { - if (body) - strtoul (body, &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; - - len = strlen (str); - p = str; - while ((p = strpbrk (p, "\"\\"))) { - len++; - p++; - } - - quoted = q = g_malloc (len + 3); - *q++ = '"'; - while ((p = strpbrk (str, "\"\\"))) { - memcpy (q, str, p - str); - q += p - str; - *q++ = '\\'; - *q++ = *p++; - str = p; - } - sprintf (q, "%s\"", str); - - return quoted; -} diff --git a/camel/providers/imap/camel-imap-utils.h b/camel/providers/imap/camel-imap-utils.h deleted file mode 100644 index 985f177b3a..0000000000 --- a/camel/providers/imap/camel-imap-utils.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast - * - * Copyright 2000 Helix Code, Inc. (www.helixcode.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #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 "camel-folder-summary.h" - -char *imap_next_word (const char *buf); - -#define IMAP_LIST_FLAG_NOINFERIORS (1 << 0) -#define IMAP_LIST_FLAG_NOSELECT (1 << 1) -#define IMAP_LIST_FLAG_MARKED (1 << 2) -#define IMAP_LIST_FLAG_UNMARKED (1 << 3) -gboolean imap_parse_list_response (const char *buf, int *flags, char *sep, char **folder); - -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 (char **str_p, int *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 (char **body_p, CamelFolder *folder, - CamelMessageContentInfo *ci); - -char *imap_quote_string (const char *str); - -#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 e4d06a009b..0000000000 --- a/camel/providers/imap/camel-imap-wrapper.c +++ /dev/null @@ -1,234 +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 - * - * Copyright 2000 Helix Code, Inc. (http://www.helixcode.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include - -#include "camel-imap-wrapper.h" -#include "camel-imap-command.h" -#include "camel-imap-store.h" -#include "camel-imap-utils.h" -#include "camel-imap-private.h" -#include "camel-exception.h" -#include "camel-folder.h" -#include "camel-stream-mem.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" - -#include -#include - -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 int -write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) -{ - CamelImapWrapper *imap_wrapper = CAMEL_IMAP_WRAPPER (data_wrapper); - CamelImapStore *store; - CamelImapResponse *response; - CamelStream *memstream; - CamelStreamFilter *filterstream; - CamelMimeFilter *filter; - CamelContentType *ct; - char *result, *p, *body; - int len; - - CAMEL_IMAP_WRAPPER_LOCK (imap_wrapper, lock); - if (!data_wrapper->offline) { - CAMEL_IMAP_WRAPPER_UNLOCK (imap_wrapper, lock); - return parent_class->write_to_stream (data_wrapper, stream); - } - - store = CAMEL_IMAP_STORE (imap_wrapper->folder->parent_store); - CAMEL_IMAP_STORE_LOCK (store, command_lock); - response = camel_imap_command (store, imap_wrapper->folder, NULL, - "UID FETCH %s BODY.PEEK[%s]", - imap_wrapper->uid, - imap_wrapper->part_spec); - CAMEL_IMAP_STORE_UNLOCK (store, command_lock); - if (!response) - goto lose; - - result = camel_imap_response_extract (response, "FETCH", NULL); - if (!result) - goto lose; - - p = strchr (result, ']'); - if (!p) { - g_free (result); - goto lose; - } - p += 2; - - body = imap_parse_nstring (&p, &len); - g_free (result); - if (!body) - goto lose; - - memstream = camel_stream_mem_new_with_buffer (body, len); - g_free (body); - filterstream = camel_stream_filter_new_with_stream (memstream); - - if (camel_mime_part_get_encoding (imap_wrapper->part) == - 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); - } else if (camel_mime_part_get_encoding (imap_wrapper->part) == - 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); - } else - 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, 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; - - CAMEL_IMAP_WRAPPER_UNLOCK (imap_wrapper, lock); - - return parent_class->write_to_stream (data_wrapper, stream); - - lose: - CAMEL_IMAP_WRAPPER_UNLOCK (imap_wrapper, lock); - errno = ENETUNREACH; - return -1; -} - - -CamelDataWrapper * -camel_imap_wrapper_new (CamelFolder *folder, CamelContentType *type, - const char *uid, const char *part_spec, - CamelMimePart *part) -{ - CamelImapWrapper *imap_wrapper; - - 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 = folder; - camel_object_ref (CAMEL_OBJECT (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; - - 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 8eb9d0969a..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 Helix Code, Inc. (http://www.helixcode.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_IMAP_WRAPPER_H -#define CAMEL_IMAP_WRAPPER_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include - -#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; - - CamelFolder *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 (CamelFolder *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 -- cgit v1.2.3