protocol.c revision 2d399cd7535887fceaa9f8f116eb98ce68ddd602
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme/* ====================================================================
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * The Apache Software License, Version 1.1
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * Copyright (c) 2000-2002 The Apache Software Foundation. All rights
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * reserved.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * Redistribution and use in source and binary forms, with or without
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * modification, are permitted provided that the following conditions
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * 1. Redistributions of source code must retain the above copyright
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * notice, this list of conditions and the following disclaimer.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * 2. Redistributions in binary form must reproduce the above copyright
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * notice, this list of conditions and the following disclaimer in
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * the documentation and/or other materials provided with the
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * distribution.
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * 3. The end-user documentation included with the redistribution,
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * if any, must include the following acknowledgment:
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * "This product includes software developed by the
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * Apache Software Foundation (http://www.apache.org/)."
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * Alternately, this acknowledgment may appear in the software itself,
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * if and wherever such third-party acknowledgments normally appear.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * 4. The names "Apache" and "Apache Software Foundation" must
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * not be used to endorse or promote products derived from this
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * software without prior written permission. For written
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * permission, please contact apache@apache.org.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * 5. Products derived from this software may not be called "Apache",
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * nor may "Apache" appear in their name, without prior written
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * permission of the Apache Software Foundation.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * SUCH DAMAGE.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * ====================================================================
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * This software consists of voluntary contributions made by many
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * individuals on behalf of the Apache Software Foundation. For more
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * information on the Apache Software Foundation, please see
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * Portions of this software are based upon public domain software
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * originally written at the National Center for Supercomputing Applications,
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick * University of Illinois, Urbana-Champaign.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * http_protocol.c --- routines which directly communicate with the client.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * Code originally by Rob McCool; much redone by Robert S. Thau
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * and the Apache Software Foundation.
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim#include "http_log.h" /* For errors detected in basic auth common
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * support code... */
11f2c481e1d57bedb3f758565307501e9a2730ddtrawickAP_DECLARE_DATA ap_filter_rec_t *ap_old_write_func = NULL;
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme/* Patterns to match in ap_make_content_type() */
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jimstatic const char *needcset[] = {
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemmeAP_DECLARE(void) ap_setup_make_content_type(apr_pool_t *pool)
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme for (i = 0; needcset[i]; i++) {
59d316b83d42d2a07e25c20d8c35a07b369618bdsf apr_palloc(pool, (i + 1) * sizeof(apr_strmatch_pattern *));
59d316b83d42d2a07e25c20d8c35a07b369618bdsf for (i = 0; needcset[i]; i++) {
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim needcset_patterns[i] = apr_strmatch_precompile(pool, needcset[i], 0);
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme charset_pattern = apr_strmatch_precompile(pool, "charset=", 0);
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick * Builds the content-type that should be sent to the client from the
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * content-type specified. The following rules are followed:
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * - if type is NULL, type is set to ap_default_type(r)
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * - if charset adding is disabled, stop processing and return type.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * - then, if there are no parameters on type, add the default charset
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * - return type
5400544d62947907986d570435dd16f02ca824e0sfAP_DECLARE(const char *)ap_make_content_type(request_rec *r, const char *type)
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme (core_dir_config *)ap_get_module_config(r->per_dir_config,
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme if (conf->add_default_charset != ADD_DEFAULT_CHARSET_ON) {
5400544d62947907986d570435dd16f02ca824e0sf if (apr_strmatch(charset_pattern, type, type_len) != NULL) {
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim /* already has parameter, do nothing */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* XXX we don't check the validity */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* see if it makes sense to add the charset. At present,
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * we only add it if the Content-type is one of needcset[]
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme concat[2].iov_base = (void *)(conf->add_default_charset_name);
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme concat[2].iov_len = strlen(conf->add_default_charset_name);
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemmeAP_DECLARE(void) ap_set_content_length(request_rec *r, apr_off_t clength)
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * Return the latest rational time from a request/mtime (modification time)
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * pair. We return the mtime unless it's in the future, in which case we
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * return the current time. We use the request time as a reference in order
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * to limit the number of calls to time(). We don't check for futurosity
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * unless the mtime is at least as new as the reference.
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jimAP_DECLARE(apr_time_t) ap_rationalize_mtime(request_rec *r, apr_time_t mtime)
5400544d62947907986d570435dd16f02ca824e0sf /* For all static responses, it's almost certain that the file was
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * last modified before the beginning of the request. So there's
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick * no reason to call time(NULL) again. But if the response has been
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * created on demand, then it might be newer than the time the request
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * started. In this event we really have to call time(NULL) again
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * so that we can give the clients the most accurate Last-Modified. If we
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * were given a time in the future, we return the current time - the
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * Last-Modified can't be in the future.
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim now = (mtime < r->request_time) ? r->request_time : apr_time_now();
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme/* Min # of bytes to allocate when reading a request line */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme/* Get a line of protocol input, including any continuation lines
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * caused by MIME folding (or broken clients) if fold != 0, and place it
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * in the buffer s, of size n bytes, without the ending newline.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * If s is NULL, ap_rgetline_core will allocate necessary memory from r->pool.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * Returns APR_SUCCESS if there are no problems and sets *read to be
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * the full length of s.
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * APR_ENOSPC is returned if there is not enough buffer space.
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * Other errors may be returned on other errors.
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * The LF is *not* returned in the buffer. Therefore, a *read of 0
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * indicates that an empty line was read.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * Notes: Because the buffer uses 1 char for NUL, the most we can return is
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * (n - 1) actual characters.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * If no LF is detected on the last line due to a dropped connection
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * or a full buffer, that's considered an error.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemmeAP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n,
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme b = apr_brigade_create(r->pool, r->connection->bucket_alloc);
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme rv = ap_get_brigade(r->input_filters, b, AP_MODE_GETLINE,
5400544d62947907986d570435dd16f02ca824e0sf /* Something horribly wrong happened. Someone didn't block! */
5400544d62947907986d570435dd16f02ca824e0sf const char *str;
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* If we see an EOS, don't bother doing anything more. */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim if (len == 0) {
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* no use attempting a zero-byte alloc (hurts when
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * using --with-efence --enable-pool-debug) or
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * doing any of the other logic either
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* Would this overrun our buffer? If so, we'll die. */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* Do we have to handle the allocation ourselves? */
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim /* We'll assume the common case where one bucket is enough. */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* Increase the buffer size */
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim /* Copy what we already had. */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* Just copy the rest of the data to the end of the old buffer. */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* We've now processed that new data - update accordingly. */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* We no longer need the returned brigade. */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* We likely aborted early before reading anything or we read no
36ef8f77bffe75d1aa327882be1b5bdbe2ff567asf * data. Technically, this might be success condition. But,
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * probably means something is horribly wrong. For now, we'll
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * treat this as APR_SUCCESS, but it may be worth re-examining.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* If we didn't get a full line of input, try again. */
if (bytes_handled < n) {
char *tmp;
if (do_alloc) {
return rv;
char *new_buffer;
*s = new_buffer;
return APR_ENOSPC;
--pos;
--pos;
const char *str;
return rv;
return APR_SUCCESS;
if (APR_BUCKET_IS_EOS(e)) {
return APR_SUCCESS;
return rv;
c = *str;
if (bytes_handled < n) {
char *tmp;
if (do_alloc) {
return rv;
char *new_buffer;
*s = new_buffer;
return APR_SUCCESS;
return APR_ENOSPC;
return APR_SUCCESS;
int fold)
return rv;
char *tmp_s = s;
return (int)len;
* This will prevent "http://www.wherever.com/..\..\/" from
const char *ll;
const char *uri;
const char *pro;
&len, r, 0);
} while (len <= 0);
r->method);
if (ll[0]) {
r->assbackwards = 0;
char* field;
char *value;
int fields_read = 0;
if (len == 0) {
++value;
request_rec *r;
apr_pool_t *p;
const char *expect;
int access_status;
r->pool = p;
r->read_length = 0;
if (!read_request_line(r)) {
ap_send_error_response(r, 0);
return NULL;
if (!r->assbackwards) {
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;
apr_bucket *b;
while (r->next) {
r = r->next;
if (!r->eos_sent) {
if (type) {
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;
struct content_length_ctx {
int compute_len;
request_rec *r = f->r;
apr_bucket *e;
more = b;
while (more) {
b = more;
flush = 0;
APR_BRIGADE_FOREACH(e, b) {
const char *ignored;
len = 0;
if (APR_BUCKET_IS_EOS(e)) {
else if (APR_BUCKET_IS_FLUSH(e)) {
if (partial_send_okay) {
split = b;
if (partial_send_okay) {
split = b;
if (partial_send_okay) {
split = b;
return rv;
if (split) {
if (flush) {
return rv;
if (!eos) {
apr_bucket *b;
return rv;
#if APR_HAS_MMAP
apr_bucket *b;
ap_filter_t *f;
if (len == 0)
return APR_SUCCESS;
if (f == NULL) {
f = r->output_filters;
if (f != r->output_filters) {
char c2 = (char)c;
return len;
return nbyte;
struct ap_vrprintf_data {
request_rec *r;
char *buff;
* vformatter needs to write into buff and buff.curpos > buff.endpos */
return APR_SUCCESS;
vd.r = r;
written += n;
return written;
if (s == NULL)
return written;
apr_bucket *b;
if (!r->assbackwards) {
(const request_rec *r), (r), 0)