diff options
Diffstat (limited to 'subversion/mod_dav_svn/reports/inherited-props.c')
-rw-r--r-- | subversion/mod_dav_svn/reports/inherited-props.c | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/subversion/mod_dav_svn/reports/inherited-props.c b/subversion/mod_dav_svn/reports/inherited-props.c new file mode 100644 index 0000000..ce0f4de --- /dev/null +++ b/subversion/mod_dav_svn/reports/inherited-props.c @@ -0,0 +1,236 @@ +/* + * inherited-props.c: mod_dav_svn REPORT handler for querying inherited props. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include <apr_pools.h> +#include <apr_strings.h> +#include <apr_xml.h> + +#include <http_request.h> +#include <http_log.h> +#include <mod_dav.h> + +#include "svn_pools.h" +#include "svn_repos.h" +#include "svn_xml.h" +#include "svn_path.h" +#include "svn_dav.h" +#include "svn_props.h" +#include "svn_base64.h" + +#include "private/svn_fspath.h" +#include "private/svn_dav_protocol.h" +#include "private/svn_log.h" +#include "private/svn_mergeinfo_private.h" + +#include "../dav_svn.h" + +dav_error * +dav_svn__get_inherited_props_report(const dav_resource *resource, + const apr_xml_doc *doc, + ap_filter_t *output) +{ + svn_error_t *serr; + dav_error *derr = NULL; + apr_xml_elem *child; + apr_array_header_t *inherited_props; + dav_svn__authz_read_baton arb; + int ns; + apr_bucket_brigade *bb; + const char *path = "/"; + svn_fs_root_t *root; + int i; + svn_revnum_t rev = SVN_INVALID_REVNUM; + apr_pool_t *iterpool; + + /* Sanity check. */ + if (!resource->info->repos_path) + return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, + "The request does not specify a repository path"); + ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); + if (ns == -1) + { + return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0, + "The request does not contain the 'svn:' " + "namespace, so it is not going to have " + "certain required elements.", + SVN_DAV_ERROR_NAMESPACE, + SVN_DAV_ERROR_TAG); + } + + iterpool = svn_pool_create(resource->pool); + + for (child = doc->root->first_child; + child != NULL; + child = child->next) + { + /* if this element isn't one of ours, then skip it */ + if (child->ns != ns) + continue; + + if (strcmp(child->name, SVN_DAV__REVISION) == 0) + { + rev = SVN_STR_TO_REV(dav_xml_get_cdata(child, iterpool, 1)); + } + else if (strcmp(child->name, SVN_DAV__PATH) == 0) + { + path = dav_xml_get_cdata(child, resource->pool, 0); + if ((derr = dav_svn__test_canonical(path, iterpool))) + return derr; + path = svn_fspath__join(resource->info->repos_path, path, + resource->pool); + } + /* else unknown element; skip it */ + } + + /* Build authz read baton */ + arb.r = resource->info->r; + arb.repos = resource->info->repos; + + /* Build inherited property brigade */ + bb = apr_brigade_create(resource->pool, output->c->bucket_alloc); + + serr = svn_fs_revision_root(&root, resource->info->repos->fs, + rev, resource->pool); + if (serr != NULL) + return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, + "couldn't retrieve revision root", + resource->pool); + + serr = svn_repos_fs_get_inherited_props(&inherited_props, root, path, NULL, + dav_svn__authz_read_func(&arb), + &arb, resource->pool, iterpool); + if (serr) + { + derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST, serr->message, + resource->pool); + goto cleanup; + } + + serr = dav_svn__brigade_puts(bb, output, + DAV_XML_HEADER DEBUG_CR + "<S:" SVN_DAV__INHERITED_PROPS_REPORT " " + "xmlns:S=\"" SVN_XML_NAMESPACE "\" " + "xmlns:D=\"DAV:\">" DEBUG_CR); + if (serr) + { + derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST, serr->message, + resource->pool); + goto cleanup; + } + + for (i = 0; i < inherited_props->nelts; i++) + { + svn_prop_inherited_item_t *elt = + APR_ARRAY_IDX(inherited_props, i, svn_prop_inherited_item_t *); + + svn_pool_clear(iterpool); + + serr = dav_svn__brigade_printf( + bb, output, + "<S:" SVN_DAV__IPROP_ITEM ">" + DEBUG_CR + "<S:" SVN_DAV__IPROP_PATH ">%s</S:" SVN_DAV__IPROP_PATH ">" + DEBUG_CR, + apr_xml_quote_string(resource->pool, elt->path_or_url, 0)); + + if (!serr) + { + apr_hash_index_t *hi; + + for (hi = apr_hash_first(resource->pool, elt->prop_hash); + hi; + hi = apr_hash_next(hi)) + { + const char *propname = svn__apr_hash_index_key(hi); + svn_string_t *propval = svn__apr_hash_index_val(hi); + const char *xml_safe; + + serr = dav_svn__brigade_printf( + bb, output, + "<S:" SVN_DAV__IPROP_PROPNAME ">%s</S:" + SVN_DAV__IPROP_PROPNAME ">" DEBUG_CR, + apr_xml_quote_string(iterpool, propname, 0)); + + if (!serr) + { + if (svn_xml_is_xml_safe(propval->data, propval->len)) + { + svn_stringbuf_t *tmp = NULL; + svn_xml_escape_cdata_string(&tmp, propval, + iterpool); + xml_safe = tmp->data; + serr = dav_svn__brigade_printf( + bb, output, + "<S:" SVN_DAV__IPROP_PROPVAL ">%s</S:" + SVN_DAV__IPROP_PROPVAL ">" DEBUG_CR, xml_safe); + } + else + { + xml_safe = svn_base64_encode_string2( + propval, TRUE, iterpool)->data; + serr = dav_svn__brigade_printf( + bb, output, + "<S:" SVN_DAV__IPROP_PROPVAL + " encoding=\"base64\"" ">%s</S:" + SVN_DAV__IPROP_PROPVAL ">" DEBUG_CR, xml_safe); + } + } + + if (serr) + break; + } + if (!serr) + serr = dav_svn__brigade_printf(bb, output, + "</S:" SVN_DAV__IPROP_ITEM ">" + DEBUG_CR); + } + + if (serr) + { + derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, + "Error ending REPORT response.", + resource->pool); + goto cleanup; + } + } + + if ((serr = dav_svn__brigade_puts(bb, output, + "</S:" SVN_DAV__INHERITED_PROPS_REPORT ">" + DEBUG_CR))) + { + derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, + "Error ending REPORT response.", + resource->pool); + goto cleanup; + } + + cleanup: + + /* Log this 'high level' svn action. */ + dav_svn__operational_log(resource->info, + svn_log__get_inherited_props(path, rev, + resource->pool)); + svn_pool_destroy(iterpool); + return dav_svn__final_flush_or_error(resource->info->r, bb, output, + derr, resource->pool); +} |