You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/09/15 21:32:38 UTC

svn commit: r997472 [31/41] - in /subversion/branches/py-tests-as-modules: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/server-side/ notes/ notes/tree-conflicts/ notes/wc-ng/ subversion/bindings/javahl/native/ subversi...

Modified: subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/dav_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/dav_svn.h?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/dav_svn.h Wed Sep 15 19:32:26 2010
@@ -37,6 +37,7 @@
 #include "svn_path.h"
 #include "svn_xml.h"
 #include "private/svn_dav_protocol.h"
+#include "private/svn_skel.h"
 #include "mod_authz_svn.h"
 
 #ifdef __cplusplus
@@ -419,7 +420,7 @@ dav_svn__store_activity(const dav_svn_re
                         const char *txn_name);
 
 
-/* HTTP protocol v2:  client does POST against 'me' resource. */
+/* POST request handler.  (Used by HTTP protocol v2 clients only.)  */
 int dav_svn__method_post(request_rec *r);
 
 
@@ -640,6 +641,23 @@ dav_svn__get_deleted_rev_report(const da
                                 const apr_xml_doc *doc,
                                 ap_filter_t *output);
 
+
+/*** posts/ ***/
+
+/* The list of Subversion's custom POSTs. */
+/* ### should move these report names to a public header to share with
+   ### the client (and third parties). */
+static const char * dav_svn__posts_list[] = {
+  "create-txn",
+  NULL
+};
+
+/* The various POST handlers, defined in posts/, and used by repos.c.  */
+dav_error *
+dav_svn__post_create_txn(const dav_resource *resource,
+                         svn_skel_t *request_skel,
+                         ap_filter_t *output);
+
 /*** authz.c ***/
 
 /* A baton needed by dav_svn__authz_read_func(). */
@@ -654,17 +672,32 @@ typedef struct
 } dav_svn__authz_read_baton;
 
 
-/* Convert incoming RESOURCE and revision REV into a version-resource URI and
-   perform a GET subrequest on it.  This will invoke any authz modules loaded
-   into apache. Return TRUE if the subrequest succeeds, FALSE otherwise.
+/* Return TRUE iff the current user (as determined by Apache's
+   authentication system) has permission to read PATH in REPOS at REV
+   (where an invalid REV means "HEAD").  This will invoke any authz
+   modules loaded into Apache unless this Subversion location has been
+   configured to bypass those in favor of a direct lookup in the
+   Subversion authz subsystem.  Use POOL for any temporary allocation.
+*/
+svn_boolean_t
+dav_svn__allow_read(request_rec *r,
+                    const dav_svn_repos *repos,
+                    const char *path,
+                    svn_revnum_t rev,
+                    apr_pool_t *pool);
 
-   If REV is SVN_INVALID_REVNUM, then we look at HEAD.
-   Use POOL for any temporary allocation.
+/* Return TRUE iff the current user (as determined by Apache's
+   authentication system) has permission to read RESOURCE in REV
+   (where an invalid REV means "HEAD").  This will invoke any authz
+   modules loaded into Apache unless this Subversion location has been
+   configured to bypass those in favor of a direct lookup in the
+   Subversion authz subsystem.  Use POOL for any temporary allocation.
 */
 svn_boolean_t
-dav_svn__allow_read(const dav_resource *resource,
-                   svn_revnum_t rev,
-                   apr_pool_t *pool);
+dav_svn__allow_read_resource(const dav_resource *resource,
+                             svn_revnum_t rev,
+                             apr_pool_t *pool);
+
 
 /* If authz is enabled in the specified BATON, return a read authorization
    function. Otherwise, return NULL. */
@@ -890,6 +923,13 @@ dav_svn__final_flush_or_error(request_re
  */
 int dav_svn__error_response_tag(request_rec *r, dav_error *err);
 
+
+/* Set *SKEL to a parsed skel read from the body of request R, and
+ * allocated in POOL.
+ */
+int dav_svn__parse_request_skel(svn_skel_t **skel, request_rec *r,
+                                apr_pool_t *pool);
+
 /*** mirror.c ***/
 
 /* Perform the fixup hook for the R request.  */

Modified: subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/deadprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/deadprops.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/deadprops.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/deadprops.c Wed Sep 15 19:32:26 2010
@@ -389,7 +389,7 @@ db_output_value(dav_db *db,
           const svn_string_t *enc_propval
             = svn_base64_encode_string2(propval, TRUE, pool);
           xml_safe = enc_propval->data;
-          encoding = apr_pstrcat(pool, " V:encoding=\"base64\"", NULL);
+          encoding = " V:encoding=\"base64\"";
         }
       else
         {
@@ -424,23 +424,15 @@ db_map_namespaces(dav_db *db,
 
 
 static dav_error *
-db_store(dav_db *db,
-         const dav_prop_name *name,
-         const apr_xml_elem *elem,
-         dav_namespace_map *mapping)
+decode_property_value(const svn_string_t **out_propval_p,
+                      const svn_string_t *maybe_encoded_propval,
+                      const apr_xml_elem *elem,
+                      apr_pool_t *pool)
 {
-  const svn_string_t *propval;
-  apr_pool_t *pool = db->p;
   apr_xml_attr *attr = elem->attr;
 
-  /* SVN sends property values as a big blob of bytes. Thus, there should be
-     no child elements of the property-name element. That also means that
-     the entire contents of the blob is located in elem->first_cdata. The
-     dav_xml_get_cdata() will figure it all out for us, but (normally) it
-     should be awfully fast and not need to copy any data. */
-
-  propval = svn_string_create
-    (dav_xml_get_cdata(elem, pool, 0 /* strip_white */), pool);
+  /* Default: no "encoding" attribute. */
+  *out_propval_p = maybe_encoded_propval;
 
   /* Check for special encodings of the property value. */
   while (attr)
@@ -451,7 +443,7 @@ db_store(dav_db *db,
 
           /* Handle known encodings here. */
           if (enc_type && (strcmp(enc_type, "base64") == 0))
-            propval = svn_base64_decode_string(propval, pool);
+            *out_propval_p = svn_base64_decode_string(maybe_encoded_propval, pool);
           else
             return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0,
                                  "Unknown property encoding");
@@ -461,6 +453,32 @@ db_store(dav_db *db,
       attr = attr->next;
     }
 
+  return NULL;
+}
+
+static dav_error *
+db_store(dav_db *db,
+         const dav_prop_name *name,
+         const apr_xml_elem *elem,
+         dav_namespace_map *mapping)
+{
+  const svn_string_t *propval;
+  apr_pool_t *pool = db->p;
+  dav_error *derr;
+
+  /* SVN sends property values as a big blob of bytes. Thus, there should be
+     no child elements of the property-name element. That also means that
+     the entire contents of the blob is located in elem->first_cdata. The
+     dav_xml_get_cdata() will figure it all out for us, but (normally) it
+     should be awfully fast and not need to copy any data. */
+
+  propval = svn_string_create
+    (dav_xml_get_cdata(elem, pool, 0 /* strip_white */), pool);
+
+  derr = decode_property_value(&propval, propval, elem, pool);
+  if (derr)
+    return derr;
+
   return save_value(db, name, propval);
 }
 

Modified: subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/liveprops.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/liveprops.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/liveprops.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/liveprops.c Wed Sep 15 19:32:26 2010
@@ -144,7 +144,7 @@ get_path_revprop(svn_string_t **propval,
 {
   *propval = NULL;
 
-  if (! dav_svn__allow_read(resource, committed_rev, pool))
+  if (! dav_svn__allow_read_resource(resource, committed_rev, pool))
     return SVN_NO_ERROR;
 
   /* Get the property of the created revision. The authz is already

Modified: subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/lock.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/lock.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/lock.c Wed Sep 15 19:32:26 2010
@@ -458,7 +458,8 @@ get_locks(dav_lockdb *lockdb,
 
   /* If the resource's fs path is unreadable, we don't want to say
      anything about locks attached to it.*/
-  if (! dav_svn__allow_read(resource, SVN_INVALID_REVNUM, resource->pool))
+  if (! dav_svn__allow_read_resource(resource, SVN_INVALID_REVNUM,
+                                     resource->pool))
     return dav_new_error(resource->pool, HTTP_FORBIDDEN,
                          DAV_ERR_LOCK_SAVE_LOCK,
                          "Path is not accessible.");
@@ -518,7 +519,8 @@ find_lock(dav_lockdb *lockdb,
 
   /* If the resource's fs path is unreadable, we don't want to say
      anything about locks attached to it.*/
-  if (! dav_svn__allow_read(resource, SVN_INVALID_REVNUM, resource->pool))
+  if (! dav_svn__allow_read_resource(resource, SVN_INVALID_REVNUM,
+                                     resource->pool))
     return dav_new_error(resource->pool, HTTP_FORBIDDEN,
                          DAV_ERR_LOCK_SAVE_LOCK,
                          "Path is not accessible.");
@@ -596,7 +598,8 @@ has_locks(dav_lockdb *lockdb, const dav_
 
   /* If the resource's fs path is unreadable, we don't want to say
      anything about locks attached to it.*/
-  if (! dav_svn__allow_read(resource, SVN_INVALID_REVNUM, resource->pool))
+  if (! dav_svn__allow_read_resource(resource, SVN_INVALID_REVNUM,
+                                     resource->pool))
     return dav_new_error(resource->pool, HTTP_FORBIDDEN,
                          DAV_ERR_LOCK_SAVE_LOCK,
                          "Path is not accessible.");
@@ -639,7 +642,8 @@ append_locks(dav_lockdb *lockdb,
 
   /* If the resource's fs path is unreadable, we don't allow a lock to
      be created on it. */
-  if (! dav_svn__allow_read(resource, SVN_INVALID_REVNUM, resource->pool))
+  if (! dav_svn__allow_read_resource(resource, SVN_INVALID_REVNUM,
+                                     resource->pool))
     return dav_new_error(resource->pool, HTTP_FORBIDDEN,
                          DAV_ERR_LOCK_SAVE_LOCK,
                          "Path is not accessible.");
@@ -806,7 +810,8 @@ remove_lock(dav_lockdb *lockdb,
 
   /* If the resource's fs path is unreadable, we don't allow a lock to
      be removed from it. */
-  if (! dav_svn__allow_read(resource, SVN_INVALID_REVNUM, resource->pool))
+  if (! dav_svn__allow_read_resource(resource, SVN_INVALID_REVNUM,
+                                     resource->pool))
     return dav_new_error(resource->pool, HTTP_FORBIDDEN,
                          DAV_ERR_LOCK_SAVE_LOCK,
                          "Path is not accessible.");
@@ -891,7 +896,8 @@ refresh_locks(dav_lockdb *lockdb,
 
   /* If the resource's fs path is unreadable, we don't want to say
      anything about locks attached to it.*/
-  if (! dav_svn__allow_read(resource, SVN_INVALID_REVNUM, resource->pool))
+  if (! dav_svn__allow_read_resource(resource, SVN_INVALID_REVNUM,
+                                     resource->pool))
     return dav_new_error(resource->pool, HTTP_FORBIDDEN,
                          DAV_ERR_LOCK_SAVE_LOCK,
                          "Path is not accessible.");

Propchange: subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/posts/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Wed Sep 15 19:32:26 2010
@@ -0,0 +1 @@
+.libs

Modified: subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/reports/get-locks.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/reports/get-locks.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/reports/get-locks.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/reports/get-locks.c Wed Sep 15 19:32:26 2010
@@ -186,6 +186,8 @@ dav_svn__get_locks_report(const dav_reso
   apr_status_t apr_err;
   apr_hash_t *locks;
   dav_svn__authz_read_baton arb;
+  svn_depth_t depth = svn_depth_unknown;
+  apr_xml_attr *this_attr;
 
   /* The request URI should be a public one representing an fs path. */
   if ((! resource->info->repos_path)
@@ -197,12 +199,33 @@ dav_svn__get_locks_report(const dav_reso
   arb.r = resource->info->r;
   arb.repos = resource->info->repos;
 
+  /* See if the client provided additional information for this request. */
+  for (this_attr = doc->root->attr; this_attr; this_attr = this_attr->next)
+    {
+      if (strcmp(this_attr->name, "depth") == 0)
+        {
+          depth = svn_depth_from_word(this_attr->value);
+          if ((depth != svn_depth_empty) &&
+              (depth != svn_depth_files) &&
+              (depth != svn_depth_immediates) &&
+              (depth != svn_depth_infinity))
+            return dav_new_error(resource->pool, HTTP_BAD_REQUEST, 0,
+                                 "Invalid 'depth' specified in "
+                                 "get-locks-report request.");
+          continue;
+        }
+    }
+
+  /* For compatibility, our default depth is infinity. */
+  if (depth == svn_depth_unknown)
+    depth = svn_depth_infinity;
+
   /* Fetch the locks, but allow authz_read checks to happen on each. */
-  if ((err = svn_repos_fs_get_locks(&locks,
-                                    resource->info->repos->repos,
-                                    resource->info->repos_path,
-                                    dav_svn__authz_read_func(&arb), &arb,
-                                    resource->pool)) != SVN_NO_ERROR)
+  if ((err = svn_repos_fs_get_locks2(&locks,
+                                     resource->info->repos->repos,
+                                     resource->info->repos_path, depth,
+                                     dav_svn__authz_read_func(&arb), &arb,
+                                     resource->pool)) != SVN_NO_ERROR)
     return dav_svn__convert_err(err, HTTP_INTERNAL_SERVER_ERROR,
                                 err->message, resource->pool);
 

Modified: subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/reports/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/reports/log.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/reports/log.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/reports/log.c Wed Sep 15 19:32:26 2010
@@ -311,7 +311,17 @@ dav_svn__log_report(const dav_resource *
       else if (strcmp(child->name, "end-revision") == 0)
         end = SVN_STR_TO_REV(dav_xml_get_cdata(child, resource->pool, 1));
       else if (strcmp(child->name, "limit") == 0)
-        limit = atoi(dav_xml_get_cdata(child, resource->pool, 1));
+        {
+          serr = svn_cstring_atoi(&limit,
+                                  dav_xml_get_cdata(child, resource->pool, 1));
+          if (serr)
+            {
+              derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST,
+                                          "Malformed CDATA in element "
+                                          "\"limit\"", resource->pool);
+              goto cleanup;
+            }
+        }
       else if (strcmp(child->name, "discover-changed-paths") == 0)
         discover_changed_paths = TRUE; /* presence indicates positivity */
       else if (strcmp(child->name, "strict-node-history") == 0)

Modified: subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/reports/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/reports/replay.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/reports/replay.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/reports/replay.c Wed Sep 15 19:32:26 2010
@@ -466,10 +466,18 @@ dav_svn__replay_report(const dav_resourc
             }
           else if (strcmp(child->name, "send-deltas") == 0)
             {
+              apr_int64_t parsed_val;
+
               cdata = dav_xml_get_cdata(child, resource->pool, 1);
               if (! cdata)
                 return malformed_element_error("send-deltas", resource->pool);
-              send_deltas = atoi(cdata);
+              err = svn_cstring_strtoi64(&parsed_val, cdata, 0, 1, 10);
+              if (err)
+                {
+                  svn_error_clear(err);
+                  return malformed_element_error("send-deltas", resource->pool);
+                }
+              send_deltas = parsed_val ? TRUE : FALSE;
             }
         }
     }

Modified: subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/reports/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/reports/update.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/reports/update.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/reports/update.c Wed Sep 15 19:32:26 2010
@@ -782,6 +782,8 @@ struct window_handler_baton
   svn_boolean_t seen_first_window;  /* False until first window seen. */
   update_ctx_t *uc;
 
+  const char *base_checksum; /* For transfer as part of the S:txdelta element */
+
   /* The _real_ window handler and baton. */
   svn_txdelta_window_handler_t handler;
   void *handler_baton;
@@ -797,7 +799,14 @@ window_handler(svn_txdelta_window_t *win
   if (! wb->seen_first_window)
     {
       wb->seen_first_window = TRUE;
-      SVN_ERR(dav_svn__brigade_puts(wb->uc->bb, wb->uc->output, "<S:txdelta>"));
+
+      if (!wb->base_checksum)
+        SVN_ERR(dav_svn__brigade_puts(wb->uc->bb, wb->uc->output,
+                                      "<S:txdelta>"));
+      else
+        SVN_ERR(dav_svn__brigade_printf(wb->uc->bb, wb->uc->output,
+                                        "<S:txdelta base-checksum=\"%s\">",
+                                        wb->base_checksum));
     }
 
   SVN_ERR(wb->handler(window, wb->handler_baton));
@@ -850,6 +859,7 @@ upd_apply_textdelta(void *file_baton,
   wb = apr_palloc(file->pool, sizeof(*wb));
   wb->seen_first_window = FALSE;
   wb->uc = file->uc;
+  wb->base_checksum = file->base_checksum;
   base64_stream = dav_svn__make_base64_output_stream(wb->uc->bb,
                                                      wb->uc->output,
                                                      file->pool);

Modified: subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/repos.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/repos.c Wed Sep 15 19:32:26 2010
@@ -44,6 +44,7 @@
 #include "svn_sorts.h"
 #include "svn_version.h"
 #include "svn_props.h"
+#include "svn_ctype.h"
 #include "mod_dav_svn.h"
 #include "svn_ra.h"  /* for SVN_RA_CAPABILITY_* */
 #include "svn_dirent_uri.h"
@@ -1519,7 +1520,7 @@ static const char *get_entry(apr_pool_t 
 
         /* Look for 'var = value' --- and make sure the var is in lcase. */
 
-        for (cp = parm; (*cp && !apr_isspace(*cp) && *cp != '='); ++cp)
+        for (cp = parm; (*cp && !svn_ctype_isspace(*cp) && *cp != '='); ++cp)
           {
             *cp = apr_tolower(*cp);
           }
@@ -1530,7 +1531,7 @@ static const char *get_entry(apr_pool_t 
           }
 
         *cp++ = '\0';           /* Delimit var */
-        while (*cp && (apr_isspace(*cp) || *cp == '='))
+        while (*cp && (svn_ctype_isspace(*cp) || *cp == '='))
           {
             ++cp;
           }
@@ -1544,7 +1545,7 @@ static const char *get_entry(apr_pool_t 
           }
         else
           {
-            for (end = cp; (*end && !apr_isspace(*end)); end++);
+            for (end = cp; (*end && !svn_ctype_isspace(*end)); end++);
           }
         if (*end)
           {
@@ -2293,19 +2294,17 @@ static const char *
 get_parent_path(const char *path, apr_pool_t *pool)
 {
   apr_size_t len;
-  const char *parentpath, *base_name;
   char *tmp = apr_pstrdup(pool, path);
 
   len = strlen(tmp);
 
   if (len > 0)
     {
-      /* Remove any trailing slash; else svn_uri_split() asserts. */
+      /* Remove any trailing slash; else svn_uri_dirname() asserts. */
       if (tmp[len-1] == '/')
         tmp[len-1] = '\0';
-      svn_uri_split(tmp, &parentpath, &base_name, pool);
 
-      return parentpath;
+      return svn_uri_dirname(tmp, pool);
     }
 
   return path;
@@ -3121,6 +3120,7 @@ deliver(const dav_resource *resource, ap
       apr_hash_t *entries;
       apr_pool_t *entry_pool;
       apr_array_header_t *sorted;
+      svn_revnum_t dir_rev = SVN_INVALID_REVNUM;
       int i;
 
       /* XML schema for the directory index if xslt_uri is set:
@@ -3165,7 +3165,8 @@ deliver(const dav_resource *resource, ap
           const char *fs_parent_path =
             dav_svn__get_fs_parent_path(resource->info->r);
 
-          serr = svn_io_get_dirents2(&dirents, fs_parent_path, resource->pool);
+          serr = svn_io_get_dirents3(&dirents, fs_parent_path, TRUE,
+                                     resource->pool, resource->pool);
           if (serr != NULL)
             return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                         "couldn't fetch dirents of SVNParentPath",
@@ -3197,6 +3198,7 @@ deliver(const dav_resource *resource, ap
         }
       else
         {
+          dir_rev = svn_fs_revision_root_revision(resource->info->root.root);
           serr = svn_fs_dir_entries(&entries, resource->info->root.root,
                                     resource->info->repos_path, resource->pool);
           if (serr != NULL)
@@ -3305,9 +3307,31 @@ deliver(const dav_resource *resource, ap
           const char *name = item->key;
           const char *href = name;
           svn_boolean_t is_dir = (entry->kind == svn_node_dir);
+          const char *repos_relpath = NULL;
 
           svn_pool_clear(entry_pool);
 
+          /* DIR_REV is set to a valid revision if we're looking at
+             the entries of a versioned directory.  Otherwise, we're
+             looking at a parent-path listing. */
+          if (SVN_IS_VALID_REVNUM(dir_rev))
+            {
+              repos_relpath = svn_path_join(resource->info->repos_path,
+                                            name, entry_pool);
+              if (! dav_svn__allow_read(resource->info->r,
+                                        resource->info->repos,
+                                        repos_relpath,
+                                        dir_rev,
+                                        entry_pool))
+                continue;
+            }
+          else
+            {
+              /* ### TODO:  We could test for readability of the root
+                     directory of each repository and hide those that
+                     the user can't see. */
+            }
+
           /* append a trailing slash onto the name for directories. we NEED
              this for the href portion so that the relative reference will
              descend properly. for the visible portion, it is just nice. */
@@ -3391,7 +3415,8 @@ deliver(const dav_resource *resource, ap
               */
               ap_fputs(output, bb,
                        " </ul>\n <hr noshade><em>Powered by "
-                       "<a href=\"http://subversion.apache.org/\">Subversion"
+                       "<a href=\"http://subversion.apache.org/\">"
+                       "Apache Subversion"
                        "</a> version " SVN_VERSION "."
                        "</em>\n</body></html>");
             }
@@ -3932,6 +3957,7 @@ do_walk(walker_ctx_t *ctx, int depth)
   apr_size_t uri_len;
   apr_size_t repos_len;
   apr_hash_t *children;
+  apr_pool_t *iterpool;
 
   /* Clear the temporary pool. */
   svn_pool_clear(ctx->info.pool);
@@ -4007,6 +4033,7 @@ do_walk(walker_ctx_t *ctx, int depth)
                                 params->pool);
 
   /* iterate over the children in this collection */
+  iterpool = svn_pool_create(params->pool);
   for (hi = apr_hash_first(params->pool, children); hi; hi = apr_hash_next(hi))
     {
       const void *key;
@@ -4014,6 +4041,8 @@ do_walk(walker_ctx_t *ctx, int depth)
       void *val;
       svn_fs_dirent_t *dirent;
 
+      svn_pool_clear(iterpool);
+
       /* fetch one of the children */
       apr_hash_this(hi, &key, &klen, &val);
       dirent = val;
@@ -4021,7 +4050,16 @@ do_walk(walker_ctx_t *ctx, int depth)
       /* authorize access to this resource, if applicable */
       if (params->walk_type & DAV_WALKTYPE_AUTH)
         {
-          /* ### how/what to do? */
+          const char *repos_relpath =
+            apr_pstrcat(iterpool, 
+                        apr_pstrmemdup(iterpool,
+                                       ctx->repos_path->data,
+                                       ctx->repos_path->len),
+                        key, NULL);
+          if (! dav_svn__allow_read(ctx->info.r, ctx->info.repos,
+                                    repos_relpath, ctx->info.root.rev,
+                                    iterpool))
+            continue;
         }
 
       /* append this child to our buffers */
@@ -4062,6 +4100,9 @@ do_walk(walker_ctx_t *ctx, int depth)
       ctx->uri->len = uri_len;
       ctx->repos_path->len = repos_len;
     }
+  
+  svn_pool_destroy(iterpool);
+
   return NULL;
 }
 
@@ -4263,58 +4304,73 @@ dav_svn__create_version_resource(dav_res
 }
 
 
-/* POST handler for HTTP protocol v2.
- 
-   Currently we allow POSTs only against the "me resource", which may
-   in the future act as a dispatcher of sorts for handling potentially
-   many different kinds of operations as specified by the body of the
-   POST request itself.
-
-   ### TODO: Define what the format of those POST bodies might be.  If
-   ### XML, we have access to Apache's streamy XML parsing code, but
-   ### ... it's XML.  Meh.  If skels, we get skels!  But we need to
-   ### write our own streamy skel parsing routine around a brigade
-   ### read loop.  Ewww...
-   ###
-   ### Today we only support transaction creation requests, but we
-   ### could conceivable support the likes of a multi-path lock
-   ### and/or unlock request, or some other thing for which stock
-   ### WebDAV doesn't work or doesn't work well enough.
-   ###
-   ### Fortunately, today we don't use the POST body at all, and we'll
-   ### be able to get away with not defining the body format in the
-   ### future thanks to the following:
-
-   As a special consideration, an empty POST body is interpreted as a
-   simple request to create a new commit transaction based on the HEAD
-   revision.  The new transaction name will be returned via a custom
-   response header SVN_DAV_TXN_NAME_HEADER.
-*/
+
+static dav_error *
+handle_post_request(request_rec *r,
+                    dav_resource *resource,
+                    ap_filter_t *output)
+{
+  svn_skel_t *request_skel;
+  int status;
+  apr_pool_t *pool = resource->pool;
+
+  /* Make sure our skel-based request parses okay, has an initial atom
+     that identifies what kind of action is expected, and that that
+     action is something we understand.  */
+  status = dav_svn__parse_request_skel(&request_skel, r, pool);
+
+  if (status != OK)
+    return dav_new_error(pool, status, 0,
+                         "Error parsing skel POST request body.");
+
+  if (svn_skel__list_length(request_skel) < 1)
+    return dav_new_error(pool, HTTP_BAD_REQUEST, 0,
+                         "Unable to identify skel POST request flavor.");
+
+  if (svn_skel__matches_atom(request_skel->children, "create-txn"))
+    {
+      return dav_svn__post_create_txn(resource, request_skel, output);
+    }
+  else
+    {
+      return dav_new_error(pool, HTTP_BAD_REQUEST, 0,
+                           "Unsupported skel POST request flavor.");
+    }
+  /* NOTREACHED */
+}
+
 int dav_svn__method_post(request_rec *r)
 {
   dav_resource *resource;
   dav_error *derr;
-  const char *txn_name;
+  const char *content_type;
 
+  /* We only allow POSTs against the "me resource" right now. */
   derr = get_resource(r, dav_svn__get_root_dir(r),
                       "ignored", 0, &resource);
   if (derr != NULL)
     return derr->status;
-
   if (resource->info->restype != DAV_SVN_RESTYPE_ME)
     return HTTP_BAD_REQUEST;
 
-  /* Create a Subversion repository transaction based on HEAD. */
-  derr = dav_svn__create_txn(resource->info->repos, &txn_name, resource->pool);
+  /* Pass skel-type POST request handling off to a dispatcher; any
+     other type of request is considered bogus. */
+  content_type = apr_table_get(r->headers_in, "content-type");
+  if (content_type && (strcmp(content_type, SVN_SKEL_MIME_TYPE) == 0))
+    {
+      derr = handle_post_request(r, resource, r->output_filters);
+    }
+  else
+    {
+      derr = dav_new_error(resource->pool, HTTP_BAD_REQUEST, 0,
+                           "Unsupported POST request type.");
+    }
+
+  /* If something went wrong above, we'll generate a response back to
+     the client with (hopefully) some helpful information. */
   if (derr)
     return dav_svn__error_response_tag(r, derr);
-
-  /* Build a "201 Created" response with header that tells the client
-     our new transaction's name. */
-  apr_table_set(resource->info->r->headers_out, SVN_DAV_TXN_NAME_HEADER,
-                txn_name);
-  r->status = HTTP_CREATED;
-
+    
   return OK;
 }
 

Modified: subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/util.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/util.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/util.c Wed Sep 15 19:32:26 2010
@@ -28,6 +28,7 @@
 
 #include <mod_dav.h>
 #include <http_protocol.h>
+#include <http_core.h>
 
 #include "svn_error.h"
 #include "svn_fs.h"
@@ -611,3 +612,140 @@ dav_svn__error_response_tag(request_rec 
    */
   return DONE;
 }
+
+
+/* Set *REQUEST_STR to a string containing the contents of the body of
+   request R, allocated from POOL.
+
+   NOTE: This was shamelessly stolen and modified from Apache's
+   ap_xml_parse_input().  */
+static int
+request_body_to_string(svn_string_t **request_str,
+                       request_rec *r,
+                       apr_pool_t *pool)
+{
+  apr_bucket_brigade *brigade;
+  int seen_eos;
+  apr_status_t status;
+  apr_off_t total_read = 0;
+  apr_off_t limit_req_body = ap_get_limit_req_body(r);
+  int result = HTTP_BAD_REQUEST;
+  const char *content_length_str;
+  char *endp;
+  apr_off_t content_length;
+  svn_stringbuf_t *buf;
+
+  *request_str = NULL;
+
+  content_length_str = apr_table_get(r->headers_in, "Content-Length");
+  if (content_length_str)
+    {
+      if (apr_strtoff(&content_length, content_length_str, &endp, 10)
+          || endp == content_length_str || *endp || content_length < 0)
+        {
+          ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Invalid Content-Length");
+          return HTTP_REQUEST_ENTITY_TOO_LARGE;
+        }
+    }
+  else
+    content_length = 0;
+
+  if (limit_req_body && (limit_req_body < content_length))
+    {
+      ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                    "Requested content-length of %" APR_OFF_T_FMT " is larger "
+                    "than the configured limit of %" APR_OFF_T_FMT,
+                    content_length, limit_req_body);
+      return HTTP_REQUEST_ENTITY_TOO_LARGE;
+    }
+
+  if (content_length)
+    {
+      buf = svn_stringbuf_create_ensure(content_length, pool);
+    }
+  else
+    {
+      buf = svn_stringbuf_create("", pool);
+    }
+
+  brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+  seen_eos = 0;
+  total_read = 0;
+
+  do
+    {
+      apr_bucket *bucket;
+
+      status = ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES,
+                              APR_BLOCK_READ, 2048);
+      if (status != APR_SUCCESS)
+        goto cleanup;
+
+      for (bucket = APR_BRIGADE_FIRST(brigade);
+           bucket != APR_BRIGADE_SENTINEL(brigade);
+           bucket = APR_BUCKET_NEXT(bucket))
+        {
+          const char *data;
+          apr_size_t len;
+          
+          if (APR_BUCKET_IS_EOS(bucket))
+            {
+              seen_eos = 1;
+              break;
+            }
+          
+          if (APR_BUCKET_IS_METADATA(bucket))
+            continue;
+          
+          status = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
+          if (status != APR_SUCCESS)
+            goto cleanup;
+          
+          total_read += len;
+          if (limit_req_body && total_read > limit_req_body)
+            {
+              ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                            "Request body is larger than the configured "
+                            "limit of %lu", (unsigned long)limit_req_body);
+              result = HTTP_REQUEST_ENTITY_TOO_LARGE;
+              goto cleanup;
+            }
+          
+          svn_stringbuf_appendbytes(buf, data, len);
+        }
+      
+      apr_brigade_cleanup(brigade);
+    }
+  while (!seen_eos);
+
+  apr_brigade_destroy(brigade);
+
+  /* Make an svn_string_t from our svn_stringbuf_t. */
+  *request_str = svn_string_create("", pool);
+  (*request_str)->data = buf->data;
+  (*request_str)->len = buf->len;
+  return OK;
+
+ cleanup:
+  apr_brigade_destroy(brigade);
+  
+  /* Apache will supply a default error, plus the error log above. */
+  return result;
+}
+
+int
+dav_svn__parse_request_skel(svn_skel_t **skel,
+                            request_rec *r,
+                            apr_pool_t *pool)
+{
+  svn_string_t *skel_str;
+  int status;
+
+  *skel = NULL;
+  status = request_body_to_string(&skel_str, r, pool);
+  if (status != OK)
+    return OK;
+
+  *skel = svn_skel__parse(skel_str->data, skel_str->len, pool);
+  return OK;
+}

Modified: subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/version.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/version.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/version.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/mod_dav_svn/version.c Wed Sep 15 19:32:26 2010
@@ -41,6 +41,7 @@
 #include "private/svn_log.h"
 
 #include "dav_svn.h"
+#include "mod_dav_svn.h"
 
 
 svn_error_t *
@@ -1014,6 +1015,22 @@ deliver_report(request_rec *r,
 
   if (doc->root->ns == ns)
     {
+      const char *cleaned_uri, *relative_path, *repos_path;
+      int trailing_slash;
+      /* During SVNPathAuthz short_circuit
+       * resource->info->repos->repo_name becomes NULL.*/
+      if (resource->info->repos->repo_name == NULL)
+        {
+          dav_error *err;
+          err = dav_svn_split_uri(r, r->uri, dav_svn__get_root_dir(r),
+                                  &cleaned_uri, &trailing_slash,
+                                  &(resource->info->repos->repo_name), 
+                                  &relative_path, &repos_path);
+          if (err)
+            {
+              return err;
+            }
+        }
       /* ### note that these report names should have symbols... */
 
       if (strcmp(doc->root->name, "update-report") == 0)