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

📄 util.c

📁 Apache 2.0.63 is the current stable version of the 2.0 series, and is recommended over any previous
💻 C
📖 第 1 页 / 共 5 页
字号:
                    goto state_list_failed;
                }
                else if (state_list->condition == DAV_IF_COND_NOT
                         && !mismatch) {
                    /*
                    ** The specified entity-tag DOES match the
                    ** entity-tag on the resource. This state_list is
                    ** not going to match. Bust outta here.
                    */
                    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) {
                        /* the locktoken is definitely not there! (success) */
                        continue;
                    }

                    /* condition == DAV_IF_COND_NORMAL */

                    /*
                    ** If no lockdb is provided, then validation fails for
                    ** this state_list (NORMAL means we were supposed to
                    ** find the token, which we obviously cannot do without
                    ** a lock database).
                    **
                    ** Go and try the next state list.
                    */
                    reason =
                        "a State-token was supplied, but a lock database "
                        "is not available for to provide the required lock.";
                    goto state_list_failed;
                }

                /* Resource validation 'fails' if:
                 *    ANY  of the lock->locktokens match
                 *         a NOT state_list->locktoken,
                 * OR
                 *    NONE of the lock->locktokens match
                 *         a NORMAL state_list->locktoken.
                 */
                num_matched = 0;
                for (lock = lock_list; lock != NULL; lock = lock->next) {

                    /*
                    DBG2("compare: rsrc=%s  ifhdr=%s",
                         (*locks_hooks->format_locktoken)(p, lock->locktoken),
                         (*locks_hooks->format_locktoken)(p, state_list->locktoken));
                    */

                    /* nothing to do if the locktokens do not match. */
                    if ((*locks_hooks->compare_locktoken)(state_list->locktoken, lock->locktoken)) {
                        continue;
                    }

                    /*
                    ** We have now matched up one of the resource's locktokens
                    ** to a locktoken in a State-token in the If: header.
                    ** Note this fact, so that we can pass the overall
                    ** requirement of seeing at least one of the resource's
                    ** locktokens.
                    */
                    seen_locktoken = 1;

                    if (state_list->condition == DAV_IF_COND_NOT) {
                        /*
                        ** This state requires that the specified locktoken
                        ** is NOT present on the resource. But we just found
                        ** it. There is no way this state-list can now
                        ** succeed, so go try another one.
                        */
                        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;
                    }

                    /* condition == DAV_IF_COND_NORMAL */

                    /* Validate auth_user:  If an authenticated user created
                    ** the lock, only the same user may submit that locktoken
                    ** to manipulate a resource.
                    */
                    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, errmsg);
                    }

                    /*
                    ** We just matched a specified State-Token to one of the
                    ** resource's locktokens.
                    **
                    ** Break out of the lock scan -- we only needed to find
                    ** one match (actually, there shouldn't be any other
                    ** matches in the lock list).
                    */
                    num_matched = 1;
                    break;
                }

                if (num_matched == 0
                    && state_list->condition == DAV_IF_COND_NORMAL) {
                    /*
                    ** We had a NORMAL state, meaning that we should have
                    ** found the State-Token within the locks on this
                    ** resource. We didn't, so this state_list must fail.
                    */
                    reason =
                        "a State-token was supplied, but it was not found "
                        "in the locks on this resource.";
                    goto state_list_failed;
                }

                break;

            } /* switch */
        } /* foreach ( state_list ) */

        /*
        ** We've checked every state in this state_list and none of them
        ** have failed. Since all of them succeeded, then we have a matching
        ** state list and we may be done.
        **
        ** The next requirement is that we have seen one of the resource's
        ** locktokens (if any). If we have, then we can just exit. If we
        ** haven't, then we need to keep looking.
        */
        if (seen_locktoken) {
            /* woo hoo! */
            return NULL;
        }

        /*
        ** Haven't seen one. Let's break out of the search and just look
        ** for a matching locktoken.
        */
        break;

        /*
        ** This label is used when we detect that a state_list is not
        ** going to match this resource. We bust out and try the next
        ** state_list.
        */
      state_list_failed:
        ;

    } /* foreach ( ifhdr_scan ) */

    /*
    ** The above loop exits for one of two reasons:
    **   1) a state_list matched and seen_locktoken is false.
    **   2) all if_header structures were scanned, without (1) occurring
    */

    if (ifhdr_scan == NULL) {
        /*
        ** We finished the loop without finding any matching state lists.
        */

        /*
        ** If none of the state_lists apply to this resource, then we
        ** may have succeeded. Note that this scenario implies a
        ** tagged-list with no matching state_lists. If the If: header
        ** was a no-tag-list, then it would have applied to this resource.
        **
        ** S9.4.2 states that when no state_lists apply, then the header
        ** should be ignored.
        **
        ** If we saw one of the resource's locktokens, then we're done.
        ** If we did not see a locktoken, then we fail.
        */
        if (num_that_apply == 0) {
            if (seen_locktoken)
                return NULL;

            /*
            ** We may have aborted the scan before seeing the locktoken.
            ** Rescan the If: header to see if we can find the locktoken
            ** somewhere.
            **
            ** Note that seen_locktoken == 0 implies lock_list != NULL
            ** which implies locks_hooks != NULL.
            */
            if (dav_find_submitted_locktoken(if_header, lock_list,
                                             locks_hooks)) {
                /*
                ** We found a match! We're set... none of the If: header
                ** assertions apply (implicit success), and the If: header
                ** specified the locktoken somewhere. We're done.
                */
                return NULL;
            }

            return dav_new_error(p, HTTP_LOCKED, 0 /* error_id */,
                                 "This resource is locked and the \"If:\" "
                                 "header did not specify one of the "
                                 "locktokens for this resource's lock(s).");
        }
        /* else: one or more state_lists were applicable, but failed. */

        /*
        ** If the dummy_header did not match, then they specified an
        ** incorrect token in the Lock-Token header. Forget whether the
        ** If: statement matched or not... we'll tell them about the
        ** bad Lock-Token first. That is considered a 400 (Bad Request).
        */
        if (if_header->dummy_header) {
            return dav_new_error(p, HTTP_BAD_REQUEST, 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,
                                 "The preconditions specified by the \"If:\" "
                                 "header did not match this resource.");
        }

        return dav_new_error(p, HTTP_PRECONDITION_FAILED, 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));
    }

    /* assert seen_locktoken == 0 */

    /*
    ** ifhdr_scan != NULL implies we found a matching state_list.
    **
    ** Since we're still here, it also means that we have not yet found
    ** one the resource's locktokens in the If: header.
    **
    ** Scan all the if_headers and states looking for one of this
    ** resource's locktokens. Note that we need to go back and scan them
    ** all -- we may have aborted a scan with a failure before we saw a
    ** matching token.
    **
    ** Note that seen_locktoken == 0 implies lock_list != NULL which implies
    ** locks_hooks != NULL.
    */
    if (dav_find_submitted_locktoken(if_header, lock_list, locks_hooks)) {
        /*
        ** We found a match! We're set... we have a matching state list,
        ** and the If: header specified the locktoken somewhere. We're done.
        */
        return NULL;
    }

    /*
    ** We had a matching state list, but the user agent did not specify one
    ** of this resource's locktokens. Tell them so.
    **
    ** Note that we need to special-case the message on whether a "dummy"
    ** header exists. If it exists, yet we didn't see a needed locktoken,
    ** then that implies the dummy header (Lock-Token header) did NOT
    ** specify one of this resource's locktokens. (this implies something
    ** in the real If: header matched)
    **
    ** We want to note the 400 (Bad Request) in favor of a 423 (Locked).
    */
    if (if_header->dummy_header) {
        return dav_new_error(p, HTTP_BAD_REQUEST, 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 /* error_id */,
                         "This resource is locked and the \"If:\" header "
                         "did not specify one of the "
                         "locktokens for this resource's lock(s).");
}

