util.c revision 313c284b8ad24b5119cca6dd6e08eb330f3f63a7
0066eddda7203f6345b56f77d146a759298dc635gryzor/* ====================================================================
0066eddda7203f6345b56f77d146a759298dc635gryzor * The Apache Software License, Version 1.1
a025329610d2b832bb62bc34dd328985e14e8718lgentis * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
0066eddda7203f6345b56f77d146a759298dc635gryzor * reserved.
0066eddda7203f6345b56f77d146a759298dc635gryzor * Redistribution and use in source and binary forms, with or without
0066eddda7203f6345b56f77d146a759298dc635gryzor * modification, are permitted provided that the following conditions
0066eddda7203f6345b56f77d146a759298dc635gryzor * 1. Redistributions of source code must retain the above copyright
0066eddda7203f6345b56f77d146a759298dc635gryzor * notice, this list of conditions and the following disclaimer.
0066eddda7203f6345b56f77d146a759298dc635gryzor * 2. Redistributions in binary form must reproduce the above copyright
0066eddda7203f6345b56f77d146a759298dc635gryzor * notice, this list of conditions and the following disclaimer in
0066eddda7203f6345b56f77d146a759298dc635gryzor * the documentation and/or other materials provided with the
0066eddda7203f6345b56f77d146a759298dc635gryzor * distribution.
0066eddda7203f6345b56f77d146a759298dc635gryzor * 3. The end-user documentation included with the redistribution,
0066eddda7203f6345b56f77d146a759298dc635gryzor * if any, must include the following acknowledgment:
0066eddda7203f6345b56f77d146a759298dc635gryzor * "This product includes software developed by the
0066eddda7203f6345b56f77d146a759298dc635gryzor * Apache Software Foundation (http://www.apache.org/)."
0066eddda7203f6345b56f77d146a759298dc635gryzor * Alternately, this acknowledgment may appear in the software itself,
0066eddda7203f6345b56f77d146a759298dc635gryzor * if and wherever such third-party acknowledgments normally appear.
0066eddda7203f6345b56f77d146a759298dc635gryzor * 4. The names "Apache" and "Apache Software Foundation" must
0066eddda7203f6345b56f77d146a759298dc635gryzor * not be used to endorse or promote products derived from this
0066eddda7203f6345b56f77d146a759298dc635gryzor * software without prior written permission. For written
0066eddda7203f6345b56f77d146a759298dc635gryzor * permission, please contact apache@apache.org.
0066eddda7203f6345b56f77d146a759298dc635gryzor * 5. Products derived from this software may not be called "Apache",
0066eddda7203f6345b56f77d146a759298dc635gryzor * nor may "Apache" appear in their name, without prior written
0066eddda7203f6345b56f77d146a759298dc635gryzor * permission of the Apache Software Foundation.
0066eddda7203f6345b56f77d146a759298dc635gryzor * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0066eddda7203f6345b56f77d146a759298dc635gryzor * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0066eddda7203f6345b56f77d146a759298dc635gryzor * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0066eddda7203f6345b56f77d146a759298dc635gryzor * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0066eddda7203f6345b56f77d146a759298dc635gryzor * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0066eddda7203f6345b56f77d146a759298dc635gryzor * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0066eddda7203f6345b56f77d146a759298dc635gryzor * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0066eddda7203f6345b56f77d146a759298dc635gryzor * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0066eddda7203f6345b56f77d146a759298dc635gryzor * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0066eddda7203f6345b56f77d146a759298dc635gryzor * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0066eddda7203f6345b56f77d146a759298dc635gryzor * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0066eddda7203f6345b56f77d146a759298dc635gryzor * SUCH DAMAGE.
a025329610d2b832bb62bc34dd328985e14e8718lgentis * ====================================================================
0066eddda7203f6345b56f77d146a759298dc635gryzor * This software consists of voluntary contributions made by many
9f47982d4f9350397f1f62f04f1ba744ad5b6fa5lgentis * individuals on behalf of the Apache Software Foundation. For more
9f47982d4f9350397f1f62f04f1ba744ad5b6fa5lgentis * information on the Apache Software Foundation, please see
0066eddda7203f6345b56f77d146a759298dc635gryzor** DAV extension module for Apache 2.0.*
0066eddda7203f6345b56f77d146a759298dc635gryzor** - various utilities, repository-independent
0066eddda7203f6345b56f77d146a759298dc635gryzorDAV_DECLARE(dav_error*) dav_new_error(apr_pool_t *p, int status,
0066eddda7203f6345b56f77d146a759298dc635gryzor /* DBG3("dav_new_error: %d %d %s", status, error_id, desc ? desc : "(no desc)"); */
0066eddda7203f6345b56f77d146a759298dc635gryzorDAV_DECLARE(dav_error*) dav_push_error(apr_pool_t *p, int status,
a025329610d2b832bb62bc34dd328985e14e8718lgentisDAV_DECLARE(void) dav_check_bufsize(apr_pool_t * p, dav_buffer *pbuf,
0066eddda7203f6345b56f77d146a759298dc635gryzor /* grow the buffer if necessary */
0066eddda7203f6345b56f77d146a759298dc635gryzor if (pbuf->cur_len + extra_needed > pbuf->alloc_len) {
0066eddda7203f6345b56f77d146a759298dc635gryzorDAV_DECLARE(void) dav_set_bufsize(apr_pool_t * p, dav_buffer *pbuf,
0066eddda7203f6345b56f77d146a759298dc635gryzor /* NOTE: this does not retain prior contents */
0066eddda7203f6345b56f77d146a759298dc635gryzor /* NOTE: this function is used to init the first pointer, too, since
0066eddda7203f6345b56f77d146a759298dc635gryzor the PAD will be larger than alloc_len (0) for zeroed structures */
0066eddda7203f6345b56f77d146a759298dc635gryzor /* grow if we don't have enough for the requested size plus padding */
0066eddda7203f6345b56f77d146a759298dc635gryzor /* set the new length; min of MINSIZE */
0066eddda7203f6345b56f77d146a759298dc635gryzor/* initialize a buffer and copy the specified (null-term'd) string into it */
784fd1e5958e08cf05cd929c6e6b117b06adc2cflgentisDAV_DECLARE(void) dav_buffer_init(apr_pool_t *p, dav_buffer *pbuf,
784fd1e5958e08cf05cd929c6e6b117b06adc2cflgentis const char *str)
784fd1e5958e08cf05cd929c6e6b117b06adc2cflgentis/* append a string to the end of the buffer, adjust length */
784fd1e5958e08cf05cd929c6e6b117b06adc2cflgentisDAV_DECLARE(void) dav_buffer_append(apr_pool_t *p, dav_buffer *pbuf,
0066eddda7203f6345b56f77d146a759298dc635gryzor const char *str)
0066eddda7203f6345b56f77d146a759298dc635gryzor/* place a string on the end of the buffer, do NOT adjust length */
0066eddda7203f6345b56f77d146a759298dc635gryzorDAV_DECLARE(void) dav_buffer_place(apr_pool_t *p, dav_buffer *pbuf,
0066eddda7203f6345b56f77d146a759298dc635gryzor const char *str)
0066eddda7203f6345b56f77d146a759298dc635gryzor/* place some memory on the end of a buffer; do NOT adjust length */
0066eddda7203f6345b56f77d146a759298dc635gryzorDAV_DECLARE(void) dav_buffer_place_mem(apr_pool_t *p, dav_buffer *pbuf,
0066eddda7203f6345b56f77d146a759298dc635gryzor** dav_lookup_uri()
0066eddda7203f6345b56f77d146a759298dc635gryzor** Extension for ap_sub_req_lookup_uri() which can't handle absolute
0066eddda7203f6345b56f77d146a759298dc635gryzor** URIs properly.
0066eddda7203f6345b56f77d146a759298dc635gryzor** If NULL is returned, then an error occurred with parsing the URI or
0066eddda7203f6345b56f77d146a759298dc635gryzor** the URI does not match the current server.
0066eddda7203f6345b56f77d146a759298dc635gryzordav_lookup_result dav_lookup_uri(const char *uri, request_rec * r)
0066eddda7203f6345b56f77d146a759298dc635gryzor const char *scheme;
0066eddda7203f6345b56f77d146a759298dc635gryzor const char *domain;
0066eddda7203f6345b56f77d146a759298dc635gryzor /* first thing to do is parse the URI into various components */
0066eddda7203f6345b56f77d146a759298dc635gryzor if (ap_parse_uri_components(r->pool, uri, &comp) != HTTP_OK) {
0066eddda7203f6345b56f77d146a759298dc635gryzor result.err.desc = "Invalid syntax in Destination URI.";
0066eddda7203f6345b56f77d146a759298dc635gryzor /* the URI must be an absoluteURI (WEBDAV S9.3) */
784fd1e5958e08cf05cd929c6e6b117b06adc2cflgentis result.err.desc = "Destination URI must be an absolute URI.";
0066eddda7203f6345b56f77d146a759298dc635gryzor /* ### not sure this works if the current request came in via https: */
784fd1e5958e08cf05cd929c6e6b117b06adc2cflgentis /* now, verify that the URI uses the same scheme as the current request.
0066eddda7203f6345b56f77d146a759298dc635gryzor the port, must match our port.
d28e54f867ab1292ce75324d90680396c1d5f47dlgentis the URI must not have a query (args) or a fragment
0066eddda7203f6345b56f77d146a759298dc635gryzor apr_sockaddr_port_get(&port, r->connection->local_addr);
0066eddda7203f6345b56f77d146a759298dc635gryzor "Destination URI refers to different "
0066eddda7203f6345b56f77d146a759298dc635gryzor "scheme or port (%s://hostname:%d)"
a025329610d2b832bb62bc34dd328985e14e8718lgentis "Destination URI contains invalid components "
0066eddda7203f6345b56f77d146a759298dc635gryzor "(a query or a fragment).";
70d39834fda98ce22bd29dc44c5fae5c9abe3a06humbedooh /* we have verified the scheme, port, and general structure */
784fd1e5958e08cf05cd929c6e6b117b06adc2cflgentis ** Hrm. IE5 will pass unqualified hostnames for both the
0066eddda7203f6345b56f77d146a759298dc635gryzor ** Host: and Destination: headers. This breaks the
0066eddda7203f6345b56f77d146a759298dc635gryzor ** http_vhost.c::matches_aliases function.
0066eddda7203f6345b56f77d146a759298dc635gryzor ** For now, qualify unqualified comp.hostnames with
0066eddda7203f6345b56f77d146a759298dc635gryzor ** r->server->server_hostname.
0066eddda7203f6345b56f77d146a759298dc635gryzor ** ### this is a big hack. Apache should provide a better way.
0066eddda7203f6345b56f77d146a759298dc635gryzor ** ### maybe the admin should list the unqualified hosts in a
0066eddda7203f6345b56f77d146a759298dc635gryzor ** ### <ServerAlias> block?
0066eddda7203f6345b56f77d146a759298dc635gryzor (domain = strchr(r->server->server_hostname, '.')) != NULL) {
0066eddda7203f6345b56f77d146a759298dc635gryzor comp.hostname = apr_pstrcat(r->pool, comp.hostname, domain, NULL);
0066eddda7203f6345b56f77d146a759298dc635gryzor /* now, if a hostname was provided, then verify that it represents the
0066eddda7203f6345b56f77d146a759298dc635gryzor same server as the current connection. note that we just use our
a025329610d2b832bb62bc34dd328985e14e8718lgentis port, since we've verified the URI matches ours */
0066eddda7203f6345b56f77d146a759298dc635gryzor result.err.desc = "Destination URI refers to a different server.";
0066eddda7203f6345b56f77d146a759298dc635gryzor /* we have verified that the requested URI denotes the same server as
0066eddda7203f6345b56f77d146a759298dc635gryzor the current request. Therefore, we can use ap_sub_req_lookup_uri() */
70d39834fda98ce22bd29dc44c5fae5c9abe3a06humbedooh /* reconstruct a URI as just the path */
70d39834fda98ce22bd29dc44c5fae5c9abe3a06humbedooh new_file = ap_unparse_uri_components(r->pool, &comp, UNP_OMITSITEPART);
0066eddda7203f6345b56f77d146a759298dc635gryzor * Lookup the URI and return the sub-request. Note that we use the
0066eddda7203f6345b56f77d146a759298dc635gryzor * same HTTP method on the destination. This allows the destination
0066eddda7203f6345b56f77d146a759298dc635gryzor * to apply appropriate restrictions (e.g. readonly).
0066eddda7203f6345b56f77d146a759298dc635gryzor result.rnew = ap_sub_req_method_uri(r->method, new_file, r, NULL);
0066eddda7203f6345b56f77d146a759298dc635gryzor/* ---------------------------------------------------------------
0066eddda7203f6345b56f77d146a759298dc635gryzor** XML UTILITY FUNCTIONS
0066eddda7203f6345b56f77d146a759298dc635gryzor/* validate that the root element uses a given DAV: tagname (TRUE==valid) */
0066eddda7203f6345b56f77d146a759298dc635gryzorint dav_validate_root(const ap_xml_doc *doc, const char *tagname)
a025329610d2b832bb62bc34dd328985e14e8718lgentis/* find and return the (unique) child with a given DAV: tagname */
0066eddda7203f6345b56f77d146a759298dc635gryzorap_xml_elem *dav_find_child(const ap_xml_elem *elem, const char *tagname)
784fd1e5958e08cf05cd929c6e6b117b06adc2cflgentis if (child->ns == AP_XML_NS_DAV_ID && !strcmp(child->name, tagname))
0066eddda7203f6345b56f77d146a759298dc635gryzor/* gather up all the CDATA into a single string */
0066eddda7203f6345b56f77d146a759298dc635gryzorconst char *dav_xml_get_cdata(const ap_xml_elem *elem, apr_pool_t *pool,
s += tlen;
s += tlen;
++cdata;
return cdata;
return DAV_TIMEOUT_INFINITE;
return DAV_TIMEOUT_INFINITE;
return DAV_TIMEOUT_INFINITE;
return NULL;
return ih;
const char *state_token,
if (t == dav_if_opaquelock) {
return err;
return NULL;
char *sp;
char *token;
token++;
return NULL;
return token;
char *str;
char *list;
const char *state_token;
int condition;
return NULL;
while (*str) {
switch(*str) {
while (*list) {
switch (*list) {
return err;
return err;
list++;
str++;
return NULL;
int flags,
request_rec *r)
const char *uri;
const char *etag;
int num_matched;
int num_that_apply;
int seen_locktoken;
return dav_push_error(p,
err);
if (seen_locktoken)
return NULL;
return NULL;
num_that_apply = 0;
case dav_if_etag:
reason =
goto state_list_failed;
&& !mismatch) {
reason =
goto state_list_failed;
case dav_if_opaquelock:
reason =
goto state_list_failed;
num_matched = 0;
reason =
goto state_list_failed;
(!r->user ||
const char *errmsg;
r->user,
if (num_matched == 0
reason =
goto state_list_failed;
if (seen_locktoken) {
return NULL;
if (num_that_apply == 0) {
if (seen_locktoken)
return NULL;
locks_hooks)) {
return NULL;
apr_psprintf(p,
return NULL;
return NULL;
return err;
return NULL;
int result;
int lock_db_opened_locally = 0;
#if DAV_DEBUG
return err;
return err;
ctx.r = r;
&work_buf, r);
return err;
return err;
return NULL;
--idx;
return s2;
NULL);
/* see mod_dav.h for docco */
int parent_only,
const char *body;
return err;
return NULL;
!= NULL)
if (!parent_only) {
return NULL;
!= NULL)
return NULL;
/* see mod_dav.h for docco */
request_rec *r,
int undo,
const char *body;
if (undo)
if (undo)
return NULL;