diff options
-rw-r--r-- | camel/ChangeLog | 6 | ||||
-rw-r--r-- | camel/Makefile.am | 2 | ||||
-rw-r--r-- | camel/camel-http-stream.c | 219 | ||||
-rw-r--r-- | camel/camel-http-stream.h | 6 | ||||
-rw-r--r-- | camel/camel-mime-utils.c | 4 | ||||
-rw-r--r-- | camel/camel-mime-utils.h | 2 | ||||
-rw-r--r-- | camel/camel-types.h | 1 |
7 files changed, 132 insertions, 108 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index 64e6a83717..7a5b6e1fe6 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,5 +1,11 @@ 2002-02-04 Jeffrey Stedfast <fejj@ximian.com> + * camel-http-stream.c (stream_read): Use camel_mime_parser_read to + read internal parser data. + (camel_http_stream_get_content_type): Implemented. + + * camel-mime-utils.c (header_decode_int): Made public. + * camel-http-stream.[c,h]: Added. New stream for HTTP requests (currently supported are GET and HEAD). diff --git a/camel/Makefile.am b/camel/Makefile.am index 751f293709..95b45f07e7 100644 --- a/camel/Makefile.am +++ b/camel/Makefile.am @@ -37,6 +37,7 @@ libcamel_la_SOURCES = \ camel-folder-thread.c \ camel-folder.c \ camel-html-parser.c \ + camel-http-stream.c \ camel-internet-address.c \ camel-lock.c \ camel-lock-client.c \ @@ -125,6 +126,7 @@ libcamelinclude_HEADERS = \ camel-folder-summary.h \ camel-folder-thread.h \ camel-folder.h \ + camel-http-stream.h \ camel-internet-address.h \ camel-lock.h \ camel-lock-client.h \ diff --git a/camel/camel-http-stream.c b/camel/camel-http-stream.c index b7880df2e2..3dbccc88e5 100644 --- a/camel/camel-http-stream.c +++ b/camel/camel-http-stream.c @@ -28,6 +28,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <ctype.h> #include <errno.h> #include "camel-http-stream.h" @@ -72,21 +73,22 @@ camel_http_stream_class_init (CamelHttpStreamClass *camel_http_stream_class) static void camel_http_stream_init (gpointer object, gpointer klass) { - CamelHttpStream *stream = CAMEL_HTTP_STREAM (object); + CamelHttpStream *http = CAMEL_HTTP_STREAM (object); - stream->content_type = NULL; - stream->headers = NULL; - stream->service = NULL; - stream->url = NULL; - stream->raw = NULL; + http->parser = NULL; + http->content_type = NULL; + http->headers = NULL; + http->service = NULL; + http->url = NULL; + http->raw = NULL; } static void -headers_free (http->headers) +headers_free (struct _header_raw *headers) { struct _header_raw *node, *next; - node = http->headers; + node = headers; while (node) { next = node->next; g_free (node->name); @@ -99,22 +101,25 @@ headers_free (http->headers) static void camel_http_stream_finalize (CamelObject *object) { - CamelHttpStream *stream = CAMEL_HTTP_STREAM (object); + CamelHttpStream *http = CAMEL_HTTP_STREAM (object); + + if (http->parser) + camel_object_unref (CAMEL_OBJECT (http->parser)); - if (stream->content_type) - header_content_type_unref (stream->content_type); + if (http->content_type) + header_content_type_unref (http->content_type); - if (stream->headers) - headers_free (stream->headers); + if (http->headers) + headers_free (http->headers); - if (stream->service) - camel_object_unref (CAMEL_OBJECT (service)); + if (http->service) + camel_object_unref (CAMEL_OBJECT (http->service)); - if (stream->url) - camel_url_free (stream->url); + if (http->url) + camel_url_free (http->url); - if (stream->raw) - camel_object_unref (CAMEL_OBJECT (stream->raw)); + if (http->raw) + camel_object_unref (CAMEL_OBJECT (http->raw)); } @@ -152,7 +157,7 @@ camel_http_stream_new (CamelHttpMethod method, CamelService *service, CamelURL * CamelHttpStream *stream; char *str; - g_return_val_if_fail (!CAMEL_IS_SERVICE (service), NULL); + g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL); g_return_val_if_fail (url != NULL, NULL); stream = CAMEL_HTTP_STREAM (camel_object_new (camel_http_stream_get_type ())); @@ -219,30 +224,29 @@ http_connect (CamelService *service, CamelURL *url) static const char * http_next_token (const unsigned char *in) { - const char *inptr = in; + const unsigned char *inptr = in; - while (*inptr && !is_lwsp (*inptr)) + while (*inptr && !isspace ((int) *inptr)) inptr++; - while (*inptr && is_lwsp (*inptr)) + while (*inptr && isspace ((int) *inptr)) inptr++; - return inptr; + return (const char *) inptr; } static int http_get_headers (CamelHttpStream *http) { - CamelMimeParser *mp; struct _header_raw *headers, *node, *tail; const char *type, *token; + char buffer[4096], *buf; int status, len, err; - char *buf; - if (camel_stream_buffer_gets (CAMEL_STREAM_BUFFER (http->raw), buffer, 4096) <= 0) + if (camel_stream_buffer_gets (CAMEL_STREAM_BUFFER (http->raw), buffer, sizeof (buffer)) <= 0) return -1; - if (!stncasecmp (buffer, "HTTP/", 5)) { + if (!strncasecmp (buffer, "HTTP/", 5)) { token = http_next_token (buffer); status = header_decode_int (&token); /* FIXME: don't just check for 200 */ @@ -251,15 +255,15 @@ http_get_headers (CamelHttpStream *http) } else goto exception; - mp = camel_mime_parser_new (); - camel_mime_parser_init_with_stream (mp, http->raw); + http->parser = camel_mime_parser_new (); + camel_mime_parser_init_with_stream (http->parser, http->raw); - switch (camel_mime_parser_step (mp, &buf, &len)) { + switch (camel_mime_parser_step (http->parser, &buf, &len)) { case HSCAN_MESSAGE: case HSCAN_HEADER: case HSCAN_MULTIPART: /* we have the headers, build them into 'us' */ - headers = camel_mime_parser_headers_raw (mp); + headers = camel_mime_parser_headers_raw (http->parser); /* if content-type exists, process it first, set for fallback charset in headers */ if (http->content_type) @@ -289,14 +293,18 @@ http_get_headers (CamelHttpStream *http) break; default: - g_warning ("Invalid state encountered???: %d", camel_mime_parser_state (mp)); + g_warning ("Invalid state encountered???: %d", camel_mime_parser_state (http->parser)); } - err = camel_mime_parser_errno (mp); - camel_object_unref (CAMEL_OBJECT (mp)); + err = camel_mime_parser_errno (http->parser); - if (err != 0) + if (err != 0) { + camel_object_unref (CAMEL_OBJECT (http->parser)); + http->parser = NULL; goto exception; + } + + camel_mime_parser_drop_step (http->parser); return 0; @@ -307,105 +315,82 @@ http_get_headers (CamelHttpStream *http) return -1; } - -static ssize_t -stream_read (CamelStream *stream, char *buffer, size_t n) +static int +http_method_invoke (CamelHttpStream *http) { - CamelHttpStream *http = CAMEL_HTTP_STREAM (stream); + const char *method = NULL; + char *url; - if (http->method != CAMEL_HTTP_METHOD_GET || http->method != CAMEL_HTTP_METHOD_HEAD) { - errno = ENOTSUPP; - return -1; + switch (http->method) { + case CAMEL_HTTP_METHOD_GET: + method = "GET"; + break; + case CAMEL_HTTP_METHOD_HEAD: + method = "HEAD"; + break; + default: + g_assert_not_reached (); } - if (!http->raw) { - const char *method; - char *url; - - http->raw = http_connect (http->service, http->url); - if (!http->raw) - return -1; - - switch (http->method) { - case CAMEL_HTTP_METHOD_GET: - method = "GET"; - break; - case CAMEL_HTTP_METHOD_HEAD: - method = "HEAD"; - break; - } - - url = camel_url_to_string (http->url, 0); - if (camel_stream_printf (http->raw, "%s %s HTTP/1.1\r\nHost: %s\r\n\r\n", - method, http->url->path ? http->url->path : "/", - http->url->host) == -1 || - camel_stream_flush (http->raw) == -1) { - camel_object_unref (CAMEL_OBJECT (http->raw)); - http->raw = NULL; - return -1; - } - g_free (url); - - if (http_get_headers (http) == -1) - return -1; + url = camel_url_to_string (http->url, 0); + if (camel_stream_printf (http->raw, "%s %s HTTP/1.1\r\nHost: %s\r\n\r\n", + method, http->url->path ? http->url->path : "/", + http->url->host) == -1 || + camel_stream_flush (http->raw) == -1) { + camel_object_unref (CAMEL_OBJECT (http->raw)); + http->raw = NULL; + return -1; } + g_free (url); - return camel_stream_read (http->raw, buffer, n); + return 0; } static ssize_t -stream_write (CamelStream *stream, const char *buffer, size_t n) +stream_read (CamelStream *stream, char *buffer, size_t n) { CamelHttpStream *http = CAMEL_HTTP_STREAM (stream); + const char *parser_buf; + ssize_t nread; - if (http->method == CAMEL_HTTP_METHOD_GET || http->method == CAMEL_HTTP_METHOD_HEAD) { - errno = ENOTSUPP; + if (http->method != CAMEL_HTTP_METHOD_GET && http->method != CAMEL_HTTP_METHOD_HEAD) { + errno = EIO; return -1; } - return -1; -#if 0 if (!http->raw) { - const char *method; - char *url; - http->raw = http_connect (http->service, http->url); if (!http->raw) return -1; - switch (http->method) { - case CAMEL_HTTP_METHOD_PUT: - method = "PUT"; - break; - case CAMEL_HTTP_METHOD_POST: - method = "POST"; - break; - } - - url = camel_url_to_string (http->url, 0); - if (camel_stream_printf (http->raw, "%s %s HTTP/1.1\r\nHost: %s\r\n\r\n", - method, http->url->path ? http->url->path : "/", - http->url->host) == -1 || - camel_stream_flush (http->raw) == -1) { - camel_object_unref (CAMEL_OBJECT (http->raw)); - http->raw = NULL; + if (http_method_invoke (http) == -1) return -1; - } - g_free (url); if (http_get_headers (http) == -1) return -1; } - return camel_stream_write (http->raw, buffer, n); -#endif + nread = camel_mime_parser_read (http->parser, &parser_buf, n); + + if (nread > 0) + memcpy (buffer, parser_buf, nread); + + return nread; +} + +static ssize_t +stream_write (CamelStream *stream, const char *buffer, size_t n) +{ + return -1; } static int stream_flush (CamelStream *stream) { - if (stream->raw) - return camel_stream_flush (stream->raw); + CamelHttpStream *http = (CamelHttpStream *) stream; + + if (http->raw) + return camel_stream_flush (http->raw); else return 0; } @@ -413,7 +398,7 @@ stream_flush (CamelStream *stream) static int stream_close (CamelStream *stream) { - CamelHttpStream *http = CAMEL_HTTP_STREAM (stream); + CamelHttpStream *http = (CamelHttpStream *) stream; if (http->raw) { if (camel_stream_close (http->raw) == -1) @@ -439,3 +424,27 @@ stream_reset (CamelStream *stream) return 0; }; + + +CamelContentType * +camel_http_stream_get_content_type (CamelHttpStream *http_stream) +{ + g_return_val_if_fail (CAMEL_IS_HTTP_STREAM (http_stream), NULL); + + if (!http_stream->content_type && !http_stream->raw) { + http_stream->raw = http_connect (http_stream->service, http_stream->url); + if (!http_stream->raw) + return NULL; + + if (http_method_invoke (http_stream) == -1) + return NULL; + + if (http_get_headers (http_stream) == -1) + return NULL; + } + + if (http_stream->content_type) + header_content_type_ref (http_stream->content_type); + + return http_stream->content_type; +} diff --git a/camel/camel-http-stream.h b/camel/camel-http-stream.h index 1ffa18d4bd..ac4b2c2a62 100644 --- a/camel/camel-http-stream.h +++ b/camel/camel-http-stream.h @@ -29,6 +29,7 @@ extern "C" { #pragma } #endif /* __cplusplus */ +#include <camel/camel-mime-parser.h> #include <camel/camel-mime-utils.h> #include <camel/camel-service.h> #include <camel/camel-stream.h> @@ -52,11 +53,12 @@ typedef enum { typedef struct _CamelHttpStreamClass CamelHttpStreamClass; -typedef struct _CamelHttpStream CamelHttpStream; struct _CamelHttpStream { CamelStream parent_object; + CamelMimeParser *parser; + CamelContentType *content_type; struct _header_raw *headers; @@ -79,6 +81,8 @@ CamelType camel_http_stream_get_type (void); /* public methods */ CamelStream *camel_http_stream_new (CamelHttpMethod method, CamelService *service, CamelURL *url); +CamelContentType *camel_http_stream_get_content_type (CamelHttpStream *http_stream); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/camel/camel-mime-utils.c b/camel/camel-mime-utils.c index 9f0c5fa662..660cc3575d 100644 --- a/camel/camel-mime-utils.c +++ b/camel/camel-mime-utils.c @@ -1815,8 +1815,8 @@ header_decode_value(const char **in) return NULL; } -/* shoudl this return -1 for no int? */ -static int +/* should this return -1 for no int? */ +int header_decode_int(const char **in) { const char *inptr = *in; diff --git a/camel/camel-mime-utils.h b/camel/camel-mime-utils.h index 7795741c48..50a3eb856b 100644 --- a/camel/camel-mime-utils.h +++ b/camel/camel-mime-utils.h @@ -160,6 +160,8 @@ char *header_unfold (const char *in); /* decode a header which is a simple token */ char *header_token_decode (const char *in); +int header_decode_int (const char **in); + /* decode/encode a string type, like a subject line */ char *header_decode_string (const char *in, const char *default_charset); char *header_encode_string (const unsigned char *in); diff --git a/camel/camel-types.h b/camel/camel-types.h index 6765424b39..86da09cae4 100644 --- a/camel/camel-types.h +++ b/camel/camel-types.h @@ -71,6 +71,7 @@ typedef struct _CamelTcpStream CamelTcpStream; typedef struct _CamelTcpStreamRaw CamelTcpStreamRaw; typedef struct _CamelTcpStreamSSL CamelTcpStreamSSL; typedef struct _CamelTcpStreamOpenSSL CamelTcpStreamOpenSSL; +typedef struct _CamelHttpStream CamelHttpStream; typedef struct _CamelTransport CamelTransport; #ifdef __cplusplus |