source: valtobtest/subversion-1.6.2/subversion/mod_dav_svn/reports/get-location-segments.c @ 3

Last change on this file since 3 was 3, checked in by valtob, 15 years ago

subversion source 1.6.2 as test

File size: 8.1 KB
Line 
1/*
2 * get-location-segments.c: mod_dav_svn versioning provider functions
3 *                          for Subversion's get-location-segments RA API.
4 *
5 * ====================================================================
6 * Copyright (c) 2007 CollabNet.  All rights reserved.
7 *
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.
13 *
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 * ====================================================================
18 */
19
20#include <apr_tables.h>
21#include <apr_uuid.h>
22
23#include <httpd.h>
24#include <http_log.h>
25#include <mod_dav.h>
26
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"
36
37#include "../dav_svn.h"
38
39
40struct location_segment_baton
41{
42  svn_boolean_t sent_opener;
43  ap_filter_t *output;
44  apr_bucket_brigade *bb;
45  dav_svn__authz_read_baton arb;
46};
47
48
49/* Send the get-location-segments-report XML open tag if it hasn't
50   been sent already.  */
51static svn_error_t *
52maybe_send_opener(struct location_segment_baton *b)
53{
54  if (! b->sent_opener)
55    {
56      SVN_ERR(dav_svn__send_xml(b->bb, b->output, DAV_XML_HEADER DEBUG_CR
57                                "<S:get-location-segments-report xmlns:S=\""
58                                SVN_XML_NAMESPACE "\" xmlns:D=\"DAV:\">"
59                                DEBUG_CR));
60      b->sent_opener = TRUE;
61    }
62  return SVN_NO_ERROR;
63}
64
65
66/* Implements `svn_location_segment_receiver_t'; helper for
67   dav_svn__get_location_segments_report(). */
68static svn_error_t *
69location_segment_receiver(svn_location_segment_t *segment,
70                          void *baton,
71                          apr_pool_t *pool)
72{
73  struct location_segment_baton *b = baton;
74  apr_status_t apr_err;
75
76  SVN_ERR(maybe_send_opener(b));
77
78  if (segment->path)
79    {
80      const char *path_quoted = apr_xml_quote_string(pool, segment->path, 1);
81      apr_err = ap_fprintf(b->output, b->bb,
82                           "<S:location-segment path=\"%s\" "
83                           "range-start=\"%ld\" range-end=\"%ld\"/>" DEBUG_CR,
84                           path_quoted,
85                           segment->range_start, segment->range_end);
86    }
87  else
88    {
89      apr_err = ap_fprintf(b->output, b->bb,
90                           "<S:location-segment "
91                           "range-start=\"%ld\" range-end=\"%ld\"/>" DEBUG_CR,
92                           segment->range_start, segment->range_end);
93    }
94  if (apr_err)
95    return svn_error_create(apr_err, 0, NULL);
96  return SVN_NO_ERROR;
97}
98
99
100dav_error *
101dav_svn__get_location_segments_report(const dav_resource *resource,
102                                      const apr_xml_doc *doc,
103                                      ap_filter_t *output)
104{
105  svn_error_t *serr;
106  dav_error *derr = NULL;
107  apr_bucket_brigade *bb;
108  int ns;
109  apr_xml_elem *child;
110  const char *path = NULL;
111  svn_revnum_t peg_revision = SVN_INVALID_REVNUM;
112  svn_revnum_t start_rev = SVN_INVALID_REVNUM;
113  svn_revnum_t end_rev = SVN_INVALID_REVNUM;
114  dav_svn__authz_read_baton arb;
115  struct location_segment_baton location_segment_baton;
116
117  /* Sanity check. */
118  ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE);
119  if (ns == -1)
120    {
121      return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
122                                    "The request does not contain the 'svn:' "
123                                    "namespace, so it is not going to have "
124                                    "certain required elements.",
125                                    SVN_DAV_ERROR_NAMESPACE,
126                                    SVN_DAV_ERROR_TAG);
127    }
128
129  /* Gather the parameters. */
130  for (child = doc->root->first_child; child != NULL; child = child->next)
131    {
132      /* If this element isn't one of ours, then skip it. */
133      if (child->ns != ns)
134        continue;
135
136      if (strcmp(child->name, "peg-revision") == 0)
137        {
138          peg_revision = SVN_STR_TO_REV(dav_xml_get_cdata(child,
139                                                          resource->pool, 1));
140        }
141      else if (strcmp(child->name, "start-revision") == 0)
142        {
143          start_rev = SVN_STR_TO_REV(dav_xml_get_cdata(child,
144                                                       resource->pool, 1));
145        }
146      else if (strcmp(child->name, "end-revision") == 0)
147        {
148          end_rev = SVN_STR_TO_REV(dav_xml_get_cdata(child,
149                                                     resource->pool, 1));
150        }
151      else if (strcmp(child->name, "path") == 0)
152        {
153          path = dav_xml_get_cdata(child, resource->pool, 0);
154          if ((derr = dav_svn__test_canonical(path, resource->pool)))
155            return derr;
156          path = svn_path_join(resource->info->repos_path, path,
157                               resource->pool);
158        }
159    }
160
161  /* Check our inputs. */
162  if (! path)
163    return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
164                                  "Not all parameters passed.",
165                                  SVN_DAV_ERROR_NAMESPACE,
166                                  SVN_DAV_ERROR_TAG);
167  if (SVN_IS_VALID_REVNUM(start_rev)
168      && SVN_IS_VALID_REVNUM(end_rev)
169      && (end_rev > start_rev))
170    return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
171                                  "End revision must not be younger than "
172                                  "start revision",
173                                  SVN_DAV_ERROR_NAMESPACE,
174                                  SVN_DAV_ERROR_TAG);
175  if (SVN_IS_VALID_REVNUM(peg_revision)
176      && SVN_IS_VALID_REVNUM(start_rev)
177      && (start_rev > peg_revision))
178    return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
179                                  "Start revision must not be younger than "
180                                  "peg revision",
181                                  SVN_DAV_ERROR_NAMESPACE,
182                                  SVN_DAV_ERROR_TAG);
183
184  /* Build an authz read baton. */
185  arb.r = resource->info->r;
186  arb.repos = resource->info->repos;
187
188  /* Build the bucket brigade we'll use for output. */
189  bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
190
191  /* Do what we came here for. */
192  location_segment_baton.sent_opener = FALSE;
193  location_segment_baton.output = output;
194  location_segment_baton.bb = bb;
195  if ((serr = svn_repos_node_location_segments(resource->info->repos->repos,
196                                               path, peg_revision,
197                                               start_rev, end_rev,
198                                               location_segment_receiver,
199                                               &location_segment_baton,
200                                               dav_svn__authz_read_func(&arb),
201                                               &arb, resource->pool)))
202    {
203      derr = dav_svn__convert_err(serr, HTTP_BAD_REQUEST, serr->message,
204                                  resource->pool);
205      goto cleanup;
206    }
207
208  if ((serr = maybe_send_opener(&location_segment_baton)))
209    {
210      derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
211                                  "Error beginning REPORT response.",
212                                  resource->pool);
213      goto cleanup;
214    }
215
216  if ((serr = dav_svn__send_xml(bb, output,
217                                "</S:get-location-segments-report>" DEBUG_CR)))
218    {
219      derr = dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
220                                  "Error ending REPORT response.",
221                                  resource->pool);
222      goto cleanup;
223    }
224
225 cleanup:
226  return dav_svn__final_flush_or_error(resource->info->r, bb, output,
227                                       derr, resource->pool);
228}
Note: See TracBrowser for help on using the repository browser.