📄 mod_dav.c
字号:
** Note that a failure on the resource itself does not generate a ** multistatus response -- only internal members/collections. */ if ((err = dav_validate_request(r, resource, depth, NULL, &multi_response, DAV_VALIDATE_PARENT | DAV_VALIDATE_USE_424, NULL)) != NULL) { err = dav_push_error(r->pool, err->status, 0, apr_psprintf(r->pool, "Could not DELETE %s due to a failed " "precondition (e.g. locks).", ap_escape_html(r->pool, r->uri)), err); return dav_handle_err(r, err, multi_response); } /* ### RFC 2518 s. 8.10.5 says to remove _all_ locks, not just those * locked by the token(s) in the if_header. */ if ((result = dav_unlock(r, resource, NULL)) != OK) { return result; } /* if versioned resource, make sure parent is checked out */ if ((err = dav_ensure_resource_writable(r, resource, 1 /* parent_only */, &av_info)) != NULL) { /* ### add a higher-level description? */ return dav_handle_err(r, err, NULL); } /* try to remove the resource */ err = (*resource->hooks->remove_resource)(resource, &multi_response); /* restore writability of parent back to what it was */ err2 = dav_revert_resource_writability(r, NULL, err != NULL /* undo if error */, &av_info); /* check for errors now */ if (err != NULL) { err = dav_push_error(r->pool, err->status, 0, apr_psprintf(r->pool, "Could not DELETE %s.", ap_escape_html(r->pool, r->uri)), err); return dav_handle_err(r, err, multi_response); } if (err2 != NULL) { /* just log a warning */ err = dav_push_error(r->pool, err2->status, 0, "The DELETE was successful, but there " "was a problem reverting the writability of " "its parent collection.", err2); dav_log_err(r, err, APLOG_WARNING); } /* ### HTTP_NO_CONTENT if no body, HTTP_OK if there is a body (some day) */ /* Apache will supply a default error for this. */ return HTTP_NO_CONTENT;}/* generate DAV:supported-method-set OPTIONS response */static dav_error *dav_gen_supported_methods(request_rec *r, const ap_xml_elem *elem, const apr_table_t *methods, ap_text_header *body){ apr_array_header_t *arr; apr_table_entry_t *elts; ap_xml_elem *child; ap_xml_attr *attr; char *s; int i; ap_text_append(r->pool, body, "<D:supported-method-set>" DEBUG_CR); if (elem->first_child == NULL) { /* show all supported methods */ arr = apr_table_elts(methods); elts = (apr_table_entry_t *) arr->elts; for (i = 0; i < arr->nelts; ++i) { if (elts[i].key == NULL) continue; s = apr_psprintf(r->pool, "<D:supported-method D:name=\"%s\"/>" DEBUG_CR, elts[i].key); ap_text_append(r->pool, body, s); } } else { /* check for support of specific methods */ for (child = elem->first_child; child != NULL; child = child->next) { if (child->ns == AP_XML_NS_DAV_ID && strcmp(child->name, "supported-method") == 0) { const char *name = NULL; /* go through attributes to find method name */ for (attr = child->attr; attr != NULL; attr = attr->next) { if (attr->ns == AP_XML_NS_DAV_ID && strcmp(attr->name, "name") == 0) name = attr->value; } if (name == NULL) { return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0, "A DAV:supported-method element " "does not have a \"name\" attribute"); } /* see if method is supported */ if (apr_table_get(methods, name) != NULL) { s = apr_psprintf(r->pool, "<D:supported-method D:name=\"%s\"/>" DEBUG_CR, name); ap_text_append(r->pool, body, s); } } } } ap_text_append(r->pool, body, "</D:supported-method-set>" DEBUG_CR); return NULL;}/* generate DAV:supported-live-property-set OPTIONS response */static dav_error *dav_gen_supported_live_props(request_rec *r, const dav_resource *resource, const ap_xml_elem *elem, ap_text_header *body){ dav_lockdb *lockdb; dav_propdb *propdb; ap_xml_elem *child; ap_xml_attr *attr; dav_error *err; /* open lock database, to report on supported lock properties */ /* ### should open read-only */ if ((err = dav_open_lockdb(r, 0, &lockdb)) != NULL) { return dav_push_error(r->pool, err->status, 0, "The lock database could not be opened, " "preventing the reporting of supported lock " "properties.", err); } /* open the property database (readonly) for the resource */ if ((err = dav_open_propdb(r, lockdb, resource, 1, NULL, &propdb)) != NULL) { if (lockdb != NULL) (*lockdb->hooks->close_lockdb)(lockdb); return dav_push_error(r->pool, err->status, 0, "The property database could not be opened, " "preventing report of supported properties.", err); } ap_text_append(r->pool, body, "<D:supported-live-property-set>" DEBUG_CR); if (elem->first_child == NULL) { /* show all supported live properties */ dav_get_props_result props = dav_get_allprops(propdb, DAV_PROP_INSERT_SUPPORTED); body->last->next = props.propstats; while (body->last->next != NULL) body->last = body->last->next; } else { /* check for support of specific live property */ for (child = elem->first_child; child != NULL; child = child->next) { if (child->ns == AP_XML_NS_DAV_ID && strcmp(child->name, "supported-live-property") == 0) { const char *name = NULL; const char *nmspace = NULL; /* go through attributes to find name and namespace */ for (attr = child->attr; attr != NULL; attr = attr->next) { if (attr->ns == AP_XML_NS_DAV_ID) { if (strcmp(attr->name, "name") == 0) name = attr->value; else if (strcmp(attr->name, "namespace") == 0) nmspace = attr->value; } } if (name == NULL) { err = dav_new_error(r->pool, HTTP_BAD_REQUEST, 0, "A DAV:supported-live-property " "element does not have a \"name\" " "attribute"); break; } /* default namespace to DAV: */ if (nmspace == NULL) nmspace = "DAV:"; /* check for support of property */ dav_get_liveprop_supported(propdb, nmspace, name, body); } } } ap_text_append(r->pool, body, "</D:supported-live-property-set>" DEBUG_CR); dav_close_propdb(propdb); if (lockdb != NULL) (*lockdb->hooks->close_lockdb)(lockdb); return err;}/* generate DAV:supported-report-set OPTIONS response */static dav_error *dav_gen_supported_reports(request_rec *r, const dav_resource *resource, const ap_xml_elem *elem, const dav_hooks_vsn *vsn_hooks, ap_text_header *body){ ap_xml_elem *child; ap_xml_attr *attr; dav_error *err; char *s; ap_text_append(r->pool, body, "<D:supported-report-set>" DEBUG_CR); if (vsn_hooks != NULL) { const dav_report_elem *reports; const dav_report_elem *rp; if ((err = (*vsn_hooks->avail_reports)(resource, &reports)) != NULL) { return dav_push_error(r->pool, err->status, 0, "DAV:supported-report-set could not be " "determined due to a problem fetching the " "available reports for this resource.", err); } if (reports != NULL) { if (elem->first_child == NULL) { /* show all supported reports */ for (rp = reports; rp->nmspace != NULL; ++rp) { /* Note: we presume reports->namespace is properly XML/URL quoted */ s = apr_psprintf(r->pool, "<D:supported-report D:name=\"%s\" D:namespace=\"%s\"/>" DEBUG_CR, rp->name, rp->nmspace); ap_text_append(r->pool, body, s); } } else { /* check for support of specific report */ for (child = elem->first_child; child != NULL; child = child->next) { if (child->ns == AP_XML_NS_DAV_ID && strcmp(child->name, "supported-report") == 0) { const char *name = NULL; const char *nmspace = NULL; /* go through attributes to find name and namespace */ for (attr = child->attr; attr != NULL; attr = attr->next) { if (attr->ns == AP_XML_NS_DAV_ID) { if (strcmp(attr->name, "name") == 0) name = attr->value; else if (strcmp(attr->name, "namespace") == 0) nmspace = attr->value; } } if (name == NULL) { return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0, "A DAV:supported-report element " "does not have a \"name\" attribute"); } /* default namespace to DAV: */ if (nmspace == NULL) nmspace = "DAV:"; for (rp = reports; rp->nmspace != NULL; ++rp) { if (strcmp(name, rp->name) == 0 && strcmp(nmspace, rp->nmspace) == 0) { /* Note: we presume reports->nmspace is properly XML/URL quoted */ s = apr_psprintf(r->pool, "<D:supported-report D:name=\"%s\" D:namespace=\"%s\"/>" DEBUG_CR, rp->name, rp->nmspace); ap_text_append(r->pool, body, s); break; } } } } } } } ap_text_append(r->pool, body, "</D:supported-report-set>" DEBUG_CR); return NULL;}/* handle the OPTIONS method */static int dav_method_options(request_rec *r){ const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r); const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r); const dav_hooks_binding *binding_hooks = DAV_GET_HOOKS_BINDING(r); dav_resource *resource; const char *dav_level; char *allow; char *s; apr_array_header_t *arr; apr_table_entry_t *elts; apr_table_t *methods = apr_table_make(r->pool, 12); ap_text_header vsn_options = { 0 }; ap_text_header body = { 0 }; ap_text *t; int text_size; int result; int i; apr_array_header_t *uri_ary; ap_xml_doc *doc; const ap_xml_elem *elem; dav_error *err; /* resolve the resource */ err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */, &resource); if (err != NULL) return dav_handle_err(r, err, NULL); /* parse any request body */ if ((result = ap_xml_parse_input(r, &doc)) != OK) { return result; } /* note: doc == NULL if no request body */ if (doc && !dav_validate_root(doc, "options")) { ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, "The \"options\" element was not found."); return HTTP_BAD_REQUEST; } /* determine which providers are available */ dav_level = "1"; if (locks_hooks != NULL) { dav_level = "1,2"; } if (binding_hooks != NULL) dav_level = apr_pstrcat(r->pool, dav_level, ",bindings", NULL); /* ### ** MSFT Web Folders chokes if length of DAV header value > 63 characters! ** To workaround that, we use separate DAV headers for versioning and ** live prop provider namespace URIs. ** ### */ apr_table_setn(r->headers_out, "DAV", dav_level); /* ** If there is a versioning provider, generate DAV headers ** for versioning options. */ if (vsn_hooks != NULL) { (*vsn_hooks->get_vsn_options)(r->pool, &vsn_options); for (t = vsn_options.first; t != NULL; t = t->next) apr_table_addn(r->headers_out, "DAV", t->text); } /* ** Gather property set URIs from all the liveprop providers, ** and generate a separate DAV header for each URI, to avoid ** problems with long header lengths. */ uri_ary = apr_array_make(r->pool, 5, sizeof(const char *)); dav_run_gather_propsets(uri_ary); for (i = 0; i < uri_ary->nelts; ++i) { if (((char **)uri_ary->elts)[i] != NULL) apr_table_addn(r->headers_out, "DAV", ((char **)uri_ary->elts)[i]); } /* this tells MSFT products to skip looking for FrontPage extensions */ apr_table_setn(r->headers_out, "MS-Author-Via", "DAV"); /* ** Determine which methods are allowed on the resource. ** Three cases: resource is null (3), is lock-null (7.4), or exists. ** ** All cases support OPTIONS, and if there is a lock provider, LOCK. ** (Lock-) null resources also support MKCOL and PUT. ** Lock-null supports PROPFIND and UNLOCK. ** Existing resources support lots of stuff. */ apr_table_addn(methods, "OPTIONS", ""); /* ### take into account resource type */ switch (dav_get_resource_state(r, resource)) { case DAV_RESOURCE_EXISTS:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -