static dav_error * dav_validate_resource_state(apr_pool_t *p,
                                               const dav_resource *resource,
                                               dav_lockdb *lockdb,
                                               const dav_if_header *if_header,
                                               int flags,
                                               dav_buffer *pbuf,
                                               request_rec *r)
{
    dav_error *err;
    const char *uri;
    const char *etag;
    const dav_hooks_locks *locks_hooks = (lockdb ? lockdb->hooks : NULL);
    const dav_if_header *ifhdr_scan;
    dav_if_state_list *state_list;
    dav_lock *lock_list;
    dav_lock *lock;
    int num_matched;
    int num_that_apply;
    int seen_locktoken;
    apr_size_t uri_len;
    const char *reason = NULL;
    if (lockdb == NULL) {
        lock_list = NULL;
    }
    else {
        if ((err = dav_lock_query(lockdb, resource, &lock_list)) != NULL) {
            return dav_push_error(p,
                                  HTTP_INTERNAL_SERVER_ERROR, 0,
                                  "The locks could not be queried for "
                                  "verification against a possible \"If:\" "
                                  "header.",
                                  err);
        }
    }
    if (flags & DAV_LOCKSCOPE_EXCLUSIVE) {
        if (lock_list != NULL) {
            return dav_new_error(p, HTTP_LOCKED, 0, 0,
                                 "Existing lock(s) on the requested resource "
                                 "prevent an exclusive lock.");
        }
        seen_locktoken = 1;
    }
    else if (flags & DAV_LOCKSCOPE_SHARED) {
        for (lock = lock_list; lock != NULL; lock = lock->next) {
            if (lock->scope == DAV_LOCKSCOPE_EXCLUSIVE) {
                return dav_new_error(p, HTTP_LOCKED, 0, 0,
                                     "The requested resource is already "
                                     "locked exclusively.");
            }
        }
        seen_locktoken = 1;
    }
    else {
        seen_locktoken = (lock_list == NULL);
    }
    if (if_header == NULL) {
        if (seen_locktoken)
            return NULL;
        return dav_new_error(p, HTTP_LOCKED, 0, 0,
                             "This resource is locked and an \"If:\" header "
                             "was not supplied to allow access to the "
                             "resource.");
    }
    if (lock_list == NULL && if_header->dummy_header) {
        if (flags & DAV_VALIDATE_IS_PARENT)
            return NULL;
        return dav_new_error(p, HTTP_BAD_REQUEST, 0, 0,
                             "The locktoken specified in the \"Lock-Token:\" "
                             "header is invalid because this resource has no "
                             "outstanding locks.");
    }
    uri = resource->uri;
    uri_len = strlen(uri);
    if (uri[uri_len - 1] == '/') {
        dav_set_bufsize(p, pbuf, uri_len);
        memcpy(pbuf->buf, uri, uri_len);
        pbuf->buf[--uri_len] = '\0';
        uri = pbuf->buf;
    }
    etag = (*resource->hooks->getetag)(resource);
    num_that_apply = 0;
    for (ifhdr_scan = if_header;
         ifhdr_scan != NULL;
         ifhdr_scan = ifhdr_scan->next) {
        if (ifhdr_scan->uri != NULL
            && (uri_len != ifhdr_scan->uri_len
                || memcmp(uri, ifhdr_scan->uri, uri_len) != 0)) {
            continue;
        }
        ++num_that_apply;
        for (state_list = ifhdr_scan->state;
             state_list != NULL;
             state_list = state_list->next) {
            switch(state_list->type) {
            case dav_if_etag:
            {
                const char *given_etag, *current_etag;
                int mismatch;
                if (state_list->etag[0] == 'W' &&
                    state_list->etag[1] == '/') {
                    given_etag = state_list->etag + 2;
                }
                else {
                    given_etag = state_list->etag;
                }
                if (etag[0] == 'W' &&
                    etag[1] == '/') {
                    current_etag = etag + 2;
                }
                else {
                    current_etag = etag;
                }
                mismatch = strcmp(given_etag, current_etag);
                if (state_list->condition == DAV_IF_COND_NORMAL && mismatch) {
                    reason =
                        "an entity-tag was specified, but the resource's "
                        "actual ETag does not match.";
                    goto state_list_failed;
                }
                else if (state_list->condition == DAV_IF_COND_NOT
                         && !mismatch) {
                    reason =
                        "an entity-tag was specified using the \"Not\" form, "
                        "but the resource's actual ETag matches the provided "
                        "entity-tag.";
                    goto state_list_failed;
                }
                break;
            }
            case dav_if_opaquelock:
                if (lockdb == NULL) {
                    if (state_list->condition == DAV_IF_COND_NOT) {
                        continue;
                    }
                    reason =
                        "a State-token was supplied, but a lock database "
                        "is not available for to provide the required lock.";
                    goto state_list_failed;
                }
                num_matched = 0;
                for (lock = lock_list; lock != NULL; lock = lock->next) {
                    if ((*locks_hooks->compare_locktoken)(state_list->locktoken, lock->locktoken)) {
                        continue;
                    }
                    seen_locktoken = 1;
                    if (state_list->condition == DAV_IF_COND_NOT) {
                        reason =
                            "a State-token was supplied, which used a "
                            "\"Not\" condition. The State-token was found "
                            "in the locks on this resource";
                        goto state_list_failed;
                    }
                    if (lock->auth_user &&
                        (!r->user ||
                         strcmp(lock->auth_user, r->user))) {
                        const char *errmsg;
                        errmsg = apr_pstrcat(p, "User \"",
                                            r->user,
                                            "\" submitted a locktoken created "
                                            "by user \"",
                                            lock->auth_user, "\".", NULL);
                        return dav_new_error(p, HTTP_FORBIDDEN, 0, 0, errmsg);
                    }
                    num_matched = 1;
                    break;
                }
                if (num_matched == 0
                    && state_list->condition == DAV_IF_COND_NORMAL) {
                    reason =
                        "a State-token was supplied, but it was not found "
                        "in the locks on this resource.";
                    goto state_list_failed;
                }
                break;
            case dav_if_unknown:
                if (state_list->condition == DAV_IF_COND_NORMAL) {
                    reason =
                        "an unknown state token was supplied";
                    goto state_list_failed;
                }
                break;
            }
        }
        if (seen_locktoken) {
            return NULL;
        }
        break;
      state_list_failed:
        ;
    }
    if (ifhdr_scan == NULL) {
        if (num_that_apply == 0) {
            if (seen_locktoken)
                return NULL;
            if (dav_find_submitted_locktoken(if_header, lock_list,
                                             locks_hooks)) {
                return NULL;
            }
            return dav_new_error(p, HTTP_LOCKED, 0  , 0,
                                 "This resource is locked and the \"If:\" "
                                 "header did not specify one of the "
                                 "locktokens for this resource's lock(s).");
        }
        if (if_header->dummy_header) {
            return dav_new_error(p, HTTP_BAD_REQUEST, 0, 0,
                                 "The locktoken specified in the "
                                 "\"Lock-Token:\" header did not specify one "
                                 "of this resource's locktoken(s).");
        }
        if (reason == NULL) {
            return dav_new_error(p, HTTP_PRECONDITION_FAILED, 0, 0,
                                 "The preconditions specified by the \"If:\" "
                                 "header did not match this resource.");
        }
        return dav_new_error(p, HTTP_PRECONDITION_FAILED, 0, 0,
                             apr_psprintf(p,
                                         "The precondition(s) specified by "
                                         "the \"If:\" header did not match "
                                         "this resource. At least one "
                                         "failure is because: %s", reason));
    }
    if (dav_find_submitted_locktoken(if_header, lock_list, locks_hooks)) {
        return NULL;
    }
    if (if_header->dummy_header) {
        return dav_new_error(p, HTTP_BAD_REQUEST, 0, 0,
                             "The locktoken specified in the "
                             "\"Lock-Token:\" header did not specify one "
                             "of this resource's locktoken(s).");
    }
    return dav_new_error(p, HTTP_LOCKED, 1  , 0,
                         "This resource is locked and the \"If:\" header "
                         "did not specify one of the "
                         "locktokens for this resource's lock(s).");
}
['static int dav_method_proppatch(request_rec *r)\n{\n    dav_error *err;\n    dav_resource *resource;\n    int result;\n    apr_xml_doc *doc;\n    apr_xml_elem *child;\n    dav_propdb *propdb;\n    int failure = 0;\n    dav_response resp = { 0 };\n    apr_text *propstat_text;\n    apr_array_header_t *ctx_list;\n    dav_prop_ctx *ctx;\n    dav_auto_version_info av_info;\n    err = dav_get_resource(r, 0  , 0  ,\n                           &resource);\n    if (err != NULL)\n        return dav_handle_err(r, err, NULL);\n    if (!resource->exists) {\n        return HTTP_NOT_FOUND;\n    }\n    if ((result = ap_xml_parse_input(r, &doc)) != OK) {\n        return result;\n    }\n    if (doc == NULL || !dav_validate_root(doc, "propertyupdate")) {\n        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00587)\n                      "The request body does not contain "\n                      "a \\"propertyupdate\\" element.");\n        return HTTP_BAD_REQUEST;\n    }\n    if ((err = dav_validate_request(r, resource, 0, NULL, NULL,\n                                    DAV_VALIDATE_RESOURCE, NULL)) != NULL) {\n        return dav_handle_err(r, err, NULL);\n    }\n    if ((err = dav_auto_checkout(r, resource,\n                                 0  ,\n                                 &av_info)) != NULL) {\n        return dav_handle_err(r, err, NULL);\n    }\n    if ((err = dav_open_propdb(r, NULL, resource, 0, doc->namespaces,\n                               &propdb)) != NULL) {\n        dav_auto_checkin(r, resource, 1  , 0  , &av_info);\n        err = dav_push_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,\n                             apr_psprintf(r->pool,\n                                          "Could not open the property "\n                                          "database for %s.",\n                                          ap_escape_html(r->pool, r->uri)),\n                             err);\n        return dav_handle_err(r, err, NULL);\n    }\n    ctx_list = apr_array_make(r->pool, 10, sizeof(dav_prop_ctx));\n    for (child = doc->root->first_child; child; child = child->next) {\n        int is_remove;\n        apr_xml_elem *prop_group;\n        apr_xml_elem *one_prop;\n        if (child->ns != APR_XML_NS_DAV_ID\n            || (!(is_remove = (strcmp(child->name, "remove") == 0))\n                && strcmp(child->name, "set") != 0)) {\n            continue;\n        }\n        if ((prop_group = dav_find_child(child, "prop")) == NULL) {\n            dav_close_propdb(propdb);\n            dav_auto_checkin(r, resource, 1  , 0  , &av_info);\n            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00588)\n                          "A \\"prop\\" element is missing inside "\n                          "the propertyupdate command.");\n            return HTTP_BAD_REQUEST;\n        }\n        for (one_prop = prop_group->first_child; one_prop;\n             one_prop = one_prop->next) {\n            ctx = (dav_prop_ctx *)apr_array_push(ctx_list);\n            ctx->propdb = propdb;\n            ctx->operation = is_remove ? DAV_PROP_OP_DELETE : DAV_PROP_OP_SET;\n            ctx->prop = one_prop;\n            ctx->r = r;\n            dav_prop_validate(ctx);\n            if ( DAV_PROP_CTX_HAS_ERR(*ctx) ) {\n                failure = 1;\n            }\n        }\n    }\n    if (!failure && dav_process_ctx_list(dav_prop_exec, ctx_list, 1, 0)) {\n        failure = 1;\n    }\n    if (failure) {\n        (void)dav_process_ctx_list(dav_prop_rollback, ctx_list, 0, 1);\n        propstat_text = dav_failed_proppatch(r->pool, ctx_list);\n    }\n    else {\n        (void)dav_process_ctx_list(dav_prop_commit, ctx_list, 0, 0);\n        propstat_text = dav_success_proppatch(r->pool, ctx_list);\n    }\n    dav_close_propdb(propdb);\n    dav_auto_checkin(r, resource, failure, 0  , &av_info);\n    (void)dav_process_ctx_list(dav_prop_log_errors, ctx_list, 0, 0);\n    resp.href = resource->uri;\n    resp.propresult.propstats = propstat_text;\n    dav_send_multistatus(r, HTTP_MULTI_STATUS, &resp, doc->namespaces);\n    return DONE;\n}', 'AP_DECLARE(int) ap_xml_parse_input(request_rec * r, apr_xml_doc **pdoc)\n{\n    apr_xml_parser *parser;\n    apr_bucket_brigade *brigade;\n    int seen_eos;\n    apr_status_t status;\n    char errbuf[200];\n    apr_size_t total_read = 0;\n    apr_size_t limit_xml_body = ap_get_limit_xml_body(r);\n    int result = HTTP_BAD_REQUEST;\n    parser = apr_xml_parser_create(r->pool);\n    brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);\n    seen_eos = 0;\n    total_read = 0;\n    do {\n        apr_bucket *bucket;\n        status = ap_get_brigade(r->input_filters, brigade,\n                                AP_MODE_READBYTES, APR_BLOCK_READ,\n                                READ_BLOCKSIZE);\n        if (status != APR_SUCCESS) {\n            goto read_error;\n        }\n        for (bucket = APR_BRIGADE_FIRST(brigade);\n             bucket != APR_BRIGADE_SENTINEL(brigade);\n             bucket = APR_BUCKET_NEXT(bucket))\n        {\n            const char *data;\n            apr_size_t len;\n            if (APR_BUCKET_IS_EOS(bucket)) {\n                seen_eos = 1;\n                break;\n            }\n            if (APR_BUCKET_IS_METADATA(bucket)) {\n                continue;\n            }\n            status = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);\n            if (status != APR_SUCCESS) {\n                goto read_error;\n            }\n            total_read += len;\n            if (limit_xml_body && total_read > limit_xml_body) {\n                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00539)\n                              "XML request body is larger than the configured "\n                              "limit of %lu", (unsigned long)limit_xml_body);\n                result = HTTP_REQUEST_ENTITY_TOO_LARGE;\n                goto read_error;\n            }\n            status = apr_xml_parser_feed(parser, data, len);\n            if (status) {\n                goto parser_error;\n            }\n        }\n        apr_brigade_cleanup(brigade);\n    } while (!seen_eos);\n    apr_brigade_destroy(brigade);\n    status = apr_xml_parser_done(parser, pdoc);\n    if (status) {\n        if (!total_read) {\n            *pdoc = NULL;\n            return OK;\n        }\n        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00540)\n                      "XML parser error (at end). status=%d", status);\n        return HTTP_BAD_REQUEST;\n    }\n#if APR_CHARSET_EBCDIC\n    apr_xml_parser_convert_doc(r->pool, *pdoc, ap_hdrs_from_ascii);\n#endif\n    return OK;\n  parser_error:\n    (void) apr_xml_parser_geterror(parser, errbuf, sizeof(errbuf));\n    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00541)\n                  "XML Parser Error: %s", errbuf);\n  read_error:\n    (void) apr_xml_parser_done(parser, NULL);\n    apr_brigade_destroy(brigade);\n    return result;\n}', 'DAV_DECLARE(int) dav_validate_root(const apr_xml_doc *doc,\n                                   const char *tagname)\n{\n    return doc->root &&\n        doc->root->ns == APR_XML_NS_DAV_ID &&\n        strcmp(doc->root->name, tagname) == 0;\n}', 'DAV_DECLARE(dav_error *) dav_validate_request(request_rec *r,\n                                              dav_resource *resource,\n                                              int depth,\n                                              dav_locktoken *locktoken,\n                                              dav_response **response,\n                                              int flags,\n                                              dav_lockdb *lockdb)\n{\n    dav_error *err;\n    int result;\n    dav_if_header *if_header;\n    int lock_db_opened_locally = 0;\n    const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);\n    const dav_hooks_repository *repos_hooks = resource->hooks;\n    dav_buffer work_buf = { 0 };\n    dav_response *new_response;\n    int resource_state;\n    const char *etag;\n    int set_etag = 0;\n#if DAV_DEBUG\n    if (depth && response == NULL) {\n        return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, 0,\n                             "DESIGN ERROR: dav_validate_request called "\n                             "with depth>0, but no response ptr.");\n    }\n#endif\n    if (response != NULL)\n        *response = NULL;\n    etag = apr_table_get(r->headers_out, "ETag");\n    if (!etag) {\n        etag = (*resource->hooks->getetag)(resource);\n        if (etag && *etag) {\n            apr_table_set(r->headers_out, "ETag", etag);\n            set_etag = 1;\n        }\n    }\n    resource_state = dav_get_resource_state(r, resource);\n    result = dav_meets_conditions(r, resource_state);\n    if (set_etag) {\n        apr_table_unset(r->headers_out, "ETag");\n    }\n    if (result != OK) {\n        return dav_new_error(r->pool, result, 0, 0, NULL);\n    }\n    if ((err = dav_process_if_header(r, &if_header)) != NULL) {\n        return err;\n    }\n    if (locktoken != NULL) {\n        dav_if_header *ifhdr_new;\n        ifhdr_new = apr_pcalloc(r->pool, sizeof(*ifhdr_new));\n        ifhdr_new->uri = resource->uri;\n        ifhdr_new->uri_len = strlen(resource->uri);\n        ifhdr_new->dummy_header = 1;\n        ifhdr_new->state = apr_pcalloc(r->pool, sizeof(*ifhdr_new->state));\n        ifhdr_new->state->type = dav_if_opaquelock;\n        ifhdr_new->state->condition = DAV_IF_COND_NORMAL;\n        ifhdr_new->state->locktoken = locktoken;\n        ifhdr_new->next = if_header;\n        if_header = ifhdr_new;\n    }\n    if (lockdb == NULL) {\n        if (locks_hooks != NULL) {\n            if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, &lockdb)) != NULL) {\n                return err;\n            }\n            lock_db_opened_locally = 1;\n        }\n    }\n    if (resource->exists && depth > 0) {\n        dav_walker_ctx ctx = { { 0 } };\n        dav_response *multi_status;\n        ctx.w.walk_type = DAV_WALKTYPE_NORMAL;\n        ctx.w.func = dav_validate_walker;\n        ctx.w.walk_ctx = &ctx;\n        ctx.w.pool = r->pool;\n        ctx.w.root = resource;\n        ctx.if_header = if_header;\n        ctx.r = r;\n        ctx.flags = flags;\n        if (lockdb != NULL) {\n            ctx.w.lockdb = lockdb;\n            ctx.w.walk_type |= DAV_WALKTYPE_LOCKNULL;\n        }\n        err = (*repos_hooks->walk)(&ctx.w, DAV_INFINITY, &multi_status);\n        if (err == NULL) {\n            *response = multi_status;;\n        }\n    }\n    else {\n        err = dav_validate_resource_state(r->pool, resource, lockdb,\n                                          if_header, flags, &work_buf, r);\n    }\n    if (err == NULL && (flags & DAV_VALIDATE_PARENT)) {\n        dav_resource *parent_resource;\n        err = (*repos_hooks->get_parent_resource)(resource, &parent_resource);\n        if (err == NULL && parent_resource == NULL) {\n            err = dav_new_error(r->pool, HTTP_FORBIDDEN, 0, 0,\n                                "Cannot access parent of repository root.");\n        }\n        else if (err == NULL) {\n            err = dav_validate_resource_state(r->pool, parent_resource, lockdb,\n                                              if_header,\n                                              flags | DAV_VALIDATE_IS_PARENT,\n                                              &work_buf, r);\n            if (err != NULL) {\n                new_response = apr_pcalloc(r->pool, sizeof(*new_response));\n                new_response->href = parent_resource->uri;\n                new_response->status = err->status;\n                new_response->desc =\n                    "A validation error has occurred on the parent resource, "\n                    "preventing the operation on the resource specified by "\n                    "the Request-URI.";\n                if (err->desc != NULL) {\n                    new_response->desc = apr_pstrcat(r->pool,\n                                                    new_response->desc,\n                                                    " The error was: ",\n                                                    err->desc, NULL);\n                }\n                new_response->next = *response;\n                *response = new_response;\n                err = NULL;\n            }\n        }\n    }\n    if (lock_db_opened_locally)\n        (*locks_hooks->close_lockdb)(lockdb);\n    if (err == NULL && response != NULL && *response != NULL) {\n        apr_text *propstat = NULL;\n        if ((flags & DAV_VALIDATE_USE_424) != 0) {\n            return dav_new_error(r->pool, HTTP_FAILED_DEPENDENCY, 0, 0,\n                                 "An error occurred on another resource, "\n                                 "preventing the requested operation on "\n                                 "this resource.");\n        }\n        if ((flags & DAV_VALIDATE_ADD_LD) != 0) {\n            propstat = apr_pcalloc(r->pool, sizeof(*propstat));\n            propstat->text =\n                "<D:propstat>" DEBUG_CR\n                "<D:prop><D:lockdiscovery/></D:prop>" DEBUG_CR\n                "<D:status>HTTP/1.1 424 Failed Dependency</D:status>" DEBUG_CR\n                "</D:propstat>" DEBUG_CR;\n        }\n        new_response = apr_pcalloc(r->pool, sizeof(*new_response));\n        new_response->href = resource->uri;\n        new_response->status = HTTP_FAILED_DEPENDENCY;\n        new_response->propresult.propstats = propstat;\n        new_response->desc =\n            "An error occurred on another resource, preventing the "\n            "requested operation on this resource.";\n        new_response->next = *response;\n        *response = new_response;\n        return dav_new_error(r->pool, HTTP_MULTI_STATUS, 0, 0,\n                             "Error(s) occurred on resources during the "\n                             "validation process.");\n    }\n    return err;\n}', 'static dav_error * dav_validate_resource_state(apr_pool_t *p,\n                                               const dav_resource *resource,\n                                               dav_lockdb *lockdb,\n                                               const dav_if_header *if_header,\n                                               int flags,\n                                               dav_buffer *pbuf,\n                                               request_rec *r)\n{\n    dav_error *err;\n    const char *uri;\n    const char *etag;\n    const dav_hooks_locks *locks_hooks = (lockdb ? lockdb->hooks : NULL);\n    const dav_if_header *ifhdr_scan;\n    dav_if_state_list *state_list;\n    dav_lock *lock_list;\n    dav_lock *lock;\n    int num_matched;\n    int num_that_apply;\n    int seen_locktoken;\n    apr_size_t uri_len;\n    const char *reason = NULL;\n    if (lockdb == NULL) {\n        lock_list = NULL;\n    }\n    else {\n        if ((err = dav_lock_query(lockdb, resource, &lock_list)) != NULL) {\n            return dav_push_error(p,\n                                  HTTP_INTERNAL_SERVER_ERROR, 0,\n                                  "The locks could not be queried for "\n                                  "verification against a possible \\"If:\\" "\n                                  "header.",\n                                  err);\n        }\n    }\n    if (flags & DAV_LOCKSCOPE_EXCLUSIVE) {\n        if (lock_list != NULL) {\n            return dav_new_error(p, HTTP_LOCKED, 0, 0,\n                                 "Existing lock(s) on the requested resource "\n                                 "prevent an exclusive lock.");\n        }\n        seen_locktoken = 1;\n    }\n    else if (flags & DAV_LOCKSCOPE_SHARED) {\n        for (lock = lock_list; lock != NULL; lock = lock->next) {\n            if (lock->scope == DAV_LOCKSCOPE_EXCLUSIVE) {\n                return dav_new_error(p, HTTP_LOCKED, 0, 0,\n                                     "The requested resource is already "\n                                     "locked exclusively.");\n            }\n        }\n        seen_locktoken = 1;\n    }\n    else {\n        seen_locktoken = (lock_list == NULL);\n    }\n    if (if_header == NULL) {\n        if (seen_locktoken)\n            return NULL;\n        return dav_new_error(p, HTTP_LOCKED, 0, 0,\n                             "This resource is locked and an \\"If:\\" header "\n                             "was not supplied to allow access to the "\n                             "resource.");\n    }\n    if (lock_list == NULL && if_header->dummy_header) {\n        if (flags & DAV_VALIDATE_IS_PARENT)\n            return NULL;\n        return dav_new_error(p, HTTP_BAD_REQUEST, 0, 0,\n                             "The locktoken specified in the \\"Lock-Token:\\" "\n                             "header is invalid because this resource has no "\n                             "outstanding locks.");\n    }\n    uri = resource->uri;\n    uri_len = strlen(uri);\n    if (uri[uri_len - 1] == \'/\') {\n        dav_set_bufsize(p, pbuf, uri_len);\n        memcpy(pbuf->buf, uri, uri_len);\n        pbuf->buf[--uri_len] = \'\\0\';\n        uri = pbuf->buf;\n    }\n    etag = (*resource->hooks->getetag)(resource);\n    num_that_apply = 0;\n    for (ifhdr_scan = if_header;\n         ifhdr_scan != NULL;\n         ifhdr_scan = ifhdr_scan->next) {\n        if (ifhdr_scan->uri != NULL\n            && (uri_len != ifhdr_scan->uri_len\n                || memcmp(uri, ifhdr_scan->uri, uri_len) != 0)) {\n            continue;\n        }\n        ++num_that_apply;\n        for (state_list = ifhdr_scan->state;\n             state_list != NULL;\n             state_list = state_list->next) {\n            switch(state_list->type) {\n            case dav_if_etag:\n            {\n                const char *given_etag, *current_etag;\n                int mismatch;\n                if (state_list->etag[0] == \'W\' &&\n                    state_list->etag[1] == \'/\') {\n                    given_etag = state_list->etag + 2;\n                }\n                else {\n                    given_etag = state_list->etag;\n                }\n                if (etag[0] == \'W\' &&\n                    etag[1] == \'/\') {\n                    current_etag = etag + 2;\n                }\n                else {\n                    current_etag = etag;\n                }\n                mismatch = strcmp(given_etag, current_etag);\n                if (state_list->condition == DAV_IF_COND_NORMAL && mismatch) {\n                    reason =\n                        "an entity-tag was specified, but the resource\'s "\n                        "actual ETag does not match.";\n                    goto state_list_failed;\n                }\n                else if (state_list->condition == DAV_IF_COND_NOT\n                         && !mismatch) {\n                    reason =\n                        "an entity-tag was specified using the \\"Not\\" form, "\n                        "but the resource\'s actual ETag matches the provided "\n                        "entity-tag.";\n                    goto state_list_failed;\n                }\n                break;\n            }\n            case dav_if_opaquelock:\n                if (lockdb == NULL) {\n                    if (state_list->condition == DAV_IF_COND_NOT) {\n                        continue;\n                    }\n                    reason =\n                        "a State-token was supplied, but a lock database "\n                        "is not available for to provide the required lock.";\n                    goto state_list_failed;\n                }\n                num_matched = 0;\n                for (lock = lock_list; lock != NULL; lock = lock->next) {\n                    if ((*locks_hooks->compare_locktoken)(state_list->locktoken, lock->locktoken)) {\n                        continue;\n                    }\n                    seen_locktoken = 1;\n                    if (state_list->condition == DAV_IF_COND_NOT) {\n                        reason =\n                            "a State-token was supplied, which used a "\n                            "\\"Not\\" condition. The State-token was found "\n                            "in the locks on this resource";\n                        goto state_list_failed;\n                    }\n                    if (lock->auth_user &&\n                        (!r->user ||\n                         strcmp(lock->auth_user, r->user))) {\n                        const char *errmsg;\n                        errmsg = apr_pstrcat(p, "User \\"",\n                                            r->user,\n                                            "\\" submitted a locktoken created "\n                                            "by user \\"",\n                                            lock->auth_user, "\\".", NULL);\n                        return dav_new_error(p, HTTP_FORBIDDEN, 0, 0, errmsg);\n                    }\n                    num_matched = 1;\n                    break;\n                }\n                if (num_matched == 0\n                    && state_list->condition == DAV_IF_COND_NORMAL) {\n                    reason =\n                        "a State-token was supplied, but it was not found "\n                        "in the locks on this resource.";\n                    goto state_list_failed;\n                }\n                break;\n            case dav_if_unknown:\n                if (state_list->condition == DAV_IF_COND_NORMAL) {\n                    reason =\n                        "an unknown state token was supplied";\n                    goto state_list_failed;\n                }\n                break;\n            }\n        }\n        if (seen_locktoken) {\n            return NULL;\n        }\n        break;\n      state_list_failed:\n        ;\n    }\n    if (ifhdr_scan == NULL) {\n        if (num_that_apply == 0) {\n            if (seen_locktoken)\n                return NULL;\n            if (dav_find_submitted_locktoken(if_header, lock_list,\n                                             locks_hooks)) {\n                return NULL;\n            }\n            return dav_new_error(p, HTTP_LOCKED, 0  , 0,\n                                 "This resource is locked and the \\"If:\\" "\n                                 "header did not specify one of the "\n                                 "locktokens for this resource\'s lock(s).");\n        }\n        if (if_header->dummy_header) {\n            return dav_new_error(p, HTTP_BAD_REQUEST, 0, 0,\n                                 "The locktoken specified in the "\n                                 "\\"Lock-Token:\\" header did not specify one "\n                                 "of this resource\'s locktoken(s).");\n        }\n        if (reason == NULL) {\n            return dav_new_error(p, HTTP_PRECONDITION_FAILED, 0, 0,\n                                 "The preconditions specified by the \\"If:\\" "\n                                 "header did not match this resource.");\n        }\n        return dav_new_error(p, HTTP_PRECONDITION_FAILED, 0, 0,\n                             apr_psprintf(p,\n                                         "The precondition(s) specified by "\n                                         "the \\"If:\\" header did not match "\n                                         "this resource. At least one "\n                                         "failure is because: %s", reason));\n    }\n    if (dav_find_submitted_locktoken(if_header, lock_list, locks_hooks)) {\n        return NULL;\n    }\n    if (if_header->dummy_header) {\n        return dav_new_error(p, HTTP_BAD_REQUEST, 0, 0,\n                             "The locktoken specified in the "\n                             "\\"Lock-Token:\\" header did not specify one "\n                             "of this resource\'s locktoken(s).");\n    }\n    return dav_new_error(p, HTTP_LOCKED, 1  , 0,\n                         "This resource is locked and the \\"If:\\" header "\n                         "did not specify one of the "\n                         "locktokens for this resource\'s lock(s).");\n}']