diff options
Diffstat (limited to 'camel/providers/imap4/camel-imap4-command.c')
-rw-r--r-- | camel/providers/imap4/camel-imap4-command.c | 706 |
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); -} |