aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers/imapp/camel-imapp-stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/providers/imapp/camel-imapp-stream.c')
-rw-r--r--camel/providers/imapp/camel-imapp-stream.c761
1 files changed, 0 insertions, 761 deletions
diff --git a/camel/providers/imapp/camel-imapp-stream.c b/camel/providers/imapp/camel-imapp-stream.c
deleted file mode 100644
index 20876beae2..0000000000
--- a/camel/providers/imapp/camel-imapp-stream.c
+++ /dev/null
@@ -1,761 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*-
- *
- * Author:
- * Michael Zucchi <notzed@ximian.com>
- *
- * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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 Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include <glib.h>
-
-#include <camel/camel-stream-mem.h>
-
-#include "camel-imapp-stream.h"
-#include "camel-imapp-exception.h"
-
-#define t(x)
-#define io(x) x
-
-static void setup_table(void);
-
-static CamelObjectClass *parent_class = NULL;
-
-/* Returns the class for a CamelStream */
-#define CS_CLASS(so) CAMEL_IMAPP_STREAM_CLASS(CAMEL_OBJECT_GET_CLASS(so))
-
-#define CAMEL_IMAPP_STREAM_SIZE (4096)
-#define CAMEL_IMAPP_STREAM_TOKEN (4096) /* maximum token size */
-
-static int
-stream_fill(CamelIMAPPStream *is)
-{
- int left = 0;
-
- if (is->source) {
- left = is->end - is->ptr;
- memcpy(is->buf, is->ptr, left);
- is->end = is->buf + left;
- is->ptr = is->buf;
- left = camel_stream_read(is->source, is->end, CAMEL_IMAPP_STREAM_SIZE - (is->end - is->buf));
- if (left > 0) {
- is->end += left;
- io(printf("camel_imapp_read: buffer is '%.*s'\n", is->end - is->ptr, is->ptr));
- return is->end - is->ptr;
- } else {
- io(printf("camel_imapp_read: -1\n"));
- return -1;
- }
- }
-
- printf("camel_imapp_read: -1\n");
-
- return -1;
-}
-
-static ssize_t
-stream_read(CamelStream *stream, char *buffer, size_t n)
-{
- CamelIMAPPStream *is = (CamelIMAPPStream *)stream;
- ssize_t max;
-
- if (is->literal == 0 || n == 0)
- return 0;
-
- max = is->end - is->ptr;
- if (max > 0) {
- max = MIN(max, is->literal);
- max = MIN(max, n);
- memcpy(buffer, is->ptr, max);
- is->ptr += max;
- } else {
- max = MIN(is->literal, n);
- max = camel_stream_read(is->source, buffer, max);
- if (max <= 0)
- return max;
- }
-
- is->literal -= max;
-
- return max;
-}
-
-static ssize_t
-stream_write(CamelStream *stream, const char *buffer, size_t n)
-{
- CamelIMAPPStream *is = (CamelIMAPPStream *)stream;
-
- return camel_stream_write(is->source, buffer, n);
-}
-
-static int
-stream_close(CamelStream *stream)
-{
- /* nop? */
- return 0;
-}
-
-static int
-stream_flush(CamelStream *stream)
-{
- /* nop? */
- return 0;
-}
-
-static gboolean
-stream_eos(CamelStream *stream)
-{
- CamelIMAPPStream *is = (CamelIMAPPStream *)stream;
-
- return is->literal == 0;
-}
-
-static int
-stream_reset(CamelStream *stream)
-{
- /* nop? reset literal mode? */
- return 0;
-}
-
-static void
-camel_imapp_stream_class_init (CamelStreamClass *camel_imapp_stream_class)
-{
- CamelStreamClass *camel_stream_class = (CamelStreamClass *)camel_imapp_stream_class;
-
- parent_class = camel_type_get_global_classfuncs( CAMEL_OBJECT_TYPE );
-
- /* virtual method definition */
- camel_stream_class->read = stream_read;
- camel_stream_class->write = stream_write;
- camel_stream_class->close = stream_close;
- camel_stream_class->flush = stream_flush;
- camel_stream_class->eos = stream_eos;
- camel_stream_class->reset = stream_reset;
-}
-
-static void
-camel_imapp_stream_init(CamelIMAPPStream *is, CamelIMAPPStreamClass *isclass)
-{
- /* +1 is room for appending a 0 if we need to for a token */
- is->ptr = is->end = is->buf = g_malloc(CAMEL_IMAPP_STREAM_SIZE+1);
- is->tokenptr = is->tokenbuf = g_malloc(CAMEL_IMAPP_STREAM_SIZE+1);
- is->tokenend = is->tokenbuf + CAMEL_IMAPP_STREAM_SIZE;
-}
-
-static void
-camel_imapp_stream_finalise(CamelIMAPPStream *is)
-{
- g_free(is->buf);
- if (is->source)
- camel_object_unref((CamelObject *)is->source);
-}
-
-CamelType
-camel_imapp_stream_get_type (void)
-{
- static CamelType camel_imapp_stream_type = CAMEL_INVALID_TYPE;
-
- if (camel_imapp_stream_type == CAMEL_INVALID_TYPE) {
- setup_table();
- camel_imapp_stream_type = camel_type_register( camel_stream_get_type(),
- "CamelIMAPPStream",
- sizeof( CamelIMAPPStream ),
- sizeof( CamelIMAPPStreamClass ),
- (CamelObjectClassInitFunc) camel_imapp_stream_class_init,
- NULL,
- (CamelObjectInitFunc) camel_imapp_stream_init,
- (CamelObjectFinalizeFunc) camel_imapp_stream_finalise );
- }
-
- return camel_imapp_stream_type;
-}
-
-/**
- * camel_imapp_stream_new:
- *
- * Returns a NULL stream. A null stream is always at eof, and
- * always returns success for all reads and writes.
- *
- * Return value: the stream
- **/
-CamelStream *
-camel_imapp_stream_new(CamelStream *source)
-{
- CamelIMAPPStream *is;
-
- is = (CamelIMAPPStream *)camel_object_new(camel_imapp_stream_get_type ());
- camel_object_ref((CamelObject *)source);
- is->source = source;
-
- return (CamelStream *)is;
-}
-
-
-/*
- From rfc2060
-
-ATOM_CHAR ::= <any CHAR except atom_specials>
-
-atom_specials ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards /
- quoted_specials
-
-CHAR ::= <any 7-bit US-ASCII character except NUL,
- 0x01 - 0x7f>
-
-CTL ::= <any ASCII control character and DEL,
- 0x00 - 0x1f, 0x7f>
-
-SPACE ::= <ASCII SP, space, 0x20>
-
-list_wildcards ::= "%" / "*"
-
-quoted_specials ::= <"> / "\"
-*/
-
-static unsigned char imap_specials[256] = {
-/* 00 */0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/* 10 */0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/* 20 */0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,
-/* 30 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 40 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 50 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
-/* 60 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 70 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 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, 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, 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, 0, 0,
-};
-
-#define imap_is_atom(c) ((imap_specials[(c)&0xff] & 0x01) != 0)
-#define imap_is_simple(c) ((imap_specials[(c)&0xff] & 0x02) != 0)
-#define imap_not_id(c) ((imap_specials[(c)&0xff] & 0x04) != 0)
-
-/* could be pregenerated, but this is cheap */
-static struct {
- unsigned char *chars;
- unsigned char mask;
-} is_masks[] = {
- { "\n*()[]+", 2 },
- { " \r\n()[]+", 4 },
-};
-
-static void setup_table(void)
-{
- int i;
- unsigned char *p, c;
-
- for (i=0;i<(int)(sizeof(is_masks)/sizeof(is_masks[0]));i++) {
- p = is_masks[i].chars;
- while ((c = *p++))
- imap_specials[c] |= is_masks[i].mask;
- }
-}
-
-#if 0
-
-static int
-skip_ws(CamelIMAPPStream *is, unsigned char *pp, unsigned char *pe)
-{
- register unsigned char c, *p;
- unsigned char *e;
-
- p = is->ptr;
- e = is->end;
-
- do {
- while (p >= e ) {
- is->ptr = p;
- if (stream_fill(is) == IMAP_TOK_ERROR)
- return IMAP_TOK_ERROR;
- p = is->ptr;
- e = is->end;
- }
- c = *p++;
- } while (c == ' ' || c == '\r');
-
- is->ptr = p;
- is->end = e;
-
- return c;
-}
-#endif
-
-/* FIXME: these should probably handle it themselves,
- and get rid of the token interface? */
-int
-camel_imapp_stream_atom(CamelIMAPPStream *is, unsigned char **data, unsigned int *lenp)
-{
- unsigned char *p, c;
-
- /* this is only 'approximate' atom */
- switch(camel_imapp_stream_token(is, data, lenp)) {
- case IMAP_TOK_TOKEN:
- p = *data;
- while ((c = *p))
- *p++ = toupper(c);
- case IMAP_TOK_INT:
- return 0;
- case IMAP_TOK_ERROR:
- return IMAP_TOK_ERROR;
- default:
- camel_exception_throw(1, "expecting atom");
- printf("expecting atom!\n");
- return IMAP_TOK_PROTOCOL;
- }
-}
-
-/* gets an atom, a quoted_string, or a literal */
-int
-camel_imapp_stream_astring(CamelIMAPPStream *is, unsigned char **data)
-{
- unsigned char *p, *start;
- unsigned int len, inlen;
-
- switch(camel_imapp_stream_token(is, data, &len)) {
- case IMAP_TOK_TOKEN:
- case IMAP_TOK_INT:
- case IMAP_TOK_STRING:
- return 0;
- case IMAP_TOK_LITERAL:
- /* FIXME: just grow buffer */
- if (len >= CAMEL_IMAPP_STREAM_TOKEN) {
- camel_exception_throw(1, "astring: literal too long");
- printf("astring too long\n");
- return IMAP_TOK_PROTOCOL;
- }
- p = is->tokenptr;
- camel_imapp_stream_set_literal(is, len);
- do {
- len = camel_imapp_stream_getl(is, &start, &inlen);
- if (len < 0)
- return len;
- memcpy(p, start, inlen);
- p += inlen;
- } while (len > 0);
- *data = is->tokenptr;
- return 0;
- case IMAP_TOK_ERROR:
- /* wont get unless no exception hanlder*/
- return IMAP_TOK_ERROR;
- default:
- camel_exception_throw(1, "expecting astring");
- printf("expecting astring!\n");
- return IMAP_TOK_PROTOCOL;
- }
-}
-
-/* check for NIL or (small) quoted_string or literal */
-int
-camel_imapp_stream_nstring(CamelIMAPPStream *is, unsigned char **data)
-{
- unsigned char *p, *start;
- unsigned int len, inlen;
-
- switch(camel_imapp_stream_token(is, data, &len)) {
- case IMAP_TOK_STRING:
- return 0;
- case IMAP_TOK_LITERAL:
- /* FIXME: just grow buffer */
- if (len >= CAMEL_IMAPP_STREAM_TOKEN) {
- camel_exception_throw(1, "nstring: literal too long");
- return IMAP_TOK_PROTOCOL;
- }
- p = is->tokenptr;
- camel_imapp_stream_set_literal(is, len);
- do {
- len = camel_imapp_stream_getl(is, &start, &inlen);
- if (len < 0)
- return len;
- memcpy(p, start, inlen);
- p += inlen;
- } while (len > 0);
- *data = is->tokenptr;
- return 0;
- case IMAP_TOK_TOKEN:
- p = *data;
- if (toupper(p[0]) == 'N' && toupper(p[1]) == 'I' && toupper(p[2]) == 'L' && p[3] == 0) {
- *data = NULL;
- return 0;
- }
- default:
- camel_exception_throw(1, "expecting nstring");
- return IMAP_TOK_PROTOCOL;
- case IMAP_TOK_ERROR:
- /* we'll never get this unless there are no exception handlers anyway */
- return IMAP_TOK_ERROR;
-
- }
-}
-
-/* parse an nstring as a stream */
-int
-camel_imapp_stream_nstring_stream(CamelIMAPPStream *is, CamelStream **stream)
-/* throws IO,PARSE exception */
-{
- unsigned char *token;
- unsigned int len;
- int ret = 0;
- CamelStream * volatile mem = NULL;
-
- *stream = NULL;
-
- CAMEL_TRY {
- switch(camel_imapp_stream_token(is, &token, &len)) {
- case IMAP_TOK_STRING:
- mem = camel_stream_mem_new_with_buffer(token, len);
- *stream = mem;
- break;
- case IMAP_TOK_LITERAL:
- /* if len is big, we could automatically use a file backing */
- camel_imapp_stream_set_literal(is, len);
- mem = camel_stream_mem_new();
- if (camel_stream_write_to_stream((CamelStream *)is, mem) == -1)
- camel_exception_throw(1, "nstring: io error: %s", strerror(errno));
- camel_stream_reset(mem);
- *stream = mem;
- break;
- case IMAP_TOK_TOKEN:
- if (toupper(token[0]) == 'N' && toupper(token[1]) == 'I' && toupper(token[2]) == 'L' && token[3] == 0) {
- *stream = NULL;
- break;
- }
- default:
- ret = -1;
- camel_exception_throw(1, "nstring: token not string");
- }
- } CAMEL_CATCH(ex) {
- if (mem)
- camel_object_unref((CamelObject *)mem);
- camel_exception_throw_ex(ex);
- } CAMEL_DONE;
-
- /* never reaches here anyway */
- return ret;
-}
-
-guint32
-camel_imapp_stream_number(CamelIMAPPStream *is)
-{
- unsigned char *token;
- unsigned int len;
-
- if (camel_imapp_stream_token(is, &token, &len) != IMAP_TOK_INT) {
- camel_exception_throw(1, "expecting number");
- return 0;
- }
-
- return strtoul(token, 0, 10);
-}
-
-int
-camel_imapp_stream_text(CamelIMAPPStream *is, unsigned char **text)
-{
- GByteArray *build = g_byte_array_new();
- unsigned char *token;
- unsigned int len;
- int tok;
-
- CAMEL_TRY {
- while (is->unget > 0) {
- switch (is->unget_tok) {
- case IMAP_TOK_TOKEN:
- case IMAP_TOK_STRING:
- case IMAP_TOK_INT:
- g_byte_array_append(build, is->unget_token, is->unget_len);
- g_byte_array_append(build, " ", 1);
- default: /* invalid, but we'll ignore */
- break;
- }
- is->unget--;
- }
-
- do {
- tok = camel_imapp_stream_gets(is, &token, &len);
- if (tok < 0)
- camel_exception_throw(1, "io error: %s", strerror(errno));
- if (len)
- g_byte_array_append(build, token, len);
- } while (tok > 0);
- } CAMEL_CATCH(ex) {
- *text = NULL;
- g_byte_array_free(build, TRUE);
- camel_exception_throw_ex(ex);
- } CAMEL_DONE;
-
- g_byte_array_append(build, "", 1);
- *text = build->data;
- g_byte_array_free(build, FALSE);
-
- return 0;
-}
-
-/* Get one token from the imap stream */
-camel_imapp_token_t
-/* throws IO,PARSE exception */
-camel_imapp_stream_token(CamelIMAPPStream *is, unsigned char **data, unsigned int *len)
-{
- register unsigned char c, *p, *o, *oe;
- unsigned char *e;
- unsigned int literal;
- int digits;
-
- if (is->unget > 0) {
- is->unget--;
- *data = is->unget_token;
- *len = is->unget_len;
- /*printf("token UNGET '%c' %s\n", is->unget_tok, is->unget_token);*/
- return is->unget_tok;
- }
-
- if (is->literal > 0)
- g_warning("stream_token called with literal %d", is->literal);
-
- p = is->ptr;
- e = is->end;
-
- /* skip whitespace/prefill buffer */
- do {
- while (p >= e ) {
- is->ptr = p;
- if (stream_fill(is) == IMAP_TOK_ERROR)
- goto io_error;
- p = is->ptr;
- e = is->end;
- }
- c = *p++;
- } while (c == ' ' || c == '\r');
-
- /*strchr("\n*()[]+", c)*/
- if (imap_is_simple(c)) {
- is->ptr = p;
- t(printf("token '%c'\n", c));
- return c;
- } else if (c == '{') {
- literal = 0;
- *data = p;
- while (1) {
- while (p < e) {
- c = *p++;
- if (isdigit(c) && literal < (UINT_MAX/10)) {
- literal = literal * 10 + (c - '0');
- } else if (c == '}') {
- while (1) {
- while (p < e) {
- c = *p++;
- if (c == '\n') {
- *len = literal;
- is->ptr = p;
- is->literal = literal;
- t(printf("token LITERAL %d\n", literal));
- return IMAP_TOK_LITERAL;
- }
- }
- is->ptr = p;
- if (stream_fill(is) == IMAP_TOK_ERROR)
- goto io_error;
- p = is->ptr;
- e = is->end;
- }
- } else {
- if (isdigit(c))
- printf("Protocol error: literal too big\n");
- else
- printf("Protocol error: literal contains invalid char %02x '%c'\n", c, isprint(c)?c:c);
- goto protocol_error;
- }
- }
- is->ptr = p;
- if (stream_fill(is) == IMAP_TOK_ERROR)
- goto io_error;
- p = is->ptr;
- e = is->end;
- }
- } else if (c == '"') {
- o = is->tokenptr;
- oe = is->tokenptr + CAMEL_IMAPP_STREAM_TOKEN - 1;
- while (1) {
- while (p < e) {
- c = *p++;
- if (c == '\\') {
- while (p >= e) {
- is->ptr = p;
- if (stream_fill(is) == IMAP_TOK_ERROR)
- goto io_error;
- p = is->ptr;
- e = is->end;
- }
- c = *p++;
- } else if (c == '\"') {
- is->ptr = p;
- *o = 0;
- *data = is->tokenbuf;
- *len = o - is->tokenbuf;
- t(printf("token STRING '%s'\n", is->tokenbuf));
- return IMAP_TOK_STRING;
- }
-
- if (c == '\n' || c == '\r' || o>=oe) {
- if (o >= oe)
- printf("Protocol error: string too long\n");
- else
- printf("Protocol error: truncated string\n");
- goto protocol_error;
- } else {
- *o++ = c;
- }
- }
- is->ptr = p;
- if (stream_fill(is) == IMAP_TOK_ERROR)
- goto io_error;
- p = is->ptr;
- e = is->end;
- }
- } else {
- o = is->tokenptr;
- oe = is->tokenptr + CAMEL_IMAPP_STREAM_TOKEN - 1;
- digits = isdigit(c);
- *o++ = c;
- while (1) {
- while (p < e) {
- c = *p++;
- /*if (strchr(" \r\n*()[]+", c) != NULL) {*/
- if (imap_not_id(c)) {
- if (c == ' ' || c == '\r')
- is->ptr = p;
- else
- is->ptr = p-1;
- *o = 0;
- *data = is->tokenbuf;
- *len = o - is->tokenbuf;
- t(printf("token TOKEN '%s'\n", is->tokenbuf));
- return digits?IMAP_TOK_INT:IMAP_TOK_TOKEN;
- } else if (o < oe) {
- digits &= isdigit(c);
- *o++ = c;
- } else {
- printf("Protocol error: token too long\n");
- goto protocol_error;
- }
- }
- is->ptr = p;
- if (stream_fill(is) == IMAP_TOK_ERROR)
- goto io_error;
- p = is->ptr;
- e = is->end;
- }
- }
-
- /* Had an i/o erorr */
-io_error:
- printf("Got io error\n");
- camel_exception_throw(1, "io error");
- return IMAP_TOK_ERROR;
-
- /* Protocol error, skip until next lf? */
-protocol_error:
- printf("Got protocol error\n");
-
- if (c == '\n')
- is->ptr = p-1;
- else
- is->ptr = p;
-
- camel_exception_throw(1, "protocol error");
- return IMAP_TOK_PROTOCOL;
-}
-
-void
-camel_imapp_stream_ungettoken(CamelIMAPPStream *is, camel_imapp_token_t tok, unsigned char *token, unsigned int len)
-{
- /*printf("ungettoken: '%c' '%s'\n", tok, token);*/
- is->unget_tok = tok;
- is->unget_token = token;
- is->unget_len = len;
- is->unget++;
-}
-
-/* returns -1 on error, 0 if last lot of data, >0 if more remaining */
-int camel_imapp_stream_gets(CamelIMAPPStream *is, unsigned char **start, unsigned int *len)
-{
- int max;
- unsigned char *end;
-
- *len = 0;
-
- max = is->end - is->ptr;
- if (max == 0) {
- max = stream_fill(is);
- if (max <= 0)
- return max;
- }
-
- *start = is->ptr;
- end = memchr(is->ptr, '\n', max);
- if (end)
- max = (end - is->ptr) + 1;
- *start = is->ptr;
- *len = max;
- is->ptr += max;
-
- return end == NULL?1:0;
-}
-
-void camel_imapp_stream_set_literal(CamelIMAPPStream *is, unsigned int literal)
-{
- is->literal = literal;
-}
-
-/* returns -1 on erorr, 0 if last data, >0 if more data left */
-int camel_imapp_stream_getl(CamelIMAPPStream *is, unsigned char **start, unsigned int *len)
-{
- int max;
-
- *len = 0;
-
- if (is->literal > 0) {
- max = is->end - is->ptr;
- if (max == 0) {
- max = stream_fill(is);
- if (max <= 0)
- return max;
- }
-
- max = MIN(max, is->literal);
- *start = is->ptr;
- *len = max;
- is->ptr += max;
- is->literal -= max;
- }
-
- if (is->literal > 0)
- return 1;
-
- return 0;
-}