Fix compiler warning due to missing function prototype.
[svn.git] / subversion / mod_dav_svn / reports / get-location-segments.c
blob0674af1060187828440d19e23e6a751763ad7bb3
1 /*
2 * get-location-segments.c: mod_dav_svn versioning provider functions
3 * for Subversion's get-location-segments RA API.
5 * ====================================================================
6 * Copyright (c) 2007 CollabNet. All rights reserved.
8 * This software is licensed as described in the file COPYING, which
9 * you should have received as part of this distribution. The terms
10 * are also available at http://subversion.tigris.org/license-1.html.
11 * If newer versions of this license are posted there, you may use a
12 * newer version instead, at your option.
14 * This software consists of voluntary contributions made by many
15 * individuals. For exact contribution history, see the revision
16 * history and logs, available at http://subversion.tigris.org/.
17 * ====================================================================
20 #include <apr_tables.h>
21 #include <apr_uuid.h>
23 #include <httpd.h>
24 #include <http_log.h>
25 #include <mod_dav.h>
27 #include "svn_fs.h"
28 #include "svn_xml.h"
29 #include "svn_repos.h"
30 #include "svn_dav.h"
31 #include "svn_time.h"
32 #include "svn_pools.h"
33 #include "svn_props.h"
34 #include "svn_dav.h"
35 #include "svn_base64.h"
37 #include "../dav_svn.h"
40 struct location_segment_baton
42 ap_filter_t *output;
43 apr_bucket_brigade *bb;
44 dav_svn__authz_read_baton arb;
48 /* Implements `svn_location_segment_receiver_t'; helper for
49 dav_svn__get_location_segments_report(). */
50 static svn_error_t *
51 location_segment_receiver(svn_location_segment_t *segment,
52 void *baton,
53 apr_pool_t *pool)
55 struct location_segment_baton *b = baton;
56 apr_status_t apr_err;
58 if (segment->path)
60 const char *path_quoted = apr_xml_quote_string(pool, segment->path, 1);
61 apr_err = ap_fprintf(b->output, b->bb,
62 "<S:location-segment path=\"%s\" "
63 "range-start=\"%ld\" range-end=\"%ld\"/>" DEBUG_CR,
64 path_quoted,
65 segment->range_start, segment->range_end);
67 else
69 apr_err = ap_fprintf(b->output, b->bb,
70 "<S:location-segment "
71 "range-start=\"%ld\" range-end=\"%ld\"/>" DEBUG_CR,
72 segment->range_start, segment->range_end);
74 if (apr_err)
75 return svn_error_create(apr_err, 0, NULL);
76 return SVN_NO_ERROR;
80 /* Drive svn_repos_node_location_segments() with PATH, START_REV, and
81 END_REV as inputs. This helper exists for simplification of error
82 handing (what with APR status, Subversion errors, and DAV error
83 types all flying about...). */
84 static svn_error_t *
85 send_get_location_segments_report(ap_filter_t *output,
86 apr_bucket_brigade *bb,
87 const dav_resource *resource,
88 svn_revnum_t peg_rev,
89 svn_revnum_t start_rev,
90 svn_revnum_t end_rev,
91 const char *path)
93 apr_status_t apr_err;
94 dav_svn__authz_read_baton arb;
95 struct location_segment_baton location_segment_baton;
97 if ((apr_err = ap_fprintf(output, bb, DAV_XML_HEADER DEBUG_CR
98 "<S:get-location-segments-report xmlns:S=\""
99 SVN_XML_NAMESPACE "\" xmlns:D=\"DAV:\">"
100 DEBUG_CR)))
101 return svn_error_create(apr_err, 0, NULL);
103 /* Build an authz read baton. */
104 arb.r = resource->info->r;
105 arb.repos = resource->info->repos;
107 /* Do what we came here for. */
108 location_segment_baton.output = output;
109 location_segment_baton.bb = bb;
110 SVN_ERR(svn_repos_node_location_segments(resource->info->repos->repos,
111 path, peg_rev,
112 start_rev, end_rev,
113 location_segment_receiver,
114 &location_segment_baton,
115 dav_svn__authz_read_func(&arb),
116 &arb, resource->pool));
118 if ((apr_err = ap_fprintf(output, bb,
119 "</S:get-location-segments-report>" DEBUG_CR)))
120 return svn_error_create(apr_err, 0, NULL);
122 return SVN_NO_ERROR;
126 dav_error *
127 dav_svn__get_location_segments_report(const dav_resource *resource,
128 const apr_xml_doc *doc,
129 ap_filter_t *output)
131 svn_error_t *serr;
132 dav_error *derr = NULL;
133 apr_status_t apr_err;
134 apr_bucket_brigade *bb;
135 int ns;
136 apr_xml_elem *child;
137 const char *path = NULL;
138 svn_revnum_t peg_revision = SVN_INVALID_REVNUM;
139 svn_revnum_t start_rev = SVN_INVALID_REVNUM;
140 svn_revnum_t end_rev = SVN_INVALID_REVNUM;
142 /* Sanity check. */
143 ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE);
144 if (ns == -1)
146 return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
147 "The request does not contain the 'svn:' "
148 "namespace, so it is not going to have "
149 "certain required elements.",
150 SVN_DAV_ERROR_NAMESPACE,
151 SVN_DAV_ERROR_TAG);
154 /* Gather the parameters. */
155 for (child = doc->root->first_child; child != NULL; child = child->next)
157 /* If this element isn't one of ours, then skip it. */
158 if (child->ns != ns)
159 continue;
161 if (strcmp(child->name, "peg-revision") == 0)
163 peg_revision = SVN_STR_TO_REV(dav_xml_get_cdata(child,
164 resource->pool, 1));
166 else if (strcmp(child->name, "start-revision") == 0)
168 start_rev = SVN_STR_TO_REV(dav_xml_get_cdata(child,
169 resource->pool, 1));
171 else if (strcmp(child->name, "end-revision") == 0)
173 end_rev = SVN_STR_TO_REV(dav_xml_get_cdata(child,
174 resource->pool, 1));
176 else if (strcmp(child->name, "path") == 0)
178 path = dav_xml_get_cdata(child, resource->pool, 0);
179 if ((derr = dav_svn__test_canonical(path, resource->pool)))
180 return derr;
181 path = svn_path_join(resource->info->repos_path, path,
182 resource->pool);
186 /* Check our inputs. */
187 if (! path)
188 return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
189 "Not all parameters passed.",
190 SVN_DAV_ERROR_NAMESPACE,
191 SVN_DAV_ERROR_TAG);
192 if (SVN_IS_VALID_REVNUM(start_rev)
193 && SVN_IS_VALID_REVNUM(end_rev)
194 && (end_rev > start_rev))
195 return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
196 "End revision must not be younger than "
197 "start revision",
198 SVN_DAV_ERROR_NAMESPACE,
199 SVN_DAV_ERROR_TAG);
200 if (SVN_IS_VALID_REVNUM(peg_revision)
201 && SVN_IS_VALID_REVNUM(start_rev)
202 && (start_rev > peg_revision))
203 return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
204 "Start revision must not be younger than "
205 "peg revision",
206 SVN_DAV_ERROR_NAMESPACE,
207 SVN_DAV_ERROR_TAG);
209 /* Build the bucket brigade we'll use for output. */
210 bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
212 /* Alright, time to drive the response. */
213 if ((serr = send_get_location_segments_report(output, bb, resource,
214 peg_revision, start_rev,
215 end_rev, path)))
216 derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
217 "Error writing REPORT response.",
218 resource->pool);
220 /* Flush the contents of the brigade (returning an error only if we
221 don't already have one). */
222 if (((apr_err = ap_fflush(output, bb))) && (! derr))
223 return dav_svn__convert_err(svn_error_create(apr_err, 0, NULL),
224 HTTP_INTERNAL_SERVER_ERROR,
225 "Error flushing brigade.",
226 resource->pool);
228 return derr;