Modified: subversion/branches/addremove/subversion/mod_authz_svn/mod_authz_svn.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/mod_authz_svn/mod_authz_svn.c?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/mod_authz_svn/mod_authz_svn.c 
(original)
+++ subversion/branches/addremove/subversion/mod_authz_svn/mod_authz_svn.c Sat 
May 23 14:16:56 2020
@@ -92,7 +92,7 @@ typedef struct authz_svn_config_rec {
 #    define USE_FORCE_AUTHN 1
 #    define IN_SOME_AUTHN_NOTE "authz_svn-in-some-authn"
 #    define FORCE_AUTHN_NOTE "authz_svn-force-authn"
-#  else 
+#  else
      /* ap_some_auth_required() is busted and no viable alternative exists */
 #    ifndef SVN_ALLOW_BROKEN_HTTPD_AUTH
 #      error This Apache httpd has broken auth (CVE-2015-3184)
@@ -327,16 +327,17 @@ log_access_verdict(LOG_ARGS_SIGNATURE,
     }
 }
 
-/* Log a message indiciating the ERR encountered during the request R.
+/* Log a message at LOG_LEVEL indicating the ERR encountered during
+ * the request R.
  * LOG_ARGS_SIGNATURE expands as in log_access_verdict() above.
  * PREFIX is inserted at the start of the message.  The rest of the
  * message is generated by combining the message for each error in the
  * chain of ERR, excluding for trace errors.  ERR will be cleared
  * when finished. */
 static void
-log_svn_error(LOG_ARGS_SIGNATURE,
-              request_rec *r, const char *prefix,
-              svn_error_t *err, apr_pool_t *scratch_pool)
+log_svn_message(LOG_ARGS_SIGNATURE, int log_level,
+                request_rec *r, const char *prefix,
+                svn_error_t *err, apr_pool_t *scratch_pool)
 {
   svn_error_t *err_pos = svn_error_purge_tracing(err);
   svn_stringbuf_t *buff = svn_stringbuf_create(prefix, scratch_pool);
@@ -360,7 +361,7 @@ log_svn_error(LOG_ARGS_SIGNATURE,
       err_pos = err_pos->child;
     }
 
-  ap_log_rerror(LOG_ARGS_CASCADE, APLOG_ERR,
+  ap_log_rerror(LOG_ARGS_CASCADE, log_level,
                 /* If it is an error code that APR can make sense of, then
                    show it, otherwise, pass zero to avoid putting "APR does
                    not understand this error code" in the error log. */
@@ -372,6 +373,40 @@ log_svn_error(LOG_ARGS_SIGNATURE,
   svn_error_clear(err);
 }
 
+/* Log the error error ERR encountered during the request R.
+ * LOG_ARGS_SIGNATURE expands as in log_access_verdict() above.
+ * PREFIX is inserted at the start of the message.  The rest of the
+ * message is generated by combining the message for each error in the
+ * chain of ERR, excluding for trace errors.  ERR will be cleared
+ * when finished. */
+static APR_INLINE void
+log_svn_error(LOG_ARGS_SIGNATURE,
+              request_rec *r, const char *prefix,
+              svn_error_t *err, apr_pool_t *scratch_pool)
+{
+  log_svn_message(LOG_ARGS_CASCADE, APLOG_ERR,
+                  r, prefix, err, scratch_pool);
+}
+
+/* Baton for log_authz_warning. */
+typedef struct authz_warning_baton_t
+{
+  request_rec *r;
+  const char *prefix;
+} authz_warning_baton_t;
+
+/* Handle an authz parser warning. ERR will *not* be cleared.*/
+static APR_INLINE void
+log_authz_warning(void *baton,
+                  const svn_error_t *err,
+                  apr_pool_t *scratch_pool)
+{
+  const authz_warning_baton_t *const warning_baton = baton;
+  log_svn_message(APLOG_MARK, APLOG_WARNING,
+                  warning_baton->r, warning_baton->prefix,
+                  svn_error_dup(err), scratch_pool);
+}
+
 /* Resolve *PATH into an absolute canonical URL iff *PATH is a repos-relative
  * URL.  If *REPOS_URL is NULL convert REPOS_PATH into a file URL stored
  * in *REPOS_URL, if *REPOS_URL is not null REPOS_PATH is ignored.  The
@@ -401,10 +436,12 @@ static svn_authz_t *
 get_access_conf(request_rec *r, authz_svn_config_rec *conf,
                 apr_pool_t *scratch_pool)
 {
+  const char *cache_key = NULL;
   const char *access_file;
   const char *groups_file;
   const char *repos_path;
   const char *repos_url = NULL;
+  void *user_data = NULL;
   svn_authz_t *access_conf = NULL;
   svn_error_t *svn_err = SVN_NO_ERROR;
   dav_error *dav_err;
@@ -464,19 +501,36 @@ get_access_conf(request_rec *r, authz_sv
                     "Path to groups file is %s", groups_file);
     }
 
-  svn_err = svn_repos_authz_read3(&access_conf,
-                                  access_file, groups_file,
-                                  TRUE, NULL,
-                                  r->connection->pool, scratch_pool);
-
-  if (svn_err)
+  cache_key = apr_pstrcat(scratch_pool, "mod_authz_svn:",
+                          access_file, groups_file, SVN_VA_NULL);
+  apr_pool_userdata_get(&user_data, cache_key, r->connection->pool);
+  access_conf = user_data;
+  if (access_conf == NULL)
     {
-      log_svn_error(APLOG_MARK, r,
-                    "Failed to load the mod_authz_svn config:",
-                    svn_err, scratch_pool);
-      access_conf = NULL;
-    }
+      authz_warning_baton_t warning_baton;
+      warning_baton.r = r;
+      warning_baton.prefix = "mod_authz_svn: warning:";
+
+      svn_err = svn_repos_authz_read4(&access_conf, access_file,
+                                      groups_file, TRUE, NULL,
+                                      log_authz_warning, &warning_baton,
+                                      r->connection->pool,
+                                      scratch_pool);
 
+      if (svn_err)
+        {
+          log_svn_error(APLOG_MARK, r,
+                        "Failed to load the mod_authz_svn config:",
+                        svn_err, scratch_pool);
+          access_conf = NULL;
+        }
+      else
+        {
+          /* Cache the open repos for the next request on this connection */
+          apr_pool_userdata_set(access_conf, cache_key,
+                                NULL, r->connection->pool);
+        }
+    }
   return access_conf;
 }
 
