martin      98/08/16 13:21:30

  Modified:    src      CHANGES
               src/include ap_mmn.h
               src/modules/proxy mod_proxy.c mod_proxy.h proxy_cache.c
                        proxy_connect.c proxy_ftp.c proxy_http.c
                        proxy_util.c
  Log:
  Modify the proxy to use tables instead of array_headers for header lines.
  That simplifies some code, but changes many of the proxy-internal interfaces.
  It should also prevent the proxy from merging multiple "Set-Cookie:" headers
  into one.
  
  Revision  Changes    Path
  1.1027    +3 -0      apache-1.3/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/CHANGES,v
  retrieving revision 1.1026
  retrieving revision 1.1027
  diff -u -u -r1.1026 -r1.1027
  --- CHANGES   1998/08/15 15:02:44     1.1026
  +++ CHANGES   1998/08/16 20:21:24     1.1027
  @@ -1,5 +1,8 @@
   Changes with Apache 1.3.2
   
  +  *) Change the proxy to use tables instead of array_headers for
  +     the header lines. [Martin Kraemer]
  +
     *) Make sure the config.status file is not overridden when just
        ``configure --help'' is used. [Ralf S. Engelschall] PR#2844
   
  
  
  
  1.4       +9 -2      apache-1.3/src/include/ap_mmn.h
  
  Index: ap_mmn.h
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/include/ap_mmn.h,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -u -r1.3 -r1.4
  --- ap_mmn.h  1998/08/14 02:49:09     1.3
  +++ ap_mmn.h  1998/08/16 20:21:25     1.4
  @@ -66,6 +66,7 @@
    *
    * MODULE_MAGIC_NUMBER_MINOR
    * Minor API changes that do not cause binary compatibility problems.
  + * Should be reset to 0 when upgrading MODULE_MAGIC_NUMBER_MAJOR.
    *
    * See the MODULE_MAGIC_AT_LEAST macro below for an example.
    */
  @@ -164,12 +165,18 @@
    *                     ap_get_limit_req_body() to get its value.
    * 19980812 (1.3.2-dev)      - split off MODULE_MAGIC_NUMBER
    * 19980812.2           - add ap_overlap_tables()
  + * 19980816 (1.3.2-dev)      - change proxy to use tables for headers, change
  + *                        struct cache_req to typedef cache_req.
  + *                        Delete ap_proxy_get_header(), 
ap_proxy_add_header(),
  + *                        ap_proxy_del_header(). Change interface of 
  + *                        ap_proxy_send_fb() and ap_proxy_cache_error(). 
  + *                        Add ap_proxy_send_hdr_line() and ap_proxy_bputs2().
    */
   
   #ifndef MODULE_MAGIC_NUMBER_MAJOR
  -#define MODULE_MAGIC_NUMBER_MAJOR 19980812
  +#define MODULE_MAGIC_NUMBER_MAJOR 19980816
   #endif
  -#define MODULE_MAGIC_NUMBER_MINOR 2
  +#define MODULE_MAGIC_NUMBER_MINOR 0                     /* 0...n */
   #define MODULE_MAGIC_NUMBER MODULE_MAGIC_NUMBER_MAJOR        /* backward 
