Author: cmpilato
Date: Tue Oct 16 20:34:30 2012
New Revision: 1398983
URL: http://svn.apache.org/viewvc?rev=1398983&view=rev
Log:
Reintegrate into trunk the 'http-dynamic-prop-namespaces' branch
(using a simple 'svn merge BRANCH-URL' with a trunk@HEAD client!).
For details of what this branch was all about, see
^/subversion/branches/http-dynamic-prop-namespaces/BRANCH-README@1398962
Modified:
subversion/trunk/ (props changed)
subversion/trunk/subversion/include/svn_dav.h
subversion/trunk/subversion/libsvn_ra_serf/commit.c
subversion/trunk/subversion/libsvn_ra_serf/options.c
subversion/trunk/subversion/libsvn_ra_serf/property.c
subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
subversion/trunk/subversion/libsvn_ra_serf/serf.c
subversion/trunk/subversion/libsvn_ra_serf/util.c
subversion/trunk/subversion/mod_dav_svn/dav_svn.h
subversion/trunk/subversion/mod_dav_svn/deadprops.c
subversion/trunk/subversion/mod_dav_svn/mod_dav_svn.c
subversion/trunk/subversion/mod_dav_svn/repos.c
subversion/trunk/subversion/mod_dav_svn/version.c
Propchange: subversion/trunk/
------------------------------------------------------------------------------
Merged /subversion/branches/http-dynamic-prop-namespaces:r1396196-1398972
Modified: subversion/trunk/subversion/include/svn_dav.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_dav.h?rev=1398983&r1=1398982&r2=1398983&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_dav.h (original)
+++ subversion/trunk/subversion/include/svn_dav.h Tue Oct 16 20:34:30 2012
@@ -260,6 +260,11 @@ extern "C" {
*/
#define SVN_DAV_PROP_NS_DAV "http://subversion.tigris.org/xmlns/dav/"
+/** An extensible base URI from which other custom namespace URIs
+ * extend on an as-needed basis.
+ */
+#define SVN_DAV_PROP_NS_EXTENSIBLE "http://subversion.apache.org/xmlns/ext/"
+
/**
* @name Custom (extension) values for the DAV header.
@@ -312,6 +317,14 @@ extern "C" {
#define SVN_DAV_NS_DAV_SVN_EPHEMERAL_TXNPROPS\
SVN_DAV_PROP_NS_DAV "svn/ephemeral-txnprops"
+/** Presence of this in a DAV header in an OPTIONS request/response
+ * indicates that the transmitter knows how to properly handle
+ * Subversion properties delivered via WebDAV's PROPFIND and PROPPATCH
+ * mechanisms using Subversion's extensible property namespace
+ * SVN_DAV_PROP_NS_EXTENSIBLE. */
+#define SVN_DAV_NS_DAV_SVN_PROP_EXT_NS\
+ SVN_DAV_PROP_NS_DAV "svn/prop-ext-ns"
+
/** @} */
/** @} */
Modified: subversion/trunk/subversion/libsvn_ra_serf/commit.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/commit.c?rev=1398983&r1=1398982&r2=1398983&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/commit.c Tue Oct 16 20:34:30 2012
@@ -61,6 +61,9 @@ typedef struct commit_context_t {
svn_boolean_t keep_locks;
apr_hash_t *deleted_entries; /* deleted files (for delete+add detection) */
+ /* Stuff for extensible property XML namespaces. */
+ svn_boolean_t use_ext_prop_ns;
+
/* HTTP v2 stuff */
const char *txn_url; /* txn URL (!svn/txn/TXN_NAME) */
const char *txn_root_url; /* commit anchor txn root URL */
@@ -670,7 +673,7 @@ proppatch_walker(void *baton,
svn_boolean_t have_old_val;
const svn_string_t *old_val;
const svn_string_t *encoded_value;
- const char *prop_name;
+ const char *prop_name, *xmlns = NULL;
SVN_ERR(derive_old_val(&have_old_val, &old_val, wb, ns, name));
@@ -701,19 +704,31 @@ proppatch_walker(void *baton,
cdata_bkt = NULL;
}
- /* Use the namespace prefix instead of adding the xmlns attribute to support
- property names containing ':' */
+ /* To reduce the wire transfer size, use prefixes for property
+ namespace for which we've predefined them. */
if (strcmp(ns, SVN_DAV_PROP_NS_SVN) == 0)
- prop_name = apr_pstrcat(wb->body_pool, "S:", name, (char *)NULL);
+ {
+ prop_name = apr_pstrcat(wb->body_pool, "S:", name, (char *)NULL);
+ }
else if (strcmp(ns, SVN_DAV_PROP_NS_CUSTOM) == 0)
- prop_name = apr_pstrcat(wb->body_pool, "C:", name, (char *)NULL);
+ {
+ prop_name = apr_pstrcat(wb->body_pool, "C:", name, (char *)NULL);
+ }
+ else if (strncmp(ns, SVN_DAV_PROP_NS_EXTENSIBLE,
+ sizeof(SVN_DAV_PROP_NS_EXTENSIBLE) - 1) == 0)
+ {
+ prop_name = name;
+ xmlns = ns;
+ }
if (cdata_bkt)
svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, prop_name,
+ "xmlns", xmlns,
"V:encoding", encoding,
NULL);
else
svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, prop_name,
+ "xmlns", xmlns,
"V:" SVN_DAV__OLD_VALUE__ABSENT, "1",
NULL);
@@ -1468,23 +1483,18 @@ open_root(void *edit_baton,
{
const void *key;
void *val;
- const char *name;
+ const char *propname;
svn_string_t *value;
- const char *ns;
+ const char *ns, *name;
apr_hash_this(hi, &key, NULL, &val);
- name = key;
+ propname = key;
value = val;
- if (strncmp(name, SVN_PROP_PREFIX, sizeof(SVN_PROP_PREFIX) - 1) == 0)
- {
- ns = SVN_DAV_PROP_NS_SVN;
- name += sizeof(SVN_PROP_PREFIX) - 1;
- }
- else
- {
- ns = SVN_DAV_PROP_NS_CUSTOM;
- }
+ /* Calculate the wirename bits for this property name. */
+ svn_ra_serf__wirename_from_svnname(&ns, &name, propname,
+ dir->commit->use_ext_prop_ns,
+ ctx->pool);
svn_ra_serf__set_prop(proppatch_ctx->changed_props,
proppatch_ctx->path,
@@ -1739,12 +1749,12 @@ open_directory(const char *path,
static svn_error_t *
change_dir_prop(void *dir_baton,
- const char *name,
+ const char *propname,
const svn_string_t *value,
apr_pool_t *pool)
{
dir_context_t *dir = dir_baton;
- const char *ns;
+ const char *ns, *name;
const char *proppatch_target;
@@ -1760,16 +1770,10 @@ change_dir_prop(void *dir_baton,
proppatch_target = dir->working_url;
}
- name = apr_pstrdup(dir->pool, name);
- if (strncmp(name, SVN_PROP_PREFIX, sizeof(SVN_PROP_PREFIX) - 1) == 0)
- {
- ns = SVN_DAV_PROP_NS_SVN;
- name += sizeof(SVN_PROP_PREFIX) - 1;
- }
- else
- {
- ns = SVN_DAV_PROP_NS_CUSTOM;
- }
+ /* Calculate the wirename bits for this property name. */
+ svn_ra_serf__wirename_from_svnname(&ns, &name, propname,
+ dir->commit->use_ext_prop_ns,
+ dir->pool);
if (value)
{
@@ -1993,24 +1997,17 @@ apply_textdelta(void *file_baton,
static svn_error_t *
change_file_prop(void *file_baton,
- const char *name,
+ const char *propname,
const svn_string_t *value,
apr_pool_t *pool)
{
file_context_t *file = file_baton;
- const char *ns;
+ const char *ns, *name;
- name = apr_pstrdup(file->pool, name);
-
- if (strncmp(name, SVN_PROP_PREFIX, sizeof(SVN_PROP_PREFIX) - 1) == 0)
- {
- ns = SVN_DAV_PROP_NS_SVN;
- name += sizeof(SVN_PROP_PREFIX) - 1;
- }
- else
- {
- ns = SVN_DAV_PROP_NS_CUSTOM;
- }
+ /* Calculate the wirename bits for this property name. */
+ svn_ra_serf__wirename_from_svnname(&ns, &name, propname,
+ file->commit->use_ext_prop_ns,
+ file->pool);
if (value)
{
@@ -2309,10 +2306,9 @@ svn_ra_serf__get_commit_editor(svn_ra_se
ctx->callback = callback;
ctx->callback_baton = callback_baton;
-
ctx->lock_tokens = lock_tokens;
ctx->keep_locks = keep_locks;
-
+ ctx->use_ext_prop_ns = session->use_ext_prop_ns;
ctx->deleted_entries = apr_hash_make(ctx->pool);
editor = svn_delta_default_editor(pool);
@@ -2347,7 +2343,7 @@ svn_ra_serf__get_commit_editor(svn_ra_se
svn_error_t *
svn_ra_serf__change_rev_prop(svn_ra_session_t *ra_session,
svn_revnum_t rev,
- const char *name,
+ const char *propname,
const svn_string_t *const *old_value_p,
const svn_string_t *value,
apr_pool_t *pool)
@@ -2356,7 +2352,7 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
proppatch_context_t *proppatch_ctx;
commit_context_t *commit;
const char *proppatch_target;
- const char *ns;
+ const char *ns, *name;
svn_error_t *err;
if (old_value_p)
@@ -2376,6 +2372,7 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
commit->session = session;
commit->conn = session->conns[0];
+ commit->use_ext_prop_ns = session->use_ext_prop_ns;
if (SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(session))
{
@@ -2394,15 +2391,9 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
pool, pool));
}
- if (strncmp(name, SVN_PROP_PREFIX, sizeof(SVN_PROP_PREFIX) - 1) == 0)
- {
- ns = SVN_DAV_PROP_NS_SVN;
- name += sizeof(SVN_PROP_PREFIX) - 1;
- }
- else
- {
- ns = SVN_DAV_PROP_NS_CUSTOM;
- }
+ /* Calculate the wirename bits for this property name. */
+ svn_ra_serf__wirename_from_svnname(&ns, &name, propname,
+ commit->use_ext_prop_ns, pool);
/* PROPPATCH our log message and pass it along. */
proppatch_ctx = apr_pcalloc(pool, sizeof(*proppatch_ctx));
Modified: subversion/trunk/subversion/libsvn_ra_serf/options.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/options.c?rev=1398983&r1=1398982&r2=1398983&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/options.c Tue Oct 16 20:34:30
2012
@@ -211,6 +211,13 @@ capabilities_headers_iterator_callback(v
SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS,
APR_HASH_KEY_STRING,
capability_yes);
}
+
+ /* The "extensible property namespace" feature is an artefact of
+ our WebDAV protocol only. We handle it specially. */
+ if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_PROP_EXT_NS, vals))
+ {
+ session->use_ext_prop_ns = TRUE;
+ }
}
/* SVN-specific headers -- if present, server supports HTTP protocol v2 */
Modified: subversion/trunk/subversion/libsvn_ra_serf/property.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/property.c?rev=1398983&r1=1398982&r2=1398983&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/property.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/property.c Tue Oct 16 20:34:30
2012
@@ -832,6 +832,64 @@ svn_ra_serf__walk_all_paths(apr_hash_t *
}
+void
+svn_ra_serf__wirename_from_svnname(const char **ns,
+ const char **name,
+ const char *svnname,
+ svn_boolean_t use_ext_prop_ns,
+ apr_pool_t *result_pool)
+{
+ /* If we're allowed to use the extensible property namespace... */
+ if (use_ext_prop_ns)
+ {
+ const char *colon;
+
+ /* If there's no colon in this property name, it's a custom
+ property (C:name). */
+ colon = strrchr(svnname, ':');
+ if (! colon)
+ {
+ *ns = SVN_DAV_PROP_NS_CUSTOM;
+ *name = apr_pstrdup(result_pool, svnname);
+ }
+ /* Otherwise... */
+ else
+ {
+ /* If the property name prefix is merely "svn:", it's a
+ Subversion property (S:name-without-the-prefix). */
+ if (strncmp(svnname, "svn:", colon - svnname) == 0)
+ {
+ *ns = SVN_DAV_PROP_NS_SVN;
+ }
+ /* ...but anything else requires the extensible namespace. */
+ else
+ {
+ const char *barename = apr_pstrndup(result_pool, svnname,
+ colon - svnname);
+ *ns = apr_pstrcat(result_pool, SVN_DAV_PROP_NS_EXTENSIBLE,
+ svn_path_uri_encode(barename, result_pool),
+ (char *)NULL);
+ }
+
+ /* Either way, the base name begins after the colon. */
+ *name = apr_pstrdup(result_pool, colon + 1);
+ }
+ }
+ else
+ {
+ if (strncmp(svnname, "svn:", 4) == 0)
+ {
+ *ns = SVN_DAV_PROP_NS_SVN;
+ *name = apr_pstrdup(result_pool, svnname + 4);
+ }
+ else
+ {
+ *ns = SVN_DAV_PROP_NS_CUSTOM;
+ *name = apr_pstrdup(result_pool, svnname);
+ }
+ }
+}
+
const char *
svn_ra_serf__svnname_from_wirename(const char *ns,
const char *name,
@@ -843,6 +901,16 @@ svn_ra_serf__svnname_from_wirename(const
if (strcmp(ns, SVN_DAV_PROP_NS_SVN) == 0)
return apr_pstrcat(result_pool, SVN_PROP_PREFIX, name, (char *)NULL);
+ /* Check for something within our extensible namespace. */
+ if (strncmp(ns, SVN_DAV_PROP_NS_EXTENSIBLE,
+ sizeof(SVN_DAV_PROP_NS_EXTENSIBLE) - 1) == 0)
+ {
+ const char *relpath =
+ svn_path_uri_decode(ns + (sizeof(SVN_DAV_PROP_NS_EXTENSIBLE) - 1),
+ result_pool);
+ return apr_pstrcat(result_pool, relpath, ":", name, (char *)NULL);
+ }
+
if (strcmp(ns, SVN_PROP_PREFIX) == 0)
return apr_pstrcat(result_pool, SVN_PROP_PREFIX, name, (char *)NULL);
@@ -932,6 +1000,13 @@ select_revprops(void *baton,
prop_name = name;
else if (strcmp(ns, SVN_DAV_PROP_NS_SVN) == 0)
prop_name = apr_pstrcat(result_pool, SVN_PROP_PREFIX, name, (char *)NULL);
+ else if (strncmp(ns, SVN_DAV_PROP_NS_EXTENSIBLE,
+ sizeof(SVN_DAV_PROP_NS_EXTENSIBLE) - 1) == 0)
+ {
+ const char *relpath = svn_uri_skip_ancestor(SVN_DAV_PROP_NS_EXTENSIBLE,
+ ns, scratch_pool);
+ prop_name = apr_pstrcat(result_pool, relpath, ":", name, (char *)NULL);
+ }
else if (strcmp(ns, SVN_PROP_PREFIX) == 0)
prop_name = apr_pstrcat(result_pool, SVN_PROP_PREFIX, name, (char *)NULL);
else if (strcmp(ns, "") == 0)
Modified: subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h?rev=1398983&r1=1398982&r2=1398983&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/ra_serf.h Tue Oct 16 20:34:30
2012
@@ -173,6 +173,9 @@ struct svn_ra_serf__session_t {
constants' addresses, therefore). */
apr_hash_t *capabilities;
+ /* Does the server understand the extensible property XML namespace? */
+ svn_boolean_t use_ext_prop_ns;
+
/* Are we using a proxy? */
int using_proxy;
@@ -1188,6 +1191,19 @@ svn_ra_serf__walk_all_paths(apr_hash_t *
apr_pool_t *pool);
+/* Map a property SVNNAME as referred to internally by Subversion to
+ its corresponding wire namespace (*NS) and *NAME.
+
+ If USE_EXT_PROP_NS is set, the function may make use of the
+ extensible property XML namespace (SVN_DAV_PROP_NS_EXTENSIBLE). */
+void
+svn_ra_serf__wirename_from_svnname(const char **ns,
+ const char **name,
+ const char *svnname,
+ svn_boolean_t use_ext_prop_ns,
+ apr_pool_t *result_pool);
+
+
/* Map a property name, as passed over the wire, into its corresponding
Subversion-internal name. The returned name will be a static value,
or allocated within RESULT_POOL.
Modified: subversion/trunk/subversion/libsvn_ra_serf/serf.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/serf.c?rev=1398983&r1=1398982&r2=1398983&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/serf.c Tue Oct 16 20:34:30 2012
@@ -676,6 +676,11 @@ dirent_walker(void *baton,
{
dwb->entry->has_props = TRUE;
}
+ else if (strncmp(ns, SVN_DAV_PROP_NS_EXTENSIBLE,
+ sizeof(SVN_DAV_PROP_NS_EXTENSIBLE) - 1) == 0)
+ {
+ dwb->entry->has_props = TRUE;
+ }
else if (strcmp(ns, SVN_DAV_PROP_NS_DAV) == 0)
{
if(strcmp(name, "deadprop-count") == 0)
Modified: subversion/trunk/subversion/libsvn_ra_serf/util.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/util.c?rev=1398983&r1=1398982&r2=1398983&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/util.c Tue Oct 16 20:34:30 2012
@@ -702,6 +702,7 @@ setup_serf_req(serf_request_t *request,
serf_bucket_headers_setn(*hdrs_bkt, "DAV", SVN_DAV_NS_DAV_SVN_DEPTH);
serf_bucket_headers_setn(*hdrs_bkt, "DAV", SVN_DAV_NS_DAV_SVN_MERGEINFO);
serf_bucket_headers_setn(*hdrs_bkt, "DAV", SVN_DAV_NS_DAV_SVN_LOG_REVPROPS);
+ serf_bucket_headers_setn(*hdrs_bkt, "DAV", SVN_DAV_NS_DAV_SVN_PROP_EXT_NS);
return SVN_NO_ERROR;
}
Modified: subversion/trunk/subversion/mod_dav_svn/dav_svn.h
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/dav_svn.h?rev=1398983&r1=1398982&r2=1398983&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/trunk/subversion/mod_dav_svn/dav_svn.h Tue Oct 16 20:34:30 2012
@@ -137,6 +137,11 @@ typedef struct dav_svn_repos {
'is_svn_client' is false, then 'capabilities' should be empty. */
apr_hash_t *client_capabilities;
+ /* Whether its okay to use the extensible property XML namespace
+ SVN_DAV_PROP_NS_SVN in PROPFIND/PROPPATCH requests and
+ responses. */
+ svn_boolean_t use_ext_prop_ns;
+
/* The path to the activities db */
const char *activities_db;
@@ -335,6 +340,10 @@ svn_boolean_t dav_svn__check_httpv2_supp
txnprop support be advertised? */
svn_boolean_t dav_svn__check_ephemeral_txnprops_support(request_rec *r);
+/* For the repository referred to by this request, should support for
+ property on-the-wire XML namespaces under the extensible namespace
+ URI be advertised? */
+svn_boolean_t dav_svn__check_prop_ext_ns_support(request_rec *r);
/* SPECIAL URI
Modified: subversion/trunk/subversion/mod_dav_svn/deadprops.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/deadprops.c?rev=1398983&r1=1398982&r2=1398983&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/deadprops.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/deadprops.c Tue Oct 16 20:34:30 2012
@@ -68,28 +68,112 @@ get_repos_path(struct dav_resource_priva
}
-/* construct the repos-local name for the given DAV property name */
-static void
-get_repos_propname(dav_db *db,
- const dav_prop_name *name,
- const char **repos_propname)
+/* Return a Subversion property name constructed from the namespace
+ and bare name values found withing DAVNAME. Use SCRATCH_POOL for
+ temporary allocations.
+
+ This is the reverse of the davname_to_propname() function. */
+static const char *
+davname_to_propname(dav_db *db,
+ const dav_prop_name *davname)
{
- if (strcmp(name->ns, SVN_DAV_PROP_NS_SVN) == 0)
+ const char *propname = NULL;
+
+ if (strcmp(davname->ns, SVN_DAV_PROP_NS_SVN) == 0)
{
/* recombine the namespace ("svn:") and the name. */
svn_stringbuf_set(db->work, SVN_PROP_PREFIX);
- svn_stringbuf_appendcstr(db->work, name->name);
- *repos_propname = db->work->data;
+ svn_stringbuf_appendcstr(db->work, davname->name);
+ propname = db->work->data;
}
- else if (strcmp(name->ns, SVN_DAV_PROP_NS_CUSTOM) == 0)
+ else if (strcmp(davname->ns, SVN_DAV_PROP_NS_CUSTOM) == 0)
{
/* the name of a custom prop is just the name -- no ns URI */
- *repos_propname = name->name;
+ propname = davname->name;
+ }
+ else if (strncmp(davname->ns, SVN_DAV_PROP_NS_EXTENSIBLE,
+ sizeof(SVN_DAV_PROP_NS_EXTENSIBLE) - 1) == 0)
+ {
+ const char *relpath =
+ svn_path_uri_decode(davname->ns +
+ (sizeof(SVN_DAV_PROP_NS_EXTENSIBLE) - 1),
+ db->resource->pool);
+ svn_stringbuf_set(db->work, relpath);
+ svn_stringbuf_appendbytes(db->work, ":", 1);
+ svn_stringbuf_appendcstr(db->work, davname->name);
+ propname = db->work->data;
+ }
+
+ return propname;
+}
+
+
+/* Return a dav_prop_name structure allocated from POOL which
+ describes the Subversion property name PROPNAME (with length
+ NAMELEN). If ALLOW_EXT_NS is set, PROPNAME is parsed according to
+ the rules which apply when the custom Subversion extensible
+ property namespace is in use. Otherwise, we fall back to old rules
+ which have been in place since Subversion's origins.
+
+ This is the reverse of the davname_to_propname() function. */
+static dav_prop_name *
+propname_to_davname(const char *propname,
+ int namelen,
+ svn_boolean_t allow_ext_ns,
+ apr_pool_t *pool)
+{
+ const char *colon;
+ dav_prop_name *davname = apr_pcalloc(pool, sizeof(*davname));
+
+ /* If we're allowed to use the extensible XML property namespace, we
+ parse pretty carefully. */
+ if (allow_ext_ns)
+ {
+ /* If there's no colon in this property name, it's a custom
+ property (C:name). */
+ colon = strrchr((char *)propname, ':');
+ if (! colon)
+ {
+ davname->ns = SVN_DAV_PROP_NS_CUSTOM;
+ davname->name = apr_pstrdup(pool, propname);
+ }
+
+ /* If the property name prefix is merely "svn:", it's a
+ Subversion property (S:name-without-the-prefix). */
+ else if (strncmp(propname, "svn:", colon - propname) == 0)
+ {
+ davname->ns = SVN_DAV_PROP_NS_SVN;
+ davname->name = apr_pstrdup(pool, colon + 1);
+ }
+
+ /* Anything else requires a custom xmlns prefix mapping beyond
+ the magic prefixes we've already built in. */
+ else
+ {
+ const char *barename = apr_pstrndup(pool, propname, colon -
propname);
+ davname->ns = apr_pstrcat(pool, SVN_DAV_PROP_NS_EXTENSIBLE,
+ svn_path_uri_encode(barename, pool),
+ (char *)NULL);
+ davname->name = apr_pstrdup(pool, colon + 1);
+ }
}
+
+ /* Otherwise, we distinguish only between "svn:*" and everything else. */
else
{
- *repos_propname = NULL;
+ if (strncmp(propname, SVN_PROP_PREFIX, sizeof(SVN_PROP_PREFIX) - 1) == 0)
+ {
+ davname->ns = SVN_DAV_PROP_NS_SVN;
+ davname->name = apr_pstrdup(pool, propname + 4);
+ }
+ else
+ {
+ davname->ns = SVN_DAV_PROP_NS_CUSTOM;
+ davname->name = apr_pstrdup(pool, propname);
+ }
}
+
+ return davname;
}
@@ -100,7 +184,7 @@ get_value(dav_db *db, const dav_prop_nam
svn_error_t *serr;
/* get the repos-local name */
- get_repos_propname(db, name, &propname);
+ propname = davname_to_propname(db, name);
if (propname == NULL)
{
@@ -172,7 +256,7 @@ save_value(dav_db *db, const dav_prop_na
const dav_resource *resource = db->resource;
/* get the repos-local name */
- get_repos_propname(db, name, &propname);
+ propname = davname_to_propname(db, name);
if (propname == NULL)
{
@@ -360,7 +444,7 @@ db_output_value(dav_db *db,
apr_text_header *phdr,
int *found)
{
- const char *prefix;
+ const char *prefix = "", *xmlns_attr = "";
const char *s;
svn_string_t *propval;
dav_error *err;
@@ -375,14 +459,25 @@ db_output_value(dav_db *db,
return NULL;
if (strcmp(name->ns, SVN_DAV_PROP_NS_CUSTOM) == 0)
- prefix = "C:";
- else
- prefix = "S:";
+ {
+ prefix = "C:";
+ }
+ else if (strcmp(name->ns, SVN_DAV_PROP_NS_SVN) == 0)
+ {
+ prefix = "S:";
+ }
+ else if (strncmp(name->ns, SVN_DAV_PROP_NS_EXTENSIBLE,
+ sizeof(SVN_DAV_PROP_NS_EXTENSIBLE) - 1) == 0)
+ {
+ prefix = "";
+ xmlns_attr = apr_pstrcat(pool, " xmlns=\"", name->ns, "\"", (char
*)NULL);
+ }
if (propval->len == 0)
{
/* empty value. add an empty elem. */
- s = apr_psprintf(pool, "<%s%s/>" DEBUG_CR, prefix, name->name);
+ s = apr_psprintf(pool, "<%s%s%s/>" DEBUG_CR,
+ prefix, name->name, xmlns_attr);
apr_text_append(pool, phdr, s);
}
else
@@ -407,7 +502,8 @@ db_output_value(dav_db *db,
xml_safe = xmlval->data;
}
- s = apr_psprintf(pool, "<%s%s%s>", prefix, name->name, encoding);
+ s = apr_psprintf(pool, "<%s%s%s%s>",
+ prefix, name->name, encoding, xmlns_attr);
apr_text_append(pool, phdr, s);
/* the value is in our pool which means it has the right lifetime. */
@@ -540,7 +636,7 @@ db_remove(dav_db *db, const dav_prop_nam
const char *propname;
/* get the repos-local name */
- get_repos_propname(db, name, &propname);
+ propname = davname_to_propname(db, name);
/* ### non-svn props aren't in our repos, so punt for now */
if (propname == NULL)
@@ -588,7 +684,7 @@ db_exists(dav_db *db, const dav_prop_nam
int retval;
/* get the repos-local name */
- get_repos_propname(db, name, &propname);
+ propname = davname_to_propname(db, name);
/* ### non-svn props aren't in our repos */
if (propname == NULL)
@@ -627,21 +723,16 @@ static void get_name(dav_db *db, dav_pro
else
{
const void *name;
+ apr_ssize_t namelen;
+ dav_prop_name *dav_name;
- apr_hash_this(db->hi, &name, NULL, NULL);
-
-#define PREFIX_LEN (sizeof(SVN_PROP_PREFIX) - 1)
- if (strncmp(name, SVN_PROP_PREFIX, PREFIX_LEN) == 0)
-#undef PREFIX_LEN
- {
- pname->ns = SVN_DAV_PROP_NS_SVN;
- pname->name = (const char *)name + 4;
- }
- else
- {
- pname->ns = SVN_DAV_PROP_NS_CUSTOM;
- pname->name = name;
- }
+ apr_hash_this(db->hi, &name, &namelen, NULL);
+ dav_name = propname_to_davname(
+ name, namelen,
+ db->resource->info->repos->use_ext_prop_ns,
+ db->resource->pool);
+ pname->ns = dav_name->ns;
+ pname->name = dav_name->name;
}
}
Modified: subversion/trunk/subversion/mod_dav_svn/mod_dav_svn.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/mod_dav_svn.c?rev=1398983&r1=1398982&r2=1398983&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/mod_dav_svn.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/mod_dav_svn.c Tue Oct 16 20:34:30
2012
@@ -820,6 +820,21 @@ dav_svn__check_ephemeral_txnprops_suppor
}
+svn_boolean_t
+dav_svn__check_prop_ext_ns_support(request_rec *r)
+{
+ svn_version_t *version = dav_svn__get_master_version(r);
+
+ /* We know this server supports extensible property namespaces. But
+ if we're proxying requests to a master server, we need to see if
+ it supports them, too. */
+ if (version && (! svn_version__at_least(version, 1, 8, 0)))
+ return FALSE;
+
+ return TRUE;
+}
+
+
/* FALSE if path authorization should be skipped.
* TRUE if either the bypass or the apache subrequest methods should be used.
*/
Modified: subversion/trunk/subversion/mod_dav_svn/repos.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/repos.c?rev=1398983&r1=1398982&r2=1398983&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/repos.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/repos.c Tue Oct 16 20:34:30 2012
@@ -2143,6 +2143,14 @@ get_resource(request_rec *r,
SVN_RA_CAPABILITY_MERGEINFO,
APR_HASH_KEY_STRING, capability_yes);
}
+
+ /* We don't need to report the DAV-specific extensible
+ property XML namespace capability to hook scripts, so
+ we'll just stash it in our repos structure. */
+ if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_PROP_EXT_NS, vals))
+ {
+ repos->use_ext_prop_ns = TRUE;
+ }
}
}
}
Modified: subversion/trunk/subversion/mod_dav_svn/version.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/version.c?rev=1398983&r1=1398982&r2=1398983&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/version.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/version.c Tue Oct 16 20:34:30 2012
@@ -203,6 +203,12 @@ get_option(const dav_resource *resource,
SVN_DAV_NS_DAV_SVN_EPHEMERAL_TXNPROPS);
}
+ if (dav_svn__check_prop_ext_ns_support(r))
+ {
+ apr_table_addn(r->headers_out, "DAV",
+ SVN_DAV_NS_DAV_SVN_PROP_EXT_NS);
+ }
+
if (resource->info->repos->fs)
{
svn_error_t *serr;