2
* dav_svn.h: types, functions, macros for the DAV/SVN Apache module
4
* ====================================================================
5
* Copyright (c) 2000-2004 CollabNet. All rights reserved.
7
* This software is licensed as described in the file COPYING, which
8
* you should have received as part of this distribution. The terms
9
* are also available at http://subversion.tigris.org/license-1.html.
10
* If newer versions of this license are posted there, you may use a
11
* newer version instead, at your option.
13
* This software consists of voluntary contributions made by many
14
* individuals. For exact contribution history, see the revision
15
* history and logs, available at http://subversion.tigris.org/.
16
* ====================================================================
24
#include <apr_tables.h>
28
#include "svn_error.h"
30
#include "svn_repos.h"
36
#endif /* __cplusplus */
39
/* what the one VCC is called */
40
#define DAV_SVN_DEFAULT_VCC_NAME "default"
42
/* a pool-key for the shared dav_svn_root used by autoversioning */
43
#define DAV_SVN_AUTOVERSIONING_ACTIVITY "svn-autoversioning-activity"
48
* Record information about the repository that a resource belongs to.
49
* This structure will be shared between multiple resources so that we
50
* can optimized our FS access.
52
* Note that we do not refcount this structure. Presumably, we will need
53
* it throughout the life of the request. Therefore, we can just leave it
54
* for the request pool to cleanup/close.
56
* Also, note that it is possible that two resources may have distinct
57
* dav_svn_repos structures, yet refer to the same repository. This is
58
* allowed by the SVN FS interface.
60
* ### should we attempt to merge them when we detect this situation in
61
* ### places like is_same_resource, is_parent_resource, or copy/move?
62
* ### I say yes: the FS will certainly have an easier time if there is
63
* ### only a single FS open; otherwise, it will have to work a bit harder
64
* ### to keep the things in sync.
67
apr_pool_t *pool; /* request_rec -> pool */
69
/* Remember the root URL path of this repository (just a path; no
70
scheme, host, or port).
72
Example: the URI is "http://host/repos/file", this will be "/repos".
74
This always starts with "/", and if there are any components
75
beyond that, then it does not end with "/".
77
const char *root_path;
79
/* Remember an absolute URL for constructing other URLs. In the above
80
example, this would be "http://host" (note: no trailing slash)
84
/* Remember the special URI component for this repository */
85
const char *special_uri;
87
/* This records the filesystem path to the SVN FS */
90
/* The name of this repository */
91
const char *repo_name;
93
/* The URI of the XSL transform for directory indexes */
96
/* Whether autoversioning is active for this repository. */
97
svn_boolean_t autoversioning;
99
/* the open repository */
102
/* a cached copy of REPOS->fs above. */
105
/* the user operating against this repository */
106
const char *username;
108
/* is the client a Subversion client? */
109
svn_boolean_t is_svn_client;
115
** dav_svn_private_restype: identifiers for our different private resources
117
** There are some resources within mod_dav_svn that are "privately defined".
118
** This isn't so much to prevent other people from knowing what they are,
119
** but merely that mod_dav doesn't have a standard name for them.
121
enum dav_svn_private_restype {
122
DAV_SVN_RESTYPE_UNSET,
124
DAV_SVN_RESTYPE_ROOT_COLLECTION, /* .../!svn/ */
125
DAV_SVN_RESTYPE_VER_COLLECTION, /* .../!svn/ver/ */
126
DAV_SVN_RESTYPE_HIS_COLLECTION, /* .../!svn/his/ */
127
DAV_SVN_RESTYPE_WRK_COLLECTION, /* .../!svn/wrk/ */
128
DAV_SVN_RESTYPE_ACT_COLLECTION, /* .../!svn/act/ */
129
DAV_SVN_RESTYPE_VCC_COLLECTION, /* .../!svn/vcc/ */
130
DAV_SVN_RESTYPE_BC_COLLECTION, /* .../!svn/bc/ */
131
DAV_SVN_RESTYPE_BLN_COLLECTION, /* .../!svn/bln/ */
132
DAV_SVN_RESTYPE_WBL_COLLECTION, /* .../!svn/wbl/ */
133
DAV_SVN_RESTYPE_VCC /* .../!svn/vcc/NAME */
137
/* store info about a root in a repository */
139
/* If a root within the FS has been opened, the value is stored here.
140
Otherwise, this field is NULL. */
143
/* If the root has been opened, and it was opened for a specific revision,
144
then it is contained in REV. If the root is unopened or corresponds to
145
a transaction, then REV will be SVN_INVALID_REVNUM. */
148
/* If this resource is an activity or part of an activity, this specifies
149
the ID of that activity. It may not (yet) correspond to a transaction
152
WORKING and ACTIVITY resources use this field.
154
const char *activity_id;
156
/* If the root is part of a transaction, this contains the FS's tranaction
157
name. It may be NULL if this root corresponds to a specific revision.
158
It may also be NULL if we have not opened the root yet.
160
WORKING and ACTIVITY resources use this field.
162
const char *txn_name;
164
/* If the root is part of a transaction, this contains the FS's transaction
165
handle. It may be NULL if this root corresponds to a specific revision.
166
It may also be NULL if we have not opened the transaction yet.
168
WORKING resources use this field.
174
/* internal structure to hold information about this resource */
175
struct dav_resource_private {
176
/* Path from the SVN repository root to this resource. This value has
177
a leading slash. It will never have a trailing slash, even if the
178
resource represents a collection.
180
For example: URI is http://host/repos/file -- path will be "/file".
182
NOTE: this path is from the URI and does NOT necessarily correspond
183
to a path within the FS repository.
185
svn_stringbuf_t *uri_path;
187
/* The FS repository path to this resource, with a leading "/". Note
188
that this is "/" the root. This value will be NULL for resources
189
that have no corresponding resource within the repository (such as
190
the PRIVATE resources, Baselines, or Working Baselines). */
191
const char *repos_path;
193
/* the FS repository this resource is associated with */
194
dav_svn_repos *repos;
196
/* what FS root this resource occurs within */
199
/* for PRIVATE resources: the private resource type */
200
enum dav_svn_private_restype restype;
202
/* The request which created this resource. We need this to
203
generate subrequests. */
206
/* ### hack to deal with the Content-Type header on a PUT */
209
/* ### record the base for computing a delta during a GET */
210
const char *delta_base;
212
/* the value of any SVN_DAV_OPTIONS_HEADER that came in the request */
213
const char *svn_client_options;
215
/* the revnum value from a possible SVN_DAV_VERSION_NAME_HEADER */
216
svn_revnum_t version_name;
218
/* Hex MD5 digests for base text and resultant fulltext.
219
Either or both of these may be null, in which case ignored. */
220
const char *base_checksum;
221
const char *result_checksum;
223
/* was this resource auto-checked-out? */
224
svn_boolean_t auto_checked_out;
226
/* Pool to allocate temporary data from */
234
These are standard hooks defined by mod_dav. We implement them to expose
235
various live properties on the resources under our control.
237
gather_propsets: appends URIs into the array; the property set URIs are
238
used to specify which sets of custom properties we
240
find_liveprop: given a namespace and name, return the hooks for the
241
provider who defines that property.
242
insert_all_liveprops: for a given resource, insert all of the live
243
properties defined on that resource. The properties
244
are inserted according to the WHAT parameter.
246
void dav_svn_gather_propsets(apr_array_header_t *uris);
247
int dav_svn_find_liveprop(const dav_resource *resource,
248
const char *ns_uri, const char *name,
249
const dav_hooks_liveprop **hooks);
250
void dav_svn_insert_all_liveprops(request_rec *r, const dav_resource *resource,
251
dav_prop_insert what, apr_text_header *phdr);
253
/* register our live property URIs with mod_dav. */
254
void dav_svn_register_uris(apr_pool_t *p);
256
/* generate an ETag for RESOURCE and return it, allocated in POOL. */
257
const char * dav_svn_getetag(const dav_resource *resource, apr_pool_t *pool);
259
/* our hooks structures; these are gathered into a dav_provider */
260
extern const dav_hooks_repository dav_svn_hooks_repos;
261
extern const dav_hooks_propdb dav_svn_hooks_propdb;
262
extern const dav_hooks_liveprop dav_svn_hooks_liveprop;
263
extern const dav_hooks_vsn dav_svn_hooks_vsn;
264
extern const dav_hooks_locks dav_svn_hooks_locks;
266
/* for the repository referred to by this request, where is the SVN FS? */
267
const char *dav_svn_get_fs_path(request_rec *r);
268
const char *dav_svn_get_fs_parent_path(request_rec *r);
270
/* for the repository referred to by this request, is autoversioning active? */
271
svn_boolean_t dav_svn_get_autoversioning_flag(request_rec *r);
273
/* for the repository referred to by this request, are subrequests active? */
274
svn_boolean_t dav_svn_get_pathauthz_flag(request_rec *r);
279
SVN needs to create many types of "pseudo resources" -- resources
280
that don't correspond to the users' files/directories in the
281
repository. Specifically, these are:
286
- version history resources
288
Each of these will be placed under a portion of the URL namespace
289
that defines the SVN repository. For example, let's say the user
290
has configured an SVN repository at http://host/svn/repos. The
291
special resources could be configured to live at .../!svn/ under
292
that repository. Thus, an activity might be located at
293
http://host/svn/repos/!svn/act/1234.
295
The special URI is configurable on a per-server basis and defaults
298
NOTE: the special URI is RELATIVE to the "root" of the
299
repository. The root is generally available only to
300
dav_svn_get_resource(). This is okay, however, because we can cache
301
the root_dir when the resource structure is built.
304
/* Return the special URI to be used for this resource. */
305
const char *dav_svn_get_special_uri(request_rec *r);
307
/* Return a descriptive name for the repository */
308
const char *dav_svn_get_repo_name(request_rec *r);
310
/* Return the URI of an XSL transform stylesheet */
311
const char *dav_svn_get_xslt_uri(request_rec *r);
313
/* Convert an svn_error_t into a dav_error, pushing another error based on
314
MESSAGE if MESSAGE is not NULL. Use the provided HTTP status for the
315
DAV errors. Allocate new DAV errors from POOL.
317
NOTE: this function destroys (cleanly, of course) SERR after it has
318
copied/converted its data to the new DAV error.
320
NOTE: MESSAGE needs to hang around for the lifetime of the error since
321
the current implementation doesn't copy it! Lots of callers pass static
323
dav_error *dav_svn_convert_err(svn_error_t *serr, int status,
324
const char *message, apr_pool_t *pool);
326
/* Test PATH for canonicalness (defined as "what won't make the
327
svn_path_* functions immediately explode"), returning an
328
HTTP_BAD_REQUEST error tag if the test fails. */
329
dav_error *dav_svn__test_canonical(const char *path, apr_pool_t *pool);
331
/* activity functions for looking up, storing, and deleting
332
ACTIVITY->TXN mappings */
333
const char *dav_svn_get_txn(const dav_svn_repos *repos,
334
const char *activity_id);
335
dav_error *dav_svn_delete_activity(const dav_svn_repos *repos,
336
const char *activity_id);
337
dav_error *dav_svn_store_activity(const dav_svn_repos *repos,
338
const char *activity_id,
339
const char *txn_name);
340
dav_error *dav_svn_create_activity(const dav_svn_repos *repos,
341
const char **ptxn_name,
345
Construct a working resource for a given resource.
347
The internal information (repository, URL parts, etc) for the new
348
resource comes from BASE, the activity to use is specified by
349
ACTIVITY_ID, and the name of the transaction is specified by
350
TXN_NAME. These will be assembled into a new dav_resource and
353
If TWEAK_IN_PLACE is non-zero, then directly tweak BASE into a
354
working resource and return NULL.
356
dav_resource *dav_svn_create_working_resource(dav_resource *base,
357
const char *activity_id,
358
const char *txn_name,
361
Convert a working RESOURCE back into a regular one, in-place.
363
In particular: change the resource type to regular, removing the
364
'working' flag, change the fs root from a txn-root to a rev-root,
365
and set the URL back into either a public URL or bc URL.
367
dav_error *dav_svn_working_to_regular_resource(dav_resource *resource);
370
Given a version-resource URI, construct a new version-resource in
371
POOL and return it in *VERSION_RES.
373
dav_error *dav_svn_create_version_resource(dav_resource **version_res,
379
Hook function of types 'checkout' and 'checkin', as defined in
380
mod_dav.h's versioning provider hooks table (see dav_hooks_vsn).
382
dav_error *dav_svn_checkout(dav_resource *resource,
384
int is_unreserved, int is_fork_ok,
386
apr_array_header_t *activities,
387
dav_resource **working_resource);
389
dav_error *dav_svn_checkin(dav_resource *resource,
390
int keep_checked_out,
391
dav_resource **version_resource);
393
/* For an autoversioning commit, a helper function which attaches an
394
auto-generated 'svn:log' property to a txn, as well as a property
395
that indicates the revision was made via autoversioning. */
396
svn_error_t *dav_svn_attach_auto_revprops(svn_fs_txn_t *txn,
400
enum dav_svn_build_what {
401
DAV_SVN_BUILD_URI_ACT_COLLECTION, /* the collection of activities */
402
DAV_SVN_BUILD_URI_BASELINE, /* a Baseline */
403
DAV_SVN_BUILD_URI_BC, /* a Baseline Collection */
404
DAV_SVN_BUILD_URI_PUBLIC, /* the "public" VCR */
405
DAV_SVN_BUILD_URI_VERSION, /* a Version Resource */
406
DAV_SVN_BUILD_URI_VCC /* a Version Controlled Configuration */
410
Construct various kinds of URIs.
412
REPOS is always required, as all URIs will be built to refer to elements
413
within that repository. WHAT specifies the type of URI to build. The
414
ADD_HREF flag determines whether the URI is to be wrapped inside of
415
<D:href>uri</D:href> elements (for inclusion in a response).
417
Different pieces of information are required for the various URI types:
419
ACT_COLLECTION: no additional params required
420
BASELINE: REVISION should be specified
421
BC: REVISION should be specified
422
PUBLIC: PATH should be specified with a leading slash
423
VERSION: REVISION and PATH should be specified
424
VCC: no additional params required
426
const char *dav_svn_build_uri(const dav_svn_repos *repos,
427
enum dav_svn_build_what what,
428
svn_revnum_t revision,
434
/* Compare (PATH in ROOT) to (PATH in ROOT/PATH's created_rev).
436
If these nodes are identical, then return the created_rev.
438
If the nodes aren't identical, or if PATH simply doesn't exist in
439
the created_rev, then return the revision represented by ROOT.
441
(This is a helper to functions that want to build version-urls and
442
use the CR if possible.)
444
svn_revnum_t dav_svn_get_safe_cr(svn_fs_root_t *root,
449
** Simple parsing of a URI. This is used for URIs which appear within a
450
** request body. It enables us to verify and break out the necessary pieces
451
** to figure out what is being referred to.
453
** ### this is horribly duplicative with the parsing functions in repos.c
454
** ### for now, this implements only a minor subset of the full range of
455
** ### URIs which we may need to parse. it also ignores any scheme, host,
456
** ### and port in the URI and simply assumes it refers to the same server.
460
const char *repos_path;
461
const char *activity_id;
464
svn_error_t *dav_svn_simple_parse_uri(dav_svn_uri_info *info,
465
const dav_resource *relative,
470
/* Given an apache request R and a ROOT_PATH to the svn location
471
block, set *KIND to the node-kind of the URI's associated
472
(revision, path) pair, if possible.
474
Public uris, baseline collections, version resources, and working
475
(non-baseline) resources all have associated (revision, path)
476
pairs, and thus one of {svn_node_file, svn_node_dir, svn_node_none}
479
If URI is something more abstract, then set *KIND to
480
svn_node_unknown. This is true for baselines, working baselines,
481
version controled configurations, activities, histories, and other
484
dav_error * dav_svn_resource_kind (request_rec *r,
486
const char *root_path,
487
svn_node_kind_t *kind);
490
/* Generate the HTTP response body for a successful MERGE. */
492
dav_error * dav_svn__merge_response(ap_filter_t *output,
493
const dav_svn_repos *repos,
494
svn_revnum_t new_rev,
495
apr_xml_elem *prop_elem,
496
svn_boolean_t disable_merge_response,
499
dav_error * dav_svn__update_report(const dav_resource *resource,
500
const apr_xml_doc *doc,
501
ap_filter_t *output);
503
/* ### todo: document this, as soon as understand what the heck it
505
dav_error * dav_svn__log_report(const dav_resource *resource,
506
const apr_xml_doc *doc,
507
ap_filter_t *output);
509
/* Respond to a client request for a REPORT of type file-revs-report for the
510
RESOURCE. Get request body from DOC and send result to OUTPUT. */
511
dav_error * dav_svn__file_revs_report(const dav_resource *resource,
512
const apr_xml_doc *doc,
513
ap_filter_t *output);
515
int dav_svn_find_ns(apr_array_header_t *namespaces, const char *uri);
517
/* Output XML data to OUTPUT using BB. Use FMT as format string for the.
519
svn_error_t * dav_svn__send_xml(apr_bucket_brigade *bb, ap_filter_t *output,
520
const char *fmt, ...)
521
__attribute__((format(printf, 3, 4)));
524
enum dav_svn_time_format {
525
dav_svn_time_format_iso8601,
526
dav_svn_time_format_rfc1123
529
/* Given a mod_dav_svn @a resource, set @a *timeval and @a *datestring
530
to the last-modified-time of the resource. The datestring will be
531
formatted according to @a format. Use @a pool for both
532
scratchwork, and to allocate @a *datestring.
534
If @a timeval or @a datestring is NULL, don't touch it.
536
Return zero on success, non-zero if an error occurs. */
537
int dav_svn_get_last_modified_time (const char **datestring,
539
const dav_resource *resource,
540
enum dav_svn_time_format format,
543
dav_error * dav_svn__get_locations_report(const dav_resource *resource,
544
const apr_xml_doc *doc,
545
ap_filter_t *output);
549
/* Return a writable generic stream that will encode its output to base64
550
and send it to the Apache filter OUTPUT using BB. Allocate the stream in
552
svn_stream_t * dav_svn_make_base64_output_stream(apr_bucket_brigade *bb,
557
/* A baton needed by dav_svn_authz_read(). */
560
/* The original request, needed to generate a subrequest. */
563
/* We need this to construct a URI based on a repository abs path. */
564
const dav_svn_repos *repos;
566
} dav_svn_authz_read_baton;
569
/* This function implements 'svn_repos_authz_func_t', specifically
570
for read authorization.
572
Convert incoming ROOT and PATH into a version-resource URI and
573
perform a GET subrequest on it. This will invoke any authz modules
574
loaded into apache. Set *ALLOWED to TRUE if the subrequest
575
succeeds, FALSE otherwise.
577
BATON must be a pointer to a dav_svn_authz_read_baton (see above).
578
Use POOL for for any temporary allocation.
580
svn_error_t *dav_svn_authz_read(svn_boolean_t *allowed,
587
/* Every provider needs to define an opaque locktoken type. */
590
/* This is identical to the 'token' field of an svn_lock_t. */
591
const char *uuid_str;
595
/* Helper for reading lock-tokens out of request bodies, by looking
596
for cached body in R->pool's userdata.
598
Return a hash that maps (const char *) absolute fs paths to (const
599
char *) locktokens. Allocate the hash and all keys/vals in POOL.
600
PATH_PREFIX is the prefix we need to prepend to each relative
601
'lock-path' in the xml in order to create an absolute fs-path.
603
dav_error *dav_svn__build_lock_hash(apr_hash_t **locks,
605
const char *path_prefix,
609
/* Helper: push all of the lock-tokens (hash values) in LOCKS into
610
RESOURCE's already-open svn_fs_t. */
611
dav_error *dav_svn__push_locks(dav_resource *resource,
618
#endif /* __cplusplus */
620
#endif /* DAV_SVN_H */