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

📄 mod_dav.c

📁 Apache 2.0.63 is the current stable version of the 2.0 series, and is recommended over any previous
💻 C
📖 第 1 页 / 共 5 页
字号:
    }

    /* 2518 says that depth must be infinity only for collections.
     * For non-collections, depth is ignored, unless it is an illegal value (1).
     */
    depth = dav_get_depth(r, DAV_INFINITY);

    if (resource->collection && depth != DAV_INFINITY) {
        /* This supplies additional information for the default message. */
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                      "Depth must be \"infinity\" for DELETE of a collection.");
        return HTTP_BAD_REQUEST;
    }

    if (!resource->collection && depth == 1) {
        /* This supplies additional information for the default message. */
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                      "Depth of \"1\" is not allowed for DELETE.");
        return HTTP_BAD_REQUEST;
    }

    /*
    ** If any resources fail the lock/If: conditions, then we must fail
    ** the delete. Each of the failing resources will be listed within
    ** a DAV:multistatus body, wrapped into a 424 response.
    **
    ** Note that a failure on the resource itself does not generate a
    ** multistatus response -- only internal members/collections.
    */
    if ((err = dav_validate_request(r, resource, depth, NULL,
                                    &multi_response,
                                    DAV_VALIDATE_PARENT
                                    | DAV_VALIDATE_USE_424, NULL)) != NULL) {
        err = dav_push_error(r->pool, err->status, 0,
                             apr_psprintf(r->pool,
                                          "Could not DELETE %s due to a failed "
                                          "precondition (e.g. locks).",
                                          ap_escape_html(r->pool, r->uri)),
                             err);
        return dav_handle_err(r, err, multi_response);
    }

    /* ### RFC 2518 s. 8.10.5 says to remove _all_ locks, not just those
     *     locked by the token(s) in the if_header.
     */
    if ((result = dav_unlock(r, resource, NULL)) != OK) {
        return result;
    }

    /* if versioned resource, make sure parent is checked out */
    if ((err = dav_auto_checkout(r, resource, 1 /* parent_only */,
                                 &av_info)) != NULL) {
        /* ### add a higher-level description? */
        return dav_handle_err(r, err, NULL);
    }

    /* try to remove the resource */
    err = (*resource->hooks->remove_resource)(resource, &multi_response);

    /* restore writability of parent back to what it was */
    err2 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
                            0 /*unlock*/, &av_info);

    /* check for errors now */
    if (err != NULL) {
        err = dav_push_error(r->pool, err->status, 0,
                             apr_psprintf(r->pool,
                                          "Could not DELETE %s.",
                                          ap_escape_html(r->pool, r->uri)),
                             err);
        return dav_handle_err(r, err, multi_response);
    }
    if (err2 != NULL) {
        /* just log a warning */
        err = dav_push_error(r->pool, err2->status, 0,
                             "The DELETE was successful, but there "
                             "was a problem automatically checking in "
                             "the parent collection.",
                             err2);
        dav_log_err(r, err, APLOG_WARNING);
    }

    /* ### HTTP_NO_CONTENT if no body, HTTP_OK if there is a body (some day) */

    /* Apache will supply a default error for this. */
    return HTTP_NO_CONTENT;
}

/* generate DAV:supported-method-set OPTIONS response */
static dav_error *dav_gen_supported_methods(request_rec *r,
                                            const apr_xml_elem *elem,
                                            const apr_table_t *methods,
                                            apr_text_header *body)
{
    const apr_array_header_t *arr;
    const apr_table_entry_t *elts;
    apr_xml_elem *child;
    apr_xml_attr *attr;
    char *s;
    int i;

    apr_text_append(r->pool, body, "<D:supported-method-set>" DEBUG_CR);

    if (elem->first_child == NULL) {
        /* show all supported methods */
        arr = apr_table_elts(methods);
        elts = (const apr_table_entry_t *)arr->elts;

        for (i = 0; i < arr->nelts; ++i) {
            if (elts[i].key == NULL)
                continue;

            s = apr_psprintf(r->pool,
                             "<D:supported-method D:name=\"%s\"/>"
                             DEBUG_CR,
                             elts[i].key);
            apr_text_append(r->pool, body, s);
        }
    }
    else {
        /* check for support of specific methods */
        for (child = elem->first_child; child != NULL; child = child->next) {
            if (child->ns == APR_XML_NS_DAV_ID
                && strcmp(child->name, "supported-method") == 0) {
                const char *name = NULL;

                /* go through attributes to find method name */
                for (attr = child->attr; attr != NULL; attr = attr->next) {
                    if (attr->ns == APR_XML_NS_DAV_ID
                        && strcmp(attr->name, "name") == 0)
                            name = attr->value;
                }

                if (name == NULL) {
                    return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0,
                                         "A DAV:supported-method element "
                                         "does not have a \"name\" attribute");
                }

                /* see if method is supported */
                if (apr_table_get(methods, name) != NULL) {
                    s = apr_psprintf(r->pool,
                                     "<D:supported-method D:name=\"%s\"/>"
                                     DEBUG_CR,
                                     name);
                    apr_text_append(r->pool, body, s);
                }
            }
        }
    }

    apr_text_append(r->pool, body, "</D:supported-method-set>" DEBUG_CR);
    return NULL;
}

