diff options
Diffstat (limited to 'camel/providers/imap4')
24 files changed, 0 insertions, 9894 deletions
diff --git a/camel/providers/imap4/.cvsignore b/camel/providers/imap4/.cvsignore deleted file mode 100644 index 08f5ed37d8..0000000000 --- a/camel/providers/imap4/.cvsignore +++ /dev/null @@ -1,7 +0,0 @@ -Makefile -Makefile.in -*.o -*.lo -*.la -.deps -.libs diff --git a/camel/providers/imap4/Makefile.am b/camel/providers/imap4/Makefile.am deleted file mode 100644 index 3cdf897f6a..0000000000 --- a/camel/providers/imap4/Makefile.am +++ /dev/null @@ -1,42 +0,0 @@ -## Process this file with automake to produce Makefile.in - -camel_provider_LTLIBRARIES = libcamelimap4.la -camel_provider_DATA = libcamelimap4.urls - -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/e-util \ - -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-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 - -EXTRA_DIST = libcamelimap4.urls diff --git a/camel/providers/imap4/camel-imap4-command.c b/camel/providers/imap4/camel-imap4-command.c deleted file mode 100644 index e869bee9c3..0000000000 --- a/camel/providers/imap4/camel-imap4-command.c +++ /dev/null @@ -1,706 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include <camel/camel-stream-null.h> -#include <camel/camel-stream-filter.h> -#include <camel/camel-mime-filter-crlf.h> -#include <camel/camel-i18n.h> - -#include "camel-imap4-stream.h" -#include "camel-imap4-engine.h" -#include "camel-imap4-folder.h" -#include "camel-imap4-specials.h" - -#include "camel-imap4-command.h" - - -#define d(x) x - - -enum { - IMAP4_STRING_ATOM, - IMAP4_STRING_QSTRING, - IMAP4_STRING_LITERAL, -}; - -static int -imap4_string_get_type (const char *str) -{ - int 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 char *str) -{ - while (is_atom (*str)) - str++; - - return *str == '\0'; -} - -static gboolean -imap4_string_is_quote_safe (const char *str) -{ - while (is_qsafe (*str)) - str++; - - return *str == '\0'; -} -#endif - -static size_t -camel_imap4_literal_length (CamelIMAP4Literal *literal) -{ - CamelStream *stream, *null; - CamelMimeFilter *crlf; - size_t 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 char *string) -{ - CamelIMAP4CommandPart *part; - CamelIMAP4Literal *literal; - - 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 */ - /* FIXME: need to escape stuff */ - g_string_append_printf (str, "\"%s\"", string); - 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 char *format, va_list args) -{ - CamelIMAP4CommandPart *parts, *part, *tail; - CamelIMAP4Command *ic; - const char *start; - GString *str; - - tail = parts = command_part_new (); - - str = g_string_new (""); - start = format; - - while (*format) { - register char ch = *format++; - - if (ch == '%') { - CamelIMAP4Literal *literal; - CamelIMAP4Folder *folder; - char *function, **strv; - unsigned int u; - char *string; - size_t len; - void *obj; - int 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, int); - g_string_append_c (str, c); - break; - case 'd': - /* integer */ - d = va_arg (args, int); - g_string_append_printf (str, "%d", d); - break; - case 'u': - /* unsigned integer */ - u = va_arg (args, unsigned int); - g_string_append_printf (str, "%u", u); - break; - case 'F': - /* CamelIMAP4Folder */ - folder = va_arg (args, CamelIMAP4Folder *); - string = (char *) camel_imap4_folder_utf7_name (folder); - imap4_command_append_string (engine, &tail, str, string); - break; - case 'L': - /* Literal */ - obj = va_arg (args, void *); - - 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, char **); - 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, char *); - imap4_command_append_string (engine, &tail, str, string); - break; - case 's': - /* safe atom string */ - string = va_arg (args, char *); - 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); - ((EDListNode *) ic)->next = NULL; - ((EDListNode *) ic)->prev = NULL; - ic->untagged = g_hash_table_new (g_str_hash, g_str_equal); - ic->status = CAMEL_IMAP4_COMMAND_QUEUED; - ic->resp_codes = g_ptr_array_new (); - ic->engine = engine; - ic->ref_count = 1; - ic->parts = parts; - ic->part = parts; - - camel_exception_init (&ic->ex); - - 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 char *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 char *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; - int 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 int -imap4_literal_write_to_stream (CamelIMAP4Literal *literal, CamelStream *stream) -{ - CamelStream *istream, *ostream = NULL; - CamelDataWrapper *wrapper; - CamelMimeFilter *crlf; - char *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", (unsigned char) (token->token & 0xff)); - break; - } -} - -int -camel_imap4_command_step (CamelIMAP4Command *ic) -{ - CamelIMAP4Engine *engine = ic->engine; - int result = CAMEL_IMAP4_RESULT_NONE; - CamelIMAP4Literal *literal; - camel_imap4_token_t token; - unsigned char *linebuf; - ssize_t nwritten; - size_t 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 d(!)0 - { - int sending = ic->part != ic->parts; - unsigned char *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); - } -#endif - - linebuf = ic->part->buffer; - len = ic->part->buflen; - - if ((nwritten = 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 "<tag> 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 "<tag> 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 d(!)0 - fprintf (stderr, "expected anything but this: "); - unexpected_token (&token); - fprintf (stderr, "\n"); -#endif - - goto unexpected; - } - - break; - } else { -#if d(!)0 - fprintf (stderr, "wtf is this: "); - unexpected_token (&token); - fprintf (stderr, "\n"); -#endif - - unexpected: - - /* no fucking clue what we got... */ - 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) -{ - int 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); - - 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 112695a0db..0000000000 --- a/camel/providers/imap4/camel-imap4-command.h +++ /dev/null @@ -1,144 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifndef __CAMEL_IMAP4_COMMAND_H__ -#define __CAMEL_IMAP4_COMMAND_H__ - -#include <stdarg.h> - -#include <glib.h> - -#include <libedataserver/e-msgport.h> - -#include <camel/camel-stream.h> -#include <camel/camel-exception.h> -#include <camel/camel-data-wrapper.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -struct _CamelIMAP4Engine; -struct _CamelIMAP4Folder; -struct _camel_imap4_token_t; - -typedef struct _CamelIMAP4Command CamelIMAP4Command; -typedef struct _CamelIMAP4Literal CamelIMAP4Literal; - -typedef int (* CamelIMAP4PlusCallback) (struct _CamelIMAP4Engine *engine, - CamelIMAP4Command *ic, - const unsigned char *linebuf, - size_t linelen, CamelException *ex); - -typedef int (* CamelIMAP4UntaggedCallback) (struct _CamelIMAP4Engine *engine, - CamelIMAP4Command *ic, - guint32 index, - struct _camel_imap4_token_t *token, - CamelException *ex); - -enum { - CAMEL_IMAP4_LITERAL_STRING, - CAMEL_IMAP4_LITERAL_STREAM, - CAMEL_IMAP4_LITERAL_WRAPPER, -}; - -struct _CamelIMAP4Literal { - int type; - union { - char *string; - CamelStream *stream; - CamelDataWrapper *wrapper; - } literal; -}; - -typedef struct _CamelIMAP4CommandPart { - struct _CamelIMAP4CommandPart *next; - unsigned char *buffer; - size_t 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 { - EDListNode node; - - struct _CamelIMAP4Engine *engine; - - unsigned int ref_count:26; - unsigned int status:3; - unsigned int result:3; - int id; - - char *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; - void *user_data; -}; - -CamelIMAP4Command *camel_imap4_command_new (struct _CamelIMAP4Engine *engine, struct _CamelIMAP4Folder *folder, - const char *format, ...); -CamelIMAP4Command *camel_imap4_command_newv (struct _CamelIMAP4Engine *engine, struct _CamelIMAP4Folder *folder, - const char *format, va_list args); - -void camel_imap4_command_register_untagged (CamelIMAP4Command *ic, const char *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 */ -int camel_imap4_command_step (CamelIMAP4Command *ic); - -void camel_imap4_command_reset (CamelIMAP4Command *ic); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#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 d6f17532ee..0000000000 --- a/camel/providers/imap4/camel-imap4-engine.c +++ /dev/null @@ -1,1698 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <ctype.h> -#include <errno.h> - -#include <camel/camel-sasl.h> -#include <camel/camel-stream-buffer.h> -#include <camel/camel-i18n.h> - -#include "camel-imap4-summary.h" -#include "camel-imap4-command.h" -#include "camel-imap4-stream.h" -#include "camel-imap4-folder.h" -#include "camel-imap4-utils.h" - -#include "camel-imap4-engine.h" - -#define d(x) 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 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_OBJECT_TYPE); - - 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; - - e_dlist_init (&engine->queue); -} - -static void -camel_imap4_engine_finalize (CamelObject *object) -{ - CamelIMAP4Engine *engine = (CamelIMAP4Engine *) object; - EDListNode *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 = e_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. - **/ -int -camel_imap4_engine_take_stream (CamelIMAP4Engine *engine, CamelStream *stream, CamelException *ex) -{ - camel_imap4_token_t token; - int 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: - - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - - camel_object_unref (engine->istream); - engine->istream = NULL; - camel_object_unref (engine->ostream); - engine->ostream = NULL; - - return -1; -} - - -/** - * 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. - **/ -int -camel_imap4_engine_capability (CamelIMAP4Engine *engine, CamelException *ex) -{ - CamelIMAP4Command *ic; - int 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); - - 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. - **/ -int -camel_imap4_engine_namespace (CamelIMAP4Engine *engine, CamelException *ex) -{ - camel_imap4_list_t *list; - GPtrArray *array = NULL; - CamelIMAP4Command *ic; - int 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. - **/ -int -camel_imap4_engine_select_folder (CamelIMAP4Engine *engine, CamelFolder *folder, CamelException *ex) -{ - CamelIMAP4RespCode *resp; - CamelIMAP4Command *ic; - int id, retval = 0; - int 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: - /*folder->mode = CAMEL_FOLDER_MODE_READ_ONLY;*/ - break; - case CAMEL_IMAP4_RESP_CODE_READWRITE: - /*folder->mode = CAMEL_FOLDER_MODE_READ_WRITE;*/ - 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 char *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 }, - { "QUOTA", CAMEL_IMAP4_CAPABILITY_QUOTA }, /* rfc2087 */ - { "ACL", CAMEL_IMAP4_CAPABILITY_ACL }, /* rfc2086 */ - { "IDLE", CAMEL_IMAP4_CAPABILITY_IDLE }, /* rfc2177 */ - { "MULTIAPPEND", CAMEL_IMAP4_CAPABILITY_MULTIAPPEND }, /* rfc3502 */ - { NULL, 0 } -}; - -static gboolean -auth_free (gpointer key, gpointer value, gpointer user_data) -{ - g_free (key); - return TRUE; -} - -static int -engine_parse_capability (CamelIMAP4Engine *engine, int sentinel, CamelException *ex) -{ - camel_imap4_token_t token; - int i; - - 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 int -engine_parse_flags_list (CamelIMAP4Engine *engine, CamelIMAP4RespCode *resp, int 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 int -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 int -engine_parse_namespace (CamelIMAP4Engine *engine, CamelException *ex) -{ - CamelIMAP4Namespace *namespaces[3], *node, *tail; - camel_imap4_token_t token; - int 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 { - /* invalid, fall thru */ - } - 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*<any TEXT-CHAR except "]">] - **/ - -static struct { - const char *name; - camel_imap4_resp_code_t code; - int 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. - **/ -int -camel_imap4_engine_parse_resp_code (CamelIMAP4Engine *engine, CamelException *ex) -{ - CamelIMAP4RespCode *resp = NULL; - camel_imap4_resp_code_t code; - camel_imap4_token_t token; - unsigned char *linebuf; - size_t 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_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*<any TEXT_CHAR except "]">] "]" */ - - /* 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 - **/ -int -camel_imap4_engine_handle_untagged_1 (CamelIMAP4Engine *engine, camel_imap4_token_t *token, CamelException *ex) -{ - int code = CAMEL_IMAP4_UNTAGGED_HANDLED; - CamelIMAP4Command *ic = engine->current; - CamelIMAP4UntaggedCallback untagged; - CamelFolder *folder; - unsigned int 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)) { - camel_imap4_summary_expunge (folder->summary, (int) 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 int -imap4_process_command (CamelIMAP4Engine *engine, CamelIMAP4Command *ic) -{ - int 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 char *cmd; - - ic = (CamelIMAP4Command *) engine->queue.head; - cmd = (const char *) 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 int -engine_state_change (CamelIMAP4Engine *engine, CamelIMAP4Command *ic) -{ - const char *cmd; - int 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. - **/ -int -camel_imap4_engine_iterate (CamelIMAP4Engine *engine) -{ - CamelIMAP4Command *ic, *nic; - GPtrArray *resp_codes; - int retval = -1; - - if (e_dlist_empty (&engine->queue)) - return 0; - - /* This sucks... 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 *) e_dlist_remhead (&engine->queue); - ic->status = CAMEL_IMAP4_COMMAND_ERROR; - camel_exception_xfer (&ic->ex, &rex); - 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 *) e_dlist_remhead (&engine->queue); - ic->status = CAMEL_IMAP4_COMMAND_ACTIVE; - - if (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 *) e_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; - } - - 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 char *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++; - e_dlist_addtail (&engine->queue, (EDListNode *) 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 char *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 (e_dlist_empty (&engine->queue)) { - e_dlist_addtail (&engine->queue, (EDListNode *) ic); - ic->id = engine->nextid++; - } else { - CamelIMAP4Command *nic; - EDListNode *node; - - node = (EDListNode *) ic; - e_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) -{ - EDListNode *node = (EDListNode *) ic; - - if (node->next == NULL && node->prev == NULL) - return; - - e_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. - **/ -int -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")); - - 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 - **/ -int -camel_imap4_engine_eat_line (CamelIMAP4Engine *engine, CamelException *ex) -{ - camel_imap4_token_t token; - unsigned char *literal; - int retval; - size_t 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")); - - 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 - **/ -int -camel_imap4_engine_line (CamelIMAP4Engine *engine, unsigned char **line, size_t *len, CamelException *ex) -{ - GByteArray *linebuf = NULL; - unsigned char *buf; - size_t buflen; - int 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")); - - 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. - **/ -int -camel_imap4_engine_literal (CamelIMAP4Engine *engine, unsigned char **literal, size_t *len, CamelException *ex) -{ - GByteArray *literalbuf = NULL; - unsigned char *buf; - size_t buflen; - int 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")); - - 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. - **/ -int -camel_imap4_engine_nstring (CamelIMAP4Engine *engine, unsigned char **nstring, CamelException *ex) -{ - camel_imap4_token_t token; - size_t 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 b4d8df2e8d..0000000000 --- a/camel/providers/imap4/camel-imap4-engine.h +++ /dev/null @@ -1,234 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifndef __CAMEL_IMAP4_ENGINE_H__ -#define __CAMEL_IMAP4_ENGINE_H__ - -#include <stdarg.h> - -#include <glib.h> - -#include <libedataserver/e-msgport.h> - -#include <camel/camel-stream.h> -#include <camel/camel-folder.h> -#include <camel/camel-session.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#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)) - -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_useful_lsub = (1 << 12), - CAMEL_IMAP4_CAPABILITY_utf8_search = (1 << 13), -}; - -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; - char *parse; - guint32 uidnext; - guint32 uidvalidity; - guint32 unseen; - char *newname[2]; - struct { - guint32 uidvalidity; - guint32 uid; - } appenduid; - struct { - guint32 uidvalidity; - char *srcset; - char *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; - char *path; - char 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_object; - - 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; - - unsigned char tagprefix; /* 'A'..'Z' */ - unsigned int tag; /* next command tag */ - int nextid; - - struct _CamelIMAP4Folder *folder; /* currently selected folder */ - - EDList queue; /* queue of waiting commands */ - struct _CamelIMAP4Command *current; -}; - -struct _CamelIMAP4EngineClass { - CamelObjectClass parent_class; - - unsigned char 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 */ -int camel_imap4_engine_take_stream (CamelIMAP4Engine *engine, CamelStream *stream, CamelException *ex); - -int camel_imap4_engine_capability (CamelIMAP4Engine *engine, CamelException *ex); -int camel_imap4_engine_namespace (CamelIMAP4Engine *engine, CamelException *ex); - -int camel_imap4_engine_select_folder (CamelIMAP4Engine *engine, CamelFolder *folder, CamelException *ex); - -struct _CamelIMAP4Command *camel_imap4_engine_queue (CamelIMAP4Engine *engine, CamelFolder *folder, - const char *format, ...); -struct _CamelIMAP4Command *camel_imap4_engine_prequeue (CamelIMAP4Engine *engine, CamelFolder *folder, - const char *format, ...); - -void camel_imap4_engine_dequeue (CamelIMAP4Engine *engine, struct _CamelIMAP4Command *ic); - -int camel_imap4_engine_iterate (CamelIMAP4Engine *engine); - - -/* untagged response utility functions */ -int 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 */ -int camel_imap4_engine_next_token (CamelIMAP4Engine *engine, struct _camel_imap4_token_t *token, CamelException *ex); -int camel_imap4_engine_line (CamelIMAP4Engine *engine, unsigned char **line, size_t *len, CamelException *ex); -int camel_imap4_engine_literal (CamelIMAP4Engine *engine, unsigned char **literal, size_t *len, CamelException *ex); -int camel_imap4_engine_nstring (CamelIMAP4Engine *engine, unsigned char **nstring, CamelException *ex); -int camel_imap4_engine_eat_line (CamelIMAP4Engine *engine, CamelException *ex); - - -/* response code stuff */ -int camel_imap4_engine_parse_resp_code (CamelIMAP4Engine *engine, CamelException *ex); -void camel_imap4_resp_code_free (CamelIMAP4RespCode *rcode); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#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 9326dd418f..0000000000 --- a/camel/providers/imap4/camel-imap4-folder.c +++ /dev/null @@ -1,1178 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <glib.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <dirent.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <time.h> - -#include <camel/camel-utf8.h> -#include <camel/camel-private.h> -#include <camel/camel-file-utils.h> -#include <camel/camel-mime-message.h> -#include <camel/camel-stream-mem.h> -#include <camel/camel-stream-filter.h> -#include <camel/camel-mime-filter-crlf.h> -#include <camel/camel-i18n.h> - -#include "camel-imap4-utils.h" -#include "camel-imap4-store.h" -#include "camel-imap4-engine.h" -#include "camel-imap4-folder.h" -#include "camel-imap4-stream.h" -#include "camel-imap4-command.h" -#include "camel-imap4-summary.h" -#include "camel-imap4-search.h" - -#define d(x) x - -static GSList *imap4_folder_props = NULL; - -static CamelProperty imap4_prop_list[] = { - { CAMEL_IMAP4_FOLDER_SYNC_OFFLINE, "sync_offline", N_("Copy folder content locally for offline operation") }, -}; - -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 int imap4_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args); -static int 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 char *uid, CamelException *ex); -static void imap4_append_message (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **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 char *expr, CamelException *ex); -static GPtrArray *imap4_search_by_uids (CamelFolder *folder, const char *expr, GPtrArray *uids, CamelException *ex); -static void imap4_search_free (CamelFolder *folder, GPtrArray *uids); - - -static CamelFolderClass *parent_class = NULL; - - -CamelType -camel_imap4_folder_get_type (void) -{ - static CamelType type = 0; - - if (!type) { - type = camel_type_register (CAMEL_FOLDER_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; - int i; - - parent_class = (CamelFolderClass *) camel_type_get_global_classfuncs (CAMEL_FOLDER_TYPE); - - 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; -} - -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->sync_offline = FALSE; - folder->utf7_name = NULL; - folder->cachedir = NULL; - folder->search = NULL; -} - -static void -camel_imap4_folder_finalize (CamelObject *object) -{ - CamelIMAP4Folder *folder = (CamelIMAP4Folder *) object; - - camel_object_unref (folder->search); - - if (folder->cache) - camel_object_unref (folder->cache); - - g_free (folder->utf7_name); - g_free (folder->cachedir); -} - -static int -imap4_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args) -{ - CamelArgGetV props; - int 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_SYNC_OFFLINE: - *arg->ca_int = ((CamelIMAP4Folder *) object)->sync_offline; - 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 int -imap4_setv (CamelObject *object, CamelException *ex, CamelArgV *args) -{ - CamelIMAP4Folder *folder = (CamelIMAP4Folder *) object; - gboolean save = FALSE; - guint32 tag; - int 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_SYNC_OFFLINE: - if (folder->sync_offline != arg->ca_int) { - folder->sync_offline = 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 char * -imap_get_summary_filename (const char *path) -{ - /* /path/to/imap/summary */ - return g_build_filename (path, "summary", NULL); -} - -static char * -imap_build_filename (const char *toplevel_dir, const char *full_name) -{ - const char *inptr = full_name; - int subdirs = 0; - char *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 char * -imap_store_build_filename (void *store, const char *full_name) -{ - CamelIMAP4Store *imap_store = (CamelIMAP4Store *) store; - char *toplevel_dir; - char *path; - - toplevel_dir = g_strdup_printf ("%s/folders", imap_store->storage_path); - path = imap_build_filename (toplevel_dir, full_name); - g_free (toplevel_dir); - - return path; -} - - -CamelFolder * -camel_imap4_folder_new (CamelStore *store, const char *full_name, CamelException *ex) -{ - CamelIMAP4Folder *imap_folder; - char *utf7_name, *name, *p; - CamelFolder *folder; - char *path; - char sep; - - if (!(p = strrchr (full_name, '/'))) - p = (char *) 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 *) (imap_folder = (CamelIMAP4Folder *) camel_object_new (CAMEL_TYPE_IMAP4_FOLDER)); - camel_folder_construct (folder, store, full_name, name); - imap_folder->utf7_name = utf7_name; - - folder->summary = camel_imap4_summary_new (folder); - imap_folder->cachedir = imap_store_build_filename (store, folder->full_name); - camel_mkdir (imap_folder->cachedir, 0777); - - imap_folder->cache = camel_data_cache_new (imap_folder->cachedir, 0, NULL); - - path = imap_get_summary_filename (imap_folder->cachedir); - camel_folder_summary_set_filename (folder->summary, path); - g_free (path); - - imap_folder->search = camel_imap4_search_new (((CamelIMAP4Store *) store)->engine, imap_folder->cachedir); - - if (camel_session_is_online (((CamelService *) store)->session)) { - /* 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 char * -camel_imap4_folder_utf7_name (CamelIMAP4Folder *folder) -{ - return folder->utf7_name; -} - - -static struct { - const char *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 int -imap4_sync_flag (CamelFolder *folder, GPtrArray *infos, char onoff, const char *flag, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - CamelIMAP4Command *ic; - int i, id, retval = 0; - char *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"), - 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 int -imap4_sync_changes (CamelFolder *folder, GPtrArray *sync, CamelException *ex) -{ - CamelIMAP4MessageInfo *iinfo; - GPtrArray *on_set, *off_set; - CamelMessageInfo *info; - flags_diff_t diff; - int retval = 0; - int i, j; - - if (folder->permanent_flags == 0) - return 0; - - 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; - CamelSession *session = ((CamelService *) folder->parent_store)->session; - CamelIMAP4MessageInfo *iinfo; - CamelMessageInfo *info; - CamelIMAP4Command *ic; - flags_diff_t diff; - GPtrArray *sync; - int id, max, i; - int retval; - - if (!camel_session_is_online (session)) - return; - - CAMEL_SERVICE_LOCK (folder->parent_store, connect_lock); - - /* gather a list of changes to sync to the server */ - 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) { - 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"), - 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_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; - CamelSession *session = ((CamelService *) folder->parent_store)->session; - CamelFolder *selected = (CamelFolder *) engine->folder; - CamelIMAP4Command *ic; - int id; - - if (!camel_session_is_online (session)) - return; - - CAMEL_SERVICE_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_UNLOCK (folder->parent_store, connect_lock); -} - -static int -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? */ - fprintf (stderr, "huh? %s?...\n", token->v.atom); - } - } while (1); - - if (token->token != ')') { - 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 char *uid, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - CamelSession *session = ((CamelService *) folder->parent_store)->session; - CamelIMAP4Folder *imap_folder = (CamelIMAP4Folder *) folder; - CamelMimeMessage *message = NULL; - CamelStream *stream, *cache; - CamelIMAP4Command *ic; - int id; - - CAMEL_SERVICE_LOCK (folder->parent_store, connect_lock); - - if (imap_folder->cache && (stream = camel_data_cache_get (imap_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_UNLOCK (folder->parent_store, connect_lock); - camel_exception_setv (ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); - 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_UNLOCK (folder->parent_store, connect_lock); - return message; - } - - if (!camel_session_is_online (session)) { - CAMEL_SERVICE_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 *mush* 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 (imap_folder->cache && (cache = camel_data_cache_add (imap_folder->cache, "cache", uid, NULL))) { - if (camel_stream_write_to_stream (stream, cache) == -1 - || camel_stream_flush (cache) == -1) - camel_data_cache_remove (imap_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_UNLOCK (folder->parent_store, connect_lock); - - return message; -} - -static char *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, char **appended_uid, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - CamelSession *session = ((CamelService *) folder->parent_store)->session; - CamelIMAP4Summary *summary = (CamelIMAP4Summary *) folder->summary; - const CamelIMAP4MessageInfo *iinfo = (const CamelIMAP4MessageInfo *)info; - CamelIMAP4RespCode *resp; - CamelIMAP4Command *ic; - CamelFolderInfo *fi; - CamelException lex; - char flags[100], *p; - char date[50]; - struct tm tm; - int id, i; - - if (appended_uid) - *appended_uid = NULL; - - if (!camel_session_is_online (session)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot append messages to IMAP folders in offline mode.")); - return; - } - - CAMEL_SERVICE_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) -1) { - int tzone; - -#ifdef HAVE_LOCALTIME_R - localtime_r (&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: - - if (engine->capa & CAMEL_IMAP4_CAPABILITY_UIDPLUS) - ic = camel_imap4_engine_queue (engine, NULL, "UID APPEND %F%s%s %L\r\n", flags, date, message); - else - ic = camel_imap4_engine_queue (engine, NULL, "APPEND %F%s%s %L\r\n", 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_UNLOCK (folder->parent_store, connect_lock); - return; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - if (!(engine->capa & CAMEL_IMAP4_CAPABILITY_UIDPLUS)) - break; - - if (!appended_uid) - 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) { - char *parent_name, *p; - - parent_name = g_alloca (strlen (folder->full_name) + 1); - 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_UNLOCK (folder->parent_store, connect_lock); -} - - -static int -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; - CamelSession *session = ((CamelService *) src->parent_store)->session; - int i, j, n, id, dest_namelen; - CamelMessageInfo *info; - CamelIMAP4Command *ic; - GPtrArray *infos; - char *set; - - if (!camel_session_is_online (session)) { - if (move) - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot move messages to or from IMAP folders in offline mode.")); - else - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot copy messages to or from IMAP folders in offline mode.")); - - 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_LOCK (src->parent_store, connect_lock); - - 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); - - 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"), - src->full_name, dest->full_name); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot copy messages from folder `%s' to folder `%s': Unknown"), - 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) { - 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_LOCK (src->parent_store, connect_lock); -} - -static GPtrArray * -imap4_search_by_expression (CamelFolder *folder, const char *expr, CamelException *ex) -{ - CamelIMAP4Folder *imap4_folder = (CamelIMAP4Folder *) folder; - GPtrArray *matches; - - CAMEL_SERVICE_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_UNLOCK(folder->parent_store, connect_lock); - - return matches; -} - -static GPtrArray * -imap4_search_by_uids (CamelFolder *folder, const char *expr, GPtrArray *uids, CamelException *ex) -{ - CamelIMAP4Folder *imap4_folder = (CamelIMAP4Folder *) folder; - GPtrArray *matches; - - if (uids->len == 0) - return g_ptr_array_new (); - - CAMEL_SERVICE_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_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_LOCK(folder->parent_store, connect_lock); - - camel_folder_search_free_result (imap4_folder->search, uids); - - CAMEL_SERVICE_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 ae0263f31d..0000000000 --- a/camel/providers/imap4/camel-imap4-folder.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifndef __CAMEL_IMAP4_FOLDER_H__ -#define __CAMEL_IMAP4_FOLDER_H__ - -#include <camel/camel-store.h> -#include <camel/camel-folder.h> -#include <camel/camel-data-cache.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#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)) - -typedef struct _CamelIMAP4Folder CamelIMAP4Folder; -typedef struct _CamelIMAP4FolderClass CamelIMAP4FolderClass; - -enum { - CAMEL_IMAP4_FOLDER_ARG_SYNC_OFFLINE = CAMEL_FOLDER_ARG_LAST, - CAMEL_IMAP4_FOLDER_ARG_LAST = CAMEL_FOLDER_ARG_LAST + 0x100 -}; - - -enum { - CAMEL_IMAP4_FOLDER_SYNC_OFFLINE = CAMEL_IMAP4_FOLDER_ARG_SYNC_OFFLINE | CAMEL_ARG_BOO, -}; - -struct _CamelIMAP4Folder { - CamelFolder parent_object; - - unsigned int sync_offline:1; - - CamelFolderSearch *search; - CamelDataCache *cache; - - char *cachedir; - char *utf7_name; -}; - -struct _CamelIMAP4FolderClass { - CamelFolderClass parent_class; - -}; - - -CamelType camel_imap4_folder_get_type (void); - -CamelFolder *camel_imap4_folder_new (CamelStore *store, const char *full_name, CamelException *ex); - -const char *camel_imap4_folder_utf7_name (CamelIMAP4Folder *folder); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_IMAP4_FOLDER_H__ */ diff --git a/camel/providers/imap4/camel-imap4-provider.c b/camel/providers/imap4/camel-imap4-provider.c deleted file mode 100644 index fa529e0c2a..0000000000 --- a/camel/providers/imap4/camel-imap4-provider.c +++ /dev/null @@ -1,151 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> - -#include <camel/camel-sasl.h> -#include <camel/camel-provider.h> -#include <camel/camel-i18n.h> - -#include "camel-imap4-store.h" - - -CamelProviderConfEntry imap4_conf_entries[] = { - { CAMEL_PROVIDER_CONF_SECTION_START, "mailcheck", NULL, - N_("Checking for new mail") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "check_all", NULL, - N_("Check for new messages in all folders"), "1" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_SECTION_START, "folders", NULL, - N_("Folders") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "use_lsub", NULL, - N_("Show only subscribed folders"), "1" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "override_namespace", NULL, - N_("Override server-supplied folder namespace"), "0" }, - { CAMEL_PROVIDER_CONF_ENTRY, "namespace", "override_namespace", - N_("Namespace") }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_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 messages in the INBOX folder"), "0" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "sync_offline", NULL, - N_("Automatically synchronize remote mail locally"), "0" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider imap4_provider = { - "imap4", - N_("IMAPv4rev1"), - - N_("For reading and storing mail on IMAPv4rev1 servers. EXPERIMENTAL !!"), - - "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, char *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->authmech); - add_hash (&hash, u->host); - hash ^= u->port; - - return hash; -} - -static int -check_equal (char *s1, char *s2) -{ - if (s1 == NULL) { - if (s2 == NULL) - return TRUE; - else - return FALSE; - } - - if (s2 == NULL) - return FALSE; - - return strcmp (s1, s2) == 0; -} - -static int -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->authmech, u2->authmech) - && 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); - - 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 7102e2fa0f..0000000000 --- a/camel/providers/imap4/camel-imap4-search.c +++ /dev/null @@ -1,314 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast <fejj@novell.com> - * Michael Zucchi <notzed@ximian.com> - * - * Copyright 2004 Novell, Inc. (www.novell.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <ctype.h> - -#include "camel-imap4-command.h" -#include "camel-imap4-engine.h" -#include "camel-imap4-stream.h" -#include "camel-imap4-utils.h" - -#include "camel-imap4-search.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, int 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 char *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 int -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; - char 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, (char *) 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, int argc, struct _ESExpResult **argv, CamelFolderSearch *search) -{ - CamelIMAP4Search *imap4_search = (CamelIMAP4Search *) search; - CamelIMAP4Engine *engine = imap4_search->engine; - GPtrArray *strings, *matches, *infos; - register const unsigned char *inptr; - gboolean utf8_search = FALSE; - GPtrArray *summary_set; - CamelMessageInfo *info; - CamelIMAP4Command *ic; - const char *expr; - ESExpResult *r; - int id, i, n; - size_t used; - char *set; - - 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] = (char *) 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 = (unsigned char *) argv[i]->value.string; - while (*inptr != '\0') { - if (!isascii ((int) *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] = (char *) 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)) { - int 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 char *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 5165367cfb..0000000000 --- a/camel/providers/imap4/camel-imap4-search.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast <fejj@novell.com> - * - * Copyright 2004 Novell, Inc. (www.novell.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef __CAMEL_IMAP4_SEARCH_H__ -#define __CAMEL_IMAP4_SEARCH_H__ - -#include <camel/camel-folder-search.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#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 ()) - -typedef struct _CamelIMAP4Search CamelIMAP4Search; -typedef struct _CamelIMAP4SearchClass CamelIMAP4SearchClass; - -struct _CamelIMAP4Engine; - -struct _CamelIMAP4Search { - CamelFolderSearch parent_object; - - struct _CamelIMAP4Engine *engine; -}; - -struct _CamelIMAP4SearchClass { - CamelFolderSearchClass parent_class; - -}; - - -CamelType camel_imap4_search_get_type (void); - -CamelFolderSearch *camel_imap4_search_new (struct _CamelIMAP4Engine *engine, const char *cachedir); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#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 4682a403e4..0000000000 --- a/camel/providers/imap4/camel-imap4-specials.c +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> - -#include "camel-imap4-specials.h" - -#define CHARS_ATOM_SPECIALS "(){]" -#define CHARS_LWSP " \t\r\n" -#define CHARS_QUOTED_SPECIALS "\\\"" -#define CHARS_LIST_WILDCARDS "*%" - -unsigned char 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, int remove, unsigned char *vals) -{ - int 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) -{ - int 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 36765cdc6b..0000000000 --- a/camel/providers/imap4/camel-imap4-specials.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifndef __CAMEL_IMAP4_SPECIALS_H__ -#define __CAMEL_IMAP4_SPECIALS_H__ - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -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 unsigned char camel_imap4_specials[256]; - -#define is_atom(x) ((camel_imap4_specials[(unsigned char)(x)] & (IS_ASPECIAL|IS_SPACE|IS_CTRL|IS_WILDCARD|IS_QSPECIAL)) == 0) -#define is_ctrl(x) ((camel_imap4_specials[(unsigned char)(x)] & IS_CTRL) != 0) -#define is_lwsp(x) ((camel_imap4_specials[(unsigned char)(x)] & IS_LWSP) != 0) -#define is_type(x, t) ((camel_imap4_specials[(unsigned char)(x)] & (t)) != 0) -#define is_qsafe(x) ((camel_imap4_specials[(unsigned char)(x)] & (IS_QSPECIAL|IS_CTRL)) == 0) -#define is_wild(x) ((camel_imap4_specials[(unsigned char)(x)] & IS_WILDCARD) != 0) - -void camel_imap4_specials_init (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#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 ffa4bd05f1..0000000000 --- a/camel/providers/imap4/camel-imap4-store-summary.c +++ /dev/null @@ -1,402 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast <fejj@novell.com> - * - * Copyright 2004 Novell, Inc. (www.novell.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -#include <camel/camel-store.h> -#include <camel/camel-file-utils.h> - -#include "camel-imap4-utils.h" -#include "camel-imap4-store-summary.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 int summary_header_load (CamelStoreSummary *s, FILE *in); -static int summary_header_save (CamelStoreSummary *s, FILE *out); - -static CamelStoreInfo *store_info_load (CamelStoreSummary *s, FILE *in); -static int 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; - 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; - char *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 int -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 int -save_namespaces (FILE *out, CamelIMAP4NamespaceList *nsl) -{ - CamelIMAP4Namespace *cur, *ns; - 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 int -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 int -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; - - fi = g_malloc0 (sizeof (CamelFolderInfo)); - fi->full_name = g_strdup (camel_store_info_path (s, si)); - fi->name = g_strdup (camel_store_info_name (s, si)); - fi->uri = g_strdup (camel_store_info_uri (s, si)); - fi->flags = si->flags; - fi->unread = si->unread; - fi->total = si->total; - - return fi; -} - -CamelFolderInfo * -camel_imap4_store_summary_get_folder_info (CamelIMAP4StoreSummary *s, const char *top, guint32 flags) -{ - CamelStoreSummary *ss = (CamelStoreSummary *) s; - CamelFolderInfo *fi; - GPtrArray *folders; - CamelStoreInfo *si; - size_t toplen, len; - int 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; - - if (toplen > 0 && (len = strlen (si->path)) > 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_folder_info_build (folders, top, '/', TRUE); - 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 4a5af80d03..0000000000 --- a/camel/providers/imap4/camel-imap4-store-summary.h +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast <fejj@novell.com> - * - * Copyright 2004 Novell, Inc. (www.novell.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef __CAMEL_IMAP_STORE_SUMMARY_H__ -#define __CAMEL_IMAP_STORE_SUMMARY_H__ - -#include <camel/camel-store-summary.h> -#include "camel-imap4-engine.h" - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#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 ()) - -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 char *top, guint32 flags); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#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 2e7308d75d..0000000000 --- a/camel/providers/imap4/camel-imap4-store.c +++ /dev/null @@ -1,1448 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> - -#include <camel/camel-sasl.h> -#include <camel/camel-utf8.h> -#include <camel/camel-tcp-stream-raw.h> -#include <camel/camel-tcp-stream-ssl.h> - -#include <camel/camel-private.h> - -#include <camel/camel-i18n.h> -#include <camel/camel-net-utils.h> - -#include "camel-imap4-store.h" -#include "camel-imap4-engine.h" -#include "camel-imap4-folder.h" -#include "camel-imap4-stream.h" -#include "camel-imap4-command.h" -#include "camel-imap4-utils.h" -#include "camel-imap4-summary.h" -#include "camel-imap4-store-summary.h" - -#define d(x) 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 char *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 char *folder_name, guint32 flags, CamelException *ex); -static CamelFolderInfo *imap4_create_folder (CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex); -static void imap4_delete_folder (CamelStore *store, const char *folder_name, CamelException *ex); -static void imap4_rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex); -static CamelFolderInfo *imap4_get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex); -static void imap4_subscribe_folder (CamelStore *store, const char *folder_name, CamelException *ex); -static void imap4_unsubscribe_folder (CamelStore *store, const char *folder_name, CamelException *ex); -static void imap4_noop (CamelStore *store, CamelException *ex); - - -static CamelStoreClass *parent_class = NULL; - - -CamelType -camel_imap4_store_get_type (void) -{ - static CamelType type = 0; - - if (!type) { - type = camel_type_register (CAMEL_STORE_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 int -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 = (CamelStoreClass *) camel_type_get_global_classfuncs (CAMEL_STORE_TYPE); - - 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->subscribe_folder = imap4_subscribe_folder; - store_class->unsubscribe_folder = imap4_unsubscribe_folder; - 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; - char *buf; - - CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); - if (camel_exception_is_set (ex)) - return; - - 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 char * -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, -}; - -#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) - -static gboolean -connect_to_server (CamelIMAP4Engine *engine, struct addrinfo *ai, int ssl_mode, CamelException *ex) -{ - CamelService *service = engine->service; - CamelStream *tcp_stream; - CamelIMAP4Command *ic; - int id, ret; - - 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 ((ret = camel_tcp_stream_connect ((CamelTcpStream *) tcp_stream, ai)) == -1) { - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Connection cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s: %s"), - service->url->host, - g_strerror (errno)); - - camel_object_unref (tcp_stream); - - return FALSE; - } - - 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; - } - - if (!(engine->capa & CAMEL_IMAP4_CAPABILITY_STARTTLS)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to IMAP server %s in secure mode: %s"), - service->url->host, _("SSL negotiations failed")); - - 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); - - return TRUE; -} - -static struct { - char *value; - char *serv; - char *port; - int 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 char *ssl_mode; - int mode, ret, i; - const char *port; - char *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; - - if (!(ret = connect_to_server (engine, ai, mode, ex)) && mode == MODE_SSL) { - camel_exception_clear (ex); - ret = connect_to_server (engine, ai, MODE_TLS, ex); - } else if (!ret && mode == MODE_TLS) { - camel_exception_clear (ex); - ret = connect_to_server (engine, ai, MODE_CLEAR, ex); - } - - camel_freeaddrinfo (ai); - - return ret; -} - -static int -sasl_auth (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, const unsigned char *linebuf, size_t linelen, CamelException *ex) -{ - /* Perform a single challenge iteration */ - CamelSasl *sasl = ic->user_data; - char *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 char *) 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 int -imap4_try_authenticate (CamelIMAP4Engine *engine, gboolean reprompt, const char *errmsg, CamelException *ex) -{ - CamelService *service = engine->service; - CamelSession *session = service->session; - CamelSasl *sasl = NULL; - CamelIMAP4Command *ic; - int id; - - if (!service->url->passwd) { - guint32 flags = CAMEL_SESSION_PASSWORD_SECRET; - char *prompt; - - if (reprompt) - flags |= CAMEL_SESSION_PASSWORD_REPROMPT; - - prompt = g_strdup_printf (_("%sPlease enter the IMAP password for %s on host %s"), - errmsg ? errmsg : "", - service->url->user, - service->url->host); - - service->url->passwd = camel_session_get_password (session, service, NULL, prompt, "password", flags, ex); - - g_free (prompt); - - if (!service->url->passwd) - return FALSE; - } - - if (service->url->authmech) { - CamelServiceAuthType *mech; - - mech = g_hash_table_lookup (engine->authtypes, 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; - CamelServiceAuthType *mech; - gboolean reprompt = FALSE; - char *errmsg = NULL; - CamelException lex; - - if (!connect_to_server_wrapper (engine, ex)) - return FALSE; - -#define CANT_USE_AUTHMECH (!(mech = 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_strdup (lex.desc); - 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 (!camel_session_is_online (service->session)) - return TRUE; - - CAMEL_SERVICE_LOCK (service, connect_lock); - if (store->engine->state == CAMEL_IMAP4_ENGINE_DISCONNECTED) - retval = imap4_reconnect (store->engine, ex); - else - retval = TRUE; - CAMEL_SERVICE_UNLOCK (service, connect_lock); - - return retval; -} - -static gboolean -imap4_disconnect (CamelService *service, gboolean clean, CamelException *ex) -{ - CamelIMAP4Store *store = (CamelIMAP4Store *) service; - CamelIMAP4Command *ic; - int id; - - if (!camel_session_is_online (service->session)) - return TRUE; - - CAMEL_SERVICE_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_UNLOCK (store, connect_lock); - - return 0; -} - -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 (!camel_session_is_online (service->session)) - return NULL; - - CAMEL_SERVICE_LOCK (store, connect_lock); - connected = connect_to_server_wrapper (store->engine, ex); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - if (!connected) - return NULL; - - sasl_types = camel_sasl_authtype_list (FALSE); - for (t = sasl_types; t; t = next) { - authtype = t->data; - next = t->next; - - if (!g_hash_table_lookup (store->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 char * -imap4_folder_utf7_name (CamelStore *store, const char *folder_name, char wildcard) -{ - char *real_name, *p; - char sep = '\0'; - int 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 char *folder_name, guint32 flags, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelSession *session = ((CamelService *) store)->session; - CamelFolder *folder = NULL; - camel_imap4_list_t *list; - CamelIMAP4Command *ic; - CamelFolderInfo *fi; - GPtrArray *array; - char *utf7_name; - int create; - int id, i; - - CAMEL_SERVICE_LOCK (store, connect_lock); - - if (!camel_session_is_online (session)) { - 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_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"), - folder_name, ((CamelService *) store)->url->host); - camel_imap4_command_unref (ic); - goto done; - } - - camel_imap4_command_unref (ic); - - if (create) { - const char *basename; - char *parent; - int 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_UNLOCK (store, connect_lock); - - return folder; -} - -static CamelFolderInfo * -imap4_create_folder (CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex) -{ - /* FIXME: also need to deal with parent folders that can't - * contain subfolders - delete them and re-create with the - * proper hint */ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelSession *session = ((CamelService *) store)->session; - CamelFolderInfo *fi = NULL; - CamelIMAP4Command *ic; - char *utf7_name; - CamelURL *url; - const char *c; - char *name; - char sep; - int id; - - 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 (!camel_session_is_online (session)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create IMAP folders in offline mode.")); - return NULL; - } - - if (parent_name != NULL && *parent_name) - name = g_strdup_printf ("%s/%s", parent_name, folder_name); - else - name = g_strdup (folder_name); - - CAMEL_SERVICE_LOCK (store, connect_lock); - - utf7_name = imap4_folder_utf7_name (store, name, '\0'); - ic = camel_imap4_engine_queue (engine, NULL, "CREATE %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); - g_free (name); - goto done; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - url = camel_url_copy (engine->url); - camel_url_set_fragment (url, name); - - c = strrchr (name, '/'); - - fi = g_malloc0 (sizeof (CamelFolderInfo)); - fi->full_name = name; - fi->name = g_strdup (c ? c + 1: 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"), - name); - g_free (name); - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create folder `%s': Bad command"), - name); - g_free (name); - break; - default: - g_assert_not_reached (); - } - - camel_imap4_command_unref (ic); - - done: - - CAMEL_SERVICE_UNLOCK (store, connect_lock); - - return fi; -} - -static void -imap4_delete_folder (CamelStore *store, const char *folder_name, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelSession *session = ((CamelService *) store)->session; - CamelFolder *selected = (CamelFolder *) engine->folder; - CamelIMAP4Command *ic, *ic0 = NULL; - CamelFolderInfo *fi; - char *utf7_name; - CamelURL *url; - const char *p; - int 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 (!camel_session_is_online (session)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot delete IMAP folders in offline mode.")); - return; - } - - CAMEL_SERVICE_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_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 = g_malloc0 (sizeof (CamelFolderInfo)); - 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_UNLOCK (store, connect_lock); -} - -static void -imap4_rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelSession *session = ((CamelService *) store)->session; - char *old_uname, *new_uname; - CamelIMAP4Command *ic; - int 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 (!camel_session_is_online (session)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot rename IMAP folders in offline mode.")); - return; - } - - CAMEL_SERVICE_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_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_UNLOCK (store, connect_lock); -} - -static int -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; - int 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 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; - char *mailbox; - int 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 CamelFolderInfo * -imap4_build_folder_info (CamelStore *store, const char *top, guint32 flags, GPtrArray *array) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelFolder *folder = (CamelFolder *) engine->folder; - camel_imap4_list_t *list; - CamelFolderInfo *fi; - char *name, *p; - CamelURL *url; - int 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); - - 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 = g_malloc0 (sizeof (CamelFolderInfo)); - - 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; - fi->unread = -1; - fi->total = -1; - - /* 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); - } - - g_free (list->name); - g_free (list); - - array->pdata[i] = fi; - - camel_imap4_store_summary_note_info (((CamelIMAP4Store *) store)->summary, fi); - } - - fi = camel_folder_info_build (array, top, '/', TRUE); - - 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 char *top, guint32 flags, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelSession *session = ((CamelService *) store)->session; - CamelIMAP4Command *ic, *ic0 = NULL; - CamelFolderInfo *fi = NULL; - camel_imap4_list_t *list; - GPtrArray *array; - const char *cmd; - char *pattern; - char wildcard; - int id, i; - - if (top == NULL) - top = ""; - - CAMEL_SERVICE_LOCK (store, connect_lock); - - if (!camel_session_is_online (session) || engine->state == CAMEL_IMAP4_ENGINE_DISCONNECTED) { - fi = camel_imap4_store_summary_get_folder_info (((CamelIMAP4Store *) store)->summary, top, flags); - if (fi == NULL && camel_session_is_online (session)) { - /* 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_UNLOCK (store, connect_lock); - return fi; - } - - check_online: - - 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, top, wildcard); - array = g_ptr_array_new (); - - if (*top != '\0') { - size_t len; - char 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 (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); - - 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 (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, - _("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")); - - 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_UNLOCK (store, connect_lock); - - return fi; -} - -static void -imap4_subscribe_folder (CamelStore *store, const char *folder_name, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelSession *session = ((CamelService *) store)->session; - CamelIMAP4Command *ic; - CamelFolderInfo *fi; - char *utf7_name; - CamelURL *url; - const char *p; - int id; - - if (!camel_session_is_online (session)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot subscribe to IMAP folders in offline mode.")); - return; - } - - CAMEL_SERVICE_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_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 = g_malloc0 (sizeof (CamelFolderInfo)); - 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_UNLOCK (store, connect_lock); -} - -static void -imap4_unsubscribe_folder (CamelStore *store, const char *folder_name, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelSession *session = ((CamelService *) store)->session; - CamelIMAP4Command *ic; - CamelFolderInfo *fi; - char *utf7_name; - CamelURL *url; - const char *p; - int id; - - if (!camel_session_is_online (session)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot unsubscribe from IMAP folders in offline mode.")); - return; - } - - CAMEL_SERVICE_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_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 = g_malloc0 (sizeof (CamelFolderInfo)); - 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_UNLOCK (store, connect_lock); -} - -static void -imap4_noop (CamelStore *store, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelSession *session = ((CamelService *) store)->session; - CamelFolder *folder = (CamelFolder *) engine->folder; - CamelIMAP4Command *ic; - int id; - - if (!camel_session_is_online (session)) - return; - - CAMEL_SERVICE_LOCK (store, connect_lock); - - if (folder) { - camel_folder_sync (folder, FALSE, ex); - if (camel_exception_is_set (ex)) { - CAMEL_SERVICE_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_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 aef3c6c6a4..0000000000 --- a/camel/providers/imap4/camel-imap4-store.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifndef __CAMEL_IMAP4_STORE_H__ -#define __CAMEL_IMAP4_STORE_H__ - -#include <camel/camel-store.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#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)) - -typedef struct _CamelIMAP4Store CamelIMAP4Store; -typedef struct _CamelIMAP4StoreClass CamelIMAP4StoreClass; - -struct _CamelIMAP4Engine; - -struct _CamelIMAP4Store { - CamelStore parent_object; - - struct _CamelIMAP4StoreSummary *summary; - struct _CamelIMAP4Engine *engine; - char *storage_path; -}; - -struct _CamelIMAP4StoreClass { - CamelStoreClass parent_class; - -}; - - -CamelType camel_imap4_store_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#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 4a48fe5cf2..0000000000 --- a/camel/providers/imap4/camel-imap4-stream.c +++ /dev/null @@ -1,725 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <ctype.h> - -#include "camel-imap4-specials.h" - -#include "camel-imap4-stream.h" - -#define d(x) x - -#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 ssize_t stream_read (CamelStream *stream, char *buffer, size_t n); -static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n); -static int stream_flush (CamelStream *stream); -static int 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 ssize_t -imap4_fill (CamelIMAP4Stream *imap4) -{ - unsigned char *inbuf, *inptr, *inend; - ssize_t nread; - size_t 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) { - size_t 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 ssize_t -stream_read (CamelStream *stream, char *buffer, size_t n) -{ - CamelIMAP4Stream *imap4 = (CamelIMAP4Stream *) stream; - ssize_t 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 ssize_t -stream_write (CamelStream *stream, const char *buffer, size_t n) -{ - CamelIMAP4Stream *imap4 = (CamelIMAP4Stream *) stream; - ssize_t nwritten; - - if (imap4->disconnected) { - errno = EINVAL; - return -1; - } - - if ((nwritten = camel_stream_write (imap4->stream, buffer, n)) == 0) - imap4->disconnected = TRUE; - - return nwritten; -} - -static int -stream_flush (CamelStream *stream) -{ - CamelIMAP4Stream *imap4 = (CamelIMAP4Stream *) stream; - - return camel_stream_flush (imap4->stream); -} - -static int -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) { \ - unsigned int 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. - **/ -int -camel_imap4_stream_next_token (CamelIMAP4Stream *stream, camel_imap4_token_t *token) -{ - register unsigned char *inptr; - unsigned char *inend, *start, *p; - gboolean escaped = FALSE; - size_t literal = 0; - guint32 nz_number; - int 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 d(!)0 - if (token->token != '\n') - fprintf (stderr, "token: %c\n", token->token); - else - fprintf (stderr, "token: \\n\n"); -#endif - break; - } else if (*inptr == '{') { - /* literal identifier token */ - if ((p = strchr (inptr, '}')) && strchr (p, '\n')) { - inptr++; - - while (isdigit ((int) *inptr) && literal < UINT_MAX / 10) - literal = (literal * 10) + (*inptr++ - '0'); - - if (*inptr != '}') { - if (isdigit ((int) *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 */ - inptr = strchr (inptr, '\n'); - } - - /* 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 ((char *) inptr, (char **) &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. - **/ -int -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. - **/ -int -camel_imap4_stream_line (CamelIMAP4Stream *stream, unsigned char **line, size_t *len) -{ - register unsigned char *inptr; - unsigned char *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; - - 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. - **/ -int -camel_imap4_stream_literal (CamelIMAP4Stream *stream, unsigned char **literal, size_t *len) -{ - unsigned char *inptr, *inend; - size_t 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 c0f870a0bd..0000000000 --- a/camel/providers/imap4/camel-imap4-stream.h +++ /dev/null @@ -1,125 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifndef __CAMEL_IMAP4_STREAM_H__ -#define __CAMEL_IMAP4_STREAM_H__ - -#include <camel/camel-stream.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#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)) - -typedef struct _CamelIMAP4Stream CamelIMAP4Stream; -typedef struct _CamelIMAP4StreamClass CamelIMAP4StreamClass; - -#define IMAP4_READ_PRELEN 128 -#define IMAP4_READ_BUFLEN 4096 - -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 char 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 { - int token; - union { - char *atom; - char *flag; - char *qstring; - size_t 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_object; - - 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 */ - - size_t literal; - - /* i/o buffers */ - unsigned char realbuf[IMAP4_READ_PRELEN + IMAP4_READ_BUFLEN + 1]; - unsigned char *inbuf; - unsigned char *inptr; - unsigned char *inend; - - /* token buffers */ - unsigned char *tokenbuf; - unsigned char *tokenptr; - unsigned int 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); - -int camel_imap4_stream_next_token (CamelIMAP4Stream *stream, camel_imap4_token_t *token); -int camel_imap4_stream_unget_token (CamelIMAP4Stream *stream, camel_imap4_token_t *token); - -int camel_imap4_stream_line (CamelIMAP4Stream *stream, unsigned char **line, size_t *len); -int camel_imap4_stream_literal (CamelIMAP4Stream *stream, unsigned char **literal, size_t *len); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#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 e38928ef43..0000000000 --- a/camel/providers/imap4/camel-imap4-summary.c +++ /dev/null @@ -1,1319 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <limits.h> -#include <utime.h> -#include <fcntl.h> -#include <ctype.h> -#include <errno.h> - -#include <libedataserver/md5-utils.h> - -#include <camel/camel-file-utils.h> -#include <camel/camel-string-utils.h> -#include <camel/camel-i18n.h> - -#include "camel-imap4-store.h" -#include "camel-imap4-engine.h" -#include "camel-imap4-folder.h" -#include "camel-imap4-stream.h" -#include "camel-imap4-command.h" -#include "camel-imap4-utils.h" - -#include "camel-imap4-summary.h" - -#define d(x) x - -#define IMAP4_SUMMARY_VERSION 1 - -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 int imap4_header_load (CamelFolderSummary *summary, FILE *fin); -static int 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 int imap4_message_info_save (CamelFolderSummary *summary, FILE *fout, CamelMessageInfo *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; -} - -static void -camel_imap4_summary_init (CamelIMAP4Summary *summary, CamelIMAP4SummaryClass *klass) -{ - CamelFolderSummary *folder_summary = (CamelFolderSummary *) summary; - - folder_summary->version += IMAP4_SUMMARY_VERSION; - 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); - - 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 int -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_uint32 (fin, &imap4_summary->uidvalidity) == -1) - return -1; - - return 0; -} - -static int -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_uint32 (fout, imap4_summary->uidvalidity) == -1) - return -1; - - return 0; -} - -static int -envelope_decode_address (CamelIMAP4Engine *engine, GString *addrs, CamelException *ex) -{ - char *addr, *name = NULL, *user = NULL; - struct _camel_header_address *cia; - unsigned char *literal = NULL; - camel_imap4_token_t token; - const char *domain = NULL; - int part = 0; - size_t 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 int -envelope_decode_addresses (CamelIMAP4Engine *engine, char **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 int -envelope_decode_date (CamelIMAP4Engine *engine, time_t *date, CamelException *ex) -{ - unsigned char *literal = NULL; - camel_imap4_token_t token; - const char *nstring; - size_t 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 int -envelope_decode_nstring (CamelIMAP4Engine *engine, char **nstring, gboolean rfc2047, CamelException *ex) -{ - camel_imap4_token_t token; - unsigned char *literal; - size_t 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 char *string) -{ - struct _camel_header_references *refs, *r; - CamelSummaryReferences *references; - unsigned char md5sum[16]; - guint32 i, n = 0; - MD5Context md5; - - if (!(r = refs = camel_header_references_inreplyto_decode (string))) - return NULL; - - while (r != NULL) { - r = r->next; - n++; - } - - references = g_malloc (sizeof (CamelSummaryReferences) + (sizeof (CamelSummaryMessageID) * (n - 1))); - references->size = n; - - for (i = 0, r = refs; i < n; i++, r = r->next) { - md5_init (&md5); - md5_update (&md5, r->id, strlen (r->id)); - md5_final (&md5, md5sum); - memcpy (references->references[i].id.hash, md5sum, sizeof (references->references[i].id.hash)); - } - - camel_header_references_list_clear (&refs); - - return references; -} - -static int -decode_envelope (CamelIMAP4Engine *engine, CamelMessageInfo *info, camel_imap4_token_t *token, CamelException *ex) -{ - unsigned char md5sum[16]; - char *nstring; - CamelIMAP4MessageInfo *iinfo = (CamelIMAP4MessageInfo *)info; - - 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) { - iinfo->info.references = decode_references (nstring); - g_free (nstring); - } - - /* message-id */ - if (envelope_decode_nstring (engine, &nstring, FALSE, ex) == -1) - goto exception; - - if (nstring != NULL) { - md5_get_digest (nstring, strlen (nstring), md5sum); - memcpy (iinfo->info.message_id.id.hash, md5sum, sizeof (iinfo->info.message_id.id.hash)); - 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 char *tm_months[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -static gboolean -decode_time (const char **in, int *hour, int *min, int *sec) -{ - register const unsigned char *inptr = (const unsigned char *) *in; - int *val, colons = 0; - - *hour = *min = *sec = 0; - - val = hour; - for ( ; *inptr && !isspace ((int) *inptr); inptr++) { - if (*inptr == ':') { - colons++; - switch (colons) { - case 1: - val = min; - break; - case 2: - val = sec; - break; - default: - return FALSE; - } - } else if (!isdigit ((int) *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 char *in) -{ - const char *inptr = in; - int hour, min, sec, n; - struct tm tm; - time_t date; - char *buf; - - memset ((void *) &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 (!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 << 1), - IMAP4_FETCH_FLAGS = (1 << 2), - IMAP4_FETCH_INTERNALDATE = (1 << 3), - IMAP4_FETCH_RFC822SIZE = (1 << 4), - IMAP4_FETCH_UID = (1 << 5), -}; - -#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; - guint changed; -}; - -struct imap4_fetch_all_t { - CamelFolderChangeInfo *changes; - CamelFolderSummary *summary; - GHashTable *uid_hash; - GPtrArray *added; - guint32 first; - guint32 need; - int count; - int total; -}; - -static void -imap4_fetch_all_free (struct imap4_fetch_all_t *fetch) -{ - struct imap4_envelope_t *envelope; - int 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_is_a_piece_of_shit (CamelFolderSummary *summary, guint32 msg) -{ - CamelSession *session = ((CamelService *) summary->folder->parent_store)->session; - char *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); -} - -static void -imap4_fetch_all_add (struct imap4_fetch_all_t *fetch) -{ - CamelFolderChangeInfo *changes = NULL; - struct imap4_envelope_t *envelope; - CamelMessageInfo *info; - int i; - - changes = fetch->changes; - - for (i = 0; i < fetch->added->len; i++) { - if (!(envelope = fetch->added->pdata[i])) { - courier_imap_is_a_piece_of_shit (fetch->summary, i + fetch->first); - break; - } - - if (envelope->changed != IMAP4_FETCH_ALL) { - d(fprintf (stderr, "Hmmm, IMAP4 server didn't give us everything for message %d\n", i + 1)); - camel_message_info_free(envelope->info); - g_free (envelope); - continue; - } - - if ((info = camel_folder_summary_uid (fetch->summary, camel_message_info_uid (envelope->info)))) { - camel_message_info_free(envelope->info); - g_free (envelope); - continue; - } - - camel_folder_change_info_add_uid (changes, camel_message_info_uid (envelope->info)); - - camel_folder_summary_add (fetch->summary, 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 guint32 -imap4_fetch_all_update (struct imap4_fetch_all_t *fetch) -{ - CamelIMAP4MessageInfo *iinfo, *new_iinfo; - CamelFolderChangeInfo *changes = NULL; - struct imap4_envelope_t *envelope; - CamelMessageInfo *info; - guint32 first = 0; - guint32 flags; - int scount, i; - - changes = fetch->changes; - - scount = camel_folder_summary_count (fetch->summary); - for (i = fetch->first - 1; i < scount; 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); - scount--; - 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_is_a_piece_of_shit (fetch->summary, i + fetch->first); - break; - } - - info = envelope->info; - if (!first && camel_message_info_uid (info)) { - if ((info = camel_folder_summary_uid (fetch->summary, camel_message_info_uid (info)))) { - camel_message_info_free(info); - } else { - first = i + fetch->first; - } - } - - 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); - - return first; -} - -static int -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; - const char *iuid; - char uid[12]; - - if (index < fetch->first) { - /* we already have this message envelope cached - - * server is probably notifying us of a FLAGS change - * by another client? */ - g_assert (index < summary->messages->len); - iinfo = (CamelIMAP4MessageInfo *)(info = summary->messages->pdata[index - 1]); - g_assert (info != NULL); - } else { - if (index > (added->len + fetch->first - 1)) - g_ptr_array_set_size (added, index - fetch->first + 1); - - if (!(envelope = added->pdata[index - fetch->first])) { - iinfo = (CamelIMAP4MessageInfo *) (info = camel_message_info_new (summary)); - envelope = g_new (struct imap4_envelope_t, 1); - added->pdata[index - fetch->first] = envelope; - envelope->info = info; - envelope->changed = 0; - } else { - iinfo = (CamelIMAP4MessageInfo *) (info = envelope->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; - int 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")) { - 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, (void *) camel_message_info_uid (info), envelope); - changed |= IMAP4_FETCH_UID; - } - } 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) - 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" - -static CamelIMAP4Command * -imap4_summary_fetch_all (CamelFolderSummary *summary, guint32 first, guint32 last) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - CamelFolder *folder = summary->folder; - struct imap4_fetch_all_t *fetch; - CamelIMAP4Engine *engine; - CamelIMAP4Command *ic; - int total; - - engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - - total = last ? (last - first) + 1 : (imap4_summary->exists - first) + 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 = first; - fetch->need = IMAP4_FETCH_ALL; - fetch->total = total; - fetch->count = 0; - - if (last != 0) - ic = camel_imap4_engine_queue (engine, folder, "FETCH %u:%u (UID " IMAP4_ALL ")\r\n", first, last); - else - ic = camel_imap4_engine_queue (engine, folder, "FETCH %u:* (UID " IMAP4_ALL ")\r\n", first); - - camel_imap4_command_register_untagged (ic, "FETCH", untagged_fetch_all); - ic->user_data = fetch; - - return ic; -} - -static CamelIMAP4Command * -imap4_summary_fetch_flags (CamelFolderSummary *summary, guint32 first, guint32 last) -{ - CamelFolder *folder = summary->folder; - struct imap4_fetch_all_t *fetch; - CamelIMAP4Engine *engine; - CamelIMAP4Command *ic; - int total; - - engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - - total = (last - first) + 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 = first; - fetch->need = IMAP4_FETCH_UID | IMAP4_FETCH_FLAGS; - fetch->total = total; - fetch->count = 0; - - if (last != 0) - ic = camel_imap4_engine_queue (engine, folder, "FETCH %u:%u (UID FLAGS)\r\n", first, last); - else - ic = camel_imap4_engine_queue (engine, folder, "FETCH %u:* (UID FLAGS)\r\n", first); - - camel_imap4_command_register_untagged (ic, "FETCH", untagged_fetch_all); - ic->user_data = fetch; - - return ic; -} - -#if 0 -static int -imap4_build_summary (CamelFolderSummary *summary, guint32 first, guint32 last) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - CamelFolder *folder = summary->folder; - struct imap4_fetch_all_t *fetch; - CamelIMAP4Engine *engine; - CamelIMAP4Command *ic; - int id; - - engine = ((CamelIMAP4Store *) folder->store)->engine; - - ic = imap4_summary_fetch_all (summary, first, last); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - fetch = ic->user_data; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_imap4_command_unref (ic); - imap4_fetch_all_free (fetch); - return -1; - } - - imap4_fetch_all_add (fetch); - - camel_imap4_command_unref (ic); - - return 0; -} -#endif - -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 int -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; -} - - -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; -} - -void -camel_imap4_summary_set_uidvalidity (CamelFolderSummary *summary, guint32 uidvalidity) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - CamelFolderChangeInfo *changes; - CamelMessageInfo *info; - int i, count; - - g_return_if_fail (CAMEL_IS_IMAP4_SUMMARY (summary)); - - if (imap4_summary->uidvalidity == uidvalidity) - return; - - 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); - 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); - - imap4_summary->uidvalidity = uidvalidity; - - imap4_summary->uidvalidity_changed = TRUE; -} - -void -camel_imap4_summary_expunge (CamelFolderSummary *summary, int seqid) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - CamelFolderChangeInfo *changes; - CamelMessageInfo *info; - const char *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 int -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 - -int -camel_imap4_summary_flush_updates (CamelFolderSummary *summary, CamelException *ex) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - CamelIMAP4Engine *engine; - CamelIMAP4Command *ic; - guint32 first = 0; - int scount, id; - - g_return_val_if_fail (CAMEL_IS_IMAP4_SUMMARY (summary), -1); - - engine = ((CamelIMAP4Store *) summary->folder->parent_store)->engine; - scount = camel_folder_summary_count (summary); - - if (imap4_summary->uidvalidity_changed) { - first = 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, 1, scount); - - 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) { - imap4_fetch_all_free (ic->user_data); - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - camel_operation_end (NULL); - return -1; - } - - if (!(first = imap4_fetch_all_update (ic->user_data)) && imap4_summary->exists > scount) - first = scount + 1; - - camel_imap4_command_unref (ic); - camel_operation_end (NULL); - } else { - first = scount + 1; - } - - if (first != 0 && first <= imap4_summary->exists) { - ic = imap4_summary_fetch_all (summary, first, 0); - - camel_operation_start (NULL, _("Fetching envelopes for new messages")); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - 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); - camel_imap4_command_unref (ic); - camel_operation_end (NULL); - -#if 0 - /* Note: this should not be needed - the code that adds envelopes to the summary - * adds them in proper order */ - - /* it's important for these to be sorted sequentially for EXPUNGE events to work */ - g_ptr_array_sort (summary->messages, (GCompareFunc) info_uid_sort); -#endif - } - - imap4_summary->update_flags = FALSE; - imap4_summary->uidvalidity_changed = FALSE; - - 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 0145e4ac52..0000000000 --- a/camel/providers/imap4/camel-imap4-summary.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifndef __CAMEL_IMAP4_SUMMARY_H__ -#define __CAMEL_IMAP4_SUMMARY_H__ - -#include <sys/types.h> - -#include <camel/camel-folder.h> -#include <camel/camel-folder-summary.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#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)) - -typedef struct _CamelIMAP4MessageInfo CamelIMAP4MessageInfo; -typedef struct _CamelIMAP4Summary CamelIMAP4Summary; -typedef struct _CamelIMAP4SummaryClass CamelIMAP4SummaryClass; - -#define CAMEL_IMAP4_MESSAGE_RECENT (1 << 17) - -struct _CamelIMAP4MessageInfo { - CamelMessageInfoBase info; - - guint32 server_flags; -}; - -struct _CamelIMAP4Summary { - CamelFolderSummary parent_object; - - 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, int seqid); - -int camel_imap4_summary_flush_updates (CamelFolderSummary *summary, CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#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 8a0e92f502..0000000000 --- a/camel/providers/imap4/camel-imap4-utils.c +++ /dev/null @@ -1,749 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> - -#include <camel/camel-store.h> -#include <camel/camel-i18n.h> -#include <camel/camel-net-utils.h> - -#include "camel-imap4-engine.h" -#include "camel-imap4-stream.h" -#include "camel-imap4-command.h" -#include "camel-imap4-summary.h" -#include "camel-imap4-store-summary.h" - -#include "camel-imap4-utils.h" - -#define d(x) x - - -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); -} - - -char -camel_imap4_get_path_delim (CamelIMAP4StoreSummary *s, const char *full_name) -{ - CamelIMAP4Namespace *namespace; - const char *slash; - size_t len; - char *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; - char buf[24]; -}; - -struct _uidset { - CamelFolderSummary *summary; - struct _uidset_range *ranges; - struct _uidset_range *tail; - size_t 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, size_t 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 int -uidset_add (struct _uidset *uidset, CamelMessageInfo *info) -{ - GPtrArray *messages = uidset->summary->messages; - struct _uidset_range *node, *tail = uidset->tail; - const char *iuid = camel_message_info_uid (info); - size_t uidlen, len; - const char *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; - } - - fprintf (stderr, "added uid %s to uidset (summary index = %u)\n", iuid, index); - - if (uidset->setlen < uidset->maxlen) - return 0; - - return 1; -} - -static char * -uidset_to_string (struct _uidset *uidset) -{ - struct _uidset_range *range; - GString *string; - char *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; -} - -int -camel_imap4_get_uid_set (CamelIMAP4Engine *engine, CamelFolderSummary *summary, GPtrArray *infos, int cur, size_t linelen, char **set) -{ - struct _uidset uidset; - size_t maxlen; - int rv = 0; - int 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, (unsigned char) (token->token & 0xff)); - break; - } - - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, errmsg->str); - - g_string_free (errmsg, TRUE); -} - - -static struct { - const char *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 }, -}; - -#if 0 -static struct { - const char *name; - guint32 flag; -} imap4_user_flags[] = { - { "$Forwarded", CAMEL_MESSAGE_FORWARDED }, -}; -#endif - - -int -camel_imap4_parse_flags_list (CamelIMAP4Engine *engine, guint32 *flags, CamelException *ex) -{ - camel_imap4_token_t token; - guint32 new = 0; - int 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 0 - if (i == G_N_ELEMENTS (imap4_flags)) { - for (i = 0; i < G_N_ELEMENTS (imap4_user_flags); i++) { - if (!g_ascii_strcasecmp (imap4_user_flags[i].name, token.v.atom)) { - new |= imap4_user_flags[i].flag; - break; - } - } - - if (i == G_N_ELEMENTS (imap4_user_flags)) - fprintf (stderr, "Encountered unknown flag: %s\n", token.v.atom); - } -#else - if (i == G_N_ELEMENTS (imap4_flags)) - fprintf (stderr, "Encountered unknown flag: %s\n", token.v.atom); -#endif - - 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; -} - - -struct { - const char *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 }, -}; - -int -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; - unsigned char *buf; - guint32 flags = 0; - GString *literal; - char delim; - size_t n; - int 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 char *name; - int 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); -} - - -int -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; - char *mailbox; - size_t len; - int type; - int 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, (unsigned char **) &mailbox, &len, ex) == -1) - return -1; - break; - default: - fprintf (stderr, "Unexpected token in IMAP4 untagged STATUS response: %s%c\n", - token->token == CAMEL_IMAP4_TOKEN_NIL ? "NIL" : "", - (unsigned char) (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 1bb8b00962..0000000000 --- a/camel/providers/imap4/camel-imap4-utils.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifndef __CAMEL_IMAP4_UTILS_H__ -#define __CAMEL_IMAP4_UTILS_H__ - -#include <glib.h> - -#include <camel/camel-exception.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -/* 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 _CamelIMAP4Engine; -struct _CamelIMAP4Command; -struct _CamelFolderSummary; -struct _camel_imap4_token_t; -struct _CamelIMAP4StoreSummary; -struct _CamelIMAP4NamespaceList; -struct _CamelIMAP4Namespace; - -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); - -char camel_imap4_get_path_delim (struct _CamelIMAP4StoreSummary *s, const char *full_name); - -int camel_imap4_get_uid_set (struct _CamelIMAP4Engine *engine, struct _CamelFolderSummary *summary, GPtrArray *infos, int cur, size_t linelen, char **set); - -void camel_imap4_utils_set_unexpected_token_error (CamelException *ex, struct _CamelIMAP4Engine *engine, struct _camel_imap4_token_t *token); - -int 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; - char delim; - char *name; -} camel_imap4_list_t; - -int 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; - char *mailbox; -} camel_imap4_status_t; - -void camel_imap4_status_free (camel_imap4_status_t *status); - -int camel_imap4_untagged_status (struct _CamelIMAP4Engine *engine, struct _CamelIMAP4Command *ic, - guint32 index, struct _camel_imap4_token_t *token, CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_IMAP4_UTILS_H__ */ diff --git a/camel/providers/imap4/libcamelimap4.urls b/camel/providers/imap4/libcamelimap4.urls deleted file mode 100644 index 7ccb0b0414..0000000000 --- a/camel/providers/imap4/libcamelimap4.urls +++ /dev/null @@ -1 +0,0 @@ -imap4 |