@@ -700,9 +754,9 @@ req_check_access(request_rec *r,
    *
    * However, if repos_path == NULL and the request requires write
    * access, then perform a global authz lookup.  The request is
-   * denied if the user commiting isn't granted any access anywhere
+   * denied if the user committing isn't granted any access anywhere
    * in the repository.  This is to avoid operations that involve no
-   * paths (commiting an empty revision, leaving a dangling
+   * paths (committing an empty revision, leaving a dangling
    * transaction in the FS) being granted by default, letting
    * unauthenticated users write some changes to the repository.
    * This was issue #2388.
@@ -898,7 +952,7 @@ access_checker(request_rec *r)
         {
           /* Set the note to force authn regardless of what access_checker_ex
              hook requires */
-          apr_table_setn(r->notes, FORCE_AUTHN_NOTE, (const char*)1);
+          apr_table_setn(r->notes, FORCE_AUTHN_NOTE, "1");
 
           /* provide the proper return so the access_checker hook doesn't
            * prevent the code from continuing on to the other auth hooks */
@@ -907,7 +961,7 @@ access_checker(request_rec *r)
           else
             return HTTP_FORBIDDEN;
         }
-    }    
+    }
 
 #else
   /* Support for older versions of httpd that have a working
@@ -964,7 +1018,7 @@ access_checker(request_rec *r)
            * ap_some_authn_rquired() without triggering an infinite
            * loop since the call will trigger this function to be
            * called again. */
-          apr_table_setn(r->notes, IN_SOME_AUTHN_NOTE, (const char*)1);
+          apr_table_setn(r->notes, IN_SOME_AUTHN_NOTE, "1");
           authn_required = ap_some_authn_required(r);
           apr_table_unset(r->notes, IN_SOME_AUTHN_NOTE);
           if (authn_required)
@@ -1007,7 +1061,7 @@ check_user_id(request_rec *r)
   status = req_check_access(r, conf, &repos_path, &dest_repos_path);
   if (status == OK)
     {
-      apr_table_setn(r->notes, "authz_svn-anon-ok", (const char*)1);
+      apr_table_setn(r->notes, "authz_svn-anon-ok", "1");
       log_access_verdict(APLOG_MARK, r, 1, FALSE, repos_path, dest_repos_path);
       return OK;
     }
@@ -1093,7 +1147,7 @@ register_hooks(apr_pool_t *p)
 module AP_MODULE_DECLARE_DATA authz_svn_module =
 {
   STANDARD20_MODULE_STUFF,
-  create_authz_svn_dir_config,     /* dir config creater */
+  create_authz_svn_dir_config,     /* dir config creator */
   NULL,                            /* dir merger --- default is to override */
   NULL,                            /* server config */
   NULL,                            /* merge server config */

Modified: subversion/branches/addremove/subversion/mod_dav_svn/dav_svn.h
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/mod_dav_svn/dav_svn.h?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/branches/addremove/subversion/mod_dav_svn/dav_svn.h Sat May 23 
14:16:56 2020
@@ -205,7 +205,7 @@ typedef struct dav_svn_root {
   */
   const char *activity_id;
 
-  /* If the root is part of a transaction, this contains the FS's tranaction
+  /* If the root is part of a transaction, this contains the FS's transaction
      name. It may be NULL if this root corresponds to a specific revision.
      It may also be NULL if we have not opened the root yet.
 
@@ -303,6 +303,9 @@ struct dav_resource_private {
   /* whether this resource parameters are fixed and won't change
      between requests. */
   svn_boolean_t idempotent;
+
+  /* resource is accessed by 'public' uri (not under "!svn") */
+  svn_boolean_t is_public_uri;
 };
 
 
@@ -359,10 +362,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 +704,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 +757,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.  */
@@ -1104,7 +1109,7 @@ int dav_svn__parse_request_skel(svn_skel
 /* Set *YOUNGEST_P to the number of the youngest revision in REPOS.
  *
  * Youngest revision will be cached in REPOS->YOUNGEST_REV to avoid
- * fetching the youngest revision multiple times during proccessing
+ * fetching the youngest revision multiple times during processing
  * the request.
  *
  * Uses SCRATCH_POOL for temporary allocations.
@@ -1114,6 +1119,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/addremove/subversion/mod_dav_svn/liveprops.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/mod_dav_svn/liveprops.c?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/mod_dav_svn/liveprops.c (original)
+++ subversion/branches/addremove/subversion/mod_dav_svn/liveprops.c Sat May 23 
14:16:56 2020
@@ -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/addremove/subversion/mod_dav_svn/mirror.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/mod_dav_svn/mirror.c?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/mod_dav_svn/mirror.c (original)
+++ subversion/branches/addremove/subversion/mod_dav_svn/mirror.c Sat May 23 
14:16:56 2020
@@ -97,7 +97,7 @@ int dav_svn__proxy_request_fixup(request
            ourselves -- but we need to make sure they aren't aimed at
            resources that only exist on the master server such as
            working resource URIs or the HTTPv2 transaction root and
-           transaction tree resouces. */
+           transaction tree resources. */
         if (r->method_number == M_PROPFIND ||
             r->method_number == M_GET) {
             if ((seg = ap_strstr(r->uri, root_dir))) {

Modified: subversion/branches/addremove/subversion/mod_dav_svn/mod_dav_svn.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/mod_dav_svn/mod_dav_svn.c?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/mod_dav_svn/mod_dav_svn.c 
(original)
+++ subversion/branches/addremove/subversion/mod_dav_svn/mod_dav_svn.c Sat May 
23 14:16:56 2020
@@ -231,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;
 }
 
@@ -289,10 +292,14 @@ 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: Location '%s' hinders access to '%s' "
-                 "in parent SVNPath Location '%s'",
+                 "in parent SVNPath Location '%s'%s",
                  child->root_dir,
                  svn_urlpath__skip_ancestor(parent->root_dir, child->root_dir),
-                 parent->root_dir);
+                 parent->root_dir,
+                 (strcmp(child->root_dir, parent->root_dir) == 0)
+                   ? " (or the subversion-specific configuration"
+                     " is included twice into httpd.conf)"
+                   : "");
 
   return newconf;
 }
@@ -923,21 +930,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.
  */
@@ -1270,7 +1262,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;
 }
 
@@ -1479,7 +1471,7 @@ register_hooks(apr_pool_t *pconf)
   /* translate_name hook is LAST so that it doesn't interfere with modules
    * like mod_alias that are MIDDLE. */
   ap_hook_translate_name(dav_svn__translate_name, NULL, NULL, APR_HOOK_LAST);
-  /* map_to_storage hook is LAST to avoid interferring with mod_http's
+  /* map_to_storage hook is LAST to avoid interfering with mod_http's
    * handling of OPTIONS and TRACE. */
   ap_hook_map_to_storage(dav_svn__map_to_storage, NULL, NULL, APR_HOOK_LAST);
 }

Modified: 
subversion/branches/addremove/subversion/mod_dav_svn/reports/file-revs.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/mod_dav_svn/reports/file-revs.c?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/mod_dav_svn/reports/file-revs.c 
(original)
+++ subversion/branches/addremove/subversion/mod_dav_svn/reports/file-revs.c 
Sat May 23 14:16:56 2020
@@ -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>"));
     }
@@ -333,7 +333,7 @@ dav_svn__file_revs_report(const dav_reso
   if ((serr = maybe_send_header(&frb)))
     {
       derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
-                                  "Error beginning REPORT reponse",
+                                  "Error beginning REPORT response",
                                   resource->pool);
       goto cleanup;
     }
@@ -342,7 +342,7 @@ dav_svn__file_revs_report(const dav_reso
                                     "</S:file-revs-report>" DEBUG_CR)))
     {
       derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
-                                  "Error ending REPORT reponse",
+                                  "Error ending REPORT response",
                                   resource->pool);
       goto cleanup;
     }

Modified: subversion/branches/addremove/subversion/mod_dav_svn/reports/log.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/mod_dav_svn/reports/log.c?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/mod_dav_svn/reports/log.c 
(original)
+++ subversion/branches/addremove/subversion/mod_dav_svn/reports/log.c Sat May 
23 14:16:56 2020
@@ -61,7 +61,7 @@ struct log_receiver_baton
      callbacks. */
   svn_boolean_t needs_log_item;
 
-  /* How deep we are in the log message tree.  We only need to surpress the
+  /* How deep we are in the log message tree.  We only need to suppress the
      SVN_INVALID_REVNUM message if the stack_depth is 0. */
   int stack_depth;
 
