Back to index

avfs  1.0.1
http_request.c
Go to the documentation of this file.
00001 /* 
00002    HTTP request/response handling
00003    Copyright (C) 1999-2001, Joe Orton <joe@light.plus.com>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009    
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public
00016    License along with this library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00018    MA 02111-1307, USA
00019 
00020 */
00021 
00022 /* This is the HTTP client request/response implementation.
00023  * The goal of this code is to be modular and simple.
00024  */
00025 
00026 /* TODO:
00027  *  - Move authentication into a hook
00028  */
00029 
00030 #include "config.h"
00031 
00032 #include <sys/types.h>
00033 #include <sys/stat.h>
00034 #ifdef __EMX__
00035 #include <sys/select.h>
00036 #endif
00037 
00038 #ifdef HAVE_LIMITS_H
00039 #include <limits.h> /* just for Win32? */
00040 #endif
00041 
00042 #include <ctype.h>
00043 #include <errno.h>
00044 #include <fcntl.h>
00045 #include <stdio.h>
00046 #ifdef HAVE_STRING_H
00047 #include <string.h>
00048 #endif
00049 #ifdef HAVE_STRINGS_H
00050 #include <strings.h>
00051 #endif 
00052 #ifdef HAVE_STDLIB_H
00053 #include <stdlib.h>
00054 #endif /* HAVE_STDLIB_H */
00055 #ifdef HAVE_UNISTD_H
00056 #include <unistd.h>
00057 #endif /* HAVE_UNISTD_H */
00058 
00059 #ifdef HAVE_SNPRINTF_H
00060 #include "snprintf.h"
00061 #endif
00062 
00063 #include <ctype.h>
00064 
00065 #include "neon_i18n.h"
00066 
00067 #include "ne_alloc.h"
00068 #include "http_request.h"
00069 #include "http_auth.h"
00070 #include "nsocket.h"
00071 #include "string_utils.h" /* for sbuffer */
00072 #include "http_utils.h"
00073 #include "uri.h"
00074 #include "http_private.h"
00075 
00076 #define HTTP_PORT 80
00077 
00078 #define HTTP_EXPECT_TIMEOUT 15
00079 /* 100-continue only used if size > HTTP_EXPECT_MINSIZ */
00080 #define HTTP_EXPECT_MINSIZE 1024
00081 
00082 #define HTTP_VERSION_PRE11(s) \
00083 ((s)->version_major<1 || ((s)->version_major==1 && (s)->version_minor<1))
00084 
00085 #define HTTP_MAXIMUM_HEADER_LENGTH 8192
00086 
00087 #define NEON_USERAGENT "neon/" NEON_VERSION;
00088 
00089 static void te_hdr_handler(void *userdata, const char *value);
00090 static void connection_hdr_handler(void *userdata, const char *value);
00091 
00092 static void set_hostinfo(struct host_info *info, const char *hostname, int port);
00093 static int lookup_host(struct host_info *info);
00094 
00095 static int open_connection(http_req *req);
00096 static int close_connection(http_session *req);
00097 
00098 static int set_sockerr(http_req *req, const char *doing, int sockerr);
00099 
00100 static char *get_hostport(struct host_info *host);
00101 static void add_fixed_headers(http_req *req);
00102 static int get_request_bodysize(http_req *req);
00103 
00104 static int send_request_body(http_req *req);
00105 static void build_request(http_req *req, sbuffer buf);
00106 static int read_message_header(http_req *req, sbuffer buf, char *extra);
00107 static int read_response_block(http_req *req, struct http_response *resp,
00108                             char *buffer, size_t *buflen);
00109 static int read_response_body(http_req *req);
00110 
00111 /* The iterative step used to produce the hash value.  This is DJB's
00112  * magic "*33" hash function.  Ralf Engelschall has done some amazing
00113  * statistical analysis to show that *33 really is a good hash
00114  * function: check the new-httpd list archives, or his 'str' library
00115  * source code, for the details.
00116  *
00117  * TODO: due to limited range of characters used in header names,
00118  * could maybe get a better hash function to use? */
00119  
00120 #define HH_ITERATE(hash, char) (((hash)*33 + char) % HH_HASHSIZE);
00121 
00122 /* Produce the hash value for a header name, which MUST be in lower
00123  * case.  */
00124 static unsigned int hdr_hash(const char *name)
00125 {
00126     const char *pnt;
00127     unsigned int hash = 0;
00128 
00129     for (pnt = name; *pnt != '\0'; pnt++) {
00130        hash = HH_ITERATE(hash,*pnt);
00131     }
00132 
00133     return hash;
00134 }
00135 
00136 /* Initializes an HTTP session */
00137 http_session *http_session_create(void) 
00138 {
00139     http_session *sess = ne_calloc(sizeof *sess);
00140 
00141     DEBUG(DEBUG_HTTP, "HTTP session begins.\n");
00142     strcpy(sess->error, "Unknown error.");
00143     sess->version_major = -1;
00144     sess->version_minor = -1;
00145     /* Default expect-100 to OFF. */
00146     sess->expect100_works = -1;
00147     return sess;
00148 }
00149 
00150 static char *lower_string(const char *str)
00151 {
00152     char *ret = ne_malloc(strlen(str) + 1), *pnt;
00153     
00154     for (pnt = ret; *str != '\0'; str++) {
00155        *pnt++ = tolower(*str);
00156     }
00157     
00158     *pnt = '\0';
00159 
00160     return ret;
00161 }
00162 
00163 static void
00164 set_hostinfo(struct host_info *info, const char *hostname, int port)
00165 {
00166     HTTP_FREE(info->hostport);
00167     HTTP_FREE(info->hostname);
00168     info->hostname= ne_strdup(hostname);
00169     info->port = port;
00170     info->hostport = get_hostport(info);
00171     http_auth_init(&info->auth);
00172 }
00173 
00174 static int lookup_host(struct host_info *info)
00175 {
00176     if (sock_name_lookup(info->hostname, &info->addr)) {
00177        return HTTP_LOOKUP;
00178     } else {
00179        return HTTP_OK;
00180     }
00181 }
00182 
00183 int http_version_pre_http11(http_session *sess)
00184 {
00185     return HTTP_VERSION_PRE11(sess);
00186 }
00187 
00188 int http_session_server(http_session *sess, const char *hostname, int port)
00189 {
00190     if (sess->connected && !sess->have_proxy) {
00191        /* Reconnect */
00192        close_connection(sess);
00193     }
00194     set_hostinfo(&sess->server, hostname, port);
00195     /* We do a name lookup on the origin server if either:
00196      *  1) we do not have a proxy server
00197      *  2) we *might not* have a proxy server (since we have a 'proxy decider' function).
00198      */
00199     if (!sess->have_proxy || sess->proxy_decider) {
00200        return lookup_host(&sess->server);
00201     } else {
00202        return HTTP_OK;
00203     }
00204 }
00205 
00206 void http_set_secure_context(http_session *sess, nssl_context *ctx)
00207 {
00208     sess->ssl_context = ctx;
00209 }
00210 
00211 int http_set_request_secure_upgrade(http_session *sess, int req_upgrade)
00212 {
00213 #ifdef ENABLE_SSL
00214     sess->request_secure_upgrade = req_upgrade;
00215     return 0;
00216 #else
00217     return -1;
00218 #endif
00219 }
00220 
00221 int http_set_accept_secure_upgrade(http_session *sess, int acc_upgrade)
00222 {
00223 #ifdef ENABLE_SSL
00224     sess->accept_secure_upgrade = acc_upgrade;
00225     return 0;
00226 #else
00227     return -1;
00228 #endif
00229 }
00230 
00231 int http_set_secure(http_session *sess, int use_secure)
00232 {
00233 #ifdef ENABLE_SSL
00234     sess->use_secure = use_secure;
00235     return 0;
00236 #else
00237     return -1;
00238 #endif
00239 }
00240 
00241 void http_session_decide_proxy(http_session *sess, http_use_proxy use_proxy,
00242                             void *userdata)
00243 {
00244     sess->proxy_decider = use_proxy;
00245     sess->proxy_decider_udata = userdata;
00246 }
00247 
00248 int http_session_proxy(http_session *sess, const char *hostname, int port)
00249 {
00250     if (sess->connected) {
00251        /* Reconnect */
00252        close_connection(sess);
00253     }
00254     sess->have_proxy = 1;
00255     set_hostinfo(&sess->proxy, hostname, port);
00256     return lookup_host(&sess->proxy);
00257 }
00258 
00259 void http_set_server_auth(http_session *sess, 
00260                        http_request_auth callback, void *userdata)
00261 {
00262     sess->server.auth_callback = callback;
00263     sess->server.auth_userdata = userdata;
00264 }
00265 
00266 /* Set callback to handle proxy authentication */
00267 void http_set_proxy_auth(http_session *sess, 
00268                       http_request_auth callback, void *userdata)
00269 {
00270     sess->proxy.auth_callback = callback;
00271     sess->proxy.auth_userdata = userdata;
00272 }
00273 
00274 void http_set_error(http_session *sess, const char *errstring)
00275 {
00276     strncpy(sess->error, errstring, BUFSIZ);
00277     sess->error[BUFSIZ-1] = '\0';
00278     STRIP_EOL(sess->error);
00279 }
00280 
00281 const char *http_get_error(http_session *sess) {
00282     return sess->error;
00283 }
00284 
00285 /* Give authentication credentials */
00286 static int give_creds(void *udata, const char *realm,
00287                     char **username, char **password) 
00288 { 
00289     http_req *req = udata;
00290     http_session *sess = req->session;
00291     if (req->status.code == 407 && req->use_proxy && sess->proxy.auth_callback) {
00292        return (*sess->proxy.auth_callback)(
00293            sess->proxy.auth_userdata, realm, sess->proxy.hostname,
00294            username, password);
00295     } else if (req->status.code == 401 && sess->server.auth_callback) {
00296        return (*sess->server.auth_callback)( 
00297            sess->server.auth_userdata, realm, sess->server.hostname,
00298            username, password);
00299     }
00300     return -1;
00301 }
00302 
00303 void http_duplicate_header(void *userdata, const char *value)
00304 {
00305     char **location = userdata;
00306     *location = ne_strdup(value);
00307 }
00308 
00309 void http_handle_numeric_header(void *userdata, const char *value)
00310 {
00311     int *location = userdata;
00312     *location = atoi(value);
00313 }
00314 
00315 /* The body reader callback */
00316 static void auth_body_reader(void *userdata, const char *block, size_t length)
00317 {
00318     http_auth_session *sess = userdata;
00319     http_auth_response_body(sess, block, length);
00320 }
00321 
00322 void http_add_hooks(http_session *sess, 
00323                   const http_request_hooks *hooks, void *private)
00324 {
00325     struct hook *hk = ne_malloc(sizeof(struct hook));
00326     hk->hooks = hooks;
00327     hk->private = private;
00328     hk->next = sess->hooks;
00329     sess->hooks = hk;
00330 }
00331 
00332 void *http_get_hook_private(http_req *req, const char *id)
00333 {
00334     struct hook_request *hk;
00335 
00336     for (hk = req->hook_store; hk != NULL; hk = hk->next) {
00337        if (strcasecmp(hk->hook->hooks->id, id) == 0) {
00338            return hk->cookie;
00339        }
00340     }
00341 
00342     return NULL;
00343 }
00344 
00345 int http_session_destroy(http_session *sess) 
00346 {
00347     struct hook *hk;
00348 
00349     DEBUG(DEBUG_HTTP, "http_session_destroy called.\n");
00350     http_auth_finish(&sess->server.auth);
00351     if (sess->have_proxy) {
00352        http_auth_finish(&sess->proxy.auth);
00353     }
00354     HTTP_FREE(sess->server.hostname);
00355     HTTP_FREE(sess->server.hostport);
00356     HTTP_FREE(sess->proxy.hostport);
00357     HTTP_FREE(sess->user_agent);
00358 
00359     /* Clear the hooks. */
00360     hk = sess->hooks;
00361     while (hk) {
00362        struct hook *nexthk = hk->next;
00363        free(hk);
00364        hk = nexthk;
00365     }
00366        
00367     if (sess->connected) {
00368        close_connection(sess);
00369     }
00370 
00371     free(sess);
00372     return HTTP_OK;
00373 }
00374 
00375 /* Sends the body down the socket.
00376  * Returns 0 on success, or SOCK_* code */
00377 static int send_request_body(http_req *req)
00378 {
00379     int ret;
00380     switch (req->body) {
00381     case body_stream:
00382        ret = sock_transfer(fileno(req->body_stream), req->session->socket, 
00383                          req->body_size);
00384        DEBUG(DEBUG_HTTP, "Sent %d bytes.\n", ret);
00385        rewind(req->body_stream); /* since we may have to send it again */
00386        break;
00387     case body_buffer:
00388        DEBUG(DEBUG_HTTP, "Sending body:\n%s\n", req->body_buffer);
00389        ret = sock_send_string(req->session->socket, req->body_buffer);
00390        DEBUG(DEBUG_HTTP, "sock_send_string returns: %d\n", ret);
00391        break;
00392     default:
00393        ret = 0;
00394        break;
00395     }
00396     if (ret < 0) {
00397        /* transfer failed */
00398        req->forced_close = 1;
00399     }
00400     return ret;
00401 }
00402 
00403 /* Deal with the body size.
00404  * Returns 0 on success or non-zero on error. */
00405 static int get_request_bodysize(http_req *req) 
00406 {
00407     struct stat bodyst;
00408     /* Do extra stuff if we have a body */
00409     switch(req->body) {
00410     case body_stream:
00411        /* Get file length */
00412        if (fstat(fileno(req->body_stream), &bodyst) < 0) {
00413            /* Stat failed */
00414            DEBUG(DEBUG_HTTP, "Stat failed: %s\n", strerror(errno));
00415            return -1;
00416        }
00417        req->body_size = bodyst.st_size;
00418        break;
00419     case body_buffer:
00420        req->body_size = strlen(req->body_buffer);
00421        break;
00422     default:
00423        /* No body, so no size. */
00424        break;
00425     }
00426     if (req->body != body_none) {
00427        char tmp[BUFSIZ];
00428        /* Add the body length header */
00429        snprintf(tmp, BUFSIZ, "Content-Length: %d" EOL, req->body_size);
00430        sbuffer_zappend(req->headers, tmp);
00431     } else {
00432        sbuffer_zappend(req->headers, "Content-Length: 0" EOL);
00433     }
00434     return 0;
00435 }
00436 
00437 static char *get_hostport(struct host_info *host) 
00438 {
00439     size_t len = strlen(host->hostname);
00440     char *ret = ne_malloc(len + 10);
00441     strcpy(ret, host->hostname);
00442     if (host->port != HTTP_PORT) {
00443        snprintf(ret + len, 9, ":%d", host->port);
00444     }
00445     return ret;
00446 }
00447 
00448 const char *http_get_server_hostport(http_session *sess) {
00449     return sess->server.hostport;
00450 }
00451 
00452 const char *http_get_scheme(http_session *sess)
00453 {
00454     if (sess->use_secure) {
00455        return "https";
00456     } else {
00457        return "http";
00458     }
00459 }
00460 
00461 /* Lob the User-Agent, connection and host headers in to the request
00462  * headers */
00463 static void add_fixed_headers(http_req *req) 
00464 {
00465     if (req->session->user_agent) {
00466        sbuffer_concat(req->headers, 
00467                      "User-Agent: ", req->session->user_agent, EOL, NULL);
00468     }
00469     /* Send Connection: Keep-Alive for pre-1.1 origin servers, so we
00470      * might get a persistent connection. 2068 sec 19.7.1 says we MUST
00471      * NOT do this for proxies, though. So we don't.  Note that on the
00472      * first request on any session, we don't know whether the server
00473      * is 1.1 compliant, so we presume that it is not. */
00474     if (HTTP_VERSION_PRE11(req->session) && !req->use_proxy) {
00475        sbuffer_zappend(req->headers, "Keep-Alive: " EOL);
00476        sbuffer_zappend(req->headers, "Connection: TE, Keep-Alive");
00477     } else {
00478        sbuffer_zappend(req->headers, "Connection: TE");
00479     }
00480     if (req->upgrade_to_tls) {
00481        sbuffer_zappend(req->headers, ", Upgrade");
00482     }
00483     sbuffer_zappend(req->headers, EOL);
00484     if (req->upgrade_to_tls) {
00485        sbuffer_zappend(req->headers, "Upgrade: TLS/1.0" EOL);
00486     }
00487     /* We send TE: trailers since we understand trailers in the chunked
00488      * response. */
00489     sbuffer_zappend(req->headers, "TE: trailers" EOL);
00490 
00491 }
00492 
00493 static int always_accept_response(void *userdata, http_req *req, http_status *st)
00494 {
00495     return 1;
00496 }                              
00497 
00498 int http_accept_2xx(void *userdata, http_req *req, http_status *st)
00499 {
00500     return (st->klass == 2);
00501 }
00502 
00503 /* Initializes the request with given method and URI.
00504  * URI must be abs_path - i.e., NO scheme+hostname. It will BREAK 
00505  * otherwise. */
00506 http_req *http_request_create(http_session *sess,
00507                            const char *method, const char *uri) 
00508 {
00509     sbuffer real_uri;
00510     http_req *req = ne_calloc(sizeof(http_req));
00511 
00512     DEBUG(DEBUG_HTTP, "Creating request...\n");
00513 
00514     req->session = sess;
00515     req->headers = sbuffer_create();
00516     
00517     /* Add in the fixed headers */
00518     add_fixed_headers(req);
00519 
00520     /* Set the standard stuff */
00521     req->method = method;
00522     req->method_is_head = (strcmp(req->method, "HEAD") == 0);
00523     req->body = body_none;
00524     
00525     /* FIXME: the proxy_decider is broken if they called
00526      * http_session_proxy before http_session_server, since in that
00527      * case we have not done a name lookup on the session server.  */
00528     if (sess->have_proxy && sess->proxy_decider != NULL) {
00529        req->use_proxy = 
00530            (*sess->proxy_decider)(sess->proxy_decider_udata,
00531                                http_get_scheme(sess), sess->server.hostname);
00532     }
00533     else {
00534        req->use_proxy = sess->have_proxy;
00535     }
00536 
00537     if (sess->request_secure_upgrade == 1) {
00538        req->upgrade_to_tls = 1;
00539     }
00540 
00541     /* Add in standard callbacks */
00542 
00543     if (sess->server.auth_callback != NULL) {
00544        http_auth_set_creds_cb(&sess->server.auth, give_creds, req);
00545        http_add_response_body_reader(req, always_accept_response, 
00546                                   auth_body_reader, 
00547                                   &req->session->server.auth);
00548     }
00549 
00550     if (req->use_proxy && sess->proxy.auth_callback != NULL) {
00551        http_auth_set_creds_cb(&sess->proxy.auth, give_creds, req);
00552        http_add_response_body_reader(req, always_accept_response, 
00553                                   auth_body_reader, 
00554                                   &req->session->proxy.auth);
00555     }
00556     
00557     /* Add in handlers for all the standard HTTP headers. */
00558 
00559     http_add_response_header_handler(req, "Content-Length", 
00560                                   http_handle_numeric_header, &req->resp.length);
00561     http_add_response_header_handler(req, "Transfer-Encoding", 
00562                                   te_hdr_handler, &req->resp);
00563     http_add_response_header_handler(req, "Connection", 
00564                                   connection_hdr_handler, req);
00565 
00566     if (uri) {
00567        req->abs_path = ne_strdup(uri);
00568        real_uri = sbuffer_create();
00569        if (req->use_proxy)
00570            sbuffer_concat(real_uri, http_get_scheme(req->session), "://", 
00571                         req->session->server.hostport, NULL);
00572        sbuffer_zappend(real_uri, req->abs_path);
00573        req->uri = sbuffer_finish(real_uri);
00574     }
00575 
00576     {
00577        struct hook *hk;
00578        struct hook_request *store;
00579        void *cookie;
00580 
00581        DEBUG(DEBUG_HTTP, "Running request create hooks.\n");
00582 
00583        for (hk = sess->hooks; hk != NULL; hk = hk->next) {
00584            cookie = (*hk->hooks->create)(hk->private, req, method, uri);
00585            if (cookie != NULL) {
00586               store = ne_malloc(sizeof(struct hook_request));
00587               store->hook = hk;
00588               store->cookie = cookie;
00589               store->next = req->hook_store;
00590               req->hook_store = store;
00591            }
00592        }
00593     }
00594 
00595     DEBUG(DEBUG_HTTP, "Request created.\n");
00596 
00597     return req;
00598 }
00599 
00600 static void run_set_body_hooks(http_req *req, const char *buf, FILE *f)
00601 {
00602     struct hook_request *st;
00603     for (st = req->hook_store; st!=NULL; st = st->next) {
00604        if (HAVE_HOOK(st,use_body)) {
00605            HOOK_FUNC(st,use_body)(st->cookie, buf, f);
00606        }
00607     }
00608 }
00609 
00610 void http_set_request_body_buffer(http_req *req, const char *buffer)
00611 {
00612     req->body = body_buffer;
00613     req->body_buffer = buffer;
00614     req->body_stream = NULL;
00615     run_set_body_hooks(req, buffer, NULL);
00616 }
00617 
00618 void http_set_request_body_stream(http_req *req, FILE *stream)
00619 {
00620     req->body = body_stream;
00621     req->body_stream = stream;
00622     req->body_buffer = NULL;
00623     run_set_body_hooks(req, NULL, stream);
00624 }
00625 
00626 void http_set_expect100(http_session *sess, int use_expect100)
00627 {
00628     if (use_expect100) {
00629        sess->expect100_works = 1;
00630     } else {
00631        sess->expect100_works = -1;
00632     }
00633 }
00634 
00635 void http_set_persist(http_session *sess, int persist)
00636 {
00637     sess->no_persist = !persist;
00638 }
00639 
00640 void http_set_useragent(http_session *sess, const char *token)
00641 {
00642     static const char *fixed = " " NEON_USERAGENT;
00643     HTTP_FREE(sess->user_agent);
00644     CONCAT2(sess->user_agent, token, fixed);
00645 }
00646 
00647 void http_add_request_header(http_req *req, const char *name, 
00648                           const char *value)
00649 {
00650     sbuffer_concat(req->headers, name, ": ", value, EOL, NULL);
00651 }
00652 
00653 sbuffer http_get_request_headers(http_req *req)
00654 {
00655     return req->headers;
00656 }
00657 
00658 void http_print_request_header(http_req *req, const char *name,
00659                             const char *format, ...)
00660 {
00661     va_list params;
00662     char buf[BUFSIZ];
00663     
00664     va_start(params, format);
00665     vsnprintf(buf, BUFSIZ, format, params);
00666     va_end(params);
00667     
00668     sbuffer_concat(req->headers, name, ": ", buf, EOL, NULL);
00669 }
00670 
00671 void
00672 http_add_response_header_handler(http_req *req, const char *name, 
00673                              http_header_handler hdl, void *userdata)
00674 {
00675     struct header_handler *new = ne_calloc(sizeof *new);
00676     int hash;
00677     new->name = lower_string(name);
00678     new->handler = hdl;
00679     new->userdata = userdata;
00680     hash = hdr_hash(new->name);
00681     new->next = req->header_handlers[hash];
00682     req->header_handlers[hash] = new;
00683 }
00684 
00685 void http_add_response_header_catcher(http_req *req, 
00686                                   http_header_handler hdl, void *userdata)
00687 {
00688     struct header_handler *new = ne_calloc(sizeof  *new);
00689     new->handler = hdl;
00690     new->userdata = userdata;
00691     new->next = req->header_catchers;
00692     req->header_catchers = new;
00693 }
00694 
00695 void
00696 http_add_response_body_reader(http_req *req, http_accept_response acpt,
00697                             http_block_reader rdr, void *userdata)
00698 {
00699     struct body_reader *new = ne_malloc(sizeof(struct body_reader));
00700     new->accept_response = acpt;
00701     new->handler = rdr;
00702     new->userdata = userdata;
00703     new->next = req->body_readers;
00704     req->body_readers = new;
00705 }
00706 
00707 void http_request_destroy(http_req *req) 
00708 {
00709     struct body_reader *rdr, *next_rdr;
00710     struct header_handler *hdlr, *next_hdlr;
00711     struct hook_request *st, *next_st;
00712     int n;
00713 
00714     HTTP_FREE(req->uri);
00715     HTTP_FREE(req->abs_path);
00716 
00717     for (rdr = req->body_readers; rdr != NULL; rdr = next_rdr) {
00718        next_rdr = rdr->next;
00719        free(rdr);
00720     }
00721 
00722     for (hdlr = req->header_catchers; hdlr != NULL; hdlr = next_hdlr) {
00723        next_hdlr = hdlr->next;
00724        free(hdlr);
00725     }
00726 
00727     for (n = 0; n < HH_HASHSIZE; n++) {
00728        for (hdlr = req->header_handlers[n]; hdlr != NULL; 
00729             hdlr = next_hdlr) {
00730            next_hdlr = hdlr->next;
00731            free(hdlr->name);
00732            free(hdlr);
00733        }
00734     }
00735 
00736     sbuffer_destroy(req->headers);
00737 
00738     DEBUG(DEBUG_HTTP, "Running destroy hooks.\n");
00739     for (st = req->hook_store; st!=NULL; st = next_st) {
00740        next_st = st->next;
00741        if (HAVE_HOOK(st,destroy)) {
00742            HOOK_FUNC(st,destroy)(st->cookie);
00743        }
00744        free(st);
00745     }
00746 
00747     DEBUG(DEBUG_HTTP, "Request ends.\n");
00748     free(req);
00749 }
00750 
00751 
00752 /* Reads a block of the response into buffer, which is of size buflen.
00753  * Returns number of bytes read, 0 on end-of-response, or HTTP_* on error.
00754  * TODO?: only make one actual read() call in here... 
00755  */
00756 static int read_response_block(http_req *req, struct http_response *resp, 
00757                             char *buffer, size_t *buflen) 
00758 {
00759     int willread, readlen;
00760     nsocket *sock = req->session->socket;
00761     if (resp->is_chunked) {
00762        /* We are doing a chunked transfer-encoding.
00763         * It goes:  `SIZE CRLF CHUNK CRLF SIZE CRLF CHUNK CRLF ...'
00764         * ended by a `CHUNK CRLF 0 CRLF', a 0-sized chunk.
00765         * The slight complication is that we have to cope with
00766         * partial reads of chunks.
00767         * For this reason, resp.chunk_left contains the number of
00768         * bytes left to read in the current chunk.
00769         */
00770        if (resp->chunk_left == 0) {
00771            long int chunk_len;
00772            /* We are at the start of a new chunk. */
00773            DEBUG(DEBUG_HTTP, "New chunk.\n");
00774            readlen = sock_readline(sock, buffer, *buflen);
00775            if (readlen <= 0) {
00776               return set_sockerr(req, _("Could not read chunk size"), readlen);
00777            }
00778            DEBUG(DEBUG_HTTP, "[Chunk Size] < %s", buffer);
00779            chunk_len = strtol(buffer, NULL, 16);
00780            if (chunk_len == LONG_MIN || chunk_len == LONG_MAX) {
00781               DEBUG(DEBUG_HTTP, "Couldn't read chunk size.\n");
00782               http_set_error(req->session, _("Could not parse chunk size"));
00783               return -1;
00784            }
00785            DEBUG(DEBUG_HTTP, "Got chunk size: %ld\n", chunk_len);
00786            if (chunk_len == 0) {
00787               /* Zero-size chunk == end of response. */
00788               DEBUG(DEBUG_HTTP, "Zero-size chunk.\n");
00789               *buflen = 0;
00790               return HTTP_OK;
00791            }
00792            resp->chunk_left = chunk_len;
00793        }
00794        willread = min(*buflen - 1, resp->chunk_left);
00795     } else if (resp->length > 0) {
00796        /* Have we finished reading the body? */
00797        if (resp->left == 0) {
00798            *buflen = 0;
00799            return HTTP_OK;
00800        }
00801        willread = min(*buflen - 1, resp->left);
00802     } else {
00803        /* Read until socket-close */
00804        willread = *buflen - 1;
00805     }
00806     DEBUG(DEBUG_HTTP, "Reading %d bytes of response body.\n", willread);
00807     readlen = sock_read(sock, buffer, willread);
00808     DEBUG(DEBUG_HTTP, "Got %d bytes.\n", readlen);
00809 
00810     /* EOF is valid if we don't know the response body length, or
00811      * we've read all of the response body, and we're not using
00812      * chunked. */
00813     if (readlen == SOCK_CLOSED && resp->length <= 0 && !resp->is_chunked) {
00814        readlen = 0;
00815     } else if (readlen < 0) {
00816        return set_sockerr(req, _("Could not read response body"), readlen);
00817     }
00818     buffer[readlen] = '\0';
00819     *buflen = readlen;
00820     DEBUG(DEBUG_HTTPBODY, "Read block:\n%s\n", buffer);
00821     if (resp->is_chunked) {
00822        resp->chunk_left -= readlen;
00823        if (resp->chunk_left == 0) {
00824            char crlfbuf[2];
00825            /* If we've read a whole chunk, read a CRLF */
00826            readlen = sock_fullread(sock, crlfbuf, 2);
00827            if (readlen < 0 || strncmp(crlfbuf, EOL, 2) != 0) {
00828               return set_sockerr(req, 
00829                                _("Error reading chunked response body"),
00830                                readlen);
00831            }
00832        }
00833     } else if (resp->length > 0) {
00834        resp->left -= readlen;
00835     }
00836     return HTTP_OK;
00837 }
00838 
00839 /* Build a request string into the buffer.
00840  * If we sent the data as we generated it, it's possible that multiple
00841  * packets could go out on the wire, which is less efficient. */
00842 static void build_request(http_req *req, sbuffer buf) 
00843 {
00844     const char *uri;
00845     char *tmp;
00846     http_session *sess = req->session;
00847     
00848     /* If we are talking to a proxy, we send them the absoluteURI
00849      * as the Request-URI. If we are talking to a server, we just 
00850      * send abs_path. */
00851     if (req->use_proxy)
00852        uri = req->uri;
00853     else
00854        uri = req->abs_path;
00855     
00856     sbuffer_clear(buf);
00857 
00858     /* Add in the request and the user-supplied headers */
00859     sbuffer_concat(buf, req->method, " ", uri, " HTTP/1.1" EOL,
00860                   sbuffer_data(req->headers), NULL);
00861     
00862     /* And the all-important Host header.  This is done here since it
00863      * might change for a new server. */
00864     sbuffer_concat(buf, "Host: ", req->session->server.hostport, 
00865                  EOL, NULL);
00866 
00867 
00868     /* Note that we pass the abs_path here... */
00869     http_auth_new_request(&sess->server.auth, req->method, req->uri,
00870                         req->body_buffer, req->body_stream);
00871     if (req->use_proxy) {
00872        /* ...and absoluteURI here. */
00873        http_auth_new_request(&sess->proxy.auth, req->method, req->uri,
00874                             req->body_buffer, req->body_stream);
00875     }
00876 
00877     /* Add the authorization headers in */
00878     tmp = http_auth_request_header(&req->session->server.auth);
00879     if (tmp != NULL) {
00880        sbuffer_concat(buf, "Authorization: ", tmp, NULL);
00881        free(tmp);
00882     }
00883 
00884     if (req->use_proxy) {
00885        tmp = http_auth_request_header(&req->session->proxy.auth);
00886        if (tmp != NULL) {
00887            sbuffer_concat(buf, "Proxy-Authorization: ", tmp, NULL);
00888            free(tmp);
00889        }
00890     }
00891     
00892     /* Now handle the body. */
00893     req->use_expect100 = 0;
00894     if (req->body!=body_none && 
00895        (req->session->expect100_works > -1) &&
00896        (req->body_size > HTTP_EXPECT_MINSIZE) && 
00897        !HTTP_VERSION_PRE11(req->session)) {
00898        /* Add Expect: 100-continue. */
00899        sbuffer_zappend(buf, "Expect: 100-continue" EOL);
00900        req->use_expect100 = 1;
00901     }
00902 
00903 }
00904 
00905 static int set_sockerr(http_req *req, const char *doing, int code)
00906 {
00907     switch(code) {
00908     case 0: /* FIXME: still needed? */
00909     case SOCK_CLOSED:
00910        if (req->use_proxy) {
00911            snprintf(req->session->error, BUFSIZ,
00912                     _("%s: connection was closed by proxy server."), doing);
00913        } else {
00914            snprintf(req->session->error, BUFSIZ,
00915                     _("%s: connection was closed by server."), doing);
00916        }
00917        return HTTP_ERROR;
00918     case SOCK_TIMEOUT:
00919        snprintf(req->session->error, BUFSIZ, 
00920                 _("%s: connection timed out."), doing);
00921        return HTTP_TIMEOUT;
00922     default:
00923        if (req->session->socket != NULL) {
00924            const char *err = sock_get_error(req->session->socket);
00925            if (err != NULL) {
00926               snprintf(req->session->error, BUFSIZ, "%s: %s", doing, err);
00927            } else {
00928               snprintf(req->session->error, BUFSIZ, _("%s: socket error."),
00929                       doing);
00930            }
00931        } else {
00932            snprintf(req->session->error, BUFSIZ,
00933                    "%s: %s", doing, strerror(errno));
00934        }          
00935        return HTTP_ERROR;
00936     }
00937 }
00938 
00939 /* FIXME: this function need re-writing.
00940  *
00941  * buf is used to read response lines, must be created, and of size >= BUFSIZ.
00942  * Returns HTTP_*, and sets session error appropriately.
00943  */
00944 static int send_request(http_req *req, const char *request, sbuffer buf)
00945 {
00946     http_session *sess = req->session;
00947     int ret, try_again, send_attempt;
00948 
00949     try_again = 1;
00950     
00951     do {
00952 
00953        /* FIXME: this is broken */
00954        try_again--;
00955 
00956 #ifdef DEBUGGING
00957        { 
00958            if ((DEBUG_HTTPPLAIN&neon_debug_mask) == DEBUG_HTTPPLAIN) { 
00959               /* Display everything mode */
00960               DEBUG(DEBUG_HTTP, "Sending request headers:\n%s", request);
00961            } else {
00962               /* Blank out the Authorization paramaters */
00963               char *reqdebug = ne_strdup(request), *pnt = reqdebug;
00964               while ((pnt = strstr(pnt, "Authorization: ")) != NULL) {
00965                   for (pnt += 15; *pnt != '\r' && *pnt != '\0'; pnt++) {
00966                      *pnt = 'x';
00967                   }
00968               }
00969               DEBUG(DEBUG_HTTP, "Sending request headers:\n%s", reqdebug);
00970               free(reqdebug);
00971            }
00972        }
00973 #endif /* DEBUGGING */
00974        
00975        /* Send the Request-Line and headers */
00976        for (send_attempt = 0; send_attempt < 2; send_attempt++) {
00977            DEBUG(DEBUG_HTTP, "Sending headers: attempt %d\n", send_attempt);
00978            /* Open the connection if necessary */
00979            ret = open_connection(req);
00980            if (ret != HTTP_OK) {
00981               return ret;
00982            }
00983            ret = sock_send_string(req->session->socket, request);
00984            if (ret == SOCK_CLOSED) {
00985               /* Could happen due to a persistent connection timeout.
00986                * Or the server being restarted. */
00987               DEBUG(DEBUG_HTTP, "Connection was closed by server.\n");
00988               close_connection(req->session);
00989            } else {
00990               break;
00991            }
00992        }
00993        
00994        if (ret < 0) {
00995            return set_sockerr(req, _("Could not send request"), ret);
00996        }
00997 
00998        DEBUG(DEBUG_HTTP, "Request sent\n");
00999        
01000        /* Now, if we are doing a Expect: 100, hang around for a short
01001         * amount of time, to see if the server actually cares about the 
01002         * Expect and sends us a 100 Continue response if the request
01003         * is valid, else an error code if it's not. This saves sending
01004         * big files to the server when they will be rejected.
01005         */
01006        
01007        if (req->use_expect100) {
01008            DEBUG(DEBUG_HTTP, "Waiting for response...\n");
01009            ret = sock_block(sess->socket, HTTP_EXPECT_TIMEOUT);
01010            switch(ret) {
01011            case SOCK_TIMEOUT: 
01012               /* Timed out - i.e. Expect: ignored. There is a danger
01013                * here that the server DOES respect the Expect: header,
01014                * but was going SO slowly that it didn't get time to
01015                * respond within HTTP_EXPECT_TIMEOUT.
01016                * TODO: while sending the body, check to see if the
01017                * server has sent anything back - if it HAS, then
01018                * stop sending - this is a spec compliance SHOULD */
01019               DEBUG(DEBUG_HTTP, "Wait timed out.\n");
01020               sess->expect100_works = -1; /* don't try that again */
01021               /* Try sending the request again without using 100-continue */
01022               try_again++;
01023               continue;
01024               break;
01025            case SOCK_CLOSED:
01026            case SOCK_ERROR: /* error */
01027               return set_sockerr(req, _("Error waiting for response"), ret);
01028            default:
01029               DEBUG(DEBUG_HTTP, "Wait got data.\n");
01030               sess->expect100_works = 1; /* it works - use it again */
01031               break;
01032            }
01033        } else if (req->body != body_none) {
01034            /* Just chuck the file down the socket */
01035            DEBUG(DEBUG_HTTP, "Sending body...\n");
01036            ret = send_request_body(req);
01037            if (ret == SOCK_CLOSED) {
01038               /* This happens if the persistent connection times out:
01039                * the first write() of the headers gets a delayed write
01040                * seemingly, so the write doesn't fail till this one.
01041                */
01042               DEBUG(DEBUG_HTTP, "Connection closed before request sent, retrying\n");
01043               try_again++;
01044               close_connection(req->session);
01045               continue;
01046            } else if (ret < 0) {
01047               DEBUG(DEBUG_HTTP, "Body send failed.\n");
01048               return set_sockerr(req, _("Could not send request body"), ret);
01049            }
01050            DEBUG(DEBUG_HTTP, "Body sent.\n");
01051            
01052        }
01053        
01054        /* Now, we have either:
01055         *   - Sent the header and body, or
01056         *   - Sent the header incl. Expect: line, and got some response.
01057         * In any case, we get the status line of the response.
01058         */
01059        
01060        /* HTTP/1.1 says that the server MAY emit any number of
01061         * interim 100 (Continue) responses prior to the normal
01062         * response.  So loop while we get them.  */
01063        
01064        do {
01065            if (sock_readline(sess->socket, sbuffer_data(buf), BUFSIZ) <= 0) {
01066               if (try_again) {
01067                   return set_sockerr(req, _("Could not read status line"), ret);
01068               }
01069               DEBUG(DEBUG_HTTP, "Failed to read status line.\n");
01070               try_again++;
01071               break;
01072            }
01073 
01074            DEBUG(DEBUG_HTTP, "[Status Line] < %s", sbuffer_data(buf));
01075            
01076            /* Got the status line - parse it */
01077            if (http_parse_statusline(sbuffer_data(buf), &req->status)) {
01078               http_set_error(sess, _("Could not parse response status line."));
01079               return -1;
01080            }
01081 
01082            sess->version_major = req->status.major_version;
01083            sess->version_minor = req->status.minor_version;
01084            snprintf(sess->error, BUFSIZ, "%d %s", 
01085                    req->status.code, req->status.reason_phrase);
01086            STRIP_EOL(sess->error);
01087 
01088            if (req->status.klass == 1) {
01089               DEBUG(DEBUG_HTTP, "Got 1xx-class.\n");
01090               /* Skip any headers, we don't need them */
01091               do {
01092                   ret = sock_readline(sess->socket, sbuffer_data(buf), BUFSIZ);
01093                   if (ret <= 0) {
01094                      return set_sockerr(
01095                          req, _("Error reading response headers"), ret);
01096                   }
01097                   DEBUG(DEBUG_HTTP, "[Ignored header] < %s", 
01098                         sbuffer_data(buf));
01099               } while (strcmp(sbuffer_data(buf), EOL) != 0);
01100        
01101               if (req->use_expect100 && (req->status.code == 100)) {
01102                   /* We are using Expect: 100, and we got a 100-continue 
01103                    * return code... send the request body */
01104                   DEBUG(DEBUG_HTTP, "Got continue... sending body now.\n");
01105                   ret = send_request_body(req);
01106                   if (ret <= 0) {
01107                      return set_sockerr(
01108                          req, _("Error sending request body"), ret);
01109                   }
01110 
01111                   DEBUG(DEBUG_HTTP, "Body sent.\n");
01112               } else if (req->upgrade_to_tls && (req->status.code == 101)) {
01113                   /* Switch to TLS on the fly */
01114                   if (sock_make_secure(sess->socket, sess->ssl_context)) {
01115                      close_connection(sess);
01116                      return set_sockerr(req, _("Could not negotiate SSL session"),
01117                                       SOCK_ERROR);
01118                   }
01119               }
01120            }
01121        } while (req->status.klass == 1);
01122 
01123        if (try_again == 1) {
01124            /* If we're trying again, close the conn first */
01125            DEBUG(DEBUG_HTTP, "Retrying request, closing connection first.\n");
01126            close_connection(sess);
01127        }
01128 
01129     } while (try_again == 1);
01130 
01131     return HTTP_OK;
01132 }
01133 
01134 /* Read a message header from sock into buf.
01135  * 'extra' is used to store continuation lines in, and must be
01136  * at least of size BUFSIZ.
01137  * Returns:
01138  *   HTTP_RETRY: Read a header into buf.
01139  *   HTTP_OK: End-of-headers
01140  *   HTTP_ERROR: Error (session error is set).
01141  */
01142 static int read_message_header(http_req *req, sbuffer buf, char *extra)
01143 {
01144     char *pnt, ch;
01145     int ret;
01146     nsocket *sock = req->session->socket;
01147 
01148     ret = sock_readline(sock, sbuffer_data(buf), BUFSIZ);
01149     if (ret <= 0)
01150        return set_sockerr(req, _("Error reading response headers"), ret);
01151     DEBUG(DEBUG_HTTP, "[Header:%d] < %s", 
01152           strlen(sbuffer_data(buf)), sbuffer_data(buf));
01153 
01154     STRIP_EOL(sbuffer_data(buf));
01155     sbuffer_altered(buf);
01156 
01157     if (sbuffer_size(buf) == 0) {
01158        DEBUG(DEBUG_HTTP, "End of headers.\n");
01159        return HTTP_OK;
01160     }
01161 
01162     while (sbuffer_size(buf) < HTTP_MAXIMUM_HEADER_LENGTH) {
01163        /* Collect any extra lines into buffer */
01164        ret = sock_peek(sock, &ch, 1);
01165        if (ret <= 0) {
01166            return set_sockerr(req, _("Error reading response headers"), ret);
01167        }
01168        if (ch != ' ' && ch != '\t') {
01169            /* No continuation of this header */
01170            return HTTP_RETRY;
01171        }
01172        /* Read BUFSIZ-1 bytes to guarantee that we have a \0 */
01173        ret = sock_readline(sock, extra, BUFSIZ-1);
01174        if (ret <= 0) {
01175            return set_sockerr(req, _("Error reading response headers"), ret);
01176        }
01177        DEBUG(DEBUG_HTTP, "[Cont:%d] < %s", strlen(extra), extra);
01178        /* Append a space to the end of the last header, in
01179         * place of the CRLF. */
01180        sbuffer_append(buf, " ", 1);
01181        for (pnt = extra; *pnt!='\0' && 
01182                (*pnt == ' ' || *pnt =='\t'); pnt++) /*oneliner*/;
01183        DEBUG(DEBUG_HTTP, "[Continued] < %s", pnt);
01184        sbuffer_zappend(buf, pnt);
01185     }
01186 
01187     http_set_error(req->session, _("Response header too long"));
01188     return HTTP_ERROR;
01189 }
01190 
01191 static void normalize_response_length(http_req *req)
01192 {
01193     /* Response entity-body length calculation, bit icky.
01194      * Here, we set:
01195      * length==-1 if we DO NOT know the exact body length
01196      * length>=0 if we DO know the body length.
01197      *
01198      * RFC2616, section 4.4: 
01199      * NO body is returned if the method is HEAD, or the resp status
01200      * is 204 or 304
01201      */
01202     if (req->method_is_head || req->status.code==204 || 
01203        req->status.code==304) {
01204        req->resp.length = 0;
01205     } else {
01206        /* RFC2616, section 4.4: if we have a transfer encoding
01207         * and a content-length, then ignore the content-length. */
01208        if ((req->resp.length>-1) && 
01209            (req->resp.is_chunked)) {
01210            req->resp.length = -1;
01211        }
01212     }
01213     /* Noddy noddy noddy. Testing from Apache/mod_proxy, CONNECT does
01214      * not return a Content-Length... */
01215     if (req->resp.length == -1 && req->session->in_connect &&
01216        req->status.klass == 2) {
01217        req->resp.length = 0;
01218     }
01219        
01220 }
01221 
01222 /* Read response headers, using buffer buffer.
01223  * Returns HTTP_* code, sets session error. */
01224 static int read_response_headers(http_req *req, sbuffer buf) 
01225 {
01226     char extra[BUFSIZ] = {0};
01227     int ret;
01228     
01229     /* Read response headers.  This loop has been optimized: my GCC
01230      * will put all the local vars in registers. */
01231     while ((ret = read_message_header(req, buf, extra)) == HTTP_RETRY) {
01232        struct header_handler *hdl;
01233        char *hdr;
01234        /* hint to the compiler that we'd like these in registers */
01235        register char *pnt;
01236        register int hash = 0;
01237 
01238        /* Quicker than sbuffer_data(), and means 'hdr' can be 
01239         * optimized away. */
01240        hdr = SBUFFER_CAST(buf);
01241        
01242        for (hdl = req->header_catchers; hdl != NULL; hdl = hdl->next) {
01243            (*hdl->handler)(hdl->userdata, hdr);
01244        }
01245        
01246        /* Iterate over the header name, converting it to lower case and 
01247         * calculating the hash value as we go. */
01248        for (pnt = hdr; *pnt != '\0' && *pnt != ':'; pnt++) {
01249            *pnt = tolower(*pnt);
01250            hash = HH_ITERATE(hash,*pnt);
01251        }
01252 
01253        if (*pnt != '\0') {
01254            /* Null-term name at the : */
01255            *pnt = '\0';
01256            
01257            /* Value starts after any whitespace... */
01258            do {
01259               pnt++;
01260            } while (*pnt == ' ' || *pnt == '\t');
01261            
01262            DEBUG(DEBUG_HTTP, "Header Name: [%s], Value: [%s]\n", hdr, pnt);
01263            
01264            /* Iterate through the header handlers */
01265            for (hdl = req->header_handlers[hash]; hdl != NULL; 
01266                hdl = hdl->next) {
01267               if (strcmp(hdr, hdl->name) == 0) {
01268                   (*hdl->handler)(hdl->userdata, pnt);
01269               }
01270            }
01271        } else {
01272            http_set_error(req->session, _("Malformed header line."));
01273            return HTTP_ERROR;
01274        }
01275     }
01276 
01277     return ret;
01278 }
01279 
01280 /* Read the response message body */
01281 static int read_response_body(http_req *req)
01282 {
01283     char buffer[BUFSIZ];
01284     int ret = HTTP_OK;
01285     size_t readlen;
01286     struct body_reader *rdr;
01287            
01288     /* If there is nothing to do... */
01289     if (req->resp.length == 0) {
01290        /* Do nothing */
01291        return HTTP_OK;
01292     }
01293     
01294     /* First off, tell all of the response body handlers that they are
01295      * going to get a body, and let them work out whether they want to 
01296      * handle it or not */
01297     for (rdr = req->body_readers; rdr != NULL; rdr=rdr->next) {
01298        rdr->use = (*rdr->accept_response)(rdr->userdata, req, &req->status);
01299     }    
01300     
01301     req->resp.left = req->resp.length;
01302     req->resp.chunk_left = 0;
01303 
01304     /* Now actually read the thing */
01305     
01306     do {
01307        /* Read a block */
01308        readlen = BUFSIZ;
01309        ret = read_response_block(req, &req->resp, buffer, &readlen);
01310        
01311        /* TODO: Do we need to call them if readlen==0, or if
01312         * readlen == -1, to tell them something has gone wrong? */
01313           
01314        if (ret == HTTP_OK) {
01315            for (rdr = req->body_readers; rdr!=NULL; rdr=rdr->next) {
01316               if (rdr->use)
01317                   (*rdr->handler)(rdr->userdata, buffer, readlen);
01318            }
01319        }
01320 
01321     } while (ret == HTTP_OK && readlen > 0);
01322 
01323     if (ret != HTTP_OK)
01324        req->forced_close = 1;
01325 
01326     return ret;
01327 }
01328 
01329 /* Handler for the "Transfer-Encoding" response header */
01330 static void te_hdr_handler(void *userdata, const char *value) 
01331 {
01332     struct http_response *resp = userdata;
01333     if (strcasecmp(value, "chunked") == 0) {
01334        resp->is_chunked = 1;
01335     } else {
01336        resp->is_chunked = 0;
01337     }
01338 }
01339 
01340 /* Handler for the "Connection" response header */
01341 static void connection_hdr_handler(void *userdata, const char *value)
01342 {
01343     http_req *req = userdata;
01344     if (strcasecmp(value, "close") == 0) {
01345        req->forced_close = 1;
01346     } else if (strcasecmp(value, "Keep-Alive") == 0) {
01347        req->can_persist = 1;
01348     }
01349 }
01350 
01351 
01352 /* HTTP/1.x request/response mechanism 
01353  *
01354  * Returns an HTTP_* return code. 
01355  *   
01356  * The status information is placed in status. The error string is
01357  * placed in req->session->error
01358  *
01359  */
01360 int http_request_dispatch(http_req *req) 
01361 {
01362     http_session *sess = req->session;
01363     sbuffer buf, request;
01364     int ret, attempt, proxy_attempt, con_attempt, can_retry;
01365     /* Response header storage */
01366     char *www_auth, *proxy_auth, *authinfo, *proxy_authinfo;
01367     http_status *status = &req->status;
01368 
01369     /* Initialization... */
01370     DEBUG(DEBUG_HTTP, "Request started...\n");
01371     http_set_error(sess, "Unknown error.");
01372     ret = HTTP_OK;
01373 
01374     if (get_request_bodysize(req))
01375        return HTTP_ERROR;
01376 
01377     buf = sbuffer_create_sized(BUFSIZ);
01378 
01379     if (sess->server.auth_callback != NULL) {
01380        http_add_response_header_handler(req, "WWW-Authenticate",
01381                                     http_duplicate_header, &www_auth);
01382        http_add_response_header_handler(req, "Authentication-Info",
01383                                     http_duplicate_header, &authinfo);
01384     }
01385 
01386     if (req->use_proxy && sess->proxy.auth_callback != NULL) {
01387        http_add_response_header_handler(req, "Proxy-Authenticate",
01388                                     http_duplicate_header, &proxy_auth);
01389        http_add_response_header_handler(req, "Proxy-Authentication-Info",
01390                                     http_duplicate_header, 
01391                                     &proxy_authinfo);
01392     }
01393                                  
01394     request = sbuffer_create();
01395     proxy_attempt = con_attempt = attempt = 1;
01396     www_auth = proxy_auth = authinfo = proxy_authinfo = NULL;
01397     
01398     /* Loop sending the request:
01399      * Retry whilst authentication fails and we supply it. */
01400     
01401     do {
01402        struct hook_request *st;
01403        
01404        can_retry = 0;
01405        req->can_persist = 0;
01406        req->forced_close = 0;
01407 
01408        build_request(req, request);
01409 
01410        DEBUG(DEBUG_HTTP, "Running pre_send hooks\n");
01411        for (st = req->hook_store; st!=NULL; st = st->next) {
01412            if (HAVE_HOOK(st,pre_send)) {
01413               HOOK_FUNC(st,pre_send)(st->cookie, request);
01414            }
01415        }                                             
01416 
01417        /* Final CRLF */
01418        sbuffer_zappend(request, EOL);
01419        
01420        /* Now send the request, and read the Status-Line */
01421        ret = send_request(req, sbuffer_data(request), buf);
01422        if (ret != HTTP_OK) goto dispatch_error;
01423 
01424        req->resp.length = -1;
01425        req->resp.is_chunked = 0;
01426 
01427        /* Read the headers */
01428        if (read_response_headers(req, buf) != HTTP_OK) {
01429            ret = HTTP_ERROR;
01430            goto dispatch_error;
01431        }
01432 
01433        normalize_response_length(req);
01434 
01435        ret = read_response_body(req);
01436        if (ret != HTTP_OK) goto dispatch_error;
01437 
01438        /* Read headers in chunked trailers */
01439        if (req->resp.is_chunked) {
01440            ret = read_response_headers(req, buf);
01441            if (ret != HTTP_OK) goto dispatch_error;
01442        }
01443 
01444        DEBUG(DEBUG_HTTP, "Running post_send hooks\n");
01445        for (st = req->hook_store; st!=NULL; st = st->next) {
01446            if (HAVE_HOOK(st,post_send)) {
01447               int hret = HOOK_FUNC(st,post_send)(st->cookie, status);
01448               /* TODO: this will simplify down to using just 'ret' once
01449                * we move authentication into hooks. */
01450               switch(hret) {
01451               case HTTP_OK:
01452                   break;
01453               case HTTP_RETRY:
01454                   can_retry = 1;
01455                   break;
01456               default:
01457                   /* They must set session error */
01458                   ret = hret;
01459               }
01460            }
01461        }
01462 
01463        if (proxy_authinfo != NULL && 
01464            http_auth_verify_response(&sess->proxy.auth, proxy_authinfo)) {
01465            DEBUG(DEBUG_HTTP, "Proxy response authentication invalid.\n");
01466            ret = HTTP_SERVERAUTH;
01467            http_set_error(sess, _("Proxy server was not authenticated correctly."));
01468        } else if (authinfo != NULL &&
01469                  http_auth_verify_response(&sess->server.auth, authinfo)) {
01470            DEBUG(DEBUG_HTTP, "Response authenticated as invalid.\n");
01471            ret = HTTP_PROXYAUTH;
01472            http_set_error(sess, _("Server was not authenticated correctly."));
01473        } else if (status->code == 401 && www_auth != NULL && attempt++ == 1) {
01474            if (!http_auth_challenge(&sess->server.auth, www_auth)) {
01475               can_retry = 1;
01476            }         
01477        } else if (status->code == 407 && proxy_auth != NULL && proxy_attempt++ == 1) {
01478            if (!http_auth_challenge(&sess->proxy.auth, proxy_auth)) {
01479               can_retry = 1;
01480            }
01481        }
01482 
01483        HTTP_FREE(www_auth);
01484        HTTP_FREE(proxy_auth);
01485        HTTP_FREE(authinfo);
01486        HTTP_FREE(proxy_authinfo);
01487        
01488        DEBUG(DEBUG_HTTP, "Connection status: %s, %s, %s\n",
01489              req->forced_close?"forced close":"no forced close",
01490              sess->no_persist?"no persistent connection":"persistent connection",
01491              HTTP_VERSION_PRE11(sess)?"pre-HTTP/1.1":"HTTP/1.1 or later");
01492 
01493        /* Close the connection if any of the following are true:
01494         *  - We have a forced close (e.g. "Connection: close" header)
01495         *  - We are not using persistent connections for this session
01496         *  - All of the following are true:
01497         *    * this is HTTP/1.0
01498         *    * and they haven't said they can do persistent connections 
01499         *    * we've not just done a successful CONNECT
01500         */
01501        if (req->forced_close || sess->no_persist ||
01502            (HTTP_VERSION_PRE11(sess) && 
01503             !req->can_persist && 
01504             (!sess->in_connect || status->klass != 2))) {
01505            close_connection(sess);
01506        }
01507     
01508        /* Retry it if we had an auth challenge */
01509 
01510     } while (can_retry);
01511 
01512     DEBUG(DEBUG_HTTP | DEBUG_FLUSH, 
01513           "Request ends, status %d class %dxx, error line:\n%s\n", 
01514           status->code, status->klass, sess->error);
01515     DEBUG(DEBUG_HTTPBASIC, "Response: %d %s", status->code, sess->error);
01516 
01517     if (ret == HTTP_OK) {
01518        switch(status->code) {
01519        case 401:
01520            ret = HTTP_AUTH;
01521            break;
01522        case 407:
01523            ret = HTTP_AUTHPROXY;
01524            break;
01525        default:
01526            break;
01527        }
01528     }
01529 
01530 dispatch_error:
01531     
01532     sbuffer_destroy(request);
01533     sbuffer_destroy(buf);
01534 
01535     HTTP_FREE(www_auth);
01536     HTTP_FREE(proxy_auth);
01537     HTTP_FREE(authinfo);
01538     HTTP_FREE(proxy_authinfo);
01539 
01540     return ret;
01541 }
01542 
01543 const http_status *http_get_status(http_req *req)
01544 {
01545     return &(req->status);
01546 }
01547 
01548 /* Create a CONNECT tunnel through the proxy server.
01549  * Returns HTTP_* */
01550 static int proxy_tunnel(http_session *sess)
01551 {
01552     /* Hack up an HTTP CONNECT request... */
01553     http_req *req = http_request_create(sess, "CONNECT", NULL);
01554     int ret = HTTP_OK;
01555 
01556     /* Fudge the URI to be how we want it */
01557     req->uri = ne_strdup(sess->server.hostport);
01558 
01559     sess->connected = 1;
01560     sess->in_connect = 1;
01561 
01562     ret = http_request_dispatch(req);
01563 
01564     sess->in_connect = 0;
01565 
01566     if (ret != HTTP_OK || !sess->connected || 
01567        req->status.klass != 2) {
01568        /* It failed */
01569        http_set_error(sess, 
01570                      _("Could not create SSL connection through proxy server"));
01571        ret = HTTP_ERROR;
01572     }
01573 
01574     http_request_destroy(req);
01575     
01576     return ret;
01577 }
01578 
01579 static int open_connection(http_req *req) 
01580 {
01581     http_session *sess = req->session;
01582 
01583     if (req->use_proxy) {
01584        switch(sess->connected) {
01585        case 0:
01586            /* Make the TCP connection to the proxy */
01587            DEBUG(DEBUG_SOCKET, "Connecting to proxy at %s:%d...\n", 
01588                  sess->proxy.hostname, sess->proxy.port);
01589            sess->socket = sock_connect(sess->proxy.addr, sess->proxy.port);
01590            if (sess->socket == NULL) {
01591               (void) set_sockerr(req, _("Could not connect to proxy server"), SOCK_ERROR);
01592               return HTTP_CONNECT;
01593            }
01594            sess->connected = 1;
01595            /* FALL-THROUGH */
01596        case 1:
01597            if (sess->use_secure && !sess->in_connect) {
01598               int ret;
01599               ret = proxy_tunnel(sess);
01600               if (ret != HTTP_OK) {
01601                   close_connection(sess);
01602                   return ret;
01603               }
01604               if (sock_make_secure(sess->socket, sess->ssl_context)) {
01605                   (void) set_sockerr(req, _("Could not negotiate SSL session"), SOCK_ERROR);
01606                   close_connection(sess);
01607                   return HTTP_ERROR;
01608               }
01609               sess->connected = 2;
01610            } else {
01611               break;
01612            }
01613            break;
01614        default:
01615            /* We've got everything we need */
01616            break;        
01617        }
01618     } else if (sess->connected == 0) {
01619 
01620        DEBUG(DEBUG_SOCKET, "Connecting to server at %s:%d...\n", 
01621               sess->server.hostname, sess->server.port);
01622 
01623        sess->socket = sock_connect(sess->server.addr, sess->server.port);
01624            
01625        if (sess->socket == NULL) {
01626            (void) set_sockerr(req, _("Could not connect to server"), -1);
01627            return HTTP_CONNECT;
01628        }
01629 
01630        if (sess->use_secure) {
01631            DEBUG(DEBUG_SOCKET, "Starting SSL...\n");
01632            if (sock_make_secure(sess->socket, sess->ssl_context)) {
01633               (void) set_sockerr(req, _("Could not negotiate SSL session"), SOCK_ERROR);
01634               return HTTP_ERROR;
01635            }
01636        }
01637 
01638        sess->connected = 1;
01639     }
01640     return HTTP_OK;
01641 }
01642 
01643 static int close_connection(http_session *sess) 
01644 {
01645     DEBUG(DEBUG_SOCKET, "Closing connection.\n");
01646     if (sess->connected > 0) {
01647        sock_close(sess->socket);
01648        sess->socket = NULL;
01649     }
01650     sess->connected = 0;
01651     DEBUG(DEBUG_SOCKET, "Connection closed.\n");
01652     return 0;
01653 }
01654