http_protocol.c revision 97c0c3f13de0b6189a71a53df005c8b38074c869
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd/* ====================================================================
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * Copyright (c) 1995-2000 The Apache Software Foundation. All rights reserved.
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * Redistribution and use in source and binary forms, with or without
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * modification, are permitted provided that the following conditions
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * are met:
96ad5d81ee4a2cc66a4ae19893efc8aa6d06fae7jailletc * 1. Redistributions of source code must retain the above copyright
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * notice, this list of conditions and the following disclaimer.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * 2. Redistributions in binary form must reproduce the above copyright
2e545ce2450a9953665f701bb05350f0d3f26275nd * notice, this list of conditions and the following disclaimer in
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * the documentation and/or other materials provided with the
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * distribution.
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * 3. All advertising materials mentioning features or use of this
af33a4994ae2ff15bc67d19ff1a7feb906745bf8rbowen * software must display the following acknowledgment:
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * "This product includes software developed by the Apache Software Foundation
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * for use in the Apache HTTP server project (http://www.apache.org/)."
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * 4. The names "Apache Server" and "Apache Software Foundation" must not be used to
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * endorse or promote products derived from this software without
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * prior written permission. For written permission, please contact
9472e4d3c410be3b3f1addbf3b1db1769f64e765nd * apache@apache.org.
1c8f2418892d98febb00a06b9a4f45f8bcfd80a3nd * 5. Products derived from this software may not be called "Apache"
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * nor may "Apache" appear in their names without prior written
1ac39787115a288f5e848344b1b1e8dccb1c58f1nd * permission of the Apache Software Foundation.
d474d8ef01ec5c2a09341cd148851ed383c3287crbowen * 6. Redistributions of any form whatsoever must retain the following
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * acknowledgment:
4b575a6b6704b516f22d65a3ad35696d7b9ba372rpluem * "This product includes software developed by the Apache Software Foundation
4b575a6b6704b516f22d65a3ad35696d7b9ba372rpluem * for use in the Apache HTTP server project (http://www.apache.org/)."
4b575a6b6704b516f22d65a3ad35696d7b9ba372rpluem * THIS SOFTWARE IS PROVIDED BY THE Apache Software Foundation ``AS IS'' AND ANY
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE Apache Software Foundation OR
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * OF THE POSSIBILITY OF SUCH DAMAGE.
4b5981e276e93df97c34e4da05ca5cf8bbd937dand * ====================================================================
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * This software consists of voluntary contributions made by many
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * individuals on behalf of the Apache Software Foundation and was originally based
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * on public domain software written at the National Center for
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * Supercomputing Applications, University of Illinois, Urbana-Champaign.
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * For more information on the Apache Software Foundation and the Apache HTTP server
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * project, please see <http://www.apache.org/>.
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * http_protocol.c --- routines which directly communicate with the client.
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * Code originally by Rob McCool; much redone by Robert S. Thau
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * and the Apache Software Foundation.
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#include "http_log.h" /* For errors detected in basic auth common
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * support code... */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd#include "util_date.h" /* For parseHTTPdate and BAD_DATE */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd do { if (r->sent_bodyct) \
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd ap_bgetopt (r->connection->client, BO_BYTECT, &r->bytes_sent); \
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd } while (0)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * Builds the content-type that should be sent to the client from the
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * content-type specified. The following rules are followed:
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * - if type is NULL, type is set to ap_default_type(r)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * - if charset adding is disabled, stop processing and return type.
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * - then, if there are no parameters on type, add the default charset
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * - return type
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndstatic const char *make_content_type(request_rec *r, const char *type) {
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd char *needcset[] = {
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd core_dir_config *conf = (core_dir_config *)ap_get_module_config(
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd if (conf->add_default_charset != ADD_DEFAULT_CHARSET_ON) return type;
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd /* already has parameter, do nothing */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd /* XXX we don't check the validity */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd /* see if it makes sense to add the charset. At present,
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd * we only add it if the Content-type is one of needcset[]
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndstatic int parse_byterange(char *range, long clength, long *start, long *end)
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd /* In the form "-5" */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd else /* "5-" */
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34ndstatic int internal_byterange(int, long *, request_rec *, const char **,
9472e4d3c410be3b3f1addbf3b1db1769f64e765nd ap_off_t *, long *);
cc7e1025de9ac63bd4db6fe7f71c158b2cf09fe4humbedooh /* Check for Range request-header (HTTP/1.1) or Request-Range for
0d0ba3a410038e179b695446bb149cce6264e0abnd * backwards-compatibility with second-draft Luotonen/Franks
cc7e1025de9ac63bd4db6fe7f71c158b2cf09fe4humbedooh * byte-ranges (e.g. Netscape Navigator 2-3).
0d0ba3a410038e179b695446bb149cce6264e0abnd * We support this form, with Request-Range, and (farther down) we
0d0ba3a410038e179b695446bb149cce6264e0abnd * send multipart/x-byteranges instead of multipart/byteranges for
0d0ba3a410038e179b695446bb149cce6264e0abnd * Request-Range based requests to work around a bug in Netscape
ac082aefa89416cbdc9a1836eaf3bed9698201c8humbedooh * Navigator 2-3 and MSIE 3.
727872d18412fc021f03969b8641810d8896820bhumbedooh range = ap_table_get(r->headers_in, "Request-Range");
0d0ba3a410038e179b695446bb149cce6264e0abnd /* Check the If-Range header for Etag or Date.
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd * Note that this check will return false (as required) if either
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd * of the two etags are weak.
97a3ecc40b65d5f8e865bbe0b1c9325d8c016e34nd if ((if_range = ap_table_get(r->headers_in, "If-Range"))) {
long tlength = 0;
long *length)
long *length)
char *range;
if (!**r_range) {
if (realreq)
length);
r->clength);
if (realreq)
NULL);
if (realreq) {
int ka_sent = 0;
r->header_only ||
!wimpy &&
if (ka_sent) {
if (!wimpy)
return OK;
return HTTP_PRECONDITION_FAILED;
return HTTP_PRECONDITION_FAILED;
return HTTP_NOT_MODIFIED;
return HTTP_NOT_MODIFIED;
return HTTP_NOT_MODIFIED;
return HTTP_PRECONDITION_FAILED;
&& ((if_modified_since =
return HTTP_NOT_MODIFIED;
return OK;
char *etag;
char *weak;
(unsigned long) r->mtime);
(unsigned long) r->mtime);
return etag;
char *etag;
int vlv_weak;
if (!r->vlist_validator) {
if (vlv_weak)
vlv++;
* something like a mod_http_methods.c, complete with config stuff.
switch (*method) {
return M_GET;
return M_POST;
return M_PUT;
return M_PATCH;
return M_PROPFIND;
return M_PROPPATCH;
return M_DELETE;
return M_CONNECT;
return M_COPY;
return M_MKCOL;
return M_MOVE;
return M_OPTIONS;
return M_TRACE;
return M_LOCK;
return M_UNLOCK;
return M_INVALID;
int retval;
int total = 0;
pos = s;
if (retval <= 0)
--total;
return total;
* This will prevent "http://www.wherever.com/..\..\/" from
const char *ll = l;
const char *uri;
int len;
char *value;
char *copy;
int len;
unsigned int fields_read = 0;
++value;
if (!r->input) {
return status;
if (!iol)
return APR_EBADF;
return APR_SUCCESS;
request_rec *r;
ap_context_t *p;
const char *expect;
int access_status;
r->pool = p;
r->read_length = 0;
#ifdef CHARSET_EBCDIC
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 SERVER_ERROR;
if (!auth_line) {
return AUTH_REQUIRED;
return AUTH_REQUIRED;
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;
#ifdef CHARSET_EBCDIC
if (r->assbackwards)
if (!r->status_line)
if (r->proxyreq
#ifdef CHARSET_EBCDIC
#ifdef CHARSET_EBCDIC
if (!convert)
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;
#ifdef CHARSET_EBCDIC
if (r->assbackwards) {
if (!r->main)
r->headers_out);
fixup_vary(r);
#ifdef CHARSET_EBCDIC
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 CHARSET_EBCDIC
if (!convert)
r->chunked = 0;
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;
return OK;
NULL);
ap_rflush(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;
if (c != LF) {
int rv;
return rv;
if (r->expecting_100) {
return OK;
if (rv < 0)
return HTTP_BAD_REQUEST;
return OK;
#ifdef HAVE_SENDFILE
if (!r->chunked) {
&len,
return len;
long total_bytes_sent = 0;
ap_ssize_t w;
ap_ssize_t n;
if (length == 0)
o = IOBUFSIZE;
total_bytes_sent += w;
SET_BYTES_SENT(r);
return total_bytes_sent;
long total_bytes_sent = 0;
long zero_timeout = 0;
ap_ssize_t w;
ap_ssize_t n;
if (length == 0) {
(void) ap_rflush(r);
(void) ap_rflush(r);
total_bytes_sent += w;
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);
SET_BYTES_SENT(r);
SET_BYTES_SENT(r);
ap_ssize_t i;
return EOF;
if (x == NULL)
j = strlen(x);
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);
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 AUTH_REQUIRED:
case BAD_REQUEST:
case HTTP_FORBIDDEN:
case NOT_FOUND:
case METHOD_NOT_ALLOWED:
case NOT_ACCEPTABLE:
ap_rvputs(r,
case MULTIPLE_CHOICES:
const char *list;
case LENGTH_REQUIRED:
case PRECONDITION_FAILED:
case HTTP_NOT_IMPLEMENTED:
case BAD_GATEWAY:
case 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);
NULL)