diff options
-rw-r--r-- | camel/ChangeLog | 16 | ||||
-rw-r--r-- | camel/camel-http-stream.c | 173 | ||||
-rw-r--r-- | camel/camel-http-stream.h | 15 |
3 files changed, 170 insertions, 34 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index 07e165d70c..2441aa6d1b 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,19 @@ +2002-04-05 Jeffrey Stedfast <fejj@ximian.com> + + * camel-http-stream.c (http_get_headers): Don't get the statuscode + here anymore. + (http_method_invoke): Use a User-Agent header and do basic proxy + authentication. + (stream_read): Handle redirects. + (camel_http_stream_set_user_agent): New function to allow client + to set the User-Agent string. + (camel_http_stream_set_proxy): New function for setting the proxy + server. + (camel_http_stream_set_proxy_authrealm): New function for setting + the proxy auth realm. + (camel_http_stream_set_proxy_authpass): New function for setting + the proxy auth password. + 2002-04-04 Jeffrey Stedfast <fejj@ximian.com> * camel-folder-summary.c (message_info_new): Simplified since we diff --git a/camel/camel-http-stream.c b/camel/camel-http-stream.c index e0cdaba430..bc9aa33508 100644 --- a/camel/camel-http-stream.c +++ b/camel/camel-http-stream.c @@ -32,6 +32,8 @@ #include <errno.h> #include "camel-http-stream.h" + +#include "camel-mime-utils.h" #include "camel-stream-buffer.h" #include "camel-tcp-stream-raw.h" #ifdef HAVE_SSL @@ -77,25 +79,14 @@ camel_http_stream_init (gpointer object, gpointer klass) http->headers = NULL; http->service = NULL; http->url = NULL; + http->proxy = NULL; + http->authrealm = NULL; + http->authpass = NULL; + http->statuscode = 0; http->raw = NULL; } static void -headers_free (struct _header_raw *headers) -{ - struct _header_raw *node, *next; - - node = headers; - while (node) { - next = node->next; - g_free (node->name); - g_free (node->value); - g_free (node); - node = next; - } -} - -static void camel_http_stream_finalize (CamelObject *object) { CamelHttpStream *http = CAMEL_HTTP_STREAM (object); @@ -107,7 +98,7 @@ camel_http_stream_finalize (CamelObject *object) header_content_type_unref (http->content_type); if (http->headers) - headers_free (http->headers); + header_raw_clear (&http->headers); if (http->service) camel_object_unref (CAMEL_OBJECT (http->service)); @@ -115,6 +106,12 @@ camel_http_stream_finalize (CamelObject *object) if (http->url) camel_url_free (http->url); + if (http->proxy) + camel_url_free (http->proxy); + + g_free (http->authrealm); + g_free (http->authpass); + if (http->raw) camel_object_unref (CAMEL_OBJECT (http->raw)); } @@ -229,24 +226,37 @@ http_next_token (const unsigned char *in) } static int -http_get_headers (CamelHttpStream *http) +http_get_statuscode (CamelHttpStream *http) { - struct _header_raw *headers, *node, *tail; - const char *type, *token; - char buffer[4096], *buf; - int status, len, err; + const char *token; + char buffer[4096]; if (camel_stream_buffer_gets (CAMEL_STREAM_BUFFER (http->raw), buffer, sizeof (buffer)) <= 0) return -1; + /* parse the HTTP status code */ if (!strncasecmp (buffer, "HTTP/", 5)) { token = http_next_token (buffer); - status = header_decode_int (&token); - /* FIXME: don't just check for 200 */ - if (status != 200 /* OK */) - goto exception; - } else - goto exception; + http->statuscode = header_decode_int (&token); + return http->statuscode; + } + + camel_object_unref (CAMEL_OBJECT (http->raw)); + http->raw = NULL; + + return -1; +} + +static int +http_get_headers (CamelHttpStream *http) +{ + struct _header_raw *headers, *node, *tail; + const char *type; + char *buf; + int len, err; + + if (http->parser) + camel_object_unref (CAMEL_OBJECT (http->parser)); http->parser = camel_mime_parser_new (); camel_mime_parser_init_with_stream (http->parser, http->raw); @@ -254,7 +264,6 @@ http_get_headers (CamelHttpStream *http) 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 (http->parser); @@ -268,7 +277,7 @@ http_get_headers (CamelHttpStream *http) http->content_type = NULL; if (http->headers) - headers_free (http->headers); + header_raw_clear (&http->headers); http->headers = NULL; tail = (struct _header_raw *) &http->headers; @@ -326,16 +335,37 @@ http_method_invoke (CamelHttpStream *http) } url = camel_url_to_string (http->url, 0); - if (camel_stream_printf (http->raw, "%s %s HTTP/1.0\r\nHost: %s\r\n\r\n", - method, http->url->path ? http->url->path : "/", - http->url->host) == -1 || - camel_stream_flush (http->raw) == -1) { + if (camel_stream_printf (http->raw, "%s %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s\r\n", + method, http->user_agent ? http->user_agent : "CamelHttpStream/1.0", + http->proxy ? url : http->url->path, + http->url->host) == -1) { camel_object_unref (CAMEL_OBJECT (http->raw)); http->raw = NULL; + g_free (url); return -1; } g_free (url); + if (http->authrealm && camel_stream_printf (http->raw, "WWW-Authenticate: %s\r\n", http->authrealm) == -1) { + camel_object_unref (CAMEL_OBJECT (http->raw)); + http->raw = NULL; + return -1; + } + + if (http->authpass && http->proxy && camel_stream_printf (http->raw, "Proxy-Authorization: Basic %s\r\n", + http->authpass) == -1) { + camel_object_unref (CAMEL_OBJECT (http->raw)); + http->raw = NULL; + return -1; + } + + /* end the headers */ + if (camel_stream_write (http->raw, "\r\n", 2) == -1 || camel_stream_flush (http->raw) == -1) { + camel_object_unref (CAMEL_OBJECT (http->raw)); + http->raw = NULL; + return -1; + } + return 0; } @@ -351,16 +381,52 @@ stream_read (CamelStream *stream, char *buffer, size_t n) return -1; } + redirect: + if (!http->raw) { - http->raw = http_connect (http->service, http->url); + http->raw = http_connect (http->service, http->proxy ? http->proxy : http->url); if (!http->raw) return -1; if (http_method_invoke (http) == -1) return -1; + if (http_get_statuscode (http) == -1) + return -1; + if (http_get_headers (http) == -1) return -1; + + switch (http->statuscode) { + case 200: + case 206: + /* we are OK to go... */ + break; + case 301: + case 302: + /* redirect... */ + camel_url_free (http->url); + http->url = camel_url_new (header_raw_find (&http->headers, "Location", NULL), NULL); + + camel_object_unref (CAMEL_OBJECT (http->parser)); + camel_object_unref (CAMEL_OBJECT (http->raw)); + header_content_type_unref (http->content_type); + header_raw_clear (&http->headers); + http->parser = NULL; + http->raw = NULL; + + goto redirect; + break; + case 407: + /* failed proxy authentication? */ + default: + /* unknown error */ + camel_object_unref (CAMEL_OBJECT (http->parser)); + camel_object_unref (CAMEL_OBJECT (http->raw)); + http->parser = NULL; + http->raw = NULL; + return -1; + } } nread = camel_mime_parser_read (http->parser, &parser_buf, n); @@ -441,3 +507,42 @@ camel_http_stream_get_content_type (CamelHttpStream *http_stream) return http_stream->content_type; } + + +void +camel_http_stream_set_user_agent (CamelHttpStream *http_stream, const char *user_agent) +{ + g_return_if_fail (CAMEL_IS_HTTP_STREAM (http_stream)); + + g_free (http_stream->user_agent); + http_stream->user_agent = g_strdup (user_agent); +} + +void +camel_http_stream_set_proxy (CamelHttpStream *http_stream, const char *proxy_url) +{ + g_return_if_fail (CAMEL_IS_HTTP_STREAM (http_stream)); + + if (http_stream->proxy) + camel_url_free (http_stream->proxy); + + http_stream->proxy = camel_url_new (proxy_url, NULL); +} + +void +camel_http_stream_set_proxy_authrealm (CamelHttpStream *http_stream, const char *proxy_authrealm) +{ + g_return_if_fail (CAMEL_IS_HTTP_STREAM (http_stream)); + + g_free (http_stream->authrealm); + http_stream->authrealm = g_strdup (proxy_authrealm); +} + +void +camel_http_stream_set_proxy_authpass (CamelHttpStream *http_stream, const char *proxy_authpass) +{ + g_return_if_fail (CAMEL_IS_HTTP_STREAM (http_stream)); + + g_free (http_stream->authpass); + http_stream->authpass = g_strdup (proxy_authpass); +} diff --git a/camel/camel-http-stream.h b/camel/camel-http-stream.h index 98a470104c..40733662ef 100644 --- a/camel/camel-http-stream.h +++ b/camel/camel-http-stream.h @@ -66,6 +66,15 @@ struct _CamelHttpStream { CamelService *service; CamelURL *url; + char *user_agent; + + /* proxy info */ + CamelURL *proxy; + char *authrealm; + char *authpass; + + int statuscode; + CamelStream *raw; }; @@ -81,6 +90,12 @@ CamelType camel_http_stream_get_type (void); /* public methods */ CamelStream *camel_http_stream_new (CamelHttpMethod method, CamelService *service, CamelURL *url); +void camel_http_stream_set_user_agent (CamelHttpStream *http_stream, const char *user_agent); + +void camel_http_stream_set_proxy (CamelHttpStream *http_stream, const char *proxy_url); +void camel_http_stream_set_proxy_authrealm (CamelHttpStream *http_stream, const char *proxy_authrealm); +void camel_http_stream_set_proxy_authpass (CamelHttpStream *http_stream, const char *proxy_authpass); + CamelContentType *camel_http_stream_get_content_type (CamelHttpStream *http_stream); #ifdef __cplusplus |