You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2018/11/07 12:30:11 UTC

svn commit: r1846002 [22/44] - in /subversion/branches/ra-git: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ build/generator/util/ build/win32/ contrib/client-side/ contrib/client-side/svn_load_dirs/ contr...

Modified: subversion/branches/ra-git/subversion/mod_dav_svn/dav_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/mod_dav_svn/dav_svn.h?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/branches/ra-git/subversion/mod_dav_svn/dav_svn.h Wed Nov  7 12:30:06 2018
@@ -359,10 +359,6 @@ svn_boolean_t dav_svn__get_list_parentpa
    master server version (if provided via SVNMasterVersion).  */
 svn_boolean_t dav_svn__check_httpv2_support(request_rec *r);
 
-/* For the repository referred to by this request, should ephemeral
-   txnprop support be advertised?  */
-svn_boolean_t dav_svn__check_ephemeral_txnprops_support(request_rec *r);
-
 
 
 /* SPECIAL URI
@@ -705,6 +701,7 @@ static const dav_report_elem dav_svn__re
   { SVN_XML_NAMESPACE, "get-deleted-rev-report" },
   { SVN_XML_NAMESPACE, SVN_DAV__MERGEINFO_REPORT },
   { SVN_XML_NAMESPACE, SVN_DAV__INHERITED_PROPS_REPORT },
+  { SVN_XML_NAMESPACE, "list-report" },
   { NULL, NULL },
 };
 
@@ -757,6 +754,11 @@ dav_svn__get_inherited_props_report(cons
                                     const apr_xml_doc *doc,
                                     dav_svn__output *output);
 
+dav_error *
+dav_svn__list_report(const dav_resource *resource,
+                     const apr_xml_doc *doc,
+                     dav_svn__output *output);
+
 /*** posts/ ***/
 
 /* The various POST handlers, defined in posts/, and used by repos.c.  */
@@ -1114,6 +1116,19 @@ dav_svn__get_youngest_rev(svn_revnum_t *
                           dav_svn_repos *repos,
                           apr_pool_t *scratch_pool);
 
+/* Return the liveprop-encoded form of AUTHOR, allocated in RESULT_POOL.
+ * If IS_SVN_CLIENT is set, assume that the data will be sent to a SVN
+ * client.  This mainly sanitizes AUTHOR strings with control chars in
+ * them without converting them to escape sequences etc.
+ *
+ * Use SCRATCH_POOL for temporary allocations.
+ */
+const char *
+dav_svn__fuzzy_escape_author(const char *author,
+                             svn_boolean_t is_svn_client,
+                             apr_pool_t *result_pool,
+                             apr_pool_t *scratch_pool);
+
 /*** mirror.c ***/
 
 /* Perform the fixup hook for the R request.  */

Modified: subversion/branches/ra-git/subversion/mod_dav_svn/liveprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/mod_dav_svn/liveprops.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/mod_dav_svn/liveprops.c (original)
+++ subversion/branches/ra-git/subversion/mod_dav_svn/liveprops.c Wed Nov  7 12:30:06 2018
@@ -423,43 +423,10 @@ insert_prop_internal(const dav_resource
         if (last_author == NULL)
           return DAV_PROP_INSERT_NOTDEF;
 
-        if (svn_xml_is_xml_safe(last_author->data, last_author->len)
-            || !resource->info->repos->is_svn_client)
-          value = apr_xml_quote_string(scratch_pool, last_author->data, 1);
-        else
-          {
-            /* We are talking to a Subversion client, which will (like any proper
-               xml parser) error out if we produce control characters in XML.
-
-               However Subversion clients process both the generic
-               <creator-displayname /> as the custom element for svn:author.
-
-               Let's skip outputting the invalid characters here to make the XML
-               valid, so clients can see the custom element.
-
-               Subversion Clients will then either use a slightly invalid
-               author (unlikely) or more likely use the second result, which
-               will be transferred with full escaping capabilities.
-
-               We have tests in place to assert proper behavior over the RA layer.
-             */
-            apr_size_t i;
-            svn_stringbuf_t *buf;
-
-            buf = svn_stringbuf_create_from_string(last_author, scratch_pool);
-
-            for (i = 0; i < buf->len; i++)
-              {
-                char c = buf->data[i];
-
-                if (svn_ctype_iscntrl(c))
-                  {
-                    svn_stringbuf_remove(buf, i--, 1);
-                  }
-              }
-
-            value = apr_xml_quote_string(scratch_pool, buf->data, 1);
-          }
+        /* We need to sanitize the LAST_AUTHOR. */
+        value = dav_svn__fuzzy_escape_author(last_author->data,
+                                      resource->info->repos->is_svn_client,
+                                      scratch_pool, scratch_pool);
         break;
       }
 

