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

📄 mod_dav.c

📁 最新apache的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        return result;    }    /* note: doc == NULL if no request body */    if (doc && !dav_validate_root(doc, "options")) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "The \"options\" element was not found.");        return HTTP_BAD_REQUEST;    }    /* determine which providers are available */    dav_level = "1";    if (locks_hooks != NULL) {        dav_level = "1,2";    }    if (binding_hooks != NULL)        dav_level = apr_pstrcat(r->pool, dav_level, ",bindings", NULL);    /* ###     * MSFT Web Folders chokes if length of DAV header value > 63 characters!     * To workaround that, we use separate DAV headers for versioning and     * live prop provider namespace URIs.     * ###     */    apr_table_setn(r->headers_out, "DAV", dav_level);    /*     * If there is a versioning provider, generate DAV headers     * for versioning options.     */    if (vsn_hooks != NULL) {        (*vsn_hooks->get_vsn_options)(r->pool, &vsn_options);        for (t = vsn_options.first; t != NULL; t = t->next)            apr_table_addn(r->headers_out, "DAV", t->text);    }    /*     * Gather property set URIs from all the liveprop providers,     * and generate a separate DAV header for each URI, to avoid     * problems with long header lengths.     */    uri_ary = apr_array_make(r->pool, 5, sizeof(const char *));    dav_run_gather_propsets(uri_ary);    for (i = 0; i < uri_ary->nelts; ++i) {        if (((char **)uri_ary->elts)[i] != NULL)            apr_table_addn(r->headers_out, "DAV", ((char **)uri_ary->elts)[i]);    }    /* this tells MSFT products to skip looking for FrontPage extensions */    apr_table_setn(r->headers_out, "MS-Author-Via", "DAV");    /*     * Determine which methods are allowed on the resource.     * Three cases:  resource is null (3), is lock-null (7.4), or exists.     *     * All cases support OPTIONS, and if there is a lock provider, LOCK.     * (Lock-) null resources also support MKCOL and PUT.     * Lock-null supports PROPFIND and UNLOCK.     * Existing resources support lots of stuff.     */    apr_table_addn(methods, "OPTIONS", "");    /* ### take into account resource type */    switch (dav_get_resource_state(r, resource))    {    case DAV_RESOURCE_EXISTS:        /* resource exists */        apr_table_addn(methods, "GET", "");        apr_table_addn(methods, "HEAD", "");        apr_table_addn(methods, "POST", "");        apr_table_addn(methods, "DELETE", "");        apr_table_addn(methods, "TRACE", "");        apr_table_addn(methods, "PROPFIND", "");        apr_table_addn(methods, "PROPPATCH", "");        apr_table_addn(methods, "COPY", "");        apr_table_addn(methods, "MOVE", "");        if (!resource->collection)            apr_table_addn(methods, "PUT", "");        if (locks_hooks != NULL) {            apr_table_addn(methods, "LOCK", "");            apr_table_addn(methods, "UNLOCK", "");        }        break;    case DAV_RESOURCE_LOCK_NULL:        /* resource is lock-null. */        apr_table_addn(methods, "MKCOL", "");        apr_table_addn(methods, "PROPFIND", "");        apr_table_addn(methods, "PUT", "");        if (locks_hooks != NULL) {            apr_table_addn(methods, "LOCK", "");            apr_table_addn(methods, "UNLOCK", "");        }        break;    case DAV_RESOURCE_NULL:        /* resource is null. */        apr_table_addn(methods, "MKCOL", "");        apr_table_addn(methods, "PUT", "");        if (locks_hooks != NULL)            apr_table_addn(methods, "LOCK", "");        break;    default:        /* ### internal error! */        break;    }    /* If there is a versioning provider, add versioning methods */    if (vsn_hooks != NULL) {        if (!resource->exists) {            if ((*vsn_hooks->versionable)(resource))                apr_table_addn(methods, "VERSION-CONTROL", "");            if (vsn_hooks->can_be_workspace != NULL                && (*vsn_hooks->can_be_workspace)(resource))                apr_table_addn(methods, "MKWORKSPACE", "");            if (vsn_hooks->can_be_activity != NULL                && (*vsn_hooks->can_be_activity)(resource))                apr_table_addn(methods, "MKACTIVITY", "");        }        else if (!resource->versioned) {            if ((*vsn_hooks->versionable)(resource))                apr_table_addn(methods, "VERSION-CONTROL", "");        }        else if (resource->working) {            apr_table_addn(methods, "CHECKIN", "");            /* ### we might not support this DeltaV option */            apr_table_addn(methods, "UNCHECKOUT", "");        }        else if (vsn_hooks->add_label != NULL) {            apr_table_addn(methods, "CHECKOUT", "");            apr_table_addn(methods, "LABEL", "");        }        else {            apr_table_addn(methods, "CHECKOUT", "");        }    }    /* If there is a bindings provider, see if resource is bindable */    if (binding_hooks != NULL        && (*binding_hooks->is_bindable)(resource)) {        apr_table_addn(methods, "BIND", "");    }    /* If there is a search provider, set SEARCH in option */    if (search_hooks != NULL) {        apr_table_addn(methods, "SEARCH", "");    }    /* Generate the Allow header */    arr = apr_table_elts(methods);    elts = (const apr_table_entry_t *)arr->elts;    text_size = 0;    /* first, compute total length */    for (i = 0; i < arr->nelts; ++i) {        if (elts[i].key == NULL)            continue;        /* add 1 for comma or null */        text_size += strlen(elts[i].key) + 1;    }    s = allow = apr_palloc(r->pool, text_size);    for (i = 0; i < arr->nelts; ++i) {        if (elts[i].key == NULL)            continue;        if (s != allow)            *s++ = ',';        strcpy(s, elts[i].key);        s += strlen(s);    }    apr_table_setn(r->headers_out, "Allow", allow);    /* If there is search set_option_head function, set head */    /* DASL: <DAV:basicsearch>     * DASL: <http://foo.bar.com/syntax1>     * DASL: <http://akuma.com/syntax2>     */    if (search_hooks != NULL        && *search_hooks->set_option_head != NULL) {        if ((err = (*search_hooks->set_option_head)(r)) != NULL) {            return dav_handle_err(r, err, NULL);        }    }    /* if there was no request body, then there is no response body */    if (doc == NULL) {        ap_set_content_length(r, 0);        /* ### this sends a Content-Type. the default OPTIONS does not. */        /* ### the default (ap_send_http_options) returns OK, but I believe         * ### that is because it is the default handler and nothing else         * ### will run after the thing. */        return DONE;    }    /* handle each options request */    for (elem = doc->root->first_child; elem != NULL; elem = elem->next) {        /* check for something we recognize first */        int core_option = 0;        dav_error *err = NULL;        if (elem->ns == APR_XML_NS_DAV_ID) {            if (strcmp(elem->name, "supported-method-set") == 0) {                err = dav_gen_supported_methods(r, elem, methods, &body);                core_option = 1;            }            else if (strcmp(elem->name, "supported-live-property-set") == 0) {                err = dav_gen_supported_live_props(r, resource, elem, &body);                core_option = 1;            }            else if (strcmp(elem->name, "supported-report-set") == 0) {                err = dav_gen_supported_reports(r, resource, elem, vsn_hooks, &body);                core_option = 1;            }        }        if (err != NULL)            return dav_handle_err(r, err, NULL);        /* if unrecognized option, pass to versioning provider */        if (!core_option && vsn_hooks != NULL) {            if ((err = (*vsn_hooks->get_option)(resource, elem, &body))                != NULL) {                return dav_handle_err(r, err, NULL);            }        }    }    /* send the options response */    r->status = HTTP_OK;    ap_set_content_type(r, DAV_XML_CONTENT_TYPE);    /* send the headers and response body */    ap_rputs(DAV_XML_HEADER DEBUG_CR             "<D:options-response xmlns:D=\"DAV:\">" DEBUG_CR, r);    for (t = body.first; t != NULL; t = t->next)        ap_rputs(t->text, r);    ap_rputs("</D:options-response>" DEBUG_CR, r);    /* we've sent everything necessary to the client. */    return DONE;}static void dav_cache_badprops(dav_walker_ctx *ctx){    const apr_xml_elem *elem;    apr_text_header hdr = { 0 };    /* just return if we built the thing already */    if (ctx->propstat_404 != NULL) {        return;    }    apr_text_append(ctx->w.pool, &hdr,                    "<D:propstat>" DEBUG_CR                    "<D:prop>" DEBUG_CR);    elem = dav_find_child(ctx->doc->root, "prop");    for (elem = elem->first_child; elem; elem = elem->next) {        apr_text_append(ctx->w.pool, &hdr,                        apr_xml_empty_elem(ctx->w.pool, elem));    }    apr_text_append(ctx->w.pool, &hdr,                    "</D:prop>" DEBUG_CR                    "<D:status>HTTP/1.1 404 Not Found</D:status>" DEBUG_CR                    "</D:propstat>" DEBUG_CR);    ctx->propstat_404 = hdr.first;}static dav_error * dav_propfind_walker(dav_walk_resource *wres, int calltype){    dav_walker_ctx *ctx = wres->walk_ctx;    dav_error *err;    dav_propdb *propdb;    dav_get_props_result propstats = { 0 };    /*    ** Note: ctx->doc can only be NULL for DAV_PROPFIND_IS_ALLPROP. Since    ** dav_get_allprops() does not need to do namespace translation,    ** we're okay.    **    ** Note: we cast to lose the "const". The propdb won't try to change    ** the resource, however, since we are opening readonly.    */    err = dav_open_propdb(ctx->r, ctx->w.lockdb, wres->resource, 1,                          ctx->doc ? ctx->doc->namespaces : NULL, &propdb);    if (err != NULL) {        /* ### do something with err! */        if (ctx->propfind_type == DAV_PROPFIND_IS_PROP) {            dav_get_props_result badprops = { 0 };            /* some props were expected on this collection/resource */            dav_cache_badprops(ctx);            badprops.propstats = ctx->propstat_404;            dav_stream_response(wres, 0, &badprops, ctx->scratchpool);        }        else {            /* no props on this collection/resource */            dav_stream_response(wres, HTTP_OK, NULL, ctx->scratchpool);        }        apr_pool_clear(ctx->scratchpool);        return NULL;    }    /* ### what to do about closing the propdb on server failure? */    if (ctx->propfind_type == DAV_PROPFIND_IS_PROP) {        propstats = dav_get_props(propdb, ctx->doc);    }    else {        dav_prop_insert what = ctx->propfind_type == DAV_PROPFIND_IS_ALLPROP                                 ? DAV_PROP_INSERT_VALUE                                 : DAV_PROP_INSERT_NAME;        propstats = dav_get_allprops(propdb, what);    }    dav_close_propdb(propdb);    dav_stream_response(wres, 0, &propstats, ctx->scratchpool);    /* at this point, ctx->scratchpool has been used to stream a       single response.  this function fully controls the pool, and       thus has the right to clear it for the next iteration of this       callback. */    apr_pool_clear(ctx->scratchpool);    return NULL;}/* handle the PROPFIND method */static int dav_method_propfind(request_rec *r){    dav_resource *resource;    int depth;    dav_error *err;    int result;    apr_xml_doc *doc;    const apr_xml_elem *child;    dav_walker_ctx ctx = { { 0 } };    dav_response *multi_status;    /* Ask repository module to resolve the resource */    err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,                           &resource);    if (err != NULL)        return dav_handle_err(r, err, NULL);    if (dav_get_resource_state(r, resource) == DAV_RESOURCE_NULL) {        /* Apache will supply a default error for this. */        return HTTP_NOT_FOUND;    }    if ((depth = dav_get_depth(r, DAV_INFINITY)) < 0) {        /* dav_get_depth() supplies additional information for the         * default message. */        return HTTP_BAD_REQUEST;    }    if (depth == DAV_INFINITY && resource->collection) {        dav_dir_conf *conf;        conf = (dav_dir_conf *)ap_get_module_config(r->per_dir_config,                                                    &dav_module);        /* default is to DISALLOW these requests */        if (conf->allow_depthinfinity != DAV_ENABLED_ON) {            return dav_error_response(r, HTTP_FORBIDDEN,                                      apr_psprintf(r->pool,                      

⌨️ 快捷键说明

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