📄 util.c
字号:
ifhdr_new->uri_len = strlen(resource->uri); ifhdr_new->dummy_header = 1; ifhdr_new->state = apr_pcalloc(r->pool, sizeof(*ifhdr_new->state)); ifhdr_new->state->type = dav_if_opaquelock; ifhdr_new->state->condition = DAV_IF_COND_NORMAL; ifhdr_new->state->locktoken = locktoken; ifhdr_new->next = if_header; if_header = ifhdr_new; } /* ** If necessary, open the lock database (read-only, lazily); ** the validation process may need to retrieve or update lock info. ** Otherwise, assume provided lockdb is valid and opened rw. */ if (lockdb == NULL) { if (locks_hooks != NULL) { if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, &lockdb)) != NULL) { /* ### maybe insert higher-level comment */ return err; } lock_db_opened_locally = 1; } } /* (1) Validate the specified resource, at the specified depth */ if (resource->exists && depth > 0) { dav_walker_ctx ctx = { { 0 } }; dav_response *multi_status; ctx.w.walk_type = DAV_WALKTYPE_NORMAL; ctx.w.func = dav_validate_walker; ctx.w.walk_ctx = &ctx; ctx.w.pool = r->pool; ctx.w.root = resource; ctx.if_header = if_header; ctx.r = r; ctx.flags = flags; if (lockdb != NULL) { ctx.w.lockdb = lockdb; ctx.w.walk_type |= DAV_WALKTYPE_LOCKNULL; } err = (*repos_hooks->walk)(&ctx.w, DAV_INFINITY, &multi_status); if (err == NULL) { *response = multi_status;; } /* else: implies a 5xx status code occurred. */ } else { err = dav_validate_resource_state(r->pool, resource, lockdb, if_header, flags, &work_buf, r); } /* (2) Validate the parent resource if requested */ if (err == NULL && (flags & DAV_VALIDATE_PARENT)) { dav_resource *parent_resource; err = (*repos_hooks->get_parent_resource)(resource, &parent_resource); if (err == NULL && parent_resource == NULL) { err = dav_new_error(r->pool, HTTP_FORBIDDEN, 0, "Cannot access parent of repository root."); } else if (err == NULL) { err = dav_validate_resource_state(r->pool, parent_resource, lockdb, if_header, flags | DAV_VALIDATE_IS_PARENT, &work_buf, r); /* ** This error occurred on the parent resource. This implies that ** we have to create a multistatus response (to report the error ** against a URI other than the Request-URI). "Convert" this error ** into a multistatus response. */ if (err != NULL) { new_response = apr_pcalloc(r->pool, sizeof(*new_response)); new_response->href = parent_resource->uri; new_response->status = err->status; new_response->desc = "A validation error has occurred on the parent resource, " "preventing the operation on the resource specified by " "the Request-URI."; if (err->desc != NULL) { new_response->desc = apr_pstrcat(r->pool, new_response->desc, " The error was: ", err->desc, NULL); } /* assert: DAV_VALIDATE_PARENT implies response != NULL */ new_response->next = *response; *response = new_response; err = NULL; } } } if (lock_db_opened_locally) (*locks_hooks->close_lockdb)(lockdb); /* ** If we don't have a (serious) error, and we have multistatus responses, ** then we need to construct an "error". This error will be the overall ** status returned, and the multistatus responses will go into its body. ** ** For certain methods, the overall error will be a 424. The default is ** to construct a standard 207 response. */ if (err == NULL && response != NULL && *response != NULL) { ap_text *propstat = NULL; if ((flags & DAV_VALIDATE_USE_424) != 0) { /* manufacture a 424 error to hold the multistatus response(s) */ return dav_new_error(r->pool, HTTP_FAILED_DEPENDENCY, 0, "An error occurred on another resource, " "preventing the requested operation on " "this resource."); } /* ** Whatever caused the error, the Request-URI should have a 424 ** associated with it since we cannot complete the method. ** ** For a LOCK operation, insert an empty DAV:lockdiscovery property. ** For other methods, return a simple 424. */ if ((flags & DAV_VALIDATE_ADD_LD) != 0) { propstat = apr_pcalloc(r->pool, sizeof(*propstat)); propstat->text = "<D:propstat>" DEBUG_CR "<D:prop><D:lockdiscovery/></D:prop>" DEBUG_CR "<D:status>HTTP/1.1 424 Failed Dependency</D:status>" DEBUG_CR "</D:propstat>" DEBUG_CR; } /* create the 424 response */ new_response = apr_pcalloc(r->pool, sizeof(*new_response)); new_response->href = resource->uri; new_response->status = HTTP_FAILED_DEPENDENCY; new_response->propresult.propstats = propstat; new_response->desc = "An error occurred on another resource, preventing the " "requested operation on this resource."; new_response->next = *response; *response = new_response; /* manufacture a 207 error for the multistatus response(s) */ return dav_new_error(r->pool, HTTP_MULTI_STATUS, 0, "Error(s) occurred on resources during the " "validation process."); } return err;}/* dav_get_locktoken_list: * * Sets ltl to a locktoken_list of all positive locktokens in header, * else NULL if no If-header, or no positive locktokens. */dav_error * dav_get_locktoken_list(request_rec *r, dav_locktoken_list **ltl) { dav_error *err; dav_if_header *if_header; dav_if_state_list *if_state; dav_locktoken_list *lock_token = NULL; *ltl = NULL; if ((err = dav_process_if_header(r, &if_header)) != NULL) { /* ### add a higher-level description? */ return err; } while (if_header != NULL) { if_state = if_header->state; /* Begining of the if_state linked list */ while (if_state != NULL) { if (if_state->condition == DAV_IF_COND_NORMAL && if_state->type == dav_if_opaquelock) { lock_token = apr_pcalloc(r->pool, sizeof(dav_locktoken_list)); lock_token->locktoken = if_state->locktoken; lock_token->next = *ltl; *ltl = lock_token; } if_state = if_state->next; } if_header = if_header->next; } if (*ltl == NULL) { /* No nodes added */ return dav_new_error(r->pool, HTTP_BAD_REQUEST, DAV_ERR_IF_ABSENT, "No locktokens were specified in the \"If:\" " "header, so the refresh could not be performed."); } return NULL;}#if 0 /* not needed right now... */static const char *strip_white(const char *s, apr_pool_t *pool){ apr_size_t idx; /* trim leading whitespace */ while (apr_isspace(*s)) /* assume: return false for '\0' */ ++s; /* trim trailing whitespace */ idx = strlen(s) - 1; if (apr_isspace(s[idx])) { char *s2 = apr_pstrdup(pool, s); while (apr_isspace(s2[idx]) && idx > 0) --idx; s2[idx + 1] = '\0'; return s2; } return s;}#endif#define DAV_LABEL_HDR "Label"/* dav_add_vary_header * * If there were any headers in the request which require a Vary header * in the response, add it. */void dav_add_vary_header(request_rec *in_req, request_rec *out_req, const dav_resource *resource){ const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(in_req); /* ### this is probably all wrong... I think there is a function in ### the Apache API to add things to the Vary header. need to check */ /* Only versioning headers require a Vary response header, * so only do this check if there is a versioning provider */ if (vsn_hooks != NULL) { const char *target = apr_table_get(in_req->headers_in, DAV_LABEL_HDR); const char *vary = apr_table_get(out_req->headers_out, "Vary"); /* If Target-Selector specified, add it to the Vary header */ if (target != NULL) { if (vary == NULL) vary = DAV_LABEL_HDR; else vary = apr_pstrcat(out_req->pool, vary, "," DAV_LABEL_HDR, NULL); apr_table_setn(out_req->headers_out, "Vary", vary); } }}/* see mod_dav.h for docco */dav_error *dav_ensure_resource_writable(request_rec *r, dav_resource *resource, int parent_only, dav_auto_version_info *av_info){ const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r); const char *body; dav_error *err; /* Initialize results */ memset(av_info, 0, sizeof(*av_info)); /* check parent resource if requested or if resource must be created */ if (!resource->exists || parent_only) { dav_resource *parent; if ((err = (*resource->hooks->get_parent_resource)(resource, &parent)) != NULL) return err; if (parent == NULL || !parent->exists) { body = apr_psprintf(r->pool, "Missing one or more intermediate collections. " "Cannot create resource %s.", ap_escape_html(r->pool, resource->uri)); return dav_new_error(r->pool, HTTP_CONFLICT, 0, body); } av_info->parent_resource = parent; /* if parent not versioned, assume child can be created */ if (!parent->versioned) { return NULL; } /* if no versioning provider, something is terribly wrong */ if (vsn_hooks == NULL) { return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "INTERNAL ERROR: " "versioned resource with no versioning " "provider?"); } /* parent must be checked out */ if (!parent->working) { /* if parent cannot be automatically checked out, fail */ if (!(*vsn_hooks->auto_version_enabled)(parent)) { body = apr_psprintf(r->pool, "Parent collection must be checked out. " "Cannot create resource %s.", ap_escape_html(r->pool, resource->uri)); return dav_new_error(r->pool, HTTP_CONFLICT, 0, body); } /* Try to checkout the parent collection. * Note that auto-versioning can only be applied to a version selector, * so no separate working resource will be created. */ if ((err = (*vsn_hooks->checkout)(parent, 0, 0, 0, NULL, NULL)) != NULL) { body = apr_psprintf(r->pool, "Unable to checkout parent collection. " "Cannot create resource %s.", ap_escape_html(r->pool, resource->uri)); return dav_push_error(r->pool, HTTP_CONFLICT, 0, body, err); } /* remember that parent was checked out */ av_info->parent_checkedout = 1; } /* if not just checking parent, create new child resource */ if (!parent_only) { if ((err = (*vsn_hooks->vsn_control)(resource, NULL)) != NULL) { body = apr_psprintf(r->pool, "Unable to create versioned resource %s.", ap_escape_html(r->pool, resource->uri)); return dav_push_error(r->pool, HTTP_CONFLICT, 0, body, err); } /* remember that resource was created */ av_info->resource_created = 1; } } else if (!resource->versioned) { /* resource exists and is not versioned; assume it is writable */ return NULL; } /* if not just checking parent, make sure child resource is checked out */ if (!parent_only && !resource->working) { /* Auto-versioning can only be applied to version selectors, so * no separate working resource will be created. */ if ((err = (*vsn_hooks->checkout)(resource, 0, 0, 0, NULL, NULL)) != NULL) { body = apr_psprintf(r->pool, "Unable to checkout resource %s.", ap_escape_html(r->pool, resource->uri)); return dav_push_error(r->pool, HTTP_CONFLICT, 0, body, err); } /* remember that resource was checked out */ av_info->resource_checkedout = 1; } return NULL;}/* see mod_dav.h for docco */dav_error *dav_revert_resource_writability( request_rec *r, dav_resource *resource, int undo, const dav_auto_version_info *av_info){ const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r); const char *body; dav_error *err; /* If a resource was provided, restore its writable state. * Otherwise, only the parent must have been modified */ if (resource != NULL) { if (av_info->resource_checkedout) { if (undo) err = (*vsn_hooks->uncheckout)(resource); else err = (*vsn_hooks->checkin)(resource, NULL); if (err != NULL) { body = apr_psprintf(r->pool, "Unable to %s resource %s.", undo ? "uncheckout" : "checkin", ap_escape_html(r->pool, resource->uri)); return dav_push_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, body, err); } } /* If undoing because of an error, and the resource was created, * then remove it */ if (undo && av_info->resource_created) { dav_response *response; /* ### should we do anything with the response? */ if ((err = (*resource->hooks->remove_resource)(resource, &response)) != NULL) { body = apr_psprintf(r->pool, "Unable to undo creation of resource %s.", ap_escape_html(r->pool, resource->uri)); return dav_push_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, body, err); } } } /* If parent resource was made writable, restore its state */ if (av_info->parent_resource != NULL && av_info->parent_checkedout) { if (undo) err = (*vsn_hooks->uncheckout)(av_info->parent_resource); else err = (*vsn_hooks->checkin)(av_info->parent_resource, NULL); if (err != NULL) { body = apr_psprintf(r->pool, "Unable to %s parent collection %s.", undo ? "uncheckout" : "checkin", ap_escape_html(r->pool, av_info->parent_resource->uri)); return dav_push_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, body, err); } } return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -