httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Roy Fielding <field...@hyperreal.com>
Subject cvs commit: apache/src/modules/proxy mod_proxy.c proxy_http.c
Date Mon, 25 Nov 1996 11:22:07 GMT
fielding    96/11/25 03:22:06

  Modified:    src       httpd.h http_config.h http_protocol.h
                        http_protocol.c  mod_cgi.c mod_fastcgi.c
                        util_script.c
               src/modules/proxy  mod_proxy.c proxy_http.c
  Log:
  Added ability for modules to select the policy for reading a request
  message body as part of the call to setup_client_block().  The code can
  now reject a message body, require Content-Length if there is a body,
  transparently dechunk a chunked body, or pass the chunks to the module.
  Added read_body (to remember the policy) and read_length (to keep track
  of the amount of bytes read) to the request_rec structure.
  Added code to force an end to keepalive if the client input is errored,
  since this might not be caught by a CGI script and might result in
  a hanging connection til timeout, or a double response to the remaining
  input as if it were an additional request. Fixed a bug in get_client_block
  not checking for a negative (error) result from the read routines, and
  made the corresponding changes to the calls from mod_cgi, mod_fastcgi,
  and mod_proxy.  Removed the method-dependent code from the three module
  input routines, since the question of whether or not the request message
  contains a body is solely determined by the presence of a non-zero
  Content-Length or Transfer-Encoding field.
  
  This is an interface change, so the API version has been bumped.
  
  Fixed a bug in outgoing CGI responses, due to not checking for a script
  sending Content-Length or Transfer-Encoding, that was causing keepalive
  to end in 1.1.1 and an invalid combination of Content-Length and
  Transfer-Encoding in the current version.
  
  Fixed a bug in the proxy in regards to how it was clearing the Connection
  header field and fields indicated by it.
  
  Reviewed by: Randy Terbush, Brian Behlendorf, Jim Jagielski
  
  Revision  Changes    Path
  1.63      +14 -1     apache/src/httpd.h
  
  Index: httpd.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/httpd.h,v
  retrieving revision 1.62
  retrieving revision 1.63
  diff -C3 -r1.62 -r1.63
  *** httpd.h	1996/11/23 23:18:52	1.62
  --- httpd.h	1996/11/25 11:21:58	1.63
  ***************
  *** 341,346 ****
  --- 341,357 ----
    #define LF 10
    #define CR 13
    
  + /* Possible values for request_rec.read_body (set by handling module):
  +  *    REQUEST_NO_BODY          Send 413 error if message has any body
  +  *    REQUEST_CHUNKED_ERROR    Send 411 error if body without Content-Length
  +  *    REQUEST_CHUNKED_DECHUNK  If chunked, remove the chunks for me.
  +  *    REQUEST_CHUNKED_PASS     Pass the chunks to me without removal.
  +  */
  + #define REQUEST_NO_BODY          0
  + #define REQUEST_CHUNKED_ERROR    1
  + #define REQUEST_CHUNKED_DECHUNK  2
  + #define REQUEST_CHUNKED_PASS     3
  + 
    /* Things which may vary per file-lookup WITHIN a request ---
     * e.g., state of MIME config.  Basically, the name of an object, info
     * about the object, and any other info we may ahve which may need to
  ***************
  *** 426,432 ****
      char *range;			/* The Range: header */
      long clength;			/* The "real" content length */
    
  !   long int remaining;		/* bytes left to read */
      int read_chunked;		/* reading chunked transfer-coding */
    
      /* MIME header environments, in and out.  Also, an array containing
  --- 437,445 ----
      char *range;			/* The Range: header */
      long clength;			/* The "real" content length */
    
  !   long remaining;		/* bytes left to read */
  !   long read_length;		/* bytes that have been read */
  !   int read_body;   		/* how the request body should be read */
      int read_chunked;		/* reading chunked transfer-coding */
    
      /* MIME header environments, in and out.  Also, an array containing
  
  
  
  1.22      +1 -1      apache/src/http_config.h
  
  Index: http_config.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_config.h,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -C3 -r1.21 -r1.22
  *** http_config.h	1996/11/12 05:22:03	1.21
  --- http_config.h	1996/11/25 11:21:58	1.22
  ***************
  *** 225,231 ****
     * handle it back-compatibly, or at least signal an error).
     */
    
  ! #define MODULE_MAGIC_NUMBER 19961007
    #define STANDARD_MODULE_STUFF MODULE_MAGIC_NUMBER, -1, __FILE__, NULL
    
    /* Generic accessors for other modules to get at their own module-specific
  --- 225,231 ----
     * handle it back-compatibly, or at least signal an error).
     */
    
  ! #define MODULE_MAGIC_NUMBER 19961125
    #define STANDARD_MODULE_STUFF MODULE_MAGIC_NUMBER, -1, __FILE__, NULL
    
    /* Generic accessors for other modules to get at their own module-specific
  
  
  
  1.13      +1 -1      apache/src/http_protocol.h
  
  Index: http_protocol.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_protocol.h,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -C3 -r1.12 -r1.13
  *** http_protocol.h	1996/10/20 18:03:32	1.12
  --- http_protocol.h	1996/11/25 11:21:59	1.13
  ***************
  *** 124,130 ****
    
    /* Reading a block of data from the client connection (e.g., POST arg) */
         
  ! int setup_client_block (request_rec *r);
    int should_client_block (request_rec *r);
    long get_client_block (request_rec *r, char *buffer, int bufsiz);
    
  --- 124,130 ----
    
    /* Reading a block of data from the client connection (e.g., POST arg) */
         
  ! int setup_client_block (request_rec *r, int read_policy);
    int should_client_block (request_rec *r);
    long get_client_block (request_rec *r, char *buffer, int bufsiz);
    
  
  
  
  1.77      +214 -90   apache/src/http_protocol.c
  
  Index: http_protocol.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_protocol.c,v
  retrieving revision 1.76
  retrieving revision 1.77
  diff -C3 -r1.76 -r1.77
  *** http_protocol.c	1996/11/23 20:51:45	1.76
  --- http_protocol.c	1996/11/25 11:21:59	1.77
  ***************
  *** 206,218 ****
    
    int set_keepalive(request_rec *r)
    {
  !     char *conn = table_get (r->headers_in, "Connection");
  !     char *length = table_get (r->headers_out, "Content-length");
        int ka_sent;
    
  !     if ((r->server->keep_alive > r->connection->keepalives) &&
    	(r->server->keep_alive_timeout > 0) &&
  ! 	(r->header_only || length ||
    	 ((r->proto_num >= 1001) && (r->byterange > 1 || (r->chunked =
1)))) &&
    	(!find_token(r->pool, conn, "close")) &&
    	((ka_sent = find_token(r->pool, conn, "keep-alive")) ||
  --- 206,221 ----
    
    int set_keepalive(request_rec *r)
    {
  !     char *conn   = table_get(r->headers_in,  "Connection");
  !     char *length = table_get(r->headers_out, "Content-Length");
  !     char *tenc   = table_get(r->headers_out, "Transfer-Encoding");
        int ka_sent;
    
  !     if (r->connection->keepalive == -1)  /* Did we get bad input? */
  !         r->connection->keepalive = 0;
  !     else if ((r->server->keep_alive > r->connection->keepalives) &&
    	(r->server->keep_alive_timeout > 0) &&
  ! 	(r->header_only || length || tenc ||
    	 ((r->proto_num >= 1001) && (r->byterange > 1 || (r->chunked =
1)))) &&
    	(!find_token(r->pool, conn, "close")) &&
    	((ka_sent = find_token(r->pool, conn, "keep-alive")) ||
  ***************
  *** 633,638 ****
  --- 636,644 ----
        r->per_dir_config = r->server->lookup_defaults; /* For now. */
    
        r->sent_bodyct = 0; /* bytect isn't for body */
  + 
  +     r->read_length  = 0;
  +     r->read_body    = REQUEST_NO_BODY;
        
        r->status = HTTP_OK;	/* Until further notice.
    				 * Only changed by die(), or (bletch!)
  ***************
  *** 703,708 ****
  --- 709,717 ----
        rnew->err_headers_out = make_table (rnew->pool, 5);
        rnew->notes = make_table (rnew->pool, 5);
        
  +     rnew->read_length = r->read_length;
  +     rnew->read_body   = REQUEST_NO_BODY;
  +     
        rnew->main = (request_rec *)r;
    }
    
  ***************
  *** 1056,1112 ****
    
    }
    
  ! /* Here we deal with getting input from the client. This can be in the
  !  * form of POST or PUT (other methods can be added later), and may be
  !  * transmitted in either a fixed content-length or via chunked
  !  * transfer-coding.
     *
     * Note that this is more complicated than it was in Apache 1.1 and prior
     * versions, because chunked support means that the module does less.
     *
     * The proper procedure is this:
     * 1. Call setup_client_block() near the beginning of the request
  !  *    handler. This will set up all the neccessary properties, and
  !  *    will return either OK, or an error code. If the latter,
  !  *    the module should return that error code.
     *
  !  * 2. When you are ready to possibly accept input, call should_client_block().
  !  *    This will tell the module whether or not to read input. If it is 0,
  !  *    the module should assume that the input is of a non-entity type
  !  *    (e.g. a GET request). This step also sends a 100 Continue response
  !  *    to HTTP/1.1 clients, so should not be called until the module
  !  *    is *definitely* ready to read content. (otherwise, the point of the
  !  *    100 response is defeated). Never call this function more than once.
     *
  !  * 3. Finally, call get_client_block in a loop. Pass it a buffer and its
  !  *    size. It will put data into the buffer (not neccessarily the full
  !  *    buffer, in the case of chunked inputs), and return the length of
  !  *    the input block. When it is done reading, it will return 0.
     *
     */
    
  ! int setup_client_block (request_rec *r)
    {
  !     char *tenc = table_get (r->headers_in, "Transfer-Encoding");
  !     char *lenp = table_get (r->headers_in, "Content-length");
    
  !     if ((r->method_number != M_POST) && (r->method_number != M_PUT))
  ! 	return OK;
    
        if (tenc) {
  ! 	if (strcasecmp(tenc, "chunked")) {
  ! 	    log_printf(r->server, "Unknown Transfer-Encoding %s", tenc);
  ! 	    return BAD_REQUEST;
  ! 	}
  ! 	r->read_chunked = 1;
  ! 	r->remaining = 0;
        }
  !     else {
  ! 	if (!lenp) {
  ! 	    log_reason("POST or PUT without Content-length:", r->filename, r);
  ! 	    return LENGTH_REQUIRED;
  ! 	}
  ! 	r->remaining = atol(lenp);
        }
    
        return OK;
  --- 1065,1147 ----
    
    }
    
  ! /* Here we deal with getting the request message body from the client.
  !  * Whether or not the request contains a body is signaled by the presence
  !  * of a non-zero Content-Length or by a Transfer-Encoding: chunked.
     *
     * Note that this is more complicated than it was in Apache 1.1 and prior
     * versions, because chunked support means that the module does less.
     *
     * The proper procedure is this:
  +  *
     * 1. Call setup_client_block() near the beginning of the request
  !  *    handler. This will set up all the necessary properties, and will
  !  *    return either OK, or an error code. If the latter, the module should
  !  *    return that error code. The second parameter selects the policy to
  !  *    apply if the request message indicates a body, and how a chunked
  !  *    transfer-coding should be interpreted. Choose one of
     *
  !  *    REQUEST_NO_BODY          Send 413 error if message has any body
  !  *    REQUEST_CHUNKED_ERROR    Send 411 error if body without Content-Length
  !  *    REQUEST_CHUNKED_DECHUNK  If chunked, remove the chunks for me.
  !  *    REQUEST_CHUNKED_PASS     Pass the chunks to me without removal.
     *
  !  *    In order to use the last two options, the caller MUST provide a buffer
  !  *    large enough to hold a chunk-size line, including any extensions.
     *
  +  * 2. When you are ready to read a body (if any), call should_client_block().
  +  *    This will tell the module whether or not to read input. If it is 0,
  +  *    the module should assume that there is no message body to read.
  +  *    This step also sends a 100 Continue response to HTTP/1.1 clients,
  +  *    so should not be called until the module is *definitely* ready to
  +  *    read content. (otherwise, the point of the 100 response is defeated).
  +  *    Never call this function more than once.
  +  *
  +  * 3. Finally, call get_client_block in a loop. Pass it a buffer and its size.
  +  *    It will put data into the buffer (not necessarily a full buffer), and
  +  *    return the length of the input block. When it is done reading, it will
  +  *    return 0 if EOF, or -1 if there was an error.
  +  *    If an error occurs on input, we force an end to keepalive.
     */
    
  ! int setup_client_block (request_rec *r, int read_policy)
    {
  !     char *tenc = table_get(r->headers_in, "Transfer-Encoding");
  !     char *lenp = table_get(r->headers_in, "Content-length");
    
  !     r->read_body    = read_policy;
  !     r->read_chunked = 0;
  !     r->remaining    = 0;
    
        if (tenc) {
  !         if (strcasecmp(tenc, "chunked")) {
  !             log_printf(r->server, "Unknown Transfer-Encoding %s", tenc);
  !             return HTTP_BAD_REQUEST;
  !         }
  !         if (r->read_body == REQUEST_CHUNKED_ERROR) {
  !             log_reason("chunked Transfer-Encoding forbidden", r->uri, r);
  !             return (lenp) ? HTTP_BAD_REQUEST : HTTP_LENGTH_REQUIRED;
  !         }
  ! 
  !         r->read_chunked = 1;
        }
  !     else if (lenp) {
  !         char *pos = lenp;
  ! 
  !         while (isdigit(*pos) || isspace(*pos)) ++pos;
  !         if (*pos != '\0') {
  !             log_printf(r->server, "Invalid Content-Length %s", lenp);
  !             return HTTP_BAD_REQUEST;
  !         }
  ! 
  !         r->remaining = atol(lenp);
  !     }
  ! 
  !     if ((r->read_body == REQUEST_NO_BODY) &&
  !         (r->read_chunked || (r->remaining > 0))) {
  !         log_printf(r->server, "%s with body is not allowed for %s",
  !                    r->method, r->uri);
  !         return HTTP_REQUEST_ENTITY_TOO_LARGE;
        }
    
        return OK;
  ***************
  *** 1114,1124 ****
    
    int should_client_block (request_rec *r)
    {
  !     /* The following should involve a test of whether the request message
  !      * included a Content-Length or Transfer-Encoding header field, since
  !      * methods are supposed to be extensible.  However, this'll do for now.
  !      */
  !     if (r->method_number != M_POST && r->method_number != M_PUT)
            return 0;
    
        if (r->proto_num >= 1001) {    /* sending 100 Continue interim response */
  --- 1149,1155 ----
    
    int should_client_block (request_rec *r)
    {
  !     if (!r->read_chunked && (r->remaining <= 0))
            return 0;
    
        if (r->proto_num >= 1001) {    /* sending 100 Continue interim response */
  ***************
  *** 1130,1196 ****
        return 1;
    }
    
  ! static int rd_chunk_size (BUFF *b)
    {
  !     int chunksize = 0;
  !     int c;
    
  !     while ((c = bgetc (b)) != EOF && isxdigit (c)) {
            int xvalue = 0;
    
  !         if (c >= '0' && c <= '9') xvalue = c - '0';
  !         else if (c >= 'A' && c <= 'F') xvalue = c - 'A' + 0xa;
  !         else if (c >= 'a' && c <= 'f') xvalue = c - 'a' + 0xa;
    
            chunksize = (chunksize << 4) | xvalue;
        }
    
  !     /* Skip to end of line, bypassing chunk options, if present */
  ! 
  !     while (c != '\n' && c != EOF)
  !         c = bgetc (b);
  ! 
  !     return (c == EOF) ? -1 : chunksize;
    }
    
    long get_client_block (request_rec *r, char *buffer, int bufsiz)
    {
  !     long c, len_read, len_to_read = r->remaining;
    
  !     if (!r->read_chunked) {	/* Content-length read */
  ! 	if (len_to_read > bufsiz)
  ! 	    len_to_read = bufsiz;
  ! 	len_read = bread(r->connection->client, buffer, len_to_read);
  ! 	r->remaining -= len_read;
  ! 	return len_read;
  !     }
  ! 
  !     /* Handle chunked reading */
  !     if (len_to_read == 0) {
  ! 	len_to_read = rd_chunk_size(r->connection->client);
  ! 	if (len_to_read == 0) {
  ! 	    /* Read any footers - the module may not notice them,
  ! 	     * but they're there, and so we read them */
  ! 	    get_mime_headers(r);
  ! 	    return 0;
  ! 	}
        }
  !     if (len_to_read > bufsiz) {
  ! 	r->remaining = len_to_read - bufsiz;
  ! 	len_to_read = bufsiz;
        }
  !     else
  ! 	r->remaining = 0;
        
        len_read = bread(r->connection->client, buffer, len_to_read);
  !     if (r->remaining == 0) {
  ! 	/* Read the newline at the end of the chunk
  ! 	 * (and any other garbage that might be present) */
  ! 	do c = bgetc (r->connection->client);
  ! 	while (c != '\n' && c != EOF);
        }
    
  !     return len_read;
    }
    
    long send_fd(FILE *f, request_rec *r) { return send_fd_length(f, r, -1); }
  --- 1161,1318 ----
        return 1;
    }
    
  ! static long get_chunk_size (char *b)
    {
  !     long chunksize = 0;
    
  !     while (isxdigit(*b)) {
            int xvalue = 0;
    
  !         if (*b >= '0' && *b <= '9')      xvalue = *b - '0';
  !         else if (*b >= 'A' && *b <= 'F') xvalue = *b - 'A' + 0xa;
  !         else if (*b >= 'a' && *b <= 'f') xvalue = *b - 'a' + 0xa;
    
            chunksize = (chunksize << 4) | xvalue;
  +         ++b;
        }
    
  !     return chunksize;
    }
    
  + /* get_client_block is called in a loop to get the request message body.
  +  * This is quite simple if the client includes a content-length
  +  * (the normal case), but gets messy if the body is chunked. Note that
  +  * r->remaining is used to maintain state across calls and that
  +  * r->read_length is the total number of bytes given to the caller
  +  * across all invocations.  It is messy because we have to be careful not
  +  * to read past the data provided by the client, since these reads block.
  +  * Returns 0 on End-of-body, -1 on error or premature chunk end.
  +  *
  +  * Reading the chunked encoding requires a buffer size large enough to
  +  * hold a chunk-size line, including any extensions. For now, we'll leave
  +  * that to the caller, at least until we can come up with a better solution.
  +  */
    long get_client_block (request_rec *r, char *buffer, int bufsiz)
    {
  !     int c;
  !     long len_read, len_to_read;
  !     long chunk_start = 0;
    
  !     if (!r->read_chunked) {                 /* Content-length read */
  !         len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining;
  !         len_read = bread(r->connection->client, buffer, len_to_read);
  !         if (len_read <= 0) {
  !             if (len_read < 0) r->connection->keepalive = -1;
  !             return len_read;
  !         }
  !         r->read_length += len_read;
  !         r->remaining   -= len_read;
  !         return len_read;
        }
  ! 
  !     /* Handle chunked reading
  !      * Note: we are careful to shorten the input bufsiz so that there
  !      * will always be enough space for us to add a CRLF (if necessary).
  !      */
  !     if (r->read_body == REQUEST_CHUNKED_PASS)
  !         bufsiz -= 2;
  !     if (bufsiz <= 0)
  !         return -1;             /* Cannot read chunked with a small buffer */
  ! 
  !     if (r->remaining == 0) {         /* Start of new chunk */
  ! 
  !         chunk_start = getline(buffer, bufsiz, r->connection->client, 0);
  !         if ((chunk_start <= 0) || (chunk_start >= (bufsiz - 1))
  !                                || !isxdigit(*buffer)) {
  !             r->connection->keepalive = -1;
  !             return -1;
  !         }
  ! 
  !         len_to_read = get_chunk_size(buffer);
  ! 
  !         if (len_to_read == 0) {      /* Last chunk indicated, get footers */
  !             if (r->read_body == REQUEST_CHUNKED_DECHUNK) {
  !                 get_mime_headers(r);
  !                 sprintf(buffer, "%ld", r->read_length);
  !                 table_unset(r->headers_in, "Transfer-Encoding");
  !                 table_set(r->headers_in, "Content-Length", buffer);
  !                 return 0;
  !             }
  !             r->remaining = -1;       /* Indicate footers in-progress */
  !         }
  !         else {
  !             r->remaining = len_to_read;
  !         }
  !         if (r->read_body == REQUEST_CHUNKED_PASS) {
  !             buffer[chunk_start++] = CR;  /* Restore chunk-size line end  */
  !             buffer[chunk_start++] = LF;
  !             buffer += chunk_start;       /* and pass line on to caller   */
  !             bufsiz -= chunk_start;
  !         }
        }
  !                                      /* When REQUEST_CHUNKED_PASS, we are */
  !     if (r->remaining == -1) {        /* reading footers until empty line  */
  !         len_read = chunk_start;
  ! 
  !         while ((bufsiz > 1) && ((len_read =
  !                 getline(buffer, bufsiz, r->connection->client, 1)) > 0)) {
  ! 
  !             if (len_read != (bufsiz - 1)) {
  !                 buffer[len_read++] = CR;  /* Restore footer line end  */
  !                 buffer[len_read++] = LF;
  !             }
  !             chunk_start += len_read;
  !             buffer      += len_read;
  !             bufsiz      -= len_read;
  !         }
  !         if (len_read < 0) {
  !             r->connection->keepalive = -1;
  !             return -1;
  !         }
  ! 
  !         if (len_read == 0) {         /* Indicates an empty line */
  !             buffer[0] = CR;
  !             buffer[1] = LF;
  !             chunk_start += 2;
  !             r->remaining = -2;
  !         }
  !         r->read_length += chunk_start;
  !         return chunk_start;
  !     }
  !                                      /* When REQUEST_CHUNKED_PASS, we     */
  !     if (r->remaining == -2) {        /* finished footers when last called */
  !         r->remaining = 0;            /*     so now we must signal EOF     */
  !         return 0;
  !     }
  ! 
  !     /* Otherwise, we are in the midst of reading a chunk of data */
  ! 
  !     len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining;
        
        len_read = bread(r->connection->client, buffer, len_to_read);
  !     if (len_read <= 0) {
  !         r->connection->keepalive = -1;
  !         return -1;
        }
    
  !     r->remaining -= len_read;
  ! 
  !     if (r->remaining == 0) {         /* End of chunk, get trailing CRLF */
  !         if ((c = bgetc(r->connection->client)) == CR) {
  !            c = bgetc(r->connection->client);
  !         }
  !         if (c != LF) {
  !             r->connection->keepalive = -1;
  !             return -1;
  !         }
  !         if (r->read_body == REQUEST_CHUNKED_PASS) {
  !             buffer[len_read++] = CR;
  !             buffer[len_read++] = LF;
  !         }
  !     }
  !     r->read_length += (chunk_start + len_read);
  ! 
  !     return (chunk_start + len_read);
    }
    
    long send_fd(FILE *f, request_rec *r) { return send_fd_length(f, r, -1); }
  ***************
  *** 1469,1478 ****
    	           "Please remove all references to this resource.\n", NULL);
      	    break;
    	case HTTP_REQUEST_ENTITY_TOO_LARGE:
  ! 	    bputs("The supplied request data exceeds the capacity\n", fd);
  ! 	    bputs("limit placed on this resource. The request data \n", fd);
  ! 	    bputs("must be reduced before the request can proceed.\n", fd);
  !   	    break;
    	case HTTP_REQUEST_URI_TOO_LARGE:
    	    bputs("The requested URL's length exceeds the capacity\n", fd);
    	    bputs("limit for this server.\n", fd);
  --- 1591,1602 ----
    	           "Please remove all references to this resource.\n", NULL);
      	    break;
    	case HTTP_REQUEST_ENTITY_TOO_LARGE:
  ! 	    bvputs(fd, "The requested resource<BR>",
  ! 	           escape_html(r->pool, r->uri), "<BR>\n",
  ! 	           "does not allow request data with ", r->method,
  ! 	           " requests, or the amount of data provided in\n",
  ! 	           "the request exceeds the capacity limit.\n", NULL);
  ! 	    break;
    	case HTTP_REQUEST_URI_TOO_LARGE:
    	    bputs("The requested URL's length exceeds the capacity\n", fd);
    	    bputs("limit for this server.\n", fd);
  
  
  
  1.21      +9 -4      apache/src/mod_cgi.c
  
  Index: mod_cgi.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/mod_cgi.c,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -C3 -r1.20 -r1.21
  *** mod_cgi.c	1996/10/20 18:03:34	1.20
  --- mod_cgi.c	1996/11/25 11:22:00	1.21
  ***************
  *** 381,387 ****
    	return log_scripterror(r, conf, FORBIDDEN,
    			       "file permissions deny server execution");
        
  !     if ((retval = setup_client_block(r)))
    	return retval;
    
        add_common_vars (r);
  --- 381,387 ----
    	return log_scripterror(r, conf, FORBIDDEN,
    			       "file permissions deny server execution");
        
  !     if ((retval = setup_client_block(r, REQUEST_CHUNKED_ERROR)))
    	return retval;
    
        add_common_vars (r);
  ***************
  *** 422,437 ****
            hard_timeout ("copy script args", r);
            handler = signal (SIGPIPE, SIG_IGN);
        
  ! 	while ((len_read = get_client_block (r, argsbuffer, HUGE_STRING_LEN)))
    	{
  - 	    if (fwrite (argsbuffer, 1, len_read, script_out) == 0)
  - 		break;
    	    if (conf->logname) {
    		if ((dbpos + len_read) > conf->bufbytes)
    		    dbsize = conf->bufbytes - dbpos;
    		else dbsize = len_read;
    		strncpy(dbuf + dbpos, argsbuffer, dbsize);
    		dbpos += dbsize;
    	    }
    	}
    
  --- 422,442 ----
            hard_timeout ("copy script args", r);
            handler = signal (SIGPIPE, SIG_IGN);
        
  ! 	while ((len_read =
  !                 get_client_block(r, argsbuffer, HUGE_STRING_LEN)) > 0)
    	{
    	    if (conf->logname) {
    		if ((dbpos + len_read) > conf->bufbytes)
    		    dbsize = conf->bufbytes - dbpos;
    		else dbsize = len_read;
    		strncpy(dbuf + dbpos, argsbuffer, dbsize);
    		dbpos += dbsize;
  + 	    }
  + 	    if (fwrite(argsbuffer, 1, len_read, script_out) < len_read) {
  + 		/* silly script stopped reading, soak up remaining message */
  + 	        while (get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0)
  + 	            ; /* dump it */
  + 	        break;
    	    }
    	}
    
  
  
  
  1.3       +1 -1      apache/src/mod_fastcgi.c
  
  Index: mod_fastcgi.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/mod_fastcgi.c,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -C3 -r1.2 -r1.3
  *** mod_fastcgi.c	1996/10/22 20:38:11	1.2
  --- mod_fastcgi.c	1996/11/25 11:22:00	1.3
  ***************
  *** 3673,3679 ****
                    reqPtr->filename, reqPtr);
            return NOT_FOUND;
        }
  !     status = setup_client_block(reqPtr);
        if(status != OK) {
            return status;
        }
  --- 3673,3679 ----
                    reqPtr->filename, reqPtr);
            return NOT_FOUND;
        }
  !     status = setup_client_block(reqPtr, REQUEST_CHUNKED_ERROR);
        if(status != OK) {
            return status;
        }
  
  
  
  1.27      +6 -0      apache/src/util_script.c
  
  Index: util_script.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/util_script.c,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -C3 -r1.26 -r1.27
  *** util_script.c	1996/11/12 06:02:54	1.26
  --- util_script.c	1996/11/25 11:22:01	1.27
  ***************
  *** 327,332 ****
  --- 327,338 ----
            else if(!strcasecmp(w,"Location")) {
    	    table_set (r->headers_out, w, l);
            }   
  +         else if(!strcasecmp(w,"Content-Length")) {
  + 	    table_set (r->headers_out, w, l);
  +         }   
  +         else if(!strcasecmp(w,"Transfer-Encoding")) {
  + 	    table_set (r->headers_out, w, l);
  +         }   
    
    /* The HTTP specification says that it is legal to merge duplicate
     * headers into one.  Some browsers that support Cookies don't like
  
  
  
  1.6       +1 -1      apache/src/modules/proxy/mod_proxy.c
  
  Index: mod_proxy.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/modules/proxy/mod_proxy.c,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -C3 -r1.5 -r1.6
  *** mod_proxy.c	1996/10/20 23:58:59	1.5
  --- mod_proxy.c	1996/11/25 11:22:05	1.6
  ***************
  *** 196,202 ****
    
        if (strncmp(r->filename, "proxy:", 6) != 0) return DECLINED;
    
  !     if ((rc = setup_client_block(r)))
    	return rc;
    
        url = r->filename + 6;
  --- 196,202 ----
    
        if (strncmp(r->filename, "proxy:", 6) != 0) return DECLINED;
    
  !     if ((rc = setup_client_block(r, REQUEST_CHUNKED_ERROR)))
    	return rc;
    
        url = r->filename + 6;
  
  
  
  1.6       +23 -2     apache/src/modules/proxy/proxy_http.c
  
  Index: proxy_http.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/modules/proxy/proxy_http.c,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -C3 -r1.5 -r1.6
  *** proxy_http.c	1996/10/27 18:29:57	1.5
  --- proxy_http.c	1996/11/25 11:22:05	1.6
  ***************
  *** 108,113 ****
  --- 108,133 ----
        return OK;
    }
    
  + /* Clear all connection-based headers from the incoming headers table */
  + static void clear_connection (table *headers)
  + {
  +     char *name;
  +     char *next = table_get(headers, "Connection");
  + 
  +     if (!next) return;
  + 
  +     while (*next) {
  +         name = next;
  +         while (*next && !isspace(*next) && (*next != ',')) ++next;
  +         while (*next && (isspace(*next) || (*next == ','))) {
  +             *next = '\0';
  +             ++next;
  +         }
  +         table_unset(headers, name);
  +     }
  +     table_unset(headers, "Connection");
  + }
  + 
    /*
     * This handles http:// URLs, and other URLs using a remote proxy over http
     * If proxyhost is NULL, then contact the server directly, otherwise
  ***************
  *** 193,198 ****
  --- 213,220 ----
    	else return proxyerror(r, "Could not connect to remote machine");
        }
    
  +     clear_connection(r->headers_in);   /* Strip connection-based headers */
  + 
        f = bcreate(pool, B_RDWR);
        bpushfd(f, sock, sock);
    
  ***************
  *** 204,210 ****
        for (i=0; i < reqhdrs_arr->nelts; i++)
        {
    	if (reqhdrs[i].key == NULL || reqhdrs[i].val == NULL) continue;
  - 	if (!strcasecmp(reqhdrs[i].key, "Connection")) continue;
    	bvputs(f, reqhdrs[i].key, ": ", reqhdrs[i].val, "\015\012", NULL);
        }
    
  --- 226,231 ----
  ***************
  *** 213,219 ****
    
        if (should_client_block(r))
        {
  ! 	while ((i = get_client_block (r, buffer, HUGE_STRING_LEN)))
                bwrite(f, buffer, i);
        }
        bflush(f);
  --- 234,240 ----
    
        if (should_client_block(r))
        {
  ! 	while ((i = get_client_block(r, buffer, HUGE_STRING_LEN)) > 0)
                bwrite(f, buffer, i);
        }
        bflush(f);
  
  
  

Mime
View raw message