/* dav_validate_walker:  Walker callback function to validate resource state */
static dav_error * dav_validate_walker(dav_walk_resource *wres, int calltype)
{
    dav_walker_ctx *ctx = wres->walk_ctx;
    dav_error *err;

    if ((err = dav_validate_resource_state(ctx->w.pool, wres->resource,
                                           ctx->w.lockdb,
                                           ctx->if_header, ctx->flags,
                                           &ctx->work_buf, ctx->r)) == NULL) {
        /* There was no error, so just bug out. */
        return NULL;
    }

    /*
    ** If we have a serious server error, or if the request itself failed,
    ** then just return error (not a multistatus).
    */
    if (ap_is_HTTP_SERVER_ERROR(err->status)
        || (*wres->resource->hooks->is_same_resource)(wres->resource,
                                                      ctx->w.root)) {
        /* ### maybe push a higher-level description? */
        return err;
    }

    /* associate the error with the current URI */
    dav_add_response(wres, err->status, NULL);

    return NULL;
}

/*
** dav_validate_request:  Validate if-headers (and check for locks) on:
**    (1) r->filename @ depth;
**    (2) Parent of r->filename if check_parent == 1
**
** The check of parent should be done when it is necessary to verify that
** the parent collection will accept a new member (ie current resource
** state is null).
**
** Return OK on successful validation.
** On error, return appropriate HTTP_* code, and log error. If a multi-stat
** error is necessary, response will point to it, else NULL.
*/
DAV_DECLARE(dav_error *) dav_validate_request(request_rec *r, 
                                              dav_resource *resource,
                                              int depth,
                                              dav_locktoken *locktoken,
                                              dav_response **response,
                                              int flags,
                                              dav_lockdb *lockdb)
{
    dav_error *err;
    int result;
    dav_if_header *if_header;
    int lock_db_opened_locally = 0;
    const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);
    const dav_hooks_repository *repos_hooks = resource->hooks;

⌨️ 快捷键说明

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