📄 util.c
字号:
"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; 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;}/* If-* header checking */static int dav_meets_conditions(request_rec *r, int resource_state){ const char *if_match, *if_none_match; int retVal; /* If-Match '*' fix. Resource existence not checked by ap_meets_conditions. * If-Match '*' request should succeed only if the resource exists. */ if ((if_match = apr_table_get(r->headers_in, "If-Match")) != NULL) { if (if_match[0] == '*' && resource_state != DAV_RESOURCE_EXISTS) return HTTP_PRECONDITION_FAILED; } retVal = ap_meets_conditions(r); /* If-None-Match '*' fix. If-None-Match '*' request should succeed * if the resource does not exist. */ if (retVal == HTTP_PRECONDITION_FAILED) { /* Note. If if_none_match != NULL, if_none_match is the culprit. * Since, in presence of If-None-Match, * other If-* headers are undefined. */ if ((if_none_match = apr_table_get(r->headers_in, "If-None-Match")) != NULL) { if (if_none_match[0] == '*' && resource_state != DAV_RESOURCE_EXISTS) { return OK; } } } return retVal;}/*** dav_validate_request: Validate if-headers (and check for locks) on:** (1) r->filename @ depth;** (2) Parent of r->filename if check_parent == 1**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -