📄 util.c
字号:
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; case dav_if_unknown: /* Request is predicated on some unknown state token, * which must be presumed to *not* match, so fail * unless this is a Not condition. */ if (state_list->condition == DAV_IF_COND_NORMAL) { reason = "an unknown state token was supplied"; 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; dav_buffer work_buf = { 0 }; dav_response *new_response;#if DAV_DEBUG if (depth && response == NULL) { /* ** ### bleck. we can't return errors for other URIs unless we have ** ### a "response" ptr. */ return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "DESIGN ERROR: dav_validate_request called " "with depth>0, but no response ptr."); }#endif if (response != NULL) *response = NULL; /* Do the standard checks for conditional requests using
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -