aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers/imap4/camel-imap4-engine.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/providers/imap4/camel-imap4-engine.c')
-rw-r--r--camel/providers/imap4/camel-imap4-engine.c1698
1 files changed, 0 insertions, 1698 deletions
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);
-}