Index: subversion/mod_dav_svn/dav_svn.h
===================================================================
--- subversion/mod_dav_svn/dav_svn.h	(revision 1465320)
+++ subversion/mod_dav_svn/dav_svn.h	(working copy)
@@ -289,6 +289,9 @@
 
   /* Cache any revprop change error */
   svn_error_t *revprop_error;
+
+  /* was keywords subsitution requested by client? (ie: /path/to/item?kw=1)*/
+  svn_boolean_t keyword_subst;
 };
 
 
Index: subversion/mod_dav_svn/repos.c
===================================================================
--- subversion/mod_dav_svn/repos.c	(revision 1465320)
+++ subversion/mod_dav_svn/repos.c	(working copy)
@@ -49,6 +49,7 @@
 #include "svn_version.h"
 #include "svn_props.h"
 #include "svn_ctype.h"
+#include "svn_subst.h"
 #include "mod_dav_svn.h"
 #include "svn_ra.h"  /* for SVN_RA_CAPABILITY_* */
 #include "svn_dirent_uri.h"
@@ -1821,6 +1822,7 @@
   apr_table_t *pairs = querystring_to_table(query, pool);
   const char *prevstr = apr_table_get(pairs, "p");
   const char *wrevstr;
+  const char *keyword_subst;
 
   if (prevstr)
     {
@@ -1924,6 +1926,10 @@
                                 0, "redirecting to canonical location");
     }
 
+  keyword_subst = apr_table_get(pairs, "kw");
+  if (keyword_subst && *keyword_subst != '0')
+    comb->priv.keyword_subst = TRUE;
+
   return NULL;
 }
 
@@ -3026,18 +3032,23 @@
 
 
       /* if we aren't sending a diff, then we know the length of the file,
-         so set up the Content-Length header */
-      serr = svn_fs_file_length(&length,
-                                resource->info->root.root,
-                                resource->info->repos_path,
-                                resource->pool);
-      if (serr != NULL)
+         so set up the Content-Length header.
+         Except when keywords substitution was requested (length may increase
+         during deliver) */
+      if (resource->info->keyword_subst == FALSE)
         {
-          return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
-                                      "could not fetch the resource length",
-                                      resource->pool);
+          serr = svn_fs_file_length(&length,
+                                    resource->info->root.root,
+                                    resource->info->repos_path,
+                                    resource->pool);
+          if (serr != NULL)
+            {
+              return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+                                          "could not fetch the resource length",
+                                          resource->pool);
+            }
+          ap_set_content_length(r, (apr_off_t) length);
         }
-      ap_set_content_length(r, (apr_off_t) length);
     }
 
   /* set the discovered MIME type */
@@ -3563,6 +3574,60 @@
                                       resource->pool);
         }
 
+      /* Perform keywords substitution if requested by client */
+      if (resource->info->keyword_subst == TRUE)
+        {
+          const char *err_msg_props = "could not get revision properties"
+                                      " for keywords substitution";
+          svn_string_t *keywords;
+          serr = svn_fs_node_prop(&keywords,
+                                  resource->info->root.root,
+                                  resource->info->repos_path,
+                                  SVN_PROP_KEYWORDS,
+                                  resource->pool);
+          if (serr != NULL)
+            return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+                                        err_msg_props, resource->pool);
+
+          if (keywords)
+            {
+              apr_hash_t *kw;
+              svn_revnum_t cmt_rev;
+              char *str_cmt_rev, *str_uri;
+              const char *cmt_date, *cmt_author;
+              apr_time_t when = 0;
+
+              serr = svn_repos_get_committed_info(&cmt_rev, &cmt_date, &cmt_author,
+                                                  resource->info->root.root,
+                                                  resource->info->repos_path,
+                                                  resource->pool);
+              if (serr != NULL)
+                return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+                                            err_msg_props, resource->pool);
+
+              str_cmt_rev = apr_psprintf(resource->pool,
+                                         "%ld", cmt_rev);
+              str_uri = apr_psprintf(resource->pool,
+                                     "%s%s", resource->info->repos->base_url,
+                                     resource->info->r->uri);
+              serr = svn_time_from_cstring(&when, cmt_date, resource->pool);
+              if (serr != NULL)
+                return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+                                            err_msg_props, resource->pool);
+
+              serr = svn_subst_build_keywords2(&kw, keywords->data,
+                                               str_cmt_rev, str_uri, when, cmt_author,
+                                               resource->pool);
+              if (serr != NULL)
+                return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
+                                            "could not perform keywords substitution",
+                                            resource->pool);
+
+              stream = svn_subst_stream_translated(svn_stream_disown(stream, resource->pool),
+                                                    NULL, FALSE, kw, TRUE, resource->pool);
+            }
+        }
+
       /* ### one day in the future, we can create a custom bucket type
          ### which will read from the FS stream on demand */
 
