~ubuntu-branches/debian/sid/subversion/sid

« back to all changes in this revision

Viewing changes to subversion/mod_dav_svn/repos.c

  • Committer: Package Import Robot
  • Author(s): James McCoy, Peter Samuelson, James McCoy
  • Date: 2014-01-12 19:48:33 UTC
  • mfrom: (0.2.10)
  • Revision ID: package-import@ubuntu.com-20140112194833-w3axfwksn296jn5x
Tags: 1.8.5-1
[ Peter Samuelson ]
* New upstream release.  (Closes: #725787) Rediff patches:
  - Remove apr-abi1 (applied upstream), rename apr-abi2 to apr-abi
  - Remove loosen-sqlite-version-check (shouldn't be needed)
  - Remove java-osgi-metadata (applied upstream)
  - svnmucc prompts for a changelog if none is provided. (Closes: #507430)
  - Remove fix-bdb-version-detection, upstream uses "apu-config --dbm-libs"
  - Remove ruby-test-wc (applied upstream)
  - Fix “svn diff -r N file” when file has svn:mime-type set.
    (Closes: #734163)
  - Support specifying an encoding for mod_dav_svn's environment in which
    hooks are run.  (Closes: #601544)
  - Fix ordering of “svnadmin dump” paths with certain APR versions.
    (Closes: #687291)
  - Provide a better error message when authentication fails with an
    svn+ssh:// URL.  (Closes: #273874)
  - Updated Polish translations.  (Closes: #690815)

[ James McCoy ]
* Remove all traces of libneon, replaced by libserf.
* patches/sqlite_3.8.x_workaround: Upstream fix for wc-queries-test test
  failurse.
* Run configure with --with-apache-libexecdir, which allows removing part of
  patches/rpath.
* Re-enable auth-test as upstream has fixed the problem of picking up
  libraries from the environment rather than the build tree.
  (Closes: #654172)
* Point LD_LIBRARY_PATH at the built auth libraries when running the svn
  command during the build.  (Closes: #678224)
* Add a NEWS entry describing how to configure mod_dav_svn to understand
  UTF-8.  (Closes: #566148)
* Remove ancient transitional package, libsvn-ruby.
* Enable compatibility with Sqlite3 versions back to Wheezy.
* Enable hardening flags.  (Closes: #734918)
* patches/build-fixes: Enable verbose build logs.
* Build against the default ruby version.  (Closes: #722393)

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
#define CORE_PRIVATE      /* To make ap_show_mpm public in 2.2 */
38
38
#include <http_config.h>
39
39
 
 
40
#include "svn_hash.h"
40
41
#include "svn_types.h"
41
42
#include "svn_pools.h"
42
43
#include "svn_error.h"
48
49
#include "svn_version.h"
49
50
#include "svn_props.h"
50
51
#include "svn_ctype.h"
 
52
#include "svn_subst.h"
51
53
#include "mod_dav_svn.h"
52
54
#include "svn_ra.h"  /* for SVN_RA_CAPABILITY_* */
53
55
#include "svn_dirent_uri.h"
1502
1504
  repos->xslt_uri = dav_svn__get_xslt_uri(r);
1503
1505
  repos->autoversioning = dav_svn__get_autoversioning_flag(r);
1504
1506
  repos->bulk_updates = dav_svn__get_bulk_updates_flag(r);
1505
 
  repos->v2_protocol = dav_svn__get_v2_protocol_flag(r);
 
1507
  repos->v2_protocol = dav_svn__check_httpv2_support(r);
1506
1508
  repos->base_url = ap_construct_url(r->pool, "", r);
1507
1509
  repos->special_uri = dav_svn__get_special_uri(r);
1508
1510
  repos->username = r->user;
1576
1578
 
1577
1579
        for (cp = parm; (*cp && !svn_ctype_isspace(*cp) && *cp != '='); ++cp)
1578
1580
          {
1579
 
            *cp = apr_tolower(*cp);
 
1581
            *cp = (char)apr_tolower(*cp);
1580
1582
          }
1581
1583
 
1582
1584
        if (!*cp)
1820
1822
  apr_table_t *pairs = querystring_to_table(query, pool);
1821
1823
  const char *prevstr = apr_table_get(pairs, "p");
1822
1824
  const char *wrevstr;
 
1825
  const char *keyword_subst;
 
1826
 
 
1827
  /* Will we be doing keyword substitution? */
 
1828
  keyword_subst = apr_table_get(pairs, "kw");
 
1829
  if (keyword_subst && (strcmp(keyword_subst, "1") == 0))
 
1830
    comb->priv.keyword_subst = TRUE;
1823
1831
 
1824
1832
  if (prevstr)
1825
1833
    {
 
1834
      while (*prevstr == 'r')
 
1835
        prevstr++;
1826
1836
      peg_rev = SVN_STR_TO_REV(prevstr);
1827
1837
      if (!SVN_IS_VALID_REVNUM(peg_rev))
1828
1838
        return dav_svn__new_error(pool, HTTP_BAD_REQUEST, 0,
1840
1850
  wrevstr = apr_table_get(pairs, "r");
1841
1851
  if (wrevstr)
1842
1852
    {
 
1853
      while (*wrevstr == 'r')
 
1854
        wrevstr++;
1843
1855
      working_rev = SVN_STR_TO_REV(wrevstr);
1844
1856
      if (!SVN_IS_VALID_REVNUM(working_rev))
1845
1857
        return dav_svn__new_error(pool, HTTP_BAD_REQUEST, 0,
1875
1887
    }
1876
1888
  else
1877
1889
    {
1878
 
      const char *newpath;
 
1890
      const char *newpath, *location;
1879
1891
      apr_hash_t *locations;
1880
1892
      apr_array_header_t *loc_revs = apr_array_make(pool, 1,
1881
1893
                                                    sizeof(svn_revnum_t));
1904
1916
      /* Redirect folks to a canonical, peg-revision-only location.
1905
1917
         If they used a peg revision in this request, we can use a
1906
1918
         permanent redirect.  If they didn't (peg-rev is HEAD), we can
1907
 
         only use a temporary redirect. */
1908
 
      apr_table_setn(r->headers_out, "Location",
1909
 
                     ap_construct_url(r->pool,
1910
 
                                  apr_psprintf(r->pool, "%s%s?p=%ld",
 
1919
         only use a temporary redirect.  In either case, preserve the
 
1920
         "keyword_subst" state in the redirected location, too.  */
 
1921
      location = ap_construct_url(r->pool,
 
1922
                                  apr_psprintf(r->pool, "%s%s?p=%ld%s",
1911
1923
                                               (comb->priv.repos->root_path[1]
1912
1924
                                                ? comb->priv.repos->root_path
1913
1925
                                                : ""),
1914
 
                                               newpath, working_rev),
1915
 
                                      r));
 
1926
                                               newpath, working_rev,
 
1927
                                               keyword_subst ? "&kw=1" : ""),
 
1928
                                  r);
 
1929
      apr_table_setn(r->headers_out, "Location", location);
1916
1930
      return dav_svn__new_error(r->pool,
1917
1931
                                prevstr ? HTTP_MOVED_PERMANENTLY
1918
1932
                                        : HTTP_MOVED_TEMPORARILY,
1922
1936
  return NULL;
1923
1937
}
1924
1938
 
1925
 
 
1926
 
 
1927
1939
static dav_error *
1928
1940
get_resource(request_rec *r,
1929
1941
             const char *root_path,
2066
2078
  repos->bulk_updates = dav_svn__get_bulk_updates_flag(r);
2067
2079
 
2068
2080
  /* Are we advertising HTTP v2 protocol support? */
2069
 
  repos->v2_protocol = dav_svn__get_v2_protocol_flag(r);
 
2081
  repos->v2_protocol = dav_svn__check_httpv2_support(r);
2070
2082
 
2071
2083
  /* Path to activities database */
2072
2084
  repos->activities_db = dav_svn__get_activities_db(r);
2111
2123
           more than that). */
2112
2124
 
2113
2125
        /* Start out assuming no capabilities. */
2114
 
        apr_hash_set(repos->client_capabilities, SVN_RA_CAPABILITY_MERGEINFO,
2115
 
                     APR_HASH_KEY_STRING, capability_no);
 
2126
        svn_hash_sets(repos->client_capabilities,
 
2127
                      SVN_RA_CAPABILITY_MERGEINFO,
 
2128
                      capability_no);
2116
2129
 
2117
2130
        /* Then see what we can find. */
2118
2131
        val = apr_table_get(r->headers_in, "DAV");
2123
2136
 
2124
2137
            if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_MERGEINFO, vals))
2125
2138
              {
2126
 
                apr_hash_set(repos->client_capabilities,
2127
 
                             SVN_RA_CAPABILITY_MERGEINFO,
2128
 
                             APR_HASH_KEY_STRING, capability_yes);
 
2139
                svn_hash_sets(repos->client_capabilities,
 
2140
                              SVN_RA_CAPABILITY_MERGEINFO, capability_yes);
2129
2141
              }
2130
2142
          }
2131
2143
      }
2141
2153
 
2142
2154
      /* construct FS configuration parameters */
2143
2155
      fs_config = apr_hash_make(r->connection->pool);
2144
 
      apr_hash_set(fs_config,
2145
 
                   SVN_FS_CONFIG_FSFS_CACHE_DELTAS,
2146
 
                   APR_HASH_KEY_STRING,
2147
 
                   dav_svn__get_txdelta_cache_flag(r) ? "1" : "0");
2148
 
      apr_hash_set(fs_config,
2149
 
                   SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
2150
 
                   APR_HASH_KEY_STRING,
2151
 
                   dav_svn__get_fulltext_cache_flag(r) ? "1" : "0");
 
2156
      svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_DELTAS,
 
2157
                    dav_svn__get_txdelta_cache_flag(r) ? "1" :"0");
 
2158
      svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
 
2159
                    dav_svn__get_fulltext_cache_flag(r) ? "1" :"0");
 
2160
      svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
 
2161
                    dav_svn__get_revprop_cache_flag(r) ? "1" :"0");
2152
2162
 
2153
2163
      /* Disallow BDB/event until issue 4157 is fixed. */
2154
2164
      if (!strcmp(ap_show_mpm(), "event"))
2201
2211
                                         "in repos object",
2202
2212
                                         HTTP_INTERNAL_SERVER_ERROR, r);
2203
2213
        }
 
2214
 
 
2215
      /* Configure hook script environment variables. */
 
2216
      serr = svn_repos_hooks_setenv(repos->repos, dav_svn__get_hooks_env(r),
 
2217
                                    r->pool);
 
2218
      if (serr)
 
2219
        return dav_svn__sanitize_error(serr,
 
2220
                                       "Error settings hooks environment",
 
2221
                                       HTTP_INTERNAL_SERVER_ERROR, r);
2204
2222
    }
2205
2223
 
2206
2224
  /* cache the filesystem object */
2564
2582
}
2565
2583
 
2566
2584
 
2567
 
#if 0
2568
 
/* Given an apache request R and a ROOT_PATH to the svn location
2569
 
   block, set *KIND to the node-kind of the URI's associated
2570
 
   (revision, path) pair, if possible.
2571
 
 
2572
 
   Public uris, baseline collections, version resources, and working
2573
 
   (non-baseline) resources all have associated (revision, path)
2574
 
   pairs, and thus one of {svn_node_file, svn_node_dir, svn_node_none}
2575
 
   will be returned.
2576
 
 
2577
 
   If URI is something more abstract, then set *KIND to
2578
 
   svn_node_unknown.  This is true for baselines, working baselines,
2579
 
   version controled configurations, activities, histories, and other
2580
 
   private resources.
2581
 
*/
2582
 
static dav_error *
2583
 
resource_kind(request_rec *r,
2584
 
              const char *uri,
2585
 
              const char *root_path,
2586
 
              svn_node_kind_t *kind)
2587
 
{
2588
 
  dav_error *derr;
2589
 
  svn_error_t *serr;
2590
 
  dav_resource *resource;
2591
 
  svn_revnum_t base_rev;
2592
 
  svn_fs_root_t *base_rev_root;
2593
 
  char *saved_uri;
2594
 
 
2595
 
  /* Temporarily insert the uri that the user actually wants us to
2596
 
     convert into a resource.  Typically, this is already r->uri, so
2597
 
     this is usually a no-op.  But sometimes the caller may pass in
2598
 
     the Destination: header uri.
2599
 
 
2600
 
     ### WHAT WE REALLY WANT here is to refactor get_resource,
2601
 
     so that some alternate interface actually allows us to specify
2602
 
     the URI to process, i.e. not always process r->uri.
2603
 
  */
2604
 
  saved_uri = r->uri;
2605
 
  r->uri = apr_pstrdup(r->pool, uri);
2606
 
 
2607
 
  /* parse the uri and prep the associated resource. */
2608
 
  derr = get_resource(r, root_path,
2609
 
                      /* ### I can't believe that every single
2610
 
                         parser ignores the LABEL and USE_CHECKED_IN
2611
 
                         args below!! */
2612
 
                      "ignored_label", 1,
2613
 
                      &resource);
2614
 
  /* Restore r back to normal. */
2615
 
  r->uri = saved_uri;
2616
 
 
2617
 
  if (derr)
2618
 
    return derr;
2619
 
 
2620
 
  if (resource->type == DAV_RESOURCE_TYPE_REGULAR)
2621
 
    {
2622
 
      /* Either a public URI or a bc.  In both cases, prep_regular()
2623
 
         has already set the 'exists' and 'collection' flags by
2624
 
         querying the appropriate revision root and path.  */
2625
 
      if (! resource->exists)
2626
 
        *kind = svn_node_none;
2627
 
      else
2628
 
        *kind = resource->collection ? svn_node_dir : svn_node_file;
2629
 
    }
2630
 
 
2631
 
  else if (resource->type == DAV_RESOURCE_TYPE_VERSION)
2632
 
    {
2633
 
      if (resource->baselined)  /* bln */
2634
 
        *kind = svn_node_unknown;
2635
 
 
2636
 
      else /* ver */
2637
 
        {
2638
 
          derr = fs_check_path(kind, resource->info->root.root,
2639
 
                               resource->info->repos_path, r->pool);
2640
 
          if (derr != NULL)
2641
 
            return derr;
2642
 
        }
2643
 
    }
2644
 
 
2645
 
  else if (resource->type == DAV_RESOURCE_TYPE_WORKING)
2646
 
    {
2647
 
      if (resource->baselined) /* wbl */
2648
 
        *kind = svn_node_unknown;
2649
 
 
2650
 
      else /* wrk */
2651
 
        {
2652
 
          /* don't call fs_check_path on the txn, but on the original
2653
 
             revision that the txn is based on. */
2654
 
          base_rev = svn_fs_txn_base_revision(resource->info->root.txn);
2655
 
          serr = svn_fs_revision_root(&base_rev_root,
2656
 
                                      resource->info->repos->fs,
2657
 
                                      base_rev, r->pool);
2658
 
          if (serr)
2659
 
            return dav_svn__convert_err
2660
 
              (serr, HTTP_INTERNAL_SERVER_ERROR,
2661
 
               apr_psprintf(r->pool,
2662
 
                            "Could not open root of revision %ld",
2663
 
                            base_rev),
2664
 
               r->pool);
2665
 
 
2666
 
          derr = fs_check_path(kind, base_rev_root,
2667
 
                               resource->info->repos_path, r->pool);
2668
 
          if (derr != NULL)
2669
 
            return derr;
2670
 
        }
2671
 
    }
2672
 
 
2673
 
  else
2674
 
    /* act, his, vcc, or some other private resource */
2675
 
    *kind = svn_node_unknown;
2676
 
 
2677
 
  return NULL;
2678
 
}
2679
 
#endif
2680
 
 
2681
 
 
2682
2585
static dav_error *
2683
2586
open_stream(const dav_resource *resource,
2684
2587
            dav_stream_mode mode,
2698
2601
        }
2699
2602
    }
2700
2603
 
2701
 
#if 1
 
2604
  /* ### TODO:  Can we support range writes someday? */
2702
2605
  if (mode == DAV_MODE_WRITE_SEEKABLE)
2703
2606
    {
2704
2607
      return dav_svn__new_error(resource->pool, HTTP_NOT_IMPLEMENTED, 0,
2705
2608
                                "Resource body writes cannot use ranges "
2706
2609
                                "(at this time).");
2707
2610
    }
2708
 
#endif
2709
2611
 
2710
2612
  /* start building the stream structure */
2711
2613
  *stream = apr_pcalloc(resource->pool, sizeof(**stream));
3021
2923
  apr_table_setn(r->headers_out, "ETag",
3022
2924
                 dav_svn__getetag(resource, resource->pool));
3023
2925
 
3024
 
#if 0
3025
2926
  /* As version resources don't change, encourage caching. */
3026
 
  /* ### FIXME: This conditional is wrong -- type is often REGULAR,
3027
 
     ### and the resource doesn't seem to be baselined. */
3028
 
  if (resource->type == DAV_RESOURCE_TYPE_VERSION)
 
2927
  if ((resource->type == DAV_RESOURCE_TYPE_REGULAR
 
2928
       && resource->versioned && !resource->collection)
 
2929
      || resource->type == DAV_RESOURCE_TYPE_VERSION)
3029
2930
    /* Cache resource for one week (specified in seconds). */
3030
2931
    apr_table_setn(r->headers_out, "Cache-Control", "max-age=604800");
3031
 
#endif
3032
2932
 
3033
2933
  /* we accept byte-ranges */
3034
2934
  apr_table_setn(r->headers_out, "Accept-Ranges", "bytes");
3116
3016
        mimetype = "text/plain";
3117
3017
 
3118
3018
 
3119
 
      /* if we aren't sending a diff, then we know the length of the file,
3120
 
         so set up the Content-Length header */
3121
 
      serr = svn_fs_file_length(&length,
3122
 
                                resource->info->root.root,
3123
 
                                resource->info->repos_path,
3124
 
                                resource->pool);
3125
 
      if (serr != NULL)
 
3019
      /* if we aren't sending a diff and aren't expanding keywords,
 
3020
         then we know the exact length of the file, so set up the
 
3021
         Content-Length header. */
 
3022
      if (! resource->info->keyword_subst)
3126
3023
        {
3127
 
          return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
3128
 
                                      "could not fetch the resource length",
3129
 
                                      resource->pool);
 
3024
          serr = svn_fs_file_length(&length,
 
3025
                                    resource->info->root.root,
 
3026
                                    resource->info->repos_path,
 
3027
                                    resource->pool);
 
3028
          if (serr != NULL)
 
3029
            {
 
3030
              return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
 
3031
                                          "could not fetch the resource length",
 
3032
                                          resource->pool);
 
3033
            }
 
3034
          ap_set_content_length(r, (apr_off_t) length);
3130
3035
        }
3131
 
      ap_set_content_length(r, (apr_off_t) length);
3132
3036
    }
3133
3037
 
3134
3038
  /* set the discovered MIME type */
3145
3049
} diff_ctx_t;
3146
3050
 
3147
3051
 
3148
 
static svn_error_t *
 
3052
static svn_error_t *  __attribute__((warn_unused_result))
3149
3053
write_to_filter(void *baton, const char *buffer, apr_size_t *len)
3150
3054
{
3151
3055
  diff_ctx_t *dc = baton;
3166
3070
}
3167
3071
 
3168
3072
 
3169
 
static svn_error_t *
 
3073
static svn_error_t *  __attribute__((warn_unused_result))
3170
3074
close_filter(void *baton)
3171
3075
{
3172
3076
  diff_ctx_t *dc = baton;
3279
3183
              if (dirent->kind == svn_node_file && dirent->special)
3280
3184
                {
3281
3185
                  svn_node_kind_t resolved_kind;
3282
 
                  const char *link_path = 
 
3186
                  const char *link_path =
3283
3187
                    svn_dirent_join(fs_parent_path, key, resource->pool);
3284
3188
 
3285
3189
                  serr = svn_io_check_resolved_path(link_path, &resolved_kind,
3292
3196
                                                resource->pool);
3293
3197
                  if (resolved_kind != svn_node_dir)
3294
3198
                    continue;
3295
 
                  
 
3199
 
3296
3200
                  dirent->kind = svn_node_dir;
3297
3201
                }
3298
3202
              else if (dirent->kind != svn_node_dir)
3302
3206
              ent->id = NULL;     /* ### does it matter? */
3303
3207
              ent->kind = dirent->kind;
3304
3208
 
3305
 
              apr_hash_set(entries, key, APR_HASH_KEY_STRING, ent);
 
3209
              svn_hash_sets(entries, key, ent);
3306
3210
            }
3307
3211
 
3308
3212
        }
3439
3343
            }
3440
3344
          else
3441
3345
            {
3442
 
              /* ### TODO:  We could test for readability of the root
3443
 
                     directory of each repository and hide those that
3444
 
                     the user can't see. */
 
3346
                if (! dav_svn__allow_list_repos(resource->info->r,
 
3347
                                                entry->name, entry_pool))
 
3348
                  continue;
3445
3349
            }
3446
3350
 
3447
3351
          /* append a trailing slash onto the name for directories. we NEED
3616
3520
          /* get a handler/baton for writing into the output stream */
3617
3521
          svn_txdelta_to_svndiff3(&handler, &h_baton,
3618
3522
                                  o_stream, resource->info->svndiff_version,
3619
 
                                  dav_svn__get_compression_level(),
 
3523
                                  dav_svn__get_compression_level(resource->info->r),
3620
3524
                                  resource->pool);
3621
3525
 
3622
3526
          /* got everything set up. read in delta windows and shove them into
3654
3558
                                      resource->pool);
3655
3559
        }
3656
3560
 
 
3561
      /* Perform keywords substitution if requested by client */
 
3562
      if (resource->info->keyword_subst)
 
3563
        {
 
3564
          svn_string_t *keywords;
 
3565
 
 
3566
          serr = svn_fs_node_prop(&keywords,
 
3567
                                  resource->info->root.root,
 
3568
                                  resource->info->repos_path,
 
3569
                                  SVN_PROP_KEYWORDS,
 
3570
                                  resource->pool);
 
3571
          if (serr != NULL)
 
3572
            return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
 
3573
                                        "could not get fetch '"
 
3574
                                        SVN_PROP_KEYWORDS "' property for "
 
3575
                                        "for keywords substitution",
 
3576
                                        resource->pool);
 
3577
 
 
3578
          if (keywords)
 
3579
            {
 
3580
              apr_hash_t *kw;
 
3581
              svn_revnum_t cmt_rev;
 
3582
              const char *str_cmt_rev, *str_uri, *str_root;
 
3583
              const char *cmt_date, *cmt_author;
 
3584
              apr_time_t when = 0;
 
3585
 
 
3586
              serr = svn_repos_get_committed_info(&cmt_rev,
 
3587
                                                  &cmt_date,
 
3588
                                                  &cmt_author,
 
3589
                                                  resource->info->root.root,
 
3590
                                                  resource->info->repos_path,
 
3591
                                                  resource->pool);
 
3592
              if (serr != NULL)
 
3593
                return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
 
3594
                                            "could not fetch committed info "
 
3595
                                            "for keywords substitution",
 
3596
                                            resource->pool);
 
3597
 
 
3598
              serr = svn_time_from_cstring(&when, cmt_date, resource->pool);
 
3599
              if (serr != NULL)
 
3600
                return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
 
3601
                                            "could not parse committed date "
 
3602
                                            "for keywords substitution",
 
3603
                                            resource->pool);
 
3604
              str_cmt_rev = apr_psprintf(resource->pool, "%ld", cmt_rev);
 
3605
              str_uri = apr_pstrcat(resource->pool,
 
3606
                                    resource->info->repos->base_url,
 
3607
                                    ap_escape_uri(resource->pool,
 
3608
                                                  resource->info->r->uri),
 
3609
                                    NULL);
 
3610
              str_root = apr_pstrcat(resource->pool,
 
3611
                                     resource->info->repos->base_url,
 
3612
                                     resource->info->repos->root_path,
 
3613
                                     NULL);
 
3614
 
 
3615
              serr = svn_subst_build_keywords3(&kw, keywords->data,
 
3616
                                               str_cmt_rev, str_uri, str_root,
 
3617
                                               when, cmt_author,
 
3618
                                               resource->pool);
 
3619
              if (serr != NULL)
 
3620
                return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
 
3621
                                            "could not perform keywords "
 
3622
                                            "substitution", resource->pool);
 
3623
 
 
3624
              /* Replace the raw file STREAM with a wrapper that
 
3625
                 handles keyword translation. */
 
3626
              stream = svn_subst_stream_translated(
 
3627
                           svn_stream_disown(stream, resource->pool),
 
3628
                           NULL, FALSE, kw, TRUE, resource->pool);
 
3629
            }
 
3630
        }
 
3631
 
3657
3632
      /* ### one day in the future, we can create a custom bucket type
3658
3633
         ### which will read from the FS stream on demand */
3659
3634
 
4434
4409
                    dav_resource *resource,
4435
4410
                    ap_filter_t *output)
4436
4411
{
4437
 
  svn_skel_t *request_skel;
 
4412
  svn_skel_t *request_skel, *post_skel;
4438
4413
  int status;
4439
4414
  apr_pool_t *pool = resource->pool;
4440
4415
 
4451
4426
    return dav_svn__new_error(pool, HTTP_BAD_REQUEST, 0,
4452
4427
                              "Unable to identify skel POST request flavor.");
4453
4428
 
4454
 
  if (svn_skel__matches_atom(request_skel->children, "create-txn"))
 
4429
  post_skel = request_skel->children;
 
4430
 
 
4431
  /* NOTE: If you add POST handlers here, you'll want to advertise
 
4432
     that the server supports them, too.  See version.c:get_option(). */
 
4433
 
 
4434
  if (svn_skel__matches_atom(post_skel, "create-txn"))
4455
4435
    {
4456
4436
      return dav_svn__post_create_txn(resource, request_skel, output);
4457
4437
    }
4458
 
  else
 
4438
  else if (svn_skel__matches_atom(post_skel, "create-txn-with-props"))
4459
4439
    {
4460
 
      return dav_svn__new_error(pool, HTTP_BAD_REQUEST, 0,
4461
 
                                "Unsupported skel POST request flavor.");
 
4440
      return dav_svn__post_create_txn_with_props(resource,
 
4441
                                                 request_skel, output);
4462
4442
    }
4463
 
  /* NOTREACHED */
4464
 
}
 
4443
 
 
4444
  return dav_svn__new_error(pool, HTTP_BAD_REQUEST, 0,
 
4445
                            "Unsupported skel POST request flavor.");
 
4446
}
 
4447
 
 
4448
 
 
4449
/* A stripped down version of mod_dav's dav_handle_err so that POST
 
4450
   errors, which are not passed via mod_dav, are handled in the same
 
4451
   way as errors for requests that are passed via mod_dav. */
 
4452
static int
 
4453
handle_err(request_rec *r, dav_error *err)
 
4454
{
 
4455
  dav_error *stackerr = err;
 
4456
 
 
4457
  dav_svn__log_err(r, err, APLOG_ERR);
 
4458
 
 
4459
  /* our error messages are safe; tell Apache this */
 
4460
  apr_table_setn(r->notes, "verbose-error-to", "*");
 
4461
 
 
4462
  /* We might be able to generate a standard <D:error> response.
 
4463
     Search the error stack for an errortag. */
 
4464
  while (stackerr != NULL && stackerr->tagname == NULL)
 
4465
    stackerr = stackerr->prev;
 
4466
 
 
4467
  if (stackerr != NULL && stackerr->tagname != NULL)
 
4468
    return dav_svn__error_response_tag(r, stackerr);
 
4469
 
 
4470
  return err->status;
 
4471
}
 
4472
 
4465
4473
 
4466
4474
int dav_svn__method_post(request_rec *r)
4467
4475
{
4495
4503
  if (derr)
4496
4504
    {
4497
4505
      /* POST is not a DAV method and so mod_dav isn't involved and
4498
 
         won't log this error.  Do it explicitly. */
4499
 
      dav_svn__log_err(r, derr, APLOG_ERR);
4500
 
      return dav_svn__error_response_tag(r, derr);
 
4506
         won't handle this error.  Do it explicitly. */
 
4507
      return handle_err(r, derr);
4501
4508
    }
4502
4509
 
4503
4510
  return OK;