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