⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_dav.c

📁 最新apache的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as * applicable. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * DAV extension module for Apache 2.0.* * * This module is repository-independent. It depends on hooks provided by a * repository implementation. * * APACHE ISSUES: *   - within a DAV hierarchy, if an unknown method is used and we default *     to Apache's implementation, it sends back an OPTIONS with the wrong *     set of methods -- there is NO HOOK for us. *     therefore: we need to manually handle the HTTP_METHOD_NOT_ALLOWED *       and HTTP_NOT_IMPLEMENTED responses (not ap_send_error_response). *   - process_mkcol_body() had to dup code from ap_setup_client_block(). *   - it would be nice to get status lines from Apache for arbitrary *     status codes *   - it would be nice to be able to extend Apache's set of response *     codes so that it doesn't return 500 when an unknown code is placed *     into r->status. *   - http_vhost functions should apply "const" to their params * * DESIGN NOTES: *   - For PROPFIND, we batch up the entire response in memory before *     sending it. We may want to reorganize around sending the information *     as we suck it in from the propdb. Alternatively, we should at least *     generate a total Content-Length if we're going to buffer in memory *     so that we can keep the connection open. */#include "apr_strings.h"#include "apr_lib.h"            /* for apr_is* */#define APR_WANT_STRFUNC#include "apr_want.h"#include "httpd.h"#include "http_config.h"#include "http_core.h"#include "http_log.h"#include "http_main.h"#include "http_protocol.h"#include "http_request.h"#include "util_script.h"#include "mod_dav.h"/* ### what is the best way to set this? */#define DAV_DEFAULT_PROVIDER    "filesystem"/* used to denote that mod_dav will be handling this request */#define DAV_HANDLER_NAME "dav-handler"enum {    DAV_ENABLED_UNSET = 0,    DAV_ENABLED_OFF,    DAV_ENABLED_ON};/* per-dir configuration */typedef struct {    const char *provider_name;    const dav_provider *provider;    const char *dir;    int locktimeout;    int allow_depthinfinity;} dav_dir_conf;/* per-server configuration */typedef struct {    int unused;} dav_server_conf;#define DAV_INHERIT_VALUE(parent, child, field) \                ((child)->field ? (child)->field : (parent)->field)/* forward-declare for use in configuration lookup */extern module DAV_DECLARE_DATA dav_module;/* DAV methods */enum {    DAV_M_BIND = 0,    DAV_M_SEARCH,    DAV_M_LAST};static int dav_methods[DAV_M_LAST];static int dav_init_handler(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,                             server_rec *s){    /* DBG0("dav_init_handler"); */    /* Register DAV methods */    dav_methods[DAV_M_BIND] = ap_method_register(p, "BIND");    dav_methods[DAV_M_SEARCH] = ap_method_register(p, "SEARCH");    ap_add_version_component(p, "DAV/2");    return OK;}static void *dav_create_server_config(apr_pool_t *p, server_rec *s){    dav_server_conf *newconf;    newconf = (dav_server_conf *)apr_pcalloc(p, sizeof(*newconf));    /* ### this isn't used at the moment... */    return newconf;}static void *dav_merge_server_config(apr_pool_t *p, void *base, void *overrides){#if 0    dav_server_conf *child = overrides;#endif    dav_server_conf *newconf;    newconf = (dav_server_conf *)apr_pcalloc(p, sizeof(*newconf));    /* ### nothing to merge right now... */    return newconf;}static void *dav_create_dir_config(apr_pool_t *p, char *dir){    /* NOTE: dir==NULL creates the default per-dir config */    dav_dir_conf *conf;    conf = (dav_dir_conf *)apr_pcalloc(p, sizeof(*conf));    /* clean up the directory to remove any trailing slash */    if (dir != NULL) {        char *d;        apr_size_t l;        d = apr_pstrdup(p, dir);        l = strlen(d);        if (l > 1 && d[l - 1] == '/')            d[l - 1] = '\0';        conf->dir = d;    }    return conf;}static void *dav_merge_dir_config(apr_pool_t *p, void *base, void *overrides){    dav_dir_conf *parent = base;    dav_dir_conf *child = overrides;    dav_dir_conf *newconf = (dav_dir_conf *)apr_pcalloc(p, sizeof(*newconf));    /* DBG3("dav_merge_dir_config: new=%08lx  base=%08lx  overrides=%08lx",       (long)newconf, (long)base, (long)overrides); */    newconf->provider_name = DAV_INHERIT_VALUE(parent, child, provider_name);    newconf->provider = DAV_INHERIT_VALUE(parent, child, provider);    if (parent->provider_name != NULL) {        if (child->provider_name == NULL) {            ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,                         "\"DAV Off\" cannot be used to turn off a subtree "                         "of a DAV-enabled location.");        }        else if (strcasecmp(child->provider_name,                            parent->provider_name) != 0) {            ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,                         "A subtree cannot specify a different DAV provider "                         "than its parent.");        }    }    newconf->locktimeout = DAV_INHERIT_VALUE(parent, child, locktimeout);    newconf->dir = DAV_INHERIT_VALUE(parent, child, dir);    newconf->allow_depthinfinity = DAV_INHERIT_VALUE(parent, child,                                                     allow_depthinfinity);    return newconf;}static const dav_provider *dav_get_provider(request_rec *r){    dav_dir_conf *conf;    conf = ap_get_module_config(r->per_dir_config, &dav_module);    /* assert: conf->provider_name != NULL       (otherwise, DAV is disabled, and we wouldn't be here) */    /* assert: conf->provider != NULL       (checked when conf->provider_name is set) */    return conf->provider;}DAV_DECLARE(const dav_hooks_locks *) dav_get_lock_hooks(request_rec *r){    return dav_get_provider(r)->locks;}DAV_DECLARE(const dav_hooks_propdb *) dav_get_propdb_hooks(request_rec *r){    return dav_get_provider(r)->propdb;}DAV_DECLARE(const dav_hooks_vsn *) dav_get_vsn_hooks(request_rec *r){    return dav_get_provider(r)->vsn;}DAV_DECLARE(const dav_hooks_binding *) dav_get_binding_hooks(request_rec *r){    return dav_get_provider(r)->binding;}DAV_DECLARE(const dav_hooks_search *) dav_get_search_hooks(request_rec *r){    return dav_get_provider(r)->search;}/* * Command handler for the DAV directive, which is TAKE1. */static const char *dav_cmd_dav(cmd_parms *cmd, void *config, const char *arg1){    dav_dir_conf *conf = (dav_dir_conf *)config;    if (strcasecmp(arg1, "on") == 0) {        conf->provider_name = DAV_DEFAULT_PROVIDER;    }    else if (strcasecmp(arg1, "off") == 0) {        conf->provider_name = NULL;        conf->provider = NULL;    }    else {        conf->provider_name = apr_pstrdup(cmd->pool, arg1);    }    if (conf->provider_name != NULL) {        /* lookup and cache the actual provider now */        conf->provider = dav_lookup_provider(conf->provider_name);        if (conf->provider == NULL) {            /* by the time they use it, the provider should be loaded and               registered with us. */            return apr_psprintf(cmd->pool,                                "Unknown DAV provider: %s",                                conf->provider_name);        }    }    return NULL;}/* * Command handler for the DAVDepthInfinity directive, which is FLAG. */static const char *dav_cmd_davdepthinfinity(cmd_parms *cmd, void *config,                                            int arg){    dav_dir_conf *conf = (dav_dir_conf *)config;    if (arg)        conf->allow_depthinfinity = DAV_ENABLED_ON;    else        conf->allow_depthinfinity = DAV_ENABLED_OFF;    return NULL;}/* * Command handler for DAVMinTimeout directive, which is TAKE1 */static const char *dav_cmd_davmintimeout(cmd_parms *cmd, void *config,                                         const char *arg1){    dav_dir_conf *conf = (dav_dir_conf *)config;    conf->locktimeout = atoi(arg1);    if (conf->locktimeout < 0)        return "DAVMinTimeout requires a non-negative integer.";    return NULL;}/*** dav_error_response()**** Send a nice response back to the user. In most cases, Apache doesn't** allow us to provide details in the body about what happened. This** function allows us to completely specify the response body.**** ### this function is not logging any errors! (e.g. the body)*/static int dav_error_response(request_rec *r, int status, const char *body){    r->status = status;    /* ### I really don't think this is needed; gotta test */    r->status_line = ap_get_status_line(status);    ap_set_content_type(r, "text/html");    /* begin the response now... */    ap_rvputs(r,              DAV_RESPONSE_BODY_1,              r->status_line,              DAV_RESPONSE_BODY_2,              &r->status_line[4],              DAV_RESPONSE_BODY_3,              body,              DAV_RESPONSE_BODY_4,              ap_psignature("<hr />\n", r),              DAV_RESPONSE_BODY_5,              NULL);    /* the response has been sent. */    /*     * ### Use of DONE obviates logging..!     */    return DONE;}/* * Send a "standardized" error response based on the error's namespace & tag */static int dav_error_response_tag(request_rec *r,                                  dav_error *err){    r->status = err->status;    /* ### I really don't think this is needed; gotta test */    r->status_line = ap_get_status_line(err->status);    ap_set_content_type(r, DAV_XML_CONTENT_TYPE);    ap_rputs(DAV_XML_HEADER DEBUG_CR             "<D:error xmlns:D=\"DAV:\"", r);    if (err->desc != NULL) {        /* ### should move this namespace somewhere (with the others!) */        ap_rputs(" xmlns:m=\"http://apache.org/dav/xmlns\"", r);    }    if (err->namespace != NULL) {        ap_rprintf(r,                   " xmlns:C=\"%s\">" DEBUG_CR                   "<C:%s/>" DEBUG_CR,                   err->namespace, err->tagname);    }    else {        ap_rprintf(r,                   ">" DEBUG_CR                   "<D:%s/>" DEBUG_CR, err->tagname);    }    /* here's our mod_dav specific tag: */    if (err->desc != NULL) {        ap_rprintf(r,                   "<m:human-readable errcode=\"%d\">" DEBUG_CR                   "%s" DEBUG_CR                   "</m:human-readable>" DEBUG_CR,                   err->error_id,                   apr_xml_quote_string(r->pool, err->desc, 0));    }    ap_rputs("</D:error>" DEBUG_CR, r);    /* the response has been sent. */    /*     * ### Use of DONE obviates logging..!     */    return DONE;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -