Index: subversion/mod_dav_svn/mod_dav_svn.c
===================================================================
--- subversion/mod_dav_svn/mod_dav_svn.c	(revision 1662035)
+++ subversion/mod_dav_svn/mod_dav_svn.c	(working copy)
@@ -48,6 +48,9 @@
 #include "dav_svn.h"
 #include "mod_authz_svn.h"
 
+#if AP_MODULE_MAGIC_AT_LEAST(20111025,3)
+#include <ap_expr.h>
+#endif
 
 /* This is the default "special uri" used for SVN's special resources
    (e.g. working resources, activities) */
@@ -70,6 +73,14 @@
 } server_conf_t;
 
 
+/* combination of path and expression */
+typedef struct path_expr_t {
+    const char *base;                /* base path */
+#if AP_MODULE_MAGIC_AT_LEAST(20111025,3)
+    const ap_expr_info_t *expr;      /* expression suffix added to the base */
+#endif
+} path_expr_t;
+
 /* A tri-state enum used for per directory on/off flags.  Note that
    it's important that CONF_FLAG_DEFAULT is 0 to make
    merge_dir_config in mod_dav_svn do the right thing. */
@@ -89,10 +100,10 @@
 
 /* per-dir configuration */
 typedef struct dir_conf_t {
-  const char *fs_path;               /* path to the SVN FS */
+  path_expr_t *fs_path;              /* path to the SVN FS */
   const char *repo_name;             /* repository name */
   const char *xslt_uri;              /* XSL transform URI */
-  const char *fs_parent_path;        /* path to parent of SVN FS'es  */
+  path_expr_t *fs_parent_path;       /* path to parent of SVN FS'es  */
   enum conf_flag autoversioning;     /* whether autoversioning is active */
   dav_svn__bulk_upd_conf bulk_updates; /* whether bulk updates are allowed */
   enum conf_flag v2_protocol;        /* whether HTTP v2 is advertised */
@@ -469,29 +480,67 @@
 
 
 static const char *
-SVNPath_cmd(cmd_parms *cmd, void *config, const char *arg1)
+SVNPath_cmd(cmd_parms *cmd, void *config, const char *arg1, const char *arg2)
 {
   dir_conf_t *conf = config;
 
   if (conf->fs_parent_path != NULL)
     return "SVNPath cannot be defined at same time as SVNParentPath.";
 
-  conf->fs_path = svn_dirent_internal_style(arg1, cmd->pool);
+  conf->fs_path = apr_pcalloc(cmd->pool, sizeof(path_expr_t));
+  conf->fs_path->base = svn_dirent_internal_style(arg1, cmd->pool);
 
+  if (arg2)
+    {
+#if AP_MODULE_MAGIC_AT_LEAST(20111025,3)
+      const char *expr_err = NULL;
+
+      conf->fs_path->expr = ap_expr_parse_cmd(cmd, arg2, AP_EXPR_FLAG_STRING_RESULT,
+              &expr_err, NULL);
+      if (expr_err)
+        {
+          return apr_pstrcat(cmd->temp_pool,
+                  "Cannot parse expression in SVNPath: ",
+                  expr_err, NULL);
+        }
+#else
+      return "Expressions require httpd v2.4.0 or higher"
+#endif
+    }
+
   return NULL;
 }
 
 
 static const char *
-SVNParentPath_cmd(cmd_parms *cmd, void *config, const char *arg1)
+SVNParentPath_cmd(cmd_parms *cmd, void *config, const char *arg1, const char *arg2)
 {
   dir_conf_t *conf = config;
 
   if (conf->fs_path != NULL)
     return "SVNParentPath cannot be defined at same time as SVNPath.";
 
-  conf->fs_parent_path = svn_dirent_internal_style(arg1, cmd->pool);
+  conf->fs_parent_path = apr_pcalloc(cmd->pool, sizeof(path_expr_t));
+  conf->fs_parent_path->base = svn_dirent_internal_style(arg1, cmd->pool);
 
+  if (arg2)
+    {
+#if AP_MODULE_MAGIC_AT_LEAST(20111025,3)
+      const char *expr_err = NULL;
+
+      conf->fs_parent_path->expr = ap_expr_parse_cmd(cmd, arg2, AP_EXPR_FLAG_STRING_RESULT,
+              &expr_err, NULL);
+      if (expr_err)
+        {
+          return apr_pstrcat(cmd->temp_pool,
+                  "Cannot parse expression in SVNParentPath: ",
+                      expr_err, NULL);
+        }
+#else
+      return "Expressions require httpd v2.4.0 or higher"
+#endif
+    }
+
   return NULL;
 }
 
@@ -668,7 +717,61 @@
   dir_conf_t *conf;
 
   conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
-  return conf->fs_path;
+
+  if (conf->fs_path)
+    {
+
+  #if AP_MODULE_MAGIC_AT_LEAST(20111025,3)
+      if (conf->fs_path->expr)
+        {
+          svn_error_t *serr;
+          svn_boolean_t under_root;
+          const char *err = NULL, *suffix;
+
+          suffix = ap_expr_str_exec(r, conf->fs_path->expr, &err);
+          if (!err)
+            {
+              serr = svn_dirent_is_under_root(&under_root,
+                      &suffix, conf->fs_path->base, suffix, r->pool);
+              if (!serr && under_root)
+                {
+                  return svn_dirent_join(conf->fs_path->base,
+                          svn_dirent_internal_style(suffix, r->pool), r->pool);
+                }
+              else if (serr)
+                {
+                  ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err, r,
+                          "mod_dav_svn: SVNPath: '%s' not under '%s': '%s'",
+                          suffix, conf->fs_path->base,
+                          serr->message ? serr->message : "(no more info)");
+                  return NULL;
+                }
+              else
+                {
+                  ap_log_rerror(
+                          APLOG_MARK, APLOG_ERR, 0, r,
+                          "mod_dav_svn: SVNPath: '%s' not under '%s'",
+                          suffix, conf->fs_path->base);
+                  return NULL;
+                }
+            }
+          else
+            {
+              ap_log_rerror(
+                      APLOG_MARK, APLOG_ERR, 0, r, "mod_dav_svn: SVNPath: can't "
+                      "evaluate expression: %s", err);
+              return NULL;
+            }
+
+        }
+  #endif
+
+      return conf->fs_path->base;
+    }
+  else
+    {
+      return NULL;
+    }
 }
 
 
@@ -678,7 +781,61 @@
   dir_conf_t *conf;
 
   conf = ap_get_module_config(r->per_dir_config, &dav_svn_module);
-  return conf->fs_parent_path;
+
+  if (conf->fs_parent_path)
+    {
+
+#if AP_MODULE_MAGIC_AT_LEAST(20111025,3)
+      if (conf->fs_parent_path->expr)
+        {
+          svn_error_t *serr;
+          svn_boolean_t under_root;
+          const char *err = NULL, *suffix;
+
+          suffix = ap_expr_str_exec(r, conf->fs_parent_path->expr, &err);
+          if (!err)
+            {
+              serr = svn_dirent_is_under_root(&under_root,
+                      &suffix, conf->fs_parent_path->base, suffix, r->pool);
+              if (!serr && under_root)
+                {
+                  return svn_dirent_join(conf->fs_parent_path->base,
+                          svn_dirent_internal_style(suffix, r->pool), r->pool);
+                }
+              else if (serr)
+                {
+                  ap_log_rerror(APLOG_MARK, APLOG_ERR, serr->apr_err, r,
+                          "mod_dav_svn: SVNParentPath: '%s' not under '%s': '%s'",
+                          suffix, conf->fs_parent_path->base,
+                          serr->message ? serr->message : "(no more info)");
+                  return NULL;
+                }
+              else
+                {
+                  ap_log_rerror(
+                          APLOG_MARK, APLOG_ERR, 0, r,
+                          "mod_dav_svn: SVNParentPath: '%s' not under '%s'",
+                          suffix, conf->fs_parent_path->base);
+                  return NULL;
+                }
+            }
+          else
+            {
+              ap_log_rerror(
+                      APLOG_MARK, APLOG_ERR, 0, r, "mod_dav_svn: SVNParentPath: can't "
+                      "evaluate expression: %s", err);
+              return NULL;
+            }
+
+        }
+#endif
+
+      return conf->fs_parent_path->base;
+    }
+  else
+    {
+      return NULL;
+    }
 }
 
 
@@ -1205,12 +1362,18 @@
 
   if (conf->fs_parent_path)
     {
-      fs_path = svn_dirent_join(conf->fs_parent_path, repos_basename,
-                                r->pool);
+      fs_path = dav_svn__get_fs_parent_path(r);
+      if (!fs_path)
+          return HTTP_INTERNAL_SERVER_ERROR;
+
+      fs_path = svn_dirent_join(fs_path, repos_basename,
+              r->pool);
     }
   else
     {
-      fs_path = conf->fs_path;
+      fs_path = dav_svn__get_fs_path(r);
+      if (!fs_path)
+          return HTTP_INTERNAL_SERVER_ERROR;
     }
 
   /* Avoid a trailing slash on the bogus path when repos_path is just "/" */
@@ -1254,7 +1417,7 @@
 static const command_rec cmds[] =
 {
   /* per directory/location */
-  AP_INIT_TAKE1("SVNPath", SVNPath_cmd, NULL, ACCESS_CONF,
+  AP_INIT_TAKE12("SVNPath", SVNPath_cmd, NULL, ACCESS_CONF,
                 "specifies the location in the filesystem for a Subversion "
                 "repository's files."),
 
@@ -1273,7 +1436,7 @@
                 "directory indexes"),
 
   /* per directory/location */
-  AP_INIT_TAKE1("SVNParentPath", SVNParentPath_cmd, NULL, ACCESS_CONF,
+  AP_INIT_TAKE12("SVNParentPath", SVNParentPath_cmd, NULL, ACCESS_CONF,
                 "specifies the location in the filesystem whose "
                 "subdirectories are assumed to be Subversion repositories."),
 
