From d184ede3a56453f95e09479de75e38e8e6a9c2a2 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Tue, 6 Apr 2010 19:43:19 -0400 Subject: [PATCH] Drop the "imap4" Camel provider. IMAPX is the future. --- camel/providers/Makefile.am | 6 +- camel/providers/imap4/Makefile.am | 49 - camel/providers/imap4/camel-imap4-command.c | 728 --------- camel/providers/imap4/camel-imap4-command.h | 142 -- camel/providers/imap4/camel-imap4-engine.c | 1775 -------------------- camel/providers/imap4/camel-imap4-engine.h | 233 --- camel/providers/imap4/camel-imap4-folder.c | 1274 --------------- camel/providers/imap4/camel-imap4-folder.h | 86 - camel/providers/imap4/camel-imap4-journal.c | 354 ---- camel/providers/imap4/camel-imap4-journal.h | 84 - camel/providers/imap4/camel-imap4-provider.c | 150 -- camel/providers/imap4/camel-imap4-search.c | 310 ---- camel/providers/imap4/camel-imap4-search.h | 69 - camel/providers/imap4/camel-imap4-specials.c | 99 -- camel/providers/imap4/camel-imap4-specials.h | 51 - camel/providers/imap4/camel-imap4-store-summary.c | 400 ----- camel/providers/imap4/camel-imap4-store-summary.h | 82 - camel/providers/imap4/camel-imap4-store.c | 1799 --------------------- camel/providers/imap4/camel-imap4-store.h | 58 - camel/providers/imap4/camel-imap4-stream.c | 723 --------- camel/providers/imap4/camel-imap4-stream.h | 120 -- camel/providers/imap4/camel-imap4-summary.c | 1662 ------------------- camel/providers/imap4/camel-imap4-summary.h | 99 -- camel/providers/imap4/camel-imap4-utils.c | 788 --------- camel/providers/imap4/camel-imap4-utils.h | 104 -- camel/providers/imap4/libcamelimap4.urls | 1 - configure.ac | 17 - 27 files changed, 1 insertion(+), 11262 deletions(-) delete mode 100644 camel/providers/imap4/Makefile.am delete mode 100644 camel/providers/imap4/camel-imap4-command.c delete mode 100644 camel/providers/imap4/camel-imap4-command.h delete mode 100644 camel/providers/imap4/camel-imap4-engine.c delete mode 100644 camel/providers/imap4/camel-imap4-engine.h delete mode 100644 camel/providers/imap4/camel-imap4-folder.c delete mode 100644 camel/providers/imap4/camel-imap4-folder.h delete mode 100644 camel/providers/imap4/camel-imap4-journal.c delete mode 100644 camel/providers/imap4/camel-imap4-journal.h delete mode 100644 camel/providers/imap4/camel-imap4-provider.c delete mode 100644 camel/providers/imap4/camel-imap4-search.c delete mode 100644 camel/providers/imap4/camel-imap4-search.h delete mode 100644 camel/providers/imap4/camel-imap4-specials.c delete mode 100644 camel/providers/imap4/camel-imap4-specials.h delete mode 100644 camel/providers/imap4/camel-imap4-store-summary.c delete mode 100644 camel/providers/imap4/camel-imap4-store-summary.h delete mode 100644 camel/providers/imap4/camel-imap4-store.c delete mode 100644 camel/providers/imap4/camel-imap4-store.h delete mode 100644 camel/providers/imap4/camel-imap4-stream.c delete mode 100644 camel/providers/imap4/camel-imap4-stream.h delete mode 100644 camel/providers/imap4/camel-imap4-summary.c delete mode 100644 camel/providers/imap4/camel-imap4-summary.h delete mode 100644 camel/providers/imap4/camel-imap4-utils.c delete mode 100644 camel/providers/imap4/camel-imap4-utils.h delete mode 100644 camel/providers/imap4/libcamelimap4.urls diff --git a/camel/providers/Makefile.am b/camel/providers/Makefile.am index 5cdbafa..56de312 100644 --- a/camel/providers/Makefile.am +++ b/camel/providers/Makefile.am @@ -2,10 +2,6 @@ if ENABLE_NNTP NNTP_DIR=nntp endif -if ENABLE_IMAP4 -IMAP4_DIR=imap4 -endif - if ENABLE_HULA HULA_DIR=hula endif @@ -15,6 +11,6 @@ else SENDMAIL_DIR=sendmail endif -SUBDIRS = pop3 $(SENDMAIL_DIR) smtp imap imapx $(IMAP4_DIR) $(NNTP_DIR) local groupwise $(HULA_DIR) +SUBDIRS = pop3 $(SENDMAIL_DIR) smtp imap imapx $(NNTP_DIR) local groupwise $(HULA_DIR) -include $(top_srcdir)/git.mk diff --git a/camel/providers/imap4/Makefile.am b/camel/providers/imap4/Makefile.am deleted file mode 100644 index 7b85498..0000000 --- a/camel/providers/imap4/Makefile.am +++ /dev/null @@ -1,49 +0,0 @@ -camel_provider_LTLIBRARIES = libcamelimap4.la -camel_provider_DATA = libcamelimap4.urls - -libcamelimap4_la_CPPFLAGS = \ - $(AM_CPPFLAGS) \ - -I$(top_srcdir) \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir) \ - $(CAMEL_CFLAGS) \ - $(GNOME_INCLUDEDIR) \ - $(GTK_INCLUDEDIR) \ - -DG_LOG_DOMAIN=\"camel-imap4-provider\" - -libcamelimap4_la_SOURCES = \ - camel-imap4-command.c \ - camel-imap4-command.h \ - camel-imap4-engine.c \ - camel-imap4-engine.h \ - camel-imap4-folder.c \ - camel-imap4-folder.h \ - camel-imap4-journal.c \ - camel-imap4-journal.h \ - camel-imap4-provider.c \ - camel-imap4-search.c \ - camel-imap4-search.h \ - camel-imap4-specials.c \ - camel-imap4-specials.h \ - camel-imap4-store.c \ - camel-imap4-store.h \ - camel-imap4-store-summary.c \ - camel-imap4-store-summary.h \ - camel-imap4-stream.c \ - camel-imap4-stream.h \ - camel-imap4-summary.c \ - camel-imap4-summary.h \ - camel-imap4-utils.c \ - camel-imap4-utils.h - -libcamelimap4_la_LDFLAGS = -avoid-version -module $(NO_UNDEFINED) - -libcamelimap4_la_LIBADD = \ - $(top_builddir)/libedataserver/libedataserver-${API_VERSION}.la \ - $(top_builddir)/camel/libcamel-provider-1.2.la \ - $(top_builddir)/camel/libcamel-1.2.la \ - $(CAMEL_LIBS) - -EXTRA_DIST = libcamelimap4.urls - --include $(top_srcdir)/git.mk diff --git a/camel/providers/imap4/camel-imap4-command.c b/camel/providers/imap4/camel-imap4-command.c deleted file mode 100644 index 6cdca40..0000000 --- a/camel/providers/imap4/camel-imap4-command.c +++ /dev/null @@ -1,728 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include "camel-imap4-command.h" -#include "camel-imap4-engine.h" -#include "camel-imap4-folder.h" -#include "camel-imap4-specials.h" -#include "camel-imap4-stream.h" - -#define d(x) (camel_debug ("imap4:command") ? (x) : 0) - -enum { - IMAP4_STRING_ATOM, - IMAP4_STRING_QSTRING, - IMAP4_STRING_LITERAL, -}; - -static gint -imap4_string_get_type (const gchar *str) -{ - gint type = 0; - - while (*str) { - if (!is_atom (*str)) { - if (is_qsafe (*str)) - type = IMAP4_STRING_QSTRING; - else - return IMAP4_STRING_LITERAL; - } - str++; - } - - return type; -} - -#if 0 -static gboolean -imap4_string_is_atom_safe (const gchar *str) -{ - while (is_atom (*str)) - str++; - - return *str == '\0'; -} - -static gboolean -imap4_string_is_quote_safe (const gchar *str) -{ - while (is_qsafe (*str)) - str++; - - return *str == '\0'; -} -#endif - -static gsize -camel_imap4_literal_length (CamelIMAP4Literal *literal) -{ - CamelStream *stream, *null; - CamelMimeFilter *crlf; - gsize len; - - if (literal->type == CAMEL_IMAP4_LITERAL_STRING) - return strlen (literal->literal.string); - - null = camel_stream_null_new (); - crlf = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); - stream = (CamelStream *) camel_stream_filter_new_with_stream (null); - camel_stream_filter_add ((CamelStreamFilter *) stream, crlf); - camel_object_unref (crlf); - - switch (literal->type) { - case CAMEL_IMAP4_LITERAL_STREAM: - camel_stream_write_to_stream (literal->literal.stream, stream); - camel_stream_reset (literal->literal.stream); - break; - case CAMEL_IMAP4_LITERAL_WRAPPER: - camel_data_wrapper_write_to_stream (literal->literal.wrapper, stream); - break; - default: - g_assert_not_reached (); - break; - } - - len = ((CamelStreamNull *) null)->written; - - camel_object_unref (stream); - camel_object_unref (null); - - return len; -} - -static CamelIMAP4CommandPart * -command_part_new (void) -{ - CamelIMAP4CommandPart *part; - - part = g_new (CamelIMAP4CommandPart, 1); - part->next = NULL; - part->buffer = NULL; - part->buflen = 0; - part->literal = NULL; - - return part; -} - -static void -imap4_command_append_string (CamelIMAP4Engine *engine, CamelIMAP4CommandPart **tail, GString *str, const gchar *string) -{ - CamelIMAP4CommandPart *part; - CamelIMAP4Literal *literal; - register const gchar *inptr; - const gchar *start; - - switch (imap4_string_get_type (string)) { - case IMAP4_STRING_ATOM: - /* string is safe as it is... */ - g_string_append (str, string); - break; - case IMAP4_STRING_QSTRING: - /* we need to quote the string */ - g_string_append_c (str, '"'); - - inptr = string; - while (*inptr) { - start = string; - while (*inptr && *inptr != '\\' && *inptr != '"') - inptr++; - - if (inptr > start) - g_string_append_len (str, start, inptr - start); - - if (*inptr != '\0') { - g_string_append_c (str, '\\'); - g_string_append_c (str, *inptr); - inptr++; - } - } - - g_string_append_c (str, '"'); - break; - case IMAP4_STRING_LITERAL: - if (engine->capa & CAMEL_IMAP4_CAPABILITY_LITERALPLUS) { - /* we have to send a literal, but the server supports LITERAL+ so use that */ - g_string_append_printf (str, "{%u+}\r\n%s", strlen (string), string); - } else { - /* we have to make it a literal */ - literal = g_new (CamelIMAP4Literal, 1); - literal->type = CAMEL_IMAP4_LITERAL_STRING; - literal->literal.string = g_strdup (string); - - g_string_append_printf (str, "{%u}\r\n", strlen (string)); - - (*tail)->buffer = g_strdup (str->str); - (*tail)->buflen = str->len; - (*tail)->literal = literal; - - part = command_part_new (); - (*tail)->next = part; - (*tail) = part; - - g_string_truncate (str, 0); - } - break; - } -} - -CamelIMAP4Command * -camel_imap4_command_newv (CamelIMAP4Engine *engine, CamelIMAP4Folder *imap4_folder, const gchar *format, va_list args) -{ - CamelIMAP4CommandPart *parts, *part, *tail; - CamelIMAP4Command *ic; - const gchar *start; - GString *str; - - tail = parts = command_part_new (); - - str = g_string_new (""); - start = format; - - while (*format) { - register gchar ch = *format++; - - if (ch == '%') { - CamelIMAP4Literal *literal; - CamelIMAP4Folder *folder; - gchar *function, **strv; - guint u; - gchar *string; - gsize len; - gpointer obj; - gint c, d; - - g_string_append_len (str, start, format - start - 1); - - switch (*format) { - case '%': - /* literal % */ - g_string_append_c (str, '%'); - break; - case 'c': - /* character */ - c = va_arg (args, gint); - g_string_append_c (str, c); - break; - case 'd': - /* integer */ - d = va_arg (args, gint); - g_string_append_printf (str, "%d", d); - break; - case 'u': - /* unsigned integer */ - u = va_arg (args, guint); - g_string_append_printf (str, "%u", u); - break; - case 'F': - /* CamelIMAP4Folder */ - folder = va_arg (args, CamelIMAP4Folder *); - string = (gchar *) camel_imap4_folder_utf7_name (folder); - imap4_command_append_string (engine, &tail, str, string); - break; - case 'L': - /* Literal */ - obj = va_arg (args, gpointer ); - - literal = g_new (CamelIMAP4Literal, 1); - if (CAMEL_IS_DATA_WRAPPER (obj)) { - literal->type = CAMEL_IMAP4_LITERAL_WRAPPER; - literal->literal.wrapper = obj; - } else if (CAMEL_IS_STREAM (obj)) { - literal->type = CAMEL_IMAP4_LITERAL_STREAM; - literal->literal.stream = obj; - } else { - g_assert_not_reached (); - } - - camel_object_ref (obj); - - /* FIXME: take advantage of LITERAL+? */ - len = camel_imap4_literal_length (literal); - g_string_append_printf (str, "{%u}\r\n", len); - - tail->buffer = g_strdup (str->str); - tail->buflen = str->len; - tail->literal = literal; - - part = command_part_new (); - tail->next = part; - tail = part; - - g_string_truncate (str, 0); - - break; - case 'V': - /* a string vector of arguments which may need to be quoted or made into literals */ - function = str->str + str->len - 2; - while (*function != ' ') - function--; - function++; - - function = g_strdup (function); - - strv = va_arg (args, gchar **); - for (d = 0; strv[d]; d++) { - if (d > 0) - g_string_append (str, function); - imap4_command_append_string (engine, &tail, str, strv[d]); - } - - g_free (function); - break; - case 'S': - /* string which may need to be quoted or made into a literal */ - string = va_arg (args, gchar *); - imap4_command_append_string (engine, &tail, str, string); - break; - case 's': - /* safe atom string */ - string = va_arg (args, gchar *); - g_string_append (str, string); - break; - default: - g_warning ("unknown formatter %%%c", *format); - g_string_append_c (str, '%'); - g_string_append_c (str, *format); - break; - } - - format++; - - start = format; - } - } - - g_string_append (str, start); - tail->buffer = str->str; - tail->buflen = str->len; - tail->literal = NULL; - g_string_free (str, FALSE); - - ic = g_new0 (CamelIMAP4Command, 1); - ((CamelDListNode *) ic)->next = NULL; - ((CamelDListNode *) ic)->prev = NULL; - ic->untagged = g_hash_table_new (g_str_hash, g_str_equal); - ic->status = CAMEL_IMAP4_COMMAND_QUEUED; - ic->result = CAMEL_IMAP4_RESULT_NONE; - ic->resp_codes = g_ptr_array_new (); - ic->engine = engine; - ic->ref_count = 1; - ic->parts = parts; - ic->part = parts; - ic->reset = NULL; - ic->plus = NULL; - ic->tag = NULL; - ic->id = -1; - - camel_exception_init (&ic->ex); - - ic->user_data = NULL; - - if (imap4_folder) { - camel_object_ref (imap4_folder); - ic->folder = imap4_folder; - } else - ic->folder = NULL; - - return ic; -} - -CamelIMAP4Command * -camel_imap4_command_new (CamelIMAP4Engine *engine, CamelIMAP4Folder *folder, const gchar *format, ...) -{ - CamelIMAP4Command *command; - va_list args; - - va_start (args, format); - command = camel_imap4_command_newv (engine, folder, format, args); - va_end (args); - - return command; -} - -void -camel_imap4_command_register_untagged (CamelIMAP4Command *ic, const gchar *atom, CamelIMAP4UntaggedCallback untagged) -{ - g_hash_table_insert (ic->untagged, g_strdup (atom), untagged); -} - -void -camel_imap4_command_ref (CamelIMAP4Command *ic) -{ - ic->ref_count++; -} - -void -camel_imap4_command_unref (CamelIMAP4Command *ic) -{ - CamelIMAP4CommandPart *part, *next; - gint i; - - if (ic == NULL) - return; - - ic->ref_count--; - if (ic->ref_count == 0) { - if (ic->folder) - camel_object_unref (ic->folder); - - g_free (ic->tag); - - for (i = 0; i < ic->resp_codes->len; i++) { - CamelIMAP4RespCode *resp_code; - - resp_code = ic->resp_codes->pdata[i]; - camel_imap4_resp_code_free (resp_code); - } - g_ptr_array_free (ic->resp_codes, TRUE); - - g_hash_table_foreach (ic->untagged, (GHFunc) g_free, NULL); - g_hash_table_destroy (ic->untagged); - - camel_exception_clear (&ic->ex); - - part = ic->parts; - while (part != NULL) { - g_free (part->buffer); - if (part->literal) { - switch (part->literal->type) { - case CAMEL_IMAP4_LITERAL_STRING: - g_free (part->literal->literal.string); - break; - case CAMEL_IMAP4_LITERAL_STREAM: - camel_object_unref (part->literal->literal.stream); - break; - case CAMEL_IMAP4_LITERAL_WRAPPER: - camel_object_unref (part->literal->literal.wrapper); - break; - } - - g_free (part->literal); - } - - next = part->next; - g_free (part); - part = next; - } - - g_free (ic); - } -} - -static gint -imap4_literal_write_to_stream (CamelIMAP4Literal *literal, CamelStream *stream) -{ - CamelStream *istream, *ostream = NULL; - CamelDataWrapper *wrapper; - CamelMimeFilter *crlf; - gchar *string; - - if (literal->type == CAMEL_IMAP4_LITERAL_STRING) { - string = literal->literal.string; - if (camel_stream_write (stream, string, strlen (string)) == -1) - return -1; - - return 0; - } - - crlf = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); - ostream = (CamelStream *) camel_stream_filter_new_with_stream (stream); - camel_stream_filter_add ((CamelStreamFilter *) ostream, crlf); - camel_object_unref (crlf); - - /* write the literal */ - switch (literal->type) { - case CAMEL_IMAP4_LITERAL_STREAM: - istream = literal->literal.stream; - if (camel_stream_write_to_stream (istream, ostream) == -1) - goto exception; - break; - case CAMEL_IMAP4_LITERAL_WRAPPER: - wrapper = literal->literal.wrapper; - if (camel_data_wrapper_write_to_stream (wrapper, ostream) == -1) - goto exception; - break; - } - - camel_object_unref (ostream); - ostream = NULL; - -#if 0 - if (camel_stream_write (stream, "\r\n", 2) == -1) - return -1; -#endif - - return 0; - - exception: - - camel_object_unref (ostream); - - return -1; -} - -static void -unexpected_token (camel_imap4_token_t *token) -{ - switch (token->token) { - case CAMEL_IMAP4_TOKEN_NO_DATA: - fprintf (stderr, "*** NO DATA ***"); - break; - case CAMEL_IMAP4_TOKEN_ERROR: - fprintf (stderr, "*** ERROR ***"); - break; - case CAMEL_IMAP4_TOKEN_NIL: - fprintf (stderr, "NIL"); - break; - case CAMEL_IMAP4_TOKEN_ATOM: - fprintf (stderr, "%s", token->v.atom); - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - fprintf (stderr, "\"%s\"", token->v.qstring); - break; - case CAMEL_IMAP4_TOKEN_LITERAL: - fprintf (stderr, "{%u}", token->v.literal); - break; - default: - fprintf (stderr, "%c", (guchar) (token->token & 0xff)); - break; - } -} - -gint -camel_imap4_command_step (CamelIMAP4Command *ic) -{ - CamelIMAP4Engine *engine = ic->engine; - gint result = CAMEL_IMAP4_RESULT_NONE; - CamelIMAP4Literal *literal; - camel_imap4_token_t token; - guchar *linebuf; - gsize len; - - g_assert (ic->part != NULL); - - if (ic->part == ic->parts) { - ic->tag = g_strdup_printf ("%c%.5u", engine->tagprefix, engine->tag++); - camel_stream_printf (engine->ostream, "%s ", ic->tag); - d(fprintf (stderr, "sending: %s ", ic->tag)); - } - - if (camel_debug ("imap4:command")) { - gint sending = ic->part != ic->parts; - guchar *eoln, *eob; - - linebuf = ic->part->buffer; - eob = linebuf + ic->part->buflen; - - do { - eoln = linebuf; - while (eoln < eob && *eoln != '\n') - eoln++; - - if (eoln < eob) - eoln++; - - if (sending) - fwrite ("sending: ", 1, 10, stderr); - fwrite (linebuf, 1, eoln - linebuf, stderr); - - linebuf = eoln + 1; - sending = 1; - } while (linebuf < eob); - } - - linebuf = ic->part->buffer; - len = ic->part->buflen; - - if (camel_stream_write (engine->ostream, linebuf, len) == -1) { - camel_exception_setv (&ic->ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed sending command to IMAP server %s: %s"), - engine->url->host, g_strerror (errno)); - goto exception; - } - - if (camel_stream_flush (engine->ostream) == -1) { - camel_exception_setv (&ic->ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed sending command to IMAP server %s: %s"), - engine->url->host, g_strerror (errno)); - goto exception; - } - - /* now we need to read the response(s) from the IMAP4 server */ - - do { - if (camel_imap4_engine_next_token (engine, &token, &ic->ex) == -1) - goto exception; - - if (token.token == '+') { - /* we got a continuation response from the server */ - literal = ic->part->literal; - - if (camel_imap4_engine_line (engine, &linebuf, &len, &ic->ex) == -1) - goto exception; - - if (literal) { - if (imap4_literal_write_to_stream (literal, engine->ostream) == -1) - goto exception; - - g_free (linebuf); - linebuf = NULL; - - break; - } else if (ic->plus) { - /* command expected a '+' response - probably AUTHENTICATE? */ - if (ic->plus (engine, ic, linebuf, len, &ic->ex) == -1) { - g_free (linebuf); - return -1; - } - - /* now we need to wait for a " OK/NO/BAD" response */ - } else { - /* FIXME: error?? */ - g_assert_not_reached (); - } - - g_free (linebuf); - linebuf = NULL; - } else if (token.token == '*') { - /* we got an untagged response, let the engine handle this */ - if (camel_imap4_engine_handle_untagged_1 (engine, &token, &ic->ex) == -1) - goto exception; - } else if (token.token == CAMEL_IMAP4_TOKEN_ATOM && !strcmp (token.v.atom, ic->tag)) { - /* we got " OK/NO/BAD" */ - d(fprintf (stderr, "got %s response\n", token.v.atom)); - - if (camel_imap4_engine_next_token (engine, &token, &ic->ex) == -1) - goto exception; - - if (token.token == CAMEL_IMAP4_TOKEN_ATOM) { - if (!strcmp (token.v.atom, "OK")) - result = CAMEL_IMAP4_RESULT_OK; - else if (!strcmp (token.v.atom, "NO")) - result = CAMEL_IMAP4_RESULT_NO; - else if (!strcmp (token.v.atom, "BAD")) - result = CAMEL_IMAP4_RESULT_BAD; - - if (result == CAMEL_IMAP4_RESULT_NONE) { - d(fprintf (stderr, "expected OK/NO/BAD but got %s\n", token.v.atom)); - goto unexpected; - } - - if (camel_imap4_engine_next_token (engine, &token, &ic->ex) == -1) - goto exception; - - if (token.token == '[') { - /* we have a response code */ - camel_imap4_stream_unget_token (engine->istream, &token); - if (camel_imap4_engine_parse_resp_code (engine, &ic->ex) == -1) - goto exception; - } else if (token.token != '\n') { - /* just gobble up the rest of the line */ - if (camel_imap4_engine_line (engine, NULL, NULL, &ic->ex) == -1) - goto exception; - } - } else { - if (camel_debug ("imap4:command")) { - fprintf (stderr, "expected anything but this: "); - unexpected_token (&token); - fprintf (stderr, "\n"); - } - - goto unexpected; - } - - break; - } else { - if (camel_debug ("imap4:command")) { - fprintf (stderr, "wtf is this: "); - unexpected_token (&token); - fprintf (stderr, "\n"); - } - - unexpected: - - if (camel_imap4_engine_line (engine, &linebuf, &len, &ic->ex) == -1) - goto exception; - - camel_exception_setv (&ic->ex, CAMEL_EXCEPTION_SYSTEM, - _("Unexpected response from IMAP4 server %s: %s"), - engine->url->host, linebuf); - - g_free (linebuf); - - goto exception; - } - } while (1); - - /* status should always be ACTIVE here... */ - if (ic->status == CAMEL_IMAP4_COMMAND_ACTIVE) { - ic->part = ic->part->next; - if (ic->part == NULL || result) { - ic->status = CAMEL_IMAP4_COMMAND_COMPLETE; - ic->result = result; - return 1; - } - } - - return 0; - - exception: - - ic->status = CAMEL_IMAP4_COMMAND_ERROR; - - return -1; -} - -void -camel_imap4_command_reset (CamelIMAP4Command *ic) -{ - gint i; - - for (i = 0; i < ic->resp_codes->len; i++) - camel_imap4_resp_code_free (ic->resp_codes->pdata[i]); - g_ptr_array_set_size (ic->resp_codes, 0); - - if (ic->reset && ic->user_data) - ic->reset (ic, ic->user_data); - - ic->status = CAMEL_IMAP4_COMMAND_QUEUED; - ic->result = CAMEL_IMAP4_RESULT_NONE; - ic->part = ic->parts; - g_free (ic->tag); - ic->tag = NULL; - - camel_exception_clear (&ic->ex); -} diff --git a/camel/providers/imap4/camel-imap4-command.h b/camel/providers/imap4/camel-imap4-command.h deleted file mode 100644 index 7b6e504..0000000 --- a/camel/providers/imap4/camel-imap4-command.h +++ /dev/null @@ -1,142 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef CAMEL_IMAP4_COMMAND_H -#define CAMEL_IMAP4_COMMAND_H - -#include - -#include - -#include -#include -#include -#include - -G_BEGIN_DECLS - -struct _CamelIMAP4Engine; -struct _CamelIMAP4Folder; -struct _camel_imap4_token_t; - -typedef struct _CamelIMAP4Command CamelIMAP4Command; -typedef struct _CamelIMAP4Literal CamelIMAP4Literal; - -typedef gint (* CamelIMAP4PlusCallback) (struct _CamelIMAP4Engine *engine, - CamelIMAP4Command *ic, - const guchar *linebuf, - gsize linelen, CamelException *ex); - -typedef gint (* CamelIMAP4UntaggedCallback) (struct _CamelIMAP4Engine *engine, - CamelIMAP4Command *ic, - guint32 index, - struct _camel_imap4_token_t *token, - CamelException *ex); - -typedef void (* CamelIMAP4CommandReset) (CamelIMAP4Command *ic, gpointer user_data); - -enum { - CAMEL_IMAP4_LITERAL_STRING, - CAMEL_IMAP4_LITERAL_STREAM, - CAMEL_IMAP4_LITERAL_WRAPPER, -}; - -struct _CamelIMAP4Literal { - gint type; - union { - gchar *string; - CamelStream *stream; - CamelDataWrapper *wrapper; - } literal; -}; - -typedef struct _CamelIMAP4CommandPart { - struct _CamelIMAP4CommandPart *next; - guchar *buffer; - gsize buflen; - - CamelIMAP4Literal *literal; -} CamelIMAP4CommandPart; - -enum { - CAMEL_IMAP4_COMMAND_QUEUED, - CAMEL_IMAP4_COMMAND_ACTIVE, - CAMEL_IMAP4_COMMAND_COMPLETE, - CAMEL_IMAP4_COMMAND_ERROR, -}; - -enum { - CAMEL_IMAP4_RESULT_NONE, - CAMEL_IMAP4_RESULT_OK, - CAMEL_IMAP4_RESULT_NO, - CAMEL_IMAP4_RESULT_BAD, -}; - -struct _CamelIMAP4Command { - CamelDListNode node; - - struct _CamelIMAP4Engine *engine; - - guint ref_count:26; - guint status:3; - guint result:3; - gint id; - - gchar *tag; - - GPtrArray *resp_codes; - - struct _CamelIMAP4Folder *folder; - CamelException ex; - - /* command parts - logical breaks in the overall command based on literals */ - CamelIMAP4CommandPart *parts; - - /* current part */ - CamelIMAP4CommandPart *part; - - /* untagged handlers */ - GHashTable *untagged; - - /* '+' callback/data */ - CamelIMAP4PlusCallback plus; - CamelIMAP4CommandReset reset; - gpointer user_data; -}; - -CamelIMAP4Command *camel_imap4_command_new (struct _CamelIMAP4Engine *engine, struct _CamelIMAP4Folder *folder, - const gchar *format, ...); -CamelIMAP4Command *camel_imap4_command_newv (struct _CamelIMAP4Engine *engine, struct _CamelIMAP4Folder *folder, - const gchar *format, va_list args); - -void camel_imap4_command_register_untagged (CamelIMAP4Command *ic, const gchar *atom, CamelIMAP4UntaggedCallback untagged); - -void camel_imap4_command_ref (CamelIMAP4Command *ic); -void camel_imap4_command_unref (CamelIMAP4Command *ic); - -/* returns 1 when complete, 0 if there is more to do, or -1 on error */ -gint camel_imap4_command_step (CamelIMAP4Command *ic); - -void camel_imap4_command_reset (CamelIMAP4Command *ic); - -G_END_DECLS - -#endif /* CAMEL_IMAP4_COMMAND_H */ diff --git a/camel/providers/imap4/camel-imap4-engine.c b/camel/providers/imap4/camel-imap4-engine.c deleted file mode 100644 index 1271049..0000000 --- a/camel/providers/imap4/camel-imap4-engine.c +++ /dev/null @@ -1,1775 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include - -#include -#include - -#include "camel-imap4-command.h" -#include "camel-imap4-engine.h" -#include "camel-imap4-folder.h" -#include "camel-imap4-stream.h" -#include "camel-imap4-summary.h" -#include "camel-imap4-utils.h" - -#define d(x) - -static void camel_imap4_engine_class_init (CamelIMAP4EngineClass *klass); -static void camel_imap4_engine_init (CamelIMAP4Engine *engine, CamelIMAP4EngineClass *klass); -static void camel_imap4_engine_finalize (CamelObject *object); - -static gint parse_xgwextensions (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, guint32 index, - camel_imap4_token_t *token, CamelException *ex); - -static CamelObjectClass *parent_class = NULL; - -CamelType -camel_imap4_engine_get_type (void) -{ - static CamelType type = 0; - - if (!type) { - type = camel_type_register (camel_object_get_type (), - "CamelIMAP4Engine", - sizeof (CamelIMAP4Engine), - sizeof (CamelIMAP4EngineClass), - (CamelObjectClassInitFunc) camel_imap4_engine_class_init, - NULL, - (CamelObjectInitFunc) camel_imap4_engine_init, - (CamelObjectFinalizeFunc) camel_imap4_engine_finalize); - } - - return type; -} - -static void -camel_imap4_engine_class_init (CamelIMAP4EngineClass *klass) -{ - parent_class = camel_type_get_global_classfuncs (CAMEL_TYPE_OBJECT); - - klass->tagprefix = 'A'; -} - -static void -camel_imap4_engine_init (CamelIMAP4Engine *engine, CamelIMAP4EngineClass *klass) -{ - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - engine->level = CAMEL_IMAP4_LEVEL_UNKNOWN; - - engine->session = NULL; - engine->service = NULL; - engine->url = NULL; - - engine->istream = NULL; - engine->ostream = NULL; - - engine->authtypes = g_hash_table_new (g_str_hash, g_str_equal); - - engine->capa = 0; - - /* this is the suggested default, impacts the max command line length we'll send */ - engine->maxlentype = CAMEL_IMAP4_ENGINE_MAXLEN_LINE; - engine->maxlen = 1000; - - engine->namespaces.personal = NULL; - engine->namespaces.other = NULL; - engine->namespaces.shared = NULL; - - if (klass->tagprefix > 'Z') - klass->tagprefix = 'A'; - - engine->tagprefix = klass->tagprefix++; - engine->tag = 0; - - engine->nextid = 1; - - engine->folder = NULL; - - camel_dlist_init (&engine->queue); -} - -static void -camel_imap4_engine_finalize (CamelObject *object) -{ - CamelIMAP4Engine *engine = (CamelIMAP4Engine *) object; - CamelDListNode *node; - - if (engine->istream) - camel_object_unref (engine->istream); - - if (engine->ostream) - camel_object_unref (engine->ostream); - - g_hash_table_foreach (engine->authtypes, (GHFunc) g_free, NULL); - g_hash_table_destroy (engine->authtypes); - - camel_imap4_namespace_clear (&engine->namespaces.personal); - camel_imap4_namespace_clear (&engine->namespaces.other); - camel_imap4_namespace_clear (&engine->namespaces.shared); - - if (engine->folder) - camel_object_unref (engine->folder); - - while ((node = camel_dlist_remhead (&engine->queue))) { - node->next = NULL; - node->prev = NULL; - - camel_imap4_command_unref ((CamelIMAP4Command *) node); - } -} - -/** - * camel_imap4_engine_new: - * @service: service - * @reconnect: reconnect callback function - * - * Returns: a new imap4 engine - **/ -CamelIMAP4Engine * -camel_imap4_engine_new (CamelService *service, CamelIMAP4ReconnectFunc reconnect) -{ - CamelIMAP4Engine *engine; - - g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL); - - engine = (CamelIMAP4Engine *) camel_object_new (CAMEL_TYPE_IMAP4_ENGINE); - engine->session = service->session; - engine->url = service->url; - engine->service = service; - engine->reconnect = reconnect; - - return engine; -} - -/** - * camel_imap4_engine_take_stream: - * @engine: imap4 engine - * @stream: tcp stream - * @ex: exception - * - * Gives ownership of @stream to @engine and reads the greeting from - * the stream. - * - * Returns: 0 on success or -1 on fail. - * - * Note: on error, @stream will be unref'd. - **/ -gint -camel_imap4_engine_take_stream (CamelIMAP4Engine *engine, CamelStream *stream, CamelException *ex) -{ - camel_imap4_token_t token; - gint code; - - g_return_val_if_fail (CAMEL_IS_IMAP4_ENGINE (engine), -1); - g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1); - - if (engine->istream) - camel_object_unref (engine->istream); - - if (engine->ostream) - camel_object_unref (engine->ostream); - - engine->istream = (CamelIMAP4Stream *) camel_imap4_stream_new (stream); - engine->ostream = camel_stream_buffer_new (stream, CAMEL_STREAM_BUFFER_WRITE); - engine->state = CAMEL_IMAP4_ENGINE_CONNECTED; - camel_object_unref (stream); - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - if (token.token != '*') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if ((code = camel_imap4_engine_handle_untagged_1 (engine, &token, ex)) == -1) { - goto exception; - } else if (code != CAMEL_IMAP4_UNTAGGED_OK && code != CAMEL_IMAP4_UNTAGGED_PREAUTH) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Unexpected greeting from IMAP server %s."), - engine->url->host); - goto exception; - } - - return 0; - - exception: - - camel_imap4_engine_disconnect (engine); - - return -1; -} - -/** - * camel_imap4_engine_disconnect: - * @engine: IMAP4 engine - * - * Closes the engine's connection to the IMAP4 server and sets state - * to #CAMEL_IMAP4_ENGINE_DISCONNECTED. - **/ -void -camel_imap4_engine_disconnect (CamelIMAP4Engine *engine) -{ - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - - if (engine->istream) { - camel_object_unref (engine->istream); - engine->istream = NULL; - } - - if (engine->ostream) { - camel_object_unref (engine->ostream); - engine->ostream = NULL; - } -} - -/** - * camel_imap4_engine_capability: - * @engine: IMAP4 engine - * @ex: exception - * - * Forces the IMAP4 engine to query the IMAP4 server for a list of capabilities. - * - * Returns: %0 on success or %-1 on fail. - **/ -gint -camel_imap4_engine_capability (CamelIMAP4Engine *engine, CamelException *ex) -{ - CamelIMAP4Command *ic; - gint id, retval = 0; - - ic = camel_imap4_engine_prequeue (engine, NULL, "CAPABILITY\r\n"); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - retval = -1; - } - - camel_imap4_command_unref (ic); - - if (retval == -1 || !(engine->capa & CAMEL_IMAP4_CAPABILITY_XGWEXTENSIONS)) - return retval; - - ic = camel_imap4_engine_prequeue (engine, NULL, "XGWEXTENSIONS\r\n"); - camel_imap4_command_register_untagged (ic, "XGWEXTENSIONS", parse_xgwextensions); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - retval = -1; - } - - camel_imap4_command_unref (ic); - - return retval; -} - -/** - * camel_imap4_engine_namespace: - * @engine: IMAP4 engine - * @ex: exception - * - * Forces the IMAP4 engine to query the IMAP4 server for a list of namespaces. - * - * Returns: 0 on success or -1 on fail. - **/ -gint -camel_imap4_engine_namespace (CamelIMAP4Engine *engine, CamelException *ex) -{ - camel_imap4_list_t *list; - GPtrArray *array = NULL; - CamelIMAP4Command *ic; - gint id, i; - - if (engine->capa & CAMEL_IMAP4_CAPABILITY_NAMESPACE) { - ic = camel_imap4_engine_prequeue (engine, NULL, "NAMESPACE\r\n"); - } else { - ic = camel_imap4_engine_prequeue (engine, NULL, "LIST \"\" \"\"\r\n"); - camel_imap4_command_register_untagged (ic, "LIST", camel_imap4_untagged_list); - ic->user_data = array = g_ptr_array_new (); - } - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - - if (array != NULL) - g_ptr_array_free (array, TRUE); - - return -1; - } - - if (array != NULL) { - if (ic->result == CAMEL_IMAP4_RESULT_OK) { - CamelIMAP4Namespace *namespace; - - g_assert (array->len >= 1); - list = array->pdata[0]; - - namespace = g_new (CamelIMAP4Namespace, 1); - namespace->next = NULL; - namespace->path = g_strdup (""); - namespace->sep = list->delim; - - engine->namespaces.personal = namespace; - } else { - /* should never *ever* happen */ - } - - for (i = 0; i < array->len; i++) { - list = array->pdata[i]; - g_free (list->name); - g_free (list); - } - - g_ptr_array_free (array, TRUE); - } - - camel_imap4_command_unref (ic); - - return 0; -} - -/** - * camel_imap4_engine_select_folder: - * @engine: IMAP4 engine - * @folder: folder to select - * @ex: exception - * - * Convenience function to select @folder. - * - * Returns: 0 on success or -1 on fail. - **/ -gint -camel_imap4_engine_select_folder (CamelIMAP4Engine *engine, CamelFolder *folder, CamelException *ex) -{ - CamelIMAP4RespCode *resp; - CamelIMAP4Command *ic; - gint id, retval = 0; - gint i; - - g_return_val_if_fail (CAMEL_IS_IMAP4_ENGINE (engine), -1); - g_return_val_if_fail (CAMEL_IS_IMAP4_FOLDER (folder), -1); - - /* POSSIBLE FIXME: if the folder to be selected will already - * be selected by the time the queue is emptied, simply - * no-op? */ - - ic = camel_imap4_engine_queue (engine, folder, "SELECT %F\r\n", folder); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - return -1; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - /*folder->mode = 0;*/ - for (i = 0; i < ic->resp_codes->len; i++) { - resp = ic->resp_codes->pdata[i]; - switch (resp->code) { - case CAMEL_IMAP4_RESP_CODE_PERM_FLAGS: - folder->permanent_flags = resp->v.flags; - break; - case CAMEL_IMAP4_RESP_CODE_READONLY: - ((CamelIMAP4Folder *) folder)->read_only = TRUE; - break; - case CAMEL_IMAP4_RESP_CODE_READWRITE: - ((CamelIMAP4Folder *) folder)->read_only = FALSE; - break; - case CAMEL_IMAP4_RESP_CODE_UIDNEXT: - camel_imap4_summary_set_uidnext (folder->summary, resp->v.uidnext); - break; - case CAMEL_IMAP4_RESP_CODE_UIDVALIDITY: - camel_imap4_summary_set_uidvalidity (folder->summary, resp->v.uidvalidity); - break; - case CAMEL_IMAP4_RESP_CODE_UNSEEN: - camel_imap4_summary_set_unseen (folder->summary, resp->v.unseen); - break; - default: - break; - } - } - - /*if (folder->mode == 0) { - folder->mode = CAMEL_FOLDER_MODE_READ_ONLY; - g_warning ("Expected to find [READ-ONLY] or [READ-WRITE] in SELECT response"); - }*/ - - break; - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot select folder '%s': Invalid mailbox name"), - folder->full_name); - retval = -1; - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot select folder '%s': Bad command"), - folder->full_name); - retval = -1; - break; - default: - g_assert_not_reached (); - retval = -1; - } - - camel_imap4_command_unref (ic); - - return retval; -} - -static struct { - const gchar *name; - guint32 flag; -} imap4_capabilities[] = { - { "IMAP4", CAMEL_IMAP4_CAPABILITY_IMAP4 }, - { "IMAP4REV1", CAMEL_IMAP4_CAPABILITY_IMAP4REV1 }, - { "STATUS", CAMEL_IMAP4_CAPABILITY_STATUS }, - { "NAMESPACE", CAMEL_IMAP4_CAPABILITY_NAMESPACE }, /* rfc2342 */ - { "UIDPLUS", CAMEL_IMAP4_CAPABILITY_UIDPLUS }, /* rfc2359 */ - { "LITERAL+", CAMEL_IMAP4_CAPABILITY_LITERALPLUS }, /* rfc2088 */ - { "LOGINDISABLED", CAMEL_IMAP4_CAPABILITY_LOGINDISABLED }, - { "STARTTLS", CAMEL_IMAP4_CAPABILITY_STARTTLS }, /* rfc3501 */ - { "QUOTA", CAMEL_IMAP4_CAPABILITY_QUOTA }, /* rfc2087 */ - { "ACL", CAMEL_IMAP4_CAPABILITY_ACL }, /* rfc2086 */ - { "IDLE", CAMEL_IMAP4_CAPABILITY_IDLE }, /* rfc2177 */ - { "MULTIAPPEND", CAMEL_IMAP4_CAPABILITY_MULTIAPPEND }, /* rfc3502 */ - { "UNSELECT", CAMEL_IMAP4_CAPABILITY_UNSELECT }, - { "XGWEXTENSIONS", CAMEL_IMAP4_CAPABILITY_XGWEXTENSIONS }, /* GroupWise extensions */ - { NULL, 0 } -}; - -static struct { - const gchar *name; - guint32 flag; -} imap4_xgwextensions[] = { - { "XGWMOVE", CAMEL_IMAP4_CAPABILITY_XGWMOVE }, /* GroupWise MOVE command */ - { NULL, 0 } -}; - -static gint -parse_xgwextensions (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, guint32 index, camel_imap4_token_t *token, CamelException *ex) -{ - gint i; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - while (token->token == CAMEL_IMAP4_TOKEN_ATOM) { - for (i = 0; imap4_xgwextensions[i].name; i++) { - if (!g_ascii_strcasecmp (imap4_xgwextensions[i].name, token->v.atom)) - engine->capa |= imap4_xgwextensions[i].flag; - } - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - } - - if (token->token != '\n') { - d(fprintf (stderr, "expected '\\n' at the end of the XGWEXTENSIONS response\n")); - goto unexpected; - } - - return 0; - - unexpected: - - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - - return -1; -} - -static gboolean -auth_free (gpointer key, gpointer value, gpointer user_data) -{ - g_free (key); - return TRUE; -} - -static gint -engine_parse_capability (CamelIMAP4Engine *engine, gint sentinel, CamelException *ex) -{ - camel_imap4_token_t token; - gint i; - - /* we assume UTF8 searches work until proven otherwise */ - engine->capa = CAMEL_IMAP4_CAPABILITY_utf8_search; - engine->level = 0; - - g_hash_table_foreach_remove (engine->authtypes, (GHRFunc) auth_free, NULL); - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - while (token.token == CAMEL_IMAP4_TOKEN_ATOM) { - if (!g_ascii_strncasecmp ("AUTH=", token.v.atom, 5)) { - CamelServiceAuthType *auth; - - if ((auth = camel_sasl_authtype (token.v.atom + 5)) != NULL) - g_hash_table_insert (engine->authtypes, g_strdup (token.v.atom + 5), auth); - } else { - for (i = 0; imap4_capabilities[i].name; i++) { - if (!g_ascii_strcasecmp (imap4_capabilities[i].name, token.v.atom)) - engine->capa |= imap4_capabilities[i].flag; - } - } - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - } - - if (token.token != sentinel) { - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - /* unget our sentinel token */ - camel_imap4_stream_unget_token (engine->istream, &token); - - /* figure out which version of IMAP4 we are dealing with */ - if (engine->capa & CAMEL_IMAP4_CAPABILITY_IMAP4REV1) { - engine->level = CAMEL_IMAP4_LEVEL_IMAP4REV1; - engine->capa |= CAMEL_IMAP4_CAPABILITY_STATUS; - } else if (engine->capa & CAMEL_IMAP4_CAPABILITY_IMAP4) { - engine->level = CAMEL_IMAP4_LEVEL_IMAP4; - } else { - engine->level = CAMEL_IMAP4_LEVEL_UNKNOWN; - } - - return 0; -} - -static gint -engine_parse_flags_list (CamelIMAP4Engine *engine, CamelIMAP4RespCode *resp, gint perm, CamelException *ex) -{ - guint32 flags = 0; - - if (camel_imap4_parse_flags_list (engine, &flags, ex) == -1) - return-1; - - if (resp != NULL) - resp->v.flags = flags; - - if (engine->current && engine->current->folder) { - if (perm) - ((CamelFolder *) engine->current->folder)->permanent_flags = flags; - /*else - ((CamelFolder *) engine->current->folder)->folder_flags = flags;*/ - } else if (engine->folder) { - if (perm) - ((CamelFolder *) engine->folder)->permanent_flags = flags; - /*else - ((CamelFolder *) engine->folder)->folder_flags = flags;*/ - } else { - fprintf (stderr, "We seem to be in a bit of a pickle. we've just parsed an untagged %s\n" - "response for a folder, yet we do not currently have a folder selected?\n", - perm ? "PERMANENTFLAGS" : "FLAGS"); - } - - return 0; -} - -static gint -engine_parse_flags (CamelIMAP4Engine *engine, CamelException *ex) -{ - camel_imap4_token_t token; - - if (engine_parse_flags_list (engine, NULL, FALSE, ex) == -1) - return -1; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != '\n') { - d(fprintf (stderr, "Expected to find a '\\n' token after the FLAGS response\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - return 0; -} - -static gint -engine_parse_namespace (CamelIMAP4Engine *engine, CamelException *ex) -{ - CamelIMAP4Namespace *namespaces[3], *node, *tail; - camel_imap4_token_t token; - gint i, n = 0; - - camel_imap4_namespace_clear (&engine->namespaces.personal); - camel_imap4_namespace_clear (&engine->namespaces.other); - camel_imap4_namespace_clear (&engine->namespaces.shared); - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - do { - namespaces[n] = NULL; - tail = (CamelIMAP4Namespace *) &namespaces[n]; - - if (token.token == '(') { - /* decode the list of namespace pairs */ - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - while (token.token == '(') { - /* decode a namespace pair */ - - /* get the path name token */ - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - if (token.token != CAMEL_IMAP4_TOKEN_QSTRING) { - d(fprintf (stderr, "Expected to find a qstring token as first element in NAMESPACE pair\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - node = g_new (CamelIMAP4Namespace, 1); - node->next = NULL; - node->path = g_strdup (token.v.qstring); - - /* get the path delimiter token */ - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) { - g_free (node->path); - g_free (node); - - goto exception; - } - - switch (token.token) { - case CAMEL_IMAP4_TOKEN_NIL: - node->sep = '\0'; - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - if (strlen (token.v.qstring) == 1) { - node->sep = *token.v.qstring; - break; - } else { - /* check the last gchar in the path component of the namespace */ - if (*node->path) - node->sep = node->path[strlen (node->path) - 1]; - else - node->sep = '\0'; - } - break; - default: - d(fprintf (stderr, "Expected to find a nil or a valid qstring token as second element in NAMESPACE pair\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - g_free (node->path); - g_free (node); - - goto exception; - } - - tail->next = node; - tail = node; - - /* canonicalise the namespace path */ - if (node->path[strlen (node->path) - 1] == node->sep) - node->path[strlen (node->path) - 1] = '\0'; - - /* canonicalise if this is an INBOX namespace */ - if (!g_ascii_strncasecmp (node->path, "INBOX", 5) && - (node->path[6] == '\0' || node->path[6] == node->sep)) - memcpy (node->path, "INBOX", 5); - - /* get the closing ')' for this namespace pair */ - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - if (token.token != ')') { - d(fprintf (stderr, "Expected to find a ')' token to close the current namespace pair\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - - goto exception; - } - - /* get the next token (should be either '(' or ')') */ - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - } - - if (token.token != ')') { - d(fprintf (stderr, "Expected to find a ')' to close the current namespace list\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - } else if (token.token == CAMEL_IMAP4_TOKEN_NIL) { - /* namespace list is NIL */ - namespaces[n] = NULL; - } else { - d(fprintf (stderr, "Expected to find either NIL or '(' token in untagged NAMESPACE response\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - /* get the next token (should be either '(', NIL, or '\n') */ - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - n++; - } while (n < 3); - - engine->namespaces.personal = namespaces[0]; - engine->namespaces.other = namespaces[1]; - engine->namespaces.shared = namespaces[2]; - - return 0; - - exception: - - for (i = 0; i <= n; i++) - camel_imap4_namespace_clear (&namespaces[i]); - - return -1; -} - -/* - * resp-text-code = "ALERT" / - * "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / - * capability-data / "PARSE" / - * "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / - * "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / - * "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / - * "UNSEEN" SP nz-number / - * atom [SP 1*] - */ - -static struct { - const gchar *name; - camel_imap4_resp_code_t code; - gint save; -} imap4_resp_codes[] = { - { "ALERT", CAMEL_IMAP4_RESP_CODE_ALERT, 0 }, - { "BADCHARSET", CAMEL_IMAP4_RESP_CODE_BADCHARSET, 0 }, - { "CAPABILITY", CAMEL_IMAP4_RESP_CODE_CAPABILITY, 0 }, - { "PARSE", CAMEL_IMAP4_RESP_CODE_PARSE, 1 }, - { "PERMANENTFLAGS", CAMEL_IMAP4_RESP_CODE_PERM_FLAGS, 1 }, - { "READ-ONLY", CAMEL_IMAP4_RESP_CODE_READONLY, 1 }, - { "READ-WRITE", CAMEL_IMAP4_RESP_CODE_READWRITE, 1 }, - { "TRYCREATE", CAMEL_IMAP4_RESP_CODE_TRYCREATE, 1 }, - { "UIDNEXT", CAMEL_IMAP4_RESP_CODE_UIDNEXT, 1 }, - { "UIDVALIDITY", CAMEL_IMAP4_RESP_CODE_UIDVALIDITY, 1 }, - { "UNSEEN", CAMEL_IMAP4_RESP_CODE_UNSEEN, 1 }, - { "NEWNAME", CAMEL_IMAP4_RESP_CODE_NEWNAME, 1 }, - { "APPENDUID", CAMEL_IMAP4_RESP_CODE_APPENDUID, 1 }, - { "COPYUID", CAMEL_IMAP4_RESP_CODE_COPYUID, 1 }, - { NULL, CAMEL_IMAP4_RESP_CODE_UNKNOWN, 0 } -}; - -/** - * camel_imap4_engine_parse_resp_code: - * @engine: IMAP4 engine - * @ex: exception - * - * Parses a RESP-CODE - * - * Returns: 0 on success or -1 on fail. - **/ -gint -camel_imap4_engine_parse_resp_code (CamelIMAP4Engine *engine, CamelException *ex) -{ - CamelIMAP4RespCode *resp = NULL; - camel_imap4_resp_code_t code; - camel_imap4_token_t token; - guchar *linebuf; - gsize len; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != '[') { - d(fprintf (stderr, "Expected a '[' token (followed by a RESP-CODE)\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != CAMEL_IMAP4_TOKEN_ATOM) { - d(fprintf (stderr, "Expected an atom token containing a RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - for (code = 0; imap4_resp_codes[code].name; code++) { - if (!strcmp (imap4_resp_codes[code].name, token.v.atom)) { - if (engine->current && imap4_resp_codes[code].save) { - resp = g_new0 (CamelIMAP4RespCode, 1); - resp->code = code; - } - break; - } - } - - switch (code) { - case CAMEL_IMAP4_RESP_CODE_ALERT: - /* nothing to do here, handled after switch statement */ - break; - case CAMEL_IMAP4_RESP_CODE_BADCHARSET: - /* apparently we don't support UTF-8 afterall */ - engine->capa &= ~CAMEL_IMAP4_CAPABILITY_utf8_search; - break; - case CAMEL_IMAP4_RESP_CODE_CAPABILITY: - /* capability list follows */ - if (engine_parse_capability (engine, ']', ex) == -1) - goto exception; - break; - case CAMEL_IMAP4_RESP_CODE_PERM_FLAGS: - /* flag list follows */ - if (engine_parse_flags_list (engine, resp, TRUE, ex) == -1) - goto exception; - break; - case CAMEL_IMAP4_RESP_CODE_READONLY: - break; - case CAMEL_IMAP4_RESP_CODE_READWRITE: - break; - case CAMEL_IMAP4_RESP_CODE_TRYCREATE: - break; - case CAMEL_IMAP4_RESP_CODE_UIDNEXT: - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - if (token.token != CAMEL_IMAP4_TOKEN_NUMBER) { - d(fprintf (stderr, "Expected an nz_number token as an argument to the UIDNEXT RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) - resp->v.uidnext = token.v.number; - - break; - case CAMEL_IMAP4_RESP_CODE_UIDVALIDITY: - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - if (token.token != CAMEL_IMAP4_TOKEN_NUMBER) { - d(fprintf (stderr, "Expected an nz_number token as an argument to the UIDVALIDITY RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) - resp->v.uidvalidity = token.v.number; - - break; - case CAMEL_IMAP4_RESP_CODE_UNSEEN: - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != CAMEL_IMAP4_TOKEN_NUMBER) { - d(fprintf (stderr, "Expected an nz_number token as an argument to the UNSEEN RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) - resp->v.unseen = token.v.number; - - break; - case CAMEL_IMAP4_RESP_CODE_NEWNAME: - /* this RESP-CODE may actually be removed - see here: - * http://www.washington.edu/imap4/listarch/2001/msg00058.html */ - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != CAMEL_IMAP4_TOKEN_ATOM && token.token != CAMEL_IMAP4_TOKEN_QSTRING) { - d(fprintf (stderr, "Expected an atom or qstring token as the first argument to the NEWNAME RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) - resp->v.newname[0] = g_strdup (token.v.atom); - - if (token.token != CAMEL_IMAP4_TOKEN_ATOM && token.token != CAMEL_IMAP4_TOKEN_QSTRING) { - d(fprintf (stderr, "Expected an atom or qstring token as the second argument to the NEWNAME RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) - resp->v.newname[1] = g_strdup (token.v.atom); - - break; - case CAMEL_IMAP4_RESP_CODE_APPENDUID: - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != CAMEL_IMAP4_TOKEN_NUMBER) { - d(fprintf (stderr, "Expected an nz_number token as the first argument to the APPENDUID RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) - resp->v.appenduid.uidvalidity = token.v.number; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != CAMEL_IMAP4_TOKEN_NUMBER) { - d(fprintf (stderr, "Expected an nz_number token as the second argument to the APPENDUID RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) - resp->v.appenduid.uid = token.v.number; - - break; - case CAMEL_IMAP4_RESP_CODE_COPYUID: - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != CAMEL_IMAP4_TOKEN_NUMBER) { - d(fprintf (stderr, "Expected an nz_number token as the first argument to the COPYUID RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) - resp->v.copyuid.uidvalidity = token.v.number; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != CAMEL_IMAP4_TOKEN_ATOM && token.token != CAMEL_IMAP4_TOKEN_NUMBER) { - d(fprintf (stderr, "Expected an atom or numeric token as the second argument to the COPYUID RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) { - if (token.token == CAMEL_IMAP4_TOKEN_NUMBER) - resp->v.copyuid.srcset = g_strdup_printf ("%u", token.v.number); - else - resp->v.copyuid.srcset = g_strdup (token.v.atom); - } - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != CAMEL_IMAP4_TOKEN_ATOM && token.token != CAMEL_IMAP4_TOKEN_NUMBER) { - d(fprintf (stderr, "Expected an atom or numeric token as the third argument to the APPENDUID RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) { - if (token.token == CAMEL_IMAP4_TOKEN_NUMBER) - resp->v.copyuid.destset = g_strdup_printf ("%u", token.v.number); - else - resp->v.copyuid.destset = g_strdup (token.v.atom); - } - - break; - default: - d(fprintf (stderr, "Unknown RESP-CODE encountered: %s\n", token.v.atom)); - - /* extensions are of the form: "[" atom [SPACE 1*] "]" */ - - /* eat up the TEXT_CHARs */ - while (token.token != ']' && token.token != '\n') { - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - } - - break; - } - - while (token.token != ']' && token.token != '\n') { - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - } - - if (token.token != ']') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - d(fprintf (stderr, "Expected to find a ']' token after the RESP-CODE\n")); - return -1; - } - - if (code == CAMEL_IMAP4_RESP_CODE_ALERT) { - if (camel_imap4_engine_line (engine, &linebuf, &len, ex) == -1) - goto exception; - - camel_session_alert_user (engine->session, CAMEL_SESSION_ALERT_INFO, linebuf, FALSE); - g_free (linebuf); - } else if (resp != NULL && code == CAMEL_IMAP4_RESP_CODE_PARSE) { - if (camel_imap4_engine_line (engine, &linebuf, &len, ex) == -1) - goto exception; - - resp->v.parse = linebuf; - } else { - /* eat up the rest of the response */ - if (camel_imap4_engine_line (engine, NULL, NULL, ex) == -1) - goto exception; - } - - if (resp != NULL) - g_ptr_array_add (engine->current->resp_codes, resp); - - return 0; - - exception: - - if (resp != NULL) - camel_imap4_resp_code_free (resp); - - return -1; -} - -/** - * camel_imap4_engine_handle_untagged_1: - * @engine: IMAP4 engine - * @token: IMAP4 token - * @ex: exception - * - * Handles a single untagged response - * - * Returns: -1 on error or one of - * CAMEL_IMAP4_UNTAGGED_[OK,NO,BAD,PREAUTH,HANDLED] on success - **/ -gint -camel_imap4_engine_handle_untagged_1 (CamelIMAP4Engine *engine, camel_imap4_token_t *token, CamelException *ex) -{ - gint code = CAMEL_IMAP4_UNTAGGED_HANDLED; - CamelIMAP4Command *ic = engine->current; - CamelIMAP4UntaggedCallback untagged; - CamelFolder *folder; - guint v; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token == CAMEL_IMAP4_TOKEN_ATOM) { - if (!strcmp ("BYE", token->v.atom)) { - /* we don't care if we fail here, either way we've been disconnected */ - if (camel_imap4_engine_next_token (engine, token, NULL) == 0) { - if (token->token == '[') { - camel_imap4_stream_unget_token (engine->istream, token); - camel_imap4_engine_parse_resp_code (engine, NULL); - } else { - camel_imap4_engine_line (engine, NULL, NULL, NULL); - } - } - - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - - /* we don't return -1 here because there may be more untagged responses after the BYE */ - } else if (!strcmp ("CAPABILITY", token->v.atom)) { - /* capability tokens follow */ - if (engine_parse_capability (engine, '\n', ex) == -1) - return -1; - - /* find the eoln token */ - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token != '\n') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - return -1; - } - } else if (!strcmp ("FLAGS", token->v.atom)) { - /* flags list follows */ - if (engine_parse_flags (engine, ex) == -1) - return -1; - } else if (!strcmp ("NAMESPACE", token->v.atom)) { - if (engine_parse_namespace (engine, ex) == -1) - return -1; - } else if (!strcmp ("NO", token->v.atom) || !strcmp ("BAD", token->v.atom)) { - code = !strcmp ("NO", token->v.atom) ? CAMEL_IMAP4_UNTAGGED_NO : CAMEL_IMAP4_UNTAGGED_BAD; - - /* our command has been rejected */ - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token == '[') { - /* we have a resp code */ - camel_imap4_stream_unget_token (engine->istream, token); - if (camel_imap4_engine_parse_resp_code (engine, ex) == -1) - return -1; - } else if (token->token != '\n') { - /* we just have resp text */ - if (camel_imap4_engine_line (engine, NULL, NULL, ex) == -1) - return -1; - } - } else if (!strcmp ("OK", token->v.atom)) { - code = CAMEL_IMAP4_UNTAGGED_OK; - - if (engine->state == CAMEL_IMAP4_ENGINE_CONNECTED) { - /* initial server greeting */ - engine->state = CAMEL_IMAP4_ENGINE_PREAUTH; - } - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token == '[') { - /* we have a resp code */ - camel_imap4_stream_unget_token (engine->istream, token); - if (camel_imap4_engine_parse_resp_code (engine, ex) == -1) - return -1; - } else { - /* we just have resp text */ - if (camel_imap4_engine_line (engine, NULL, NULL, ex) == -1) - return -1; - } - } else if (!strcmp ("PREAUTH", token->v.atom)) { - code = CAMEL_IMAP4_UNTAGGED_PREAUTH; - - if (engine->state == CAMEL_IMAP4_ENGINE_CONNECTED) - engine->state = CAMEL_IMAP4_ENGINE_AUTHENTICATED; - - if (camel_imap4_engine_parse_resp_code (engine, ex) == -1) - return -1; - } else if (ic && (untagged = g_hash_table_lookup (ic->untagged, token->v.atom))) { - /* registered untagged handler for imap4 command */ - if (untagged (engine, ic, 0, token, ex) == -1) - return -1; - } else { - d(fprintf (stderr, "Unhandled atom token in untagged response: %s", token->v.atom)); - - if (camel_imap4_engine_eat_line (engine, ex) == -1) - return -1; - } - } else if (token->token == CAMEL_IMAP4_TOKEN_NUMBER) { - /* we probably have something like "* 1 EXISTS" */ - v = token->v.number; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token != CAMEL_IMAP4_TOKEN_ATOM) { - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - - return -1; - } - - /* which folder is this EXISTS/EXPUNGE/RECENT acting on? */ - if (engine->current && engine->current->folder) - folder = (CamelFolder *) engine->current->folder; - else if (engine->folder) - folder = (CamelFolder *) engine->folder; - else - folder = NULL; - - /* NOTE: these can be over-ridden by a registered untagged response handler */ - if (!strcmp ("EXISTS", token->v.atom)) { - camel_imap4_summary_set_exists (folder->summary, v); - } else if (!strcmp ("EXPUNGE", token->v.atom) || !strcmp ("XGWMOVE", token->v.atom)) { - camel_imap4_summary_expunge (folder->summary, (gint) v); - } else if (!strcmp ("RECENT", token->v.atom)) { - camel_imap4_summary_set_recent (folder->summary, v); - } else if (ic && (untagged = g_hash_table_lookup (ic->untagged, token->v.atom))) { - /* registered untagged handler for imap4 command */ - if (untagged (engine, ic, v, token, ex) == -1) - return -1; - } else { - d(fprintf (stderr, "Unrecognized untagged response: * %u %s\n", v, token->v.atom)); - } - - /* find the eoln token */ - if (camel_imap4_engine_eat_line (engine, ex) == -1) - return -1; - } else { - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - - return -1; - } - - return code; -} - -/** - * camel_imap4_engine_handle_untagged: - * @engine: IMAP4 engine - * @ex: exception - * - * Handle a stream of untagged responses. - **/ -void -camel_imap4_engine_handle_untagged (CamelIMAP4Engine *engine, CamelException *ex) -{ - camel_imap4_token_t token; - - g_return_if_fail (CAMEL_IS_IMAP4_ENGINE (engine)); - - do { - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - if (token.token != '*') - break; - - if (camel_imap4_engine_handle_untagged_1 (engine, &token, ex) == -1) - goto exception; - } while (1); - - camel_imap4_stream_unget_token (engine->istream, &token); - - return; - - exception: - - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; -} - -static gint -imap4_process_command (CamelIMAP4Engine *engine, CamelIMAP4Command *ic) -{ - gint retval; - - while ((retval = camel_imap4_command_step (ic)) == 0) - ; - - if (retval == -1) { - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - return -1; - } - - return 0; -} - -static void -engine_prequeue_folder_select (CamelIMAP4Engine *engine) -{ - CamelIMAP4Command *ic; - const gchar *cmd; - - ic = (CamelIMAP4Command *) engine->queue.head; - cmd = (const gchar *) ic->parts->buffer; - - if (!ic->folder || ic->folder == engine->folder || - !strncmp (cmd, "SELECT ", 7) || !strncmp (cmd, "EXAMINE ", 8)) { - /* no need to pre-queue a SELECT */ - return; - } - - /* we need to pre-queue a SELECT */ - ic = camel_imap4_engine_prequeue (engine, (CamelFolder *) ic->folder, "SELECT %F\r\n", ic->folder); - ic->user_data = engine; - - camel_imap4_command_unref (ic); -} - -static gint -engine_state_change (CamelIMAP4Engine *engine, CamelIMAP4Command *ic) -{ - const gchar *cmd; - gint retval = 0; - - cmd = ic->parts->buffer; - if (!strncmp (cmd, "SELECT ", 7) || !strncmp (cmd, "EXAMINE ", 8)) { - if (ic->result == CAMEL_IMAP4_RESULT_OK) { - /* Update the selected folder */ - camel_object_ref (ic->folder); - if (engine->folder) - camel_object_unref (engine->folder); - engine->folder = ic->folder; - - engine->state = CAMEL_IMAP4_ENGINE_SELECTED; - } else if (ic->user_data == engine) { - /* the engine pre-queued this SELECT command */ - retval = -1; - } - } else if (!strncmp (cmd, "CLOSE", 5)) { - if (ic->result == CAMEL_IMAP4_RESULT_OK) - engine->state = CAMEL_IMAP4_ENGINE_AUTHENTICATED; - } else if (!strncmp (cmd, "LOGOUT", 6)) { - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - } - - return retval; -} - -/** - * camel_imap4_engine_iterate: - * @engine: IMAP4 engine - * - * Processes the first command in the queue. - * - * Returns: the id of the processed command, %0 if there were no - * commands to process, or %-1 on error. - * - * Note: more details on the error will be held on the - * #CamelIMAP4Command that failed. - **/ -gint -camel_imap4_engine_iterate (CamelIMAP4Engine *engine) -{ - CamelIMAP4Command *ic, *nic; - GPtrArray *resp_codes; - gint retries = 0; - gint retval; - - if (camel_dlist_empty (&engine->queue)) - return 0; - - retry: - /* FIXME: it would be nicer if we didn't have to check the stream's disconnected status */ - if ((engine->state == CAMEL_IMAP4_ENGINE_DISCONNECTED || engine->istream->disconnected) - && !engine->reconnecting) { - CamelException rex; - gboolean connected; - - camel_exception_init (&rex); - engine->reconnecting = TRUE; - connected = engine->reconnect (engine, &rex); - engine->reconnecting = FALSE; - - if (!connected) { - /* pop the first command and act as tho it failed (which, technically, it did...) */ - ic = (CamelIMAP4Command *) camel_dlist_remhead (&engine->queue); - ic->status = CAMEL_IMAP4_COMMAND_ERROR; - camel_exception_xfer (&ic->ex, &rex); - camel_imap4_command_unref (ic); - return -1; - } - } - - /* check to see if we need to pre-queue a SELECT, if so do it */ - engine_prequeue_folder_select (engine); - - engine->current = ic = (CamelIMAP4Command *) camel_dlist_remhead (&engine->queue); - ic->status = CAMEL_IMAP4_COMMAND_ACTIVE; - - if ((retval = imap4_process_command (engine, ic)) != -1) { - if (engine_state_change (engine, ic) == -1) { - /* This can ONLY happen if @ic was the pre-queued SELECT command - * and it got a NO or BAD response. - * - * We have to pop the next imap4 command or we'll get into an - * infinite loop. In order to provide @nic's owner with as much - * information as possible, we move all @ic status information - * over to @nic and pretend we just processed @nic. - **/ - - nic = (CamelIMAP4Command *) camel_dlist_remhead (&engine->queue); - - nic->status = ic->status; - nic->result = ic->result; - resp_codes = nic->resp_codes; - nic->resp_codes = ic->resp_codes; - ic->resp_codes = resp_codes; - - camel_exception_xfer (&nic->ex, &ic->ex); - - camel_imap4_command_unref (ic); - ic = nic; - } - - retval = ic->id; - } else if (!engine->reconnecting && retries < 3) { - /* put @ic back in the queue and retry */ - camel_dlist_addhead (&engine->queue, (CamelDListNode *) ic); - camel_imap4_command_reset (ic); - retries++; - goto retry; - } else { - camel_exception_setv (&ic->ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Failed to send command to IMAP server %s: %s"), - engine->url->host, errno ? g_strerror (errno) : - _("service unavailable")); - } - - camel_imap4_command_unref (ic); - - return retval; -} - -/** - * camel_imap4_engine_queue: - * @engine: IMAP4 engine - * @folder: IMAP4 folder that the command will affect (or %NULL if it doesn't matter) - * @format: command format - * @Varargs: arguments - * - * Basically the same as camel_imap4_command_new() except that this - * function also places the command in the engine queue. - * - * Returns: the CamelIMAP4Command. - **/ -CamelIMAP4Command * -camel_imap4_engine_queue (CamelIMAP4Engine *engine, CamelFolder *folder, const gchar *format, ...) -{ - CamelIMAP4Command *ic; - va_list args; - - g_return_val_if_fail (CAMEL_IS_IMAP4_ENGINE (engine), NULL); - - va_start (args, format); - ic = camel_imap4_command_newv (engine, (CamelIMAP4Folder *) folder, format, args); - va_end (args); - - ic->id = engine->nextid++; - camel_dlist_addtail (&engine->queue, (CamelDListNode *) ic); - camel_imap4_command_ref (ic); - - return ic; -} - -/** - * camel_imap4_engine_prequeue: - * @engine: IMAP4 engine - * @folder: IMAP4 folder that the command will affect (or %NULL if it doesn't matter) - * @format: command format - * @Varargs: arguments - * - * Same as camel_imap4_engine_queue() except this places the new - * command at the head of the queue. - * - * Returns: the CamelIMAP4Command. - **/ -CamelIMAP4Command * -camel_imap4_engine_prequeue (CamelIMAP4Engine *engine, CamelFolder *folder, const gchar *format, ...) -{ - CamelIMAP4Command *ic; - va_list args; - - g_return_val_if_fail (CAMEL_IS_IMAP4_ENGINE (engine), NULL); - - va_start (args, format); - ic = camel_imap4_command_newv (engine, (CamelIMAP4Folder *) folder, format, args); - va_end (args); - - if (camel_dlist_empty (&engine->queue)) { - camel_dlist_addtail (&engine->queue, (CamelDListNode *) ic); - ic->id = engine->nextid++; - } else { - CamelIMAP4Command *nic; - CamelDListNode *node; - - node = (CamelDListNode *) ic; - camel_dlist_addhead (&engine->queue, node); - nic = (CamelIMAP4Command *) node->next; - ic->id = nic->id - 1; - - if (ic->id == 0) { - /* increment all command ids */ - node = engine->queue.head; - while (node->next) { - nic = (CamelIMAP4Command *) node; - node = node->next; - nic->id++; - } - } - } - - camel_imap4_command_ref (ic); - - return ic; -} - -/** - * camel_imap4_engine_dequeue: - * @engine: IMAP4 engine - * @ic: IMAP4 command - * - * Removes @ic from the processing queue. - **/ -void -camel_imap4_engine_dequeue (CamelIMAP4Engine *engine, CamelIMAP4Command *ic) -{ - CamelDListNode *node = (CamelDListNode *) ic; - - if (node->next == NULL && node->prev == NULL) - return; - - camel_dlist_remove (node); - node->next = NULL; - node->prev = NULL; - - camel_imap4_command_unref (ic); -} - -/** - * camel_imap4_engine_next_token: - * @engine: IMAP4 engine - * @token: IMAP4 token - * @ex: exception - * - * Wraps camel_imap4_stream_next_token() to set an exception on - * failure and updates the engine state to DISCONNECTED if the stream - * gets disconencted. - * - * Returns: %0 on success or %-1 on fail. - **/ -gint -camel_imap4_engine_next_token (CamelIMAP4Engine *engine, camel_imap4_token_t *token, CamelException *ex) -{ - if (camel_imap4_stream_next_token (engine->istream, token) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("IMAP4 server %s unexpectedly disconnected: %s"), - engine->url->host, errno ? g_strerror (errno) : _("Unknown error")); - - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - - return -1; - } - - return 0; -} - -/** - * camel_imap4_engine_eat_line: - * @engine: IMAP4 engine - * @ex: exception - * - * Gobbles up the remainder of the response line. - * - * Returns: 0 on success or -1 on fail - **/ -gint -camel_imap4_engine_eat_line (CamelIMAP4Engine *engine, CamelException *ex) -{ - camel_imap4_token_t token; - guchar *literal; - gint retval; - gsize n; - - do { - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token == CAMEL_IMAP4_TOKEN_LITERAL) { - while ((retval = camel_imap4_stream_literal (engine->istream, &literal, &n)) == 1) - ; - - if (retval == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("IMAP4 server %s unexpectedly disconnected: %s"), - engine->url->host, errno ? g_strerror (errno) : _("Unknown error")); - - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - - return -1; - } - } - } while (token.token != '\n'); - - return 0; -} - -/** - * camel_imap4_engine_line: - * @engine: IMAP4 engine - * @line: line pointer - * @len: length pointer - * @ex: exception - * - * Reads in a single line of input from the IMAP4 server and updates - * @line to point to the line buffer. @len is set to the length of the - * line buffer. @line must be free'd using g_free(). - * - * Returns: 0 on success or -1 on fail - **/ -gint -camel_imap4_engine_line (CamelIMAP4Engine *engine, guchar **line, gsize *len, CamelException *ex) -{ - GByteArray *linebuf = NULL; - guchar *buf; - gsize buflen; - gint retval; - - if (line != NULL) - linebuf = g_byte_array_new (); - - while ((retval = camel_imap4_stream_line (engine->istream, &buf, &buflen)) > 0) { - if (linebuf != NULL) - g_byte_array_append (linebuf, buf, buflen); - } - - if (retval == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("IMAP4 server %s unexpectedly disconnected: %s"), - engine->url->host, errno ? g_strerror (errno) : _("Unknown error")); - - if (linebuf != NULL) - g_byte_array_free (linebuf, TRUE); - - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - - return -1; - } - - if (linebuf != NULL) { - g_byte_array_append (linebuf, buf, buflen); - - *line = linebuf->data; - *len = linebuf->len; - - g_byte_array_free (linebuf, FALSE); - } - - return 0; -} - -/** - * camel_imap4_engine_literal: - * @engine: IMAP4 engine - * @literal: literal pointer - * @len: len pointer - * @ex: exception - * - * Reads in an entire literal string and updates @literal to point to - * it. @len is set to the length of the literal. @literal will also - * conveniently be terminated with a nul-byte. @literal must be free'd - * using g_free(). - * - * Returns: 0 on success or -1 on fail. - **/ -gint -camel_imap4_engine_literal (CamelIMAP4Engine *engine, guchar **literal, gsize *len, CamelException *ex) -{ - GByteArray *literalbuf = NULL; - guchar *buf; - gsize buflen; - gint retval; - - if (literal != NULL) - literalbuf = g_byte_array_new (); - - while ((retval = camel_imap4_stream_literal (engine->istream, &buf, &buflen)) > 0) { - if (literalbuf != NULL) - g_byte_array_append (literalbuf, buf, buflen); - } - - if (retval == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("IMAP4 server %s unexpectedly disconnected: %s"), - engine->url->host, errno ? g_strerror (errno) : _("Unknown error")); - - if (literalbuf != NULL) - g_byte_array_free (literalbuf, TRUE); - - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - - return -1; - } - - if (literalbuf != NULL) { - g_byte_array_append (literalbuf, buf, buflen); - g_byte_array_append (literalbuf, "", 1); - - *literal = literalbuf->data; - *len = literalbuf->len - 1; - - g_byte_array_free (literalbuf, FALSE); - } - - return 0; -} - -/** - * camel_imap4_engine_nstring: - * @engine: IMAP4 engine - * @nstring: nstring pointer - * @ex: exception - * - * Reads in an nstring (NIL, atom, qstring or literal) and updates - * @nstring to point to it. @nstring must be free'd using g_free(). - * - * Returns: 0 on success or -1 on fail. - **/ -gint -camel_imap4_engine_nstring (CamelIMAP4Engine *engine, guchar **nstring, CamelException *ex) -{ - camel_imap4_token_t token; - gsize n; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - switch (token.token) { - case CAMEL_IMAP4_TOKEN_NIL: - *nstring = NULL; - break; - case CAMEL_IMAP4_TOKEN_ATOM: - *nstring = g_strdup (token.v.atom); - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - *nstring = g_strdup (token.v.qstring); - break; - case CAMEL_IMAP4_TOKEN_LITERAL: - if (camel_imap4_engine_literal (engine, nstring, &n, ex) == -1) - return -1; - break; - default: - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - return 0; -} - -/** - * camel_imap4_resp_code_free: - * @rcode: RESP-CODE - * - * Free's the RESP-CODE - **/ -void -camel_imap4_resp_code_free (CamelIMAP4RespCode *rcode) -{ - switch (rcode->code) { - case CAMEL_IMAP4_RESP_CODE_PARSE: - g_free (rcode->v.parse); - break; - case CAMEL_IMAP4_RESP_CODE_NEWNAME: - g_free (rcode->v.newname[0]); - g_free (rcode->v.newname[1]); - break; - case CAMEL_IMAP4_RESP_CODE_COPYUID: - g_free (rcode->v.copyuid.srcset); - g_free (rcode->v.copyuid.destset); - break; - default: - break; - } - - g_free (rcode); -} diff --git a/camel/providers/imap4/camel-imap4-engine.h b/camel/providers/imap4/camel-imap4-engine.h deleted file mode 100644 index 74f0ab5..0000000 --- a/camel/providers/imap4/camel-imap4-engine.h +++ /dev/null @@ -1,233 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef CAMEL_IMAP4_ENGINE_H -#define CAMEL_IMAP4_ENGINE_H - -#include - -#include - -#include -#include -#include -#include - -#define CAMEL_TYPE_IMAP4_ENGINE (camel_imap4_engine_get_type ()) -#define CAMEL_IMAP4_ENGINE(obj) (CAMEL_CHECK_CAST ((obj), CAMEL_TYPE_IMAP4_ENGINE, CamelIMAP4Engine)) -#define CAMEL_IMAP4_ENGINE_CLASS(klass) (CAMEL_CHECK_CLASS_CAST ((klass), CAMEL_TYPE_IMAP4_ENGINE, CamelIMAP4EngineClass)) -#define CAMEL_IS_IMAP4_ENGINE(obj) (CAMEL_CHECK_TYPE ((obj), CAMEL_TYPE_IMAP4_ENGINE)) -#define CAMEL_IS_IMAP4_ENGINE_CLASS(klass) (CAMEL_CHECK_CLASS_TYPE ((klass), CAMEL_TYPE_IMAP4_ENGINE)) -#define CAMEL_IMAP4_ENGINE_GET_CLASS(obj) (CAMEL_CHECK_GET_CLASS ((obj), CAMEL_TYPE_IMAP4_ENGINE, CamelIMAP4EngineClass)) - -G_BEGIN_DECLS - -typedef struct _CamelIMAP4Engine CamelIMAP4Engine; -typedef struct _CamelIMAP4EngineClass CamelIMAP4EngineClass; - -struct _camel_imap4_token_t; -struct _CamelIMAP4Command; -struct _CamelIMAP4Folder; -struct _CamelIMAP4Stream; - -typedef enum { - CAMEL_IMAP4_ENGINE_DISCONNECTED, - CAMEL_IMAP4_ENGINE_CONNECTED, - CAMEL_IMAP4_ENGINE_PREAUTH, - CAMEL_IMAP4_ENGINE_AUTHENTICATED, - CAMEL_IMAP4_ENGINE_SELECTED, -} camel_imap4_engine_t; - -typedef enum { - CAMEL_IMAP4_LEVEL_UNKNOWN, - CAMEL_IMAP4_LEVEL_IMAP4, - CAMEL_IMAP4_LEVEL_IMAP4REV1 -} camel_imap4_level_t; - -enum { - CAMEL_IMAP4_CAPABILITY_IMAP4 = (1 << 0), - CAMEL_IMAP4_CAPABILITY_IMAP4REV1 = (1 << 1), - CAMEL_IMAP4_CAPABILITY_STATUS = (1 << 2), - CAMEL_IMAP4_CAPABILITY_NAMESPACE = (1 << 3), - CAMEL_IMAP4_CAPABILITY_UIDPLUS = (1 << 4), - CAMEL_IMAP4_CAPABILITY_LITERALPLUS = (1 << 5), - CAMEL_IMAP4_CAPABILITY_LOGINDISABLED = (1 << 6), - CAMEL_IMAP4_CAPABILITY_STARTTLS = (1 << 7), - CAMEL_IMAP4_CAPABILITY_IDLE = (1 << 8), - CAMEL_IMAP4_CAPABILITY_QUOTA = (1 << 9), - CAMEL_IMAP4_CAPABILITY_ACL = (1 << 10), - CAMEL_IMAP4_CAPABILITY_MULTIAPPEND = (1 << 11), - CAMEL_IMAP4_CAPABILITY_UNSELECT = (1 << 12), - - CAMEL_IMAP4_CAPABILITY_XGWEXTENSIONS = (1 << 16), - CAMEL_IMAP4_CAPABILITY_XGWMOVE = (1 << 17), - - CAMEL_IMAP4_CAPABILITY_useful_lsub = (1 << 30), - CAMEL_IMAP4_CAPABILITY_utf8_search = (1 << 31), -}; - -typedef enum { - CAMEL_IMAP4_RESP_CODE_ALERT, - CAMEL_IMAP4_RESP_CODE_BADCHARSET, - CAMEL_IMAP4_RESP_CODE_CAPABILITY, - CAMEL_IMAP4_RESP_CODE_PARSE, - CAMEL_IMAP4_RESP_CODE_PERM_FLAGS, - CAMEL_IMAP4_RESP_CODE_READONLY, - CAMEL_IMAP4_RESP_CODE_READWRITE, - CAMEL_IMAP4_RESP_CODE_TRYCREATE, - CAMEL_IMAP4_RESP_CODE_UIDNEXT, - CAMEL_IMAP4_RESP_CODE_UIDVALIDITY, - CAMEL_IMAP4_RESP_CODE_UNSEEN, - CAMEL_IMAP4_RESP_CODE_NEWNAME, - CAMEL_IMAP4_RESP_CODE_APPENDUID, - CAMEL_IMAP4_RESP_CODE_COPYUID, - CAMEL_IMAP4_RESP_CODE_UNKNOWN, -} camel_imap4_resp_code_t; - -typedef struct _CamelIMAP4RespCode { - camel_imap4_resp_code_t code; - union { - guint32 flags; - gchar *parse; - guint32 uidnext; - guint32 uidvalidity; - guint32 unseen; - gchar *newname[2]; - struct { - guint32 uidvalidity; - guint32 uid; - } appenduid; - struct { - guint32 uidvalidity; - gchar *srcset; - gchar *destset; - } copyuid; - } v; -} CamelIMAP4RespCode; - -enum { - CAMEL_IMAP4_UNTAGGED_ERROR = -1, - CAMEL_IMAP4_UNTAGGED_OK, - CAMEL_IMAP4_UNTAGGED_NO, - CAMEL_IMAP4_UNTAGGED_BAD, - CAMEL_IMAP4_UNTAGGED_PREAUTH, - CAMEL_IMAP4_UNTAGGED_HANDLED, -}; - -typedef struct _CamelIMAP4Namespace { - struct _CamelIMAP4Namespace *next; - gchar *path; - gchar sep; -} CamelIMAP4Namespace; - -typedef struct _CamelIMAP4NamespaceList { - CamelIMAP4Namespace *personal; - CamelIMAP4Namespace *other; - CamelIMAP4Namespace *shared; -} CamelIMAP4NamespaceList; - -enum { - CAMEL_IMAP4_ENGINE_MAXLEN_LINE, - CAMEL_IMAP4_ENGINE_MAXLEN_TOKEN -}; - -typedef gboolean (* CamelIMAP4ReconnectFunc) (CamelIMAP4Engine *engine, CamelException *ex); - -struct _CamelIMAP4Engine { - CamelObject parent; - - CamelIMAP4ReconnectFunc reconnect; - gboolean reconnecting; - - CamelSession *session; - CamelService *service; - CamelURL *url; - - camel_imap4_engine_t state; - camel_imap4_level_t level; - guint32 capa; - - guint32 maxlen:31; - guint32 maxlentype:1; - - CamelIMAP4NamespaceList namespaces; - GHashTable *authtypes; /* supported authtypes */ - - struct _CamelIMAP4Stream *istream; - CamelStream *ostream; - - guchar tagprefix; /* 'A'..'Z' */ - guint tag; /* next command tag */ - gint nextid; - - struct _CamelIMAP4Folder *folder; /* currently selected folder */ - - CamelDList queue; /* queue of waiting commands */ - struct _CamelIMAP4Command *current; -}; - -struct _CamelIMAP4EngineClass { - CamelObjectClass parent_class; - - guchar tagprefix; -}; - -CamelType camel_imap4_engine_get_type (void); - -CamelIMAP4Engine *camel_imap4_engine_new (CamelService *service, CamelIMAP4ReconnectFunc reconnect); - -/* returns 0 on success or -1 on error */ -gint camel_imap4_engine_take_stream (CamelIMAP4Engine *engine, CamelStream *stream, CamelException *ex); - -void camel_imap4_engine_disconnect (CamelIMAP4Engine *engine); - -gint camel_imap4_engine_capability (CamelIMAP4Engine *engine, CamelException *ex); -gint camel_imap4_engine_namespace (CamelIMAP4Engine *engine, CamelException *ex); - -gint camel_imap4_engine_select_folder (CamelIMAP4Engine *engine, CamelFolder *folder, CamelException *ex); - -struct _CamelIMAP4Command *camel_imap4_engine_queue (CamelIMAP4Engine *engine, CamelFolder *folder, - const gchar *format, ...); -struct _CamelIMAP4Command *camel_imap4_engine_prequeue (CamelIMAP4Engine *engine, CamelFolder *folder, - const gchar *format, ...); - -void camel_imap4_engine_dequeue (CamelIMAP4Engine *engine, struct _CamelIMAP4Command *ic); - -gint camel_imap4_engine_iterate (CamelIMAP4Engine *engine); - -/* untagged response utility functions */ -gint camel_imap4_engine_handle_untagged_1 (CamelIMAP4Engine *engine, struct _camel_imap4_token_t *token, CamelException *ex); -void camel_imap4_engine_handle_untagged (CamelIMAP4Engine *engine, CamelException *ex); - -/* stream wrapper utility functions */ -gint camel_imap4_engine_next_token (CamelIMAP4Engine *engine, struct _camel_imap4_token_t *token, CamelException *ex); -gint camel_imap4_engine_line (CamelIMAP4Engine *engine, guchar **line, gsize *len, CamelException *ex); -gint camel_imap4_engine_literal (CamelIMAP4Engine *engine, guchar **literal, gsize *len, CamelException *ex); -gint camel_imap4_engine_nstring (CamelIMAP4Engine *engine, guchar **nstring, CamelException *ex); -gint camel_imap4_engine_eat_line (CamelIMAP4Engine *engine, CamelException *ex); - -/* response code stuff */ -gint camel_imap4_engine_parse_resp_code (CamelIMAP4Engine *engine, CamelException *ex); -void camel_imap4_resp_code_free (CamelIMAP4RespCode *rcode); - -G_END_DECLS - -#endif /* CAMEL_IMAP4_ENGINE_H */ diff --git a/camel/providers/imap4/camel-imap4-folder.c b/camel/providers/imap4/camel-imap4-folder.c deleted file mode 100644 index 0e388fb..0000000 --- a/camel/providers/imap4/camel-imap4-folder.c +++ /dev/null @@ -1,1274 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "camel-imap4-utils.h" -#include "camel-imap4-store.h" -#include "camel-imap4-engine.h" -#include "camel-imap4-folder.h" -#include "camel-imap4-journal.h" -#include "camel-imap4-stream.h" -#include "camel-imap4-command.h" -#include "camel-imap4-summary.h" -#include "camel-imap4-search.h" - -#define d(x) - -static void camel_imap4_folder_class_init (CamelIMAP4FolderClass *klass); -static void camel_imap4_folder_init (CamelIMAP4Folder *folder, CamelIMAP4FolderClass *klass); -static void camel_imap4_folder_finalize (CamelObject *object); - -static gint imap4_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args); -static gint imap4_setv (CamelObject *object, CamelException *ex, CamelArgV *args); - -static void imap4_sync (CamelFolder *folder, gboolean expunge, CamelException *ex); -static void imap4_refresh_info (CamelFolder *folder, CamelException *ex); -static void imap4_expunge (CamelFolder *folder, CamelException *ex); -static CamelMimeMessage *imap4_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex); -static void imap4_append_message (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, gchar **appended_uid, CamelException *ex); -static void imap4_transfer_messages_to (CamelFolder *src, GPtrArray *uids, CamelFolder *dest, - GPtrArray **transferred_uids, gboolean move, CamelException *ex); -static GPtrArray *imap4_search_by_expression (CamelFolder *folder, const gchar *expr, CamelException *ex); -static GPtrArray *imap4_search_by_uids (CamelFolder *folder, const gchar *expr, GPtrArray *uids, CamelException *ex); -static void imap4_search_free (CamelFolder *folder, GPtrArray *uids); -static gchar * imap4_get_filename (CamelFolder *folder, const gchar *uid, CamelException *ex); - -static CamelOfflineFolderClass *parent_class = NULL; - -static GSList *imap4_folder_props = NULL; - -static CamelProperty imap4_prop_list[] = { - { CAMEL_IMAP4_FOLDER_ENABLE_MLIST, "mlist_info", N_("Enable extended Mailing-List detection required for some filter and vFolder rules") }, - { CAMEL_IMAP4_FOLDER_EXPIRE_ACCESS, "expire-access", N_("Expire cached messages that haven't been read in X seconds") }, - { CAMEL_IMAP4_FOLDER_EXPIRE_AGE, "expire-age", N_("Expire cached messages older than X seconds") }, -}; - -CamelType -camel_imap4_folder_get_type (void) -{ - static CamelType type = 0; - - if (!type) { - type = camel_type_register (camel_offline_folder_get_type (), - "CamelIMAP4Folder", - sizeof (CamelIMAP4Folder), - sizeof (CamelIMAP4FolderClass), - (CamelObjectClassInitFunc) camel_imap4_folder_class_init, - NULL, - (CamelObjectInitFunc) camel_imap4_folder_init, - (CamelObjectFinalizeFunc) camel_imap4_folder_finalize); - } - - return type; -} - -static void -camel_imap4_folder_class_init (CamelIMAP4FolderClass *klass) -{ - CamelFolderClass *folder_class = (CamelFolderClass *) klass; - CamelObjectClass *object_class = (CamelObjectClass *) klass; - gint i; - - parent_class = (CamelOfflineFolderClass *) camel_type_get_global_classfuncs (CAMEL_OFFLINE_FOLDER_TYPE); - - if (imap4_folder_props == NULL) { - for (i = 0; i < G_N_ELEMENTS (imap4_prop_list); i++) { - imap4_prop_list[i].description = _(imap4_prop_list[i].description); - imap4_folder_props = g_slist_prepend (imap4_folder_props, &imap4_prop_list[i]); - } - } - - object_class->getv = imap4_getv; - object_class->setv = imap4_setv; - - folder_class->sync = imap4_sync; - folder_class->refresh_info = imap4_refresh_info; - folder_class->expunge = imap4_expunge; - folder_class->get_message = imap4_get_message; - folder_class->append_message = imap4_append_message; - folder_class->transfer_messages_to = imap4_transfer_messages_to; - folder_class->search_by_expression = imap4_search_by_expression; - folder_class->search_by_uids = imap4_search_by_uids; - folder_class->search_free = imap4_search_free; - folder_class->get_filename = imap4_get_filename; -} - -static void -camel_imap4_folder_init (CamelIMAP4Folder *folder, CamelIMAP4FolderClass *klass) -{ - ((CamelFolder *) folder)->folder_flags |= CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | CAMEL_FOLDER_HAS_SEARCH_CAPABILITY; - - folder->utf7_name = NULL; - folder->cachedir = NULL; - folder->journal = NULL; - folder->search = NULL; -} - -static void -camel_imap4_folder_finalize (CamelObject *object) -{ - CamelIMAP4Folder *folder = (CamelIMAP4Folder *) object; - - camel_object_unref (folder->search); - - camel_object_unref (folder->cache); - - if (folder->journal) { - camel_offline_journal_write (folder->journal, NULL); - camel_object_unref (folder->journal); - } - - g_free (folder->utf7_name); - g_free (folder->cachedir); -} - -static gchar * -imap4_get_filename (CamelFolder *folder, const gchar *uid, CamelException *ex) -{ - CamelIMAP4Folder *imap4_folder = (CamelIMAP4Folder *) folder; - - return camel_data_cache_get_filename (imap4_folder->cache, "cache", uid, ex); -} - -static gint -imap4_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args) -{ - CamelIMAP4Folder *folder = (CamelIMAP4Folder *) object; - CamelArgGetV props; - gint i, count = 0; - guint32 tag; - - for (i = 0; i < args->argc; i++) { - CamelArgGet *arg = &args->argv[i]; - - tag = arg->tag; - - switch (tag & CAMEL_ARG_TAG) { - case CAMEL_OBJECT_ARG_PERSISTENT_PROPERTIES: - case CAMEL_FOLDER_ARG_PROPERTIES: - props.argc = 1; - props.argv[0] = *arg; - ((CamelObjectClass *) parent_class)->getv (object, ex, &props); - *arg->ca_ptr = g_slist_concat (*arg->ca_ptr, g_slist_copy (imap4_folder_props)); - break; - case CAMEL_IMAP4_FOLDER_ARG_ENABLE_MLIST: - *arg->ca_int = folder->enable_mlist; - break; - case CAMEL_IMAP4_FOLDER_ARG_EXPIRE_ACCESS: - *arg->ca_int = folder->cache->expire_access; - break; - case CAMEL_IMAP4_FOLDER_ARG_EXPIRE_AGE: - *arg->ca_int = folder->cache->expire_age; - break; - default: - count++; - continue; - } - - arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE; - } - - if (count) - return ((CamelObjectClass *) parent_class)->getv (object, ex, args); - - return 0; -} - -static gint -imap4_setv (CamelObject *object, CamelException *ex, CamelArgV *args) -{ - CamelIMAP4Folder *folder = (CamelIMAP4Folder *) object; - CamelDataCache *cache = folder->cache; - gboolean save = FALSE; - guint32 tag; - gint i; - - for (i = 0; i < args->argc; i++) { - CamelArg *arg = &args->argv[i]; - - tag = arg->tag; - - switch (tag & CAMEL_ARG_TAG) { - case CAMEL_IMAP4_FOLDER_ARG_ENABLE_MLIST: - if (folder->enable_mlist != arg->ca_int) { - folder->enable_mlist = arg->ca_int; - save = TRUE; - } - break; - case CAMEL_IMAP4_FOLDER_ARG_EXPIRE_ACCESS: - if (cache->expire_access != (time_t) arg->ca_int) { - camel_data_cache_set_expire_access (cache, (time_t) arg->ca_int); - save = TRUE; - } - break; - case CAMEL_IMAP4_FOLDER_ARG_EXPIRE_AGE: - if (cache->expire_age != (time_t) arg->ca_int) { - camel_data_cache_set_expire_age (cache, (time_t) arg->ca_int); - save = TRUE; - } - break; - default: - continue; - } - - arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE; - } - - if (save) - camel_object_state_write (object); - - return ((CamelObjectClass *) parent_class)->setv (object, ex, args); -} - -static gchar * -imap4_get_summary_filename (const gchar *path) -{ - /* /path/to/imap/summary */ - return g_build_filename (path, "summary", NULL); -} - -static gchar * -imap4_get_journal_filename (const gchar *path) -{ - /* /path/to/imap/journal */ - return g_build_filename (path, "journal", NULL); -} - -static gchar * -imap4_build_filename (const gchar *toplevel_dir, const gchar *full_name) -{ - const gchar *inptr = full_name; - gint subdirs = 0; - gchar *path, *p; - - if (*full_name == '\0') - return g_strdup (toplevel_dir); - - while (*inptr != '\0') { - if (*inptr == '/') - subdirs++; - inptr++; - } - - path = g_malloc (strlen (toplevel_dir) + (inptr - full_name) + (12 * subdirs) + 2); - p = g_stpcpy (path, toplevel_dir); - - if (p[-1] != '/') - *p++ = '/'; - - inptr = full_name; - while (*inptr != '\0') { - while (*inptr != '/' && *inptr != '\0') - *p++ = *inptr++; - - if (*inptr == '/') { - p = g_stpcpy (p, "/subfolders/"); - inptr++; - - /* strip extranaeous '/'s */ - while (*inptr == '/') - inptr++; - } - } - - *p = '\0'; - - return path; -} - -static gchar * -imap4_store_build_filename (gpointer store, const gchar *full_name) -{ - CamelIMAP4Store *imap4_store = (CamelIMAP4Store *) store; - gchar *toplevel_dir; - gchar *path; - - toplevel_dir = g_strdup_printf ("%s/folders", imap4_store->storage_path); - path = imap4_build_filename (toplevel_dir, full_name); - g_free (toplevel_dir); - - return path; -} - -CamelFolder * -camel_imap4_folder_new (CamelStore *store, const gchar *full_name, CamelException *ex) -{ - CamelIMAP4Folder *imap4_folder; - gchar *utf7_name, *name, *p; - CamelFolder *folder; - gchar *path; - gchar sep; - - if (!(p = strrchr (full_name, '/'))) - p = (gchar *) full_name; - else - p++; - - name = g_alloca (strlen (p) + 1); - strcpy (name, p); - - utf7_name = g_alloca (strlen (full_name) + 1); - strcpy (utf7_name, full_name); - - sep = camel_imap4_get_path_delim (((CamelIMAP4Store *) store)->summary, full_name); - if (sep != '/') { - p = utf7_name; - while (*p != '\0') { - if (*p == '/') - *p = sep; - p++; - } - } - - utf7_name = camel_utf8_utf7 (utf7_name); - - folder = (CamelFolder *) (imap4_folder = (CamelIMAP4Folder *) camel_object_new (CAMEL_TYPE_IMAP4_FOLDER)); - camel_folder_construct (folder, store, full_name, name); - imap4_folder->utf7_name = utf7_name; - - folder->summary = camel_imap4_summary_new (folder); - imap4_folder->cachedir = imap4_store_build_filename (store, folder->full_name); - g_mkdir_with_parents (imap4_folder->cachedir, 0700); - - imap4_folder->cache = camel_data_cache_new (imap4_folder->cachedir, 0, NULL); - - path = imap4_get_summary_filename (imap4_folder->cachedir); - camel_folder_summary_set_filename (folder->summary, path); - g_free (path); - - path = imap4_get_journal_filename (imap4_folder->cachedir); - imap4_folder->journal = camel_imap4_journal_new (imap4_folder, path); - g_free (path); - - path = g_build_filename (imap4_folder->cachedir, "cmeta", NULL); - camel_object_set (folder, NULL, CAMEL_OBJECT_STATE_FILE, path, NULL); - g_free (path); - - if (camel_object_state_read (folder) == -1) { - /* set our defaults */ - imap4_folder->enable_mlist = FALSE; - } - - if (!g_ascii_strcasecmp (full_name, "INBOX")) { - if (camel_url_get_param (((CamelService *) store)->url, "filter")) - folder->folder_flags |= CAMEL_FOLDER_FILTER_RECENT; - if (camel_url_get_param (((CamelService *) store)->url, "filter_junk")) - folder->folder_flags |= CAMEL_FOLDER_FILTER_JUNK; - } else if (!camel_url_get_param (((CamelService *) store)->url, "filter_junk_inbox")) { - if (camel_url_get_param (((CamelService *) store)->url, "filter_junk")) - folder->folder_flags |= CAMEL_FOLDER_FILTER_JUNK; - } - - imap4_folder->search = camel_imap4_search_new (((CamelIMAP4Store *) store)->engine, imap4_folder->cachedir); - - if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_AVAIL) { - /* we don't care if the summary loading fails here */ - camel_folder_summary_load (folder->summary); - - if (camel_imap4_engine_select_folder (((CamelIMAP4Store *) store)->engine, folder, ex) == -1) { - camel_object_unref (folder); - folder = NULL; - } - - if (folder && camel_imap4_summary_flush_updates (folder->summary, ex) == -1) { - camel_object_unref (folder); - folder = NULL; - } - } else { - /* we *do* care if summary loading fails here though */ - if (camel_folder_summary_load (folder->summary) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_PATH, - _("Cannot access folder '%s': %s"), - full_name, g_strerror (ENOENT)); - - camel_object_unref (folder); - folder = NULL; - } - } - - return folder; -} - -const gchar * -camel_imap4_folder_utf7_name (CamelIMAP4Folder *folder) -{ - return folder->utf7_name; -} - -static struct { - const gchar *name; - guint32 flag; -} imap4_flags[] = { - { "\\Answered", CAMEL_MESSAGE_ANSWERED }, - { "\\Deleted", CAMEL_MESSAGE_DELETED }, - { "\\Draft", CAMEL_MESSAGE_DRAFT }, - { "\\Flagged", CAMEL_MESSAGE_FLAGGED }, - /*{ "$Forwarded", CAMEL_MESSAGE_FORWARDED },*/ - { "\\Seen", CAMEL_MESSAGE_SEEN }, -}; - -static gint -imap4_sync_flag (CamelFolder *folder, GPtrArray *infos, gchar onoff, const gchar *flag, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - CamelIMAP4Command *ic; - gint i, id, retval = 0; - gchar *set = NULL; - - for (i = 0; i < infos->len; ) { - i += camel_imap4_get_uid_set (engine, folder->summary, infos, i, 30 + strlen (flag), &set); - - ic = camel_imap4_engine_queue (engine, folder, "UID STORE %s %cFLAGS.SILENT (%s)\r\n", set, onoff, flag); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - g_free (set); - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - - return -1; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot sync flags to folder '%s': Unknown error"), - folder->full_name); - retval = -1; - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot sync flags to folder '%s': Bad command"), - folder->full_name); - retval = -1; - break; - } - - camel_imap4_command_unref (ic); - - if (retval == -1) - return -1; - } - - return 0; -} - -static gint -imap4_sync_changes (CamelFolder *folder, GPtrArray *sync, CamelException *ex) -{ - CamelIMAP4MessageInfo *iinfo; - GPtrArray *on_set, *off_set; - CamelMessageInfo *info; - flags_diff_t diff; - gint retval = 0; - gint i, j; - - on_set = g_ptr_array_new (); - off_set = g_ptr_array_new (); - - /* construct commands to sync system and user flags */ - for (i = 0; i < G_N_ELEMENTS (imap4_flags); i++) { - if (!(imap4_flags[i].flag & folder->permanent_flags)) - continue; - - for (j = 0; j < sync->len; j++) { - iinfo = (CamelIMAP4MessageInfo *) (info = sync->pdata[j]); - camel_imap4_flags_diff (&diff, iinfo->server_flags, iinfo->info.flags); - if (diff.changed & imap4_flags[i].flag) { - if (diff.bits & imap4_flags[i].flag) { - g_ptr_array_add (on_set, info); - } else { - g_ptr_array_add (off_set, info); - } - } - } - - if (on_set->len > 0) { - if ((retval = imap4_sync_flag (folder, on_set, '+', imap4_flags[i].name, ex)) == -1) - break; - - g_ptr_array_set_size (on_set, 0); - } - - if (off_set->len > 0) { - if ((retval = imap4_sync_flag (folder, off_set, '-', imap4_flags[i].name, ex)) == -1) - break; - - g_ptr_array_set_size (off_set, 0); - } - } - - g_ptr_array_free (on_set, TRUE); - g_ptr_array_free (off_set, TRUE); - - if (retval == -1) - return-1; - - for (i = 0; i < sync->len; i++) { - iinfo = (CamelIMAP4MessageInfo *) (info = sync->pdata[i]); - iinfo->info.flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED; - iinfo->server_flags = iinfo->info.flags & folder->permanent_flags; - } - - return 0; -} - -static void -imap4_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - CamelOfflineStore *offline = (CamelOfflineStore *) folder->parent_store; - CamelIMAP4MessageInfo *iinfo; - CamelMessageInfo *info; - CamelIMAP4Command *ic; - flags_diff_t diff; - GPtrArray *sync; - gint id, max, i; - gint retval; - - if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) - return; - - CAMEL_SERVICE_REC_LOCK (folder->parent_store, connect_lock); - - /* gather a list of changes to sync to the server */ - if (folder->permanent_flags) { - sync = g_ptr_array_new (); - max = camel_folder_summary_count (folder->summary); - for (i = 0; i < max; i++) { - iinfo = (CamelIMAP4MessageInfo *) (info = camel_folder_summary_index (folder->summary, i)); - if (iinfo->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) { - camel_imap4_flags_diff (&diff, iinfo->server_flags, iinfo->info.flags); - diff.changed &= folder->permanent_flags; - - /* weed out flag changes that we can't sync to the server */ - if (!diff.changed) - camel_message_info_free(info); - else - g_ptr_array_add (sync, info); - } else { - camel_message_info_free(info); - } - } - - if (sync->len > 0) { - retval = imap4_sync_changes (folder, sync, ex); - - for (i = 0; i < sync->len; i++) - camel_message_info_free(sync->pdata[i]); - - g_ptr_array_free (sync, TRUE); - - if (retval == -1) - goto done; - } else { - g_ptr_array_free (sync, TRUE); - } - } - - if (expunge && !((CamelIMAP4Folder *) folder)->read_only) { - ic = camel_imap4_engine_queue (engine, folder, "EXPUNGE\r\n"); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - camel_imap4_summary_flush_updates (folder->summary, ex); - break; - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot expunge folder '%s': Unknown error"), - folder->full_name); - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot expunge folder '%s': Bad command"), - folder->full_name); - break; - } - - camel_imap4_command_unref (ic); - } else { - camel_imap4_summary_flush_updates (folder->summary, ex); - } - - camel_folder_summary_save (folder->summary); - - done: - - CAMEL_SERVICE_REC_UNLOCK (folder->parent_store, connect_lock); -} - -static void -imap4_expunge (CamelFolder *folder, CamelException *ex) -{ - imap4_sync (folder, TRUE, ex); -} - -static void -imap4_refresh_info (CamelFolder *folder, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - CamelOfflineStore *offline = (CamelOfflineStore *) folder->parent_store; - CamelFolder *selected = (CamelFolder *) engine->folder; - CamelIMAP4Command *ic; - gint id; - - if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) - return; - - CAMEL_SERVICE_REC_LOCK (folder->parent_store, connect_lock); - - if (folder != selected) { - if (camel_imap4_engine_select_folder (engine, folder, ex) == -1) - goto done; - - ((CamelIMAP4Summary *) folder->summary)->update_flags = TRUE; - } else { - ic = camel_imap4_engine_queue (engine, NULL, "NOOP\r\n"); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) - camel_exception_xfer (ex, &ic->ex); - - camel_imap4_command_unref (ic); - - if (camel_exception_is_set (ex)) - goto done; - } - - camel_imap4_summary_flush_updates (folder->summary, ex); - - done: - - CAMEL_SERVICE_REC_UNLOCK (folder->parent_store, connect_lock); -} - -static gint -untagged_fetch (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, guint32 index, camel_imap4_token_t *token, CamelException *ex) -{ - CamelFolderSummary *summary = ((CamelFolder *) engine->folder)->summary; - CamelStream *fstream, *stream = ic->user_data; - CamelFolderChangeInfo *changes; - CamelIMAP4MessageInfo *iinfo; - CamelMessageInfo *info; - CamelMimeFilter *crlf; - guint32 flags; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - /* parse the FETCH response list */ - if (token->token != '(') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - return -1; - } - - do { - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token == ')' || token->token == '\n') - break; - - if (token->token != CAMEL_IMAP4_TOKEN_ATOM) - goto unexpected; - - if (!strcmp (token->v.atom, "BODY[")) { - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token != ']') - goto unexpected; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token != CAMEL_IMAP4_TOKEN_LITERAL) - goto unexpected; - - fstream = (CamelStream *) camel_stream_filter_new_with_stream (stream); - crlf = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_DECODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); - camel_stream_filter_add ((CamelStreamFilter *) fstream, crlf); - camel_object_unref (crlf); - - camel_stream_write_to_stream ((CamelStream *) engine->istream, fstream); - camel_stream_flush (fstream); - camel_object_unref (fstream); - } else if (!strcmp (token->v.atom, "UID")) { - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token != CAMEL_IMAP4_TOKEN_NUMBER || token->v.number == 0) - goto unexpected; - } else if (!strcmp (token->v.atom, "FLAGS")) { - /* even though we didn't request this bit of information, it might be - * given to us if another client recently changed the flags... */ - if (camel_imap4_parse_flags_list (engine, &flags, ex) == -1) - goto exception; - - if ((info = camel_folder_summary_index (summary, index - 1))) { - iinfo = (CamelIMAP4MessageInfo *) info; - iinfo->info.flags = camel_imap4_merge_flags (iinfo->server_flags, iinfo->info.flags, flags); - iinfo->server_flags = flags; - - changes = camel_folder_change_info_new (); - camel_folder_change_info_change_uid (changes, camel_message_info_uid (info)); - camel_object_trigger_event (engine->folder, "folder_changed", changes); - camel_folder_change_info_free (changes); - - camel_message_info_free(info); - } - } else { - /* wtf? */ - d(fprintf (stderr, "huh? %s?...\n", token->v.atom)); - } - } while (1); - - if (token->token != ')') { - d(fprintf (stderr, "expected ')' to close untagged FETCH response\n")); - goto unexpected; - } - - return 0; - - unexpected: - - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - - exception: - - return -1; -} - -static CamelMimeMessage * -imap4_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - CamelOfflineStore *offline = (CamelOfflineStore *) folder->parent_store; - CamelIMAP4Folder *imap4_folder = (CamelIMAP4Folder *) folder; - CamelMimeMessage *message = NULL; - CamelStream *stream, *cache; - CamelIMAP4Command *ic; - gint id; - - CAMEL_SERVICE_REC_LOCK (folder->parent_store, connect_lock); - - if (imap4_folder->cache && (stream = camel_data_cache_get (imap4_folder->cache, "cache", uid, ex))) { - message = camel_mime_message_new (); - - if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) message, stream) == -1) { - if (errno == EINTR) { - CAMEL_SERVICE_REC_UNLOCK (folder->parent_store, connect_lock); - camel_exception_setv (ex, CAMEL_EXCEPTION_USER_CANCEL, _("User canceled")); - camel_object_unref (message); - camel_object_unref (stream); - return NULL; - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get message %s: %s"), - uid, g_strerror (errno)); - camel_object_unref (message); - message = NULL; - } - } - - camel_object_unref (stream); - } - - if (message != NULL) { - CAMEL_SERVICE_REC_UNLOCK (folder->parent_store, connect_lock); - return message; - } - - if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) { - CAMEL_SERVICE_REC_UNLOCK (folder->parent_store, connect_lock); - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("This message is not available in offline mode.")); - return NULL; - } - - /* Note: While some hard-core IMAP extremists are probably - * going to flame me for fetching entire messages here, it's - * the *only* sure-fire way of working with all IMAP - * servers. There are numerous problems with fetching - * individual MIME parts from a good handful of IMAP servers - * which makes this a pain to do the Right Way (tm). For - * example: Courier-IMAP has "issues" parsing some multipart - * messages apparently, because BODY responses are often - * inaccurate. I'm also not very trusting of the free German - * IMAP hosting either (such as mail.gmx.net and imap.web.de) - * as they have proven themselves to be quite flakey wrt FETCH - * requests (they seem to be written exclusively for - * Outlook). Also, some IMAP servers such as GroupWise don't - * store mail in MIME format and so must re-construct the - * entire message in order to extract the requested part, so - * it is *much* more efficient (generally) to just request the - * entire message anyway. */ - ic = camel_imap4_engine_queue (engine, folder, "UID FETCH %s BODY.PEEK[]\r\n", uid); - camel_imap4_command_register_untagged (ic, "FETCH", untagged_fetch); - ic->user_data = stream = camel_stream_mem_new (); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - camel_object_unref (stream); - goto done; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - camel_stream_reset (stream); - message = camel_mime_message_new (); - camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) message, stream); - camel_stream_reset (stream); - - /* cache the message locally */ - if (imap4_folder->cache && (cache = camel_data_cache_add (imap4_folder->cache, "cache", uid, NULL))) { - if (camel_stream_write_to_stream (stream, cache) == -1 - || camel_stream_flush (cache) == -1) - camel_data_cache_remove (imap4_folder->cache, "cache", uid, NULL); - camel_object_unref (cache); - } - - break; - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get message %s from folder '%s': No such message"), - uid, folder->full_name); - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get message %s from folder '%s': Bad command"), - uid, folder->full_name); - break; - } - - camel_imap4_command_unref (ic); - - camel_object_unref (stream); - - done: - - CAMEL_SERVICE_REC_UNLOCK (folder->parent_store, connect_lock); - - return message; -} - -static gchar *tm_months[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -static void -imap4_append_message (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, gchar **appended_uid, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - CamelOfflineStore *offline = (CamelOfflineStore *) folder->parent_store; - CamelIMAP4Summary *summary = (CamelIMAP4Summary *) folder->summary; - const CamelIMAP4MessageInfo *iinfo = (const CamelIMAP4MessageInfo *) info; - CamelIMAP4Folder *imap4_folder = (CamelIMAP4Folder *) folder; - CamelIMAP4RespCode *resp; - CamelIMAP4Command *ic; - CamelFolderInfo *fi; - CamelException lex; - gchar flags[100], *p; - gchar date[50]; - struct tm tm; - gint id, i; - - if (appended_uid) - *appended_uid = NULL; - - if (((CamelIMAP4Folder *) folder)->read_only) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message to folder '%s': Folder is read-only"), - folder->full_name); - return; - } - - if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) { - camel_imap4_journal_append ((CamelIMAP4Journal *) imap4_folder->journal, message, info, appended_uid, ex); - return; - } - - CAMEL_SERVICE_REC_LOCK (folder->parent_store, connect_lock); - - /* construct the option flags list */ - if (iinfo->info.flags & folder->permanent_flags) { - p = g_stpcpy (flags, " ("); - - for (i = 0; i < G_N_ELEMENTS (imap4_flags); i++) { - if ((iinfo->info.flags & imap4_flags[i].flag) & folder->permanent_flags) { - p = g_stpcpy (p, imap4_flags[i].name); - *p++ = ' '; - } - } - - p[-1] = ')'; - *p = '\0'; - } else { - flags[0] = '\0'; - } - - /* construct the optional date_time string */ - if (iinfo->info.date_received > (time_t) 0) { - gint tzone; - -#ifdef HAVE_LOCALTIME_R - localtime_r (&iinfo->info.date_received, &tm); -#else - memcpy (&tm, localtime (&iinfo->info.date_received), sizeof (tm)); -#endif - -#if defined (HAVE_TM_GMTOFF) - tzone = -tm.tm_gmtoff; -#elif defined (HAVE_TIMEZONE) - if (tm.tm_isdst > 0) { -#if defined (HAVE_ALTZONE) - tzone = altzone; -#else /* !defined (HAVE_ALTZONE) */ - tzone = (timezone - 3600); -#endif - } else { - tzone = timezone; - } -#else -#error Neither HAVE_TIMEZONE nor HAVE_TM_GMTOFF defined. Rerun autoheader, autoconf, etc. -#endif - - sprintf (date, " \"%02d-%s-%04d %02d:%02d:%02d %+05d\"", - tm.tm_mday, tm_months[tm.tm_mon], tm.tm_year + 1900, - tm.tm_hour, tm.tm_min, tm.tm_sec, tzone); - } else { - date[0] = '\0'; - } - - retry: - - ic = camel_imap4_engine_queue (engine, NULL, "APPEND %F%s%s %L\r\n", folder, flags, date, message); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - CAMEL_SERVICE_REC_UNLOCK (folder->parent_store, connect_lock); - return; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - if (!appended_uid || !(engine->capa & CAMEL_IMAP4_CAPABILITY_UIDPLUS)) - break; - - for (i = 0; i < ic->resp_codes->len; i++) { - resp = ic->resp_codes->pdata[i]; - if (resp->code == CAMEL_IMAP4_RESP_CODE_APPENDUID) { - if (resp->v.appenduid.uidvalidity == summary->uidvalidity) - *appended_uid = g_strdup_printf ("%u", resp->v.appenduid.uid); - break; - } - } - break; - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: can we give the user any more information? */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message to folder '%s': Unknown error"), - folder->full_name); - - for (i = 0; i < ic->resp_codes->len; i++) { - resp = ic->resp_codes->pdata[i]; - if (resp->code == CAMEL_IMAP4_RESP_CODE_TRYCREATE) { - gchar *parent_name, *p; - - parent_name = g_alloca (strlen (folder->full_name) + 1); - strcpy (parent_name, folder->full_name); - if (!(p = strrchr (parent_name, '/'))) - *parent_name = '\0'; - else - *p = '\0'; - - if (!(fi = camel_store_create_folder (folder->parent_store, parent_name, folder->name, &lex))) { - camel_exception_clear (&lex); - break; - } - - camel_store_free_folder_info (folder->parent_store, fi); - camel_imap4_command_unref (ic); - camel_exception_clear (ex); - goto retry; - } - } - - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message to folder '%s': Bad command"), - folder->full_name); - - break; - default: - g_assert_not_reached (); - } - - camel_imap4_command_unref (ic); - - CAMEL_SERVICE_REC_UNLOCK (folder->parent_store, connect_lock); -} - -static gint -info_uid_sort (const CamelMessageInfo **info0, const CamelMessageInfo **info1) -{ - guint32 uid0, uid1; - - uid0 = strtoul (camel_message_info_uid (*info0), NULL, 10); - uid1 = strtoul (camel_message_info_uid (*info1), NULL, 10); - - if (uid0 == uid1) - return 0; - - return uid0 < uid1 ? -1 : 1; -} - -static void -imap4_transfer_messages_to (CamelFolder *src, GPtrArray *uids, CamelFolder *dest, - GPtrArray **transferred_uids, gboolean move, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) src->parent_store)->engine; - CamelOfflineStore *offline = (CamelOfflineStore *) src->parent_store; - gint i, j, n, id, dest_namelen; - CamelMessageInfo *info; - CamelIMAP4Command *ic; - CamelException lex; - GPtrArray *infos; - gchar *set; - - if (transferred_uids) - *transferred_uids = NULL; - - camel_exception_init (&lex); - imap4_sync (src, FALSE, &lex); - if (camel_exception_is_set (&lex)) { - camel_exception_xfer (ex, &lex); - return; - } - - infos = g_ptr_array_new (); - for (i = 0; i < uids->len; i++) { - if (!(info = camel_folder_summary_uid (src->summary, uids->pdata[i]))) - continue; - - g_ptr_array_add (infos, info); - } - - if (infos->len == 0) { - g_ptr_array_free (infos, TRUE); - return; - } - - g_ptr_array_sort (infos, (GCompareFunc) info_uid_sort); - - CAMEL_SERVICE_REC_LOCK (src->parent_store, connect_lock); - - /* check for offline operation */ - if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) { - CamelIMAP4Journal *journal = (CamelIMAP4Journal *) ((CamelIMAP4Folder *) dest)->journal; - CamelMimeMessage *message; - - for (i = 0; i < infos->len; i++) { - info = infos->pdata[i]; - - if (!(message = imap4_get_message (src, camel_message_info_uid (info), ex))) - break; - - camel_imap4_journal_append (journal, message, info, NULL, ex); - camel_object_unref (message); - - if (camel_exception_is_set (ex)) - break; - - if (move) - camel_folder_set_message_flags (src, camel_message_info_uid (info), - CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_DELETED); - } - - goto done; - } - - dest_namelen = strlen (camel_imap4_folder_utf7_name ((CamelIMAP4Folder *) dest)); - - for (i = 0; i < infos->len; i += n) { - n = camel_imap4_get_uid_set (engine, src->summary, infos, i, 10 + dest_namelen, &set); - - if (move && (engine->capa & CAMEL_IMAP4_CAPABILITY_XGWMOVE)) - ic = camel_imap4_engine_queue (engine, src, "UID XGWMOVE %s %F\r\n", set, dest); - else - ic = camel_imap4_engine_queue (engine, src, "UID COPY %s %F\r\n", set, dest); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - g_free (set); - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - g_free (set); - goto done; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - if (move) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot move messages from folder '%s' to folder '%s': Unknown error"), - src->full_name, dest->full_name); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot copy messages from folder '%s' to folder '%s': Unknown error"), - src->full_name, dest->full_name); - } - - goto done; - case CAMEL_IMAP4_RESULT_BAD: - if (move) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot move messages from folder '%s' to folder '%s': Bad command"), - src->full_name, dest->full_name); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot copy messages from folder '%s' to folder '%s': Bad command"), - src->full_name, dest->full_name); - } - - goto done; - } - - camel_imap4_command_unref (ic); - - if (move && !(engine->capa & CAMEL_IMAP4_CAPABILITY_XGWMOVE)) { - for (j = i; j < n; j++) { - info = infos->pdata[j]; - camel_folder_set_message_flags (src, camel_message_info_uid (info), - CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_DELETED); - } - - camel_folder_summary_touch (src->summary); - } - } - - done: - - for (i = 0; i < infos->len; i++) - camel_message_info_free (infos->pdata[i]); - g_ptr_array_free (infos, TRUE); - - CAMEL_SERVICE_REC_UNLOCK (src->parent_store, connect_lock); -} - -static GPtrArray * -imap4_search_by_expression (CamelFolder *folder, const gchar *expr, CamelException *ex) -{ - CamelIMAP4Folder *imap4_folder = (CamelIMAP4Folder *) folder; - GPtrArray *matches; - - CAMEL_SERVICE_REC_LOCK(folder->parent_store, connect_lock); - - camel_folder_search_set_folder (imap4_folder->search, folder); - matches = camel_folder_search_search (imap4_folder->search, expr, NULL, ex); - - CAMEL_SERVICE_REC_UNLOCK(folder->parent_store, connect_lock); - - return matches; -} - -static GPtrArray * -imap4_search_by_uids (CamelFolder *folder, const gchar *expr, GPtrArray *uids, CamelException *ex) -{ - CamelIMAP4Folder *imap4_folder = (CamelIMAP4Folder *) folder; - GPtrArray *matches; - - if (uids->len == 0) - return g_ptr_array_new (); - - CAMEL_SERVICE_REC_LOCK(folder->parent_store, connect_lock); - - camel_folder_search_set_folder (imap4_folder->search, folder); - matches = camel_folder_search_search (imap4_folder->search, expr, uids, ex); - - CAMEL_SERVICE_REC_UNLOCK(folder->parent_store, connect_lock); - - return matches; -} - -static void -imap4_search_free (CamelFolder *folder, GPtrArray *uids) -{ - CamelIMAP4Folder *imap4_folder = (CamelIMAP4Folder *) folder; - - g_return_if_fail (imap4_folder->search); - - CAMEL_SERVICE_REC_LOCK(folder->parent_store, connect_lock); - - camel_folder_search_free_result (imap4_folder->search, uids); - - CAMEL_SERVICE_REC_UNLOCK(folder->parent_store, connect_lock); -} diff --git a/camel/providers/imap4/camel-imap4-folder.h b/camel/providers/imap4/camel-imap4-folder.h deleted file mode 100644 index 1d4cbae..0000000 --- a/camel/providers/imap4/camel-imap4-folder.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef CAMEL_IMAP4_FOLDER_H -#define CAMEL_IMAP4_FOLDER_H - -#include -#include -#include -#include -#include - -#define CAMEL_TYPE_IMAP4_FOLDER (camel_imap4_folder_get_type ()) -#define CAMEL_IMAP4_FOLDER(obj) (CAMEL_CHECK_CAST ((obj), CAMEL_TYPE_IMAP4_FOLDER, CamelIMAP4Folder)) -#define CAMEL_IMAP4_FOLDER_CLASS(klass) (CAMEL_CHECK_CLASS_CAST ((klass), CAMEL_TYPE_IMAP4_FOLDER, CamelIMAP4FolderClass)) -#define CAMEL_IS_IMAP4_FOLDER(obj) (CAMEL_CHECK_TYPE ((obj), CAMEL_TYPE_IMAP4_FOLDER)) -#define CAMEL_IS_IMAP4_FOLDER_CLASS(klass) (CAMEL_CHECK_CLASS_TYPE ((klass), CAMEL_TYPE_IMAP4_FOLDER)) -#define CAMEL_IMAP4_FOLDER_GET_CLASS(obj) (CAMEL_CHECK_GET_CLASS ((obj), CAMEL_TYPE_IMAP4_FOLDER, CamelIMAP4FolderClass)) - -G_BEGIN_DECLS - -typedef struct _CamelIMAP4Folder CamelIMAP4Folder; -typedef struct _CamelIMAP4FolderClass CamelIMAP4FolderClass; - -struct _CamelIMAP4Journal; - -enum { - CAMEL_IMAP4_FOLDER_ARG_ENABLE_MLIST = CAMEL_OFFLINE_FOLDER_ARG_LAST, - CAMEL_IMAP4_FOLDER_ARG_EXPIRE_ACCESS, - CAMEL_IMAP4_FOLDER_ARG_EXPIRE_AGE, - CAMEL_IMAP4_FOLDER_ARG_LAST = CAMEL_OFFLINE_FOLDER_ARG_LAST + 0x100 -}; - -enum { - CAMEL_IMAP4_FOLDER_ENABLE_MLIST = CAMEL_IMAP4_FOLDER_ARG_ENABLE_MLIST | CAMEL_ARG_BOO, - CAMEL_IMAP4_FOLDER_EXPIRE_ACCESS = CAMEL_IMAP4_FOLDER_ARG_EXPIRE_ACCESS | CAMEL_ARG_INT, - CAMEL_IMAP4_FOLDER_EXPIRE_AGE = CAMEL_IMAP4_FOLDER_ARG_EXPIRE_AGE | CAMEL_ARG_INT, -}; - -struct _CamelIMAP4Folder { - CamelOfflineFolder parent; - - CamelFolderSearch *search; - - CamelOfflineJournal *journal; - CamelDataCache *cache; - - gchar *cachedir; - gchar *utf7_name; - - guint read_only:1; - guint enable_mlist:1; -}; - -struct _CamelIMAP4FolderClass { - CamelOfflineFolderClass parent_class; - -}; - -CamelType camel_imap4_folder_get_type (void); - -CamelFolder *camel_imap4_folder_new (CamelStore *store, const gchar *full_name, CamelException *ex); - -const gchar *camel_imap4_folder_utf7_name (CamelIMAP4Folder *folder); - -G_END_DECLS - -#endif /* CAMEL_IMAP4_FOLDER_H */ diff --git a/camel/providers/imap4/camel-imap4-journal.c b/camel/providers/imap4/camel-imap4-journal.c deleted file mode 100644 index 6985f8f..0000000 --- a/camel/providers/imap4/camel-imap4-journal.c +++ /dev/null @@ -1,354 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include "camel-imap4-folder.h" -#include "camel-imap4-journal.h" - -#define d(x) - -static void camel_imap4_journal_class_init (CamelIMAP4JournalClass *klass); -static void camel_imap4_journal_init (CamelIMAP4Journal *journal, CamelIMAP4JournalClass *klass); -static void camel_imap4_journal_finalize (CamelObject *object); - -static void imap4_entry_free (CamelOfflineJournal *journal, CamelDListNode *entry); -static CamelDListNode *imap4_entry_load (CamelOfflineJournal *journal, FILE *in); -static gint imap4_entry_write (CamelOfflineJournal *journal, CamelDListNode *entry, FILE *out); -static gint imap4_entry_play (CamelOfflineJournal *journal, CamelDListNode *entry, CamelException *ex); - -static CamelOfflineJournalClass *parent_class = NULL; - -CamelType -camel_imap4_journal_get_type (void) -{ - static CamelType type = 0; - - if (!type) { - type = camel_type_register (camel_offline_journal_get_type (), - "CamelIMAP4Journal", - sizeof (CamelIMAP4Journal), - sizeof (CamelIMAP4JournalClass), - (CamelObjectClassInitFunc) camel_imap4_journal_class_init, - NULL, - (CamelObjectInitFunc) camel_imap4_journal_init, - (CamelObjectFinalizeFunc) camel_imap4_journal_finalize); - } - - return type; -} - -static void -camel_imap4_journal_class_init (CamelIMAP4JournalClass *klass) -{ - CamelOfflineJournalClass *journal_class = (CamelOfflineJournalClass *) klass; - - parent_class = (CamelOfflineJournalClass *) camel_type_get_global_classfuncs (CAMEL_TYPE_OFFLINE_JOURNAL); - - journal_class->entry_free = imap4_entry_free; - journal_class->entry_load = imap4_entry_load; - journal_class->entry_write = imap4_entry_write; - journal_class->entry_play = imap4_entry_play; -} - -static void -camel_imap4_journal_init (CamelIMAP4Journal *journal, CamelIMAP4JournalClass *klass) -{ - journal->failed = g_ptr_array_new (); -} - -static void -camel_imap4_journal_finalize (CamelObject *object) -{ - CamelIMAP4Journal *journal = (CamelIMAP4Journal *) object; - gint i; - - if (journal->failed) { - for (i = 0; i < journal->failed->len; i++) - camel_message_info_free (journal->failed->pdata[i]); - g_ptr_array_free (journal->failed, TRUE); - } -} - -static void -imap4_entry_free (CamelOfflineJournal *journal, CamelDListNode *entry) -{ - CamelIMAP4JournalEntry *imap4_entry = (CamelIMAP4JournalEntry *) entry; - - g_free (imap4_entry->v.append_uid); - g_free (imap4_entry); -} - -static CamelDListNode * -imap4_entry_load (CamelOfflineJournal *journal, FILE *in) -{ - CamelIMAP4JournalEntry *entry; - - entry = g_malloc0 (sizeof (CamelIMAP4JournalEntry)); - - if (camel_file_util_decode_uint32 (in, &entry->type) == -1) - goto exception; - - switch (entry->type) { - case CAMEL_IMAP4_JOURNAL_ENTRY_APPEND: - if (camel_file_util_decode_string (in, &entry->v.append_uid) == -1) - goto exception; - - break; - default: - goto exception; - } - - return (CamelDListNode *) entry; - - exception: - - switch (entry->type) { - case CAMEL_IMAP4_JOURNAL_ENTRY_APPEND: - g_free (entry->v.append_uid); - break; - default: - g_assert_not_reached (); - } - - g_free (entry); - - return NULL; -} - -static gint -imap4_entry_write (CamelOfflineJournal *journal, CamelDListNode *entry, FILE *out) -{ - CamelIMAP4JournalEntry *imap4_entry = (CamelIMAP4JournalEntry *) entry; - - if (camel_file_util_encode_uint32 (out, imap4_entry->type) == -1) - return -1; - - switch (imap4_entry->type) { - case CAMEL_IMAP4_JOURNAL_ENTRY_APPEND: - if (camel_file_util_encode_string (out, imap4_entry->v.append_uid)) - return -1; - - break; - default: - g_assert_not_reached (); - } - - return 0; -} - -static void -imap4_message_info_dup_to (CamelMessageInfoBase *dest, CamelMessageInfoBase *src) -{ - camel_flag_list_copy (&dest->user_flags, &src->user_flags); - camel_tag_list_copy (&dest->user_tags, &src->user_tags); - dest->date_received = src->date_received; - dest->date_sent = src->date_sent; - dest->flags = src->flags; - dest->size = src->size; -} - -static gint -imap4_entry_play_append (CamelOfflineJournal *journal, CamelIMAP4JournalEntry *entry, CamelException *ex) -{ - CamelIMAP4Folder *imap4_folder = (CamelIMAP4Folder *) journal->folder; - CamelFolder *folder = journal->folder; - CamelMessageInfo *info, *real; - CamelMimeMessage *message; - CamelStream *stream; - CamelException lex; - gchar *uid = NULL; - - /* if the message isn't in the cache, the user went behind our backs so "not our problem" */ - if (!imap4_folder->cache || !(stream = camel_data_cache_get (imap4_folder->cache, "cache", entry->v.append_uid, ex))) - goto done; - - message = camel_mime_message_new (); - if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) message, stream) == -1) { - camel_object_unref (message); - camel_object_unref (stream); - goto done; - } - - camel_object_unref (stream); - - if (!(info = camel_folder_summary_uid (folder->summary, entry->v.append_uid))) { - /* info not in the summary, either because the summary - * got corrupted or because the previous time this - * journal was replay'd, it failed [1] */ - info = camel_message_info_new (NULL); - } - - camel_exception_init (&lex); - camel_folder_append_message (folder, message, info, &uid, &lex); - camel_object_unref (message); - - if (camel_exception_is_set (&lex)) { - /* Remove the message-info from the summary even if we fail or the next - * summary downsync will break because info indexes will be wrong */ - if (info->summary == folder->summary) { - camel_folder_summary_remove (folder->summary, info); - g_ptr_array_add (((CamelIMAP4Journal *) journal)->failed, info); - } else { - /* info wasn't in the summary to begin with */ - camel_folder_summary_remove_uid (folder->summary, entry->v.append_uid); - camel_message_info_free (info); - } - - camel_exception_xfer (ex, &lex); - - return -1; - } - - if (uid != NULL && (real = camel_folder_summary_uid (folder->summary, uid))) { - /* Copy the system flags and user flags/tags over to the real - message-info now stored in the summary to prevent the user - from losing any of this meta-data */ - imap4_message_info_dup_to ((CamelMessageInfoBase *) real, (CamelMessageInfoBase *) info); - } - - camel_message_info_free (info); - g_free (uid); - - done: - - camel_folder_summary_remove_uid (folder->summary, entry->v.append_uid); - camel_data_cache_remove (imap4_folder->cache, "cache", entry->v.append_uid, NULL); - - return 0; -} - -static gint -imap4_entry_play (CamelOfflineJournal *journal, CamelDListNode *entry, CamelException *ex) -{ - CamelIMAP4JournalEntry *imap4_entry = (CamelIMAP4JournalEntry *) entry; - - switch (imap4_entry->type) { - case CAMEL_IMAP4_JOURNAL_ENTRY_APPEND: - return imap4_entry_play_append (journal, imap4_entry, ex); - default: - g_assert_not_reached (); - return -1; - } -} - -CamelOfflineJournal * -camel_imap4_journal_new (CamelIMAP4Folder *folder, const gchar *filename) -{ - CamelOfflineJournal *journal; - - g_return_val_if_fail (CAMEL_IS_IMAP4_FOLDER (folder), NULL); - - journal = (CamelOfflineJournal *) camel_object_new (camel_imap4_journal_get_type ()); - camel_offline_journal_construct (journal, (CamelFolder *) folder, filename); - - return journal; -} - -void -camel_imap4_journal_readd_failed (CamelIMAP4Journal *journal) -{ - CamelFolderSummary *summary = ((CamelOfflineJournal *) journal)->folder->summary; - gint i; - - for (i = 0; i < journal->failed->len; i++) - camel_folder_summary_add (summary, journal->failed->pdata[i]); - - g_ptr_array_set_size (journal->failed, 0); -} - -void -camel_imap4_journal_append (CamelIMAP4Journal *imap4_journal, CamelMimeMessage *message, - const CamelMessageInfo *mi, gchar **appended_uid, CamelException *ex) -{ - CamelOfflineJournal *journal = (CamelOfflineJournal *) imap4_journal; - CamelIMAP4Folder *imap4_folder = (CamelIMAP4Folder *) journal->folder; - CamelFolder *folder = (CamelFolder *) journal->folder; - CamelIMAP4JournalEntry *entry; - CamelMessageInfo *info; - CamelStream *cache; - guint32 nextuid; - gchar *uid; - - if (imap4_folder->cache == NULL) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message in offline mode: cache unavailable")); - return; - } - - nextuid = camel_folder_summary_next_uid (folder->summary); - uid = g_strdup_printf ("-%u", nextuid); - - if (!(cache = camel_data_cache_add (imap4_folder->cache, "cache", uid, ex))) { - folder->summary->nextuid--; - g_free (uid); - return; - } - - if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *) message, cache) == -1 - || camel_stream_flush (cache) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message in offline mode: %s"), - g_strerror (errno)); - camel_data_cache_remove (imap4_folder->cache, "cache", uid, NULL); - folder->summary->nextuid--; - camel_object_unref (cache); - g_free (uid); - return; - } - - camel_object_unref (cache); - - entry = g_new (CamelIMAP4JournalEntry, 1); - entry->type = CAMEL_IMAP4_JOURNAL_ENTRY_APPEND; - entry->v.append_uid = uid; - - camel_dlist_addtail (&journal->queue, (CamelDListNode *) entry); - - info = camel_folder_summary_info_new_from_message (folder->summary, message); - g_free(info->uid); - info->uid = g_strdup (uid); - - imap4_message_info_dup_to ((CamelMessageInfoBase *) info, (CamelMessageInfoBase *) mi); - - camel_folder_summary_add (folder->summary, info); - - if (appended_uid) - *appended_uid = g_strdup (uid); -} diff --git a/camel/providers/imap4/camel-imap4-journal.h b/camel/providers/imap4/camel-imap4-journal.h deleted file mode 100644 index a1f885d..0000000 --- a/camel/providers/imap4/camel-imap4-journal.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef CAMEL_IMAP4_JOURNAL_H -#define CAMEL_IMAP4_JOURNAL_H - -#include - -#include - -#include -#include - -#define CAMEL_TYPE_IMAP4_JOURNAL (camel_imap4_journal_get_type ()) -#define CAMEL_IMAP4_JOURNAL(obj) (CAMEL_CHECK_CAST ((obj), CAMEL_TYPE_IMAP4_JOURNAL, CamelIMAP4Journal)) -#define CAMEL_IMAP4_JOURNAL_CLASS(klass) (CAMEL_CHECK_CLASS_CAST ((klass), CAMEL_TYPE_IMAP4_JOURNAL, CamelIMAP4JournalClass)) -#define CAMEL_IS_IMAP4_JOURNAL(obj) (CAMEL_CHECK_TYPE ((obj), CAMEL_TYPE_IMAP4_JOURNAL)) -#define CAMEL_IS_IMAP4_JOURNAL_CLASS(klass) (CAMEL_CHECK_CLASS_TYPE ((klass), CAMEL_TYPE_IMAP4_JOURNAL)) -#define CAMEL_IMAP4_JOURNAL_GET_CLASS(obj) (CAMEL_CHECK_GET_CLASS ((obj), CAMEL_TYPE_IMAP4_JOURNAL, CamelIMAP4JournalClass)) - -G_BEGIN_DECLS - -typedef struct _CamelIMAP4Journal CamelIMAP4Journal; -typedef struct _CamelIMAP4JournalClass CamelIMAP4JournalClass; -typedef struct _CamelIMAP4JournalEntry CamelIMAP4JournalEntry; - -struct _CamelIMAP4Folder; - -enum { - CAMEL_IMAP4_JOURNAL_ENTRY_APPEND, -}; - -struct _CamelIMAP4JournalEntry { - CamelDListNode node; - - gint type; - - union { - gchar *append_uid; - } v; -}; - -struct _CamelIMAP4Journal { - CamelOfflineJournal parent; - - GPtrArray *failed; -}; - -struct _CamelIMAP4JournalClass { - CamelOfflineJournalClass parent_class; - -}; - -CamelType camel_imap4_journal_get_type (void); - -CamelOfflineJournal *camel_imap4_journal_new (struct _CamelIMAP4Folder *folder, const gchar *filename); - -void camel_imap4_journal_readd_failed (CamelIMAP4Journal *journal); - -/* interfaces for adding a journal entry */ -void camel_imap4_journal_append (CamelIMAP4Journal *journal, CamelMimeMessage *message, const CamelMessageInfo *mi, - gchar **appended_uid, CamelException *ex); - -G_END_DECLS - -#endif /* CAMEL_IMAP4_JOURNAL_H */ diff --git a/camel/providers/imap4/camel-imap4-provider.c b/camel/providers/imap4/camel-imap4-provider.c deleted file mode 100644 index 7c5f90c..0000000 --- a/camel/providers/imap4/camel-imap4-provider.c +++ /dev/null @@ -1,150 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include - -#include -#include - -#include "camel-imap4-store.h" - -/* FIXME: Add options for cache expiration */ -static CamelProviderConfEntry imap4_conf_entries[] = { - { CAMEL_PROVIDER_CONF_SECTION_START, "mailcheck", NULL, - N_("Checking for new mail") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "check_all", NULL, - N_("C_heck for new messages in all folders"), "1" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_SECTION_START, "folders", NULL, - N_("Folders") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "use_lsub", NULL, - N_("_Show only subscribed folders"), "1" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "override_namespace", NULL, - N_("O_verride server-supplied folder namespace"), "0" }, - { CAMEL_PROVIDER_CONF_ENTRY, "namespace", "override_namespace", - N_("Namespace:") }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_SECTION_START, "general", NULL, N_("Options") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter", NULL, - N_("_Apply filters to new messages in INBOX on this server"), "0" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter_junk", NULL, - N_("Check new messages for _Junk contents"), "0" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter_junk_inbox", "filter_junk", - N_("Only check for Junk messa_ges in the INBOX folder"), "0" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "sync_offline", NULL, - N_("Automatically synchroni_ze remote mail locally"), "0" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider imap4_provider = { - "imap4", - N_("IMAP4rev1"), - - N_("For reading and storing mail on IMAPv4rev1 servers."), - - "mail", - - CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE | - CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_SUPPORTS_SSL, - - CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH | CAMEL_URL_FRAGMENT_IS_PATH, - - imap4_conf_entries, - - /* ... */ -}; - -CamelServiceAuthType camel_imap4_password_authtype = { - N_("Password"), - - N_("This option will connect to the IMAPv4rev1 server using a " - "plaintext password."), - - "", - TRUE -}; - -static void -add_hash (guint *hash, gchar *s) -{ - if (s) - *hash ^= g_str_hash(s); -} - -static guint -imap4_url_hash (gconstpointer key) -{ - const CamelURL *u = (CamelURL *)key; - guint hash = 0; - - add_hash (&hash, u->user); - add_hash (&hash, u->host); - hash ^= u->port; - - return hash; -} - -static gint -check_equal (gchar *s1, gchar *s2) -{ - if (s1 == NULL) { - if (s2 == NULL) - return TRUE; - else - return FALSE; - } - - if (s2 == NULL) - return FALSE; - - return strcmp (s1, s2) == 0; -} - -static gint -imap4_url_equal (gconstpointer a, gconstpointer b) -{ - const CamelURL *u1 = a, *u2 = b; - - return check_equal (u1->protocol, u2->protocol) - && check_equal (u1->user, u2->user) - && check_equal (u1->host, u2->host) - && u1->port == u2->port; -} - -void -camel_provider_module_init (void) -{ - imap4_provider.object_types[CAMEL_PROVIDER_STORE] = camel_imap4_store_get_type (); - imap4_provider.url_hash = imap4_url_hash; - imap4_provider.url_equal = imap4_url_equal; - imap4_provider.authtypes = camel_sasl_authtype_list (FALSE); - imap4_provider.authtypes = g_list_prepend (imap4_provider.authtypes, &camel_imap4_password_authtype); - imap4_provider.translation_domain = GETTEXT_PACKAGE; - - camel_provider_register (&imap4_provider); -} diff --git a/camel/providers/imap4/camel-imap4-search.c b/camel/providers/imap4/camel-imap4-search.c deleted file mode 100644 index 2590cd5..0000000 --- a/camel/providers/imap4/camel-imap4-search.c +++ /dev/null @@ -1,310 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * Michael Zucchi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include - -#include "camel-imap4-command.h" -#include "camel-imap4-engine.h" -#include "camel-imap4-search.h" -#include "camel-imap4-stream.h" -#include "camel-imap4-utils.h" - -static void camel_imap4_search_class_init (CamelIMAP4SearchClass *klass); -static void camel_imap4_search_init (CamelIMAP4Search *search, CamelIMAP4SearchClass *klass); -static void camel_imap4_search_finalize (CamelObject *object); - -static ESExpResult *imap4_body_contains (struct _ESExp *f, gint argc, struct _ESExpResult **argv, CamelFolderSearch *search); - -static CamelFolderSearchClass *parent_class = NULL; - -CamelType -camel_imap4_search_get_type (void) -{ - static CamelType type = 0; - - if (!type) { - type = camel_type_register (camel_folder_search_get_type (), - "CamelIMAP4Search", - sizeof (CamelIMAP4Search), - sizeof (CamelIMAP4SearchClass), - (CamelObjectClassInitFunc) camel_imap4_search_class_init, - NULL, - (CamelObjectInitFunc) camel_imap4_search_init, - (CamelObjectFinalizeFunc) camel_imap4_search_finalize); - } - - return type; -} - -static void -camel_imap4_search_class_init (CamelIMAP4SearchClass *klass) -{ - CamelFolderSearchClass *search_class = (CamelFolderSearchClass *) klass; - - parent_class = (CamelFolderSearchClass *) camel_type_get_global_classfuncs (CAMEL_FOLDER_SEARCH_TYPE); - - search_class->body_contains = imap4_body_contains; -} - -static void -camel_imap4_search_init (CamelIMAP4Search *search, CamelIMAP4SearchClass *klass) -{ - search->engine = NULL; -} - -static void -camel_imap4_search_finalize (CamelObject *object) -{ - ; -} - -CamelFolderSearch * -camel_imap4_search_new (CamelIMAP4Engine *engine, const gchar *cachedir) -{ - CamelIMAP4Search *search; - - search = (CamelIMAP4Search *) camel_object_new (camel_imap4_search_get_type ()); - camel_folder_search_construct ((CamelFolderSearch *) search); - search->engine = engine; - - return (CamelFolderSearch *) search; -} - -static gint -untagged_search (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, guint32 index, camel_imap4_token_t *token, CamelException *ex) -{ - CamelFolderSummary *summary = ((CamelFolder *) engine->folder)->summary; - GPtrArray *matches = ic->user_data; - CamelMessageInfo *info; - gchar uid[12]; - - while (1) { - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token == '\n') - break; - - if (token->token != CAMEL_IMAP4_TOKEN_NUMBER || token->v.number == 0) - goto unexpected; - - sprintf (uid, "%u", token->v.number); - if ((info = camel_folder_summary_uid (summary, uid))) { - g_ptr_array_add (matches, (gchar *) camel_message_info_uid (info)); - camel_message_info_free (info); - } - } - - return 0; - - unexpected: - - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - - return -1; -} - -static ESExpResult * -imap4_body_contains (struct _ESExp *f, gint argc, struct _ESExpResult **argv, CamelFolderSearch *search) -{ - CamelIMAP4Search *imap4_search = (CamelIMAP4Search *) search; - CamelIMAP4Engine *engine = imap4_search->engine; - GPtrArray *strings, *matches, *infos; - register const guchar *inptr; - gboolean utf8_search = FALSE; - GPtrArray *summary_set; - CamelMessageInfo *info; - CamelIMAP4Command *ic; - const gchar *expr; - ESExpResult *r; - gint id, i, n; - gsize used; - gchar *set; - - if (((CamelOfflineStore *) engine->service)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) - return parent_class->body_contains (f, argc, argv, search); - - summary_set = search->summary_set ? search->summary_set : search->summary; - - /* check the simple cases */ - if (argc == 0 || summary_set->len == 0) { - /* match nothing */ - if (search->current) { - r = e_sexp_result_new (f, ESEXP_RES_BOOL); - r->value.bool = FALSE; - } else { - r = e_sexp_result_new (f, ESEXP_RES_ARRAY_PTR); - r->value.ptrarray = g_ptr_array_new (); - } - - return r; - } else if (argc == 1 && argv[0]->type == ESEXP_RES_STRING && argv[0]->value.string[0] == '\0') { - /* match everything */ - if (search->current) { - r = e_sexp_result_new (f, ESEXP_RES_BOOL); - r->value.bool = TRUE; - } else { - r = e_sexp_result_new (f, ESEXP_RES_ARRAY_PTR); - r->value.ptrarray = g_ptr_array_new (); - g_ptr_array_set_size (r->value.ptrarray, summary_set->len); - r->value.ptrarray->len = summary_set->len; - for (i = 0; i < summary_set->len; i++) { - info = g_ptr_array_index (summary_set, i); - r->value.ptrarray->pdata[i] = (gchar *) camel_message_info_uid (info); - } - } - - return r; - } - - strings = g_ptr_array_new (); - for (i = 0; i < argc; i++) { - if (argv[i]->type == ESEXP_RES_STRING && argv[i]->value.string[0] != '\0') { - g_ptr_array_add (strings, argv[i]->value.string); - if (!utf8_search) { - inptr = (guchar *) argv[i]->value.string; - while (*inptr != '\0') { - if (!isascii ((gint) *inptr)) { - utf8_search = TRUE; - break; - } - - inptr++; - } - } - } - } - - if (strings->len == 0) { - /* match everything */ - g_ptr_array_free (strings, TRUE); - - if (search->current) { - r = e_sexp_result_new (f, ESEXP_RES_BOOL); - r->value.bool = TRUE; - } else { - r = e_sexp_result_new (f, ESEXP_RES_ARRAY_PTR); - r->value.ptrarray = g_ptr_array_new (); - g_ptr_array_set_size (r->value.ptrarray, summary_set->len); - r->value.ptrarray->len = summary_set->len; - for (i = 0; i < summary_set->len; i++) { - info = g_ptr_array_index (summary_set, i); - r->value.ptrarray->pdata[i] = (gchar *) camel_message_info_uid (info); - } - } - - return r; - } - - g_ptr_array_add (strings, NULL); - matches = g_ptr_array_new (); - infos = g_ptr_array_new (); - - if (search->current) { - g_ptr_array_add (infos, search->current); - } else { - g_ptr_array_set_size (infos, summary_set->len); - infos->len = summary_set->len; - for (i = 0; i < summary_set->len; i++) - infos->pdata[i] = summary_set->pdata[i]; - } - - retry: - if (utf8_search && (engine->capa & CAMEL_IMAP4_CAPABILITY_utf8_search)) - expr = "UID SEARCH CHARSET UTF-8 UID %s BODY %V\r\n"; - else - expr = "UID SEARCH UID %s BODY %V\r\n"; - - used = strlen (expr) + (5 * (strings->len - 2)); - - for (i = 0; i < infos->len; i += n) { - n = camel_imap4_get_uid_set (engine, search->folder->summary, infos, i, used, &set); - - ic = camel_imap4_engine_queue (engine, search->folder, expr, set, strings->pdata); - camel_imap4_command_register_untagged (ic, "SEARCH", untagged_search); - ic->user_data = matches; - g_free (set); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_imap4_command_unref (ic); - goto done; - } - - if (ic->result == CAMEL_IMAP4_RESULT_NO && utf8_search && (engine->capa & CAMEL_IMAP4_CAPABILITY_utf8_search)) { - gint j; - - /* might be because the server is lame and doesn't support UTF-8 */ - for (j = 0; j < ic->resp_codes->len; j++) { - CamelIMAP4RespCode *resp = ic->resp_codes->pdata[j]; - - if (resp->code == CAMEL_IMAP4_RESP_CODE_BADCHARSET) { - engine->capa &= ~CAMEL_IMAP4_CAPABILITY_utf8_search; - camel_imap4_command_unref (ic); - goto retry; - } - } - } - - if (ic->result != CAMEL_IMAP4_RESULT_OK) { - camel_imap4_command_unref (ic); - break; - } - - camel_imap4_command_unref (ic); - } - - done: - - g_ptr_array_free (strings, TRUE); - g_ptr_array_free (infos, TRUE); - - if (search->current) { - const gchar *uid; - - uid = camel_message_info_uid (search->current); - r = e_sexp_result_new (f, ESEXP_RES_BOOL); - r->value.bool = FALSE; - for (i = 0; i < matches->len; i++) { - if (!strcmp (matches->pdata[i], uid)) { - r->value.bool = TRUE; - break; - } - } - - g_ptr_array_free (matches, TRUE); - } else { - r = e_sexp_result_new (f, ESEXP_RES_ARRAY_PTR); - r->value.ptrarray = matches; - } - - return r; -} diff --git a/camel/providers/imap4/camel-imap4-search.h b/camel/providers/imap4/camel-imap4-search.h deleted file mode 100644 index d9706cf..0000000 --- a/camel/providers/imap4/camel-imap4-search.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * Michael Zucchi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef CAMEL_IMAP4_SEARCH_H -#define CAMEL_IMAP4_SEARCH_H - -#include -#include -#include - -#define CAMEL_IMAP4_SEARCH_TYPE (camel_imap4_search_get_type ()) -#define CAMEL_IMAP4_SEARCH(obj) CAMEL_CHECK_CAST (obj, camel_imap4_search_get_type (), CamelIMAP4Search) -#define CAMEL_IMAP4_SEARCH_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imap4_search_get_type (), CamelIMAP4SearchClass) -#define CAMEL_IS_IMAP4_SEARCH(obj) CAMEL_CHECK_TYPE (obj, camel_imap4_search_get_type ()) - -G_BEGIN_DECLS - -typedef struct _CamelIMAP4Search CamelIMAP4Search; -typedef struct _CamelIMAP4SearchClass CamelIMAP4SearchClass; - -struct _CamelIMAP4Engine; - -struct _CamelIMAP4Search { - CamelFolderSearch parent; - - struct _CamelIMAP4Engine *engine; - - guint32 lastuid; /* current 'last uid' for the folder */ - guint32 validity; /* validity of the current folder */ - - CamelDataCache *cache; /* disk-cache for searches */ - - /* cache of body search matches */ - CamelDList matches; - GHashTable *matches_hash; - guint matches_count; -}; - -struct _CamelIMAP4SearchClass { - CamelFolderSearchClass parent_class; - -}; - -CamelType camel_imap4_search_get_type (void); - -CamelFolderSearch *camel_imap4_search_new (struct _CamelIMAP4Engine *engine, const gchar *cachedir); - -G_END_DECLS - -#endif /* CAMEL_IMAP4_SEARCH_H */ diff --git a/camel/providers/imap4/camel-imap4-specials.c b/camel/providers/imap4/camel-imap4-specials.c deleted file mode 100644 index 45c800d..0000000 --- a/camel/providers/imap4/camel-imap4-specials.c +++ /dev/null @@ -1,99 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "camel-imap4-specials.h" - -#define CHARS_ATOM_SPECIALS "(){]" -#define CHARS_LWSP " \t\r\n" -#define CHARS_QUOTED_SPECIALS "\\\"" -#define CHARS_LIST_WILDCARDS "*%" - -guchar camel_imap4_specials[256] = { - 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 2, 2, 6, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 20, 0, 8, 0, 0, 32, 0, 0, 1, 1, 32, 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, 8, 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, 1, 0, 0, 0, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -}; - -static void -imap4_init_bits (unsigned short bit, unsigned short bitcopy, gint remove, guchar *vals) -{ - gint i, len = strlen (vals); - - if (!remove) { - for (i = 0; i < len; i++) - camel_imap4_specials[vals[i]] |= bit; - if (bitcopy) { - for (i = 0; i < 256; i++) { - if (camel_imap4_specials[i] & bitcopy) - camel_imap4_specials[i] |= bit; - } - } - } else { - for (i = 0; i < 256; i++) - camel_imap4_specials[i] |= bit; - for (i = 0; i < len; i++) - camel_imap4_specials[vals[i]] &= ~bit; - if (bitcopy) { - for (i = 0; i < 256; i++) { - if (camel_imap4_specials[i] & bitcopy) - camel_imap4_specials[i] &= ~bit; - } - } - } -} - -void -camel_imap4_specials_init (void) -{ - gint i; - - for (i = 0; i < 256; i++) { - camel_imap4_specials[i] = 0; - if (i <= 0x1f || i >= 0x7f) - camel_imap4_specials[i] |= IS_CTRL; - } - - camel_imap4_specials[' '] |= IS_SPACE; - - imap4_init_bits (IS_LWSP, 0, 0, CHARS_LWSP); - imap4_init_bits (IS_ASPECIAL, 0, 0, CHARS_ATOM_SPECIALS); - imap4_init_bits (IS_QSPECIAL, 0, 0, CHARS_QUOTED_SPECIALS); - imap4_init_bits (IS_WILDCARD, 0, 0, CHARS_LIST_WILDCARDS); -} diff --git a/camel/providers/imap4/camel-imap4-specials.h b/camel/providers/imap4/camel-imap4-specials.h deleted file mode 100644 index 3672ca1..0000000 --- a/camel/providers/imap4/camel-imap4-specials.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef CAMEL_IMAP4_SPECIALS_H -#define CAMEL_IMAP4_SPECIALS_H - -#include - -G_BEGIN_DECLS - -enum { - IS_ASPECIAL = (1 << 0), - IS_CTRL = (1 << 1), - IS_LWSP = (1 << 2), - IS_QSPECIAL = (1 << 3), - IS_SPACE = (1 << 4), - IS_WILDCARD = (1 << 5), -}; - -extern guchar camel_imap4_specials[256]; - -#define is_atom(x) ((camel_imap4_specials[(guchar)(x)] & (IS_ASPECIAL|IS_SPACE|IS_CTRL|IS_WILDCARD|IS_QSPECIAL)) == 0) -#define is_ctrl(x) ((camel_imap4_specials[(guchar)(x)] & IS_CTRL) != 0) -#define is_lwsp(x) ((camel_imap4_specials[(guchar)(x)] & IS_LWSP) != 0) -#define is_type(x, t) ((camel_imap4_specials[(guchar)(x)] & (t)) != 0) -#define is_qsafe(x) ((camel_imap4_specials[(guchar)(x)] & (IS_QSPECIAL|IS_CTRL)) == 0) -#define is_wild(x) ((camel_imap4_specials[(guchar)(x)] & IS_WILDCARD) != 0) - -void camel_imap4_specials_init (void); - -G_END_DECLS - -#endif /* CAMEL_IMAP4_SPECIALS_H */ diff --git a/camel/providers/imap4/camel-imap4-store-summary.c b/camel/providers/imap4/camel-imap4-store-summary.c deleted file mode 100644 index 00b12f0..0000000 --- a/camel/providers/imap4/camel-imap4-store-summary.c +++ /dev/null @@ -1,400 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include "camel-imap4-store-summary.h" -#include "camel-imap4-utils.h" - -#define CAMEL_IMAP4_STORE_SUMMARY_VERSION_0 (0) -#define CAMEL_IMAP4_STORE_SUMMARY_VERSION (0) - -static void camel_imap4_store_summary_class_init (CamelIMAP4StoreSummaryClass *klass); -static void camel_imap4_store_summary_init (CamelIMAP4StoreSummary *obj); -static void camel_imap4_store_summary_finalize (CamelObject *obj); - -static gint summary_header_load (CamelStoreSummary *s, FILE *in); -static gint summary_header_save (CamelStoreSummary *s, FILE *out); - -static CamelStoreInfo *store_info_load (CamelStoreSummary *s, FILE *in); -static gint store_info_save (CamelStoreSummary *s, FILE *out, CamelStoreInfo *info); -static void store_info_free (CamelStoreSummary *s, CamelStoreInfo *info); - -static CamelStoreSummaryClass *parent_class = NULL; - -CamelType -camel_imap4_store_summary_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_store_summary_get_type (), - "CamelIMAP4StoreSummary", - sizeof (CamelIMAP4StoreSummary), - sizeof (CamelIMAP4StoreSummaryClass), - (CamelObjectClassInitFunc) camel_imap4_store_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_imap4_store_summary_init, - (CamelObjectFinalizeFunc) camel_imap4_store_summary_finalize); - } - - return type; -} - -static void -camel_imap4_store_summary_class_init (CamelIMAP4StoreSummaryClass *klass) -{ - CamelStoreSummaryClass *ssklass = (CamelStoreSummaryClass *) klass; - - parent_class = (CamelStoreSummaryClass *) camel_store_summary_get_type (); - - ssklass->summary_header_load = summary_header_load; - ssklass->summary_header_save = summary_header_save; - - ssklass->store_info_load = store_info_load; - ssklass->store_info_save = store_info_save; - ssklass->store_info_free = store_info_free; -} - -static void -camel_imap4_store_summary_init (CamelIMAP4StoreSummary *s) -{ - ((CamelStoreSummary *) s)->store_info_size = sizeof (CamelIMAP4StoreInfo); - s->version = CAMEL_IMAP4_STORE_SUMMARY_VERSION; - s->namespaces = NULL; -} - -static void -camel_imap4_store_summary_finalize (CamelObject *obj) -{ - CamelIMAP4StoreSummary *s = (CamelIMAP4StoreSummary *) obj; - - if (s->namespaces) - camel_imap4_namespace_list_free (s->namespaces); -} - -static CamelIMAP4NamespaceList * -load_namespaces (FILE *in) -{ - CamelIMAP4Namespace *ns, *tail = NULL; - CamelIMAP4NamespaceList *nsl; - guint32 i, j, n; - - nsl = g_malloc (sizeof (CamelIMAP4NamespaceList)); - nsl->personal = NULL; - nsl->shared = NULL; - nsl->other = NULL; - - for (j = 0; j < 3; j++) { - switch (j) { - case 0: - tail = (CamelIMAP4Namespace *) &nsl->personal; - break; - case 1: - tail = (CamelIMAP4Namespace *) &nsl->shared; - break; - case 2: - tail = (CamelIMAP4Namespace *) &nsl->other; - break; - } - - if (camel_file_util_decode_fixed_int32 (in, &n) == -1) - goto exception; - - for (i = 0; i < n; i++) { - guint32 sep; - gchar *path; - - if (camel_file_util_decode_string (in, &path) == -1) - goto exception; - - if (camel_file_util_decode_uint32 (in, &sep) == -1) { - g_free (path); - goto exception; - } - - tail->next = ns = g_malloc (sizeof (CamelIMAP4Namespace)); - ns->sep = sep & 0xff; - ns->path = path; - ns->next = NULL; - tail = ns; - } - } - - return nsl; - - exception: - - camel_imap4_namespace_list_free (nsl); - - return NULL; -} - -static gint -summary_header_load (CamelStoreSummary *s, FILE *in) -{ - CamelIMAP4StoreSummary *is = (CamelIMAP4StoreSummary *) s; - guint32 version, capa; - - if (parent_class->summary_header_load (s, in) == -1) - return -1; - - if (camel_file_util_decode_fixed_int32 (in, &version) == -1) - return -1; - - is->version = version; - if (version < CAMEL_IMAP4_STORE_SUMMARY_VERSION_0) { - g_warning ("IMAP4 store summary header version too low"); - errno = EINVAL; - return -1; - } - - if (camel_file_util_decode_fixed_int32 (in, &capa) == -1) - return -1; - - is->capa = capa; - - if (!(is->namespaces = load_namespaces (in))) - return -1; - - return 0; -} - -static gint -save_namespaces (FILE *out, CamelIMAP4NamespaceList *nsl) -{ - CamelIMAP4Namespace *ns, *cur = NULL; - guint32 i, n; - - for (i = 0; i < 3; i++) { - switch (i) { - case 0: - cur = nsl->personal; - break; - case 1: - cur = nsl->shared; - break; - case 2: - cur = nsl->other; - break; - } - - for (ns = cur, n = 0; ns; n++) - ns = ns->next; - - if (camel_file_util_encode_fixed_int32 (out, n) == -1) - return -1; - - ns = cur; - while (ns != NULL) { - if (camel_file_util_encode_string (out, ns->path) == -1) - return -1; - - if (camel_file_util_encode_uint32 (out, ns->sep) == -1) - return -1; - - ns = ns->next; - } - } - - return 0; -} - -static gint -summary_header_save (CamelStoreSummary *s, FILE *out) -{ - CamelIMAP4StoreSummary *is = (CamelIMAP4StoreSummary *) s; - - if (parent_class->summary_header_save (s, out) == -1) - return -1; - - if (camel_file_util_encode_fixed_int32 (out, is->version) == -1) - return -1; - - if (camel_file_util_encode_fixed_int32 (out, is->capa) == -1) - return -1; - - if (save_namespaces (out, is->namespaces) == -1) - return -1; - - return 0; -} - -static CamelStoreInfo * -store_info_load (CamelStoreSummary *s, FILE *in) -{ - return parent_class->store_info_load (s, in); -} - -static gint -store_info_save (CamelStoreSummary *s, FILE *out, CamelStoreInfo *info) -{ - return parent_class->store_info_save (s, out, info); -} - -static void -store_info_free (CamelStoreSummary *s, CamelStoreInfo *info) -{ - parent_class->store_info_free (s, info); -} - -/** - * camel_imap4_store_summary_new: - * - * Create a new CamelIMAP4StoreSummary object. - * - * Returns: a new CamelIMAP4StoreSummary object. - **/ -CamelIMAP4StoreSummary * -camel_imap4_store_summary_new (void) -{ - return (CamelIMAP4StoreSummary *) camel_object_new (camel_imap4_store_summary_get_type ()); -} - -void -camel_imap4_store_summary_set_capabilities (CamelIMAP4StoreSummary *s, guint32 capa) -{ - s->capa = capa; -} - -void -camel_imap4_store_summary_set_namespaces (CamelIMAP4StoreSummary *s, const CamelIMAP4NamespaceList *ns) -{ - if (s->namespaces) - camel_imap4_namespace_list_free (s->namespaces); - s->namespaces = camel_imap4_namespace_list_copy (ns); -} - -void -camel_imap4_store_summary_note_info (CamelIMAP4StoreSummary *s, CamelFolderInfo *fi) -{ - CamelStoreSummary *ss = (CamelStoreSummary *) s; - CamelStoreInfo *si; - - if ((si = camel_store_summary_path (ss, fi->full_name))) { - if (fi->unread != -1) { - si->unread = fi->unread; - ss->flags |= CAMEL_STORE_SUMMARY_DIRTY; - } - - if (fi->total != -1) { - si->total = fi->total; - ss->flags |= CAMEL_STORE_SUMMARY_DIRTY; - } - - camel_store_summary_info_free (ss, si); - return; - } - - si = camel_store_summary_info_new (ss); - si->path = g_strdup (fi->full_name); - si->uri = g_strdup (fi->uri); - si->flags = fi->flags; - si->unread = fi->unread; - si->total = fi->total; - - camel_store_summary_add (ss, si); - - /* FIXME: should this be recursive? */ -} - -void -camel_imap4_store_summary_unnote_info (CamelIMAP4StoreSummary *s, CamelFolderInfo *fi) -{ - CamelStoreSummary *ss = (CamelStoreSummary *) s; - - camel_store_summary_remove_path (ss, fi->full_name); -} - -static CamelFolderInfo * -store_info_to_folder_info (CamelStoreSummary *s, CamelStoreInfo *si) -{ - CamelFolderInfo *fi; - const gchar *name; - - fi = camel_folder_info_new (); - fi->full_name = g_strdup (camel_store_info_path (s, si)); - fi->uri = g_strdup (camel_store_info_uri (s, si)); - fi->flags = si->flags; - fi->unread = si->unread; - fi->total = si->total; - - name = camel_store_info_name (s, si); - if (!g_ascii_strcasecmp (fi->full_name, "INBOX")) { - fi->flags |= CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_TYPE_INBOX; - fi->name = g_strdup (_("Inbox")); - } else { - fi->name = g_strdup (name); - } - - return fi; -} - -CamelFolderInfo * -camel_imap4_store_summary_get_folder_info (CamelIMAP4StoreSummary *s, const gchar *top, guint32 flags) -{ - CamelStoreSummary *ss = (CamelStoreSummary *) s; - CamelFolderInfo *fi; - GPtrArray *folders; - CamelStoreInfo *si; - gsize toplen, len; - gint i; - - toplen = strlen (top); - folders = g_ptr_array_new (); - - for (i = 0; i < ss->folders->len; i++) { - si = ss->folders->pdata[i]; - if (strncmp (si->path, top, toplen) != 0) - continue; - - len = strlen (si->path); - if (toplen > 0 && len > toplen && si->path[toplen] != '/') - continue; - - if (len == toplen) { - /* found toplevel folder */ - g_ptr_array_add (folders, store_info_to_folder_info (ss, si)); - continue; - } - - if ((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) || !strchr (si->path + toplen + 1, '/')) - g_ptr_array_add (folders, store_info_to_folder_info (ss, si)); - } - - fi = camel_imap4_build_folder_info_tree (folders, top); - g_ptr_array_free (folders, TRUE); - - return fi; -} diff --git a/camel/providers/imap4/camel-imap4-store-summary.h b/camel/providers/imap4/camel-imap4-store-summary.h deleted file mode 100644 index ce1e5f0..0000000 --- a/camel/providers/imap4/camel-imap4-store-summary.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef CAMEL_IMAP_STORE_SUMMARY_H -#define CAMEL_IMAP_STORE_SUMMARY_H - -#include -#include "camel-imap4-engine.h" - -#define CAMEL_IMAP4_STORE_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_imap4_store_summary_get_type (), CamelIMAP4StoreSummary) -#define CAMEL_IMAP4_STORE_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imap4_store_summary_get_type (), CamelIMAP4StoreSummaryClass) -#define CAMEL_IS_IMAP4_STORE_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_imap4_store_summary_get_type ()) - -G_BEGIN_DECLS - -typedef struct _CamelIMAP4StoreSummary CamelIMAP4StoreSummary; -typedef struct _CamelIMAP4StoreSummaryClass CamelIMAP4StoreSummaryClass; - -typedef struct _CamelIMAP4StoreInfo CamelIMAP4StoreInfo; - -enum { - CAMEL_IMAP4_STORE_INFO_FULL_NAME = CAMEL_STORE_INFO_LAST, - CAMEL_IMAP4_STORE_INFO_LAST, -}; - -struct _CamelFolderInfo; - -struct _CamelIMAP4StoreInfo { - CamelStoreInfo info; -}; - -struct _CamelIMAP4StoreSummary { - CamelStoreSummary summary; - - struct _CamelIMAP4StoreSummaryPrivate *priv; - - /* header info */ - guint32 version; - - CamelIMAP4NamespaceList *namespaces; - guint32 capa; -}; - -struct _CamelIMAP4StoreSummaryClass { - CamelStoreSummaryClass summary_class; -}; - -CamelType camel_imap4_store_summary_get_type (void); - -CamelIMAP4StoreSummary *camel_imap4_store_summary_new (void); - -void camel_imap4_store_summary_set_capabilities (CamelIMAP4StoreSummary *s, guint32 capa); -void camel_imap4_store_summary_set_namespaces (CamelIMAP4StoreSummary *s, const CamelIMAP4NamespaceList *ns); - -/* add the info to the cache if we don't already have it, otherwise do nothing */ -void camel_imap4_store_summary_note_info (CamelIMAP4StoreSummary *s, struct _CamelFolderInfo *fi); - -void camel_imap4_store_summary_unnote_info (CamelIMAP4StoreSummary *s, struct _CamelFolderInfo *fi); - -struct _CamelFolderInfo *camel_imap4_store_summary_get_folder_info (CamelIMAP4StoreSummary *s, const gchar *top, guint32 flags); - -G_END_DECLS - -#endif /* CAMEL_IMAP4_STORE_SUMMARY_H */ diff --git a/camel/providers/imap4/camel-imap4-store.c b/camel/providers/imap4/camel-imap4-store.c deleted file mode 100644 index d7f35e6..0000000 --- a/camel/providers/imap4/camel-imap4-store.c +++ /dev/null @@ -1,1799 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#ifdef HAVE_SSL -#include -#endif - -#include "camel-imap4-command.h" -#include "camel-imap4-engine.h" -#include "camel-imap4-folder.h" -#include "camel-imap4-store-summary.h" -#include "camel-imap4-store.h" -#include "camel-imap4-stream.h" -#include "camel-imap4-summary.h" -#include "camel-imap4-utils.h" - -#define d(x) - -static void camel_imap4_store_class_init (CamelIMAP4StoreClass *klass); -static void camel_imap4_store_init (CamelIMAP4Store *store, CamelIMAP4StoreClass *klass); -static void camel_imap4_store_finalize (CamelObject *object); - -/* service methods */ -static void imap4_construct (CamelService *service, CamelSession *session, - CamelProvider *provider, CamelURL *url, - CamelException *ex); -static gchar *imap4_get_name (CamelService *service, gboolean brief); -static gboolean imap4_connect (CamelService *service, CamelException *ex); -static gboolean imap4_reconnect (CamelIMAP4Engine *engine, CamelException *ex); -static gboolean imap4_disconnect (CamelService *service, gboolean clean, CamelException *ex); -static GList *imap4_query_auth_types (CamelService *service, CamelException *ex); - -/* store methods */ -static CamelFolder *imap4_get_folder (CamelStore *store, const gchar *folder_name, guint32 flags, CamelException *ex); -static CamelFolderInfo *imap4_create_folder (CamelStore *store, const gchar *parent_name, const gchar *folder_name, CamelException *ex); -static void imap4_delete_folder (CamelStore *store, const gchar *folder_name, CamelException *ex); -static void imap4_rename_folder (CamelStore *store, const gchar *old_name, const gchar *new_name, CamelException *ex); -static CamelFolderInfo *imap4_get_folder_info (CamelStore *store, const gchar *top, guint32 flags, CamelException *ex); -static void imap4_free_folder_info (CamelStore *store, CamelFolderInfo *fi); -static void imap4_subscribe_folder (CamelStore *store, const gchar *folder_name, CamelException *ex); -static void imap4_unsubscribe_folder (CamelStore *store, const gchar *folder_name, CamelException *ex); -static gboolean imap4_folder_subscribed (CamelStore *store, const gchar *folder_name); -static void imap4_noop (CamelStore *store, CamelException *ex); - -static CamelOfflineStoreClass *parent_class = NULL; - -CamelType -camel_imap4_store_get_type (void) -{ - static CamelType type = 0; - - if (!type) { - type = camel_type_register (camel_offline_store_get_type (), - "CamelIMAP4Store", - sizeof (CamelIMAP4Store), - sizeof (CamelIMAP4StoreClass), - (CamelObjectClassInitFunc) camel_imap4_store_class_init, - NULL, - (CamelObjectInitFunc) camel_imap4_store_init, - (CamelObjectFinalizeFunc) camel_imap4_store_finalize); - } - - return type; -} - -static guint -imap4_hash_folder_name (gconstpointer key) -{ - if (g_ascii_strcasecmp (key, "INBOX") == 0) - return g_str_hash ("INBOX"); - else - return g_str_hash (key); -} - -static gint -imap4_compare_folder_name (gconstpointer a, gconstpointer b) -{ - gconstpointer aname = a, bname = b; - - if (g_ascii_strcasecmp (a, "INBOX") == 0) - aname = "INBOX"; - if (g_ascii_strcasecmp (b, "INBOX") == 0) - bname = "INBOX"; - - return g_str_equal (aname, bname); -} - -static void -camel_imap4_store_class_init (CamelIMAP4StoreClass *klass) -{ - CamelServiceClass *service_class = (CamelServiceClass *) klass; - CamelStoreClass *store_class = (CamelStoreClass *) klass; - - parent_class = (CamelOfflineStoreClass *) camel_type_get_global_classfuncs (CAMEL_TYPE_OFFLINE_STORE); - - service_class->construct = imap4_construct; - service_class->get_name = imap4_get_name; - service_class->connect = imap4_connect; - service_class->disconnect = imap4_disconnect; - service_class->query_auth_types = imap4_query_auth_types; - - store_class->hash_folder_name = imap4_hash_folder_name; - store_class->compare_folder_name = imap4_compare_folder_name; - - store_class->get_folder = imap4_get_folder; - store_class->create_folder = imap4_create_folder; - store_class->delete_folder = imap4_delete_folder; - store_class->rename_folder = imap4_rename_folder; - store_class->get_folder_info = imap4_get_folder_info; - store_class->free_folder_info = imap4_free_folder_info; - store_class->subscribe_folder = imap4_subscribe_folder; - store_class->unsubscribe_folder = imap4_unsubscribe_folder; - store_class->folder_subscribed = imap4_folder_subscribed; - store_class->noop = imap4_noop; -} - -static void -camel_imap4_store_init (CamelIMAP4Store *store, CamelIMAP4StoreClass *klass) -{ - store->engine = NULL; - store->summary = NULL; -} - -static void -camel_imap4_store_finalize (CamelObject *object) -{ - CamelIMAP4Store *store = (CamelIMAP4Store *) object; - - if (store->summary) { - camel_store_summary_save ((CamelStoreSummary *) store->summary); - camel_object_unref (store->summary); - } - - if (store->engine) - camel_object_unref (store->engine); - - g_free (store->storage_path); -} - -static void -imap4_construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex) -{ - CamelIMAP4Store *store = (CamelIMAP4Store *) service; - gchar *buf; - - CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); - if (camel_exception_is_set (ex)) - return; - - if (camel_url_get_param (url, "use_lsub")) - ((CamelStore *) store)->flags |= CAMEL_STORE_SUBSCRIPTIONS; - - store->storage_path = camel_session_get_storage_path (session, service, ex); - store->engine = camel_imap4_engine_new (service, imap4_reconnect); - - /* setup/load the summary */ - buf = g_alloca (strlen (store->storage_path) + 32); - sprintf (buf, "%s/.summary", store->storage_path); - store->summary = camel_imap4_store_summary_new (); - camel_store_summary_set_filename ((CamelStoreSummary *) store->summary, buf); - - buf = camel_url_to_string (service->url, CAMEL_URL_HIDE_ALL); - url = camel_url_new (buf, NULL); - g_free (buf); - camel_store_summary_set_uri_base ((CamelStoreSummary *) store->summary, url); - camel_url_free (url); - - camel_store_summary_load ((CamelStoreSummary *) store->summary); -} - -static gchar * -imap4_get_name (CamelService *service, gboolean brief) -{ - if (brief) - return g_strdup_printf (_("IMAP server %s"), service->url->host); - else - return g_strdup_printf (_("IMAP service for %s on %s"), - service->url->user, service->url->host); -} - -enum { - MODE_CLEAR, - MODE_SSL, - MODE_TLS, -}; - -#ifdef HAVE_SSL -#define SSL_PORT_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3) -#define STARTTLS_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_TLS) -#endif - -static gboolean -connect_to_server (CamelIMAP4Engine *engine, struct addrinfo *ai, gint ssl_mode, CamelException *ex) -{ - CamelService *service = engine->service; - CamelSockOptData sockopt; - CamelStream *tcp_stream; -#ifdef HAVE_SSL - CamelIMAP4Command *ic; - gint id; -#endif - - if (ssl_mode != MODE_CLEAR) { -#ifdef HAVE_SSL - if (ssl_mode == MODE_TLS) { - tcp_stream = camel_tcp_stream_ssl_new_raw (service->session, service->url->host, STARTTLS_FLAGS); - } else { - tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, SSL_PORT_FLAGS); - } -#else - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s: %s"), - service->url->host, _("SSL unavailable")); - - return FALSE; -#endif /* HAVE_SSL */ - } else { - tcp_stream = camel_tcp_stream_raw_new (); - } - - if (camel_tcp_stream_connect ((CamelTcpStream *) tcp_stream, ai) == -1) { - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Connection canceled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s: %s"), - service->url->host, - g_strerror (errno)); - - camel_object_unref (tcp_stream); - - return FALSE; - } - - /* set some socket options to better tailor the connection to our needs */ - sockopt.option = CAMEL_SOCKOPT_NODELAY; - sockopt.value.no_delay = TRUE; - camel_tcp_stream_setsockopt ((CamelTcpStream *) tcp_stream, &sockopt); - - sockopt.option = CAMEL_SOCKOPT_KEEPALIVE; - sockopt.value.keep_alive = TRUE; - camel_tcp_stream_setsockopt ((CamelTcpStream *) tcp_stream, &sockopt); - - if (camel_imap4_engine_take_stream (engine, tcp_stream, ex) == -1) - return FALSE; - - if (camel_imap4_engine_capability (engine, ex) == -1) - return FALSE; - - camel_imap4_store_summary_set_capabilities (((CamelIMAP4Store *) service)->summary, engine->capa); - - if (ssl_mode != MODE_TLS) { - /* we're done */ - return TRUE; - } - -#ifdef HAVE_SSL - if (!(engine->capa & CAMEL_IMAP4_CAPABILITY_STARTTLS)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to IMAP server %s in secure mode: " - "Server does not support STARTTLS"), - service->url->host); - - return FALSE; - } - - ic = camel_imap4_engine_prequeue (engine, NULL, "STARTTLS\r\n"); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->result != CAMEL_IMAP4_RESULT_OK) { - if (ic->result != CAMEL_IMAP4_RESULT_OK) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to IMAP server %s in secure mode: %s"), - service->url->host, _("Unknown error")); - } else { - camel_exception_xfer (ex, &ic->ex); - } - - camel_imap4_command_unref (ic); - - return FALSE; - } - - camel_imap4_command_unref (ic); - - if (camel_tcp_stream_ssl_enable_ssl ((CamelTcpStreamSSL *) tcp_stream) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to IMAP server %s in secure mode: %s"), - service->url->host, _("TLS negotiations failed")); - camel_imap4_engine_disconnect (engine); - return FALSE; - } - - return TRUE; -#else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to IMAP server %s in secure mode: %s"), - service->url->host, _("SSL is not available in this build")); - - return FALSE; -#endif /* HAVE_SSL */ -} - -static struct { - gchar *value; - gchar *serv; - gchar *port; - gint mode; -} ssl_options[] = { - { "", "imaps", "993", MODE_SSL }, /* really old (1.x) */ - { "always", "imaps", "993", MODE_SSL }, - { "when-possible", "imap", "143", MODE_TLS }, - { "never", "imap", "143", MODE_CLEAR }, - { NULL, "imap", "143", MODE_CLEAR }, -}; - -static gboolean -connect_to_server_wrapper (CamelIMAP4Engine *engine, CamelException *ex) -{ - CamelService *service = engine->service; - struct addrinfo *ai, hints; - const gchar *ssl_mode; - gint mode, ret, i; - const gchar *port; - gchar *serv; - - if ((ssl_mode = camel_url_get_param (service->url, "use_ssl"))) { - for (i = 0; ssl_options[i].value; i++) - if (!strcmp (ssl_options[i].value, ssl_mode)) - break; - mode = ssl_options[i].mode; - serv = ssl_options[i].serv; - port = ssl_options[i].port; - } else { - mode = MODE_CLEAR; - serv = "imap"; - port = "143"; - } - - if (service->url->port) { - serv = g_alloca (16); - sprintf (serv, "%d", service->url->port); - port = NULL; - } - - memset (&hints, 0, sizeof (hints)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = PF_UNSPEC; - ai = camel_getaddrinfo (service->url->host, serv, &hints, ex); - if (ai == NULL && port != NULL && camel_exception_get_id(ex) != CAMEL_EXCEPTION_USER_CANCEL) { - camel_exception_clear (ex); - ai = camel_getaddrinfo (service->url->host, port, &hints, ex); - } - - if (ai == NULL) - return FALSE; - - ret = connect_to_server (engine, ai, mode, ex); - - camel_freeaddrinfo (ai); - - return ret; -} - -static gint -sasl_auth (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, const guchar *linebuf, gsize linelen, CamelException *ex) -{ - /* Perform a single challenge iteration */ - CamelSasl *sasl = ic->user_data; - gchar *challenge; - - if (camel_sasl_authenticated (sasl)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Cannot authenticate to IMAP server %s using the %s authentication mechanism"), - engine->url->host, engine->url->authmech); - return -1; - } - - while (isspace (*linebuf)) - linebuf++; - - if (*linebuf == '\0') - linebuf = NULL; - - if (!(challenge = camel_sasl_challenge_base64 (sasl, (const gchar *) linebuf, ex))) - return -1; - - d(fprintf (stderr, "sending : %s\r\n", challenge)); - - if (camel_stream_printf (engine->ostream, "%s\r\n", challenge) == -1) { - g_free (challenge); - return -1; - } - - g_free (challenge); - - if (camel_stream_flush (engine->ostream) == -1) - return -1; - - return 0; -} - -static gint -imap4_try_authenticate (CamelIMAP4Engine *engine, gboolean reprompt, const gchar *errmsg, CamelException *ex) -{ - CamelService *service = engine->service; - CamelSession *session = service->session; - CamelServiceAuthType *mech = NULL; - CamelSasl *sasl = NULL; - CamelIMAP4Command *ic; - gint id; - - if (service->url->authmech) - mech = g_hash_table_lookup (engine->authtypes, service->url->authmech); - - if ((!mech || (mech && mech->need_password)) && !service->url->passwd) { - guint32 flags = CAMEL_SESSION_PASSWORD_SECRET; - gchar *base_prompt; - gchar *full_prompt; - - if (reprompt) - flags |= CAMEL_SESSION_PASSWORD_REPROMPT; - - base_prompt = camel_session_build_password_prompt ( - "IMAP", service->url->user, service->url->host); - - if (errmsg != NULL) - full_prompt = g_strconcat (errmsg, base_prompt, NULL); - else - full_prompt = g_strdup (base_prompt); - - service->url->passwd = camel_session_get_password ( - session, service, NULL, full_prompt, - "password", flags, ex); - - g_free (base_prompt); - g_free (full_prompt); - - if (!service->url->passwd) - return FALSE; - } - - if (service->url->authmech) { - sasl = camel_sasl_new ("imap", mech->authproto, service); - - ic = camel_imap4_engine_prequeue (engine, NULL, "AUTHENTICATE %s\r\n", service->url->authmech); - ic->plus = sasl_auth; - ic->user_data = sasl; - } else { - ic = camel_imap4_engine_prequeue (engine, NULL, "LOGIN %S %S\r\n", - service->url->user, service->url->passwd); - } - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (sasl != NULL) - camel_object_unref (sasl); - - if (id == -1 || ic->status == CAMEL_IMAP4_COMMAND_ERROR) { - /* unrecoverable error */ - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - - return FALSE; - } - - if (ic->result != CAMEL_IMAP4_RESULT_OK) { - camel_imap4_command_unref (ic); - - /* try again */ - - return TRUE; - } - - camel_imap4_command_unref (ic); - - return FALSE; -} - -static gboolean -imap4_reconnect (CamelIMAP4Engine *engine, CamelException *ex) -{ - CamelService *service = engine->service; - gboolean reprompt = FALSE; - gchar *errmsg = NULL; - CamelException lex; - - if (!connect_to_server_wrapper (engine, ex)) - return FALSE; - - if (engine->state != CAMEL_IMAP4_ENGINE_AUTHENTICATED) { -#define CANT_USE_AUTHMECH (!g_hash_table_lookup (engine->authtypes, service->url->authmech)) - if (service->url->authmech && CANT_USE_AUTHMECH) { - /* Oops. We can't AUTH using the requested mechanism */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Cannot authenticate to IMAP server %s using %s"), - service->url->host, service->url->authmech); - - return FALSE; - } - - camel_exception_init (&lex); - while (imap4_try_authenticate (engine, reprompt, errmsg, &lex)) { - g_free (errmsg); - errmsg = g_markup_escape_text (lex.desc, -1); - camel_exception_clear (&lex); - g_free (service->url->passwd); - service->url->passwd = NULL; - reprompt = TRUE; - } - g_free (errmsg); - - if (camel_exception_is_set (&lex)) { - camel_exception_xfer (ex, &lex); - return FALSE; - } - } - - if (camel_imap4_engine_namespace (engine, ex) == -1) - return FALSE; - - camel_imap4_store_summary_set_namespaces (((CamelIMAP4Store *) service)->summary, &engine->namespaces); - - return TRUE; -} - -static gboolean -imap4_connect (CamelService *service, CamelException *ex) -{ - CamelIMAP4Store *store = (CamelIMAP4Store *) service; - gboolean retval; - - if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) - return TRUE; - - CAMEL_SERVICE_REC_LOCK (service, connect_lock); - if (store->engine->state == CAMEL_IMAP4_ENGINE_DISCONNECTED) - retval = imap4_reconnect (store->engine, ex); - else - retval = TRUE; - CAMEL_SERVICE_REC_UNLOCK (service, connect_lock); - - return retval; -} - -static gboolean -imap4_disconnect (CamelService *service, gboolean clean, CamelException *ex) -{ - CamelIMAP4Store *store = (CamelIMAP4Store *) service; - CamelIMAP4Command *ic; - gint id; - - if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) - return TRUE; - - CAMEL_SERVICE_REC_LOCK (store, connect_lock); - if (clean && store->engine->state != CAMEL_IMAP4_ENGINE_DISCONNECTED) { - ic = camel_imap4_engine_queue (store->engine, NULL, "LOGOUT\r\n"); - while ((id = camel_imap4_engine_iterate (store->engine)) < ic->id && id != -1) - ; - - camel_imap4_command_unref (ic); - } - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); - - return FALSE; -} - -extern CamelServiceAuthType camel_imap4_password_authtype; - -static GList * -imap4_query_auth_types (CamelService *service, CamelException *ex) -{ - CamelIMAP4Store *store = (CamelIMAP4Store *) service; - CamelServiceAuthType *authtype; - GList *sasl_types, *t, *next; - gboolean connected; - - if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) - return NULL; - - CAMEL_SERVICE_REC_LOCK (store, connect_lock); - connected = connect_to_server_wrapper (store->engine, ex); - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); - if (!connected) - return NULL; - - sasl_types = camel_sasl_authtype_list (FALSE); - for (t = sasl_types; t; t = next) { - authtype = t->data; - next = t->next; - - if (!g_hash_table_lookup (store->engine->authtypes, authtype->authproto)) { - sasl_types = g_list_remove_link (sasl_types, t); - g_list_free_1 (t); - } - } - - return g_list_prepend (sasl_types, &camel_imap4_password_authtype); -} - -static gchar * -imap4_folder_utf7_name (CamelStore *store, const gchar *folder_name, gchar wildcard) -{ - gchar *real_name, *p; - gchar sep = '\0'; - gint len; - - if (*folder_name) { - sep = camel_imap4_get_path_delim (((CamelIMAP4Store *) store)->summary, folder_name); - - if (sep != '/') { - p = real_name = g_alloca (strlen (folder_name) + 1); - strcpy (real_name, folder_name); - while (*p != '\0') { - if (*p == '/') - *p = sep; - p++; - } - - folder_name = real_name; - } - - real_name = camel_utf8_utf7 (folder_name); - } else - real_name = g_strdup (""); - - if (wildcard) { - len = strlen (real_name); - real_name = g_realloc (real_name, len + 3); - - if (len > 0) - real_name[len++] = sep; - - real_name[len++] = wildcard; - real_name[len] = '\0'; - } - - return real_name; -} - -static CamelFolder * -imap4_get_folder (CamelStore *store, const gchar *folder_name, guint32 flags, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelFolder *folder = NULL; - camel_imap4_list_t *list; - CamelIMAP4Command *ic; - CamelFolderInfo *fi; - GPtrArray *array; - gchar *utf7_name; - gint create; - gint id, i; - - CAMEL_SERVICE_REC_LOCK (store, connect_lock); - - if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) { - if ((flags & CAMEL_STORE_FOLDER_CREATE) != 0) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create IMAP folders in offline mode.")); - } else { - folder = camel_imap4_folder_new (store, folder_name, ex); - } - - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); - - return folder; - } - - /* make sure the folder exists - try LISTing it? */ - utf7_name = imap4_folder_utf7_name (store, folder_name, '\0'); - ic = camel_imap4_engine_queue (engine, NULL, "LIST \"\" %S\r\n", utf7_name); - camel_imap4_command_register_untagged (ic, "LIST", camel_imap4_untagged_list); - ic->user_data = array = g_ptr_array_new (); - g_free (utf7_name); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - g_ptr_array_free (array, TRUE); - goto done; - } - - create = array->len == 0; - - for (i = 0; i < array->len; i++) { - list = array->pdata[i]; - g_free (list->name); - g_free (list); - } - - g_ptr_array_free (array, TRUE); - - if (ic->result != CAMEL_IMAP4_RESULT_OK) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get folder '%s' on IMAP server %s: Unknown error"), - folder_name, ((CamelService *) store)->url->host); - camel_imap4_command_unref (ic); - goto done; - } - - camel_imap4_command_unref (ic); - - if (create) { - const gchar *basename; - gchar *parent; - gint len; - - if (!(flags & CAMEL_STORE_FOLDER_CREATE)) - goto done; - - if (!(basename = strrchr (folder_name, '/'))) - basename = folder_name; - else - basename++; - - len = basename > folder_name ? (basename - folder_name) - 1 : 0; - parent = g_alloca (len + 1); - memcpy (parent, folder_name, len); - parent[len] = '\0'; - - if (!(fi = imap4_create_folder (store, parent, basename, ex))) - goto done; - - camel_store_free_folder_info (store, fi); - } - - folder = camel_imap4_folder_new (store, folder_name, ex); - - done: - - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); - - return folder; -} - -static gboolean -imap4_folder_can_contain_folders (CamelStore *store, const gchar *folder_name, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - guint32 flags = CAMEL_FOLDER_NOINFERIORS; - camel_imap4_list_t *list; - CamelIMAP4Command *ic; - GPtrArray *array; - gchar *utf7_name; - gint id, i; - - CAMEL_SERVICE_REC_LOCK (store, connect_lock); - - utf7_name = imap4_folder_utf7_name (store, folder_name, '\0'); - - ic = camel_imap4_engine_queue (engine, NULL, "LIST \"\" %S\r\n", utf7_name); - camel_imap4_command_register_untagged (ic, "LIST", camel_imap4_untagged_list); - ic->user_data = array = g_ptr_array_new (); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - - for (i = 0; i < array->len; i++) { - list = array->pdata[i]; - g_free (list->name); - g_free (list); - } - - goto done; - } - - if (ic->result != CAMEL_IMAP4_RESULT_OK) { - camel_imap4_command_unref (ic); - - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get LIST information for '%s' on IMAP server %s: %s"), - folder_name, engine->url->host, ic->result == CAMEL_IMAP4_RESULT_BAD ? - _("Bad command") : _("Unknown error")); - - for (i = 0; i < array->len; i++) { - list = array->pdata[i]; - g_free (list->name); - g_free (list); - } - - goto done; - } - - flags = 0; - for (i = 0; i < array->len; i++) { - list = array->pdata[i]; - if (!strcmp (list->name, utf7_name)) - flags |= list->flags; - g_free (list->name); - g_free (list); - } - - done: - - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); - - g_ptr_array_free (array, TRUE); - g_free (utf7_name); - - return (flags & CAMEL_FOLDER_NOINFERIORS) == 0; -} - -static CamelFolderInfo * -imap4_folder_create (CamelStore *store, const gchar *folder_name, const gchar *subfolder_hint, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelFolderInfo *fi = NULL; - CamelIMAP4Command *ic; - gchar *utf7_name; - CamelURL *url; - const gchar *c; - gint id; - - CAMEL_SERVICE_REC_LOCK (store, connect_lock); - - utf7_name = imap4_folder_utf7_name (store, folder_name, '\0'); - ic = camel_imap4_engine_queue (engine, NULL, "CREATE %S%s\r\n", utf7_name, subfolder_hint); - g_free (utf7_name); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - goto done; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - url = camel_url_copy (engine->url); - camel_url_set_fragment (url, folder_name); - - c = strrchr (folder_name, '/'); - - fi = camel_folder_info_new (); - fi->full_name = g_strdup (folder_name); - fi->name = g_strdup (c ? c + 1: folder_name); - fi->uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - camel_url_free (url); - fi->flags = 0; - fi->unread = -1; - fi->total = -1; - - camel_imap4_store_summary_note_info (((CamelIMAP4Store *) store)->summary, fi); - - camel_object_trigger_event (store, "folder_created", fi); - break; - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create folder '%s': Invalid mailbox name"), - folder_name); - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create folder '%s': Bad command"), - folder_name); - break; - default: - g_assert_not_reached (); - } - - camel_imap4_command_unref (ic); - - done: - - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); - - return fi; -} - -static gboolean -imap4_folder_recreate (CamelStore *store, const gchar *folder_name, CamelException *ex) -{ - CamelFolderInfo *fi = NULL; - gchar hint[2]; - gchar sep; - - sep = camel_imap4_get_path_delim (((CamelIMAP4Store *) store)->summary, folder_name); - sprintf (hint, "%c", sep); - - imap4_delete_folder (store, folder_name, ex); - if (camel_exception_is_set (ex)) - return FALSE; - - if (!(fi = imap4_folder_create (store, folder_name, hint, ex))) - return FALSE; - - camel_folder_info_free (fi); - - return TRUE; -} - -static CamelFolderInfo * -imap4_create_folder (CamelStore *store, const gchar *parent_name, const gchar *folder_name, CamelException *ex) -{ - CamelFolderInfo *fi = NULL; - const gchar *c; - gchar *name; - gchar sep; - - sep = camel_imap4_get_path_delim (((CamelIMAP4Store *) store)->summary, parent_name); - - c = folder_name; - while (*c != '\0') { - if (*c == sep || strchr ("/#%*", *c)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_PATH, - _("The folder name \"%s\" is invalid because " - "it contains the character \"%c\""), - folder_name, *c); - return NULL; - } - - c++; - } - - if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create IMAP folders in offline mode.")); - return NULL; - } - - if (parent_name != NULL && *parent_name) { - CamelException lex; - - camel_exception_init (&lex); - if (!imap4_folder_can_contain_folders (store, parent_name, &lex)) { - if (camel_exception_is_set (&lex)) { - camel_exception_xfer (ex, &lex); - return NULL; - } - - if (!imap4_folder_recreate (store, parent_name, &lex)) { - camel_exception_xfer (ex, &lex); - return NULL; - } - } - - name = g_strdup_printf ("%s/%s", parent_name, folder_name); - } else - name = g_strdup (folder_name); - - fi = imap4_folder_create (store, name, "", ex); - g_free (name); - - return fi; -} - -static void -imap4_delete_folder (CamelStore *store, const gchar *folder_name, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelFolder *selected = (CamelFolder *) engine->folder; - CamelIMAP4Command *ic, *ic0 = NULL; - CamelFolderInfo *fi; - gchar *utf7_name; - CamelURL *url; - const gchar *p; - gint id; - - if (!g_ascii_strcasecmp (folder_name, "INBOX")) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot delete folder '%s': Special folder"), - folder_name); - - return; - } - - if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot delete IMAP folders in offline mode.")); - return; - } - - CAMEL_SERVICE_REC_LOCK (store, connect_lock); - - if (selected && !strcmp (folder_name, selected->full_name)) - ic0 = camel_imap4_engine_queue (engine, NULL, "CLOSE\r\n"); - - utf7_name = imap4_folder_utf7_name (store, folder_name, '\0'); - ic = camel_imap4_engine_queue (engine, NULL, "DELETE %S\r\n", utf7_name); - g_free (utf7_name); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - if (ic0 && ic0->status != CAMEL_IMAP4_COMMAND_COMPLETE) - camel_exception_xfer (ex, &ic0->ex); - else - camel_exception_xfer (ex, &ic->ex); - - if (ic0 != NULL) - camel_imap4_command_unref (ic0); - - camel_imap4_command_unref (ic); - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); - return; - } - - if (ic0 != NULL) - camel_imap4_command_unref (ic0); - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - /* deleted */ - url = camel_url_copy (engine->url); - camel_url_set_fragment (url, folder_name); - - p = strrchr (folder_name, '/'); - - fi = camel_folder_info_new (); - fi->full_name = g_strdup (folder_name); - fi->name = g_strdup (p ? p + 1: folder_name); - fi->uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - camel_url_free (url); - fi->flags = 0; - fi->unread = -1; - fi->total = -1; - - camel_imap4_store_summary_unnote_info (((CamelIMAP4Store *) store)->summary, fi); - - camel_object_trigger_event (store, "folder_deleted", fi); - - camel_folder_info_free (fi); - break; - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot delete folder '%s': Invalid mailbox name"), - folder_name); - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot delete folder '%s': Bad command"), - folder_name); - break; - } - - camel_imap4_command_unref (ic); - - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); -} - -static void -imap4_rename_folder (CamelStore *store, const gchar *old_name, const gchar *new_name, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - gchar *old_uname, *new_uname; - CamelIMAP4Command *ic; - gint id; - - if (!g_ascii_strcasecmp (old_name, "INBOX")) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot rename folder '%s' to '%s': Special folder"), - old_name, new_name); - - return; - } - - if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot rename IMAP folders in offline mode.")); - return; - } - - CAMEL_SERVICE_REC_LOCK (store, connect_lock); - - old_uname = imap4_folder_utf7_name (store, old_name, '\0'); - new_uname = imap4_folder_utf7_name (store, new_name, '\0'); - - ic = camel_imap4_engine_queue (engine, NULL, "RENAME %S %S\r\n", old_uname, new_uname); - g_free (old_uname); - g_free (new_uname); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); - return; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - /* FIXME: need to update state on the renamed folder object */ - /* FIXME: need to update cached summary info too */ - break; - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot rename folder '%s' to '%s': Invalid mailbox name"), - old_name, new_name); - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot rename folder '%s' to '%s': Bad command"), - old_name, new_name); - break; - } - - camel_imap4_command_unref (ic); - - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); -} - -static gint -list_sort (const camel_imap4_list_t **list0, const camel_imap4_list_t **list1) -{ - return strcmp ((*list0)->name, (*list1)->name); -} - -static void -list_remove_duplicates (GPtrArray *array) -{ - camel_imap4_list_t *list, *last; - gint i; - - last = array->pdata[0]; - for (i = 1; i < array->len; i++) { - list = array->pdata[i]; - if (!strcmp (list->name, last->name)) { - g_ptr_array_remove_index (array, i--); - last->flags |= list->flags; - g_free (list->name); - g_free (list); - } - } -} - -static gchar * -list_parent (camel_imap4_list_t *mbox) -{ - const gchar *d; - - if (!(d = strrchr (mbox->name, mbox->delim))) - return NULL; - - return g_strndup (mbox->name, d - mbox->name); -} - -/* bloody glib... GPtrArray doesn't have an insert method */ -static void -array_insert (GPtrArray *array, gint index, gpointer data) -{ - gint i; - - if ((index + 1) == array->len) { - /* special case, adding to the end of the array */ - g_ptr_array_add (array, data); - return; - } - - if (index >= array->len) { - /* special case, adding past the end of the array */ - g_ptr_array_set_size (array, index + 1); - array->pdata[index] = data; - return; - } - - g_ptr_array_set_size (array, array->len + 1); - - /* shift all elements starting at @index 1 position to the right */ - for (i = array->len - 2; i >= index; i--) - array->pdata[i + 1] = array->pdata[i]; - - array->pdata[index] = data; -} - -static void -list_add_ghosts (GPtrArray *array) -{ - camel_imap4_list_t *mbox; - GHashTable *list_hash; - gchar delim, *parent; - gint i = 0; - - list_hash = g_hash_table_new (g_str_hash, g_str_equal); - - while (i < array->len) { - mbox = array->pdata[i]; - if ((parent = list_parent (mbox))) { - if (!g_hash_table_lookup (list_hash, parent)) { - /* ghost folder, insert a fake LIST info w/ a \NoSelect flag */ - delim = mbox->delim; - mbox = g_new (camel_imap4_list_t, 1); - mbox->flags = CAMEL_FOLDER_NOSELECT; - mbox->name = parent; - mbox->delim = delim; - - g_hash_table_insert (list_hash, parent, mbox); - - array_insert (array, i, mbox); - continue; - } else { - /* already exists */ - g_free (parent); - } - } - - g_hash_table_insert (list_hash, mbox->name, mbox); - - i++; - } - - g_hash_table_destroy (list_hash); -} - -static void -imap4_status (CamelStore *store, CamelFolderInfo *fi) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - camel_imap4_status_attr_t *attr, *next; - camel_imap4_status_t *status; - CamelIMAP4Command *ic; - GPtrArray *array; - gchar *mailbox; - gint id, i; - - mailbox = imap4_folder_utf7_name (store, fi->full_name, '\0'); - ic = camel_imap4_engine_queue (engine, NULL, "STATUS %S (MESSAGES UNSEEN)\r\n", mailbox); - g_free (mailbox); - - camel_imap4_command_register_untagged (ic, "STATUS", camel_imap4_untagged_status); - ic->user_data = array = g_ptr_array_new (); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_imap4_command_unref (ic); - g_ptr_array_free (array, TRUE); - return; - } - - for (i = 0; i < array->len; i++) { - status = array->pdata[i]; - attr = status->attr_list; - while (attr != NULL) { - next = attr->next; - if (attr->type == CAMEL_IMAP4_STATUS_MESSAGES) - fi->total = attr->value; - else if (attr->type == CAMEL_IMAP4_STATUS_UNSEEN) - fi->unread = attr->value; - g_free (attr); - attr = next; - } - - g_free (status->mailbox); - g_free (status); - } - - camel_imap4_command_unref (ic); - g_ptr_array_free (array, TRUE); -} - -static void -imap4_subscription_info (CamelStore *store, CamelFolderInfo *fi) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - camel_imap4_list_t *lsub; - CamelIMAP4Command *ic; - GPtrArray *array; - gchar *mailbox; - gint id, i; - - mailbox = imap4_folder_utf7_name (store, fi->full_name, '\0'); - ic = camel_imap4_engine_queue (engine, NULL, "LSUB \"\" %S\r\n", mailbox); - camel_imap4_command_register_untagged (ic, "LSUB", camel_imap4_untagged_list); - ic->user_data = array = g_ptr_array_new (); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - camel_imap4_command_unref (ic); - for (i = 0; i < array->len; i++) { - lsub = array->pdata[i]; - - if (!strcmp (lsub->name, mailbox)) - fi->flags |= CAMEL_FOLDER_SUBSCRIBED; - - g_free (lsub->name); - g_free (lsub); - } - - g_ptr_array_free (array, TRUE); -} - -static CamelFolderInfo * -imap4_build_folder_info (CamelStore *store, const gchar *top, guint32 flags, GPtrArray *array) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelFolder *folder = (CamelFolder *) engine->folder; - gboolean lsub = (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED); - camel_imap4_list_t *list; - CamelFolderInfo *fi; - gchar *name, *p; - CamelURL *url; - gint i; - - if (array->len == 0) { - g_ptr_array_free (array, TRUE); - return NULL; - } - - g_ptr_array_sort (array, (GCompareFunc) list_sort); - - list_remove_duplicates (array); - list_add_ghosts (array); - - url = camel_url_copy (engine->url); - - if (!strcmp (top, "") && (flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE)) { - /* clear the folder-info cache */ - camel_store_summary_clear ((CamelStoreSummary *) ((CamelIMAP4Store *) store)->summary); - } - - for (i = 0; i < array->len; i++) { - list = array->pdata[i]; - fi = camel_folder_info_new (); - - p = name = camel_utf7_utf8 (list->name); - while (*p != '\0') { - if (*p == list->delim) - *p = '/'; - p++; - } - - p = strrchr (name, '/'); - camel_url_set_fragment (url, name); - - fi->full_name = name; - fi->name = g_strdup (p ? p + 1: name); - fi->uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - fi->flags = list->flags | (lsub ? CAMEL_FOLDER_SUBSCRIBED : 0); - fi->unread = -1; - fi->total = -1; - - if (!g_ascii_strcasecmp (fi->full_name, "INBOX")) - fi->flags |= CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_TYPE_INBOX; - - /* SELECTED folder, just get it from the folder */ - if (folder && !strcmp (folder->full_name, fi->full_name)) { - camel_object_get (folder, NULL, CAMEL_FOLDER_TOTAL, &fi->total, CAMEL_FOLDER_UNREAD, &fi->unread, 0); - } else if (!(flags & CAMEL_STORE_FOLDER_INFO_FAST)) { - imap4_status (store, fi); - } - - if (!(fi->flags & CAMEL_FOLDER_SUBSCRIBED)) - imap4_subscription_info (store, fi); - - array->pdata[i] = fi; - - camel_imap4_store_summary_note_info (((CamelIMAP4Store *) store)->summary, fi); - - if (!g_ascii_strcasecmp (fi->full_name, "INBOX")) { - g_free (fi->name); - fi->name = g_strdup (_("Inbox")); - } - - g_free (list->name); - g_free (list); - } - - fi = camel_imap4_build_folder_info_tree (array, top); - - camel_url_free (url); - - g_ptr_array_free (array, TRUE); - - camel_store_summary_save ((CamelStoreSummary *) ((CamelIMAP4Store *) store)->summary); - - return fi; -} - -static CamelFolderInfo * -imap4_get_folder_info (CamelStore *store, const gchar *top, guint32 flags, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelIMAP4Command *ic, *ic0 = NULL, *ic1 = NULL; - CamelFolderInfo *inbox = NULL, *fi = NULL; - const gchar *base, *namespace; - camel_imap4_list_t *list; - GPtrArray *array; - const gchar *cmd; - gchar *pattern; - gchar wildcard; - gint id, i; - - if (top == NULL) - top = ""; - - if (!(namespace = camel_url_get_param (((CamelService *) store)->url, "namespace"))) - namespace = ""; - - if (!strcmp (top, "")) - base = namespace; - else - base = top; - - CAMEL_SERVICE_REC_LOCK (store, connect_lock); - -#ifdef USE_FOLDER_INFO_CACHE_LOGIC_FOR_SPEED - if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL - || engine->state == CAMEL_IMAP4_ENGINE_DISCONNECTED) { - fi = camel_imap4_store_summary_get_folder_info (((CamelIMAP4Store *) store)->summary, base, flags); - if (base == namespace && *namespace) { - inbox = camel_imap4_store_summary_get_folder_info (((CamelIMAP4Store *) store)->summary, "INBOX", - flags & ~CAMEL_STORE_FOLDER_INFO_RECURSIVE); - if (inbox) { - inbox->next = fi; - fi = inbox; - } - } - - if (fi == NULL && ((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_AVAIL) { - /* folder info hasn't yet been cached and the store hasn't been - * connected yet, but the network is available so we can connect - * and query the server. */ - goto check_online; - } - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); - return fi; - } -#else - /* this is the way the old imap code was meant to work (except it was broken and disregarded the - * NETWORK_UNAVAIL state and went online anyway if fi was NULL, but we won't be evil like that) - */ - if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) { - fi = camel_imap4_store_summary_get_folder_info (((CamelIMAP4Store *) store)->summary, base, flags); - if (base == namespace && *namespace) { - inbox = camel_imap4_store_summary_get_folder_info (((CamelIMAP4Store *) store)->summary, "INBOX", - flags & ~CAMEL_STORE_FOLDER_INFO_RECURSIVE); - if (inbox) { - inbox->next = fi; - fi = inbox; - } - } - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); - return fi; - } -#endif - -#ifdef USE_FOLDER_INFO_CACHE_LOGIC_FOR_SPEED - check_online: -#endif - - if (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) - cmd = "LSUB"; - else - cmd = "LIST"; - - wildcard = (flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) ? '*' : '%'; - pattern = imap4_folder_utf7_name (store, base, wildcard); - array = g_ptr_array_new (); - - if (base == namespace && *namespace) { - /* Make sure to get INBOX: we always use LIST so the user sees his/her INBOX even - if it isn't subscribed and the user has enabled "Only show subscribed folders" */ - ic1 = camel_imap4_engine_queue (engine, NULL, "LIST \"\" INBOX\r\n"); - camel_imap4_command_register_untagged (ic1, "LIST", camel_imap4_untagged_list); - ic1->user_data = array; - } - - if (*top != '\0') { - gsize len; - gchar sep; - - len = strlen (pattern); - sep = pattern[len - 2]; - pattern[len - 2] = '\0'; - - ic0 = camel_imap4_engine_queue (engine, NULL, "%s \"\" %S\r\n", cmd, pattern); - camel_imap4_command_register_untagged (ic0, cmd, camel_imap4_untagged_list); - ic0->user_data = array; - - pattern[len - 2] = sep; - } - - ic = camel_imap4_engine_queue (engine, NULL, "%s \"\" %S\r\n", cmd, pattern); - camel_imap4_command_register_untagged (ic, cmd, camel_imap4_untagged_list); - ic->user_data = array; - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - if (ic1 && ic1->status != CAMEL_IMAP4_COMMAND_COMPLETE) - camel_exception_xfer (ex, &ic1->ex); - else if (ic0 && ic0->status != CAMEL_IMAP4_COMMAND_COMPLETE) - camel_exception_xfer (ex, &ic0->ex); - else - camel_exception_xfer (ex, &ic->ex); - - if (ic1 != NULL) - camel_imap4_command_unref (ic1); - - if (ic0 != NULL) - camel_imap4_command_unref (ic0); - - camel_imap4_command_unref (ic); - - for (i = 0; i < array->len; i++) { - list = array->pdata[i]; - g_free (list->name); - g_free (list); - } - - g_ptr_array_free (array, TRUE); - g_free (pattern); - - goto done; - } - - if (ic1 != NULL) - camel_imap4_command_unref (ic1); - - if (ic0 != NULL) - camel_imap4_command_unref (ic0); - - if (ic->result != CAMEL_IMAP4_RESULT_OK) { - camel_imap4_command_unref (ic); - - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - /* Translators: the first %s is an IMAP4 command, either LSUB or LIST. - * The fourth one is an error message. */ - _("Cannot get %s information for pattern '%s' on IMAP server %s: %s"), - cmd, pattern, engine->url->host, ic->result == CAMEL_IMAP4_RESULT_BAD ? - _("Bad command") : _("Unknown error")); - - for (i = 0; i < array->len; i++) { - list = array->pdata[i]; - g_free (list->name); - g_free (list); - } - - g_ptr_array_free (array, TRUE); - - g_free (pattern); - - goto done; - } - - g_free (pattern); - - fi = imap4_build_folder_info (store, top, flags, array); - - done: - - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); - - return fi; -} - -static void -imap4_free_folder_info (CamelStore *store, CamelFolderInfo *fi) -{ - camel_folder_info_free (fi); -} - -static gboolean -imap4_folder_subscribed (CamelStore *store, const gchar *folder_name) -{ - CamelIMAP4Store *imap4_store = (CamelIMAP4Store *) store; - CamelStoreInfo *si; - gint truth = FALSE; - - if ((si = camel_store_summary_path ((CamelStoreSummary *) imap4_store->summary, folder_name))) { - truth = (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) != 0; - camel_store_summary_info_free ((CamelStoreSummary *) imap4_store->summary, si); - } - - return truth; -} - -static void -imap4_subscribe_folder (CamelStore *store, const gchar *folder_name, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelIMAP4Command *ic; - CamelFolderInfo *fi; - gchar *utf7_name; - CamelURL *url; - const gchar *p; - gint id; - - if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot subscribe to IMAP folders in offline mode.")); - return; - } - - CAMEL_SERVICE_REC_LOCK (store, connect_lock); - - utf7_name = imap4_folder_utf7_name (store, folder_name, '\0'); - ic = camel_imap4_engine_queue (engine, NULL, "SUBSCRIBE %S\r\n", utf7_name); - g_free (utf7_name); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); - return; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - /* subscribed */ - url = camel_url_copy (engine->url); - camel_url_set_fragment (url, folder_name); - - p = strrchr (folder_name, '/'); - - fi = camel_folder_info_new (); - fi->full_name = g_strdup (folder_name); - fi->name = g_strdup (p ? p + 1: folder_name); - fi->uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - camel_url_free (url); - fi->flags = CAMEL_FOLDER_NOCHILDREN; - fi->unread = -1; - fi->total = -1; - - camel_imap4_store_summary_note_info (((CamelIMAP4Store *) store)->summary, fi); - - camel_object_trigger_event (store, "folder_subscribed", fi); - camel_folder_info_free (fi); - break; - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot subscribe to folder '%s': Invalid mailbox name"), - folder_name); - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot subscribe to folder '%s': Bad command"), - folder_name); - break; - } - - camel_imap4_command_unref (ic); - - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); -} - -static void -imap4_unsubscribe_folder (CamelStore *store, const gchar *folder_name, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelIMAP4Command *ic; - CamelFolderInfo *fi; - gchar *utf7_name; - CamelURL *url; - const gchar *p; - gint id; - - if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot unsubscribe from IMAP folders in offline mode.")); - return; - } - - CAMEL_SERVICE_REC_LOCK (store, connect_lock); - - utf7_name = imap4_folder_utf7_name (store, folder_name, '\0'); - ic = camel_imap4_engine_queue (engine, NULL, "UNSUBSCRIBE %S\r\n", utf7_name); - g_free (utf7_name); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); - return; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - /* unsubscribed */ - url = camel_url_copy (engine->url); - camel_url_set_fragment (url, folder_name); - - p = strrchr (folder_name, '/'); - - fi = camel_folder_info_new (); - fi->full_name = g_strdup (folder_name); - fi->name = g_strdup (p ? p + 1: folder_name); - fi->uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - camel_url_free (url); - fi->flags = 0; - fi->unread = -1; - fi->total = -1; - - camel_imap4_store_summary_unnote_info (((CamelIMAP4Store *) store)->summary, fi); - - camel_object_trigger_event (store, "folder_unsubscribed", fi); - camel_folder_info_free (fi); - break; - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot unsubscribe from folder '%s': Invalid mailbox name"), - folder_name); - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot unsubscribe from folder '%s': Bad command"), - folder_name); - break; - } - - camel_imap4_command_unref (ic); - - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); -} - -static void -imap4_noop (CamelStore *store, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelFolder *folder = (CamelFolder *) engine->folder; - CamelIMAP4Command *ic; - gint id; - - if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) - return; - - CAMEL_SERVICE_REC_LOCK (store, connect_lock); - - if (folder) { - camel_folder_sync (folder, FALSE, ex); - if (camel_exception_is_set (ex)) { - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); - return; - } - } - - ic = camel_imap4_engine_queue (engine, NULL, "NOOP\r\n"); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) - camel_exception_xfer (ex, &ic->ex); - - camel_imap4_command_unref (ic); - - if (folder && !camel_exception_is_set (ex)) - camel_imap4_summary_flush_updates (folder->summary, ex); - - CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); -} diff --git a/camel/providers/imap4/camel-imap4-store.h b/camel/providers/imap4/camel-imap4-store.h deleted file mode 100644 index 21e7036..0000000 --- a/camel/providers/imap4/camel-imap4-store.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef CAMEL_IMAP4_STORE_H -#define CAMEL_IMAP4_STORE_H - -#include - -#define CAMEL_TYPE_IMAP4_STORE (camel_imap4_store_get_type ()) -#define CAMEL_IMAP4_STORE(obj) (CAMEL_CHECK_CAST ((obj), CAMEL_TYPE_IMAP4_STORE, CamelIMAP4Store)) -#define CAMEL_IMAP4_STORE_CLASS(klass) (CAMEL_CHECK_CLASS_CAST ((klass), CAMEL_TYPE_IMAP4_STORE, CamelIMAP4StoreClass)) -#define CAMEL_IS_IMAP4_STORE(obj) (CAMEL_CHECK_TYPE ((obj), CAMEL_TYPE_IMAP4_STORE)) -#define CAMEL_IS_IMAP4_STORE_CLASS(klass) (CAMEL_CHECK_CLASS_TYPE ((klass), CAMEL_TYPE_IMAP4_STORE)) -#define CAMEL_IMAP4_STORE_GET_CLASS(obj) (CAMEL_CHECK_GET_CLASS ((obj), CAMEL_TYPE_IMAP4_STORE, CamelIMAP4StoreClass)) - -G_BEGIN_DECLS - -typedef struct _CamelIMAP4Store CamelIMAP4Store; -typedef struct _CamelIMAP4StoreClass CamelIMAP4StoreClass; - -struct _CamelIMAP4Engine; - -struct _CamelIMAP4Store { - CamelOfflineStore parent; - - struct _CamelIMAP4StoreSummary *summary; - struct _CamelIMAP4Engine *engine; - gchar *storage_path; -}; - -struct _CamelIMAP4StoreClass { - CamelOfflineStoreClass parent_class; - -}; - -CamelType camel_imap4_store_get_type (void); - -G_END_DECLS - -#endif /* CAMEL_IMAP4_STORE_H */ diff --git a/camel/providers/imap4/camel-imap4-stream.c b/camel/providers/imap4/camel-imap4-stream.c deleted file mode 100644 index a460455..0000000 --- a/camel/providers/imap4/camel-imap4-stream.c +++ /dev/null @@ -1,723 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include - -#include "camel-imap4-specials.h" -#include "camel-imap4-stream.h" - -#define d(x) (camel_debug ("imap4:stream") ? (x) : 0) - -#define IMAP4_TOKEN_LEN 128 - -static void camel_imap4_stream_class_init (CamelIMAP4StreamClass *klass); -static void camel_imap4_stream_init (CamelIMAP4Stream *stream, CamelIMAP4StreamClass *klass); -static void camel_imap4_stream_finalize (CamelObject *object); - -static gssize stream_read (CamelStream *stream, gchar *buffer, gsize n); -static gssize stream_write (CamelStream *stream, const gchar *buffer, gsize n); -static gint stream_flush (CamelStream *stream); -static gint stream_close (CamelStream *stream); -static gboolean stream_eos (CamelStream *stream); - -static CamelStreamClass *parent_class = NULL; - -CamelType -camel_imap4_stream_get_type (void) -{ - static CamelType type = 0; - - if (!type) { - type = camel_type_register (CAMEL_STREAM_TYPE, - "CamelIMAP4Stream", - sizeof (CamelIMAP4Stream), - sizeof (CamelIMAP4StreamClass), - (CamelObjectClassInitFunc) camel_imap4_stream_class_init, - NULL, - (CamelObjectInitFunc) camel_imap4_stream_init, - (CamelObjectFinalizeFunc) camel_imap4_stream_finalize); - } - - return type; -} - -static void -camel_imap4_stream_class_init (CamelIMAP4StreamClass *klass) -{ - CamelStreamClass *stream_class = (CamelStreamClass *) klass; - - parent_class = (CamelStreamClass *) camel_type_get_global_classfuncs (CAMEL_STREAM_TYPE); - - /* virtual method overload */ - stream_class->read = stream_read; - stream_class->write = stream_write; - stream_class->flush = stream_flush; - stream_class->close = stream_close; - stream_class->eos = stream_eos; -} - -static void -camel_imap4_stream_init (CamelIMAP4Stream *imap4, CamelIMAP4StreamClass *klass) -{ - imap4->stream = NULL; - - imap4->mode = CAMEL_IMAP4_STREAM_MODE_TOKEN; - imap4->disconnected = FALSE; - imap4->have_unget = FALSE; - imap4->eol = FALSE; - - imap4->literal = 0; - - imap4->inbuf = imap4->realbuf + IMAP4_READ_PRELEN; - imap4->inptr = imap4->inbuf; - imap4->inend = imap4->inbuf; - - imap4->tokenbuf = g_malloc (IMAP4_TOKEN_LEN); - imap4->tokenptr = imap4->tokenbuf; - imap4->tokenleft = IMAP4_TOKEN_LEN; -} - -static void -camel_imap4_stream_finalize (CamelObject *object) -{ - CamelIMAP4Stream *imap4 = (CamelIMAP4Stream *) object; - - if (imap4->stream) - camel_object_unref (imap4->stream); - - g_free (imap4->tokenbuf); -} - -static gssize -imap4_fill (CamelIMAP4Stream *imap4) -{ - guchar *inbuf, *inptr, *inend; - gssize nread; - gsize inlen; - - if (imap4->disconnected) { - errno = EINVAL; - return -1; - } - - inbuf = imap4->inbuf; - inptr = imap4->inptr; - inend = imap4->inend; - inlen = inend - inptr; - - g_assert (inptr <= inend); - - /* attempt to align 'inend' with realbuf + SCAN_HEAD */ - if (inptr >= inbuf) { - inbuf -= inlen < IMAP4_READ_PRELEN ? inlen : IMAP4_READ_PRELEN; - memmove (inbuf, inptr, inlen); - inptr = inbuf; - inbuf += inlen; - } else if (inptr > imap4->realbuf) { - gsize shift; - - shift = MIN (inptr - imap4->realbuf, inend - inbuf); - memmove (inptr - shift, inptr, inlen); - inptr -= shift; - inbuf = inptr + inlen; - } else { - /* we can't shift... */ - inbuf = inend; - } - - imap4->inptr = inptr; - imap4->inend = inbuf; - inend = imap4->realbuf + IMAP4_READ_PRELEN + IMAP4_READ_BUFLEN - 1; - - if ((nread = camel_stream_read (imap4->stream, inbuf, inend - inbuf)) == -1) - return -1; - else if (nread == 0) - imap4->disconnected = TRUE; - - imap4->inend += nread; - - return imap4->inend - imap4->inptr; -} - -static gssize -stream_read (CamelStream *stream, gchar *buffer, gsize n) -{ - CamelIMAP4Stream *imap4 = (CamelIMAP4Stream *) stream; - gssize len, nread = 0; - - if (imap4->mode == CAMEL_IMAP4_STREAM_MODE_LITERAL) { - /* don't let our caller read past the end of the literal */ - n = MIN (n, imap4->literal); - } - - if (imap4->inptr < imap4->inend) { - len = MIN (n, imap4->inend - imap4->inptr); - memcpy (buffer, imap4->inptr, len); - imap4->inptr += len; - nread = len; - } - - if (nread < n) { - if ((len = camel_stream_read (imap4->stream, buffer + nread, n - nread)) == 0) - imap4->disconnected = TRUE; - else if (len == -1) - return -1; - - nread += len; - } - - if (imap4->mode == CAMEL_IMAP4_STREAM_MODE_LITERAL) { - imap4->literal -= nread; - - if (imap4->literal == 0) { - imap4->mode = CAMEL_IMAP4_STREAM_MODE_TOKEN; - imap4->eol = TRUE; - } - } - - return nread; -} - -static gssize -stream_write (CamelStream *stream, const gchar *buffer, gsize n) -{ - CamelIMAP4Stream *imap4 = (CamelIMAP4Stream *) stream; - gssize nwritten; - - if (imap4->disconnected) { - errno = EINVAL; - return -1; - } - - if ((nwritten = camel_stream_write (imap4->stream, buffer, n)) == 0) - imap4->disconnected = TRUE; - - return nwritten; -} - -static gint -stream_flush (CamelStream *stream) -{ - CamelIMAP4Stream *imap4 = (CamelIMAP4Stream *) stream; - - return camel_stream_flush (imap4->stream); -} - -static gint -stream_close (CamelStream *stream) -{ - CamelIMAP4Stream *imap4 = (CamelIMAP4Stream *) stream; - - if (camel_stream_close (imap4->stream) == -1) - return -1; - - camel_object_unref (imap4->stream); - imap4->stream = NULL; - - imap4->disconnected = TRUE; - - return 0; -} - -static gboolean -stream_eos (CamelStream *stream) -{ - CamelIMAP4Stream *imap4 = (CamelIMAP4Stream *) stream; - - if (imap4->eol) - return TRUE; - - if (imap4->disconnected && imap4->inptr == imap4->inend) - return TRUE; - - if (camel_stream_eos (imap4->stream)) - return TRUE; - - return FALSE; -} - -/** - * camel_imap4_stream_new: - * @stream: tcp stream - * - * Returns: a new imap4 stream - **/ -CamelStream * -camel_imap4_stream_new (CamelStream *stream) -{ - CamelIMAP4Stream *imap4; - - g_return_val_if_fail (CAMEL_IS_STREAM (stream), NULL); - - imap4 = (CamelIMAP4Stream *) camel_object_new (CAMEL_TYPE_IMAP4_STREAM); - camel_object_ref (stream); - imap4->stream = stream; - - return (CamelStream *) imap4; -} - -#define token_save(imap4, start, len) G_STMT_START { \ - if (imap4->tokenleft <= len) { \ - guint tlen, toff; \ - \ - tlen = toff = imap4->tokenptr - imap4->tokenbuf; \ - tlen = tlen ? tlen : 1; \ - \ - while (tlen < toff + len) \ - tlen <<= 1; \ - \ - imap4->tokenbuf = g_realloc (imap4->tokenbuf, tlen + 1); \ - imap4->tokenptr = imap4->tokenbuf + toff; \ - imap4->tokenleft = tlen - toff; \ - } \ - \ - memcpy (imap4->tokenptr, start, len); \ - imap4->tokenptr += len; \ - imap4->tokenleft -= len; \ -} G_STMT_END - -#define token_clear(imap4) G_STMT_START { \ - imap4->tokenleft += imap4->tokenptr - imap4->tokenbuf; \ - imap4->tokenptr = imap4->tokenbuf; \ - imap4->literal = 0; \ -} G_STMT_END - -/** - * camel_imap4_stream_next_token: - * @stream: imap4 stream - * @token: imap4 token - * - * Reads the next token from the imap4 stream and saves it in @token. - * - * Returns: 0 on success or -1 on fail. - **/ -gint -camel_imap4_stream_next_token (CamelIMAP4Stream *stream, camel_imap4_token_t *token) -{ - register guchar *inptr; - guchar *inend, *start, *p; - gboolean escaped = FALSE; - gsize literal = 0; - guint32 nz_number; - gint ret; - - g_return_val_if_fail (CAMEL_IS_IMAP4_STREAM (stream), -1); - g_return_val_if_fail (stream->mode != CAMEL_IMAP4_STREAM_MODE_LITERAL, -1); - g_return_val_if_fail (token != NULL, -1); - - if (stream->have_unget) { - memcpy (token, &stream->unget, sizeof (camel_imap4_token_t)); - stream->have_unget = FALSE; - return 0; - } - - token_clear (stream); - - inptr = stream->inptr; - inend = stream->inend; - *inend = '\0'; - - do { - if (inptr == inend) { - if ((ret = imap4_fill (stream)) < 0) { - token->token = CAMEL_IMAP4_TOKEN_ERROR; - return -1; - } else if (ret == 0) { - token->token = CAMEL_IMAP4_TOKEN_NO_DATA; - return 0; - } - - inptr = stream->inptr; - inend = stream->inend; - *inend = '\0'; - } - - while (*inptr == ' ' || *inptr == '\r') - inptr++; - } while (inptr == inend); - - do { - if (inptr < inend) { - if (*inptr == '"') { - /* qstring token */ - escaped = FALSE; - start = inptr; - - /* eat the beginning " */ - inptr++; - - p = inptr; - while (inptr < inend) { - if (*inptr == '"' && !escaped) - break; - - if (*inptr == '\\' && !escaped) { - token_save (stream, p, inptr - p); - escaped = TRUE; - inptr++; - p = inptr; - } else { - inptr++; - escaped = FALSE; - } - } - - token_save (stream, p, inptr - p); - - if (inptr == inend) { - stream->inptr = start; - goto refill; - } - - /* eat the ending " */ - inptr++; - - /* nul-terminate the atom token */ - token_save (stream, "", 1); - - token->token = CAMEL_IMAP4_TOKEN_QSTRING; - token->v.qstring = stream->tokenbuf; - - d(fprintf (stderr, "token: \"%s\"\n", token->v.qstring)); - - break; - } else if (strchr ("+*()[]\n", *inptr)) { - /* special character token */ - token->token = *inptr++; - - if (camel_debug ("imap4:stream")) { - if (token->token != '\n') - fprintf (stderr, "token: %c\n", token->token); - else - fprintf (stderr, "token: \\n\n"); - } - - break; - } else if (*inptr == '{') { - /* literal identifier token */ - if ((p = strchr (inptr, '}')) && strchr (p, '\n')) { - inptr++; - - while (isdigit ((gint) *inptr) && literal < UINT_MAX / 10) - literal = (literal * 10) + (*inptr++ - '0'); - - if (*inptr != '}') { - if (isdigit ((gint) *inptr)) - g_warning ("illegal literal identifier: literal too large"); - else if (*inptr != '+') - g_warning ("illegal literal identifier: garbage following size"); - - while (*inptr != '}') - inptr++; - } - - /* skip over '}' */ - inptr++; - - /* skip over any trailing whitespace */ - while (*inptr == ' ' || *inptr == '\r') - inptr++; - - if (*inptr != '\n') { - g_warning ("illegal token following literal identifier: %s", inptr); - - /* skip ahead to the eoln */ - if (!(inptr = strchr (inptr, '\n'))) { - stream->inptr = start; - goto refill; - } - } - - /* skip over '\n' */ - inptr++; - - token->token = CAMEL_IMAP4_TOKEN_LITERAL; - token->v.literal = literal; - - d(fprintf (stderr, "token: {%u}\n", literal)); - - stream->mode = CAMEL_IMAP4_STREAM_MODE_LITERAL; - stream->literal = literal; - stream->eol = FALSE; - - break; - } else { - stream->inptr = inptr; - goto refill; - } - } else if (*inptr >= '0' && *inptr <= '9') { - /* number token */ - *inend = '\0'; - nz_number = strtoul ((gchar *) inptr, (gchar **) &start, 10); - if (start == inend) - goto refill; - - if (*start == ':' || *start == ',') { - /* workaround for 'set' tokens (APPENDUID / COPYUID) */ - goto atom_token; - } - - inptr = start; - token->token = CAMEL_IMAP4_TOKEN_NUMBER; - token->v.number = nz_number; - - d(fprintf (stderr, "token: %u\n", nz_number)); - - break; - } else if (is_atom (*inptr)) { - atom_token: - /* simple atom token */ - start = inptr; - - while (inptr < inend && is_atom (*inptr)) - inptr++; - - if (inptr == inend) { - stream->inptr = start; - goto refill; - } - - token_save (stream, start, inptr - start); - - /* nul-terminate the atom token */ - token_save (stream, "", 1); - - if (!strcmp (stream->tokenbuf, "NIL")) { - /* special atom token */ - token->token = CAMEL_IMAP4_TOKEN_NIL; - d(fprintf (stderr, "token: NIL\n")); - } else { - token->token = CAMEL_IMAP4_TOKEN_ATOM; - token->v.atom = stream->tokenbuf; - d(fprintf (stderr, "token: %s\n", token->v.atom)); - } - - break; - } else if (*inptr == '\\') { - /* possible flag token ("\" atom) */ - start = inptr++; - - while (inptr < inend && is_atom (*inptr)) - inptr++; - - if (inptr == inend) { - stream->inptr = start; - goto refill; - } - - /* handle the \* case */ - if ((inptr - start) == 1 && *inptr == '*') - inptr++; - - if ((inptr - start) > 1) { - token_save (stream, start, inptr - start); - - /* nul-terminate the flag token */ - token_save (stream, "", 1); - - token->token = CAMEL_IMAP4_TOKEN_FLAG; - token->v.atom = stream->tokenbuf; - d(fprintf (stderr, "token: %s\n", token->v.atom)); - } else { - token->token = '\\'; - d(fprintf (stderr, "token: %c\n", token->token)); - } - break; - } else if (is_lwsp (*inptr)) { - inptr++; - } else { - /* unknown character token? */ - token->token = *inptr++; - d(fprintf (stderr, "token: %c\n", token->token)); - break; - } - } else { - refill: - token_clear (stream); - - if (imap4_fill (stream) <= 0) { - token->token = CAMEL_IMAP4_TOKEN_ERROR; - return -1; - } - - inptr = stream->inptr; - inend = stream->inend; - *inend = '\0'; - } - } while (inptr < inend); - - stream->inptr = inptr; - - return 0; -} - -/** - * camel_imap4_stream_unget_token: - * @stream: imap4 stream - * @token: token to 'unget' - * - * Ungets an imap4 token (as in ungetc()). - * - * Note: you may *ONLY* unget a single token. Trying to unget another - * token will fail. - * - * Returns: 0 on success or -1 on fail. - **/ -gint -camel_imap4_stream_unget_token (CamelIMAP4Stream *stream, camel_imap4_token_t *token) -{ - if (stream->have_unget) - return -1; - - if (token->token != CAMEL_IMAP4_TOKEN_NO_DATA) { - memcpy (&stream->unget, token, sizeof (camel_imap4_token_t)); - stream->have_unget = TRUE; - } - - return 0; -} - -/** - * camel_imap4_stream_line: - * @stream: imap4 stream - * @line: line pointer - * @len: line length - * - * Reads a single line from the imap4 stream and points @line at an - * internal buffer containing the line read and sets @len to the - * length of the line buffer. - * - * Returns: -1 on error, 0 if the line read is complete, or 1 if the - * read is incomplete. - **/ -gint -camel_imap4_stream_line (CamelIMAP4Stream *stream, guchar **line, gsize *len) -{ - register guchar *inptr; - guchar *inend; - - g_return_val_if_fail (CAMEL_IS_IMAP4_STREAM (stream), -1); - g_return_val_if_fail (stream->mode != CAMEL_IMAP4_STREAM_MODE_LITERAL, -1); - g_return_val_if_fail (line != NULL, -1); - g_return_val_if_fail (len != NULL, -1); - - inptr = stream->inptr; - inend = stream->inend; - - *inend = '\0'; - if (inptr == inend || ((inend - inptr) < 2 && *inptr != '\n')) { - if (imap4_fill (stream) == -1 && stream->inptr == stream->inend) - return -1; - } - - *line = stream->inptr; - inptr = stream->inptr; - inend = stream->inend; - *inend = '\n'; - - while (*inptr != '\n') - inptr++; - - *len = (inptr - stream->inptr); - - if (inptr > stream->inptr && inptr[-1] == '\r') - inptr[-1] = '\0'; - - if (inptr < inend) { - /* got the eoln */ - inptr[0] = '\0'; - *len += 1; - - stream->inptr = inptr + 1; - - return 0; - } - - stream->inptr = inptr; - - return 1; -} - -/** - * camel_imap4_stream_literal: - * @stream: IMAP stream - * @literal: literal pointer - * @len: literal length - * - * Sets @literal to the beginning of the next chunk of the literal - * buffer from the IMAP stream and sets @len to the length of the - * @literal buffer. - * - * Returns: >0 if more literal data exists, 0 if the end of the literal - * has been reached or -1 on fail. - **/ -gint -camel_imap4_stream_literal (CamelIMAP4Stream *stream, guchar **literal, gsize *len) -{ - guchar *inptr, *inend; - gsize nread; - - g_return_val_if_fail (CAMEL_IS_IMAP4_STREAM (stream), -1); - g_return_val_if_fail (stream->mode == CAMEL_IMAP4_STREAM_MODE_LITERAL, -1); - g_return_val_if_fail (literal != NULL, -1); - g_return_val_if_fail (len != NULL, -1); - - if (stream->eol) { - *len = 0; - return 0; - } - - if ((stream->inend - stream->inptr) < 1) { - /* keep our buffer full to the optimal size */ - if (imap4_fill (stream) == -1 && stream->inptr == stream->inend) - return -1; - } - - *literal = inptr = stream->inptr; - inend = stream->inend; - if ((inend - inptr) > stream->literal) - inend = inptr + stream->literal; - else - inend = stream->inend; - - *len = nread = inend - inptr; - - stream->literal -= nread; - stream->inptr += nread; - - if (stream->literal == 0) { - stream->mode = CAMEL_IMAP4_STREAM_MODE_TOKEN; - stream->eol = TRUE; - return 0; - } - - return 1; -} diff --git a/camel/providers/imap4/camel-imap4-stream.h b/camel/providers/imap4/camel-imap4-stream.h deleted file mode 100644 index eb7c048..0000000 --- a/camel/providers/imap4/camel-imap4-stream.h +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef CAMEL_IMAP4_STREAM_H -#define CAMEL_IMAP4_STREAM_H - -#include - -#define CAMEL_TYPE_IMAP4_STREAM (camel_imap4_stream_get_type ()) -#define CAMEL_IMAP4_STREAM(obj) (CAMEL_CHECK_CAST ((obj), CAMEL_TYPE_IMAP4_STREAM, CamelIMAP4Stream)) -#define CAMEL_IMAP4_STREAM_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_TYPE_IMAP4_STREAM, CamelIMAP4StreamClass)) -#define CAMEL_IS_IMAP4_STREAM(o) (CAMEL_CHECK_TYPE((o), CAMEL_TYPE_IMAP4_STREAM)) - -#define IMAP4_READ_PRELEN 128 -#define IMAP4_READ_BUFLEN 4096 - -G_BEGIN_DECLS - -typedef struct _CamelIMAP4Stream CamelIMAP4Stream; -typedef struct _CamelIMAP4StreamClass CamelIMAP4StreamClass; - -enum { - CAMEL_IMAP4_TOKEN_NO_DATA = -8, - CAMEL_IMAP4_TOKEN_ERROR = -7, - CAMEL_IMAP4_TOKEN_NIL = -6, - CAMEL_IMAP4_TOKEN_ATOM = -5, - CAMEL_IMAP4_TOKEN_FLAG = -4, - CAMEL_IMAP4_TOKEN_NUMBER = -3, - CAMEL_IMAP4_TOKEN_QSTRING = -2, - CAMEL_IMAP4_TOKEN_LITERAL = -1, - /* CAMEL_IMAP4_TOKEN_CHAR would just be the gchar we got */ - CAMEL_IMAP4_TOKEN_EOLN = '\n', - CAMEL_IMAP4_TOKEN_LPAREN = '(', - CAMEL_IMAP4_TOKEN_RPAREN = ')', - CAMEL_IMAP4_TOKEN_ASTERISK = '*', - CAMEL_IMAP4_TOKEN_PLUS = '+', - CAMEL_IMAP4_TOKEN_LBRACKET = '[', - CAMEL_IMAP4_TOKEN_RBRACKET = ']', -}; - -typedef struct _camel_imap4_token_t { - gint token; - union { - gchar *atom; - gchar *flag; - gchar *qstring; - gsize literal; - guint32 number; - } v; -} camel_imap4_token_t; - -enum { - CAMEL_IMAP4_STREAM_MODE_TOKEN = 0, - CAMEL_IMAP4_STREAM_MODE_LITERAL = 1, -}; - -struct _CamelIMAP4Stream { - CamelStream parent; - - CamelStream *stream; - - guint disconnected:1; /* disconnected state */ - guint have_unget:1; /* have an unget token */ - guint mode:1; /* TOKEN vs LITERAL */ - guint eol:1; /* end-of-literal */ - - gsize literal; - - /* i/o buffers */ - guchar realbuf[IMAP4_READ_PRELEN + IMAP4_READ_BUFLEN + 1]; - guchar *inbuf; - guchar *inptr; - guchar *inend; - - /* token buffers */ - guchar *tokenbuf; - guchar *tokenptr; - guint tokenleft; - - camel_imap4_token_t unget; -}; - -struct _CamelIMAP4StreamClass { - CamelStreamClass parent_class; - - /* Virtual methods */ -}; - -/* Standard Camel function */ -CamelType camel_imap4_stream_get_type (void); - -CamelStream *camel_imap4_stream_new (CamelStream *stream); - -gint camel_imap4_stream_next_token (CamelIMAP4Stream *stream, camel_imap4_token_t *token); -gint camel_imap4_stream_unget_token (CamelIMAP4Stream *stream, camel_imap4_token_t *token); - -gint camel_imap4_stream_line (CamelIMAP4Stream *stream, guchar **line, gsize *len); -gint camel_imap4_stream_literal (CamelIMAP4Stream *stream, guchar **literal, gsize *len); - -G_END_DECLS - -#endif /* CAMEL_IMAP4_STREAM_H */ diff --git a/camel/providers/imap4/camel-imap4-summary.c b/camel/providers/imap4/camel-imap4-summary.c deleted file mode 100644 index 9ab9202..0000000 --- a/camel/providers/imap4/camel-imap4-summary.c +++ /dev/null @@ -1,1662 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include - -#include "camel-imap4-command.h" -#include "camel-imap4-engine.h" -#include "camel-imap4-folder.h" -#include "camel-imap4-journal.h" -#include "camel-imap4-store.h" -#include "camel-imap4-stream.h" -#include "camel-imap4-summary.h" -#include "camel-imap4-utils.h" - -#define d(x) - -#define CAMEL_IMAP4_SUMMARY_VERSION 3 - -#define IMAP_SAVE_INCREMENT 1024 - -static void camel_imap4_summary_class_init (CamelIMAP4SummaryClass *klass); -static void camel_imap4_summary_init (CamelIMAP4Summary *summary, CamelIMAP4SummaryClass *klass); -static void camel_imap4_summary_finalize (CamelObject *object); - -static gint imap4_header_load (CamelFolderSummary *summary, FILE *fin); -static gint imap4_header_save (CamelFolderSummary *summary, FILE *fout); -static CamelMessageInfo *imap4_message_info_new_from_header (CamelFolderSummary *summary, struct _camel_header_raw *header); -static CamelMessageInfo *imap4_message_info_load (CamelFolderSummary *summary, FILE *fin); -static gint imap4_message_info_save (CamelFolderSummary *summary, FILE *fout, CamelMessageInfo *info); -static CamelMessageInfo *imap4_message_info_clone (CamelFolderSummary *summary, const CamelMessageInfo *mi); -static CamelMessageContentInfo *imap4_content_info_load (CamelFolderSummary *summary, FILE *in); -static gint imap4_content_info_save (CamelFolderSummary *summary, FILE *out, CamelMessageContentInfo *info); - -static CamelFolderSummaryClass *parent_class = NULL; - -CamelType -camel_imap4_summary_get_type (void) -{ - static CamelType type = 0; - - if (!type) { - type = camel_type_register (CAMEL_FOLDER_SUMMARY_TYPE, - "CamelIMAP4Summary", - sizeof (CamelIMAP4Summary), - sizeof (CamelIMAP4SummaryClass), - (CamelObjectClassInitFunc) camel_imap4_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_imap4_summary_init, - (CamelObjectFinalizeFunc) camel_imap4_summary_finalize); - } - - return type; -} - -static void -camel_imap4_summary_class_init (CamelIMAP4SummaryClass *klass) -{ - CamelFolderSummaryClass *summary_class = (CamelFolderSummaryClass *) klass; - - parent_class = (CamelFolderSummaryClass *) camel_type_get_global_classfuncs (camel_folder_summary_get_type ()); - - summary_class->summary_header_load = imap4_header_load; - summary_class->summary_header_save = imap4_header_save; - summary_class->message_info_new_from_header = imap4_message_info_new_from_header; - summary_class->message_info_load = imap4_message_info_load; - summary_class->message_info_save = imap4_message_info_save; - summary_class->message_info_clone = imap4_message_info_clone; - summary_class->content_info_load = imap4_content_info_load; - summary_class->content_info_save = imap4_content_info_save; -} - -static void -camel_imap4_summary_init (CamelIMAP4Summary *summary, CamelIMAP4SummaryClass *klass) -{ - CamelFolderSummary *folder_summary = (CamelFolderSummary *) summary; - - folder_summary->flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_DELETED | - CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN; - - folder_summary->message_info_size = sizeof (CamelIMAP4MessageInfo); - folder_summary->content_info_size = sizeof (CamelIMAP4MessageContentInfo); - - summary->update_flags = TRUE; - summary->uidvalidity_changed = FALSE; -} - -static void -camel_imap4_summary_finalize (CamelObject *object) -{ -} - -CamelFolderSummary * -camel_imap4_summary_new (CamelFolder *folder) -{ - CamelFolderSummary *summary; - - summary = (CamelFolderSummary *) camel_object_new (CAMEL_TYPE_IMAP4_SUMMARY); - summary->folder = folder; - - return summary; -} - -static gint -imap4_header_load (CamelFolderSummary *summary, FILE *fin) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - - if (CAMEL_FOLDER_SUMMARY_CLASS (parent_class)->summary_header_load (summary, fin) == -1) - return -1; - - if (camel_file_util_decode_fixed_int32 (fin, &imap4_summary->version) == -1) - return -1; - - if (imap4_summary->version > CAMEL_IMAP4_SUMMARY_VERSION) { - g_warning ("Unknown IMAP4 summary version\n"); - errno = EINVAL; - return -1; - } - - if (imap4_summary->version == 2) { - /* check that we have Mailing-List info */ - gint have_mlist; - - if (camel_file_util_decode_fixed_int32 (fin, &have_mlist) == -1) - return -1; - - if (have_mlist) - summary->flags |= CAMEL_IMAP4_SUMMARY_HAVE_MLIST; - else - summary->flags ^= CAMEL_IMAP4_SUMMARY_HAVE_MLIST; - } - - if (camel_file_util_decode_fixed_int32 (fin, &imap4_summary->uidvalidity) == -1) - return -1; - - return 0; -} - -static gint -imap4_header_save (CamelFolderSummary *summary, FILE *fout) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - - if (CAMEL_FOLDER_SUMMARY_CLASS (parent_class)->summary_header_save (summary, fout) == -1) - return -1; - - if (camel_file_util_encode_fixed_int32 (fout, CAMEL_IMAP4_SUMMARY_VERSION) == -1) - return -1; - - if (camel_file_util_encode_fixed_int32 (fout, imap4_summary->uidvalidity) == -1) - return -1; - - return 0; -} - -static gint -envelope_decode_address (CamelIMAP4Engine *engine, GString *addrs, CamelException *ex) -{ - gchar *addr, *name = NULL, *user = NULL; - struct _camel_header_address *cia; - guchar *literal = NULL; - camel_imap4_token_t token; - const gchar *domain = NULL; - gint part = 0; - gsize n; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token == CAMEL_IMAP4_TOKEN_NIL) { - return 0; - } else if (token.token != '(') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - if (addrs->len > 0) - g_string_append (addrs, ", "); - - do { - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - literal = NULL; - switch (token.token) { - case CAMEL_IMAP4_TOKEN_NIL: - break; - case CAMEL_IMAP4_TOKEN_ATOM: - case CAMEL_IMAP4_TOKEN_QSTRING: - switch (part) { - case 0: - name = camel_header_decode_string (token.v.qstring, NULL); - break; - case 2: - user = g_strdup (token.v.qstring); - break; - case 3: - domain = token.v.qstring; - break; - } - break; - case CAMEL_IMAP4_TOKEN_LITERAL: - if (camel_imap4_engine_literal (engine, &literal, &n, ex) == -1) - goto exception; - - switch (part) { - case 0: - name = camel_header_decode_string (literal, NULL); - g_free (literal); - break; - case 2: - user = literal; - break; - case 3: - domain = literal; - break; - } - break; - default: - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - part++; - } while (part < 4); - - addr = g_strdup_printf ("%s@%s", user, domain); - g_free (literal); - g_free (user); - - cia = camel_header_address_new_name (name, addr); - g_free (name); - g_free (addr); - - addr = camel_header_address_list_format (cia); - camel_header_address_unref (cia); - - g_string_append (addrs, addr); - g_free (addr); - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != ')') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - return 0; - - exception: - - g_free (name); - g_free (user); - - return -1; -} - -static gint -envelope_decode_addresses (CamelIMAP4Engine *engine, gchar **addrlist, CamelException *ex) -{ - camel_imap4_token_t token; - GString *addrs; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token == CAMEL_IMAP4_TOKEN_NIL) { - *addrlist = NULL; - return 0; - } else if (token.token != '(') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - addrs = g_string_new (""); - - do { - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) { - g_string_free (addrs, TRUE); - return -1; - } - - if (token.token == '(') { - camel_imap4_stream_unget_token (engine->istream, &token); - - if (envelope_decode_address (engine, addrs, ex) == -1) { - g_string_free (addrs, TRUE); - return -1; - } - } else if (token.token == ')') { - break; - } else { - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - } while (1); - - *addrlist = addrs->str; - g_string_free (addrs, FALSE); - - return 0; -} - -static gint -envelope_decode_date (CamelIMAP4Engine *engine, time_t *date, CamelException *ex) -{ - guchar *literal = NULL; - camel_imap4_token_t token; - const gchar *nstring; - gsize n; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - switch (token.token) { - case CAMEL_IMAP4_TOKEN_NIL: - *date = (time_t) -1; - return 0; - case CAMEL_IMAP4_TOKEN_ATOM: - nstring = token.v.atom; - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - nstring = token.v.qstring; - break; - case CAMEL_IMAP4_TOKEN_LITERAL: - if (camel_imap4_engine_literal (engine, &literal, &n, ex) == -1) - return -1; - - nstring = literal; - break; - default: - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - *date = camel_header_decode_date (nstring, NULL); - - g_free (literal); - - return 0; -} - -static gint -envelope_decode_nstring (CamelIMAP4Engine *engine, gchar **nstring, gboolean rfc2047, CamelException *ex) -{ - camel_imap4_token_t token; - guchar *literal; - gsize n; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - switch (token.token) { - case CAMEL_IMAP4_TOKEN_NIL: - *nstring = NULL; - break; - case CAMEL_IMAP4_TOKEN_ATOM: - if (rfc2047) - *nstring = camel_header_decode_string (token.v.atom, NULL); - else - *nstring = g_strdup (token.v.atom); - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - if (rfc2047) - *nstring = camel_header_decode_string (token.v.qstring, NULL); - else - *nstring = g_strdup (token.v.qstring); - break; - case CAMEL_IMAP4_TOKEN_LITERAL: - if (camel_imap4_engine_literal (engine, &literal, &n, ex) == -1) - return -1; - - if (rfc2047) { - *nstring = camel_header_decode_string (literal, NULL); - g_free (literal); - } else - *nstring = literal; - - break; - default: - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - return 0; -} - -static CamelSummaryReferences * -decode_references (const gchar *refstr, const gchar *irtstr) -{ - struct _camel_header_references *refs, *irt, *r; - CamelSummaryReferences *references; - MD5Context checksum; - guint8 digest[16]; - guint32 i, n; - - refs = camel_header_references_decode (refstr); - irt = camel_header_references_inreplyto_decode (irtstr); - - if (!refs && !irt) - return NULL; - - if (irt) { - /* The References field is populated from the `References' and/or `In-Reply-To' - headers. If both headers exist, take the first thing in the In-Reply-To header - that looks like a Message-ID, and append it to the References header. */ - - if (refs) { - r = irt; - while (r->next != NULL) - r = r->next; - r->next = refs; - } - - refs = irt; - } - - n = camel_header_references_list_size (&refs); - references = g_malloc (sizeof (CamelSummaryReferences) + (sizeof (CamelSummaryMessageID) * (n - 1))); - references->size = n; - - for (i = 0, r = refs; r != NULL; i++, r = r->next) { - md5_init (&checksum); - md5_update (&checksum, (guchar *) r->id, strlen (r->id)); - md5_final (&checksum, digest); - - memcpy (references->references[i].id.hash, digest, sizeof (CamelSummaryMessageID)); - } - - camel_header_references_list_clear (&refs); - - return references; -} - -static gint -decode_envelope (CamelIMAP4Engine *engine, CamelMessageInfo *info, camel_imap4_token_t *token, CamelException *ex) -{ - CamelIMAP4MessageInfo *iinfo = (CamelIMAP4MessageInfo *) info; - gchar *nstring, *msgid; - MD5Context checksum; - guint8 digest[16]; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token != '(') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - return -1; - } - - if (envelope_decode_date (engine, &iinfo->info.date_sent, ex) == -1) - goto exception; - - /* subject */ - if (envelope_decode_nstring (engine, &nstring, TRUE, ex) == -1) - goto exception; - - iinfo->info.subject = camel_pstring_strdup (nstring); - g_free (nstring); - - /* from */ - if (envelope_decode_addresses (engine, &nstring, ex) == -1) - goto exception; - - iinfo->info.from = camel_pstring_strdup (nstring); - g_free (nstring); - - /* sender */ - if (envelope_decode_addresses (engine, &nstring, ex) == -1) - goto exception; - - g_free (nstring); - - /* reply-to */ - if (envelope_decode_addresses (engine, &nstring, ex) == -1) - goto exception; - - g_free (nstring); - - /* to */ - if (envelope_decode_addresses (engine, &nstring, ex) == -1) - goto exception; - - iinfo->info.to = camel_pstring_strdup (nstring); - g_free (nstring); - - /* cc */ - if (envelope_decode_addresses (engine, &nstring, ex) == -1) - goto exception; - - iinfo->info.cc = camel_pstring_strdup (nstring); - g_free (nstring); - - /* bcc */ - if (envelope_decode_addresses (engine, &nstring, ex) == -1) - goto exception; - - g_free (nstring); - - /* in-reply-to */ - if (envelope_decode_nstring (engine, &nstring, FALSE, ex) == -1) - goto exception; - - if (nstring != NULL) { - if (!iinfo->info.references) - iinfo->info.references = decode_references (NULL, nstring); - - g_free (nstring); - } - - /* message-id */ - if (envelope_decode_nstring (engine, &nstring, FALSE, ex) == -1) - goto exception; - - if (nstring != NULL) { - if ((msgid = camel_header_msgid_decode (nstring))) { - md5_init (&checksum); - md5_update (&checksum, (guchar *) msgid, strlen (msgid)); - md5_final (&checksum, digest); - - memcpy (iinfo->info.message_id.id.hash, digest, sizeof (CamelSummaryMessageID)); - g_free (msgid); - } - g_free (nstring); - } - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token != ')') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - goto exception; - } - - return 0; - - exception: - - return -1; -} - -static gchar *tm_months[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -static gboolean -decode_time (const gchar **in, gint *hour, gint *min, gint *sec) -{ - register const guchar *inptr = (const guchar *) *in; - gint *val, colons = 0; - - *hour = *min = *sec = 0; - - val = hour; - for (; *inptr && !isspace ((gint) *inptr); inptr++) { - if (*inptr == ':') { - colons++; - switch (colons) { - case 1: - val = min; - break; - case 2: - val = sec; - break; - default: - return FALSE; - } - } else if (!isdigit ((gint) *inptr)) - return FALSE; - else - *val = (*val * 10) + (*inptr - '0'); - } - - *in = inptr; - - return TRUE; -} - -static time_t -mktime_utc (struct tm *tm) -{ - time_t tt; - - tm->tm_isdst = -1; - tt = mktime (tm); - -#if defined (HAVE_TM_GMTOFF) - tt += tm->tm_gmtoff; -#elif defined (HAVE_TIMEZONE) - if (tm->tm_isdst > 0) { -#if defined (HAVE_ALTZONE) - tt -= altzone; -#else /* !defined (HAVE_ALTZONE) */ - tt -= (timezone - 3600); -#endif - } else - tt -= timezone; -#endif - - return tt; -} - -static time_t -decode_internaldate (const gchar *in) -{ - const gchar *inptr = in; - gint hour, min, sec, n; - struct tm tm; - time_t date; - gchar *buf; - - memset ((gpointer) &tm, 0, sizeof (struct tm)); - - tm.tm_mday = strtoul (inptr, &buf, 10); - if (buf == inptr || *buf != '-') - return (time_t) -1; - - inptr = buf + 1; - if (inptr[3] != '-') - return (time_t) -1; - - for (n = 0; n < 12; n++) { - if (!g_ascii_strncasecmp (inptr, tm_months[n], 3)) - break; - } - - if (n >= 12) - return (time_t) -1; - - tm.tm_mon = n; - - inptr += 4; - - n = strtoul (inptr, &buf, 10); - if (buf == inptr || *buf != ' ') - return (time_t) -1; - - tm.tm_year = n - 1900; - - inptr = buf + 1; - if (!decode_time (&inptr, &hour, &min, &sec)) - return (time_t) -1; - - tm.tm_hour = hour; - tm.tm_min = min; - tm.tm_sec = sec; - - n = strtol (inptr, NULL, 10); - - date = mktime_utc (&tm); - - /* date is now GMT of the time we want, but not offset by the timezone ... */ - - /* this should convert the time to the GMT equiv time */ - date -= ((n / 100) * 60 * 60) + (n % 100) * 60; - - return date; -} - -enum { - IMAP4_FETCH_ENVELOPE = (1 << 0), - IMAP4_FETCH_FLAGS = (1 << 1), - IMAP4_FETCH_INTERNALDATE = (1 << 2), - IMAP4_FETCH_RFC822SIZE = (1 << 3), - IMAP4_FETCH_UID = (1 << 4), - - IMAP4_FETCH_SAVED = (1 << 7), -}; - -#define IMAP4_FETCH_ALL (IMAP4_FETCH_ENVELOPE | IMAP4_FETCH_FLAGS | IMAP4_FETCH_INTERNALDATE | IMAP4_FETCH_RFC822SIZE | IMAP4_FETCH_UID) - -struct imap4_envelope_t { - CamelMessageInfo *info; - guint8 changed; -}; - -struct imap4_fetch_all_t { - CamelFolderChangeInfo *changes; - CamelFolderSummary *summary; - GHashTable *uid_hash; - GPtrArray *added; - guint32 count; - guint32 total; - guint32 first; - guint8 need; - guint8 all; -}; - -static void -imap4_fetch_all_free (struct imap4_fetch_all_t *fetch) -{ - struct imap4_envelope_t *envelope; - gint i; - - for (i = 0; i < fetch->added->len; i++) { - if (!(envelope = fetch->added->pdata[i])) - continue; - - camel_message_info_free (envelope->info); - g_free (envelope); - } - - g_ptr_array_free (fetch->added, TRUE); - g_hash_table_destroy (fetch->uid_hash); - camel_folder_change_info_free (fetch->changes); - g_free (fetch); -} - -static void -courier_imap_show_error (CamelFolderSummary *summary, guint32 msg) -{ - CamelSession *session = ((CamelService *) summary->folder->parent_store)->session; - gchar *warning; - - warning = g_strdup_printf ("IMAP server did not respond with an untagged FETCH response " - "for message #%u. This is illegal according to rfc3501 (and " - "the older rfc2060). You will need to contact your\n" - "Administrator(s) (or ISP) and have them resolve this issue.\n\n" - "Hint: If your IMAP server is Courier-IMAP, it is likely that this " - "message is simply unreadable by the IMAP server and will need " - "to be given read permissions.", msg); - - camel_session_alert_user (session, CAMEL_SESSION_ALERT_WARNING, warning, FALSE); - g_free (warning); -} - -/** - * imap4_fetch_all_add: - * @fetch: FETCH ALL state - * @complete: %TRUE if the FETCH command is complete or %FALSE otherwise - * - * Adds all newly acquired envelopes to the summary. Stops at the - * first incomplete envelope. - **/ -static void -imap4_fetch_all_add (struct imap4_fetch_all_t *fetch, gboolean complete) -{ - struct imap4_envelope_t *envelope; - CamelFolderChangeInfo *changes; - CamelMessageInfo *info; - guint32 i; - - changes = fetch->changes; - - for (i = 0; i < fetch->added->len; i++) { - if (!(envelope = fetch->added->pdata[i])) { - if (complete) - courier_imap_show_error (fetch->summary, i + fetch->first); - break; - } - - if ((envelope->changed & IMAP4_FETCH_ALL) != IMAP4_FETCH_ALL) { - if (complete) { - d(fprintf (stderr, "Hmmm, IMAP4 server didn't give us everything for message %d\n", - fetch->first + i)); - } - - break; - } - - if (!(envelope->changed & IMAP4_FETCH_SAVED)) { - if ((info = camel_folder_summary_uid (fetch->summary, camel_message_info_uid (envelope->info)))) { - camel_message_info_free (info); - continue; - } - - if ((((CamelMessageInfoBase *) envelope->info)->flags & CAMEL_IMAP4_MESSAGE_RECENT)) - camel_folder_change_info_recent_uid (changes, camel_message_info_uid (envelope->info)); - - camel_folder_change_info_add_uid (changes, camel_message_info_uid (envelope->info)); - camel_folder_summary_add (fetch->summary, envelope->info); - camel_message_info_ref (envelope->info); - envelope->changed |= IMAP4_FETCH_SAVED; - } - } - - if (complete) { - for (i = 0; i < fetch->added->len; i++) { - if (!(envelope = fetch->added->pdata[i])) - continue; - - camel_message_info_free (envelope->info); - g_free (envelope); - } - - g_ptr_array_free (fetch->added, TRUE); - g_hash_table_destroy (fetch->uid_hash); - } - - if (camel_folder_change_info_changed (changes)) - camel_object_trigger_event (fetch->summary->folder, "folder_changed", changes); - - if (complete) { - camel_folder_change_info_free (changes); - g_free (fetch); - } else { - camel_folder_summary_save (fetch->summary); - camel_folder_change_info_clear (changes); - } -} - -static void -imap4_fetch_all_update (struct imap4_fetch_all_t *fetch) -{ - CamelIMAP4MessageInfo *iinfo, *new_iinfo; - struct imap4_envelope_t *envelope; - CamelFolderChangeInfo *changes; - CamelMessageInfo *info; - guint32 flags; - gint total, i; - - changes = fetch->changes; - - total = camel_folder_summary_count (fetch->summary); - for (i = 0; i < total; i++) { - info = camel_folder_summary_index (fetch->summary, i); - if (!(envelope = g_hash_table_lookup (fetch->uid_hash, camel_message_info_uid (info)))) { - /* remove it */ - camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info)); - camel_folder_summary_remove (fetch->summary, info); - total--; - i--; - } else if (envelope->changed & IMAP4_FETCH_FLAGS) { - /* update it with the new flags */ - new_iinfo = (CamelIMAP4MessageInfo *) envelope->info; - iinfo = (CamelIMAP4MessageInfo *) info; - - flags = iinfo->info.flags; - iinfo->info.flags = camel_imap4_merge_flags (iinfo->server_flags, iinfo->info.flags, new_iinfo->server_flags); - iinfo->server_flags = new_iinfo->server_flags; - if (iinfo->info.flags != flags) - camel_folder_change_info_change_uid (changes, camel_message_info_uid (info)); - } - - camel_message_info_free (info); - } - - for (i = 0; i < fetch->added->len; i++) { - if (!(envelope = fetch->added->pdata[i])) { - courier_imap_show_error (fetch->summary, i + fetch->first); - continue; - } - - camel_message_info_free (envelope->info); - g_free (envelope); - } - - g_ptr_array_free (fetch->added, TRUE); - g_hash_table_destroy (fetch->uid_hash); - - if (camel_folder_change_info_changed (changes)) - camel_object_trigger_event (fetch->summary->folder, "folder_changed", changes); - camel_folder_change_info_free (changes); - - g_free (fetch); -} - -static gint -untagged_fetch_all (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, guint32 index, camel_imap4_token_t *token, CamelException *ex) -{ - struct imap4_fetch_all_t *fetch = ic->user_data; - CamelFolderSummary *summary = fetch->summary; - struct imap4_envelope_t *envelope = NULL; - GPtrArray *added = fetch->added; - CamelIMAP4MessageInfo *iinfo; - CamelMessageInfo *info; - guint32 changed = 0; - gchar uid[16]; - - if (index < fetch->first) { - /* This can happen if the connection to the - * server was dropped in a previous attempt at - * this FETCH (ALL) command and some other - * client expunged messages in the range - * before fetch->first in the period between - * our previous attempt and now. */ - gsize movelen = added->len * sizeof (gpointer); - gsize extra = index - fetch->first; - gpointer dest; - - g_assert (fetch->all); - - g_ptr_array_set_size (added, added->len + extra); - dest = ((gchar *) added->pdata) + (extra * sizeof (gpointer)); - memmove (dest, added->pdata, movelen); - fetch->total += extra; - fetch->first = index; - } else if (index > (added->len + (fetch->first - 1))) { - gsize extra = index - (added->len + (fetch->first - 1)); - g_ptr_array_set_size (added, added->len + extra); - fetch->total += extra; - } - - if (!(envelope = added->pdata[index - fetch->first])) { - info = camel_message_info_new (summary); - iinfo = (CamelIMAP4MessageInfo *) info; - envelope = g_new (struct imap4_envelope_t, 1); - added->pdata[index - fetch->first] = envelope; - envelope->info = info; - envelope->changed = 0; - } else { - info = envelope->info; - iinfo = (CamelIMAP4MessageInfo *) info; - } - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - /* parse the FETCH response list */ - if (token->token != '(') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - return -1; - } - - do { - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token == ')' || token->token == '\n') - break; - - if (token->token != CAMEL_IMAP4_TOKEN_ATOM) - goto unexpected; - - if (!strcmp (token->v.atom, "ENVELOPE")) { - if (envelope) { - if (decode_envelope (engine, info, token, ex) == -1) - goto exception; - - changed |= IMAP4_FETCH_ENVELOPE; - } else { - CamelMessageInfo *tmp; - gint rv; - - g_warning ("Hmmm, server is sending us ENVELOPE data for a message we didn't ask for (message %u)\n", - index); - tmp = camel_message_info_new (summary); - rv = decode_envelope (engine, tmp, token, ex); - camel_message_info_free(tmp); - - if (rv == -1) - goto exception; - } - } else if (!strcmp (token->v.atom, "FLAGS")) { - guint32 server_flags = 0; - - if (camel_imap4_parse_flags_list (engine, &server_flags, ex) == -1) - return -1; - - iinfo->info.flags = camel_imap4_merge_flags (iinfo->server_flags, iinfo->info.flags, server_flags); - iinfo->server_flags = server_flags; - - changed |= IMAP4_FETCH_FLAGS; - } else if (!strcmp (token->v.atom, "INTERNALDATE")) { - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - switch (token->token) { - case CAMEL_IMAP4_TOKEN_NIL: - iinfo->info.date_received = (time_t) -1; - break; - case CAMEL_IMAP4_TOKEN_ATOM: - case CAMEL_IMAP4_TOKEN_QSTRING: - iinfo->info.date_received = decode_internaldate (token->v.qstring); - break; - default: - goto unexpected; - } - - changed |= IMAP4_FETCH_INTERNALDATE; - } else if (!strcmp (token->v.atom, "RFC822.SIZE")) { - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token != CAMEL_IMAP4_TOKEN_NUMBER) - goto unexpected; - - iinfo->info.size = token->v.number; - - changed |= IMAP4_FETCH_RFC822SIZE; - } else if (!strcmp (token->v.atom, "UID")) { - const gchar *iuid; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token != CAMEL_IMAP4_TOKEN_NUMBER || token->v.number == 0) - goto unexpected; - - sprintf (uid, "%u", token->v.number); - iuid = camel_message_info_uid (info); - if (iuid != NULL && iuid[0] != '\0') { - if (strcmp (iuid, uid) != 0) { - d(fprintf (stderr, "Hmmm, UID mismatch for message %u\n", index)); - g_assert_not_reached (); - } - } else { - g_free (info->uid); - info->uid = g_strdup (uid); - g_hash_table_insert (fetch->uid_hash, (gpointer) camel_message_info_uid (info), envelope); - changed |= IMAP4_FETCH_UID; - } - } else if (!strcmp (token->v.atom, "BODY[HEADER.FIELDS")) { - /* References, Content-Type, and Mailing-List headers... */ - CamelContentType *content_type; - struct _camel_header_raw *h; - CamelMimeParser *parser; - guchar *literal; - const gchar *refs, *str; - gchar *mlist; - gsize n; - - /* '(' */ - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token != '(') - goto unexpected; - - /* header name list */ - do { - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token == ')') - break; - - switch (token->token) { - case CAMEL_IMAP4_TOKEN_ATOM: - case CAMEL_IMAP4_TOKEN_QSTRING: - break; - case CAMEL_IMAP4_TOKEN_LITERAL: - if (camel_imap4_engine_literal (engine, &literal, &n, ex) == -1) - return -1; - - g_free (literal); - break; - default: - goto unexpected; - } - - /* we don't care what the list was... */ - } while (1); - - /* ']' */ - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token != ']') - goto unexpected; - - /* literal */ - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token != CAMEL_IMAP4_TOKEN_LITERAL) - goto unexpected; - - parser = camel_mime_parser_new (); - camel_mime_parser_init_with_stream (parser, (CamelStream *) engine->istream); - - switch (camel_mime_parser_step (parser, NULL, NULL)) { - case CAMEL_MIME_PARSER_STATE_HEADER: - case CAMEL_MIME_PARSER_STATE_MESSAGE: - case CAMEL_MIME_PARSER_STATE_MULTIPART: - h = camel_mime_parser_headers_raw (parser); - - /* find our mailing-list header */ - mlist = camel_header_raw_check_mailing_list (&h); - iinfo->info.mlist = camel_pstring_strdup (mlist); - g_free (mlist); - - /* check if we possibly have attachments */ - if ((str = camel_header_raw_find (&h, "Content-Type", NULL))) { - content_type = camel_content_type_decode (str); - if (camel_content_type_is (content_type, "multipart", "*") - && !camel_content_type_is (content_type, "multipart", "alternative")) - iinfo->info.flags |= CAMEL_MESSAGE_ATTACHMENTS; - camel_content_type_unref (content_type); - } - - /* check for References: */ - g_free (iinfo->info.references); - refs = camel_header_raw_find (&h, "References", NULL); - str = camel_header_raw_find (&h, "In-Reply-To", NULL); - iinfo->info.references = decode_references (refs, str); - default: - break; - } - - camel_object_unref (parser); - } else { - /* wtf? */ - d(fprintf (stderr, "huh? %s?...\n", token->v.atom)); - } - } while (1); - - if (envelope) { - envelope->changed |= changed; - - if ((envelope->changed & fetch->need) == fetch->need) { - fetch->count++; - - /* if we're doing a FETCH ALL and fetch->count - * is a multiple of the IMAP_SAVE_INCREMENT, - * sync the newly fetched envelopes to the - * summary and to disk as a convenience to - * users on flaky networks which might drop - * our connection to the IMAP server at any - * time, thus forcing us to reconnect and lose - * our summary fetching state. */ - if (fetch->all && (fetch->count % IMAP_SAVE_INCREMENT) == 0) - imap4_fetch_all_add (fetch, FALSE); - - camel_operation_progress (NULL, (fetch->count * 100.0f) / fetch->total); - } - } else if (changed & IMAP4_FETCH_FLAGS) { - camel_folder_change_info_change_uid (fetch->changes, camel_message_info_uid (info)); - } - - if (token->token != ')') - goto unexpected; - - return 0; - - unexpected: - - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - - exception: - - return -1; -} - -#define IMAP4_ALL "FLAGS INTERNALDATE RFC822.SIZE ENVELOPE" -#define MAILING_LIST_HEADERS "List-Post Mailing-List Originator X-Mailing-List X-Loop X-List Sender Delivered-To Return-Path X-BeenThere List-Unsubscribe" - -#define BASE_HEADER_FIELDS "Content-Type References In-Reply-To List-Id" -#define MORE_HEADER_FIELDS BASE_HEADER_FIELDS " " MAILING_LIST_HEADERS - -static void -imap4_fetch_all_reset (CamelIMAP4Command *ic, struct imap4_fetch_all_t *fetch) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) fetch->summary; - CamelFolder *folder = fetch->summary->folder; - struct imap4_envelope_t *envelope; - CamelMessageInfo *info; - guint32 seqid, iuid; - const gchar *query; - gchar uid[32]; - gint scount; - gint i; - - /* sync everything we've gotten so far to the summary */ - imap4_fetch_all_add (fetch, FALSE); - - for (i = 0; i < fetch->added->len; i++) { - if (!(envelope = fetch->added->pdata[i])) - continue; - - camel_message_info_free (envelope->info); - fetch->added->pdata[i] = NULL; - g_free (envelope); - } - - scount = camel_folder_summary_count (fetch->summary); - seqid = scount + 1; - - if (seqid > fetch->first) { - /* if we get here, then it means that we managed to - * collect some summary info before the connection - * with the imap server dropped. Update our FETCH - * command state to begin fetching where we left off - * rather than at the beginning. */ - info = camel_folder_summary_index (fetch->summary, scount - 1); - iuid = strtoul (camel_message_info_uid (info), NULL, 10); - d(fprintf (stderr, "last known summary id = %d, uid = %s, iuid = %u\n", scount, info->uid, iuid)); - camel_message_info_free (info); - sprintf (uid, "%u", iuid + 1); - - fetch->total = imap4_summary->exists - scount; - g_ptr_array_set_size (fetch->added, fetch->total); - fetch->first = seqid; - - /* now we hack the SpruceIMAPCommand structure... */ - if (((CamelIMAP4Folder *) folder)->enable_mlist) - query = "UID FETCH %s:* (" IMAP4_ALL " BODY.PEEK[HEADER.FIELDS (" MORE_HEADER_FIELDS ")])\r\n"; - else - query = "UID FETCH %s:* (" IMAP4_ALL " BODY.PEEK[HEADER.FIELDS (" BASE_HEADER_FIELDS ")])\r\n"; - - g_free (ic->part->buffer); - ic->part->buffer = g_strdup_printf (query, uid); - ic->part->buflen = strlen (ic->part->buffer); - - d(fprintf (stderr, "*** RESETTING FETCH-ALL STATE. New command => %s", ic->part->buffer)); - } else { - /* we didn't manage to fetch any new info before the - * connection dropped... */ - } - - camel_folder_change_info_clear (fetch->changes); - g_hash_table_remove_all (fetch->uid_hash); -} - -static CamelIMAP4Command * -imap4_summary_fetch_all (CamelFolderSummary *summary, guint32 seqid, const gchar *uid) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - CamelFolder *folder = summary->folder; - struct imap4_fetch_all_t *fetch; - CamelIMAP4Engine *engine; - CamelIMAP4Command *ic; - const gchar *query; - guint32 total; - - engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - - total = (imap4_summary->exists - seqid) + 1; - fetch = g_new (struct imap4_fetch_all_t, 1); - fetch->uid_hash = g_hash_table_new (g_str_hash, g_str_equal); - fetch->changes = camel_folder_change_info_new (); - fetch->added = g_ptr_array_sized_new (total); - fetch->summary = summary; - fetch->first = seqid; - fetch->need = IMAP4_FETCH_ALL; - fetch->total = total; - fetch->count = 0; - fetch->all = TRUE; - - if (((CamelIMAP4Folder *) folder)->enable_mlist) - query = "UID FETCH %s:* (" IMAP4_ALL " BODY.PEEK[HEADER.FIELDS (" MORE_HEADER_FIELDS ")])\r\n"; - else - query = "UID FETCH %s:* (" IMAP4_ALL " BODY.PEEK[HEADER.FIELDS (" BASE_HEADER_FIELDS ")])\r\n"; - - ic = camel_imap4_engine_queue (engine, folder, query, uid); - - camel_imap4_command_register_untagged (ic, "FETCH", untagged_fetch_all); - ic->reset = (CamelIMAP4CommandReset) imap4_fetch_all_reset; - ic->user_data = fetch; - - return ic; -} - -static CamelIMAP4Command * -imap4_summary_fetch_flags (CamelFolderSummary *summary) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - CamelFolder *folder = summary->folder; - struct imap4_fetch_all_t *fetch; - CamelMessageInfo *info[2]; - CamelIMAP4Engine *engine; - CamelIMAP4Command *ic; - guint32 total; - gint scount; - - engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - - scount = camel_folder_summary_count (summary); - g_assert (scount > 0); - - info[0] = camel_folder_summary_index (summary, 0); - if (scount > 1) - info[1] = camel_folder_summary_index (summary, scount - 1); - else - info[1] = NULL; - - total = imap4_summary->exists < scount ? imap4_summary->exists : scount; - fetch = g_new (struct imap4_fetch_all_t, 1); - fetch->uid_hash = g_hash_table_new (g_str_hash, g_str_equal); - fetch->changes = camel_folder_change_info_new (); - fetch->added = g_ptr_array_sized_new (total); - fetch->summary = summary; - fetch->first = 1; - fetch->need = IMAP4_FETCH_UID | IMAP4_FETCH_FLAGS; - fetch->total = total; - fetch->count = 0; - fetch->all = FALSE; - - if (info[1] != NULL) { - ic = camel_imap4_engine_queue (engine, folder, "UID FETCH %s:%s (FLAGS)\r\n", - camel_message_info_uid (info[0]), - camel_message_info_uid (info[1])); - camel_message_info_free (info[1]); - } else { - ic = camel_imap4_engine_queue (engine, folder, "UID FETCH %s:* (FLAGS)\r\n", - camel_message_info_uid (info[0])); - } - - camel_message_info_free (info[0]); - - camel_imap4_command_register_untagged (ic, "FETCH", untagged_fetch_all); - ic->user_data = fetch; - - return ic; -} - -static CamelMessageInfo * -imap4_message_info_new_from_header (CamelFolderSummary *summary, struct _camel_header_raw *header) -{ - CamelMessageInfo *info; - - info = CAMEL_FOLDER_SUMMARY_CLASS (parent_class)->message_info_new_from_header (summary, header); - ((CamelIMAP4MessageInfo *) info)->server_flags = 0; - - return info; -} - -static CamelMessageInfo * -imap4_message_info_load (CamelFolderSummary *summary, FILE *fin) -{ - CamelIMAP4MessageInfo *minfo; - CamelMessageInfo *info; - - if (!(info = CAMEL_FOLDER_SUMMARY_CLASS (parent_class)->message_info_load (summary, fin))) - return NULL; - - minfo = (CamelIMAP4MessageInfo *) info; - - if (camel_file_util_decode_uint32 (fin, &minfo->server_flags) == -1) - goto exception; - - return info; - - exception: - - camel_message_info_free(info); - - return NULL; -} - -static gint -imap4_message_info_save (CamelFolderSummary *summary, FILE *fout, CamelMessageInfo *info) -{ - CamelIMAP4MessageInfo *minfo = (CamelIMAP4MessageInfo *) info; - - if (CAMEL_FOLDER_SUMMARY_CLASS (parent_class)->message_info_save (summary, fout, info) == -1) - return -1; - - if (camel_file_util_encode_uint32 (fout, minfo->server_flags) == -1) - return -1; - - return 0; -} - -static CamelMessageInfo * -imap4_message_info_clone (CamelFolderSummary *summary, const CamelMessageInfo *mi) -{ - const CamelIMAP4MessageInfo *src = (const CamelIMAP4MessageInfo *) mi; - CamelIMAP4MessageInfo *dest; - - dest = (CamelIMAP4MessageInfo *) CAMEL_FOLDER_SUMMARY_CLASS (parent_class)->message_info_clone (summary, mi); - dest->server_flags = src->server_flags; - - /* FIXME: parent clone should do this */ - dest->info.content = camel_folder_summary_content_info_new (summary); - - return (CamelMessageInfo *) dest; -} - -static CamelMessageContentInfo * -imap4_content_info_load (CamelFolderSummary *summary, FILE *in) -{ - if (fgetc (in)) - return CAMEL_FOLDER_SUMMARY_CLASS (parent_class)->content_info_load (summary, in); - else - return camel_folder_summary_content_info_new (summary); -} - -static gint -imap4_content_info_save (CamelFolderSummary *summary, FILE *out, CamelMessageContentInfo *info) -{ - if (info->type) { - fputc (1, out); - return CAMEL_FOLDER_SUMMARY_CLASS (parent_class)->content_info_save (summary, out, info); - } else - return fputc (0, out); -} - -void -camel_imap4_summary_set_exists (CamelFolderSummary *summary, guint32 exists) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - - g_return_if_fail (CAMEL_IS_IMAP4_SUMMARY (summary)); - - imap4_summary->exists = exists; -} - -void -camel_imap4_summary_set_recent (CamelFolderSummary *summary, guint32 recent) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - - g_return_if_fail (CAMEL_IS_IMAP4_SUMMARY (summary)); - - imap4_summary->recent = recent; -} - -void -camel_imap4_summary_set_unseen (CamelFolderSummary *summary, guint32 unseen) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - - g_return_if_fail (CAMEL_IS_IMAP4_SUMMARY (summary)); - - imap4_summary->unseen = unseen; -} - -void -camel_imap4_summary_set_uidnext (CamelFolderSummary *summary, guint32 uidnext) -{ - g_return_if_fail (CAMEL_IS_IMAP4_SUMMARY (summary)); - - summary->nextuid = uidnext; -} - -static void -imap4_summary_clear (CamelFolderSummary *summary, gboolean uncache) -{ - CamelFolderChangeInfo *changes; - CamelMessageInfo *info; - gint i, count; - - changes = camel_folder_change_info_new (); - count = camel_folder_summary_count (summary); - for (i = 0; i < count; i++) { - if (!(info = camel_folder_summary_index (summary, i))) - continue; - - camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info)); - camel_message_info_free(info); - } - - camel_folder_summary_clear (summary); - - if (uncache) - camel_data_cache_clear (((CamelIMAP4Folder *) summary->folder)->cache, "cache", NULL); - - if (camel_folder_change_info_changed (changes)) - camel_object_trigger_event (summary->folder, "folder_changed", changes); - camel_folder_change_info_free (changes); -} - -void -camel_imap4_summary_set_uidvalidity (CamelFolderSummary *summary, guint32 uidvalidity) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - - g_return_if_fail (CAMEL_IS_IMAP4_SUMMARY (summary)); - - if (imap4_summary->uidvalidity == uidvalidity) - return; - - imap4_summary_clear (summary, TRUE); - - imap4_summary->uidvalidity = uidvalidity; - - imap4_summary->uidvalidity_changed = TRUE; -} - -void -camel_imap4_summary_expunge (CamelFolderSummary *summary, gint seqid) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - CamelFolderChangeInfo *changes; - CamelMessageInfo *info; - const gchar *uid; - - g_return_if_fail (CAMEL_IS_IMAP4_SUMMARY (summary)); - - seqid--; - if (!(info = camel_folder_summary_index (summary, seqid))) - return; - - imap4_summary->exists--; - - uid = camel_message_info_uid (info); - camel_data_cache_remove (((CamelIMAP4Folder *) summary->folder)->cache, "cache", uid, NULL); - - changes = camel_folder_change_info_new (); - camel_folder_change_info_remove_uid (changes, uid); - - camel_message_info_free(info); - camel_folder_summary_remove_index (summary, seqid); - - camel_object_trigger_event (summary->folder, "folder_changed", changes); - camel_folder_change_info_free (changes); -} - -#if 0 -static gint -info_uid_sort (const CamelMessageInfo **info0, const CamelMessageInfo **info1) -{ - guint32 uid0, uid1; - - uid0 = strtoul (camel_message_info_uid (*info0), NULL, 10); - uid1 = strtoul (camel_message_info_uid (*info1), NULL, 10); - - if (uid0 == uid1) - return 0; - - return uid0 < uid1 ? -1 : 1; -} -#endif - -gint -camel_imap4_summary_flush_updates (CamelFolderSummary *summary, CamelException *ex) -{ - CamelIMAP4Folder *imap4_folder = (CamelIMAP4Folder *) summary->folder; - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - CamelOfflineJournal *journal = imap4_folder->journal; - CamelIMAP4Engine *engine; - CamelMessageInfo *info; - CamelIMAP4Command *ic; - guint32 iuid, seqid = 0; - gint scount, id; - gchar uid[16]; - - g_return_val_if_fail (CAMEL_IS_IMAP4_SUMMARY (summary), -1); - - /* FIXME: what do we do if replaying the journal fails? */ - camel_offline_journal_replay (journal, NULL); - - if (imap4_folder->enable_mlist && !(summary->flags & CAMEL_IMAP4_SUMMARY_HAVE_MLIST)) { - /* need to refetch all summary info to get info->mlist */ - imap4_summary_clear (summary, FALSE); - } - - summary->flags = (summary->flags & ~CAMEL_IMAP4_SUMMARY_HAVE_MLIST); - if (imap4_folder->enable_mlist) - summary->flags |= CAMEL_IMAP4_SUMMARY_HAVE_MLIST; - else - summary->flags ^= CAMEL_IMAP4_SUMMARY_HAVE_MLIST; - - engine = ((CamelIMAP4Store *) summary->folder->parent_store)->engine; - if ((scount = camel_folder_summary_count (summary)) == 0) - imap4_summary->update_flags = FALSE; - - if (imap4_summary->uidvalidity_changed) { - /* need to refetch everything */ - g_assert (scount == 0); - seqid = 1; - } else if (imap4_summary->update_flags || imap4_summary->exists < scount) { - /* this both updates flags and removes messages which - * have since been expunged from the server by another - * client */ - ic = imap4_summary_fetch_flags (summary); - - camel_operation_start (NULL, _("Scanning for changed messages")); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_imap4_journal_readd_failed ((CamelIMAP4Journal *) journal); - imap4_fetch_all_free (ic->user_data); - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - camel_operation_end (NULL); - return -1; - } - - imap4_fetch_all_update (ic->user_data); - camel_imap4_command_unref (ic); - camel_operation_end (NULL); - - scount = camel_folder_summary_count (summary); - if (imap4_summary->exists < scount) { - /* broken server? wtf? this should never happen... */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("IMAP server %s is in an inconsistent state."), - engine->url->host); - return -1; - } else if (imap4_summary->exists > scount) { - /* need to fetch new envelopes */ - seqid = scount + 1; - } else { - /* we are fully synced */ - seqid = 0; - } - } else { - /* need to fetch new envelopes */ - seqid = scount + 1; - } - - if (seqid != 0 && seqid <= imap4_summary->exists) { - if (scount > 0) { - info = camel_folder_summary_index (summary, scount - 1); - iuid = strtoul (camel_message_info_uid (info), NULL, 10); - camel_message_info_free (info); - sprintf (uid, "%u", iuid + 1); - } else { - strcpy (uid, "1"); - } - - ic = imap4_summary_fetch_all (summary, seqid, uid); - - camel_operation_start (NULL, _("Fetching envelopes of new messages")); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_imap4_journal_readd_failed ((CamelIMAP4Journal *) journal); - imap4_fetch_all_free (ic->user_data); - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - camel_operation_end (NULL); - return -1; - } - - imap4_fetch_all_add (ic->user_data, TRUE); - camel_imap4_command_unref (ic); - camel_operation_end (NULL); - } - - imap4_summary->update_flags = FALSE; - imap4_summary->uidvalidity_changed = FALSE; - - camel_imap4_journal_readd_failed ((CamelIMAP4Journal *) journal); - - return 0; -} diff --git a/camel/providers/imap4/camel-imap4-summary.h b/camel/providers/imap4/camel-imap4-summary.h deleted file mode 100644 index 0f8687b..0000000 --- a/camel/providers/imap4/camel-imap4-summary.h +++ /dev/null @@ -1,99 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef CAMEL_IMAP4_SUMMARY_H -#define CAMEL_IMAP4_SUMMARY_H - -#include - -#include -#include - -#define CAMEL_TYPE_IMAP4_SUMMARY (camel_imap4_summary_get_type ()) -#define CAMEL_IMAP4_SUMMARY(obj) (CAMEL_CHECK_CAST ((obj), CAMEL_TYPE_IMAP4_SUMMARY, CamelIMAP4Summary)) -#define CAMEL_IMAP4_SUMMARY_CLASS(klass) (CAMEL_CHECK_CLASS_CAST ((klass), CAMEL_TYPE_IMAP4_SUMMARY, CamelIMAP4SummaryClass)) -#define CAMEL_IS_IMAP4_SUMMARY(obj) (CAMEL_CHECK_TYPE ((obj), CAMEL_TYPE_IMAP4_SUMMARY)) -#define CAMEL_IS_IMAP4_SUMMARY_CLASS(klass) (CAMEL_CHECK_CLASS_TYPE ((klass), CAMEL_TYPE_IMAP4_SUMMARY)) -#define CAMEL_IMAP4_SUMMARY_GET_CLASS(obj) (CAMEL_CHECK_GET_CLASS ((obj), CAMEL_TYPE_FOLDER_SUMMARY, CamelIMAP4SummaryClass)) - -G_BEGIN_DECLS - -typedef struct _CamelIMAP4MessageInfo CamelIMAP4MessageInfo; -typedef struct _CamelIMAP4MessageContentInfo CamelIMAP4MessageContentInfo; - -typedef struct _CamelIMAP4Summary CamelIMAP4Summary; -typedef struct _CamelIMAP4SummaryClass CamelIMAP4SummaryClass; - -#define CAMEL_IMAP4_MESSAGE_RECENT (1 << 17) - -enum { - CAMEL_IMAP4_SUMMARY_HAVE_MLIST = (1 << 8) -}; - -struct _CamelIMAP4MessageInfo { - CamelMessageInfoBase info; - - guint32 server_flags; -}; - -struct _CamelIMAP4MessageContentInfo { - CamelMessageContentInfo info; - -}; - -struct _CamelIMAP4Summary { - CamelFolderSummary parent; - - guint32 version; - - guint32 exists; - guint32 recent; - guint32 unseen; - - guint32 uidvalidity; - - guint uidvalidity_changed:1; - guint update_flags:1; -}; - -struct _CamelIMAP4SummaryClass { - CamelFolderSummaryClass parent_class; - -}; - -CamelType camel_imap4_summary_get_type (void); - -CamelFolderSummary *camel_imap4_summary_new (CamelFolder *folder); - -void camel_imap4_summary_set_exists (CamelFolderSummary *summary, guint32 exists); -void camel_imap4_summary_set_recent (CamelFolderSummary *summary, guint32 recent); -void camel_imap4_summary_set_unseen (CamelFolderSummary *summary, guint32 unseen); -void camel_imap4_summary_set_uidnext (CamelFolderSummary *summary, guint32 uidnext); - -void camel_imap4_summary_set_uidvalidity (CamelFolderSummary *summary, guint32 uidvalidity); - -void camel_imap4_summary_expunge (CamelFolderSummary *summary, gint seqid); - -gint camel_imap4_summary_flush_updates (CamelFolderSummary *summary, CamelException *ex); - -G_END_DECLS - -#endif /* CAMEL_IMAP4_SUMMARY_H */ diff --git a/camel/providers/imap4/camel-imap4-utils.c b/camel/providers/imap4/camel-imap4-utils.c deleted file mode 100644 index c668115..0000000 --- a/camel/providers/imap4/camel-imap4-utils.c +++ /dev/null @@ -1,788 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include - -#include -#include - -#include "camel-imap4-command.h" -#include "camel-imap4-engine.h" -#include "camel-imap4-store-summary.h" -#include "camel-imap4-stream.h" -#include "camel-imap4-summary.h" -#include "camel-imap4-utils.h" - -#define d(x) - -CamelFolderInfo * -camel_imap4_build_folder_info_tree (GPtrArray *array, const gchar *top) -{ - CamelFolderInfo *cur, *fi, *root = NULL; - const gchar *p; - gsize n = 0; - gchar *pname; - gint i; - - if (array->len == 0) - return NULL; - - if (array->len == 1) - return array->pdata[0]; - - if (top) - n = strlen (top); - - cur = root = array->pdata[0]; - - for (i = 1; i < array->len; i++) { - fi = (CamelFolderInfo *) array->pdata[i]; - if (top && strncmp (fi->full_name, top, n) != 0) { - /* this folder info was not requested */ - camel_folder_info_free (fi); - continue; - } - - if ((p = strrchr (fi->full_name, '/'))) { - pname = g_strndup (fi->full_name, p - fi->full_name); - if (!strcmp (cur->full_name, pname)) { - /* cur is our parent */ - fi->parent = cur; - cur->child = fi; - cur = fi; - } else if (cur->parent && !strcmp (cur->parent->full_name, pname)) { - /* cur is our sibling */ - fi->parent = cur->parent; - cur->next = fi; - cur = fi; - } else { - /* search back for our parent */ - while (cur->parent) { - if (!strcmp (cur->parent->full_name, pname)) - break; - cur = cur->parent; - } - - /* cur should now be our sibling */ - fi->parent = cur->parent; - cur->next = fi; - cur = fi; - } - g_free (pname); - } else { - /* traverse back to most recent top-level fi */ - while (cur->parent) - cur = cur->parent; - - cur->next = fi; - cur = fi; - } - } - - return root; -} - -void -camel_imap4_flags_diff (flags_diff_t *diff, guint32 old, guint32 new) -{ - diff->changed = old ^ new; - diff->bits = new & diff->changed; -} - -guint32 -camel_imap4_flags_merge (flags_diff_t *diff, guint32 flags) -{ - return (flags & ~diff->changed) | diff->bits; -} - -/** - * camel_imap4_merge_flags: - * @original: original server flags - * @local: local flags (after changes) - * @server: new server flags (another client updated the server flags) - * - * Merge the local flag changes into the new server flags. - * - * Returns: the merged flags. - **/ -guint32 -camel_imap4_merge_flags (guint32 original, guint32 local, guint32 server) -{ - flags_diff_t diff; - - camel_imap4_flags_diff (&diff, original, local); - - return camel_imap4_flags_merge (&diff, server); -} - -void -camel_imap4_namespace_clear (CamelIMAP4Namespace **ns) -{ - CamelIMAP4Namespace *node, *next; - - node = *ns; - while (node != NULL) { - next = node->next; - g_free (node->path); - g_free (node); - node = next; - } - - *ns = NULL; -} - -static CamelIMAP4Namespace * -imap4_namespace_copy (const CamelIMAP4Namespace *ns) -{ - CamelIMAP4Namespace *list, *node, *tail; - - list = NULL; - tail = (CamelIMAP4Namespace *) &list; - - while (ns != NULL) { - tail->next = node = g_malloc (sizeof (CamelIMAP4Namespace)); - node->path = g_strdup (ns->path); - node->sep = ns->sep; - ns = ns->next; - tail = node; - } - - tail->next = NULL; - - return list; -} - -CamelIMAP4NamespaceList * -camel_imap4_namespace_list_copy (const CamelIMAP4NamespaceList *nsl) -{ - CamelIMAP4NamespaceList *new; - - new = g_malloc (sizeof (CamelIMAP4NamespaceList)); - new->personal = imap4_namespace_copy (nsl->personal); - new->other = imap4_namespace_copy (nsl->other); - new->shared = imap4_namespace_copy (nsl->shared); - - return new; -} - -void -camel_imap4_namespace_list_free (CamelIMAP4NamespaceList *nsl) -{ - camel_imap4_namespace_clear (&nsl->personal); - camel_imap4_namespace_clear (&nsl->shared); - camel_imap4_namespace_clear (&nsl->other); - g_free (nsl); -} - -gchar -camel_imap4_get_path_delim (CamelIMAP4StoreSummary *s, const gchar *full_name) -{ - CamelIMAP4Namespace *namespace; - const gchar *slash; - gsize len; - gchar *top; - - g_return_val_if_fail (s->namespaces != NULL, '/'); - - if ((slash = strchr (full_name, '/'))) - len = (slash - full_name); - else - len = strlen (full_name); - - top = g_alloca (len + 1); - memcpy (top, full_name, len); - top[len] = '\0'; - - if (!g_ascii_strcasecmp (top, "INBOX")) - strcpy (top, "INBOX"); - - retry: - namespace = s->namespaces->personal; - while (namespace != NULL) { - if (!strcmp (namespace->path, top)) - return namespace->sep; - namespace = namespace->next; - } - - namespace = s->namespaces->other; - while (namespace != NULL) { - if (!strcmp (namespace->path, top)) - return namespace->sep; - namespace = namespace->next; - } - - namespace = s->namespaces->shared; - while (namespace != NULL) { - if (!strcmp (namespace->path, top)) - return namespace->sep; - namespace = namespace->next; - } - - if (top[0] != '\0') { - /* look for a default namespace? */ - top[0] = '\0'; - goto retry; - } - - return '/'; -} - -struct _uidset_range { - struct _uidset_range *next; - guint32 first, last; - uint8_t buflen; - gchar buf[24]; -}; - -struct _uidset { - CamelFolderSummary *summary; - struct _uidset_range *ranges; - struct _uidset_range *tail; - gsize maxlen, setlen; -}; - -static void -uidset_range_free (struct _uidset_range *range) -{ - struct _uidset_range *next; - - while (range != NULL) { - next = range->next; - g_free (range); - range = next; - } -} - -static void -uidset_init (struct _uidset *uidset, CamelFolderSummary *summary, gsize maxlen) -{ - uidset->ranges = g_new (struct _uidset_range, 1); - uidset->ranges->first = (guint32) -1; - uidset->ranges->last = (guint32) -1; - uidset->ranges->next = NULL; - uidset->ranges->buflen = 0; - - uidset->tail = uidset->ranges; - uidset->summary = summary; - uidset->maxlen = maxlen; - uidset->setlen = 0; -} - -/* returns: -1 on full-and-not-added, 0 on added-and-not-full or 1 on added-and-full */ -static gint -uidset_add (struct _uidset *uidset, CamelMessageInfo *info) -{ - GPtrArray *messages = uidset->summary->messages; - struct _uidset_range *node, *tail = uidset->tail; - const gchar *iuid = camel_message_info_uid (info); - gsize uidlen, len; - const gchar *colon; - guint32 index; - - /* Note: depends on integer overflow for initial 'add' */ - for (index = tail->last + 1; index < messages->len; index++) { - if (info == messages->pdata[index]) - break; - } - - g_assert (index < messages->len); - - uidlen = strlen (iuid); - - if (tail->buflen == 0) { - /* first add */ - tail->first = tail->last = index; - strcpy (tail->buf, iuid); - uidset->setlen = uidlen; - tail->buflen = uidlen; - } else if (index == (tail->last + 1)) { - /* add to last range */ - if (tail->last == tail->first) { - /* make sure we've got enough room to add this one... */ - if ((uidset->setlen + uidlen + 1) > uidset->maxlen) - return -1; - - tail->buf[tail->buflen++] = ':'; - uidset->setlen++; - } else { - colon = strchr (tail->buf, ':') + 1; - - len = strlen (colon); - uidset->setlen -= len; - tail->buflen -= len; - } - - strcpy (tail->buf + tail->buflen, iuid); - uidset->setlen += uidlen; - tail->buflen += uidlen; - - tail->last = index; - } else if ((uidset->setlen + uidlen + 1) < uidset->maxlen) { - /* the beginning of a new range */ - tail->next = node = g_new (struct _uidset_range, 1); - node->first = node->last = index; - strcpy (node->buf, iuid); - uidset->setlen += uidlen + 1; - node->buflen = uidlen; - uidset->tail = node; - node->next = NULL; - } else { - /* can't add this one... */ - return -1; - } - - d(fprintf (stderr, "added uid %s to uidset (summary index = %u)\n", iuid, index)); - - if (uidset->setlen < uidset->maxlen) - return 0; - - return 1; -} - -static gchar * -uidset_to_string (struct _uidset *uidset) -{ - struct _uidset_range *range; - GString *string; - gchar *str; - - string = g_string_new (""); - - range = uidset->ranges; - while (range != NULL) { - g_string_append (string, range->buf); - range = range->next; - if (range) - g_string_append_c (string, ','); - } - - str = string->str; - g_string_free (string, FALSE); - - return str; -} - -gint -camel_imap4_get_uid_set (CamelIMAP4Engine *engine, CamelFolderSummary *summary, GPtrArray *infos, gint cur, gsize linelen, gchar **set) -{ - struct _uidset uidset; - gsize maxlen; - gint rv = 0; - gint i; - - if (engine->maxlentype == CAMEL_IMAP4_ENGINE_MAXLEN_LINE) - maxlen = engine->maxlen - linelen; - else - maxlen = engine->maxlen; - - uidset_init (&uidset, summary, maxlen); - - for (i = cur; i < infos->len && rv != 1; i++) { - if ((rv = uidset_add (&uidset, infos->pdata[i])) == -1) - break; - } - - if (i > cur) - *set = uidset_to_string (&uidset); - - uidset_range_free (uidset.ranges); - - return (i - cur); -} - -void -camel_imap4_utils_set_unexpected_token_error (CamelException *ex, CamelIMAP4Engine *engine, camel_imap4_token_t *token) -{ - GString *errmsg; - - if (ex == NULL) - return; - - errmsg = g_string_new (""); - g_string_append_printf (errmsg, _("Unexpected token in response from IMAP server %s: "), - engine->url->host); - - switch (token->token) { - case CAMEL_IMAP4_TOKEN_NIL: - g_string_append (errmsg, "NIL"); - break; - case CAMEL_IMAP4_TOKEN_ATOM: - g_string_append (errmsg, token->v.atom); - break; - case CAMEL_IMAP4_TOKEN_FLAG: - g_string_append (errmsg, token->v.flag); - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - g_string_append (errmsg, token->v.qstring); - break; - case CAMEL_IMAP4_TOKEN_LITERAL: - g_string_append_printf (errmsg, "{%u}", token->v.literal); - break; - case CAMEL_IMAP4_TOKEN_NUMBER: - g_string_append_printf (errmsg, "%u", token->v.number); - break; - case CAMEL_IMAP4_TOKEN_NO_DATA: - g_string_append (errmsg, _("No data")); - break; - default: - g_string_append_c (errmsg, (guchar) (token->token & 0xff)); - break; - } - - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, errmsg->str); - - g_string_free (errmsg, TRUE); -} - -static struct { - const gchar *name; - guint32 flag; -} imap4_flags[] = { - { "\\Answered", CAMEL_MESSAGE_ANSWERED }, - { "\\Deleted", CAMEL_MESSAGE_DELETED }, - { "\\Draft", CAMEL_MESSAGE_DRAFT }, - { "\\Flagged", CAMEL_MESSAGE_FLAGGED }, - { "\\Seen", CAMEL_MESSAGE_SEEN }, - { "\\Recent", CAMEL_IMAP4_MESSAGE_RECENT }, - { "\\*", CAMEL_MESSAGE_USER }, - - /* user flags */ - { "Junk", CAMEL_MESSAGE_JUNK }, - { "NonJunk", 0 }, -}; - -gint -camel_imap4_parse_flags_list (CamelIMAP4Engine *engine, guint32 *flags, CamelException *ex) -{ - camel_imap4_token_t token; - guint32 new = 0; - gint i; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != '(') { - d(fprintf (stderr, "Expected to find a '(' token starting the flags list\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - while (token.token == CAMEL_IMAP4_TOKEN_ATOM || token.token == CAMEL_IMAP4_TOKEN_FLAG) { - /* parse the flags list */ - for (i = 0; i < G_N_ELEMENTS (imap4_flags); i++) { - if (!g_ascii_strcasecmp (imap4_flags[i].name, token.v.atom)) { - new |= imap4_flags[i].flag; - break; - } - } - - if (i == G_N_ELEMENTS (imap4_flags)) - d(fprintf (stderr, "Encountered unknown flag: %s\n", token.v.atom)); - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - } - - if (token.token != ')') { - d(fprintf (stderr, "Expected to find a ')' token terminating the flags list\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - *flags = new; - - return 0; -} - -static struct { - const gchar *name; - guint32 flag; -} list_flags[] = { - { "\\Marked", CAMEL_IMAP4_FOLDER_MARKED }, - { "\\UnMarked", CAMEL_IMAP4_FOLDER_UNMARKED }, - { "\\NoSelect", CAMEL_FOLDER_NOSELECT }, - { "\\NoInferiors", CAMEL_FOLDER_NOINFERIORS }, - { "\\HasChildren", CAMEL_FOLDER_CHILDREN }, - { "\\HasNoChildren", CAMEL_FOLDER_NOCHILDREN }, -}; - -gint -camel_imap4_untagged_list (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, guint32 index, camel_imap4_token_t *token, CamelException *ex) -{ - GPtrArray *array = ic->user_data; - camel_imap4_list_t *list; - guchar *buf; - guint32 flags = 0; - GString *literal; - gchar delim; - gsize n; - gint i; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - /* parse the flag list */ - if (token->token != '(') - goto unexpected; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - while (token->token == CAMEL_IMAP4_TOKEN_FLAG || token->token == CAMEL_IMAP4_TOKEN_ATOM) { - for (i = 0; i < G_N_ELEMENTS (list_flags); i++) { - if (!g_ascii_strcasecmp (list_flags[i].name, token->v.atom)) { - flags |= list_flags[i].flag; - break; - } - } - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - } - - if (token->token != ')') - goto unexpected; - - /* parse the path delimiter */ - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - switch (token->token) { - case CAMEL_IMAP4_TOKEN_NIL: - delim = '\0'; - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - delim = *token->v.qstring; - break; - default: - goto unexpected; - } - - /* parse the folder name */ - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - list = g_new (camel_imap4_list_t, 1); - list->flags = flags; - list->delim = delim; - - switch (token->token) { - case CAMEL_IMAP4_TOKEN_ATOM: - list->name = g_strdup (token->v.atom); - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - list->name = g_strdup (token->v.qstring); - break; - case CAMEL_IMAP4_TOKEN_LITERAL: - literal = g_string_new (""); - while ((i = camel_imap4_stream_literal (engine->istream, &buf, &n)) == 1) - g_string_append_len (literal, buf, n); - - if (i == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("IMAP server %s unexpectedly disconnected: %s"), - engine->url->host, errno ? g_strerror (errno) : _("Unknown")); - g_string_free (literal, TRUE); - return -1; - } - - g_string_append_len (literal, buf, n); - list->name = literal->str; - g_string_free (literal, FALSE); - break; - default: - g_free (list); - goto unexpected; - } - - g_ptr_array_add (array, list); - - return camel_imap4_engine_eat_line (engine, ex); - - unexpected: - - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - - return -1; -} - -static struct { - const gchar *name; - gint type; -} imap4_status[] = { - { "MESSAGES", CAMEL_IMAP4_STATUS_MESSAGES }, - { "RECENT", CAMEL_IMAP4_STATUS_RECENT }, - { "UIDNEXT", CAMEL_IMAP4_STATUS_UIDNEXT }, - { "UIDVALIDITY", CAMEL_IMAP4_STATUS_UIDVALIDITY }, - { "UNSEEN", CAMEL_IMAP4_STATUS_UNSEEN }, -}; - -void -camel_imap4_status_free (camel_imap4_status_t *status) -{ - camel_imap4_status_attr_t *attr, *next; - - attr = status->attr_list; - while (attr != NULL) { - next = attr->next; - g_free (attr); - attr = next; - } - - g_free (status->mailbox); - g_free (status); -} - -gint -camel_imap4_untagged_status (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, guint32 index, camel_imap4_token_t *token, CamelException *ex) -{ - camel_imap4_status_attr_t *attr, *tail, *list = NULL; - GPtrArray *array = ic->user_data; - camel_imap4_status_t *status; - guchar *literal; - gchar *mailbox; - gsize len; - gint type; - gint i; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - switch (token->token) { - case CAMEL_IMAP4_TOKEN_ATOM: - mailbox = g_strdup (token->v.atom); - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - mailbox = g_strdup (token->v.qstring); - break; - case CAMEL_IMAP4_TOKEN_LITERAL: - if (camel_imap4_engine_literal (engine, &literal, &len, ex) == -1) - return -1; - - mailbox = (gchar *) literal; - break; - default: - fprintf (stderr, "Unexpected token in IMAP4 untagged STATUS response: %s%c\n", - token->token == CAMEL_IMAP4_TOKEN_NIL ? "NIL" : "", - (guchar) (token->token & 0xff)); - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - return -1; - } - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) { - g_free (mailbox); - return -1; - } - - if (token->token != '(') { - d(fprintf (stderr, "Expected to find a '(' token after the mailbox token in the STATUS response\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - g_free (mailbox); - return -1; - } - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) { - g_free (mailbox); - return -1; - } - - tail = (camel_imap4_status_attr_t *) &list; - - while (token->token == CAMEL_IMAP4_TOKEN_ATOM) { - /* parse the status messages list */ - type = CAMEL_IMAP4_STATUS_UNKNOWN; - for (i = 0; i < G_N_ELEMENTS (imap4_status); i++) { - if (!g_ascii_strcasecmp (imap4_status[i].name, token->v.atom)) { - type = imap4_status[i].type; - break; - } - } - - if (type == CAMEL_IMAP4_STATUS_UNKNOWN) - fprintf (stderr, "unrecognized token in STATUS list: %s\n", token->v.atom); - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token != CAMEL_IMAP4_TOKEN_NUMBER) - break; - - attr = g_new (camel_imap4_status_attr_t, 1); - attr->next = NULL; - attr->type = type; - attr->value = token->v.number; - - tail->next = attr; - tail = attr; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - } - - status = g_new (camel_imap4_status_t, 1); - status->mailbox = mailbox; - status->attr_list = list; - list = NULL; - - g_ptr_array_add (array, status); - - if (token->token != ')') { - d(fprintf (stderr, "Expected to find a ')' token terminating the untagged STATUS response\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - return -1; - } - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token != '\n') { - d(fprintf (stderr, "Expected to find a '\\n' token after the STATUS response\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - return -1; - } - - return 0; - - exception: - - g_free (mailbox); - - attr = list; - while (attr != NULL) { - list = attr->next; - g_free (attr); - attr = list; - } - - return -1; -} diff --git a/camel/providers/imap4/camel-imap4-utils.h b/camel/providers/imap4/camel-imap4-utils.h deleted file mode 100644 index ecf0d19..0000000 --- a/camel/providers/imap4/camel-imap4-utils.h +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * Authors: Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef CAMEL_IMAP4_UTILS_H -#define CAMEL_IMAP4_UTILS_H - -#include - -#include - -G_BEGIN_DECLS - -/* IMAP4 flag merging */ -typedef struct { - guint32 changed; - guint32 bits; -} flags_diff_t; - -void camel_imap4_flags_diff (flags_diff_t *diff, guint32 old, guint32 new); -guint32 camel_imap4_flags_merge (flags_diff_t *diff, guint32 flags); -guint32 camel_imap4_merge_flags (guint32 original, guint32 local, guint32 server); - -struct _CamelFolderInfo; -struct _CamelIMAP4Engine; -struct _CamelIMAP4Command; -struct _CamelFolderSummary; -struct _camel_imap4_token_t; -struct _CamelIMAP4StoreSummary; -struct _CamelIMAP4NamespaceList; -struct _CamelIMAP4Namespace; - -struct _CamelFolderInfo *camel_imap4_build_folder_info_tree (GPtrArray *array, const gchar *top); - -void camel_imap4_namespace_clear (struct _CamelIMAP4Namespace **ns); -struct _CamelIMAP4NamespaceList *camel_imap4_namespace_list_copy (const struct _CamelIMAP4NamespaceList *nsl); -void camel_imap4_namespace_list_free (struct _CamelIMAP4NamespaceList *nsl); - -gchar camel_imap4_get_path_delim (struct _CamelIMAP4StoreSummary *s, const gchar *full_name); - -gint camel_imap4_get_uid_set (struct _CamelIMAP4Engine *engine, struct _CamelFolderSummary *summary, GPtrArray *infos, gint cur, gsize linelen, gchar **set); - -void camel_imap4_utils_set_unexpected_token_error (CamelException *ex, struct _CamelIMAP4Engine *engine, struct _camel_imap4_token_t *token); - -gint camel_imap4_parse_flags_list (struct _CamelIMAP4Engine *engine, guint32 *flags, CamelException *ex); - -/* Note: make sure these don't clash with any bit flags in camel-store.h */ -#define CAMEL_IMAP4_FOLDER_MARKED (1 << 17) -#define CAMEL_IMAP4_FOLDER_UNMARKED (1 << 18) - -typedef struct { - guint32 flags; - gchar delim; - gchar *name; -} camel_imap4_list_t; - -gint camel_imap4_untagged_list (struct _CamelIMAP4Engine *engine, struct _CamelIMAP4Command *ic, - guint32 index, struct _camel_imap4_token_t *token, CamelException *ex); - -enum { - CAMEL_IMAP4_STATUS_UNKNOWN, - CAMEL_IMAP4_STATUS_MESSAGES, - CAMEL_IMAP4_STATUS_RECENT, - CAMEL_IMAP4_STATUS_UIDNEXT, - CAMEL_IMAP4_STATUS_UIDVALIDITY, - CAMEL_IMAP4_STATUS_UNSEEN, -}; - -typedef struct _camel_imap4_status_attr { - struct _camel_imap4_status_attr *next; - guint32 type; - guint32 value; -} camel_imap4_status_attr_t; - -typedef struct { - camel_imap4_status_attr_t *attr_list; - gchar *mailbox; -} camel_imap4_status_t; - -void camel_imap4_status_free (camel_imap4_status_t *status); - -gint camel_imap4_untagged_status (struct _CamelIMAP4Engine *engine, struct _CamelIMAP4Command *ic, - guint32 index, struct _camel_imap4_token_t *token, CamelException *ex); - -G_END_DECLS - -#endif /* CAMEL_IMAP4_UTILS_H */ diff --git a/camel/providers/imap4/libcamelimap4.urls b/camel/providers/imap4/libcamelimap4.urls deleted file mode 100644 index 7ccb0b0..0000000 --- a/camel/providers/imap4/libcamelimap4.urls +++ /dev/null @@ -1 +0,0 @@ -imap4 diff --git a/configure.ac b/configure.ac index 4152a85..2617a59 100644 --- a/configure.ac +++ b/configure.ac @@ -987,22 +987,6 @@ AM_CONDITIONAL(ENABLE_NNTP, [test x$enable_nntp = xyes]) AC_DEFINE(HANDLE_LIBICAL_MEMORY, 1, [Define it once memory returned by libical is free'ed properly]) dnl ****************************** -dnl IMAP4rev1 code support. -dnl ****************************** -AC_ARG_ENABLE(imap4, - AS_HELP_STRING([--enable-imap4=no/yes], - [Attempt to compile yet another, incomplete, very unsupported IMAPv4r1 implementation]), - [],[enable_imap4=no]) - -if test "x$enable_imap4" = "xyes"; then - AC_DEFINE(ENABLE_IMAP4,1,[Really don't try this at home]) - msg_imap4="yes" -else - msg_imap4="no" -fi -AM_CONDITIONAL(ENABLE_IMAP4, [test x$enable_imap4 = xyes]) - -dnl ****************************** dnl Hula support dnl ****************************** AC_ARG_ENABLE([hula], @@ -1474,7 +1458,6 @@ camel/providers/groupwise/Makefile camel/providers/hula/Makefile camel/providers/imap/Makefile camel/providers/imapx/Makefile -camel/providers/imap4/Makefile camel/providers/local/Makefile camel/providers/nntp/Makefile camel/providers/pop3/Makefile -- 2.7.4