/* generate DAV:supported-live-property-set OPTIONS response */
static dav_error *dav_gen_supported_live_props(request_rec *r,
                                               const dav_resource *resource,
                                               const apr_xml_elem *elem,
                                               apr_text_header *body)
{
    dav_lockdb *lockdb;
    dav_propdb *propdb;
    apr_xml_elem *child;
    apr_xml_attr *attr;
    dav_error *err;

    /* open lock database, to report on supported lock properties */
    /* ### should open read-only */
    if ((err = dav_open_lockdb(r, 0, &lockdb)) != NULL) {
        return dav_push_error(r->pool, err->status, 0,
                              "The lock database could not be opened, "
                              "preventing the reporting of supported lock "
                              "properties.",
                              err);
    }

    /* open the property database (readonly) for the resource */
    if ((err = dav_open_propdb(r, lockdb, resource, 1, NULL,
                               &propdb)) != NULL) {
        if (lockdb != NULL)
            (*lockdb->hooks->close_lockdb)(lockdb);

        return dav_push_error(r->pool, err->status, 0,
                              "The property database could not be opened, "
                              "preventing report of supported properties.",
                              err);
    }

    apr_text_append(r->pool, body, "<D:supported-live-property-set>" DEBUG_CR);

    if (elem->first_child == NULL) {
        /* show all supported live properties */
        dav_get_props_result props = dav_get_allprops(propdb, DAV_PROP_INSERT_SUPPORTED);
        body->last->next = props.propstats;
        while (body->last->next != NULL)
            body->last = body->last->next;
    }
    else {
        /* check for support of specific live property */
        for (child = elem->first_child; child != NULL; child = child->next) {
            if (child->ns == APR_XML_NS_DAV_ID
                && strcmp(child->name, "supported-live-property") == 0) {
                const char *name = NULL;
                const char *nmspace = NULL;

                /* go through attributes to find name and namespace */
                for (attr = child->attr; attr != NULL; attr = attr->next) {
                    if (attr->ns == APR_XML_NS_DAV_ID) {
                        if (strcmp(attr->name, "name") == 0)
                            name = attr->value;
                        else if (strcmp(attr->name, "namespace") == 0)
                            nmspace = attr->value;
                    }
                }

                if (name == NULL) {
                    err = dav_new_error(r->pool, HTTP_BAD_REQUEST, 0,
                                        "A DAV:supported-live-property "
                                        "element does not have a \"name\" "
                                        "attribute");
                    break;
                }

                /* default namespace to DAV: */
                if (nmspace == NULL)
                    nmspace = "DAV:";

                /* check for support of property */
                dav_get_liveprop_supported(propdb, nmspace, name, body);
            }
        }
    }

    apr_text_append(r->pool, body, "</D:supported-live-property-set>" DEBUG_CR);

    dav_close_propdb(propdb);

    if (lockdb != NULL)
        (*lockdb->hooks->close_lockdb)(lockdb);

    return err;
}