Modified: subversion/branches/ra-git/subversion/mod_dav_svn/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/mod_dav_svn/merge.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/mod_dav_svn/merge.c (original)
+++ subversion/branches/ra-git/subversion/mod_dav_svn/merge.c Wed Nov  7 12:30:06 2018
@@ -171,7 +171,12 @@ do_resources(const dav_svn_repos *repos,
           if (! apr_hash_get(sent, path, change->path.len))
             {
               svn_node_kind_t kind;
-              SVN_ERR(svn_fs_check_path(&kind, root, path, iterpool));
+
+              if (change->node_kind == svn_node_unknown)
+                SVN_ERR(svn_fs_check_path(&kind, root, path, iterpool));
+              else
+                kind = change->node_kind;
+
               SVN_ERR(send_response(repos, root, change->path.data,
                                     kind == svn_node_dir,
                                     output, bb, iterpool));

Modified: subversion/branches/ra-git/subversion/mod_dav_svn/mod_dav_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/mod_dav_svn/mod_dav_svn.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/mod_dav_svn/mod_dav_svn.c (original)
+++ subversion/branches/ra-git/subversion/mod_dav_svn/mod_dav_svn.c Wed Nov  7 12:30:06 2018
@@ -137,6 +137,15 @@ init(apr_pool_t *p, apr_pool_t *plog, ap
       return HTTP_INTERNAL_SERVER_ERROR;
     }
 
+  serr = svn_repos_authz_initialize(p);
+  if (serr)
+    {
+      ap_log_perror(APLOG_MARK, APLOG_ERR, serr->apr_err, p,
+               "mod_dav_svn: error calling svn_repos_authz_initialize: '%s'",
+                    serr->message ? serr->message : "(no more info)");
+      return HTTP_INTERNAL_SERVER_ERROR;
+    }
+
   /* This returns void, so we can't check for error. */
   conf = ap_get_module_config(s->module_config, &dav_svn_module);
   svn_utf_initialize2(conf->use_utf8, p);
@@ -222,6 +231,9 @@ merge_server_config(apr_pool_t *p, void
       newconf->compression_level = child->compression_level;
     }
 
+  newconf->use_utf8 = INHERIT_VALUE(parent, child, use_utf8);                 
+  svn_utf_initialize2(newconf->use_utf8, p); 
+
   return newconf;
 }
 
@@ -279,8 +291,8 @@ merge_dir_config(apr_pool_t *p, void *ba
 
   if (parent->fs_path)
     ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
-                 "mod_dav_svn: nested Location '%s' hinders access to '%s' "
-                 "in SVNPath Location '%s'",
+                 "mod_dav_svn: Location '%s' hinders access to '%s' "
+                 "in parent SVNPath Location '%s'",
                  child->root_dir,
                  svn_urlpath__skip_ancestor(parent->root_dir, child->root_dir),
                  parent->root_dir);
@@ -914,21 +926,6 @@ dav_svn__check_httpv2_support(request_re
 }
 
 
-svn_boolean_t
-dav_svn__check_ephemeral_txnprops_support(request_rec *r)
-{
-  svn_version_t *version = dav_svn__get_master_version(r);
-
-  /* We know this server supports ephemeral txnprops.  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.
  */
@@ -994,7 +991,9 @@ dav_svn__get_fulltext_cache_flag(request
   dir_conf_t *conf;
 
   conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
-  return conf->fulltext_cache == CONF_FLAG_ON;
+
+  /* fulltext caching is enabled by default. */
+  return get_conf_flag(conf->fulltext_cache, TRUE);
 }
 
 
@@ -1004,7 +1003,9 @@ dav_svn__get_revprop_cache_flag(request_
   dir_conf_t *conf;
 
   conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
-  return conf->revprop_cache == CONF_FLAG_ON;
+
+  /* revprop caching is enabled by default. */
+  return get_conf_flag(conf->revprop_cache, TRUE);
 }
 
 svn_boolean_t
@@ -1013,8 +1014,9 @@ dav_svn__get_nodeprop_cache_flag(request
   dir_conf_t *conf;
 
   conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
+
   /* node properties caching is enabled by default. */
-  return get_conf_flag(conf->nodeprop_cache, FALSE);
+  return get_conf_flag(conf->nodeprop_cache, TRUE);
 }
 
 svn_boolean_t
@@ -1023,7 +1025,9 @@ dav_svn__get_block_read_flag(request_rec
   dir_conf_t *conf;
 
   conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
-  return conf->block_read == CONF_FLAG_ON;
+
+  /* the block-read feature is disabled by default. */
+  return get_conf_flag(conf->block_read, FALSE);
 }
 
 int
@@ -1254,7 +1258,7 @@ static int dav_svn__translate_name(reque
 
   /* Leave a note to ourselves so that we know not to decline in the
    * map_to_storage hook. */
-  apr_table_setn(r->notes, NO_MAP_TO_STORAGE_NOTE, (const char*)1);
+  apr_table_setn(r->notes, NO_MAP_TO_STORAGE_NOTE, "1");
   return OK;
 }
 

Modified: subversion/branches/ra-git/subversion/mod_dav_svn/reports/file-revs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/mod_dav_svn/reports/file-revs.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/mod_dav_svn/reports/file-revs.c (original)
+++ subversion/branches/ra-git/subversion/mod_dav_svn/reports/file-revs.c Wed Nov  7 12:30:06 2018
@@ -214,7 +214,7 @@ file_rev_handler(void *baton,
                               frb->compression_level, pool);
       *window_handler = delta_window_handler;
       *window_baton = frb;
-      /* Start the txdelta element wich will be terminated by the window
+      /* Start the txdelta element which will be terminated by the window
          handler together with the file-rev element. */
       SVN_ERR(dav_svn__brigade_puts(frb->bb, frb->output, "<S:txdelta>"));
     }

Modified: subversion/branches/ra-git/subversion/mod_dav_svn/reports/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/mod_dav_svn/reports/mergeinfo.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/mod_dav_svn/reports/mergeinfo.c (original)
+++ subversion/branches/ra-git/subversion/mod_dav_svn/reports/mergeinfo.c Wed Nov  7 12:30:06 2018
@@ -42,6 +42,85 @@
 
 #include "../dav_svn.h"
 
+/* Baton type to be used with mergeinfo_receiver. */
+typedef struct mergeinfo_receiver_baton_t
+{
+  /* Start path of the query; report paths relative to this one. */
+  const char *fs_path;
+
+  /* Allocate the BRIGADE contents here. */
+  apr_pool_t *resource_pool;
+
+  /* Attach the response to this brigade. */
+  apr_bucket_brigade *brigade;
+
+  /* Send the response out here. */
+  dav_svn__output *output;
+
+  /* Did we already send the opening sequence? */
+  svn_boolean_t starting_tuple_sent;
+} mergeinfo_receiver_baton_t;
+
+/* Utility method sending the start of the "get m/i" response once
+   over BATON. */
+static svn_error_t *
+send_mergeinfo_starting_sequence(mergeinfo_receiver_baton_t *baton,
+                                apr_pool_t *scratch_pool)
+{
+  if (baton->starting_tuple_sent)
+    return SVN_NO_ERROR;
+
+  /* Ideally, dav_svn__brigade_printf() would set a flag in bb (or rather,
+     in r->sent_bodyct, see dav_method_report()), and ap_fflush()
+     would not set that flag unless it actually sent something.  But
+     we are condemned to live in another universe, so we must keep
+     track ourselves of whether we've sent anything or not.  See the
+     long comment after the 'cleanup' label for more details. */
+  SVN_ERR(dav_svn__brigade_puts(baton->brigade, baton->output,
+                                DAV_XML_HEADER DEBUG_CR
+                                "<S:" SVN_DAV__MERGEINFO_REPORT " "
+                                "xmlns:S=\"" SVN_XML_NAMESPACE "\" "
+                                "xmlns:D=\"DAV:\">" DEBUG_CR));
+  baton->starting_tuple_sent = TRUE;
+
+  return SVN_NO_ERROR;
+}
+
+/* Implements svn_repos_mergeinfo_receiver_t, sending the MERGEINFO
+ * out over the connection in the mergeinfo_receiver_baton_t * BATON. */
+static svn_error_t *
+mergeinfo_receiver(const char *path,
+                   svn_mergeinfo_t mergeinfo,
+                   void *baton,
+                   apr_pool_t *scratch_pool)
+{
+  mergeinfo_receiver_baton_t *b = baton;
+  svn_string_t *mergeinfo_string;
+
+  /* Delay starting the response until we checked that the initial
+     request went through.  We are at that point now b/c we've got
+     the first results in. */
+  SVN_ERR(send_mergeinfo_starting_sequence(b, scratch_pool));
+
+  /* Adjust the path info and send the m/i. */
+  path = svn_fspath__skip_ancestor(b->fs_path, path);
+  SVN_ERR(svn_mergeinfo_to_string(&mergeinfo_string, mergeinfo,
+                                  scratch_pool));
+
+  SVN_ERR(dav_svn__brigade_printf
+        (b->brigade, b->output,
+         "<S:" SVN_DAV__MERGEINFO_ITEM ">"
+         DEBUG_CR
+         "<S:" SVN_DAV__MERGEINFO_PATH ">%s</S:" SVN_DAV__MERGEINFO_PATH ">"
+         DEBUG_CR
+         "<S:" SVN_DAV__MERGEINFO_INFO ">%s</S:" SVN_DAV__MERGEINFO_INFO ">"
+         DEBUG_CR
+         "</S:" SVN_DAV__MERGEINFO_ITEM ">",
+         apr_xml_quote_string(b->resource_pool, path, 0),
+         apr_xml_quote_string(b->resource_pool, mergeinfo_string->data, 0)));
+
+  return SVN_NO_ERROR;
+}
 
 dav_error *
 dav_svn__get_mergeinfo_report(const dav_resource *resource,
@@ -51,13 +130,12 @@ dav_svn__get_mergeinfo_report(const dav_
   svn_error_t *serr;
   dav_error *derr = NULL;
   apr_xml_elem *child;
-  svn_mergeinfo_catalog_t catalog;
   svn_boolean_t include_descendants = FALSE;
   dav_svn__authz_read_baton arb;
   const dav_svn_repos *repos = resource->info->repos;
   int ns;
   apr_bucket_brigade *bb;
-  apr_hash_index_t *hi;
+  mergeinfo_receiver_baton_t receiver_baton;
 
   /* These get determined from the request document. */
   svn_revnum_t rev = SVN_INVALID_REVNUM;
@@ -127,20 +205,17 @@ dav_svn__get_mergeinfo_report(const dav_
   bb = apr_brigade_create(resource->pool,
                           dav_svn__output_get_bucket_alloc(output));
 
-  serr = svn_repos_fs_get_mergeinfo(&catalog, repos->repos, paths, rev,
-                                    inherit, include_descendants,
-                                    dav_svn__authz_read_func(&arb),
-                                    &arb, resource->pool);
-  if (serr)
-    {
-      derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST, NULL,
-                                  resource->pool);
-      goto cleanup;
-    }
-
-  serr = svn_mergeinfo__remove_prefix_from_catalog(&catalog, catalog,
-                                                   resource->info->repos_path,
-                                                   resource->pool);
+  receiver_baton.brigade = bb;
+  receiver_baton.output = output;
+  receiver_baton.fs_path = resource->info->repos_path;
+  receiver_baton.resource_pool = resource->pool;
+  receiver_baton.starting_tuple_sent = FALSE;
+
+  serr = svn_repos_fs_get_mergeinfo2(repos->repos, paths, rev,
+                                     inherit, include_descendants,
+                                     dav_svn__authz_read_func(&arb), &arb,
+                                     mergeinfo_receiver, &receiver_baton,
+                                     resource->pool);
   if (serr)
     {
       derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST, NULL,
@@ -148,17 +223,9 @@ dav_svn__get_mergeinfo_report(const dav_
       goto cleanup;
     }
 
-  /* Ideally, dav_svn__brigade_printf() would set a flag in bb (or rather,
-     in r->sent_bodyct, see dav_method_report()), and ap_fflush()
-     would not set that flag unless it actually sent something.  But
-     we are condemned to live in another universe, so we must keep
-     track ourselves of whether we've sent anything or not.  See the
-     long comment after the 'cleanup' label for more details. */
-  serr = dav_svn__brigade_puts(bb, output,
-                               DAV_XML_HEADER DEBUG_CR
-                               "<S:" SVN_DAV__MERGEINFO_REPORT " "
-                               "xmlns:S=\"" SVN_XML_NAMESPACE "\" "
-                               "xmlns:D=\"DAV:\">" DEBUG_CR);
+  /* We might not have sent anything
+     => ensure to begin the response in any case. */
+  serr = send_mergeinfo_starting_sequence(&receiver_baton, resource->pool);
   if (serr)
     {
       derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST, NULL,
@@ -166,46 +233,6 @@ dav_svn__get_mergeinfo_report(const dav_
       goto cleanup;
     }
 
-  for (hi = apr_hash_first(resource->pool, catalog); hi;
-       hi = apr_hash_next(hi))
-    {
-      const void *key;
-      void *value;
-      const char *path;
-      svn_mergeinfo_t mergeinfo;
-      svn_string_t *mergeinfo_string;
-
-      apr_hash_this(hi, &key, NULL, &value);
-      path = key;
-      mergeinfo = value;
-      serr = svn_mergeinfo_to_string(&mergeinfo_string, mergeinfo,
-                                     resource->pool);
-      if (serr)
-        {
-          derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
-                                      "Error ending REPORT response.",
-                                      resource->pool);
-          goto cleanup;
-        }
-      serr = dav_svn__brigade_printf
-        (bb, output,
-         "<S:" SVN_DAV__MERGEINFO_ITEM ">"
-         DEBUG_CR
-         "<S:" SVN_DAV__MERGEINFO_PATH ">%s</S:" SVN_DAV__MERGEINFO_PATH ">"
-         DEBUG_CR
-         "<S:" SVN_DAV__MERGEINFO_INFO ">%s</S:" SVN_DAV__MERGEINFO_INFO ">"
-         DEBUG_CR
-         "</S:" SVN_DAV__MERGEINFO_ITEM ">",
-         apr_xml_quote_string(resource->pool, path, 0),
-         apr_xml_quote_string(resource->pool, mergeinfo_string->data, 0));
-      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__MERGEINFO_REPORT ">"

Modified: subversion/branches/ra-git/subversion/mod_dav_svn/reports/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/mod_dav_svn/reports/replay.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/mod_dav_svn/reports/replay.c (original)
+++ subversion/branches/ra-git/subversion/mod_dav_svn/reports/replay.c Wed Nov  7 12:30:06 2018
@@ -48,6 +48,7 @@ typedef struct edit_baton_t {
   svn_boolean_t started;
   svn_boolean_t sending_textdelta;
   int compression_level;
+  int svndiff_version;
 } edit_baton_t;
 
 
@@ -326,7 +327,7 @@ apply_textdelta(void *file_baton,
                           dav_svn__make_base64_output_stream(eb->bb,
                                                              eb->output,
                                                              pool),
-                          0,
+                          eb->svndiff_version,
                           eb->compression_level,
                           pool);
 
@@ -369,6 +370,7 @@ make_editor(const svn_delta_editor_t **e
             apr_bucket_brigade *bb,
             dav_svn__output *output,
             int compression_level,
+            int svndiff_version,
             apr_pool_t *pool)
 {
   edit_baton_t *eb = apr_pcalloc(pool, sizeof(*eb));
@@ -379,6 +381,7 @@ make_editor(const svn_delta_editor_t **e
   eb->started = FALSE;
   eb->sending_textdelta = FALSE;
   eb->compression_level = compression_level;
+  eb->svndiff_version = svndiff_version;
 
   e->set_target_revision = set_target_revision;
   e->open_root = open_root;
@@ -434,7 +437,7 @@ dav_svn__replay_report(const dav_resourc
      URL, and BASE_DIR is embedded in the request body.
 
      The old-school (and incorrect, see issue #4287 --
-     http://subversion.tigris.org/issues/show_bug.cgi?id=4287) way was
+     https://issues.apache.org/jira/browse/SVN-4287) way was
      to REPORT on the public URL of the BASE_DIR and embed the REV in
      the report body.
   */
@@ -544,6 +547,7 @@ dav_svn__replay_report(const dav_resourc
 
   make_editor(&editor, &edit_baton, bb, output,
               dav_svn__get_compression_level(resource->info->r),
+              resource->info->svndiff_version,
               resource->pool);
 
   if ((err = svn_repos_replay2(root, base_dir, low_water_mark,

Modified: subversion/branches/ra-git/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/mod_dav_svn/repos.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/ra-git/subversion/mod_dav_svn/repos.c Wed Nov  7 12:30:06 2018
@@ -1739,6 +1739,18 @@ static int sort_encoding_pref(const void
   return (diff == 0 ? 0 : (diff > 0 ? -1 : 1));
 }
 
+static int get_svndiff_version(const struct accept_rec *rec)
+{
+  if (strcmp(rec->name, "svndiff2") == 0)
+    return 2;
+  else if (strcmp(rec->name, "svndiff1") == 0)
+    return 1;
+  else if (strcmp(rec->name, "svndiff") == 0)
+    return 0;
+  else
+    return -1;
+}
+
 /* Parse and handle any possible Accept-Encoding header that has been
    sent as part of the request.  */
 static void
@@ -1752,6 +1764,9 @@ negotiate_encoding_prefs(request_rec *r,
      necessary ones in this file. */
   int i;
   apr_array_header_t *encoding_prefs;
+  apr_array_header_t *svndiff_encodings;
+  svn_boolean_t accepts_svndiff2 = FALSE;
+
   encoding_prefs = do_header_line(r->pool,
                                   apr_table_get(r->headers_in,
                                                 "Accept-Encoding"));
@@ -1762,22 +1777,47 @@ negotiate_encoding_prefs(request_rec *r,
       return;
     }
 
-  *svndiff_version = 0;
-  svn_sort__array(encoding_prefs, sort_encoding_pref);
+  svndiff_encodings = apr_array_make(r->pool, 3, sizeof(struct accept_rec));
   for (i = 0; i < encoding_prefs->nelts; i++)
     {
-      struct accept_rec rec = APR_ARRAY_IDX(encoding_prefs, i,
-                                            struct accept_rec);
-      if (strcmp(rec.name, "svndiff1") == 0)
-        {
-          *svndiff_version = 1;
-          break;
-        }
-      else if (strcmp(rec.name, "svndiff") == 0)
-        {
-          *svndiff_version = 0;
-          break;
-        }
+      const struct accept_rec *rec = &APR_ARRAY_IDX(encoding_prefs, i,
+                                                    struct accept_rec);
+      int version = get_svndiff_version(rec);
+
+      if (version > 0)
+        APR_ARRAY_PUSH(svndiff_encodings, struct accept_rec) = *rec;
+
+      if (version == 2)
+        accepts_svndiff2 = TRUE;
+    }
+
+  if (dav_svn__get_compression_level(r) == 0)
+    {
+      /* If the compression is disabled on the server, use the uncompressed
+       * svndiff0 format, which we assume is always supported. */
+      *svndiff_version = 0;
+    }
+  else if (accepts_svndiff2 && dav_svn__get_compression_level(r) == 1)
+    {
+      /* Enable svndiff2 if the client can read it, and if the server-side
+       * compression level is set to 1.  Svndiff2 offers better speed and
+       * compression ratio comparable to svndiff1 with compression level 1,
+       * but not with other compression levels.
+       */
+      *svndiff_version = 2;
+    }
+  else if (svndiff_encodings->nelts > 0)
+    {
+      const struct accept_rec *rec;
+
+      /* Otherwise, use what the client prefers to see. */
+      svn_sort__array(svndiff_encodings, sort_encoding_pref);
+      rec = &APR_ARRAY_IDX(svndiff_encodings, 0, struct accept_rec);
+      *svndiff_version = get_svndiff_version(rec);
+    }
+  else
+    {
+      *svndiff_version = 0;
     }
 }
 
@@ -2821,6 +2861,13 @@ open_stream(const dav_resource *resource
                                     "Resource body changes may only be made to "
                                     "working resources (at this time).");
         }
+      if (!resource->info->root.root)
+        {
+          return dav_svn__new_error(resource->pool, HTTP_METHOD_NOT_ALLOWED,
+                                    0, 0,
+                                    "Resource body changes may only be made to "
+                                    "checked-out resources (at this time).");
+        }
     }
 
   /* ### TODO:  Can we support range writes someday? */
@@ -2969,6 +3016,26 @@ close_stream(dav_stream *stream, int com
            pool);
     }
 
+  if (stream->wstream != NULL || stream->delta_handler != NULL)
+    {
+      request_rec *r = stream->res->info->r;
+      svn_checksum_t *checksum;
+
+      serr = svn_fs_file_checksum(&checksum, svn_checksum_md5,
+                                  stream->res->info->root.root,
+                                  stream->res->info->repos_path,
+                                  FALSE, pool);
+      if (serr)
+        return dav_svn__convert_err
+          (serr, HTTP_INTERNAL_SERVER_ERROR,
+            "mod_dav_svn close_stream: error getting file checksum",
+            pool);
+
+      if (checksum)
+        apr_table_set(r->headers_out, SVN_DAV_RESULT_FULLTEXT_MD5_HEADER,
+                      svn_checksum_to_cstring(checksum, pool));
+    }
+
   return NULL;
 }
 

Modified: subversion/branches/ra-git/subversion/mod_dav_svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/mod_dav_svn/util.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/mod_dav_svn/util.c (original)
+++ subversion/branches/ra-git/subversion/mod_dav_svn/util.c Wed Nov  7 12:30:06 2018
@@ -37,6 +37,7 @@
 #include "svn_fs.h"
 #include "svn_dav.h"
 #include "svn_base64.h"
+#include "svn_ctype.h"
 
 #include "dav_svn.h"
 #include "private/svn_fspath.h"
@@ -954,3 +955,48 @@ dav_svn__get_youngest_rev(svn_revnum_t *
    *youngest_p = repos->youngest_rev;
    return SVN_NO_ERROR;
 }
+
+const char *
+dav_svn__fuzzy_escape_author(const char *author,
+                             svn_boolean_t is_svn_client,
+                             apr_pool_t *result_pool,
+                             apr_pool_t *scratch_pool)
+{
+  apr_size_t len = strlen(author);
+  if (is_svn_client && !svn_xml_is_xml_safe(author, len))
+    {
+      /* We are talking to a Subversion client, which will (like any proper
+         xml parser) error out if we produce control characters in XML.
+
+         However Subversion clients process both the generic
+         <creator-displayname /> as the custom element for svn:author.
+
+         Let's skip outputting the invalid characters here to make the XML
+         valid, so clients can see the custom element.
+
+         Subversion Clients will then either use a slightly invalid
+         author (unlikely) or more likely use the second result, which
+         will be transferred with full escaping capabilities.
+
+         We have tests in place to assert proper behavior over the RA layer.
+       */
+      apr_size_t i;
+      svn_stringbuf_t *buf;
+
+      buf = svn_stringbuf_ncreate(author, len, scratch_pool);
+
+      for (i = 0; i < buf->len; i++)
+        {
+          char c = buf->data[i];
+
+          if (svn_ctype_iscntrl(c))
+            {
+              svn_stringbuf_remove(buf, i--, 1);
+            }
+        }
+
+      author = buf->data;
+    }
+
+  return apr_xml_quote_string(result_pool, author, 1);
+}

Modified: subversion/branches/ra-git/subversion/mod_dav_svn/version.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/mod_dav_svn/version.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/mod_dav_svn/version.c (original)
+++ subversion/branches/ra-git/subversion/mod_dav_svn/version.c Wed Nov  7 12:30:06 2018
@@ -152,7 +152,7 @@ get_vsn_options(apr_pool_t *p, apr_text_
   apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_INHERITED_PROPS);
   apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_INLINE_PROPS);
   apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_REVERSE_FILE_REVS);
-  apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_SVNDIFF1);
+  apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_LIST);
   /* Mergeinfo is a special case: here we merely say that the server
    * knows how to handle mergeinfo -- whether the repository does too
    * is a separate matter.
@@ -176,11 +176,29 @@ get_option(const dav_resource *resource,
            const apr_xml_elem *elem,
            apr_text_header *option)
 {
+  int i;
   request_rec *r = resource->info->r;
   const char *repos_root_uri =
     dav_svn__build_uri(resource->info->repos, DAV_SVN__BUILD_URI_PUBLIC,
                        SVN_IGNORED_REVNUM, "", FALSE /* add_href */,
                        resource->pool);
+  svn_version_t *master_version = dav_svn__get_master_version(r);
+
+  /* These capabilities are used during commit and when configured as
+     a WebDAV slave (SVNMasterURI is set) their availablity should
+     depend on the master version (SVNMasterVersion is set) if it is
+     older than our own version.  Also, although SVNDIFF1 is available
+     before 1.10 none of those earlier servers advertised it so for
+     consistency we don't advertise it for masters older than 1.10. */
+  struct capability_versions_t {
+    const char *capability_name;
+    svn_version_t min_version;
+  } capabilities[] = {
+    { SVN_DAV_NS_DAV_SVN_EPHEMERAL_TXNPROPS,  { 1,  8, 0, ""} },
+    { SVN_DAV_NS_DAV_SVN_SVNDIFF1,            { 1, 10, 0, ""} },
+    { SVN_DAV_NS_DAV_SVN_SVNDIFF2,            { 1, 10, 0, ""} },
+    { SVN_DAV_NS_DAV_SVN_PUT_RESULT_CHECKSUM, { 1, 10, 0, ""} },
+  };
 
   /* ### DAV:version-history-collection-set */
   if (elem->ns != APR_XML_NS_DAV_ID
@@ -206,14 +224,6 @@ get_option(const dav_resource *resource,
   apr_text_append(resource->pool, option,
                   "</D:activity-collection-set>");
 
-  /* If we're allowed (by configuration) to do so, advertise support
-     for ephemeral transaction properties. */
-  if (dav_svn__check_ephemeral_txnprops_support(r))
-    {
-      apr_table_addn(r->headers_out, "DAV",
-                     SVN_DAV_NS_DAV_SVN_EPHEMERAL_TXNPROPS);
-    }
-
   if (resource->info->repos->fs)
     {
       svn_error_t *serr;
@@ -274,8 +284,6 @@ get_option(const dav_resource *resource,
      DeltaV-free!  If we're configured to advise this support, do so.  */
   if (resource->info->repos->v2_protocol)
     {
-      int i;
-      svn_version_t *master_version = dav_svn__get_master_version(r);
       dav_svn__bulk_upd_conf bulk_upd_conf = dav_svn__get_bulk_updates_flag(r);
 
       /* The list of Subversion's custom POSTs and which versions of
@@ -346,6 +354,22 @@ get_option(const dav_resource *resource,
         }
     }
 
+  /* Report commit capabilites. */
+  for (i = 0; i < sizeof(capabilities)/sizeof(capabilities[0]); ++i)
+    {
+      /* If a master version is declared filter out unsupported
+         capabilities. */
+      if (master_version
+          && (!svn_version__at_least(master_version,
+                                     capabilities[i].min_version.major,
+                                     capabilities[i].min_version.minor,
+                                     capabilities[i].min_version.patch)))
+        continue;
+
+      apr_table_addn(r->headers_out, "DAV",
+                     apr_pstrdup(r->pool, capabilities[i].capability_name));
+    }
+
   return NULL;
 }
 
@@ -1152,6 +1176,10 @@ deliver_report(request_rec *r,
         {
           return dav_svn__get_inherited_props_report(resource, doc, output);
         }
+      else if (strcmp(doc->root->name, "list-report") == 0)
+        {
+          return dav_svn__list_report(resource, doc, output);
+        }
       /* NOTE: if you add a report, don't forget to add it to the
        *       dav_svn__reports_list[] array.
        */