@@ -125,7 +125,7 @@ start_path_with_copy_from(const char **e
 {
   switch (log_item->change_kind)
     {
-      case svn_fs_path_change_add: 
+      case svn_fs_path_change_add:
         *element = "S:added-path";
         break;
 
@@ -244,7 +244,7 @@ log_revision_receiver(void *baton,
   SVN_ERR(maybe_start_log_item(lrb));
   lrb->needs_log_item = TRUE;
 
-  /* Path changes have been processed already. 
+  /* Path changes have been processed already.
      Now send the remaining per-revision info. */
   SVN_ERR(dav_svn__brigade_printf(lrb->bb, lrb->output,
                                   "<D:version-name>%ld"
@@ -325,7 +325,7 @@ log_revision_receiver(void *baton,
 
   /* In general APR will flush the brigade every 8000 bytes through the filter
      stack, but log items may not be generated that fast, especially in
-     combination with authz and busy servers. We now explictly flush after
+     combination with authz and busy servers. We now explicitly flush after
      log-item 4, 16, 64 and 256 to produce a few results fast.
 
      This introduces 4 full flushes of our brigade and the installed output

Modified: subversion/branches/addremove/subversion/mod_dav_svn/reports/replay.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/mod_dav_svn/reports/replay.c?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/mod_dav_svn/reports/replay.c 
(original)
+++ subversion/branches/addremove/subversion/mod_dav_svn/reports/replay.c Sat 
May 23 14:16:56 2020
@@ -437,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.
   */

Modified: subversion/branches/addremove/subversion/mod_dav_svn/repos.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/mod_dav_svn/repos.c?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/addremove/subversion/mod_dav_svn/repos.c Sat May 23 
14:16:56 2020
@@ -714,6 +714,8 @@ parse_uri(dav_resource_combined *comb,
       && ((ch = uri[len2]) == '/' || ch == '\0')
       && memcmp(uri, special_uri, len2) == 0)
     {
+      comb->priv.is_public_uri = FALSE;
+
       if (ch == '\0')
         {
           /* URI was "/root/!svn". It exists, but has restricted usage. */
@@ -789,6 +791,8 @@ parse_uri(dav_resource_combined *comb,
       /* The location of these resources corresponds directly to the URI,
          and we keep the leading "/". */
       comb->priv.repos_path = comb->priv.uri_path->data;
+
+      comb->priv.is_public_uri = TRUE;
     }
 
   return FALSE;
@@ -1225,25 +1229,32 @@ create_private_resource(const dav_resour
   return &comb->res;
 }
 
-
-static void log_warning(void *baton, svn_error_t *err)
+static void log_warning_req(void *baton, svn_error_t *err)
 {
   request_rec *r = baton;
   const char *continuation = "";
 
-  /* ### hmm. the FS is cleaned up at request cleanup time. "r" might
-     ### not really be valid. we should probably put the FS into a
-     ### subpool to ensure it gets cleaned before the request.
+  /* Not showing file/line so no point in tracing */
+  err = svn_error_purge_tracing(err);
+  while (err)
+    {
+      ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r, "%s%s",
+                    continuation, err->message);
+      continuation = "-";
+      err = err->child;
+    }
+}
 
-     ### is there a good way to create and use a subpool for all
-     ### of our functions ... ??
-  */
+static void log_warning_conn(void *baton, svn_error_t *err)
+{
+  conn_rec *c = baton;
+  const char *continuation = "";
 
   /* Not showing file/line so no point in tracing */
   err = svn_error_purge_tracing(err);
   while (err)
     {
-      ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r, "%s%s",
+      ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, c, "%s%s",
                     continuation, err->message);
       continuation = "-";
       err = err->child;
@@ -1547,6 +1558,24 @@ cleanup_fs_access(void *data)
   return APR_SUCCESS;
 }
 
+/* Context for cleanup handler. */
+struct cleanup_req_logging_baton
+{
+  svn_fs_t *fs;
+  conn_rec *connection;
+};
+
+static apr_status_t
+cleanup_req_logging(void *data)
+{
+  struct cleanup_req_logging_baton *baton = data;
+
+  /* The request about to be freed. Log future warnings with a connection
+   * context instead of a request context. */
+  svn_fs_set_warning_func(baton->fs, log_warning_conn, baton->connection);
+
+  return APR_SUCCESS;
+}
 
 /* Helper func to construct a special 'parentpath' private resource. */
 static dav_error *
@@ -1571,6 +1600,7 @@ get_parentpath_resource(request_rec *r,
   comb->priv.r = r;
   comb->priv.repos_path = "Collection of Repositories";
   comb->priv.root = *droot;
+  comb->priv.is_public_uri = TRUE;
   droot->rev = SVN_INVALID_REVNUM;
 
   comb->priv.repos = repos;
@@ -1945,7 +1975,7 @@ do_out_of_date_check(dav_resource_combin
          We have to check if whatever the node is in HEAD is equivalent
          to what it was in the provided BASE revision.
 
-         If the node was copied, we would process it before its decendants
+         If the node was copied, we would process it before its descendants
          and we already performed quite a few checks when making it mutable
          via its descendant, so what we should really check here is if the
          properties changed since the BASE version.
@@ -2180,6 +2210,7 @@ get_resource(request_rec *r,
   int had_slash;
   dav_locktoken_list *ltl;
   struct cleanup_fs_access_baton *cleanup_baton;
+  struct cleanup_req_logging_baton *cleanup_req_logging_baton;
   void *userdata;
   apr_hash_t *fs_config;
 
@@ -2486,7 +2517,15 @@ get_resource(request_rec *r,
   repos->fs = svn_repos_fs(repos->repos);
 
   /* capture warnings during cleanup of the FS */
-  svn_fs_set_warning_func(repos->fs, log_warning, r);
+  svn_fs_set_warning_func(repos->fs, log_warning_req, r);
+
+  /* We must degrade the logging context when the request is freed. */
+  cleanup_req_logging_baton =
+    apr_pcalloc(r->pool, sizeof(*cleanup_req_logging_baton));
+  cleanup_req_logging_baton->fs = repos->fs;
+  cleanup_req_logging_baton->connection = r->connection;
+  apr_pool_pre_cleanup_register(r->pool, cleanup_req_logging_baton,
+                                cleanup_req_logging);
 
   /* if an authenticated username is present, attach it to the FS */
   if (r->user)
@@ -2861,6 +2900,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? */
@@ -3178,6 +3224,45 @@ set_headers(request_rec *r, const dav_re
   if (!resource->exists)
     return NULL;
 
+  if ((resource->type == DAV_RESOURCE_TYPE_REGULAR)
+      && resource->info->is_public_uri)
+    {
+      /* Include Last-Modified header for 'external' GET or HEAD requests
+         (i.e. requests to URI's not under /!svn), to support usage of an
+         SVN server as a file server, where the client needs timestamps
+         for instance to use as "last modification time" of files on disk. */
+
+      svn_revnum_t created_rev;
+      svn_string_t *date_str = NULL;
+
+      serr = svn_fs_node_created_rev(&created_rev, resource->info->root.root,
+                                     resource->info->repos_path,
+                                     resource->pool);
+
+      if (serr == NULL)
+        {
+          serr = svn_fs_revision_prop2(&date_str, resource->info->repos->fs,
+                                       created_rev, SVN_PROP_REVISION_DATE,
+                                       TRUE, resource->pool, resource->pool);
+        }
+
+      if ((serr == NULL) && date_str && date_str->data)
+        {
+          apr_time_t mtime;
+          serr = svn_time_from_cstring(&mtime, date_str->data, resource->pool);
+
+          if (serr == NULL)
+            {
+              /* Note the modification time for the requested resource, and
+                 include the Last-Modified header in the response. */
+              ap_update_mtime(r, mtime);
+              ap_set_last_modified(r);
+            }
+        }
+
+      svn_error_clear(serr);
+    }
+
   /* generate our etag and place it into the output */
   apr_table_setn(r->headers_out, "ETag",
                  dav_svn__getetag(resource, resource->pool));
@@ -3484,7 +3569,7 @@ emit_collection_entry(const dav_resource
 
   /* According to httpd-2.0.54/include/httpd.h, ap_os_escape_path()
      behaves differently on different platforms.  It claims to
-     "convert an OS path to a URL in an OS dependant way".
+     "convert an OS path to a URL in an OS dependent way".
      Nevertheless, there appears to be only one implementation
      of the function in httpd, and the code seems completely
      platform independent, so we'll assume it's appropriate for
@@ -4021,7 +4106,7 @@ create_collection(dav_resource *resource
                               "autoversioning is not active.");
 
   /* ### note that the parent was checked out at some point, and this
-     ### is being preformed relative to the working rsrc for that parent */
+     ### is being performed relative to the working rsrc for that parent */
 
   /* Auto-versioning mkcol of regular resource: */
   if (resource->type == DAV_RESOURCE_TYPE_REGULAR)
@@ -4200,7 +4285,7 @@ remove_resource(dav_resource *resource,
     }
 
   /* ### note that the parent was checked out at some point, and this
-     ### is being preformed relative to the working rsrc for that parent */
+     ### is being performed relative to the working rsrc for that parent */
 
   /* NOTE: strictly speaking, we cannot determine whether the parent was
      ever checked out, and that this working resource is relative to that

Modified: subversion/branches/addremove/subversion/mod_dav_svn/util.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/mod_dav_svn/util.c?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/mod_dav_svn/util.c (original)
+++ subversion/branches/addremove/subversion/mod_dav_svn/util.c Sat May 23 
14:16:56 2020
@@ -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/addremove/subversion/mod_dav_svn/version.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/mod_dav_svn/version.c?rev=1878061&r1=1878060&r2=1878061&view=diff
==============================================================================
--- subversion/branches/addremove/subversion/mod_dav_svn/version.c (original)
+++ subversion/branches/addremove/subversion/mod_dav_svn/version.c Sat May 23 
14:16:56 2020
@@ -152,9 +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_SVNDIFF2);
-  apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_PUT_RESULT_CHECKSUM);
+  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.
@@ -178,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 availability 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
@@ -208,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;
@@ -276,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
@@ -348,6 +354,22 @@ get_option(const dav_resource *resource,
         }
     }
 
+  /* Report commit capabilities. */
+  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;
 }
 
@@ -1154,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.
        */


Reply via email to