/* generate DAV:supported-report-set OPTIONS response */
static dav_error *dav_gen_supported_reports(request_rec *r,
                                            const dav_resource *resource,
                                            const apr_xml_elem *elem,
                                            const dav_hooks_vsn *vsn_hooks,
                                            apr_text_header *body)
{
    apr_xml_elem *child;
    apr_xml_attr *attr;
    dav_error *err;
    char *s;

    apr_text_append(r->pool, body, "<D:supported-report-set>" DEBUG_CR);

    if (vsn_hooks != NULL) {
        const dav_report_elem *reports;
        const dav_report_elem *rp;

        if ((err = (*vsn_hooks->avail_reports)(resource, &reports)) != NULL) {
            return dav_push_error(r->pool, err->status, 0,
                                  "DAV:supported-report-set could not be "
                                  "determined due to a problem fetching the "
                                  "available reports for this resource.",
                                  err);
        }

        if (reports != NULL) {
            if (elem->first_child == NULL) {
                /* show all supported reports */
                for (rp = reports; rp->nmspace != NULL; ++rp) {
                    /* Note: we presume reports->namespace is 
                     * properly XML/URL quoted */
                    s = apr_psprintf(r->pool,
                                     "<D:supported-report D:name=\"%s\" "
                                     "D:namespace=\"%s\"/>" DEBUG_CR,
                                     rp->name, rp->nmspace);
                    apr_text_append(r->pool, body, s);
                }
            }
            else {
                /* check for support of specific report */
                for (child = elem->first_child; child != NULL; child = child->next) {
                    if (child->ns == APR_XML_NS_DAV_ID
                        && strcmp(child->name, "supported-report") == 0) {
                        const char *name = NULL;
                        const char *nmspace = NULL;

                        /* go through attributes to find name and namespace */
                        for (attr = child->attr; attr != NULL; attr = attr->next) {
                            if (attr->ns == APR_XML_NS_DAV_ID) {
                                if (strcmp(attr->name, "name") == 0)
                                    name = attr->value;
                                else if (strcmp(attr->name, "namespace") == 0)
                                    nmspace = attr->value;
                            }
                        }

                        if (name == NULL) {
                            return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0,
                                                 "A DAV:supported-report element "
                                                 "does not have a \"name\" attribute");
                        }

                        /* default namespace to DAV: */
                        if (nmspace == NULL)
                            nmspace = "DAV:";

                        for (rp = reports; rp->nmspace != NULL; ++rp) {
                            if (strcmp(name, rp->name) == 0
                                && strcmp(nmspace, rp->nmspace) == 0) {
                                /* Note: we presume reports->nmspace is
                                 * properly XML/URL quoted 
                                 */
                                s = apr_psprintf(r->pool,
                                                 "<D:supported-report "
                                                 "D:name=\"%s\" "
                                                 "D:namespace=\"%s\"/>"
                                                 DEBUG_CR,
                                                 rp->name, rp->nmspace);
                                apr_text_append(r->pool, body, s);
                                break;
                            }
                        }
                    }
                }
            }
        }
    }

    apr_text_append(r->pool, body, "</D:supported-report-set>" DEBUG_CR);
    return NULL;
}


/* handle the SEARCH method */
static int dav_method_search(request_rec *r)
{
    const dav_hooks_search *search_hooks = DAV_GET_HOOKS_SEARCH(r);
    dav_resource *resource;
    dav_error *err;
    dav_response *multi_status;

    /* If no search provider, decline the request */
    if (search_hooks == NULL)
        return DECLINED;

    /* This method should only be called when the resource is not
     * visible to Apache. We will fetch the resource from the repository,
     * then create a subrequest for Apache to handle.
     */
    err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
                           &resource);
    if (err != NULL)
        return dav_handle_err(r, err, NULL);

    if (!resource->exists) {
        /* Apache will supply a default error for this. */
        return HTTP_NOT_FOUND;
    }

    /* set up the HTTP headers for the response */
    if ((err = (*resource->hooks->set_headers)(r, resource)) != NULL) {
        err = dav_push_error(r->pool, err->status, 0,
                             "Unable to set up HTTP headers.",
                             err);
        return dav_handle_err(r, err, NULL);
    }

    if (r->header_only) {
        return DONE;
    }

    /* okay... time to search the content */
    /* Let's validate XML and process walk function
     * in the hook function
     */
    if ((err = (*search_hooks->search_resource)(r, &multi_status)) != NULL) {
        /* ### add a higher-level description? */

⌨️ 快捷键说明

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