http_protocol.c revision 777a2b42697cb8cb94ac4e73774862f879259c45
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann/* ====================================================================
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * The Apache Software License, Version 1.1
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * Copyright (c) 2000 The Apache Software Foundation. All rights
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * Redistribution and use in source and binary forms, with or without
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * modification, are permitted provided that the following conditions
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * 1. Redistributions of source code must retain the above copyright
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * notice, this list of conditions and the following disclaimer.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * 2. Redistributions in binary form must reproduce the above copyright
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * notice, this list of conditions and the following disclaimer in
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * the documentation and/or other materials provided with the
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * distribution.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * 3. The end-user documentation included with the redistribution,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * if any, must include the following acknowledgment:
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * "This product includes software developed by the
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * Apache Software Foundation (http://www.apache.org/)."
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * Alternately, this acknowledgment may appear in the software itself,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * if and wherever such third-party acknowledgments normally appear.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * 4. The names "Apache" and "Apache Software Foundation" must
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * not be used to endorse or promote products derived from this
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * software without prior written permission. For written
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * permission, please contact apache@apache.org.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * 5. Products derived from this software may not be called "Apache",
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * nor may "Apache" appear in their name, without prior written
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * permission of the Apache Software Foundation.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * SUCH DAMAGE.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * ====================================================================
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * This software consists of voluntary contributions made by many
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * individuals on behalf of the Apache Software Foundation. For more
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * information on the Apache Software Foundation, please see
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * Portions of this software are based upon public domain software
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * originally written at the National Center for Supercomputing Applications,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * University of Illinois, Urbana-Champaign.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * http_protocol.c --- routines which directly communicate with the client.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * Code originally by Rob McCool; much redone by Robert S. Thau
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * and the Apache Software Foundation.
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann#include "http_log.h" /* For errors detected in basic auth common
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * support code... */
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann#include "util_date.h" /* For parseHTTPdate and BAD_DATE */
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann ap_bgetopt (r->connection->client, BO_BYTECT, &r->bytes_sent); \
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann/* if this is the first error, then log an INFO message and shut down the
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * connection.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmannstatic void check_first_conn_error(const request_rec *r, const char *operation,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann ap_log_rerror(APLOG_MARK, APLOG_INFO, status, r,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann "client stopped connection before %s completed",
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann ap_bsetflag(r->connection->client, B_EOUT, 1);
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmannstatic int checked_bputstrs(request_rec *r, ...)
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann n = ap_vbputstrs(r->connection->client, va);
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann check_first_conn_error(r, "checked_bputstrs", 0);
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann if ((rv = ap_bflush(r->connection->client)) != APR_SUCCESS) {
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann check_first_conn_error(r, "checked_bflush", rv);
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmannstatic int checked_bputs(const char *str, request_rec *r)
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann rcode = ap_bputs(str, r->connection->client);
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann check_first_conn_error(r, "checked_bputs", 0);
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * Builds the content-type that should be sent to the client from the
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * content-type specified. The following rules are followed:
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * - if type is NULL, type is set to ap_default_type(r)
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * - if charset adding is disabled, stop processing and return type.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * - then, if there are no parameters on type, add the default charset
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * - return type
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmannstatic const char *make_content_type(request_rec *r, const char *type) {
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann static const char *needcset[] = {
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann const char **pcset;
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann core_dir_config *conf = (core_dir_config *)ap_get_module_config(
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann if (conf->add_default_charset != ADD_DEFAULT_CHARSET_ON)
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann if (ap_strcasestr(type, "charset=") != NULL) {
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann /* already has parameter, do nothing */
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann /* XXX we don't check the validity */
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann /* see if it makes sense to add the charset. At present,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * we only add it if the Content-type is one of needcset[]
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann type = ap_pstrcat(r->pool, type, "; charset=",
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmannstatic int parse_byterange(char *range, long clength, long *start, long *end)
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann /* In the form "-5" */
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann else /* "5-" */
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmannstatic int internal_byterange(int, long *, request_rec *, const char **,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel HoltmannAPI_EXPORT(int) ap_set_byterange(request_rec *r)
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann /* Check for Range request-header (HTTP/1.1) or Request-Range for
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * backwards-compatibility with second-draft Luotonen/Franks
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * byte-ranges (e.g. Netscape Navigator 2-3).
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * We support this form, with Request-Range, and (farther down) we
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * send multipart/x-byteranges instead of multipart/byteranges for
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * Request-Range based requests to work around a bug in Netscape
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * Navigator 2-3 and MSIE 3.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann if (!(range = ap_table_get(r->headers_in, "Range")))
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann range = ap_table_get(r->headers_in, "Request-Range");
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann if (!range || strncasecmp(range, "bytes=", 6)) {
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann /* Check the If-Range header for Etag or Date.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * Note that this check will return false (as required) if either
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * of the two etags are weak.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann if ((if_range = ap_table_get(r->headers_in, "If-Range"))) {
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann if (!(match = ap_table_get(r->headers_out, "Etag")) ||
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann else if (!(match = ap_table_get(r->headers_out, "Last-Modified")) ||
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann /* A single range */
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann if (!parse_byterange(ap_pstrdup(r->pool, range + 6), r->clength,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann ap_table_setn(r->headers_out, "Content-Range",
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann ap_table_setn(r->headers_out, "Content-Length",
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann ap_psprintf(r->pool, "%ld", range_end - range_start + 1));
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann /* a multiple range */
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann const char *r_range = ap_pstrdup(r->pool, range + 6);
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann r->boundary = ap_psprintf(r->pool, "%llx%lx",
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann while (internal_byterange(0, &tlength, r, &r_range, NULL, NULL));
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann ap_table_setn(r->headers_out, "Content-Length",
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel HoltmannAPI_EXPORT(int) ap_each_byterange(request_rec *r, ap_off_t *offset,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann return internal_byterange(1, NULL, r, &r->range, offset, length);
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann/* If this function is called with realreq=1, it will spit out
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * the correct headers for a byterange chunk, and set offset and
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * length to the positions they should be.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * If it is called with realreq=0, it will add to tlength the length
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * it *would* have used with realreq=1.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * Either case will return 1 if it should be called again, and 0
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmannstatic int internal_byterange(int realreq, long *tlength, request_rec *r,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann /* determine current translation handle, set to the one for
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * protocol strings, and reset to original setting before
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann AP_PUSH_OUTPUTCONVERSION_STATE(r->connection->client,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann#endif /*APACHE_XLATE*/
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann /* ### this isn't "content" so we can't use ap_rvputs(), but
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * ### it should be processed by non-processing filters. We
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * ### have no "in-between" APIs yet, so send it to the
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * ### network for now
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann (void) checked_bputstrs(r, CRLF "--", r->boundary, "--" CRLF,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann AP_POP_OUTPUTCONVERSION_STATE(r->connection->client);
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann#endif /*APACHE_XLATE*/
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann if (!parse_byterange(range, r->clength, &range_start, &range_end))
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann AP_POP_OUTPUTCONVERSION_STATE(r->connection->client);
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann#endif /*APACHE_XLATE*/
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann /* Skip this one */
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann return internal_byterange(realreq, tlength, r, r_range, offset,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann const char *ct = make_content_type(r, r->content_type);
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann ap_snprintf(ts, sizeof(ts), "%ld-%ld/%ld", range_start, range_end,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann (void) checked_bputstrs(r, CRLF "--", r->boundary,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann *tlength += 4 + strlen(r->boundary) + 16 + strlen(ct) + 23 +
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann AP_POP_OUTPUTCONVERSION_STATE(r->connection->client);
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann#endif /*APACHE_XLATE*/
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel HoltmannAPI_EXPORT(int) ap_set_content_length(request_rec *r, long clength)
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann ap_table_setn(r->headers_out, "Content-Length", ap_psprintf(r->pool, "%ld", clength));
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel HoltmannAPI_EXPORT(int) ap_set_keepalive(request_rec *r)
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann ap_table_get(r->headers_out, "Connection"), "close");
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann const char *conn = ap_table_get(r->headers_in, "Connection");
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann /* Translation is not single-byte-only, so we don't know the
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * content length. Zap the Content-Length header before the
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * following logic, as the absence of the Content-Length header
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * may affect the decision on chunked encoding.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann ap_table_unset(r->headers_out,"Content-Length");
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann#endif /* APACHE_XLATE */
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann /* The following convoluted conditional determines whether or not
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * the current connection should remain persistent after this response
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * (a.k.a. HTTP Keep-Alive) and whether or not the output message
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * body should use the HTTP/1.1 chunked transfer-coding. In English,
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * IF we have not marked this connection as errored;
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * and the response body has a defined length due to the status code
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * being 304 or 204, the request method being HEAD, already
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * having defined Content-Length or Transfer-Encoding: chunked, or
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * the request version being HTTP/1.1 and thus capable of being set
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * as chunked [we know the (r->chunked = 1) side-effect is ugly];
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * and the server configuration enables keep-alive;
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * and the server configuration has a reasonable inter-request timeout;
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * and there is no maximum # requests or the max hasn't been reached;
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * and the response status does not require a close;
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * and the response generator has not already indicated close;
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * and the client did not request non-persistence (Connection: close);
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * and we haven't been configured to ignore the buggy twit
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * or they're a buggy twit coming through a HTTP/1.1 proxy
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * and the client is requesting an HTTP/1.0-style keep-alive
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * or the client claims to be HTTP/1.1 compliant (perhaps a proxy);
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * THEN we can be persistent, which requires more headers be output.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * Note that the condition evaluation order is extremely important.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann ap_table_get(r->headers_out, "Content-Length") ||
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann ap_table_get(r->headers_out, "Transfer-Encoding"),
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann "chunked") ||
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann (r->chunked = 1))) && /* THIS CODE IS CORRECT, see comment above. */
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann (r->server->keep_alive_max > r->connection->keepalives)) &&
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann (!ap_table_get(r->subprocess_env, "nokeepalive") ||
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann ((ka_sent = ap_find_token(r->pool, conn, "keep-alive")) ||
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann int left = r->server->keep_alive_max - r->connection->keepalives;
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann /* If they sent a Keep-Alive token, send one back */
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann ap_table_mergen(r->headers_out, "Connection", "Keep-Alive");
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann /* Otherwise, we need to indicate that we will be closing this
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * connection immediately after the current response.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * We only really need to send "close" to HTTP/1.1 clients, but we
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * always send it anyway, because a broken proxy may identify itself
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * as HTTP/1.0, but pass our request along with our HTTP/1.1 tag
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * to a HTTP/1.1 client. Better safe than sorry.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann ap_table_mergen(r->headers_out, "Connection", "close");
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * Return the latest rational time from a request/mtime (modification time)
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * pair. We return the mtime unless it's in the future, in which case we
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * return the current time. We use the request time as a reference in order
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * to limit the number of calls to time(). We don't check for futurosity
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * unless the mtime is at least as new as the reference.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel HoltmannAPI_EXPORT(ap_time_t) ap_rationalize_mtime(request_rec *r, ap_time_t mtime)
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann /* For all static responses, it's almost certain that the file was
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * last modified before the beginning of the request. So there's
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * no reason to call time(NULL) again. But if the response has been
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * created on demand, then it might be newer than the time the request
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * started. In this event we really have to call time(NULL) again
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * so that we can give the clients the most accurate Last-Modified. If we
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * were given a time in the future, we return the current time - the
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann * Last-Modified can't be in the future.
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann now = (mtime < r->request_time) ? r->request_time : ap_now();
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel HoltmannAPI_EXPORT(int) ap_meets_conditions(request_rec *r)
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann const char *etag = ap_table_get(r->headers_out, "ETag");
94f5bbc626f2a4102debd9b17c964170a887cb49Marcel Holtmann const char *if_match, *if_modified_since, *if_unmodified, *if_nonematch;
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann /* Check for conditional requests --- note that we only want to do
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * this if we are successful so far and we are not processing a
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * subrequest or an ErrorDocument.
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * The order of the checks is important, since ETag checks are supposed
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * to be more accurate than checks relative to the modification time.
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * However, not all documents are guaranteed to *have* ETags, and some
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * might have Last-Modified values w/o ETags, so this gets a little
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * complicated.
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann if (!ap_is_HTTP_SUCCESS(r->status) || r->no_local_copy) {
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann /* XXX: we should define a "time unset" constant */
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann mtime = (r->mtime != 0) ? r->mtime : ap_now();
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann /* If an If-Match request-header field was given
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * AND the field value is not "*" (meaning match anything)
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * AND if our strong ETag does not match any entity tag in that field,
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * respond with a status of 412 (Precondition Failed).
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann if ((if_match = ap_table_get(r->headers_in, "If-Match")) != NULL) {
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann !ap_find_list_item(r->pool, if_match, etag))) {
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann /* Else if a valid If-Unmodified-Since request-header field was given
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * AND the requested resource has been modified since the time
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * specified in this field, then the server MUST
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * respond with a status of 412 (Precondition Failed).
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann if_unmodified = ap_table_get(r->headers_in, "If-Unmodified-Since");
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann ap_time_t ius = ap_parseHTTPdate(if_unmodified);
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann /* If an If-None-Match request-header field was given
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * AND the field value is "*" (meaning match anything)
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * OR our ETag matches any of the entity tags in that field, fail.
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * If the request method was GET or HEAD, failure means the server
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * SHOULD respond with a 304 (Not Modified) response.
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * For all other request methods, failure means the server MUST
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * respond with a status of 412 (Precondition Failed).
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * GET or HEAD allow weak etag comparison, all other methods require
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * strong comparison. We can only use weak if it's not a range request.
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann if_nonematch = ap_table_get(r->headers_in, "If-None-Match");
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann ap_find_list_item(r->pool, if_nonematch, etag)) {
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann ap_find_list_item(r->pool, if_nonematch, etag))) {
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann /* Else if a valid If-Modified-Since request-header field was given
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * AND it is a GET or HEAD request
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * AND the requested resource has not been modified since the time
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * specified in this field, then the server MUST
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * respond with a status of 304 (Not Modified).
4b28cdeb2332cfbd3f5172b43a2f5f534b7e6e57Marcel Holtmann * A date later than the server's current request time is invalid.
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann ap_table_get(r->headers_in, "If-Modified-Since")) != NULL)) {
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann ap_time_t ims = ap_parseHTTPdate(if_modified_since);
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann if ((ims >= mtime) && (ims <= r->request_time)) {
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * Construct an entity tag (ETag) from resource information. If it's a real
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * file, build in some of the file characteristics. If the modification time
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * is newer than (request-time minus 1 second), mark the ETag as weak - it
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * could be modified again in as short an interval. We rationalize the
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * modification time we're given to keep it from being in the future.
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel HoltmannAPI_EXPORT(char *) ap_make_etag(request_rec *r, int force_weak)
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * Make an ETag header out of various pieces of information. We use
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * the last-modified date and, if we have a real file, the
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * length and inode number - note that this doesn't have to match
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * the content-length (i.e. includes), it just has to be unique
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * for the file.
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * If the request was made within a second of the last-modified date,
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * we send a weak tag instead of a strong one, since it could
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * be modified again later in the second, and the validation
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * would be incorrect.
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann weak = ((r->request_time - r->mtime > AP_USEC_PER_SEC) && !force_weak) ? "" : "W/";
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann (unsigned long) r->mtime);
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann etag = ap_psprintf(r->pool, "%s\"%lx\"", weak,
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann (unsigned long) r->mtime);
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann /* If we have a variant list validator (vlv) due to the
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * response being negotiated, then we create a structured
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * entity tag which merges the variant etag with the variant
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * list validator (vlv). This merging makes revalidation
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * somewhat safer, ensures that caches which can deal with
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * Vary will (eventually) be updated if the set of variants is
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * changed, and is also a protocol requirement for transparent
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * content negotiation.
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann /* if the variant list validator is weak, we make the whole
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * structured etag weak. If we would not, then clients could
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * have problems merging range responses if we have different
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann * variants with the same non-globally-unique strong etag.
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann /* merge variant_etag and vlv into a structured etag */
5476ad087c0f2d45ab0dab1bab9ef3e9d70418bcMarcel Holtmann variant_etag[strlen(variant_etag) - 1] = '\0';
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann etag = ap_pstrcat(r->pool, variant_etag, ";", vlv, NULL);
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann ap_table_setn(r->headers_out, "ETag", etag);
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann * This function sets the Last-Modified output header field to the value
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann * of the mtime field in the request structure - rationalized to keep it from
b189101727e80a09864c5e5880663ef565467f19Marcel Holtmann * being in the future.
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel HoltmannAPI_EXPORT(void) ap_set_last_modified(request_rec *r)
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann ap_time_t mod_time = ap_rationalize_mtime(r, r->mtime);
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann char *datestr = ap_palloc(r->pool, AP_RFC822_DATE_LEN);
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann ap_table_setn(r->headers_out, "Last-Modified", datestr);
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann/* Get the method number associated with the given string, assumed to
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann * contain an HTTP method. Returns M_INVALID if not recognized.
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann * This is the first step toward placing method names in a configurable
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann * list. Hopefully it (and other routines) can eventually be moved to
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann * something like a mod_http_methods.c, complete with config stuff.
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel HoltmannAPI_EXPORT(int) ap_method_number_of(const char *method)
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann return M_GET; /* see header_only in request_rec */
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann/* Get a line of protocol input, including any continuation lines
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann * caused by MIME folding (or broken clients) if fold != 0, and place it
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann * in the buffer s, of size n bytes, without the ending newline.
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann * Returns -1 on error, or the length of s.
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann * Note: Because bgets uses 1 char for newline and 1 char for NUL,
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann * the most we can get is (n - 2) actual characters if it
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann * was ended by a newline, or (n - 1) characters if the line
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann * length exceeded (n - 1). So, if the result == (n - 1),
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann * then the actual input line exceeded the buffer length,
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmann * and it would be a good idea for the caller to puke 400 or 414.
c6f3f5b4b3ec439ae911ca0644237d96fd31893eMarcel Holtmannstatic int getline(char *s, int n, BUFF *in, int fold)
0234c599218518b1eb478d64d9883ba46e4ce5d8Marcel Holtmann /* When getline() is called, the HTTP protocol is in a state
0234c599218518b1eb478d64d9883ba46e4ce5d8Marcel Holtmann * where we MUST be reading "plain text" protocol stuff,
0234c599218518b1eb478d64d9883ba46e4ce5d8Marcel Holtmann * (Request line, MIME headers, Chunk sizes) regardless of
0234c599218518b1eb478d64d9883ba46e4ce5d8Marcel Holtmann * the MIME type and conversion setting of the document itself.
0234c599218518b1eb478d64d9883ba46e4ce5d8Marcel Holtmann * Save the current setting of the translation handle for
0234c599218518b1eb478d64d9883ba46e4ce5d8Marcel Holtmann * uploads, then temporarily set it to the one used for headers
0234c599218518b1eb478d64d9883ba46e4ce5d8Marcel Holtmann * (and restore it before returning).
0234c599218518b1eb478d64d9883ba46e4ce5d8Marcel Holtmann AP_PUSH_INPUTCONVERSION_STATE(in, ap_hdrs_from_ascii);
0234c599218518b1eb478d64d9883ba46e4ce5d8Marcel Holtmann#endif /*APACHE_XLATE*/
c4a3a17ee919e8b1197328394709edfe36d8b710Marcel Holtmann /* retval == -1 if error, 0 if EOF */
c4a3a17ee919e8b1197328394709edfe36d8b710Marcel Holtmann total = ((retval < 0) && (total == 0)) ? -1 : total;
c4a3a17ee919e8b1197328394709edfe36d8b710Marcel Holtmann /* retval is the number of characters read, not including NUL */
c4a3a17ee919e8b1197328394709edfe36d8b710Marcel Holtmann n -= retval; /* Keep track of how much of s is full */
43d9c2b5848b1363b659c38443c1c94db57415fdMarcel Holtmann total += retval; /* and how long s has become */
43d9c2b5848b1363b659c38443c1c94db57415fdMarcel Holtmann if (*pos == '\n') { /* Did we get a full line of input? */
43d9c2b5848b1363b659c38443c1c94db57415fdMarcel Holtmann * Trim any extra trailing spaces or tabs except for the first
43d9c2b5848b1363b659c38443c1c94db57415fdMarcel Holtmann * space or tab at the beginning of a blank string. This makes
43d9c2b5848b1363b659c38443c1c94db57415fdMarcel Holtmann * it much easier to check field values for exact matches, and
43d9c2b5848b1363b659c38443c1c94db57415fdMarcel Holtmann * saves memory as well. Terminate string at end of line.
43d9c2b5848b1363b659c38443c1c94db57415fdMarcel Holtmann while (pos > (s + 1) && (*(pos - 1) == ' ' || *(pos - 1) == '\t')) {
43d9c2b5848b1363b659c38443c1c94db57415fdMarcel Holtmann --pos; /* trim extra trailing spaces or tabs */
43d9c2b5848b1363b659c38443c1c94db57415fdMarcel Holtmann --total; /* but not one at the beginning of line */
4b28cdeb2332cfbd3f5172b43a2f5f534b7e6e57Marcel Holtmann break; /* if not, input line exceeded buffer size */
4b28cdeb2332cfbd3f5172b43a2f5f534b7e6e57Marcel Holtmann /* Continue appending if line folding is desired and
4b28cdeb2332cfbd3f5172b43a2f5f534b7e6e57Marcel Holtmann * the last line was not empty and we have room in the buffer and
4b28cdeb2332cfbd3f5172b43a2f5f534b7e6e57Marcel Holtmann * the next line begins with a continuation character.
4b28cdeb2332cfbd3f5172b43a2f5f534b7e6e57Marcel Holtmann /* restore translation handle */
4b28cdeb2332cfbd3f5172b43a2f5f534b7e6e57Marcel Holtmann#endif /*APACHE_XLATE*/
4b28cdeb2332cfbd3f5172b43a2f5f534b7e6e57Marcel Holtmann/* parse_uri: break apart the uri
4b28cdeb2332cfbd3f5172b43a2f5f534b7e6e57Marcel Holtmann * Side Effects:
4b28cdeb2332cfbd3f5172b43a2f5f534b7e6e57Marcel Holtmann * - sets r->args to rest after '?' (or NULL if no '?')
4b28cdeb2332cfbd3f5172b43a2f5f534b7e6e57Marcel Holtmann * - sets r->uri to request uri (without r->args part)
4b28cdeb2332cfbd3f5172b43a2f5f534b7e6e57Marcel Holtmann * - sets r->hostname (if not set already) from request (scheme://host:port)
4b28cdeb2332cfbd3f5172b43a2f5f534b7e6e57Marcel HoltmannCORE_EXPORT(void) ap_parse_uri(request_rec *r, const char *uri)
e525326bd07ebf3cabcfd730bc479166723f2d44Marcel Holtmann status = ap_parse_hostinfo_components(r->pool, uri, &r->parsed_uri);
e525326bd07ebf3cabcfd730bc479166723f2d44Marcel Holtmann /* Simple syntax Errors in URLs are trapped by parse_uri_components(). */
e525326bd07ebf3cabcfd730bc479166723f2d44Marcel Holtmann status = ap_parse_uri_components(r->pool, uri, &r->parsed_uri);
f401e2b24ba17452f9655993a6dedefdffe06d23Marcel Holtmann /* if it has a scheme we may need to do absoluteURI vhost stuff */
f401e2b24ba17452f9655993a6dedefdffe06d23Marcel Holtmann && !strcasecmp(r->parsed_uri.scheme, ap_http_method(r))) {
f401e2b24ba17452f9655993a6dedefdffe06d23Marcel Holtmann r->uri = r->parsed_uri.path ? r->parsed_uri.path
f401e2b24ba17452f9655993a6dedefdffe06d23Marcel Holtmann /* Handle path translations for OS/2 and plug security hole.
f89b42ec0fd51feab5566d6bdbacee101023c037Marcel Holtmann * This will prevent "http://www.wherever.com/..\..\/" from
f89b42ec0fd51feab5566d6bdbacee101023c037Marcel Holtmann * returning a directory for the root drive.
f89b42ec0fd51feab5566d6bdbacee101023c037Marcel Holtmann for (x = r->uri; (x = strchr(x, '\\')) != NULL; )
f89b42ec0fd51feab5566d6bdbacee101023c037Marcel Holtmann#endif /* OS2 || WIN32 */
b189101727e80a09864c5e5880663ef565467f19Marcel Holtmann char l[DEFAULT_LIMIT_REQUEST_LINE + 2]; /* getline's two extra for \n\0 */
b189101727e80a09864c5e5880663ef565467f19Marcel Holtmann const char *ll = l;
b189101727e80a09864c5e5880663ef565467f19Marcel Holtmann int major = 1, minor = 0; /* Assume HTTP/1.0 if non-"HTTP" protocol */
b189101727e80a09864c5e5880663ef565467f19Marcel Holtmann /* Read past empty lines until we get a real request line,
b189101727e80a09864c5e5880663ef565467f19Marcel Holtmann * a read error, the connection closes (EOF), or we timeout.
b189101727e80a09864c5e5880663ef565467f19Marcel Holtmann * We skip empty lines because browsers have to tack a CRLF on to the end
b189101727e80a09864c5e5880663ef565467f19Marcel Holtmann * of POSTs to support old CERN webservers. But note that we may not
b189101727e80a09864c5e5880663ef565467f19Marcel Holtmann * have flushed any previous response completely to the client yet.
b189101727e80a09864c5e5880663ef565467f19Marcel Holtmann * We delay the flush as long as possible so that we can improve
b189101727e80a09864c5e5880663ef565467f19Marcel Holtmann * performance for clients that are pipelining requests. If a request
b189101727e80a09864c5e5880663ef565467f19Marcel Holtmann * is pipelined then we won't block during the (implicit) read() below.
b189101727e80a09864c5e5880663ef565467f19Marcel Holtmann * If the requests aren't pipelined, then the client is still waiting
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann * for the final buffer flush from us, and we will block in the implicit
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann * read(). B_SAFEREAD ensures that the BUFF layer flushes if it will
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann * have to block during a read.
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann while ((len = getline(l, sizeof(l), conn->client, 0)) <= 0) {
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann if ((len < 0) || ap_bgetflag(conn->client, B_EOF)) {
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann /* this is a hack to make sure that request time is set,
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann * it's not perfect, but it's better than nothing
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann /* we've probably got something to do, ignore graceful restart requests */
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann /* XXX - sigwait doesn't work if the signal has been SIG_IGNed (under
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann * linux 2.0 w/ glibc 2.0, anyway), and this step isn't necessary when
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann * we're running a sigwait thread anyway. If/when unthreaded mode is
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann * put back in, we should make sure to ignore this signal iff a sigwait
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann * thread isn't used. - mvsk
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann#ifdef SIGWINCH
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann ap_signal(SIGWINCH, SIG_IGN);
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann ap_update_connection_status(conn->id, "Method", r->method);
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann /* Provide quick information about the request method as soon as known */
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann r->method_number = ap_method_number_of(r->method);
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann if (r->method_number == M_GET && r->method[0] == 'H') {
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann /* getline returns (size of max buffer - 1) if it fills up the
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann * buffer before finding the end-of-line. This is only going to
24e29480bd800d3acdb3087e5863440bd0dd1d80Marcel Holtmann * happen if it exceeds the configured limit for a request-line.
char *value;
char *copy;
int len;
unsigned int fields_read = 0;
++value;
request_rec *r;
ap_pool_t *p;
const char *expect;
int access_status;
r->pool = p;
r->read_length = 0;
#ifdef APACHE_XLATE
if (!read_request_line(r)) {
ap_send_error_response(r, 0);
return NULL;
if (!r->assbackwards) {
get_mime_headers(r);
ap_send_error_response(r, 0);
if (r->header_only) {
r->uri);
r->header_only = 0;
ap_send_error_response(r, 0);
ap_send_error_response(r, 0);
ap_send_error_response(r, 0);
(void) ap_discard_request_body(r);
return NULL;
NULL));
return DECLINED;
if (!ap_auth_name(r)) {
return HTTP_INTERNAL_SERVER_ERROR;
if (!auth_line) {
return HTTP_UNAUTHORIZED;
return HTTP_UNAUTHORIZED;
auth_line++;
*pw = t;
return OK;
* The number of status lines must equal the value of RESPONSE_CODES (httpd.h)
#ifdef UTS21
int i, pos;
return LEVEL_500;
return pos;
* In other words, don't change this one without checking table_do in alloc.c.
char *protocol;
if (r->assbackwards)
if (!r->status_line)
if (r->proxyreq
#ifdef APACHE_XLATE
#ifdef APACHE_XLATE
long int bs;
NULL);
int rv;
while (r->prev)
r = r->prev;
return rv;
ap_table_do((int (*) (void *, const char *, const char *))
return OK;
const long int zero = 0L;
if (r->assbackwards)
return DECLINED;
ap_set_keepalive(r);
terminate_header(r);
return OK;
* Here we try to be compatible with clients that want multipart/x-byteranges
* instead of multipart/byteranges (also see above), as per HTTP/1.1. We
const char *ua;
* consisting of comma/space-separated tokens.
char *start;
char **strpp;
start = e;
++i, ++strpp) {
const long int zero = 0L;
if (r->assbackwards) {
if (!r->main)
#ifdef CHARSET_EBCDIC
ap_checkconv(r);
r->headers_out);
fixup_vary(r);
#ifdef APACHE_XLATE
ap_set_keepalive(r);
if (r->chunked) {
r->content_type));
if (r->content_encoding)
else if (r->content_language)
terminate_header(r);
if (r->chunked)
#ifdef APACHE_XLATE
#ifdef APACHE_XLATE
r->chunked = 0;
#ifdef APACHE_XLATE
unsigned long max_body;
r->read_chunked = 0;
r->remaining = 0;
if (tenc) {
return HTTP_NOT_IMPLEMENTED;
else if (lenp) {
++pos;
return HTTP_BAD_REQUEST;
return HTTP_REQUEST_ENTITY_TOO_LARGE;
return HTTP_REQUEST_ENTITY_TOO_LARGE;
#ifdef CHARSET_EBCDIC
if (!convert_in) {
return OK;
(void) checked_bflush(r);
static long get_chunk_size(char *b)
long chunksize = 0;
while (ap_isxdigit(*b)) {
int xvalue = 0;
return chunksize;
long chunk_start = 0;
unsigned long max_body;
return len_read;
if (bufsiz <= 0)
max_body);
get_mime_headers(r);
chunk_start = 0;
if (len_read < 0) {
return chunk_start;
#ifdef APACHE_XLATE
#ifdef APACHE_XLATE
if (c != LF) {
int rv;
return rv;
if (r->expecting_100) {
return OK;
if (rv < 0)
return HTTP_BAD_REQUEST;
return OK;
#if APR_HAS_SENDFILE
&length,
flags);
return rv;
ap_ssize_t n;
*nbytes = 0;
return APR_SUCCESS;
#if APR_HAS_SENDFILE
if (!r->chunked) {
return rv;
return rv;
if (offset) {
return rv;
n = IOBUFSIZE;
total_bytes_sent += o;
SET_BYTES_SENT(r);
return rv;
long total_bytes_sent = 0;
long zero_timeout = 0;
ap_ssize_t n;
if (length == 0) {
bytes_read = n;
total_bytes_sent += o;
if (bytes_read == 0) {
(void) ap_rflush(r);
(void) ap_rflush(r);
goto got_read;
SET_BYTES_SENT(r);
return total_bytes_sent;
#ifdef USE_MMAP_FILES
#ifndef MMAP_SEGMENT_SIZE
ap_ssize_t w;
char *addr;
if (length == 0)
n = MMAP_SEGMENT_SIZE;
total_bytes_sent += w;
offset += w;
SET_BYTES_SENT(r);
return total_bytes_sent;
return EOF;
return EOF;
SET_BYTES_SENT(r);
int rcode;
return EOF;
if (rcode < 0) {
return EOF;
SET_BYTES_SENT(r);
return rcode;
ap_ssize_t n;
return EOF;
return EOF;
SET_BYTES_SENT(r);
return EOF;
return EOF;
SET_BYTES_SENT(r);
return EOF;
return EOF;
SET_BYTES_SENT(r);
return EOF;
return EOF;
SET_BYTES_SENT(r);
return EOF;
char *custom_response;
r->headers_out);
ap_set_keepalive(r);
(void *) r, r->headers_out,
NULL);
terminate_header(r);
if (!r->assbackwards) {
r->clength = 0;
if (r->header_only) {
ap_rflush(r);
#ifdef APACHE_XLATE
ap_rflush(r);
r = r->prev;
const char *h1;
const char *error_notes;
ap_rvputs(r,
NULL);
switch (status) {
case HTTP_MOVED_PERMANENTLY:
case HTTP_MOVED_TEMPORARILY:
case HTTP_TEMPORARY_REDIRECT:
NULL);
case HTTP_SEE_OTHER:
NULL);
case HTTP_USE_PROXY:
case HTTP_UNAUTHORIZED:
case HTTP_BAD_REQUEST:
case HTTP_FORBIDDEN:
case HTTP_NOT_FOUND:
case HTTP_METHOD_NOT_ALLOWED:
case HTTP_NOT_ACCEPTABLE:
ap_rvputs(r,
case HTTP_MULTIPLE_CHOICES:
const char *list;
case HTTP_LENGTH_REQUIRED:
case HTTP_PRECONDITION_FAILED:
case HTTP_NOT_IMPLEMENTED:
case HTTP_BAD_GATEWAY:
case HTTP_VARIANT_ALSO_VARIES:
case HTTP_REQUEST_TIME_OUT:
case HTTP_GONE:
NULL);
case HTTP_EXPECTATION_FAILED:
NULL);
case HTTP_LOCKED:
case HTTP_FAILED_DEPENDENCY:
case HTTP_SERVICE_UNAVAILABLE:
case HTTP_GATEWAY_TIME_OUT:
case HTTP_NOT_EXTENDED:
if (recursive_error) {
ap_rflush(r);
(const request_rec *r),(r),0)