Loading modules/dav/main/mod_dav.c +133 −4 Original line number Diff line number Diff line Loading @@ -357,7 +357,7 @@ static const char *dav_cmd_davparam(cmd_parms *cmd, void *config, static int dav_error_response(request_rec *r, int status, const char *body) { r->status = status; r->status_line = ap_get_status_line(status); r->status_line = ap_get_status_line(status); /* ### needed? */ r->content_type = "text/html"; /* since we're returning DONE, ensure the request body is consumed. */ Loading Loading @@ -397,7 +397,7 @@ static const char *dav_xml_escape_uri(apr_pool_t *p, const char *uri) if (ap_strchr_c(e_uri, '&') == NULL) return e_uri; /* more work needed... sigh. */ /* there was a '&', so more work is needed... sigh. */ /* ** Note: this is a teeny bit of overkill since we know there are no Loading Loading @@ -4054,8 +4054,137 @@ static int dav_method_baseline_control(request_rec *r) static int dav_method_merge(request_rec *r) { /* ### */ return HTTP_METHOD_NOT_ALLOWED; dav_resource *resource; dav_resource *source_resource; const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r); dav_error *err; int result; ap_xml_doc *doc; ap_xml_elem *source_elem; ap_xml_elem *href_elem; ap_xml_elem *prop_elem; const char *source; int no_auto_merge; int no_checkout; dav_lookup_result lookup; /* If no versioning provider, decline the request */ if (vsn_hooks == NULL) return DECLINED; if ((result = ap_xml_parse_input(r, &doc)) != OK) return result; if (doc == NULL || !dav_validate_root(doc, "merge")) { /* This supplies additional information for the default msg. */ ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, "The request body must be present and must be a " "DAV:merge element."); return HTTP_BAD_REQUEST; } if ((source_elem = dav_find_child(doc->root, "source")) == NULL) { /* This supplies additional information for the default msg. */ ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, "The DAV:merge element must contain a DAV:source " "element."); return HTTP_BAD_REQUEST; } if ((href_elem = dav_find_child(source_elem, "href")) == NULL) { /* This supplies additional information for the default msg. */ ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, "The DAV:source element must contain a DAV:href " "element."); return HTTP_BAD_REQUEST; } source = dav_xml_get_cdata(href_elem, r->pool, 1 /* strip_white */); /* get a subrequest for the source, so that we can get a dav_resource for that source. */ lookup = dav_lookup_uri(source, r); if (lookup.rnew == NULL) { if (lookup.err.status == HTTP_BAD_REQUEST) { /* This supplies additional information for the default message. */ ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, lookup.err.desc); return HTTP_BAD_REQUEST; } /* ### this assumes that dav_lookup_uri() only generates a status * ### that Apache can provide a status line for!! */ return dav_error_response(r, lookup.err.status, lookup.err.desc); } if (lookup.rnew->status != HTTP_OK) { /* ### how best to report this... */ return dav_error_response(r, lookup.rnew->status, "Merge source URI had an error."); } err = dav_get_resource(lookup.rnew, 0 /* label_allowed */, 0 /* use_checked_in */, &source_resource); if (err != NULL) return dav_handle_err(r, err, NULL); no_auto_merge = dav_find_child(doc->root, "no-auto-merge") != NULL; no_checkout = dav_find_child(doc->root, "no-checkout") != NULL; prop_elem = dav_find_child(doc->root, "prop"); /* ### check RFC. I believe the DAV:merge element may contain any ### element also allowed within DAV:checkout. need to extract them ### here, and pass them along. ### if so, then refactor the CHECKOUT method handling so we can reuse ### the code. maybe create a structure to hold CHECKOUT parameters ### which can be passed to the checkout() and merge() hooks. */ /* Ask repository module to 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); if (!resource->exists) { /* Apache will supply a default error for this. */ return HTTP_NOT_FOUND; } /* ### check the source and target resources flags/types */ /* ### do lock checks, once behavior is defined */ /* set the Cache-Control header, per the spec */ /* ### correct? */ apr_table_setn(r->headers_out, "Cache-Control", "no-cache"); /* Initialize these values for a standard MERGE response. If the MERGE is going to do something different (i.e. an error), then it must return a dav_error, and we'll reset these values properly. */ r->status = HTTP_OK; r->status_line = ap_get_status_line(HTTP_OK); /* ### needed? */ r->content_type = "text/xml"; /* ### should we do any preliminary response generation? probably not, ### because we may have an error, thus demanding something else in ### the response body. */ /* Do the merge, including any response generation. */ if ((err = (*vsn_hooks->merge)(resource, source_resource, no_auto_merge, no_checkout, prop_elem, r->output_filters)) != NULL) { /* ### is err->status the right error here? */ err = dav_push_error(r->pool, err->status, 0, apr_psprintf(r->pool, "Could not MERGE resource \"%s\" " "into \"%s\".", ap_escape_html(r->pool, source), ap_escape_html(r->pool, r->uri)), err); return dav_handle_err(r, err, NULL); } /* the response was fully generated by the merge() hook. */ /* ### urk. does this prevent logging? need to check... */ return DONE; } static int dav_method_bind(request_rec *r) Loading modules/dav/main/mod_dav.h +14 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ #include "apr_tables.h" #include "httpd.h" #include "util_filter.h" #include "util_xml.h" #include <limits.h> /* for INT_MAX */ Loading Loading @@ -2112,6 +2113,19 @@ struct dav_hooks_vsn ** it should be set to NULL. */ dav_error * (*make_activity)(dav_resource *resource); /* ** Merge a resource (tree) into target resource (tree). ** ** ### more doc... ** ** This hook is optional; if the provider does not support merging, ** then this should be set to NULL. */ dav_error * (*merge)(dav_resource *target, dav_resource *source, int no_auto_merge, int no_checkout, ap_xml_elem *prop_elem, ap_filter_t *output); }; Loading Loading
modules/dav/main/mod_dav.c +133 −4 Original line number Diff line number Diff line Loading @@ -357,7 +357,7 @@ static const char *dav_cmd_davparam(cmd_parms *cmd, void *config, static int dav_error_response(request_rec *r, int status, const char *body) { r->status = status; r->status_line = ap_get_status_line(status); r->status_line = ap_get_status_line(status); /* ### needed? */ r->content_type = "text/html"; /* since we're returning DONE, ensure the request body is consumed. */ Loading Loading @@ -397,7 +397,7 @@ static const char *dav_xml_escape_uri(apr_pool_t *p, const char *uri) if (ap_strchr_c(e_uri, '&') == NULL) return e_uri; /* more work needed... sigh. */ /* there was a '&', so more work is needed... sigh. */ /* ** Note: this is a teeny bit of overkill since we know there are no Loading Loading @@ -4054,8 +4054,137 @@ static int dav_method_baseline_control(request_rec *r) static int dav_method_merge(request_rec *r) { /* ### */ return HTTP_METHOD_NOT_ALLOWED; dav_resource *resource; dav_resource *source_resource; const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r); dav_error *err; int result; ap_xml_doc *doc; ap_xml_elem *source_elem; ap_xml_elem *href_elem; ap_xml_elem *prop_elem; const char *source; int no_auto_merge; int no_checkout; dav_lookup_result lookup; /* If no versioning provider, decline the request */ if (vsn_hooks == NULL) return DECLINED; if ((result = ap_xml_parse_input(r, &doc)) != OK) return result; if (doc == NULL || !dav_validate_root(doc, "merge")) { /* This supplies additional information for the default msg. */ ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, "The request body must be present and must be a " "DAV:merge element."); return HTTP_BAD_REQUEST; } if ((source_elem = dav_find_child(doc->root, "source")) == NULL) { /* This supplies additional information for the default msg. */ ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, "The DAV:merge element must contain a DAV:source " "element."); return HTTP_BAD_REQUEST; } if ((href_elem = dav_find_child(source_elem, "href")) == NULL) { /* This supplies additional information for the default msg. */ ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, "The DAV:source element must contain a DAV:href " "element."); return HTTP_BAD_REQUEST; } source = dav_xml_get_cdata(href_elem, r->pool, 1 /* strip_white */); /* get a subrequest for the source, so that we can get a dav_resource for that source. */ lookup = dav_lookup_uri(source, r); if (lookup.rnew == NULL) { if (lookup.err.status == HTTP_BAD_REQUEST) { /* This supplies additional information for the default message. */ ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r, lookup.err.desc); return HTTP_BAD_REQUEST; } /* ### this assumes that dav_lookup_uri() only generates a status * ### that Apache can provide a status line for!! */ return dav_error_response(r, lookup.err.status, lookup.err.desc); } if (lookup.rnew->status != HTTP_OK) { /* ### how best to report this... */ return dav_error_response(r, lookup.rnew->status, "Merge source URI had an error."); } err = dav_get_resource(lookup.rnew, 0 /* label_allowed */, 0 /* use_checked_in */, &source_resource); if (err != NULL) return dav_handle_err(r, err, NULL); no_auto_merge = dav_find_child(doc->root, "no-auto-merge") != NULL; no_checkout = dav_find_child(doc->root, "no-checkout") != NULL; prop_elem = dav_find_child(doc->root, "prop"); /* ### check RFC. I believe the DAV:merge element may contain any ### element also allowed within DAV:checkout. need to extract them ### here, and pass them along. ### if so, then refactor the CHECKOUT method handling so we can reuse ### the code. maybe create a structure to hold CHECKOUT parameters ### which can be passed to the checkout() and merge() hooks. */ /* Ask repository module to 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); if (!resource->exists) { /* Apache will supply a default error for this. */ return HTTP_NOT_FOUND; } /* ### check the source and target resources flags/types */ /* ### do lock checks, once behavior is defined */ /* set the Cache-Control header, per the spec */ /* ### correct? */ apr_table_setn(r->headers_out, "Cache-Control", "no-cache"); /* Initialize these values for a standard MERGE response. If the MERGE is going to do something different (i.e. an error), then it must return a dav_error, and we'll reset these values properly. */ r->status = HTTP_OK; r->status_line = ap_get_status_line(HTTP_OK); /* ### needed? */ r->content_type = "text/xml"; /* ### should we do any preliminary response generation? probably not, ### because we may have an error, thus demanding something else in ### the response body. */ /* Do the merge, including any response generation. */ if ((err = (*vsn_hooks->merge)(resource, source_resource, no_auto_merge, no_checkout, prop_elem, r->output_filters)) != NULL) { /* ### is err->status the right error here? */ err = dav_push_error(r->pool, err->status, 0, apr_psprintf(r->pool, "Could not MERGE resource \"%s\" " "into \"%s\".", ap_escape_html(r->pool, source), ap_escape_html(r->pool, r->uri)), err); return dav_handle_err(r, err, NULL); } /* the response was fully generated by the merge() hook. */ /* ### urk. does this prevent logging? need to check... */ return DONE; } static int dav_method_bind(request_rec *r) Loading
modules/dav/main/mod_dav.h +14 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ #include "apr_tables.h" #include "httpd.h" #include "util_filter.h" #include "util_xml.h" #include <limits.h> /* for INT_MAX */ Loading Loading @@ -2112,6 +2113,19 @@ struct dav_hooks_vsn ** it should be set to NULL. */ dav_error * (*make_activity)(dav_resource *resource); /* ** Merge a resource (tree) into target resource (tree). ** ** ### more doc... ** ** This hook is optional; if the provider does not support merging, ** then this should be set to NULL. */ dav_error * (*merge)(dav_resource *target, dav_resource *source, int no_auto_merge, int no_checkout, ap_xml_elem *prop_elem, ap_filter_t *output); }; Loading