Return-Path: Delivered-To: new-httpd-archive@hyperreal.org Received: (qmail 29181 invoked by uid 6000); 22 Jul 1998 23:43:15 -0000 Received: (qmail 29141 invoked from network); 22 Jul 1998 23:43:06 -0000 Received: from thoth.mch.sni.de (192.35.17.2) by taz.hyperreal.org with SMTP; 22 Jul 1998 23:43:06 -0000 X-Envelope-Sender-Is: Martin.Kraemer@mch.sni.de (at relayer thoth.mch.sni.de) Received: from deejai.mch.sni.de (deejai.mch.sni.de [139.25.105.242]) by thoth.mch.sni.de (8.9.1/8.9.1) with ESMTP id BAA24825 for ; Thu, 23 Jul 1998 01:43:03 +0200 (MDT) Received: (from martin@localhost) by deejai.mch.sni.de (8.8.7/8.8.7) id VAA09574; Wed, 22 Jul 1998 21:12:46 +0200 (MET DST) Message-ID: <19980722211244.57755@deejai.mch.sni.de> Date: Wed, 22 Jul 1998 21:12:44 +0200 From: Martin Kraemer To: new-httpd@apache.org Subject: [PATCH] replace `array_header' with `table' in mod_proxy Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="jI8keyz6grp/JLjh" X-Mailer: Mutt 0.69 Sender: new-httpd-owner@apache.org Precedence: bulk Reply-To: new-httpd@apache.org --jI8keyz6grp/JLjh Content-Type: text/plain; charset=us-ascii This patch tries to replace all occurences of array_header* with the equivalent table* functions. It is part of a cleanup which I would like to see in 1.3.2 in conjunction with the Via: patches. Without them, I will have to cast between array_header* and table* at several places, which I'd prefer to avoid. In general, using table* makes the code clearer and easier, but with mod_proxy, one needs a bush knife anyways. However I *fear* I overdid it and modified too much while I was at it. Whaddya think? Martin -- | S I E M E N S | | Siemens Nixdorf | ------------- | Voice: +49-89-636-46021 | Informationssysteme AG | N I X D O R F | FAX: +49-89-636-44994 | 81730 Munich, Germany ~~~~~~~~~~~~~~~~My opinions only, of course; pgp key available on request --jI8keyz6grp/JLjh Content-Type: text/plain; charset=us-ascii Content-Description: Patch to use table* instead of array_header* Content-Disposition: attachment; filename="proxy_array_header_to_table.patch" diff -u /usr/src/apache-1.3/src/modules/proxy/mod_proxy.h apache-1.3/src/modules/proxy/mod_proxy.h --- /usr/src/apache-1.3/src/modules/proxy/mod_proxy.h Thu Jul 9 22:00:26 1998 +++ apache-1.3/src/modules/proxy/mod_proxy.h Wed Jul 22 21:48:15 1998 @@ -55,6 +55,9 @@ * */ +#ifndef MOD_PROXY_H +#define MOD_PROXY_H + /* * Main include file for the Apache proxy */ @@ -237,7 +240,13 @@ unsigned int written; /* total *content* bytes written to cache */ float cache_completion; /* specific to this request */ char *resp_line; /* the whole status like (protocol, code + message) */ - array_header *hdrs; /* the HTTP headers of the file */ + table *hdrs; /* the HTTP headers of the file */ +}; + +/* Additional information passed to the function called by ap_table_do() */ +struct tbl_do_args { + request_rec *req; + struct cache_req *cache; }; /* Function prototypes */ @@ -247,7 +256,7 @@ void ap_proxy_cache_tidy(struct cache_req *c); int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, struct cache_req **cr); -int ap_proxy_cache_update(struct cache_req *c, array_header *resp_hdrs, +int ap_proxy_cache_update(struct cache_req *c, table *resp_hdrs, const int is_HTTP1, int nocache); void ap_proxy_garbage_coll(request_rec *r); @@ -277,19 +286,14 @@ char *ap_proxy_canon_netloc(pool *p, char **const urlp, char **userp, char **passwordp, char **hostp, int *port); const char *ap_proxy_date_canon(pool *p, const char *x); -array_header *ap_proxy_read_headers(pool *p, char *buffer, int size, BUFF *f); -long int ap_proxy_send_fb(BUFF *f, request_rec *r, BUFF *f2, struct cache_req *c); -struct hdr_entry *ap_proxy_get_header(array_header *hdrs_arr, const char *name); -struct hdr_entry *ap_proxy_add_header(array_header *hdrs_arr, const char *field, - const char *value, int rep); -void ap_proxy_del_header(array_header *hdrs_arr, const char *field); -void ap_proxy_send_headers(request_rec *r, const char *respline, - array_header *hdrs_arr); +table *ap_proxy_read_headers(pool *p, char *buffer, int size, BUFF *f); +long int ap_proxy_send_fb(BUFF *f, request_rec *r, struct cache_req *c); +void ap_proxy_send_headers(request_rec *r, const char *respline, table *hdrs); int ap_proxy_liststr(const char *list, const char *val); void ap_proxy_hash(const char *it, char *val, int ndepth, int nlength); int ap_proxy_hex2sec(const char *x); void ap_proxy_sec2hex(int t, char *y); -BUFF *ap_proxy_cache_error(struct cache_req *r); +struct cache_req *ap_proxy_cache_error(struct cache_req *r); int ap_proxyerror(request_rec *r, const char *message); const char *ap_proxy_host2addr(const char *host, struct hostent *reqhp); int ap_proxy_is_ipaddr(struct dirconn_entry *This, pool *p); @@ -298,3 +302,7 @@ int ap_proxy_is_word(struct dirconn_entry *This, pool *p); int ap_proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r); int ap_proxy_garbage_init(server_rec *, pool *); +/* This function is called by ap_table_do() for all header lines */ +int ap_proxy_send_hdr_line(void *p, const char *key, const char *value); + +#endif /*MOD_PROXY_H*/ diff -u /usr/src/apache-1.3/src/modules/proxy/proxy_cache.c apache-1.3/src/modules/proxy/proxy_cache.c --- /usr/src/apache-1.3/src/modules/proxy/proxy_cache.c Thu Jul 9 22:00:26 1998 +++ apache-1.3/src/modules/proxy/proxy_cache.c Wed Jul 22 22:11:34 1998 @@ -544,7 +544,7 @@ * date SP lastmod SP expire SP count SP content-length CRLF * dates are stored as hex seconds since 1970 */ - len = ap_bgets(urlbuff, 1034, cachefp); + len = ap_bgets(urlbuff, sizeof urlbuff, cachefp); if (len == -1) return -1; if (len == 0 || urlbuff[len - 1] != '\n') @@ -562,7 +562,7 @@ c->len = ap_proxy_hex2sec(urlbuff + 36); /* check that we have the same URL */ - len = ap_bgets(urlbuff, 1034, cachefp); + len = ap_bgets(urlbuff, sizeof urlbuff, cachefp); if (len == -1) return -1; if (len == 0 || strncmp(urlbuff, "X-URL: ", 7) != 0 || @@ -573,7 +573,7 @@ return 0; /* What follows is the message */ - len = ap_bgets(urlbuff, 1034, cachefp); + len = ap_bgets(urlbuff, sizeof urlbuff, cachefp); if (len == -1) return -1; if (len == 0 || urlbuff[len - 1] != '\n') @@ -586,16 +586,13 @@ return 0; c->status = atoi(strp); - c->hdrs = ap_proxy_read_headers(p, urlbuff, 1034, cachefp); + c->hdrs = ap_proxy_read_headers(p, urlbuff, sizeof urlbuff, cachefp); if (c->hdrs == NULL) return -1; if (c->len != -1) { /* add a content-length header */ - struct hdr_entry *q; - q = ap_proxy_get_header(c->hdrs, "Content-Length"); - if (q == NULL) { - strp = ap_palloc(p, 15); - ap_snprintf(strp, 15, "%lu", (unsigned long)c->len); - ap_proxy_add_header(c->hdrs, "Content-Length", strp, HDR_REP); + if (ap_table_get(c->hdrs, "Content-Length") == NULL) { + strp = ap_psprintf(p, "%lu", (unsigned long)c->len); + ap_table_set(c->hdrs, "Content-Length", strp); } } return 1; @@ -696,7 +693,7 @@ /* fixed? in this case, we want to get the headers from the remote server it will be handled later if we don't do this (I hope ;-) if (cachefp == NULL) - c->hdrs = ap_make_array(r->pool, 2, sizeof(struct hdr_entry)); + c->hdrs = ap_make_table(r->pool, 20); */ /* FIXME: Shouldn't we check the URL somewhere? */ now = time(NULL); @@ -710,14 +707,10 @@ /* No, but these header values may have changed, so we send them with the * 304 response */ - /* CHECKME: surely this was wrong? (Ben) - p = table_get(r->headers_in, "Expires"); - */ - struct hdr_entry *q; - - q = ap_proxy_get_header(c->hdrs, "Expires"); - if (q != NULL && q->value != NULL) - ap_table_set(r->headers_out, "Expires", q->value); + const char *q; + + if ((q = ap_table_get(c->hdrs, "Expires")) != NULL) + ap_table_set(r->headers_out, "Expires", q); } ap_pclosef(r->pool, cachefp->fd); Explain0("Use local copy, cached file hasn't changed"); @@ -736,7 +729,7 @@ ap_bsetopt(r->connection->client, BO_BYTECT, &zero); r->sent_bodyct = 1; if (!r->header_only) - ap_proxy_send_fb(cachefp, r, NULL, NULL); + ap_proxy_send_fb(cachefp, r, NULL); ap_pclosef(r->pool, cachefp->fd); return OK; } @@ -751,13 +744,11 @@ * from the cache */ if (c->ims == BAD_DATE || c->ims < c->lmod) { - struct hdr_entry *q; - - q = ap_proxy_get_header(c->hdrs, "Last-Modified"); + const char *q; - if (q != NULL && q->value != NULL) + if ((q = ap_table_get(c->hdrs, "Last-Modified")) != NULL) ap_table_set(r->headers_in, "If-Modified-Since", - (char *) q->value); + (char *) q); } } c->fp = cachefp; @@ -779,7 +770,7 @@ * from the cache, maybe updating the header line * otherwise, delete the old cached file and open a new temporary file */ -int ap_proxy_cache_update(struct cache_req *c, array_header *resp_hdrs, +int ap_proxy_cache_update(struct cache_req *c, table *resp_hdrs, const int is_HTTP1, int nocache) { #ifdef ULTRIX_BRAIN_DEATH @@ -788,7 +779,7 @@ request_rec *r = c->req; char *p; int i; - struct hdr_entry *expire, *dates, *lmods, *clen; + const char *expire, *lmods, *dates, *clen; time_t expc, date, lmod, now; char buff[46]; void *sconf = r->server->module_config; @@ -802,21 +793,20 @@ /* read expiry date; if a bad date, then leave it so the client can * read it */ - expire = ap_proxy_get_header(resp_hdrs, "Expires"); + expire = ap_table_get(resp_hdrs, "Expires"); if (expire != NULL) - expc = ap_parseHTTPdate(expire->value); + expc = ap_parseHTTPdate(expire); else expc = BAD_DATE; /* * read the last-modified date; if the date is bad, then delete it */ - lmods = ap_proxy_get_header(resp_hdrs, "Last-Modified"); + lmods = ap_table_get(resp_hdrs, "Last-Modified"); if (lmods != NULL) { - lmod = ap_parseHTTPdate(lmods->value); + lmod = ap_parseHTTPdate(lmods); if (lmod == BAD_DATE) { /* kill last modified date */ - lmods->value = NULL; lmods = NULL; } } @@ -834,7 +824,7 @@ */ if ((r->status != 200 && r->status != 301 && r->status != 304) || (expire != NULL && expc == BAD_DATE) || - (r->status == 304 && c->fp == NULL) || + (r->status == 304 && (c == NULL || c->fp == NULL)) || (r->status == 200 && lmods == NULL && is_HTTP1) || r->header_only || ap_table_get(r->headers_in, "Authorization") != NULL || @@ -854,9 +844,9 @@ /* * Read the date. Generate one if one is not supplied */ - dates = ap_proxy_get_header(resp_hdrs, "Date"); + dates = ap_table_get(resp_hdrs, "Date"); if (dates != NULL) - date = ap_parseHTTPdate(dates->value); + date = ap_parseHTTPdate(dates); else date = BAD_DATE; @@ -867,8 +857,8 @@ /* add one; N.B. use the time _now_ rather than when we were checking the cache */ date = now; - p = ap_gm_timestr_822(r->pool, now); - dates = ap_proxy_add_header(resp_hdrs, "Date", p, HDR_REP); + dates = ap_gm_timestr_822(r->pool, now); + ap_table_set(resp_hdrs, "Date", dates); Explain0("Added date header"); } @@ -877,7 +867,7 @@ /* if its in the future, then replace by date */ { lmod = date; - lmods->value = dates->value; + lmods = dates; Explain0("Last modified is in the future, replacing with now"); } /* if the response did not contain the header, then use the cached version */ @@ -888,9 +878,9 @@ /* we now need to calculate the expire data for the object. */ if (expire == NULL && c->fp != NULL) { /* no expiry data sent in response */ - expire = ap_proxy_get_header(c->hdrs, "Expires"); + expire = ap_table_get(c->hdrs, "Expires"); if (expire != NULL) - expc = ap_parseHTTPdate(expire->value); + expc = ap_parseHTTPdate(expire); } /* so we now have the expiry date */ /* if no expiry date then @@ -914,11 +904,11 @@ } /* get the content-length header */ - clen = ap_proxy_get_header(resp_hdrs, "Content-Length"); + clen = ap_table_get(resp_hdrs, "Content-Length"); if (clen == NULL) c->len = -1; else - c->len = atoi(clen->value); + c->len = atoi(clen); ap_proxy_sec2hex(date, buff); buff[8] = ' '; @@ -966,7 +956,7 @@ ap_bsetopt(r->connection->client, BO_BYTECT, &zero); r->sent_bodyct = 1; if (!r->header_only) - ap_proxy_send_fb(c->fp, r, NULL, NULL); + ap_proxy_send_fb(c->fp, r, NULL); /* set any changed headers somehow */ /* update dates and version, but not content-length */ if (lmod != c->lmod || expc != c->expire || date != c->date) { @@ -1031,11 +1021,13 @@ void ap_proxy_cache_tidy(struct cache_req *c) { - server_rec *s = c->req->server; + server_rec *s; long int bc; - if (c->fp == NULL) + if (c == NULL || c->fp == NULL) return; + + s = c->req->server; /* don't care how much was sent, but rather how much was written to cache ap_bgetopt(c->req->connection->client, BO_BYTECT, &bc); diff -u /usr/src/apache-1.3/src/modules/proxy/proxy_ftp.c apache-1.3/src/modules/proxy/proxy_ftp.c --- /usr/src/apache-1.3/src/modules/proxy/proxy_ftp.c Thu Jul 9 22:00:26 1998 +++ apache-1.3/src/modules/proxy/proxy_ftp.c Wed Jul 22 22:03:29 1998 @@ -355,8 +355,8 @@ while (!con->aborted) { n = ap_bgets(buf, sizeof buf, f); if (n == -1) { /* input error */ - if (f2 != NULL) - f2 = ap_proxy_cache_error(c); + if (c != NULL) + c = ap_proxy_cache_error(c); break; } if (n == 0) @@ -416,9 +416,8 @@ o = 0; total_bytes_sent += n; - if (f2 != NULL) - if (ap_bwrite(f2, buf, n) != n) - f2 = ap_proxy_cache_error(c); + if (c != NULL && ap_bwrite(f2, buf, n) != n) + c = ap_proxy_cache_error(c); while (n && !r->connection->aborted) { w = ap_bwrite(con->client, &buf[o], n); @@ -466,15 +465,15 @@ int csd = 0; struct sockaddr_in server; struct hostent server_hp; - struct hdr_entry *hdr; struct in_addr destaddr; - array_header *resp_hdrs; - BUFF *f, *cache; + table *resp_hdrs; + BUFF *f; BUFF *data = NULL; pool *p = r->pool; int one = 1; const long int zero = 0L; NET_SIZE_T clen; + struct tbl_do_args tdo; void *sconf = r->server->module_config; proxy_server_conf *conf = @@ -1002,22 +1001,21 @@ r->status = 200; r->status_line = "200 OK"; - resp_hdrs = ap_make_array(p, 2, sizeof(struct hdr_entry)); + resp_hdrs = ap_make_table(p, 2); c->hdrs = resp_hdrs; if (parms[0] == 'd') - ap_proxy_add_header(resp_hdrs, "Content-Type", "text/html", HDR_REP); + ap_table_set(resp_hdrs, "Content-Type", "text/html"); else { if (r->content_type != NULL) { - ap_proxy_add_header(resp_hdrs, "Content-Type", r->content_type, - HDR_REP); + ap_table_set(resp_hdrs, "Content-Type", r->content_type); Explain1("FTP: Content-Type set to %s", r->content_type); } else { - ap_proxy_add_header(resp_hdrs, "Content-Type", "text/plain", HDR_REP); + ap_table_set(resp_hdrs, "Content-Type", "text/plain"); } if (parms[0] != 'a' && size != NULL) { - ap_proxy_add_header(resp_hdrs, "Content-Length", size, HDR_REP); + ap_table_set(resp_hdrs, "Content-Length", size); Explain1("FTP: Content-Length set to %s", size); } } @@ -1037,10 +1035,6 @@ return i; } - cache = c->fp; - - c->hdrs = resp_hdrs; - if (!pasvmode) { /* wait for connection */ ap_hard_timeout("proxy ftp data connect", r); clen = sizeof(struct sockaddr_in); @@ -1053,7 +1047,8 @@ ap_pclosesocket(p, dsock); ap_bclose(f); ap_kill_timeout(r); - ap_proxy_cache_error(c); + if (c != NULL) + c = ap_proxy_cache_error(c); return HTTP_BAD_GATEWAY; } ap_note_cleanups_for_socket(p, csd); @@ -1075,31 +1070,19 @@ /* write status line */ if (!r->assbackwards) ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL); - if (cache != NULL) - if (ap_bvputs(cache, "HTTP/1.0 ", r->status_line, CRLF, - NULL) == -1) - cache = ap_proxy_cache_error(c); + if (c != NULL && c->fp != NULL && + ap_bvputs(c->fp, "HTTP/1.0 ", r->status_line, CRLF, NULL) == -1) + c = ap_proxy_cache_error(c); /* send headers */ - len = resp_hdrs->nelts; - hdr = (struct hdr_entry *) resp_hdrs->elts; - for (i = 0; i < len; i++) { - if (hdr[i].field == NULL || hdr[i].value == NULL || - hdr[i].value[0] == '\0') - continue; - if (!r->assbackwards) - ap_rvputs(r, hdr[i].field, ": ", hdr[i].value, CRLF, NULL); - if (cache != NULL) - if (ap_bvputs(cache, hdr[i].field, ": ", hdr[i].value, CRLF, - NULL) == -1) - cache = ap_proxy_cache_error(c); - } + tdo.req = r; + tdo.cache = c; + ap_table_do(ap_proxy_send_hdr_line, &tdo, resp_hdrs, NULL); if (!r->assbackwards) ap_rputs(CRLF, r); - if (cache != NULL) - if (ap_bputs(CRLF, cache) == -1) - cache = ap_proxy_cache_error(c); + if (c != NULL && c->fp != NULL && ap_bputs(CRLF, c->fp) == -1) + c = ap_proxy_cache_error(c); ap_bsetopt(r->connection->client, BO_BYTECT, &zero); r->sent_bodyct = 1; @@ -1107,15 +1090,16 @@ if (!r->header_only) { if (parms[0] != 'd') { /* we need to set this for ap_proxy_send_fb()... */ - c->cache_completion = 0; - ap_proxy_send_fb(data, r, cache, c); + if (c != NULL) + c->cache_completion = 0; + ap_proxy_send_fb(data, r, c); } else - send_dir(data, r, cache, c, url); + send_dir(data, r, c->fp, c, url); if (rc == 125 || rc == 150) rc = ftp_getrc(f); if (rc != 226 && rc != 250) - ap_proxy_cache_error(c); + c = ap_proxy_cache_error(c); } else { /* abort the transfer */ diff -u /usr/src/apache-1.3/src/modules/proxy/proxy_http.c apache-1.3/src/modules/proxy/proxy_http.c --- /usr/src/apache-1.3/src/modules/proxy/proxy_http.c Thu Jul 9 22:00:26 1998 +++ apache-1.3/src/modules/proxy/proxy_http.c Wed Jul 22 22:03:29 1998 @@ -172,19 +172,21 @@ char *strp2; const char *err, *desthost; int i, j, sock, len, backasswards; - array_header *reqhdrs_arr, *resp_hdrs; + array_header *reqhdrs_arr; + table *resp_hdrs; table_entry *reqhdrs; struct sockaddr_in server; struct in_addr destaddr; struct hostent server_hp; - BUFF *f, *cache; - struct hdr_entry *hdr; + BUFF *f; char buffer[HUGE_STRING_LEN]; pool *p = r->pool; const long int zero = 0L; int destport = 0; char *destportstr = NULL; const char *urlptr = NULL; + const char *datestr; + struct tbl_do_args tdo; void *sconf = r->server->module_config; proxy_server_conf *conf = @@ -313,7 +315,7 @@ if (reqhdrs[i].key == NULL || reqhdrs[i].val == NULL /* Clear out headers not to send */ || !strcasecmp(reqhdrs[i].key, "Host") /* Already sent */ - ||!strcasecmp(reqhdrs[i].key, "Proxy-Authorization")) + || !strcasecmp(reqhdrs[i].key, "Proxy-Authorization")) continue; ap_bvputs(f, reqhdrs[i].key, ": ", reqhdrs[i].val, CRLF, NULL); } @@ -322,7 +324,7 @@ /* send the request data, if any. N.B. should we trap SIGPIPE ? */ if (ap_should_client_block(r)) { - while ((i = ap_get_client_block(r, buffer, HUGE_STRING_LEN)) > 0) + while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) ap_bwrite(f, buffer, i); } ap_bflush(f); @@ -330,7 +332,7 @@ ap_hard_timeout("proxy receive", r); - len = ap_bgets(buffer, HUGE_STRING_LEN - 1, f); + len = ap_bgets(buffer, sizeof buffer - 1, f); if (len == -1 || len == 0) { ap_bclose(f); ap_kill_timeout(r); @@ -368,7 +370,7 @@ r->status_line = "200 OK"; /* no headers */ - resp_hdrs = ap_make_array(p, 2, sizeof(struct hdr_entry)); + resp_hdrs = ap_make_table(p, 20); } c->hdrs = resp_hdrs; @@ -379,20 +381,17 @@ * HTTP/1.0 requires us to accept 3 types of dates, but only generate * one type */ - - hdr = (struct hdr_entry *) resp_hdrs->elts; - for (i = 0; i < resp_hdrs->nelts; i++) { - if (hdr[i].value[0] == '\0') - continue; - strp = hdr[i].field; - if (strcasecmp(strp, "Date") == 0 || - strcasecmp(strp, "Last-Modified") == 0 || - strcasecmp(strp, "Expires") == 0) - hdr[i].value = ap_proxy_date_canon(p, hdr[i].value); - if (strcasecmp(strp, "Location") == 0 || - strcasecmp(strp, "URI") == 0) - hdr[i].value = proxy_location_reverse_map(r, hdr[i].value); - } + if ((datestr = ap_table_get(resp_hdrs, "Date")) != NULL) + ap_table_set(resp_hdrs, "Date", ap_proxy_date_canon(p, datestr)); + if ((datestr = ap_table_get(resp_hdrs, "Last-Modified")) != NULL) + ap_table_set(resp_hdrs, "Last-Modified", ap_proxy_date_canon(p, datestr)); + if ((datestr = ap_table_get(resp_hdrs, "Expires")) != NULL) + ap_table_set(resp_hdrs, "Expires", ap_proxy_date_canon(p, datestr)); + + if ((datestr = ap_table_get(resp_hdrs, "Location")) != NULL) + ap_table_set(resp_hdrs, "Location", proxy_location_reverse_map(r, datestr)); + if ((datestr = ap_table_get(resp_hdrs, "URI")) != NULL) + ap_table_set(resp_hdrs, "URI", proxy_location_reverse_map(r, datestr)); /* check if NoCache directive on this host */ for (i = 0; i < conf->nocaches->nelts; i++) { @@ -407,46 +406,32 @@ return i; } - cache = c->fp; - ap_hard_timeout("proxy receive", r); /* write status line */ if (!r->assbackwards) ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL); - if (cache != NULL) - if (ap_bvputs(cache, "HTTP/1.0 ", r->status_line, CRLF, NULL) == -1) - cache = ap_proxy_cache_error(c); + if (c != NULL && c->fp != NULL && + ap_bvputs(c->fp, "HTTP/1.0 ", r->status_line, CRLF, NULL) == -1) + c = ap_proxy_cache_error(c); /* send headers */ - for (i = 0; i < resp_hdrs->nelts; i++) { - if (hdr[i].field == NULL || hdr[i].value == NULL || - hdr[i].value[0] == '\0') - continue; - if (!r->assbackwards) { - ap_rvputs(r, hdr[i].field, ": ", hdr[i].value, CRLF, NULL); - ap_table_set(r->headers_out, hdr[i].field, hdr[i].value); - } - if (cache != NULL) - if (ap_bvputs(cache, hdr[i].field, ": ", hdr[i].value, CRLF, - NULL) == -1) - cache = ap_proxy_cache_error(c); - } + tdo.req = r; + tdo.cache = c; + ap_table_do(ap_proxy_send_hdr_line, &tdo, resp_hdrs, NULL); if (!r->assbackwards) ap_rputs(CRLF, r); - if (cache != NULL) - if (ap_bputs(CRLF, cache) == -1) - cache = ap_proxy_cache_error(c); + if (c != NULL && c->fp != NULL && ap_bputs(CRLF, c->fp) == -1) + c = ap_proxy_cache_error(c); ap_bsetopt(r->connection->client, BO_BYTECT, &zero); r->sent_bodyct = 1; /* Is it an HTTP/0.9 respose? If so, send the extra data */ if (backasswards) { ap_bwrite(r->connection->client, buffer, len); - if (cache != NULL) - if (ap_bwrite(f, buffer, len) != len) - cache = ap_proxy_cache_error(c); + if (c != NULL && c->fp != NULL && ap_bwrite(c->fp, buffer, len) != len) + c = ap_proxy_cache_error(c); } ap_kill_timeout(r); @@ -464,7 +449,7 @@ if (!r->header_only) { /* we need to set this for ap_proxy_send_fb()... */ c->cache_completion = conf->cache.cache_completion; - ap_proxy_send_fb(f, r, cache, c); + ap_proxy_send_fb(f, r, c); } ap_proxy_cache_tidy(c); diff -u /usr/src/apache-1.3/src/modules/proxy/proxy_util.c apache-1.3/src/modules/proxy/proxy_util.c --- /usr/src/apache-1.3/src/modules/proxy/proxy_util.c Thu Jul 9 22:00:26 1998 +++ apache-1.3/src/modules/proxy/proxy_util.c Wed Jul 22 22:26:54 1998 @@ -359,89 +359,116 @@ return q; } + +/* NOTE: This routine is taken from http_protocol::getline() + * because the old code found in the proxy module was too + * difficult to understand and maintain. + */ +/* Get a line of protocol input, including any continuation lines + * caused by MIME folding (or broken clients) if fold != 0, and place it + * in the buffer s, of size n bytes, without the ending newline. + * + * Returns -1 on error, or the length of s. + * + * Note: Because bgets uses 1 char for newline and 1 char for NUL, + * the most we can get is (n - 2) actual characters if it + * was ended by a newline, or (n - 1) characters if the line + * length exceeded (n - 1). So, if the result == (n - 1), + * then the actual input line exceeded the buffer length, + * and it would be a good idea for the caller to puke 400 or 414. + */ +static int proxy_getline(char *s, int n, BUFF *in, int fold) +{ + char *pos, next; + int retval; + int total = 0; + + pos = s; + + do { + retval = ap_bgets(pos, n, in); /* retval == -1 if error, 0 if EOF */ + + if (retval <= 0) + return ((retval < 0) && (total == 0)) ? -1 : total; + + /* retval is the number of characters read, not including NUL */ + + n -= retval; /* Keep track of how much of s is full */ + pos += (retval - 1); /* and where s ends */ + total += retval; /* and how long s has become */ + + if (*pos == '\n') { /* Did we get a full line of input? */ + *pos = '\0'; + --total; + ++n; + } + else + return total; /* if not, input line exceeded buffer size */ + + /* Continue appending if line folding is desired and + * the last line was not empty and we have room in the buffer and + * the next line begins with a continuation character. + */ + } while (fold && (retval != 1) && (n > 1) + && (ap_blookc(&next, in) == 1) + && ((next == ' ') || (next == '\t'))); + + return total; +} + + /* * Reads headers from a buffer and returns an array of headers. * Returns NULL on file error + * This routine tries to deal with too long lines and continuation lines. */ -array_header * - ap_proxy_read_headers(pool *p, char *buffer, int size, BUFF *f) +table *ap_proxy_read_headers(pool *p, char *buffer, int size, BUFF *f) { - int gotcr, len, i, j; - array_header *resp_hdrs; - struct hdr_entry *hdr; - char *strp; - const char *strcp; - - resp_hdrs = ap_make_array(p, 10, sizeof(struct hdr_entry)); - hdr = NULL; - - gotcr = 1; - for (;;) { - len = ap_bgets(buffer, size, f); - if (len == -1) + table *resp_hdrs; + int len; + char *value, *end; + char field[MAX_STRING_LEN]; + + resp_hdrs = ap_make_table(p, 20); + + /* + * Read header lines until we get the empty separator line, a read error, + * the connection closes (EOF), or we timeout. + */ + while ((len = proxy_getline(buffer, size, f, 1)) > 0) { + + if (!(value = strchr(buffer, ':'))) { /* Find the colon separator */ return NULL; - if (len == 0) - break; - if (buffer[len - 1] == '\n') { - buffer[--len] = '\0'; - i = 1; } - else - i = 0; - if (!gotcr || buffer[0] == ' ' || buffer[0] == '\t') { - /* a continuation header */ - if (hdr == NULL) { - /* error!! */ - if (!i) { - i = ap_bskiplf(f); - if (i == -1) - return NULL; - } - gotcr = 1; - continue; - } - hdr->value = ap_pstrcat(p, hdr->value, buffer, NULL); - } - else if (gotcr && len == 0) - break; - else { - strp = strchr(buffer, ':'); - if (strp == NULL) { - /* error!! */ - if (!gotcr) { - i = ap_bskiplf(f); - if (i == -1) - return NULL; - } - gotcr = 1; - hdr = NULL; - continue; + *value = '\0'; + ++value; + /* XXX: RFC2068 defines only SP and HT as whitespace, this test is + * wrong... and so are many others probably. + */ + while (ap_isspace(*value)) + ++value; /* Skip to start of value */ + + /* should strip trailing whitespace as well */ + for (end = &value[strlen(value)-1]; end > value && ap_isspace(*end); --end) + *end = '\0'; + + ap_table_add(resp_hdrs, buffer, value); + + /* the header was too long; at the least we should skip extra data */ + if (len >= size - 1) { + while ((len = proxy_getline(field, MAX_STRING_LEN, f, 1)) + >= MAX_STRING_LEN - 1) { + /* soak up the extra data */ } - hdr = ap_push_array(resp_hdrs); - *(strp++) = '\0'; - hdr->field = ap_pstrdup(p, buffer); - while (*strp == ' ' || *strp == '\t') - strp++; - hdr->value = ap_pstrdup(p, strp); - gotcr = i; + if (len == 0) /* time to exit the larger loop as well */ + break; } } - - hdr = (struct hdr_entry *) resp_hdrs->elts; - for (i = 0; i < resp_hdrs->nelts; i++) { - strcp = hdr[i].value; - j = strlen(strcp); - while (j > 0 && (strcp[j - 1] == ' ' || strcp[j - 1] == '\t')) - j--; - /* Note that this is OK, coz we created the header above */ - ((char *)strcp)[j] = '\0'; - } - return resp_hdrs; } -long int ap_proxy_send_fb(BUFF *f, request_rec *r, BUFF *f2, struct cache_req *c) +long int ap_proxy_send_fb(BUFF *f, request_rec *r, struct cache_req *c) { int ok = 1; char buf[IOBUFSIZE]; @@ -457,8 +484,8 @@ #ifdef CHARSET_EBCDIC /* The cache copy is ASCII, not EBCDIC, even for text/html) */ ap_bsetflag(f, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0); - if (f2 != NULL) - ap_bsetflag(f2, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0); + if (c != NULL && c->fp != NULL) + ap_bsetflag(c->fp, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0); ap_bsetflag(con->client, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0); #endif @@ -492,10 +519,11 @@ } #endif - while (ok && f != NULL) { + while (ok) { if (alt_to) ap_hard_timeout("proxy send body", r); + /* Read block from server */ n = ap_bread(f, buf, IOBUFSIZE); if (alt_to) @@ -504,8 +532,8 @@ ap_reset_timeout(r); if (n == -1) { /* input error */ - if (f2 != NULL) - f2 = ap_proxy_cache_error(c); + if (c != NULL) + c = ap_proxy_cache_error(c); break; } if (n == 0) @@ -513,14 +541,16 @@ o = 0; total_bytes_rcv += n; - if (f2 != NULL) { - if (ap_bwrite(f2, &buf[0], n) != n) { - f2 = ap_proxy_cache_error(c); + /* Write to cache first. */ + if (c != NULL && c->fp != NULL) { + if (ap_bwrite(c->fp, &buf[0], n) != n) { + c = ap_proxy_cache_error(c); } else { c->written += n; } } + /* Write the block to the client, detect aborted transfers */ while (n && !con->aborted) { if (alt_to) ap_soft_timeout("proxy send body", r); @@ -533,7 +563,7 @@ ap_reset_timeout(r); if (w <= 0) { - if (f2 != NULL) { + if (c != NULL) { /* when a send failure occurs, we need to decide * whether to continue loading and caching the * document, or to abort the whole thing @@ -545,8 +575,8 @@ if (! ok) { ap_pclosef(c->req->pool, c->fp->fd); c->fp = NULL; - f2 = NULL; unlink(c->tempfile); + c = NULL; } } con->aborted = 1; @@ -565,83 +595,26 @@ } /* - * Read a header from the array, returning the first entry - */ -struct hdr_entry * - ap_proxy_get_header(array_header *hdrs_arr, const char *name) -{ - struct hdr_entry *hdrs; - int i; - - hdrs = (struct hdr_entry *) hdrs_arr->elts; - for (i = 0; i < hdrs_arr->nelts; i++) - if (hdrs[i].field != NULL && strcasecmp(name, hdrs[i].field) == 0) - return &hdrs[i]; - - return NULL; -} - -/* - * Add to the header reply, either concatenating, or replacing existin - * headers. It stores the pointers provided, so make sure the data - * is not subsequently overwritten - */ -struct hdr_entry * - ap_proxy_add_header(array_header *hdrs_arr, const char *field, const char *value, - int rep) -{ - int i; - struct hdr_entry *hdrs; - - hdrs = (struct hdr_entry *) hdrs_arr->elts; - if (rep) - for (i = 0; i < hdrs_arr->nelts; i++) - if (hdrs[i].field != NULL && strcasecmp(field, hdrs[i].field) == 0) { - hdrs[i].value = value; - return hdrs; - } - - hdrs = ap_push_array(hdrs_arr); - hdrs->field = field; - hdrs->value = value; - - return hdrs; -} - -void ap_proxy_del_header(array_header *hdrs_arr, const char *field) -{ - int i; - struct hdr_entry *hdrs; - - hdrs = (struct hdr_entry *) hdrs_arr->elts; - - for (i = 0; i < hdrs_arr->nelts; i++) - if (hdrs[i].field != NULL && strcasecmp(field, hdrs[i].field) == 0) - hdrs[i].value = NULL; -} - -/* * Sends response line and headers. Uses the client fd and the * headers_out array from the passed request_rec to talk to the client * and to properly set the headers it sends for things such as logging. * * A timeout should be set before calling this routine. */ -void ap_proxy_send_headers(request_rec *r, const char *respline, array_header *hdrs_arr) +void ap_proxy_send_headers(request_rec *r, const char *respline, table *t) { - struct hdr_entry *hdrs; int i; BUFF *fp = r->connection->client; - - hdrs = (struct hdr_entry *) hdrs_arr->elts; + table_entry *elts = (table_entry *) ap_table_elts(t)->elts; ap_bputs(respline, fp); ap_bputs(CRLF, fp); - for (i = 0; i < hdrs_arr->nelts; i++) { - if (hdrs[i].field == NULL) - continue; - ap_bvputs(fp, hdrs[i].field, ": ", hdrs[i].value, CRLF, NULL); - ap_table_set(r->headers_out, hdrs[i].field, hdrs[i].value); + + for (i = 0; i < ap_table_elts(t)->nelts; ++i) { + if (elts[i].key != NULL) { + ap_bvputs(fp, elts[i].key, ": ", elts[i].val, CRLF, NULL); + ap_table_addn(r->headers_out, elts[i].key, elts[i].val); + } } ap_bputs(CRLF, fp); @@ -827,8 +800,8 @@ y[8] = '\0'; } -BUFF * - ap_proxy_cache_error(struct cache_req *c) + +struct cache_req *ap_proxy_cache_error(struct cache_req *c) { ap_log_error(APLOG_MARK, APLOG_ERR, c->req->server, "proxy: error writing to cache file %s", c->tempfile); @@ -1251,3 +1224,21 @@ return i; } + +/* This function is called by ap_table_do() for all header lines */ +/* (from proxy_http.c and proxy_ftp.c) */ +/* It is passed a table_do_args struct pointer and a MIME field and value pair */ +int ap_proxy_send_hdr_line(void *p, const char *key, const char *value) +{ + struct tbl_do_args *parm = (struct tbl_do_args *)p; + + if (key == NULL || value == NULL || value[0] == '\0') + return 1; + if (!parm->req->assbackwards) + ap_rvputs(parm->req, key, ": ", value, CRLF, NULL); + if (parm->cache != NULL && parm->cache->fp != NULL && + ap_bvputs(parm->cache->fp, key, ": ", value, CRLF, NULL) == -1) + parm->cache = ap_proxy_cache_error(parm->cache); + return 1; /* tell ap_table_do() to continue calling us for more headers */ +} + --jI8keyz6grp/JLjh--