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