compat */
   
   /* Useful for testing for features. */
  
  
  
  1.59      +1 -1      apache-1.3/src/modules/proxy/mod_proxy.c
  
  Index: mod_proxy.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/modules/proxy/mod_proxy.c,v
  retrieving revision 1.58
  retrieving revision 1.59
  diff -u -u -r1.58 -r1.59
  --- mod_proxy.c       1998/08/06 17:30:40     1.58
  +++ mod_proxy.c       1998/08/16 20:21:26     1.59
  @@ -292,7 +292,7 @@
       array_header *proxies = conf->proxies;
       struct proxy_remote *ents = (struct proxy_remote *) proxies->elts;
       int i, rc;
  -    struct cache_req *cr;
  +    cache_req *cr;
       int direct_connect = 0;
       const char *maxfwd_str;
   
  
  
  
  1.38      +26 -17    apache-1.3/src/modules/proxy/mod_proxy.h
  
  Index: mod_proxy.h
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/modules/proxy/mod_proxy.h,v
  retrieving revision 1.37
  retrieving revision 1.38
  diff -u -u -r1.37 -r1.38
  --- mod_proxy.h       1998/07/09 19:45:56     1.37
  +++ mod_proxy.h       1998/08/16 20:21:27     1.38
  @@ -55,6 +55,9 @@
    *
    */
   
  +#ifndef MOD_PROXY_H
  +#define MOD_PROXY_H 
  +
   /*
    * Main include file for the Apache proxy
    */
  @@ -218,7 +221,7 @@
   };
   
   /* caching information about a request */
  -struct cache_req {
  +typedef struct {
       request_rec *req;                /* the request */
       char *url;                       /* the URL requested */
       char *filename;          /* name of the cache file, or NULL if no cache 
*/
  @@ -237,35 +240,41 @@
       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 */
  +} cache_req;
  +
  +/* Additional information passed to the function called by ap_table_do() */
  +struct tbl_do_args {
  +    request_rec *req;
  +    cache_req *cache;
   };
   
   /* Function prototypes */
   
   /* proxy_cache.c */
   
  -void ap_proxy_cache_tidy(struct cache_req *c);
  +void ap_proxy_cache_tidy(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,
  +                   cache_req **cr);
  +int ap_proxy_cache_update(cache_req *c, table *resp_hdrs,
                       const int is_HTTP1, int nocache);
   void ap_proxy_garbage_coll(request_rec *r);
   
   /* proxy_connect.c */
   
  -int ap_proxy_connect_handler(request_rec *r, struct cache_req *c, char *url,
  +int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url,
                          const char *proxyhost, int proxyport);
   
   /* proxy_ftp.c */
   
   int ap_proxy_ftp_canon(request_rec *r, char *url);
  -int ap_proxy_ftp_handler(request_rec *r, struct cache_req *c, char *url);
  +int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url);
   
   /* proxy_http.c */
   
   int ap_proxy_http_canon(request_rec *r, char *url, const char *scheme,
                     int def_port);
  -int ap_proxy_http_handler(request_rec *r, struct cache_req *c, char *url,
  +int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
                       const char *proxyhost, int proxyport);
   
   /* proxy_util.c */
  @@ -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, 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);
  +cache_req *ap_proxy_cache_error(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,8 @@
   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);
  +unsigned ap_proxy_bputs2(const char *data, BUFF *client, cache_req *cache);
  +
  +#endif /*MOD_PROXY_H*/
  
  
  
  1.50      +50 -56    apache-1.3/src/modules/proxy/proxy_cache.c
  
  Index: proxy_cache.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/modules/proxy/proxy_cache.c,v
  retrieving revision 1.49
  retrieving revision 1.50
  diff -u -u -r1.49 -r1.50
  --- proxy_cache.c     1998/08/06 17:30:41     1.49
  +++ proxy_cache.c     1998/08/16 20:21:27     1.50
  @@ -535,7 +535,7 @@
    *         0 on failure (bad file or wrong URL)
    *        -1 on UNIX error
    */
  -static int rdcache(pool *p, BUFF *cachefp, struct cache_req *c)
  +static int rdcache(pool *p, BUFF *cachefp, cache_req *c)
   {
       char urlbuff[1034], *strp;
       int len;
  @@ -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) {
  +         ap_table_set(c->hdrs, "Content-Length",
  +                      ap_psprintf(p, "%lu", (unsigned long)c->len));
        }
       }
       return 1;
  @@ -617,11 +614,11 @@
    *            last modified date to request
    */
   int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf,
  -                   struct cache_req **cr)
  +                   cache_req **cr)
   {
       char hashfile[66];
       const char *imstr, *pragma, *auth;
  -    struct cache_req *c;
  +    cache_req *c;
       time_t now;
       BUFF *cachefp;
       int cfd, i;
  @@ -630,7 +627,7 @@
       proxy_server_conf *pconf =
       (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
   
  -    c = ap_pcalloc(r->pool, sizeof(struct cache_req));
  +    c = ap_pcalloc(r->pool, sizeof(cache_req));
       *cr = c;
       c->req = r;
       c->url = ap_pstrdup(r->pool, url);
  @@ -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);
  @@ -708,16 +705,12 @@
   /* has the cached file changed since this request? */
            if (c->date == BAD_DATE || c->date > c->ims) {
   /* No, but these header values may have changed, so we send them with the
  - * 304 response
  + * 304 HTTP_NOT_MODIFIED 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(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;
        }
       }
  @@ -826,16 +816,18 @@
   /*
    * what responses should we not cache?
    * Unknown status responses and those known to be uncacheable
  - * 304 response when we have no valid cache file, or
  - * 200 response from HTTP/1.0 and up without a Last-Modified header, or
  + * 304 HTTP_NOT_MODIFIED response when we have no valid cache file, or
  + * 200 HTTP_OK response from HTTP/1.0 and up without a Last-Modified header, 
or
    * HEAD requests, or
    * requests with an Authorization header, or
    * protocol requests nocache (e.g. ftp with user/password)
    */
  -    if ((r->status != 200 && r->status != 301 && r->status != 304) ||
  +/* @@@ XXX FIXME: is the test "r->status != HTTP_MOVED_PERMANENTLY" corerct?
  + * or shouldn't it be "is_HTTP_REDIRECT(r->status)" ? -MnKr */
  +    if ((r->status != HTTP_OK && r->status != HTTP_MOVED_PERMANENTLY && 
r->status != HTTP_NOT_MODIFIED) ||
        (expire != NULL && expc == BAD_DATE) ||
  -     (r->status == 304 && c->fp == NULL) ||
  -     (r->status == 200 && lmods == NULL && is_HTTP1) ||
  +     (r->status == HTTP_NOT_MODIFIED && (c == NULL || c->fp == NULL)) ||
  +     (r->status == HTTP_OK && lmods == NULL && is_HTTP1) ||
        r->header_only ||
        ap_table_get(r->headers_in, "Authorization") != NULL ||
        nocache) {
  @@ -855,9 +847,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;
   
  @@ -868,8 +860,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");
       }
   
  @@ -878,7 +870,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 */
  @@ -889,9 +881,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
  @@ -915,11 +907,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] = ' ';
  @@ -934,7 +926,7 @@
       buff[45] = '\0';
   
   /* if file not modified */
  -    if (r->status == 304) {
  +    if (r->status == HTTP_NOT_MODIFIED) {
        if (c->ims != BAD_DATE && lmod != BAD_DATE && lmod <= c->ims) {
   /* set any changed headers somehow */
   /* update dates and version, but not content-length */
  @@ -967,7 +959,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) {
  @@ -1030,13 +1022,15 @@
       return DECLINED;
   }
   
  -void ap_proxy_cache_tidy(struct cache_req *c)
  +void ap_proxy_cache_tidy(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);
  
  
  
  1.31      +1 -1      apache-1.3/src/modules/proxy/proxy_connect.c
  
  Index: proxy_connect.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/modules/proxy/proxy_connect.c,v
  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -u -r1.30 -r1.31
  --- proxy_connect.c   1998/08/06 17:30:42     1.30
  +++ proxy_connect.c   1998/08/16 20:21:27     1.31
  @@ -97,7 +97,7 @@
    * FIXME: no check for r->assbackwards, whatever that is.
    */
   
  -int ap_proxy_connect_handler(request_rec *r, struct cache_req *c, char *url,
  +int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url,
                          const char *proxyhost, int proxyport)
   {
       struct sockaddr_in server;
  
  
  
  1.66      +38 -75    apache-1.3/src/modules/proxy/proxy_ftp.c
  
  Index: proxy_ftp.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/modules/proxy/proxy_ftp.c,v
  retrieving revision 1.65
  retrieving revision 1.66
  diff -u -u -r1.65 -r1.66
  --- proxy_ftp.c       1998/08/06 17:30:43     1.65
  +++ proxy_ftp.c       1998/08/16 20:21:28     1.66
  @@ -263,7 +263,7 @@
       return status;
   }
   
  -static long int send_dir(BUFF *f, request_rec *r, BUFF *f2, struct cache_req 
*c, char *url)
  +static long int send_dir(BUFF *f, request_rec *r, cache_req *c, char *url)
   {
       char buf[IOBUFSIZE];
       char buf2[IOBUFSIZE];
  @@ -278,7 +278,6 @@
       int hostlen;
       conn_rec *con = r->connection;
       char *dir, *path, *reldir, *site, *psite;
  -    const char *sig;
   
       tempurl = ap_pstrdup(r->pool, url);
   
  @@ -318,10 +317,7 @@
                "<BODY><H2>Directory of "
                "<A HREF=\"/\">%s</A>/",
                tempurl, psite, path, site);
  -    ap_bputs(buf, con->client);
  -    if (f2 != NULL)
  -     ap_bputs(buf, f2);
  -    total_bytes_sent += strlen(buf);
  +    total_bytes_sent += ap_proxy_bputs2(buf, con->client, c);
   
       while ((dir = strchr(dir+1, '/')) != NULL)
       {
  @@ -332,17 +328,12 @@
            ++reldir;
        /* print "path/" component */
        ap_snprintf(buf, sizeof(buf), "<A HREF=\"/%s/\">%s</A>/", path+1, 
reldir);
  -     ap_bputs(buf, con->client);
  -    if (f2 != NULL)
  -         ap_bputs(buf, f2);
  +     total_bytes_sent += ap_proxy_bputs2(buf, con->client, c);
        total_bytes_sent += strlen(buf);
        *dir = '/';
       }
       ap_snprintf(buf, sizeof(buf), "</H2>\n<HR><PRE>");
  -    ap_bputs(buf, con->client);
  -    if (f2 != NULL)
  -         ap_bputs(buf, f2);
  -    total_bytes_sent += strlen(buf);
  +    total_bytes_sent += ap_proxy_bputs2(buf, con->client, c);
   
       for (hostlen=0; url[hostlen]!='/'; ++hostlen)
        continue;
  @@ -355,8 +346,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 +407,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 && c->fp && ap_bwrite(c->fp, buf, n) != n)
  +         c = ap_proxy_cache_error(c);
   
        while (n && !r->connection->aborted) {
            w = ap_bwrite(con->client, &buf[o], n);
  @@ -429,23 +419,11 @@
            o += w;
        }
       }
  -    site = "</PRE><HR>\n";
  -    ap_bputs(site, con->client);
  -    if (f2 != NULL)
  -     ap_bputs(site, f2);
  -    total_bytes_sent += strlen(site);
  -
  -    sig = ap_psignature("", r);
  -    ap_bputs(sig, con->client);
  -    if (f2 != NULL)
  -     ap_bputs(sig, f2);
  -    total_bytes_sent += strlen(sig);
  -
  -    site = "</BODY></HTML>\n";
  -    ap_bputs(site, con->client);
  -    if (f2 != NULL)
  -     ap_bputs(site, f2);
  -    total_bytes_sent += strlen(site);
  +
  +    total_bytes_sent += ap_proxy_bputs2("</PRE><HR>\n", con->client, c);
  +    total_bytes_sent += ap_proxy_bputs2(ap_psignature("", r), con->client, 
c);
  +    total_bytes_sent += ap_proxy_bputs2("</BODY></HTML>\n", con->client, c);
  +
       ap_bflush(con->client);
   
       return total_bytes_sent;
  @@ -457,7 +435,7 @@
    * Troy Morrison <[EMAIL PROTECTED]>
    * PASV added by Chuck
    */
  -int ap_proxy_ftp_handler(request_rec *r, struct cache_req *c, char *url)
  +int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
   {
       char *host, *path, *strp, *user, *password, *parms;
       const char *err;
  @@ -466,15 +444,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 =
  @@ -999,25 +977,24 @@
       if (rc != 125 && rc != 150 && rc != 226 && rc != 250)
        return HTTP_BAD_GATEWAY;
   
  -    r->status = 200;
  +    r->status = HTTP_OK;
       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 +1014,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 +1026,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 +1049,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 +1069,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, 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 */
  
  
  
  1.57      +32 -50    apache-1.3/src/modules/proxy/proxy_http.c
  
  Index: proxy_http.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/modules/proxy/proxy_http.c,v
  retrieving revision 1.56
  retrieving revision 1.57
  diff -u -u -r1.56 -r1.57
  --- proxy_http.c      1998/08/09 17:39:25     1.56
  +++ proxy_http.c      1998/08/16 20:21:28     1.57
  @@ -165,26 +165,28 @@
    * we return DECLINED so that we can try another proxy. (Or the direct
    * route.)
    */
  -int ap_proxy_http_handler(request_rec *r, struct cache_req *c, char *url,
  +int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
                       const char *proxyhost, int proxyport)
   {
       const char *strp;
       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,21 +381,18 @@
    * HTTP/1.0 requires us to accept 3 types of dates, but only generate
    * one type
    */
  +    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));
   
  -    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);
  -    }
  -
   /* check if NoCache directive on this host */
       for (i = 0; i < conf->nocaches->nelts; i++) {
        if ((ncent[i].name != NULL && strstr(desthost, ncent[i].name) != NULL)
  @@ -407,49 +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);
  -         /* XXX: can't this be ap_table_setn? -djg */
  -         ap_table_set(r->headers_out, hdr[i].field, hdr[i].value);
  -         /* XXX: regardless, there's an O(n^2) attack here, which
  -          * could be fixed with ap_overlap_tables */
  -     }
  -     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);
   
  @@ -467,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);
  
  
  
  1.69      +152 -150  apache-1.3/src/modules/proxy/proxy_util.c
  
  Index: proxy_util.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/modules/proxy/proxy_util.c,v
  retrieving revision 1.68
  retrieving revision 1.69
  diff -u -u -r1.68 -r1.69
  --- proxy_util.c      1998/08/09 17:39:25     1.68
  +++ proxy_util.c      1998/08/16 20:21:28     1.69
  @@ -359,89 +359,118 @@
       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
  - */
  -array_header *
  -             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)
  + * This routine tries to deal with too long lines and continuation lines.
  + * @@@: XXX: FIXME: currently the headers are passed thru un-merged. 
  + * Is that okay, or should they be collapsed where possible?
  + */
  +table *ap_proxy_read_headers(pool *p, char *buffer, int size, BUFF *f)
  +{
  +    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, cache_req *c)
   {
       int  ok = 1;
       char buf[IOBUFSIZE];
  @@ -457,8 +486,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 +521,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 +534,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 +543,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 +565,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 +577,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,85 +597,28 @@
   }
   
   /*
  - * 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);
  -     /* XXX: can't this be ap_table_setn? -djg */
  -     ap_table_set(r->headers_out, hdrs[i].field, hdrs[i].value);
  -     /* XXX: another O(n^2) attack, fixed by ap_overlap_tables */
  +
  +    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);
  +         /* FIXME: @@@ This used to be ap_table_set(), but I think
  +          * ap_table_addn() is correct. MnKr */
  +         ap_table_addn(r->headers_out, elts[i].key, elts[i].val);
  +     }
       }
   
       ap_bputs(CRLF, fp);
  @@ -829,8 +804,8 @@
       y[8] = '\0';
   }
   
  -BUFF *
  -     ap_proxy_cache_error(struct cache_req *c)
  +
  +cache_req *ap_proxy_cache_error(cache_req *c)
   {
       ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
                 "proxy: error writing to cache file %s", c->tempfile);
  @@ -1253,3 +1228,30 @@
   
       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 
*/
  +}
  +
  +/* send a text line to one or two BUFF's; return line length */
  +unsigned ap_proxy_bputs2(const char *data, BUFF *client, cache_req *cache)
  +{
  +    unsigned len = ap_bputs(data, client);
  +    if (cache != NULL && cache->fp != NULL)
  +     ap_bputs(data, cache->fp);
  +    return len;
  +}
  +
  
  
  

Reply via email to