2
* ra_dav.h : private declarations for the RA/DAV 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
* ====================================================================
21
#ifndef SVN_LIBSVN_RA_DAV_H
22
#define SVN_LIBSVN_RA_DAV_H
24
#include <apr_pools.h>
25
#include <apr_tables.h>
27
#include <ne_request.h>
29
#include <ne_207.h> /* for NE_ELM_207_UNUSED */
30
#include <ne_props.h> /* for ne_propname */
32
#include "svn_types.h"
33
#include "svn_string.h"
34
#include "svn_delta.h"
40
#endif /* __cplusplus */
44
/* Rename these types and constants to abstract from Neon */
46
#define SVN_RA_DAV__XML_VALID (0)
47
#define SVN_RA_DAV__XML_INVALID (-1)
48
#define SVN_RA_DAV__XML_DECLINE (-2)
50
#define SVN_RA_DAV__XML_CDATA (1<<1)
51
#define SVN_RA_DAV__XML_COLLECT ((1<<2) | SVN_RA_DAV__XML_CDATA)
53
typedef int svn_ra_dav__xml_elmid;
63
/** XML tag id to be passed to a handler. */
64
svn_ra_dav__xml_elmid id;
66
/** Processing flags for this namespace:tag.
68
* 0 (zero) - regular element, may have children,
69
* SVN_RA_DAV__XML_CDATA - child-less element,
70
* SVN_RA_DAV__XML_COLLECT - complete contents of such element must be
71
* collected as CDATA, includes *_CDATA flag. */
74
} svn_ra_dav__xml_elm_t;
77
/** (Neon 0.23) Callback to validate a new child element.
79
* @a parent and @a child are element ids found in the array of
80
* elements, @a userdata is a user baton. Returns:
82
* SVN_RA_DAV__XML_VALID - this is a valid element processed by this
84
* SVN_RA_DAV__XML_INVALID - this is not a valid element, parsing should
86
* SVN_RA_DAV__XML_DECLINE - this handler doesn't know about this element,
87
* someone else may handle it.
89
* (See @a shim_xml_push_handler in util.c for more information.) */
90
typedef int svn_ra_dav__xml_validate_cb(void *userdata,
91
svn_ra_dav__xml_elmid parent,
92
svn_ra_dav__xml_elmid child);
94
/** (Neon 0.23) Callback to start parsing a new child element.
96
* @a userdata is a user baton. @elm is a member of elements array,
97
* and @a atts is an array of name-value XML attributes.
98
* See @c svn_ra_dav__xml_validate_cb for return values.
100
* (See @a shim_xml_push_handler in util.c for more information.) */
101
typedef int svn_ra_dav__xml_startelm_cb(void *userdata,
102
const svn_ra_dav__xml_elm_t *elm,
105
/** (Neon 0.23) Callback to finish parsing a child element.
107
* Callback for @c svn_ra_dav__xml_push_handler. @a userdata is a user
108
* baton. @elm is a member of elements array, and @a cdata is the contents
110
* See @c svn_ra_dav__xml_validate_cb for return values.
112
* (See @a shim_xml_push_handler in util.c for more information.) */
113
typedef int svn_ra_dav__xml_endelm_cb(void *userdata,
114
const svn_ra_dav__xml_elm_t *elm,
121
/* Context for neon request hooks; shared by the neon callbacks in
123
struct lock_request_baton
125
/* The method neon is about to execute. */
128
/* The current working revision of item being locked. */
129
svn_revnum_t current_rev;
131
/* Whether client is "forcing" a lock or unlock. */
134
/* The creation-date returned for newly created lock. */
135
apr_time_t creation_date;
137
/* The person who created the lock. */
138
const char *lock_owner;
140
/* A parser for handling <D:error> responses from mod_dav_svn. */
141
ne_xml_parser *error_parser;
143
/* If <D:error> is returned, here's where the parsed result goes. */
146
/* A place for allocating fields in this structure. */
153
const char *url; /* original, unparsed session url */
154
ne_uri root; /* parsed version of above */
155
const char *repos_root; /* URL for repository root */
157
ne_session *sess; /* HTTP session to server */
160
const svn_ra_callbacks_t *callbacks; /* callbacks to get auth data */
161
void *callback_baton;
163
svn_auth_iterstate_t *auth_iterstate; /* state of authentication retries */
164
const char *auth_username; /* last authenticated username used */
166
svn_boolean_t compression; /* should we use http compression? */
167
const char *uuid; /* repository UUID */
170
struct lock_request_baton *lrb; /* used by lock/unlock */
172
} svn_ra_dav__session_t;
175
/* Id used with ne_set_session_private() and ne_get_session_private()
176
to retrieve the userdata (which is currently the RA session baton!) */
177
#define SVN_RA_NE_SESSION_ID "SVN"
181
#define DEBUG_CR "\n"
187
/** vtable function prototypes */
189
svn_error_t *svn_ra_dav__get_latest_revnum(svn_ra_session_t *session,
190
svn_revnum_t *latest_revnum,
193
svn_error_t *svn_ra_dav__get_dated_revision (svn_ra_session_t *session,
194
svn_revnum_t *revision,
195
apr_time_t timestamp,
198
svn_error_t *svn_ra_dav__change_rev_prop (svn_ra_session_t *session,
201
const svn_string_t *value,
204
svn_error_t *svn_ra_dav__rev_proplist (svn_ra_session_t *session,
209
svn_error_t *svn_ra_dav__rev_prop (svn_ra_session_t *session,
212
svn_string_t **value,
215
svn_error_t * svn_ra_dav__get_commit_editor(
216
svn_ra_session_t *session,
217
const svn_delta_editor_t **editor,
220
svn_commit_callback_t callback,
221
void *callback_baton,
222
apr_hash_t *lock_tokens,
223
svn_boolean_t keep_locks,
226
svn_error_t * svn_ra_dav__get_file(
227
svn_ra_session_t *session,
229
svn_revnum_t revision,
230
svn_stream_t *stream,
231
svn_revnum_t *fetched_rev,
235
svn_error_t *svn_ra_dav__get_dir(
236
svn_ra_session_t *session,
238
svn_revnum_t revision,
239
apr_hash_t **dirents,
240
svn_revnum_t *fetched_rev,
244
svn_error_t * svn_ra_dav__abort_commit(
248
svn_error_t * svn_ra_dav__do_update(
249
svn_ra_session_t *session,
250
const svn_ra_reporter2_t **reporter,
252
svn_revnum_t revision_to_update_to,
253
const char *update_target,
254
svn_boolean_t recurse,
255
const svn_delta_editor_t *wc_update,
256
void *wc_update_baton,
259
svn_error_t * svn_ra_dav__do_status(
260
svn_ra_session_t *session,
261
const svn_ra_reporter2_t **reporter,
263
const char *status_target,
264
svn_revnum_t revision,
265
svn_boolean_t recurse,
266
const svn_delta_editor_t *wc_status,
267
void *wc_status_baton,
270
svn_error_t * svn_ra_dav__do_switch(
271
svn_ra_session_t *session,
272
const svn_ra_reporter2_t **reporter,
274
svn_revnum_t revision_to_update_to,
275
const char *update_target,
276
svn_boolean_t recurse,
277
const char *switch_url,
278
const svn_delta_editor_t *wc_update,
279
void *wc_update_baton,
282
svn_error_t * svn_ra_dav__do_diff(
283
svn_ra_session_t *session,
284
const svn_ra_reporter2_t **reporter,
286
svn_revnum_t revision,
287
const char *diff_target,
288
svn_boolean_t recurse,
289
svn_boolean_t ignore_ancestry,
290
const char *versus_url,
291
const svn_delta_editor_t *wc_diff,
295
svn_error_t * svn_ra_dav__get_log(
296
svn_ra_session_t *session,
297
const apr_array_header_t *paths,
301
svn_boolean_t discover_changed_paths,
302
svn_boolean_t strict_node_history,
303
svn_log_message_receiver_t receiver,
304
void *receiver_baton,
307
svn_error_t *svn_ra_dav__do_check_path(
308
svn_ra_session_t *session,
310
svn_revnum_t revision,
311
svn_node_kind_t *kind,
314
svn_error_t *svn_ra_dav__do_stat(
315
svn_ra_session_t *session,
317
svn_revnum_t revision,
318
svn_dirent_t **dirent,
321
svn_error_t *svn_ra_dav__get_file_revs (svn_ra_session_t *session,
325
svn_ra_file_rev_handler_t handler,
331
** SVN_RA_DAV__LP_*: local properties for RA/DAV
333
** ra_dav stores properties on the client containing information needed
334
** to operate against the SVN server. Some of this informations is strictly
335
** necessary to store, and some is simply stored as a cached value.
338
#define SVN_RA_DAV__LP_NAMESPACE SVN_PROP_WC_PREFIX "ra_dav:"
340
/* store the URL where Activities can be created */
341
/* ### should fix the name to be "activity-coll" at some point */
342
#define SVN_RA_DAV__LP_ACTIVITY_COLL SVN_RA_DAV__LP_NAMESPACE "activity-url"
344
/* store the URL of the version resource (from the DAV:checked-in property) */
345
#define SVN_RA_DAV__LP_VSN_URL SVN_RA_DAV__LP_NAMESPACE "version-url"
349
** SVN_RA_DAV__PROP_*: properties that we fetch from the server
351
** These are simply symbolic names for some standard properties that we fetch.
353
#define SVN_RA_DAV__PROP_BASELINE_COLLECTION "DAV:baseline-collection"
354
#define SVN_RA_DAV__PROP_CHECKED_IN "DAV:checked-in"
355
#define SVN_RA_DAV__PROP_VCC "DAV:version-controlled-configuration"
356
#define SVN_RA_DAV__PROP_VERSION_NAME "DAV:version-name"
357
#define SVN_RA_DAV__PROP_CREATIONDATE "DAV:creationdate"
358
#define SVN_RA_DAV__PROP_CREATOR_DISPLAYNAME "DAV:creator-displayname"
359
#define SVN_RA_DAV__PROP_GETCONTENTLENGTH "DAV:getcontentlength"
361
#define SVN_RA_DAV__PROP_BASELINE_RELPATH \
362
SVN_DAV_PROP_NS_DAV "baseline-relative-path"
364
#define SVN_RA_DAV__PROP_MD5_CHECKSUM SVN_DAV_PROP_NS_DAV "md5-checksum"
366
#define SVN_RA_DAV__PROP_REPOSITORY_UUID SVN_DAV_PROP_NS_DAV "repository-uuid"
370
/* what is the URL for this resource */
373
/* is this resource a collection? (from the DAV:resourcetype element) */
376
/* PROPSET: NAME -> VALUE (const char * -> const svn_string_t *) */
379
/* --- only used during response processing --- */
380
/* when we see a DAV:href element, what element is the parent? */
385
} svn_ra_dav_resource_t;
387
/* ### WARNING: which_props can only identify properties which props.c
388
### knows about. see the elem_definitions[] array. */
390
/* fetch a bunch of properties from the server. */
391
svn_error_t * svn_ra_dav__get_props(apr_hash_t **results,
396
const ne_propname *which_props,
399
/* fetch a single resource's props from the server. */
400
svn_error_t * svn_ra_dav__get_props_resource(svn_ra_dav_resource_t **rsrc,
404
const ne_propname *which_props,
407
/* fetch a single resource's starting props from the server. */
408
svn_error_t * svn_ra_dav__get_starting_props(svn_ra_dav_resource_t **rsrc,
414
/* Shared helper func: given a public URL which may not exist in HEAD,
415
use SESS to search up parent directories until we can retrieve a
416
*RSRC (allocated in POOL) containing a standard set of "starting"
417
props: {VCC, resourcetype, baseline-relative-path}.
419
Also return *MISSING_PATH (allocated in POOL), which is the
420
trailing portion of the URL that did not exist. If an error
421
occurs, *MISSING_PATH isn't changed. */
423
svn_ra_dav__search_for_starting_props(svn_ra_dav_resource_t **rsrc,
424
const char **missing_path,
429
/* fetch a single property from a single resource */
430
svn_error_t * svn_ra_dav__get_one_prop(const svn_string_t **propval,
434
const ne_propname *propname,
437
/* Get various Baseline-related information for a given "public" URL.
439
Given a Neon session SESS and a URL, return whether the URL is a
440
directory in *IS_DIR. IS_DIR may be NULL if this flag is unneeded.
442
REVISION may be SVN_INVALID_REVNUM to indicate that the operation
443
should work against the latest (HEAD) revision, or whether it should
444
return information about that specific revision.
446
If BC_URL is not NULL, then it will be filled in with the URL for
447
the Baseline Collection for the specified revision, or the HEAD.
449
If BC_RELATIVE is not NULL, then it will be filled in with a
450
relative pathname for the baselined resource corresponding to the
451
revision of the resource specified by URL.
453
If LATEST_REV is not NULL, then it will be filled in with the revision
454
that this information corresponds to. Generally, this will be the same
455
as the REVISION parameter, unless we are working against the HEAD. In
456
that case, the HEAD revision number is returned.
458
Allocation for BC_URL->data, BC_RELATIVE->data, and temporary data,
461
Note: a Baseline Collection is a complete tree for a specified Baseline.
462
DeltaV baselines correspond one-to-one to Subversion revisions. Thus,
463
the entire state of a revision can be found in a Baseline Collection.
465
svn_error_t *svn_ra_dav__get_baseline_info(svn_boolean_t *is_dir,
466
svn_string_t *bc_url,
467
svn_string_t *bc_relative,
468
svn_revnum_t *latest_rev,
471
svn_revnum_t revision,
474
/* Fetch a baseline resource populated with specific properties.
476
Given a Neon session SESS and a URL, set *BLN_RSRC to a baseline of
477
REVISION, populated with whatever properties are specified by
478
WHICH_PROPS. To fetch all properties, pass NULL for WHICH_PROPS.
480
If BC_RELATIVE is not NULL, then it will be filled in with a
481
relative pathname for the baselined resource corresponding to the
482
revision of the resource specified by URL.
484
svn_error_t *svn_ra_dav__get_baseline_props(svn_string_t *bc_relative,
485
svn_ra_dav_resource_t **bln_rsrc,
488
svn_revnum_t revision,
489
const ne_propname *which_props,
492
/* Fetch the repository's unique Version-Controlled-Configuration url.
494
Given a Neon session SESS and a URL, set *VCC to the url of the
495
repository's version-controlled-configuration resource.
497
svn_error_t *svn_ra_dav__get_vcc(const char **vcc,
502
/* Issue a PROPPATCH request on URL, transmitting PROP_CHANGES (a hash
503
of const svn_string_t * values keyed on Subversion user-visible
504
property names) and PROP_DELETES (an array of property names to
505
delete). Send any extra request headers in EXTRA_HEADERS. Use POOL
506
for all allocations. */
507
svn_error_t *svn_ra_dav__do_proppatch (svn_ra_dav__session_t *ras,
509
apr_hash_t *prop_changes,
510
apr_array_header_t *prop_deletes,
511
apr_hash_t *extra_headers,
514
extern const ne_propname svn_ra_dav__vcc_prop;
515
extern const ne_propname svn_ra_dav__checked_in_prop;
520
/* send an OPTIONS request to fetch the activity-collection-set */
521
svn_error_t * svn_ra_dav__get_activity_collection(
522
const svn_string_t **activity_coll,
523
svn_ra_dav__session_t *ras,
528
/* Call ne_set_request_body_pdovider on REQ with a provider function
529
* that pulls data from BODY_FILE.
531
svn_error_t *svn_ra_dav__set_neon_body_provider(ne_request *req,
532
apr_file_t *body_file);
535
/** Find a given element in the table of elements.
537
* The table of XML elements @a table is searched until element identified by
538
* namespace @a nspace and name @a name is found. If no elements are found,
539
* tries to find and return element identified by @c ELEM_unknown. If that is
540
* not found, returns NULL pointer. */
541
const svn_ra_dav__xml_elm_t *
542
svn_ra_dav__lookup_xml_elem(const svn_ra_dav__xml_elm_t *table,
547
/* Send a METHOD request (e.g., "MERGE", "REPORT", "PROPFIND") to URL
548
* in session SESS, and parse the response. If BODY is non-null, it is
549
* the body of the request, else use the contents of file BODY_FILE
552
* VALIDATE_CB, STARTELM_CB, and ENDELM_CB are Neon validation, start
553
* element, and end element handlers, respectively, from Neon > 0.24.
554
* BATON is passed to each as userdata.
556
* SET_PARSER is a callback function which, if non-NULL, is called
557
* with the XML parser and BATON. This is useful for providers of
558
* validation and element handlers which require access to the parser.
560
* EXTRA_HEADERS is a hash of (const char *) key/value pairs to be
561
* inserted as extra headers in the request. Can be NULL.
563
* STATUS_CODE is an optional 'out' parameter; if non-NULL, then set
564
* *STATUS_CODE to the http status code returned by the server.
566
* If SPOOL_RESPONSE is set, the request response will be cached to
567
* disk in a tmpfile (in full), then read back and parsed.
569
* Use POOL for any temporary allocation.
572
svn_ra_dav__parsed_request(ne_session *sess,
576
apr_file_t *body_file,
577
void set_parser (ne_xml_parser *parser,
579
ne_xml_startelm_cb *startelm_cb,
580
ne_xml_cdata_cb *cdata_cb,
581
ne_xml_endelm_cb *endelm_cb,
583
apr_hash_t *extra_headers,
585
svn_boolean_t spool_response,
589
/* Same as svn_ra_dav__parsed_request, except:
591
* ELEMENTS is the set of xml elements to recognize in the response.
593
* The callbacks VALIDATE_CB, STARTELM_CB, and ENDELM_CB, are written
594
* for the Neon <= 0.23 API.
597
svn_ra_dav__parsed_request_compat(ne_session *sess,
601
apr_file_t *body_file,
602
void set_parser (ne_xml_parser *parser,
604
const svn_ra_dav__xml_elm_t *elements,
605
svn_ra_dav__xml_validate_cb validate_cb,
606
svn_ra_dav__xml_startelm_cb startelm_cb,
607
svn_ra_dav__xml_endelm_cb endelm_cb,
609
apr_hash_t *extra_headers,
611
svn_boolean_t spool_response,
615
/* ### add SVN_RA_DAV_ to these to prefix conflicts with (sys) headers? */
617
/* Redefine Neon elements */
618
/* With the new API, we need to be able to use element id also as a return
619
* value from the new `startelm' callback, hence all element ids must be
620
* positive. Root element id is the only id that is not positive, it's zero.
621
* `Root state' is never returned by a callback, it's only passed into it.
622
* Therefore, negative element ids are forbidden from now on. */
623
ELEM_unknown = 1, /* was (-1), see above why it's (1) now */
624
ELEM_root = NE_XML_STATEROOT, /* (0) */
626
ELEM_207_first = ELEM_UNUSED,
627
ELEM_multistatus = ELEM_207_first,
628
ELEM_response = ELEM_207_first + 1,
629
ELEM_responsedescription = ELEM_207_first + 2,
630
ELEM_href = ELEM_207_first + 3,
631
ELEM_propstat = ELEM_207_first + 4,
632
ELEM_prop = ELEM_207_first + 5, /* `prop' tag in the DAV namespace */
633
ELEM_status = ELEM_207_first + 6,
634
ELEM_207_UNUSED = ELEM_UNUSED + 100,
635
ELEM_PROPS_UNUSED = ELEM_207_UNUSED + 100,
638
ELEM_activity_coll_set = ELEM_207_UNUSED,
645
ELEM_creator_displayname,
649
ELEM_options_response,
653
ELEM_get_content_length,
660
ELEM_absent_directory,
664
ELEM_baseline_relpath,
666
ELEM_deleted_path, /* used in log reports */
667
ELEM_replaced_path, /* used in log reports */
668
ELEM_added_path, /* used in log reports */
669
ELEM_modified_path, /* used in log reports */
679
ELEM_target_revision,
683
ELEM_SVN_prop, /* `prop' tag in the Subversion namespace */
684
ELEM_dated_rev_report,
685
ELEM_name_version_name,
686
ELEM_name_creationdate,
687
ELEM_name_creator_displayname,
690
ELEM_repository_uuid,
691
ELEM_get_locations_report,
693
ELEM_file_revs_report,
696
ELEM_get_locks_report,
702
ELEM_lock_creationdate,
703
ELEM_lock_expirationdate
707
svn_error_t * svn_ra_dav__merge_activity(
708
svn_revnum_t *new_rev,
709
const char **committed_date,
710
const char **committed_author,
711
svn_ra_dav__session_t *ras,
712
const char *repos_url,
713
const char *activity_url,
714
apr_hash_t *valid_targets,
715
apr_hash_t *lock_tokens,
716
svn_boolean_t keep_locks,
717
svn_boolean_t disable_merge_response,
721
/* Make a buffer for repeated use with svn_stringbuf_set().
722
### it would be nice to start this buffer with N bytes, but there isn't
723
### really a way to do that in the string interface (yet), short of
724
### initializing it with a fake string (and copying it) */
725
#define MAKE_BUFFER(p) svn_stringbuf_ncreate("", 0, (p))
727
void svn_ra_dav__copy_href(svn_stringbuf_t *dst, const char *src);
731
/* If RAS contains authentication info, attempt to store it via client
734
svn_ra_dav__maybe_store_auth_info (svn_ra_dav__session_t *ras);
737
/* Like svn_ra_dav__maybe_store_auth_info(), but conditional on ERR.
739
Attempt to store auth info only if ERR is NULL or if ERR->apr_err
740
is not SVN_ERR_RA_NOT_AUTHORIZED. If ERR is not null, return it no
741
matter what, otherwise return the result of the attempt (if any) to
742
store auth info, else return SVN_NO_ERROR. */
744
svn_ra_dav__maybe_store_auth_info_after_result(svn_error_t *err,
745
svn_ra_dav__session_t *ras);
748
/* Create an error object for an error from neon in the given session,
749
where the return code from neon was RETCODE, and CONTEXT describes
750
what was being attempted. Do temporary allocations in POOL. */
751
svn_error_t *svn_ra_dav__convert_error(ne_session *sess,
757
/* Given a neon REQUEST and SESSION, run the request; if CODE_P is
758
non-null, return the http status code in *CODE_P. Return any
759
resulting error (from neon, a <D:error> body response, or any
760
non-2XX status code) as an svn_error_t, otherwise return NULL.
761
The request will be freed either way.
763
SESSION, METHOD, and URL are required as well, as they are used to
764
describe the possible error. The error will be allocated in POOL.
766
OKAY_1 and OKAY_2 are the "acceptable" result codes. Anything other
767
than one of these will generate an error. OKAY_1 should always be
768
specified (e.g. as 200); use 0 for OKAY_2 if a second result code is
771
### not super sure on this "okay" stuff, but it means that the request
772
### dispatching code can generate much better errors than the callers
773
### when something goes wrong. if we need more than two, then we could
774
### add another param, switch to an array, or do something entirely
778
svn_ra_dav__request_dispatch(int *code_p,
788
/* Give PARSER the ability to parse a mod_dav_svn <D:error> response
789
body in the case of a non-2XX response to REQUEST. If a <D:error>
790
response is detected, then set *ERR to the parsed error.
793
svn_ra_dav__add_error_handler(ne_request *request,
794
ne_xml_parser *parser,
800
* Implements the get_locations RA layer function. */
802
svn_ra_dav__get_locations (svn_ra_session_t *session,
803
apr_hash_t **locations,
805
svn_revnum_t peg_revision,
806
apr_array_header_t *location_revisions,
811
* Implements the get_locks RA layer function. */
813
svn_ra_dav__get_locks(svn_ra_session_t *session,
819
* Implements the get_lock RA layer function. */
821
svn_ra_dav__get_lock(svn_ra_session_t *session,
827
/* Helper function. Loop over LOCK_TOKENS and assemble all keys and
828
values into a stringbuf allocated in POOL. The string will be of
831
<S:lock-token-list xmlns:S="svn:">
833
<S:lock-path>path</S:lock-path>
834
<S:lock-token>token</S:lock-token>
839
Callers can then send this in the request bodies, as a way of
840
reliably marshalling potentially unbounded lists of locks. (We do
841
this because httpd has limits on how much data can be sent in 'If:'
845
svn_ra_dav__assemble_locktoken_body(svn_stringbuf_t **body,
846
apr_hash_t *lock_tokens,
852
#endif /* __cplusplus */
854
#endif /* SVN_LIBSVN_RA_DAV_H */