http_protocol.c revision c13d541615044010381184f9edf948c0a4c6723e
842ae4bd224140319ae7feec1872b93dfd491143fielding/* ====================================================================
842ae4bd224140319ae7feec1872b93dfd491143fielding * The Apache Software License, Version 1.1
842ae4bd224140319ae7feec1872b93dfd491143fielding * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
842ae4bd224140319ae7feec1872b93dfd491143fielding * reserved.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Redistribution and use in source and binary forms, with or without
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * modification, are permitted provided that the following conditions
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * 1. Redistributions of source code must retain the above copyright
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * notice, this list of conditions and the following disclaimer.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * 2. Redistributions in binary form must reproduce the above copyright
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * notice, this list of conditions and the following disclaimer in
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the documentation and/or other materials provided with the
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh * distribution.
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh * 3. The end-user documentation included with the redistribution,
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh * if any, must include the following acknowledgment:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * "This product includes software developed by the
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Apache Software Foundation (http://www.apache.org/)."
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Alternately, this acknowledgment may appear in the software itself,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * if and wherever such third-party acknowledgments normally appear.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * 4. The names "Apache" and "Apache Software Foundation" must
396aeca634b86a3ab34d5bdb9c32cbce73c72421jerenkrantz * not be used to endorse or promote products derived from this
396aeca634b86a3ab34d5bdb9c32cbce73c72421jerenkrantz * software without prior written permission. For written
396aeca634b86a3ab34d5bdb9c32cbce73c72421jerenkrantz * permission, please contact apache@apache.org.
396aeca634b86a3ab34d5bdb9c32cbce73c72421jerenkrantz * 5. Products derived from this software may not be called "Apache",
396aeca634b86a3ab34d5bdb9c32cbce73c72421jerenkrantz * nor may "Apache" appear in their name, without prior written
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * permission of the Apache Software Foundation.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
5bf029f8452b6aa105cf3d9d9b19221920725428rbb * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
5bf029f8452b6aa105cf3d9d9b19221920725428rbb * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5bf029f8452b6aa105cf3d9d9b19221920725428rbb * SUCH DAMAGE.
5bf029f8452b6aa105cf3d9d9b19221920725428rbb * ====================================================================
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * This software consists of voluntary contributions made by many
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * individuals on behalf of the Apache Software Foundation. For more
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * information on the Apache Software Foundation, please see
5bf029f8452b6aa105cf3d9d9b19221920725428rbb * Portions of this software are based upon public domain software
5bf029f8452b6aa105cf3d9d9b19221920725428rbb * originally written at the National Center for Supercomputing Applications,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * University of Illinois, Urbana-Champaign.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * http_protocol.c --- routines which directly communicate with the client.
742318b93e89c311f66b55f426c4d9cf2c14628bjim * Code originally by Rob McCool; much redone by Robert S. Thau
742318b93e89c311f66b55f426c4d9cf2c14628bjim * and the Apache Software Foundation.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "http_log.h" /* For errors detected in basic auth common
5bf029f8452b6aa105cf3d9d9b19221920725428rbb * support code... */
396aeca634b86a3ab34d5bdb9c32cbce73c72421jerenkrantz#include "apr_date.h" /* For apr_date_parse_http and APR_DATE_BAD */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_table_get(r->headers_out, "Connection"), "close");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *conn = apr_table_get(r->headers_in, "Connection");
|| 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;
* 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;
return NULL;
struct dechunk_ctx {
} state;
static long get_chunk_size(char *);
apr_bucket *b;
const char *buf;
if (!ctx) {
return rv;
case WANT_HDR:
case WANT_TRL:
b = apr_bucket_eos_create();
return APR_SUCCESS;
return rv;
b = APR_BUCKET_NEXT(b);
return APR_SUCCESS;
typedef struct http_filter_ctx {
} http_ctx_t;
apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes)
apr_bucket *e;
char *buff;
char *pos;
if (!ctx) {
apr_bucket *e;
const char *str;
e = NULL;
return APR_EOF;
const char *c = str;
if (*c == APR_ASCII_LF)
else return APR_SUCCESS;
return rv;
if (*readbytes) {
const char *ignore;
return rv;
if (len) {
*readbytes = 0;
APR_BRIGADE_INSERT_TAIL(b, e);
if (*readbytes == 0) {
return APR_SUCCESS;
return rv;
APR_BRIGADE_INSERT_TAIL(b, e);
return APR_SUCCESS;
APR_BRIGADE_INSERT_TAIL(b, e);
return APR_SUCCESS;
* The number of status lines must equal the value of RESPONSE_CODES (httpd.h)
#ifdef UTS21
int i, pos;
return LEVEL_500;
return pos;
typedef struct header_struct {
* In other words, don't change this one without checking table_do in alloc.c.
char *headfield;
const char **protocol)
if (r->assbackwards) {
if (!r->status_line)
const char *protocol)
char *tmp;
if (r->assbackwards) {
const char *protocol;
char *list;
int mask;
NULL);
int rv;
while (r->prev)
r = r->prev;
return rv;
h.bb = b;
apr_table_do((int (*) (void *, const char *, const char *))
return OK;
if (r->assbackwards)
return DECLINED;
return OK;
* consisting of comma/space-separated tokens.
char *start;
char **strpp;
start = e;
++i, ++strpp) {
ap_filter_t *f,
request_rec *r = f->r;
const char *clheader;
const char *protocol;
apr_bucket *e;
APR_BRIGADE_FOREACH(e, b) {
return AP_FILTER_ERROR;
if (r->assbackwards) {
r->bytes_sent = 0;
r->headers_out);
fixup_vary(r);
ap_set_keepalive(r);
if (r->chunked) {
r->content_type));
if (r->content_encoding) {
r->content_encoding);
else if (r->content_language) {
r->content_language);
if (r->header_only &&
(void *) &h, r->headers_out,
NULL);
if (r->header_only) {
return OK;
if (r->chunked) {
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 AP_DEBUG
&core_module);
return OK;
char *tmp;
apr_bucket *e;
e = apr_bucket_flush_create();
static long get_chunk_size(char *b)
long chunksize = 0;
while (apr_isxdigit(*b)) {
int xvalue = 0;
return chunksize;
const char *tempbuf;
&core_module);
total = 0;
&& !APR_BUCKET_IS_EOS(b)) {
old = b;
b = APR_BUCKET_NEXT(b);
return total;
int rv;
return rv;
if (r->expecting_100) {
return OK;
if (rv < 0)
return HTTP_BAD_REQUEST;
return OK;
const char *prefix,
const char *key,
const char *suffix)
return result;
request_rec *r,
const char *location)
switch (status) {
case HTTP_MOVED_PERMANENTLY:
case HTTP_MOVED_TEMPORARILY:
case HTTP_TEMPORARY_REDIRECT:
return(apr_pstrcat(p,
NULL));
case HTTP_SEE_OTHER:
return(apr_pstrcat(p,
NULL));
case HTTP_USE_PROXY:
return(apr_pstrcat(p,
NULL));
case HTTP_UNAUTHORIZED:
case HTTP_BAD_REQUEST:
return(add_optional_notes(r,
case HTTP_FORBIDDEN:
return(apr_pstrcat(p,
NULL));
case HTTP_NOT_FOUND:
return(apr_pstrcat(p,
NULL));
case HTTP_METHOD_NOT_ALLOWED:
return(apr_pstrcat(p,
NULL));
case HTTP_NOT_ACCEPTABLE:
NULL);
case HTTP_MULTIPLE_CHOICES:
case HTTP_LENGTH_REQUIRED:
r->method,
NULL);
case HTTP_PRECONDITION_FAILED:
return(apr_pstrcat(p,
NULL));
case HTTP_NOT_IMPLEMENTED:
NULL);
case HTTP_BAD_GATEWAY:
case HTTP_VARIANT_ALSO_VARIES:
return(apr_pstrcat(p,
NULL));
case HTTP_REQUEST_TIME_OUT:
case HTTP_GONE:
return(apr_pstrcat(p,
NULL));
return(apr_pstrcat(p,
r->method,
NULL));
case HTTP_EXPECTATION_FAILED:
return(apr_pstrcat(p,
NULL));
case HTTP_LOCKED:
case HTTP_FAILED_DEPENDENCY:
case HTTP_SERVICE_UNAVAILABLE:
case HTTP_GATEWAY_TIME_OUT:
case HTTP_NOT_EXTENDED:
return(apr_pstrcat(p,
NULL));
char *custom_response;
r->eos_sent = 0;
reset_filters(r);
if (!r->assbackwards) {
r->clength = 0;
if (r->header_only) {
r = r->prev;
const char *h1;
NULL);
NULL);
if (recursive_error) {
return ml;
char **imethods;
char **omethods;
int mnum),
void *rec,
const char *mname,
int mnum),
int methnum;
char **methods;
int methnum;
const char **xmethod;
char **methods;
const char *method)
int methnum;
char **methods;
l->method_mask = 0;
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++;
if (!dash)
dash++;
if (*dash)
if (*start < 0)
*start = 0;
typedef struct byterange_ctx {
int num_ranges;
const char *orig_ct;
* 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;
ap_filter_t *f,
request_rec *r = f->r;
apr_bucket *e;
char *current;
char *bound_head;
int found = 0;
if (!ctx) {
e = apr_bucket_eos_create();
if (num_ranges == 0) {
r->content_type =
return APR_SUCCESS;
NULL);
char *ts;
ec = e;
const char *str;
if (found == 0) {
return HTTP_RANGE_NOT_SATISFIABLE;
char *end;
e = apr_bucket_eos_create();
const char *range;
const char *if_range;
const char *match;
const char *ct;
int num_ranges;
if (r->assbackwards)
* send multipart/x-byteranges instead of multipart/byteranges for
int rv;
return rv;
NULL));
return num_ranges;