1 /*
2  * deleted-rev.c: mod_dav_svn REPORT handler for getting the rev in
3  *                which a path was deleted
4  *
5  * ====================================================================
6  *    Licensed to the Apache Software Foundation (ASF) under one
7  *    or more contributor license agreements.  See the NOTICE file
8  *    distributed with this work for additional information
9  *    regarding copyright ownership.  The ASF licenses this file
10  *    to you under the Apache License, Version 2.0 (the
11  *    "License"); you may not use this file except in compliance
12  *    with the License.  You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  *    Unless required by applicable law or agreed to in writing,
17  *    software distributed under the License is distributed on an
18  *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19  *    KIND, either express or implied.  See the License for the
20  *    specific language governing permissions and limitations
21  *    under the License.
22  * ====================================================================
23  */
24 
25 #include <apr_xml.h>
26 
27 #include <httpd.h>
28 #include <mod_dav.h>
29 
30 #include "svn_xml.h"
31 #include "svn_repos.h"
32 #include "svn_dav.h"
33 #include "svn_pools.h"
34 
35 #include "private/svn_fspath.h"
36 #include "private/svn_dav_protocol.h"
37 
38 #include "../dav_svn.h"
39 
40 /* Respond to a S:deleted-rev-report request. */
41 dav_error *
dav_svn__get_deleted_rev_report(const dav_resource * resource,const apr_xml_doc * doc,dav_svn__output * output)42 dav_svn__get_deleted_rev_report(const dav_resource *resource,
43                                 const apr_xml_doc *doc,
44                                 dav_svn__output *output)
45 {
46   apr_xml_elem *child;
47   int ns;
48   const char *rel_path = NULL;
49   const char *abs_path = NULL;
50   svn_revnum_t peg_rev = SVN_INVALID_REVNUM;
51   svn_revnum_t end_rev = SVN_INVALID_REVNUM;
52   svn_revnum_t deleted_rev;
53   apr_bucket_brigade *bb;
54   svn_error_t *err;
55   dav_error *derr = NULL;
56 
57   /* Sanity check. */
58   if (!resource->info->repos_path)
59     return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, 0,
60                               "The request does not specify a repository path");
61   ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE);
62   if (ns == -1)
63     return dav_svn__new_error_svn(resource->pool, HTTP_BAD_REQUEST, 0, 0,
64                                   "The request does not contain the 'svn:' "
65                                   "namespace, so it is not going to have "
66                                   "certain required elements");
67 
68   for (child = doc->root->first_child; child != NULL; child = child->next)
69     {
70       /* If this element isn't one of ours, then skip it. */
71       if (child->ns != ns )
72         continue;
73 
74       if (strcmp(child->name, "peg-revision") == 0)
75         {
76           peg_rev = SVN_STR_TO_REV(dav_xml_get_cdata(child,
77                                                      resource->pool, 1));
78         }
79       else if (strcmp(child->name, "end-revision") == 0)
80         {
81           end_rev = SVN_STR_TO_REV(dav_xml_get_cdata(child,
82                                                      resource->pool, 1));
83         }
84       else if (strcmp(child->name, "path") == 0)
85         {
86           rel_path = dav_xml_get_cdata(child, resource->pool, 0);
87           if ((derr = dav_svn__test_canonical(rel_path, resource->pool)))
88             return derr;
89           /* Force REL_PATH to be a relative path, not an fspath. */
90           rel_path = svn_relpath_canonicalize(rel_path, resource->pool);
91 
92           /* Append REL_PATH to the base FS path to get an absolute
93              repository path. */
94           abs_path = svn_fspath__join(resource->info->repos_path, rel_path,
95                                       resource->pool);
96         }
97     }
98 
99   /* Check that all parameters are present and valid. */
100   if (! (abs_path
101          && SVN_IS_VALID_REVNUM(peg_rev)
102          && SVN_IS_VALID_REVNUM(end_rev)))
103     {
104       return dav_svn__new_error_svn(resource->pool, HTTP_BAD_REQUEST, 0, 0,
105                                     "Not all parameters passed");
106     }
107 
108   /* Do what we actually came here for: Find the rev abs_path was deleted. */
109   err = svn_repos_deleted_rev(resource->info->repos->fs,
110                               abs_path, peg_rev, end_rev,
111                               &deleted_rev, resource->pool);
112   if (err)
113     {
114       svn_error_clear(err);
115       return dav_svn__new_error(resource->pool, HTTP_INTERNAL_SERVER_ERROR,
116                                 0, 0,
117                                 "Could not find revision path was deleted.");
118     }
119 
120   bb = apr_brigade_create(resource->pool,
121                           dav_svn__output_get_bucket_alloc(output));
122   err = dav_svn__brigade_printf(bb, output,
123                        DAV_XML_HEADER DEBUG_CR
124                        "<S:get-deleted-rev-report xmlns:S=\""
125                        SVN_XML_NAMESPACE "\" xmlns:D=\"DAV:\">" DEBUG_CR
126                        "<D:" SVN_DAV__VERSION_NAME ">%ld</D:"
127                        SVN_DAV__VERSION_NAME ">""</S:get-deleted-rev-report>",
128                        deleted_rev);
129   if (err)
130     derr = dav_svn__convert_err(err,
131                                 HTTP_INTERNAL_SERVER_ERROR,
132                                 "Error writing REPORT response.",
133                                 resource->pool);
134 
135   return dav_svn__final_flush_or_error(resource->info->r, bb, output,
136                                        derr, resource->pool);
137 }
138