ra_serf.h revision 251881
1/*
2 * ra_serf.h : Private declarations for the Serf-based DAV RA module.
3 *
4 * ====================================================================
5 *    Licensed to the Apache Software Foundation (ASF) under one
6 *    or more contributor license agreements.  See the NOTICE file
7 *    distributed with this work for additional information
8 *    regarding copyright ownership.  The ASF licenses this file
9 *    to you under the Apache License, Version 2.0 (the
10 *    "License"); you may not use this file except in compliance
11 *    with the License.  You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 *    Unless required by applicable law or agreed to in writing,
16 *    software distributed under the License is distributed on an
17 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 *    KIND, either express or implied.  See the License for the
19 *    specific language governing permissions and limitations
20 *    under the License.
21 * ====================================================================
22 */
23
24#ifndef SVN_LIBSVN_RA_SERF_RA_SERF_H
25#define SVN_LIBSVN_RA_SERF_RA_SERF_H
26
27
28#include <serf.h>
29#include <expat.h>  /* for XML_Parser  */
30#include <apr_uri.h>
31
32#include "svn_types.h"
33#include "svn_string.h"
34#include "svn_pools.h"
35#include "svn_ra.h"
36#include "svn_delta.h"
37#include "svn_version.h"
38#include "svn_dav.h"
39#include "svn_dirent_uri.h"
40
41#include "private/svn_dav_protocol.h"
42#include "private/svn_subr_private.h"
43#include "private/svn_editor.h"
44
45#include "blncache.h"
46
47#ifdef __cplusplus
48extern "C" {
49#endif /* __cplusplus */
50
51
52/* Enforce the minimum version of serf. */
53#if !SERF_VERSION_AT_LEAST(1, 2, 1)
54#error Please update your version of serf to at least 1.2.1.
55#endif
56
57/** Use this to silence compiler warnings about unused parameters. */
58#define UNUSED_CTX(x) ((void)(x))
59
60/** Our User-Agent string. */
61#define USER_AGENT "SVN/" SVN_VER_NUMBER " (" SVN_BUILD_TARGET ")" \
62                   " serf/" \
63                   APR_STRINGIFY(SERF_MAJOR_VERSION) "." \
64                   APR_STRINGIFY(SERF_MINOR_VERSION) "." \
65                   APR_STRINGIFY(SERF_PATCH_VERSION)
66
67/** Wait duration (in microseconds) used in calls to serf_context_run() */
68#define SVN_RA_SERF__CONTEXT_RUN_DURATION 500000
69
70
71
72/* Forward declarations. */
73typedef struct svn_ra_serf__session_t svn_ra_serf__session_t;
74
75/* A serf connection and optionally associated SSL context.  */
76typedef struct svn_ra_serf__connection_t {
77  /* Our connection to a server. */
78  serf_connection_t *conn;
79
80  /* Bucket allocator for this connection. */
81  serf_bucket_alloc_t *bkt_alloc;
82
83  /* Collected cert failures in chain.  */
84  int server_cert_failures;
85
86  /* What was the last HTTP status code we got on this connection? */
87  int last_status_code;
88
89  /* Optional SSL context for this connection. */
90  serf_ssl_context_t *ssl_context;
91  svn_auth_iterstate_t *ssl_client_auth_state;
92  svn_auth_iterstate_t *ssl_client_pw_auth_state;
93
94  svn_ra_serf__session_t *session;
95
96} svn_ra_serf__connection_t;
97
98/** Maximum value we'll allow for the http-max-connections config option.
99 *
100 * Note: minimum 2 connections are required for ra_serf to function
101 * correctly!
102 */
103#define SVN_RA_SERF__MAX_CONNECTIONS_LIMIT 8
104
105/*
106 * The master serf RA session.
107 *
108 * This is stored in the ra session ->priv field.
109 */
110struct svn_ra_serf__session_t {
111  /* Pool for allocations during this session */
112  apr_pool_t *pool;
113
114  /* The current context */
115  serf_context_t *context;
116
117  /* The maximum number of connections we'll use for parallelized
118     fetch operations (updates, etc.) */
119  apr_int64_t max_connections;
120
121  /* Are we using ssl */
122  svn_boolean_t using_ssl;
123
124  /* Should we ask for compressed responses? */
125  svn_boolean_t using_compression;
126
127  /* The user agent string */
128  const char *useragent;
129
130  /* The current connection */
131  svn_ra_serf__connection_t *conns[SVN_RA_SERF__MAX_CONNECTIONS_LIMIT];
132  int num_conns;
133  int cur_conn;
134
135  /* The URL that was passed into _open() */
136  apr_uri_t session_url;
137  const char *session_url_str;
138
139  /* The actual discovered root; may be NULL until we know it. */
140  apr_uri_t repos_root;
141  const char *repos_root_str;
142
143  /* The server is not Apache/mod_dav_svn (directly) and only supports
144     HTTP/1.0. Thus, we cannot send chunked requests.  */
145  svn_boolean_t http10;
146
147  /* Our Version-Controlled-Configuration; may be NULL until we know it. */
148  const char *vcc_url;
149
150  /* Authentication related properties. */
151  svn_auth_iterstate_t *auth_state;
152  int auth_attempts;
153
154  /* Callback functions to get info from WC */
155  const svn_ra_callbacks2_t *wc_callbacks;
156  void *wc_callback_baton;
157
158  /* Callback function to send progress info to the client */
159  svn_ra_progress_notify_func_t progress_func;
160  void *progress_baton;
161
162  /* Callback function to handle cancellation */
163  svn_cancel_func_t cancel_func;
164  void *cancel_baton;
165
166  /* Ev2 shim callbacks */
167  svn_delta_shim_callbacks_t *shim_callbacks;
168
169  /* Error that we've received but not yet returned upstream. */
170  svn_error_t *pending_error;
171
172  /* List of authn types supported by the client.*/
173  int authn_types;
174
175  /* Maps SVN_RA_CAPABILITY_foo keys to "yes" or "no" values.
176     If a capability is not yet discovered, it is absent from the table.
177     The table itself is allocated in the svn_ra_serf__session_t's pool;
178     keys and values must have at least that lifetime.  Most likely
179     the keys and values are constants anyway (and sufficiently
180     well-informed internal code may just compare against those
181     constants' addresses, therefore). */
182  apr_hash_t *capabilities;
183
184  /* Activity collection URL.  (Cached from the initial OPTIONS
185     request when run against HTTPv1 servers.)  */
186  const char *activity_collection_url;
187
188  /* Are we using a proxy? */
189  int using_proxy;
190
191  const char *proxy_username;
192  const char *proxy_password;
193  int proxy_auth_attempts;
194
195  /* SSL server certificates */
196  svn_boolean_t trust_default_ca;
197  const char *ssl_authorities;
198
199  /* Repository UUID */
200  const char *uuid;
201
202  /* Connection timeout value */
203  apr_interval_time_t timeout;
204
205  /* HTTPv1 flags */
206  svn_tristate_t supports_deadprop_count;
207
208  /*** HTTP v2 protocol stuff. ***
209   *
210   * We assume that if mod_dav_svn sends one of the special v2 OPTIONs
211   * response headers, it has sent all of them.  Specifically, we'll
212   * be looking at the presence of the "me resource" as a flag that
213   * the server supports v2 of our HTTP protocol.
214   */
215
216  /* The "me resource".  Typically used as a target for REPORTs that
217     are path-agnostic.  If we have this, we can speak HTTP v2 to the
218     server.  */
219  const char *me_resource;
220
221  /* Opaque URL "stubs".  If the OPTIONS response returns these, then
222     we know we're using HTTP protocol v2. */
223  const char *rev_stub;         /* for accessing revisions (i.e. revprops) */
224  const char *rev_root_stub;    /* for accessing REV/PATH pairs */
225  const char *txn_stub;         /* for accessing transactions (i.e. txnprops) */
226  const char *txn_root_stub;    /* for accessing TXN/PATH pairs */
227  const char *vtxn_stub;        /* for accessing transactions (i.e. txnprops) */
228  const char *vtxn_root_stub;   /* for accessing TXN/PATH pairs */
229
230  /* Hash mapping const char * server-supported POST types to
231     disinteresting-but-non-null values. */
232  apr_hash_t *supported_posts;
233
234  /*** End HTTP v2 stuff ***/
235
236  svn_ra_serf__blncache_t *blncache;
237
238  /* Trisate flag that indicates user preference for using bulk updates
239     (svn_tristate_true) with all the properties and content in the
240     update-report response. If svn_tristate_false, request a skelta
241     update-report with inlined properties. If svn_tristate_unknown then use
242     server preference. */
243  svn_tristate_t bulk_updates;
244
245  /* Indicates if the server wants bulk update requests (Prefer) or only
246     accepts skelta requests (Off). If this value is On both options are
247     allowed. */
248  const char *server_allows_bulk;
249
250  /* Indicates if the server supports sending inlined props in update editor
251   * in skelta mode (send-all == 'false'). */
252  svn_boolean_t supports_inline_props;
253
254  /* Indicates whether the server supports issuing replay REPORTs
255     against rev resources (children of `rev_stub', elsestruct). */
256  svn_boolean_t supports_rev_rsrc_replay;
257};
258
259#define SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(sess) ((sess)->me_resource != NULL)
260
261/*
262 * Structure which represents a DAV element with a NAMESPACE and NAME.
263 */
264typedef struct svn_ra_serf__dav_props_t {
265  /* Element namespace */
266  const char *namespace;
267  /* Element name */
268  const char *name;
269} svn_ra_serf__dav_props_t;
270
271/*
272 * Structure which represents an XML namespace.
273 */
274typedef struct ns_t {
275  /* The assigned name. */
276  const char *namespace;
277  /* The full URL for this namespace. */
278  const char *url;
279  /* The next namespace in our list. */
280  struct ns_t *next;
281} svn_ra_serf__ns_t;
282
283/*
284 * An incredibly simple list.
285 */
286typedef struct ra_serf_list_t {
287  void *data;
288  struct ra_serf_list_t *next;
289} svn_ra_serf__list_t;
290
291/** DAV property sets **/
292
293static const svn_ra_serf__dav_props_t base_props[] =
294{
295  { "DAV:", "version-controlled-configuration" },
296  { "DAV:", "resourcetype" },
297  { SVN_DAV_PROP_NS_DAV, "baseline-relative-path" },
298  { SVN_DAV_PROP_NS_DAV, "repository-uuid" },
299  { NULL }
300};
301
302static const svn_ra_serf__dav_props_t checked_in_props[] =
303{
304  { "DAV:", "checked-in" },
305  { NULL }
306};
307
308static const svn_ra_serf__dav_props_t baseline_props[] =
309{
310  { "DAV:", "baseline-collection" },
311  { "DAV:", SVN_DAV__VERSION_NAME },
312  { NULL }
313};
314
315static const svn_ra_serf__dav_props_t all_props[] =
316{
317  { "DAV:", "allprop" },
318  { NULL }
319};
320
321static const svn_ra_serf__dav_props_t check_path_props[] =
322{
323  { "DAV:", "resourcetype" },
324  { NULL }
325};
326
327static const svn_ra_serf__dav_props_t type_and_checksum_props[] =
328{
329  { "DAV:", "resourcetype" },
330  { SVN_DAV_PROP_NS_DAV, "sha1-checksum" },
331  { NULL }
332};
333
334/* WC props compatibility with ra_neon. */
335#define SVN_RA_SERF__WC_CHECKED_IN_URL SVN_PROP_WC_PREFIX "ra_dav:version-url"
336
337/** Serf utility functions **/
338
339apr_status_t
340svn_ra_serf__conn_setup(apr_socket_t *sock,
341                        serf_bucket_t **read_bkt,
342                        serf_bucket_t **write_bkt,
343                        void *baton,
344                        apr_pool_t *pool);
345
346void
347svn_ra_serf__conn_closed(serf_connection_t *conn,
348                         void *closed_baton,
349                         apr_status_t why,
350                         apr_pool_t *pool);
351
352
353/* Helper function to provide SSL client certificates.
354 *
355 * NOTE: This function sets the session's 'pending_error' member when
356 *       returning an non-success status.
357 */
358apr_status_t
359svn_ra_serf__handle_client_cert(void *data,
360                                const char **cert_path);
361
362/* Helper function to provide SSL client certificate passwords.
363 *
364 * NOTE: This function sets the session's 'pending_error' member when
365 *       returning an non-success status.
366 */
367apr_status_t
368svn_ra_serf__handle_client_cert_pw(void *data,
369                                   const char *cert_path,
370                                   const char **password);
371
372
373/*
374 * This function will run the serf context in SESS until *DONE is TRUE.
375 */
376svn_error_t *
377svn_ra_serf__context_run_wait(svn_boolean_t *done,
378                              svn_ra_serf__session_t *sess,
379                              apr_pool_t *scratch_pool);
380
381/* Callback for response handlers */
382typedef svn_error_t *
383(*svn_ra_serf__response_handler_t)(serf_request_t *request,
384                                   serf_bucket_t *response,
385                                   void *handler_baton,
386                                   apr_pool_t *scratch_pool);
387
388/* Callback for when a request body is needed. */
389/* ### should pass a scratch_pool  */
390typedef svn_error_t *
391(*svn_ra_serf__request_body_delegate_t)(serf_bucket_t **body_bkt,
392                                        void *baton,
393                                        serf_bucket_alloc_t *alloc,
394                                        apr_pool_t *request_pool);
395
396/* Callback for when request headers are needed. */
397/* ### should pass a scratch_pool  */
398typedef svn_error_t *
399(*svn_ra_serf__request_header_delegate_t)(serf_bucket_t *headers,
400                                          void *baton,
401                                          apr_pool_t *request_pool);
402
403/* Callback for when a response has an error. */
404typedef svn_error_t *
405(*svn_ra_serf__response_error_t)(serf_request_t *request,
406                                 serf_bucket_t *response,
407                                 int status_code,
408                                 void *baton);
409
410/* ### we should reorder the types in this file.  */
411typedef struct svn_ra_serf__server_error_t svn_ra_serf__server_error_t;
412
413/*
414 * Structure that can be passed to our default handler to guide the
415 * execution of the request through its lifecycle.
416 */
417typedef struct svn_ra_serf__handler_t {
418  /* The HTTP method string of the request */
419  const char *method;
420
421  /* The resource to the execute the method on. */
422  const char *path;
423
424  /* The content-type of the request body. */
425  const char *body_type;
426
427  /* If TRUE then default Accept-Encoding request header is not configured for
428     request. If FALSE then 'gzip' accept encoding will be used if compression
429     enabled. */
430  svn_boolean_t custom_accept_encoding;
431
432  /* Has the request/response been completed?  */
433  svn_boolean_t done;
434
435  /* If we captured an error from the server, then this will be non-NULL.
436     It will be allocated from HANDLER_POOL.  */
437  svn_ra_serf__server_error_t *server_error;
438
439  /* The handler and baton pair for our handler. */
440  svn_ra_serf__response_handler_t response_handler;
441  void *response_baton;
442
443  /* When REPONSE_HANDLER is invoked, the following fields will be set
444     based on the response header. HANDLER_POOL must be non-NULL for these
445     values to be filled in. SLINE.REASON and LOCATION will be allocated
446     within HANDLER_POOL.  */
447  serf_status_line sline;  /* The parsed Status-Line  */
448  const char *location;  /* The Location: header, if any  */
449
450  /* The handler and baton pair to be executed when a non-recoverable error
451   * is detected.  If it is NULL in the presence of an error, an abort() may
452   * be triggered.
453   */
454  svn_ra_serf__response_error_t response_error;
455  void *response_error_baton;
456
457  /* This function and baton pair allows for custom request headers to
458   * be set.
459   *
460   * It will be executed after the request has been set up but before it is
461   * delivered.
462   */
463  svn_ra_serf__request_header_delegate_t header_delegate;
464  void *header_delegate_baton;
465
466  /* This function and baton pair allows a body to be created right before
467   * delivery.
468   *
469   * It will be executed after the request has been set up but before it is
470   * delivered.
471   *
472   * May be NULL if there is no body to send.
473   *
474   */
475  svn_ra_serf__request_body_delegate_t body_delegate;
476  void *body_delegate_baton;
477
478  /* The connection and session to be used for this request. */
479  svn_ra_serf__connection_t *conn;
480  svn_ra_serf__session_t *session;
481
482  /* Internal flag to indicate we've parsed the headers.  */
483  svn_boolean_t reading_body;
484
485  /* When this flag will be set, the core handler will discard any unread
486     portion of the response body. The registered response handler will
487     no longer be called.  */
488  svn_boolean_t discard_body;
489
490  /* Pool for allocating SLINE.REASON and LOCATION. If this pool is NULL,
491     then the requestor does not care about SLINE and LOCATION.  */
492  apr_pool_t *handler_pool;
493
494} svn_ra_serf__handler_t;
495
496
497/* Run one request and process the response.
498
499   Similar to context_run_wait(), but this creates the request for HANDLER
500   and then waits for it to complete.
501
502   WARNING: context_run_wait() does NOT create a request, whereas this
503   function DOES. Avoid a double-create.  */
504svn_error_t *
505svn_ra_serf__context_run_one(svn_ra_serf__handler_t *handler,
506                             apr_pool_t *scratch_pool);
507
508
509/*
510 * Helper function to queue a request in the @a handler's connection.
511 */
512void svn_ra_serf__request_create(svn_ra_serf__handler_t *handler);
513
514/* XML helper callbacks. */
515
516typedef struct svn_ra_serf__xml_state_t {
517  /* A numeric value that represents the current state in parsing.
518   *
519   * Value 0 is reserved for use as the default state.
520   */
521  int current_state;
522
523  /* Private pointer set by the parsing code. */
524  void *private;
525
526  /* Allocations should be made in this pool to match the lifetime of the
527   * state.
528   */
529  apr_pool_t *pool;
530
531  /* The currently-declared namespace for this state. */
532  svn_ra_serf__ns_t *ns_list;
533
534  /* Our previous states. */
535  struct svn_ra_serf__xml_state_t *prev;
536} svn_ra_serf__xml_state_t;
537
538/* Forward declaration of the XML parser structure. */
539typedef struct svn_ra_serf__xml_parser_t svn_ra_serf__xml_parser_t;
540
541/* Callback invoked with @a baton by our XML @a parser when an element with
542 * the @a name containing @a attrs is opened.
543 */
544typedef svn_error_t *
545(*svn_ra_serf__xml_start_element_t)(svn_ra_serf__xml_parser_t *parser,
546                                    svn_ra_serf__dav_props_t name,
547                                    const char **attrs,
548                                    apr_pool_t *scratch_pool);
549
550/* Callback invoked with @a baton by our XML @a parser when an element with
551 * the @a name is closed.
552 */
553typedef svn_error_t *
554(*svn_ra_serf__xml_end_element_t)(svn_ra_serf__xml_parser_t *parser,
555                                  svn_ra_serf__dav_props_t name,
556                                  apr_pool_t *scratch_pool);
557
558/* Callback invoked with @a baton by our XML @a parser when a CDATA portion
559 * of @a data with size @a len is encountered.
560 *
561 * This may be invoked multiple times for the same tag.
562 */
563typedef svn_error_t *
564(*svn_ra_serf__xml_cdata_chunk_handler_t)(svn_ra_serf__xml_parser_t *parser,
565                                          const char *data,
566                                          apr_size_t len,
567                                          apr_pool_t *scratch_pool);
568
569/*
570 * Helper structure associated with handle_xml_parser handler that will
571 * specify how an XML response will be processed.
572 */
573struct svn_ra_serf__xml_parser_t {
574  /* Temporary allocations should be made in this pool. */
575  apr_pool_t *pool;
576
577  /* What kind of response are we parsing? If set, this should typically
578     define the report name.  */
579  const char *response_type;
580
581  /* Caller-specific data passed to the start, end, cdata callbacks.  */
582  void *user_data;
583
584  /* Callback invoked when a tag is opened. */
585  svn_ra_serf__xml_start_element_t start;
586
587  /* Callback invoked when a tag is closed. */
588  svn_ra_serf__xml_end_element_t end;
589
590  /* Callback invoked when a cdata chunk is received. */
591  svn_ra_serf__xml_cdata_chunk_handler_t cdata;
592
593  /* Our associated expat-based XML parser. */
594  XML_Parser xmlp;
595
596  /* Our current state. */
597  svn_ra_serf__xml_state_t *state;
598
599  /* Our previously used states (will be reused). */
600  svn_ra_serf__xml_state_t *free_state;
601
602  /* If non-NULL, this value will be set to TRUE when the response is
603   * completed.
604   */
605  svn_boolean_t *done;
606
607  /* If non-NULL, when this parser completes, it will add done_item to
608   * the list.
609   */
610  svn_ra_serf__list_t **done_list;
611
612  /* A pointer to the item that will be inserted into the list upon
613   * completeion.
614   */
615  svn_ra_serf__list_t *done_item;
616
617  /* If this flag is TRUE, errors during parsing will be ignored.
618   *
619   * This is mainly used when we are processing an error XML response to
620   * avoid infinite loops.
621   */
622  svn_boolean_t ignore_errors;
623
624  /* If an error occurred, this value will be non-NULL. */
625  svn_error_t *error;
626
627  /* Deciding whether to pause, or not, is performed within the parsing
628     callbacks. If a callback decides to set this flag, then the loop
629     driving the parse (generally, a series of calls to serf_context_run())
630     is going to need to coordinate the un-pausing of the parser by
631     processing pending content. Thus, deciding to pause the parser is a
632     coordinate effort rather than merely setting this flag.
633
634     When an XML parsing callback sets this flag, note that additional
635     elements may be parsed (as the current buffer is consumed). At some
636     point, the flag will be recognized and arriving network content will
637     be stashed away in the PENDING structure (see below).
638
639     At some point, the controlling loop should clear this value. The
640     underlying network processing will note the change and begin passing
641     content into the XML callbacks.
642
643     Note that the controlling loop should also process pending content
644     since the arriving network content will typically finish first.  */
645  svn_boolean_t paused;
646
647  /* While the XML parser is paused, content arriving from the server
648     must be saved locally. We cannot stop reading, or the server may
649     decide to drop the connection. The content will be stored in memory
650     up to a certain limit, and will then be spilled over to disk.
651
652     See libsvn_ra_serf/util.c  */
653  struct svn_ra_serf__pending_t *pending;
654
655  /* Response restart support */
656  const void *headers_baton; /* Last pointer to headers */
657  apr_off_t skip_size; /* Number of bytes to skip */
658  apr_off_t read_size; /* Number of bytes read from response */
659};
660
661
662/* v2 of the XML parsing functions  */
663
664/* The XML parsing context.  */
665typedef struct svn_ra_serf__xml_context_t svn_ra_serf__xml_context_t;
666
667
668/* An opaque structure for the XML parse element/state.  */
669typedef struct svn_ra_serf__xml_estate_t svn_ra_serf__xml_estate_t;
670
671/* Called just after the parser moves into ENTERED_STATE. The tag causing
672   the transition is passed in TAG.
673
674   This callback is applied to a parsing context by using the
675   svn_ra_serf__xml_context_customize() function.
676
677   NOTE: this callback, when set, will be invoked on *every* transition.
678   The callback must examine ENTERED_STATE to determine if any action
679   must be taken. The original state is not provided, but must be derived
680   from ENTERED_STATE and/or the TAG causing the transition (if needed).  */
681typedef svn_error_t *
682(*svn_ra_serf__xml_opened_t)(svn_ra_serf__xml_estate_t *xes,
683                             void *baton,
684                             int entered_state,
685                             const svn_ra_serf__dav_props_t *tag,
686                             apr_pool_t *scratch_pool);
687
688
689/* Called just before the parser leaves LEAVING_STATE.
690
691   If cdata collection was enabled for this state, then CDATA will be
692   non-NULL and contain the collected cdata.
693
694   If attribute collection was enabled for this state, then ATTRS will
695   contain the attributes collected for this element only, along with
696   any values stored via svn_ra_serf__xml_note().
697
698   Use svn_ra_serf__xml_gather_since() to gather up data from outer states.
699
700   ATTRS is char* -> char*.
701
702   Temporary allocations may be made in SCRATCH_POOL.  */
703typedef svn_error_t *
704(*svn_ra_serf__xml_closed_t)(svn_ra_serf__xml_estate_t *xes,
705                             void *baton,
706                             int leaving_state,
707                             const svn_string_t *cdata,
708                             apr_hash_t *attrs,
709                             apr_pool_t *scratch_pool);
710
711
712/* Called for all states that are not using the builtin cdata collection.
713   This callback is (only) appropriate for unbounded-size cdata content.
714
715   CURRENT_STATE may be used to decide what to do with the data.
716
717   Temporary allocations may be made in SCRATCH_POOL.  */
718typedef svn_error_t *
719(*svn_ra_serf__xml_cdata_t)(svn_ra_serf__xml_estate_t *xes,
720                            void *baton,
721                            int current_state,
722                            const char *data,
723                            apr_size_t len,
724                            apr_pool_t *scratch_pool);
725
726
727/* State transition table.
728
729   When the XML Context is constructed, it is in state 0. User states are
730   positive integers.
731
732   In a list of transitions, use { 0 } to indicate the end. Specifically,
733   the code looks for NS == NULL.
734
735   ### more docco
736*/
737typedef struct svn_ra_serf__xml_transition_t {
738  /* This transition applies when in this state  */
739  int from_state;
740
741  /* And when this tag is observed  */
742  const char *ns;
743  const char *name;
744
745  /* Moving to this state  */
746  int to_state;
747
748  /* Should the cdata of NAME be collected? Note that CUSTOM_CLOSE should
749     be TRUE in order to capture this cdata.  */
750  svn_boolean_t collect_cdata;
751
752  /* Which attributes of NAME should be collected? Terminate with NULL.
753     Maximum of 10 attributes may be collected. Note that attribute
754     namespaces are ignored at this time.
755
756     Attribute names beginning with "?" are optional. Other names must
757     exist on the element, or SVN_ERR_XML_ATTRIB_NOT_FOUND will be raised.  */
758  const char *collect_attrs[11];
759
760  /* When NAME is closed, should the callback be invoked?  */
761  svn_boolean_t custom_close;
762
763} svn_ra_serf__xml_transition_t;
764
765
766/* Construct an XML parsing context, based on the TTABLE transition table.
767   As content is parsed, the CLOSED_CB callback will be invoked according
768   to the definition in the table.
769
770   If OPENED_CB is not NULL, then it will be invoked for *every* tag-open
771   event. The callback will need to use the ENTERED_STATE and TAG parameters
772   to decide what it would like to do.
773
774   If CDATA_CB is not NULL, then it will be called for all cdata that is
775   not be automatically collected (based on the transition table record's
776   COLLECT_CDATA flag). It will be called in every state, so the callback
777   must examine the CURRENT_STATE parameter to decide what to do.
778
779   The same BATON value will be passed to all three callbacks.
780
781   The context will be created within RESULT_POOL.  */
782svn_ra_serf__xml_context_t *
783svn_ra_serf__xml_context_create(
784  const svn_ra_serf__xml_transition_t *ttable,
785  svn_ra_serf__xml_opened_t opened_cb,
786  svn_ra_serf__xml_closed_t closed_cb,
787  svn_ra_serf__xml_cdata_t cdata_cb,
788  void *baton,
789  apr_pool_t *result_pool);
790
791/* Destroy all subpools for this structure. */
792void
793svn_ra_serf__xml_context_destroy(
794  svn_ra_serf__xml_context_t *xmlctx);
795
796/* Construct a handler with the response function/baton set up to parse
797   a response body using the given XML context. The handler and its
798   internal structures are allocated in RESULT_POOL.
799
800   This also initializes HANDLER_POOL to the given RESULT_POOL.  */
801svn_ra_serf__handler_t *
802svn_ra_serf__create_expat_handler(svn_ra_serf__xml_context_t *xmlctx,
803                                  apr_pool_t *result_pool);
804
805
806/* Allocated within XES->STATE_POOL. Changes are not allowd (callers
807   should make a deep copy if they need to make changes).
808
809   The resulting hash maps char* names to char* values.  */
810apr_hash_t *
811svn_ra_serf__xml_gather_since(svn_ra_serf__xml_estate_t *xes,
812                              int stop_state);
813
814
815/* Attach the NAME/VALUE pair onto this/parent state identified by STATE.
816   The name and value will be copied into the target state's pool.
817
818   These values will be available to the CLOSED_CB for the target state,
819   or part of the gathered state via xml_gather_since().
820
821   Typically, this function is used by a child state's close callback,
822   or within an opening callback to store additional data.
823
824   Note: if the state is not found, then a programmer error has occurred,
825   so the function will invoke SVN_ERR_MALFUNCTION().  */
826void
827svn_ra_serf__xml_note(svn_ra_serf__xml_estate_t *xes,
828                      int state,
829                      const char *name,
830                      const char *value);
831
832
833/* Returns XES->STATE_POOL for allocating structures that should live
834   as long as the state identified by XES.
835
836   Note: a state pool is created upon demand, so only use this function
837   when memory is required for a given state.  */
838apr_pool_t *
839svn_ra_serf__xml_state_pool(svn_ra_serf__xml_estate_t *xes);
840
841
842/* Any XML parser may be used. When an opening tag is seen, call this
843   function to feed the information into XMLCTX.  */
844svn_error_t *
845svn_ra_serf__xml_cb_start(svn_ra_serf__xml_context_t *xmlctx,
846                          const char *raw_name,
847                          const char *const *attrs);
848
849
850/* When a close tag is seen, call this function to feed the information
851   into XMLCTX.  */
852svn_error_t *
853svn_ra_serf__xml_cb_end(svn_ra_serf__xml_context_t *xmlctx,
854                        const char *raw_name);
855
856
857/* When cdata is parsed by the wrapping XML parser, call this function to
858   feed the cdata into the XMLCTX.  */
859svn_error_t *
860svn_ra_serf__xml_cb_cdata(svn_ra_serf__xml_context_t *xmlctx,
861                          const char *data,
862                          apr_size_t len);
863
864
865/*
866 * Parses a server-side error message into a local Subversion error.
867 */
868struct svn_ra_serf__server_error_t {
869  /* Our local representation of the error. */
870  svn_error_t *error;
871
872  /* Are we done with the response? */
873  svn_boolean_t done;
874
875  /* Have we seen an error tag? */
876  svn_boolean_t in_error;
877
878  /* Have we seen a HTTP "412 Precondition Failed" error? */
879  svn_boolean_t contains_precondition_error;
880
881  /* Should we be collecting the XML cdata? */
882  svn_boolean_t collect_cdata;
883
884  /* Collected cdata. NULL if cdata not needed. */
885  svn_stringbuf_t *cdata;
886
887  /* XML parser and namespace used to parse the remote response */
888  svn_ra_serf__xml_parser_t parser;
889};
890
891
892/*
893 * Handler that discards the entire @a response body associated with a
894 * @a request.  Implements svn_ra_serf__response_handler_t.
895 *
896 * If @a baton is a svn_ra_serf__server_error_t (i.e. non-NULL) and an
897 * error is detected, it will be populated for later detection.
898 *
899 * All temporary allocations will be made in a @a pool.
900 */
901svn_error_t *
902svn_ra_serf__handle_discard_body(serf_request_t *request,
903                                 serf_bucket_t *response,
904                                 void *baton,
905                                 apr_pool_t *pool);
906
907
908/*
909 * Handler that retrieves the embedded XML multistatus response from the
910 * the @a RESPONSE body associated with a @a REQUEST.
911 *
912 * Implements svn_ra_serf__response_handler_t.
913 *
914 * The @a BATON should be of type svn_ra_serf__handler_t. When the request
915 * is complete, the handler's DONE flag will be set to TRUE.
916 *
917 * All temporary allocations will be made in a @a scratch_pool.
918 */
919svn_error_t *
920svn_ra_serf__handle_multistatus_only(serf_request_t *request,
921                                     serf_bucket_t *response,
922                                     void *baton,
923                                     apr_pool_t *scratch_pool);
924
925
926/* Handler that expects an empty body.
927
928   If a body IS present, and it is text/xml, then it will be parsed for
929   a server-side error.
930
931   BATON should be the svn_ra_serf__handler_t running REQUEST.
932
933   Status line information will be in HANDLER->SLINE.
934
935   Any parsed errors will be left in HANDLER->SERVER_ERROR. That member
936   may be NULL if no body was present, or a problem occurred trying to
937   parse the body.
938
939   All temporary allocations will be made in SCRATCH_POOL.  */
940svn_error_t *
941svn_ra_serf__expect_empty_body(serf_request_t *request,
942                               serf_bucket_t *response,
943                               void *baton,
944                               apr_pool_t *scratch_pool);
945
946
947/*
948 * This function will feed the RESPONSE body into XMLP.  When parsing is
949 * completed (i.e. an EOF is received), *DONE is set to TRUE.
950 * Implements svn_ra_serf__response_handler_t.
951 *
952 * If an error occurs during processing RESP_ERR is invoked with the
953 * RESP_ERR_BATON.
954 *
955 * Temporary allocations are made in POOL.
956 */
957svn_error_t *
958svn_ra_serf__handle_xml_parser(serf_request_t *request,
959                               serf_bucket_t *response,
960                               void *handler_baton,
961                               apr_pool_t *pool);
962
963/* serf_response_handler_t implementation that completely discards
964 * the response.
965 *
966 * All temporary allocations will be made in @a pool.
967 */
968apr_status_t
969svn_ra_serf__response_discard_handler(serf_request_t *request,
970                                      serf_bucket_t *response,
971                                      void *baton,
972                                      apr_pool_t *pool);
973
974
975/** XML helper functions. **/
976
977/*
978 * Advance the internal XML @a parser to the @a state.
979 */
980void
981svn_ra_serf__xml_push_state(svn_ra_serf__xml_parser_t *parser,
982                            int state);
983
984/*
985 * Return to the previous internal XML @a parser state.
986 */
987void
988svn_ra_serf__xml_pop_state(svn_ra_serf__xml_parser_t *parser);
989
990
991svn_error_t *
992svn_ra_serf__process_pending(svn_ra_serf__xml_parser_t *parser,
993                             svn_boolean_t *network_eof,
994                             apr_pool_t *scratch_pool);
995
996
997/*
998 * Add the appropriate serf buckets to @a agg_bucket represented by
999 * the XML * @a tag and @a value.
1000 *
1001 * The bucket will be allocated from @a bkt_alloc.
1002 */
1003void
1004svn_ra_serf__add_tag_buckets(serf_bucket_t *agg_bucket,
1005                             const char *tag,
1006                             const char *value,
1007                             serf_bucket_alloc_t *bkt_alloc);
1008
1009/*
1010 * Add the appropriate serf buckets to AGG_BUCKET with standard XML header:
1011 *  <?xml version="1.0" encoding="utf-8"?>
1012 *
1013 * The bucket will be allocated from BKT_ALLOC.
1014 */
1015void
1016svn_ra_serf__add_xml_header_buckets(serf_bucket_t *agg_bucket,
1017                                    serf_bucket_alloc_t *bkt_alloc);
1018
1019/*
1020 * Add the appropriate serf buckets to AGG_BUCKET representing the XML
1021 * open tag with name TAG.
1022 *
1023 * Take the tag's attributes from varargs, a NULL-terminated list of
1024 * alternating <tt>char *</tt> key and <tt>char *</tt> val.  Attribute
1025 * will be ignored if it's value is NULL.
1026 *
1027 * NOTE: Callers are responsible for XML-escaping attribute values as
1028 * necessary.
1029 *
1030 * The bucket will be allocated from BKT_ALLOC.
1031 */
1032void
1033svn_ra_serf__add_open_tag_buckets(serf_bucket_t *agg_bucket,
1034                                  serf_bucket_alloc_t *bkt_alloc,
1035                                  const char *tag,
1036                                  ...);
1037
1038/*
1039 * Add the appropriate serf buckets to AGG_BUCKET representing xml tag close
1040 * with name TAG.
1041 *
1042 * The bucket will be allocated from BKT_ALLOC.
1043 */
1044void
1045svn_ra_serf__add_close_tag_buckets(serf_bucket_t *agg_bucket,
1046                                   serf_bucket_alloc_t *bkt_alloc,
1047                                   const char *tag);
1048
1049/*
1050 * Add the appropriate serf buckets to AGG_BUCKET with xml-escaped
1051 * version of DATA.
1052 *
1053 * The bucket will be allocated from BKT_ALLOC.
1054 */
1055void
1056svn_ra_serf__add_cdata_len_buckets(serf_bucket_t *agg_bucket,
1057                                   serf_bucket_alloc_t *bkt_alloc,
1058                                   const char *data, apr_size_t len);
1059/*
1060 * Look up the @a attrs array for namespace definitions and add each one
1061 * to the @a ns_list of namespaces.
1062 *
1063 * New namespaces will be allocated in RESULT_POOL.
1064 */
1065void
1066svn_ra_serf__define_ns(svn_ra_serf__ns_t **ns_list,
1067                       const char *const *attrs,
1068                       apr_pool_t *result_pool);
1069
1070/*
1071 * Look up @a name in the @a ns_list list for previously declared namespace
1072 * definitions.
1073 *
1074 * Return (in @a *returned_prop_name) a #svn_ra_serf__dav_props_t tuple
1075 * representing the expanded name.
1076 */
1077void
1078svn_ra_serf__expand_ns(svn_ra_serf__dav_props_t *returned_prop_name,
1079                       const svn_ra_serf__ns_t *ns_list,
1080                       const char *name);
1081
1082
1083/** PROPFIND-related functions **/
1084
1085/*
1086 * This function will deliver a PROP_CTX PROPFIND request in the SESS
1087 * serf context for the properties listed in LOOKUP_PROPS at URL for
1088 * DEPTH ("0","1","infinity").
1089 *
1090 * This function will not block waiting for the response. Callers are
1091 * expected to call svn_ra_serf__wait_for_props().
1092 */
1093svn_error_t *
1094svn_ra_serf__deliver_props(svn_ra_serf__handler_t **propfind_handler,
1095                           apr_hash_t *prop_vals,
1096                           svn_ra_serf__session_t *sess,
1097                           svn_ra_serf__connection_t *conn,
1098                           const char *url,
1099                           svn_revnum_t rev,
1100                           const char *depth,
1101                           const svn_ra_serf__dav_props_t *lookup_props,
1102                           svn_ra_serf__list_t **done_list,
1103                           apr_pool_t *pool);
1104
1105/*
1106 * This helper function will block until PROPFIND_HANDLER indicates that is
1107 * done or another error is returned.
1108 */
1109svn_error_t *
1110svn_ra_serf__wait_for_props(svn_ra_serf__handler_t *handler,
1111                            apr_pool_t *scratch_pool);
1112
1113/* This is a blocking version of deliver_props.
1114
1115   The properties are fetched and placed into RESULTS, allocated in
1116   RESULT_POOL.
1117
1118   ### more docco about the other params.
1119
1120   Temporary allocations are made in SCRATCH_POOL.
1121*/
1122svn_error_t *
1123svn_ra_serf__retrieve_props(apr_hash_t **results,
1124                            svn_ra_serf__session_t *sess,
1125                            svn_ra_serf__connection_t *conn,
1126                            const char *url,
1127                            svn_revnum_t rev,
1128                            const char *depth,
1129                            const svn_ra_serf__dav_props_t *props,
1130                            apr_pool_t *result_pool,
1131                            apr_pool_t *scratch_pool);
1132
1133
1134/* Using CONN, fetch the properties specified by WHICH_PROPS using CONN
1135   for URL at REVISION. The resulting properties are placed into a 2-level
1136   hash in RESULTS, mapping NAMESPACE -> hash<PROPNAME, PROPVALUE>, which
1137   is allocated in RESULT_POOL.
1138
1139   If REVISION is SVN_INVALID_REVNUM, then the properties are fetched
1140   from HEAD for URL.
1141
1142   This function performs the request synchronously.
1143
1144   Temporary allocations are made in SCRATCH_POOL.  */
1145svn_error_t *
1146svn_ra_serf__fetch_node_props(apr_hash_t **results,
1147                              svn_ra_serf__connection_t *conn,
1148                              const char *url,
1149                              svn_revnum_t revision,
1150                              const svn_ra_serf__dav_props_t *which_props,
1151                              apr_pool_t *result_pool,
1152                              apr_pool_t *scratch_pool);
1153
1154
1155/* Using CONN, fetch a DAV: property from the resource identified by URL
1156   within REVISION. The PROPNAME may be one of:
1157
1158     "checked-in"
1159     "href"
1160
1161   The resulting value will be allocated in RESULT_POOL, and may be NULL
1162   if the property does not exist (note: "href" always exists).
1163
1164   This function performs the request synchronously.
1165
1166   Temporary allocations are made in SCRATCH_POOL.  */
1167svn_error_t *
1168svn_ra_serf__fetch_dav_prop(const char **value,
1169                            svn_ra_serf__connection_t *conn,
1170                            const char *url,
1171                            svn_revnum_t revision,
1172                            const char *propname,
1173                            apr_pool_t *result_pool,
1174                            apr_pool_t *scratch_pool);
1175
1176
1177/* Set PROPS for PATH at REV revision with a NS:NAME VAL.
1178 *
1179 * The POOL governs allocation.
1180 */
1181void
1182svn_ra_serf__set_ver_prop(apr_hash_t *props,
1183                          const char *path, svn_revnum_t rev,
1184                          const char *ns, const char *name,
1185                          const svn_string_t *val, apr_pool_t *pool);
1186#define svn_ra_serf__set_rev_prop svn_ra_serf__set_ver_prop
1187
1188/** Property walker functions **/
1189
1190typedef svn_error_t *
1191(*svn_ra_serf__walker_visitor_t)(void *baton,
1192                                 const char *ns,
1193                                 const char *name,
1194                                 const svn_string_t *val,
1195                                 apr_pool_t *pool);
1196
1197svn_error_t *
1198svn_ra_serf__walk_all_props(apr_hash_t *props,
1199                            const char *name,
1200                            svn_revnum_t rev,
1201                            svn_ra_serf__walker_visitor_t walker,
1202                            void *baton,
1203                            apr_pool_t *pool);
1204
1205
1206/* Like walk_all_props(), but a 2-level hash.  */
1207svn_error_t *
1208svn_ra_serf__walk_node_props(apr_hash_t *props,
1209                             svn_ra_serf__walker_visitor_t walker,
1210                             void *baton,
1211                             apr_pool_t *scratch_pool);
1212
1213
1214typedef svn_error_t *
1215(*svn_ra_serf__path_rev_walker_t)(void *baton,
1216                                  const char *path, apr_ssize_t path_len,
1217                                  const char *ns, apr_ssize_t ns_len,
1218                                  const char *name, apr_ssize_t name_len,
1219                                  const svn_string_t *val,
1220                                  apr_pool_t *pool);
1221svn_error_t *
1222svn_ra_serf__walk_all_paths(apr_hash_t *props,
1223                            svn_revnum_t rev,
1224                            svn_ra_serf__path_rev_walker_t walker,
1225                            void *baton,
1226                            apr_pool_t *pool);
1227
1228
1229/* Map a property name, as passed over the wire, into its corresponding
1230   Subversion-internal name. The returned name will be a static value,
1231   or allocated within RESULT_POOL.
1232
1233   If the property should be ignored (eg. some DAV properties), then NULL
1234   will be returned.  */
1235const char *
1236svn_ra_serf__svnname_from_wirename(const char *ns,
1237                                   const char *name,
1238                                   apr_pool_t *result_pool);
1239
1240
1241/* Select the basic revision properties from the set of "all" properties.
1242   Return these in *REVPROPS, allocated from RESULT_POOL.  */
1243svn_error_t *
1244svn_ra_serf__select_revprops(apr_hash_t **revprops,
1245                             const char *name,
1246                             svn_revnum_t rev,
1247                             apr_hash_t *all_revprops,
1248                             apr_pool_t *result_pool,
1249                             apr_pool_t *scratch_pool);
1250
1251
1252/* PROPS is nested hash tables mapping NS -> NAME -> VALUE.
1253   This function takes the NS:NAME:VALUE hashes and flattens them into a set of
1254   names to VALUE. The names are composed of NS:NAME, with specific
1255   rewrite from wire names (DAV) to SVN names. This mapping is managed
1256   by the svn_ra_serf__set_baton_props() function.
1257
1258   FLAT_PROPS is allocated in RESULT_POOL.
1259   ### right now, we do a shallow copy from PROPS to FLAT_PROPS. therefore,
1260   ### the names and values in PROPS must be in the proper pool.
1261
1262   Temporary allocations are made in SCRATCH_POOL.  */
1263svn_error_t *
1264svn_ra_serf__flatten_props(apr_hash_t **flat_props,
1265                           apr_hash_t *props,
1266                           apr_pool_t *result_pool,
1267                           apr_pool_t *scratch_pool);
1268
1269
1270/* Return the property value for PATH at REV revision with a NS:NAME.
1271 * PROPS is a four-level nested hash: (svn_revnum_t => char *path =>
1272 * char *ns => char *name => svn_string_t *). */
1273const svn_string_t *
1274svn_ra_serf__get_ver_prop_string(apr_hash_t *props,
1275                                 const char *path, svn_revnum_t rev,
1276                                 const char *ns, const char *name);
1277
1278/* Same as svn_ra_serf__get_ver_prop_string(), but returns a C string. */
1279const char *
1280svn_ra_serf__get_ver_prop(apr_hash_t *props,
1281                          const char *path, svn_revnum_t rev,
1282                          const char *ns, const char *name);
1283
1284/* Same as svn_ra_serf__get_ver_prop_string(), but for the unknown revision. */
1285const svn_string_t *
1286svn_ra_serf__get_prop_string(apr_hash_t *props,
1287                             const char *path,
1288                             const char *ns,
1289                             const char *name);
1290
1291/* Same as svn_ra_serf__get_ver_prop(), but for the unknown revision. */
1292const char *
1293svn_ra_serf__get_prop(apr_hash_t *props,
1294                      const char *path,
1295                      const char *ns,
1296                      const char *name);
1297
1298/* Same as svn_ra_serf__set_rev_prop(), but for the unknown revision. */
1299void
1300svn_ra_serf__set_prop(apr_hash_t *props, const char *path,
1301                      const char *ns, const char *name,
1302                      const svn_string_t *val, apr_pool_t *pool);
1303
1304svn_error_t *
1305svn_ra_serf__get_resource_type(svn_node_kind_t *kind,
1306                               apr_hash_t *props);
1307
1308
1309/** MERGE-related functions **/
1310
1311void
1312svn_ra_serf__merge_lock_token_list(apr_hash_t *lock_tokens,
1313                                   const char *parent,
1314                                   serf_bucket_t *body,
1315                                   serf_bucket_alloc_t *alloc,
1316                                   apr_pool_t *pool);
1317
1318/* Create an MERGE request aimed at the SESSION url, requesting the
1319   merge of the resource identified by MERGE_RESOURCE_URL.
1320   LOCK_TOKENS is a hash mapping paths to lock tokens owned by the
1321   client.  If KEEP_LOCKS is set, instruct the server to not release
1322   locks set on the paths included in this commit.  */
1323svn_error_t *
1324svn_ra_serf__run_merge(const svn_commit_info_t **commit_info,
1325                       int *response_code,
1326                       svn_ra_serf__session_t *session,
1327                       svn_ra_serf__connection_t *conn,
1328                       const char *merge_resource_url,
1329                       apr_hash_t *lock_tokens,
1330                       svn_boolean_t keep_locks,
1331                       apr_pool_t *result_pool,
1332                       apr_pool_t *scratch_pool);
1333
1334
1335/** OPTIONS-related functions **/
1336
1337/* On HTTPv2 connections, run an OPTIONS request over CONN to fetch the
1338   current youngest revnum, returning it in *YOUNGEST.
1339
1340   (the revnum is headers of the OPTIONS response)
1341
1342   This function performs the request synchronously.
1343
1344   All temporary allocations will be made in SCRATCH_POOL.  */
1345svn_error_t *
1346svn_ra_serf__v2_get_youngest_revnum(svn_revnum_t *youngest,
1347                                    svn_ra_serf__connection_t *conn,
1348                                    apr_pool_t *scratch_pool);
1349
1350
1351/* On HTTPv1 connections, run an OPTIONS request over CONN to fetch the
1352   activity collection set and return it in *ACTIVITY_URL, allocated
1353   from RESULT_POOL.
1354
1355   (the activity-collection-set is in the body of the OPTIONS response)
1356
1357   This function performs the request synchronously.
1358
1359   All temporary allocations will be made in SCRATCH_POOL.  */
1360svn_error_t *
1361svn_ra_serf__v1_get_activity_collection(const char **activity_url,
1362                                        svn_ra_serf__connection_t *conn,
1363                                        apr_pool_t *result_pool,
1364                                        apr_pool_t *scratch_pool);
1365
1366
1367/* Set @a VCC_URL to the default VCC for our repository based on @a
1368 * ORIG_PATH for the session @a SESSION, ensuring that the VCC URL and
1369 * repository root URLs are cached in @a SESSION.  Use @a CONN for any
1370 * required network communications if it is non-NULL; otherwise use the
1371 * default connection.
1372 *
1373 * All temporary allocations will be made in @a POOL. */
1374svn_error_t *
1375svn_ra_serf__discover_vcc(const char **vcc_url,
1376                          svn_ra_serf__session_t *session,
1377                          svn_ra_serf__connection_t *conn,
1378                          apr_pool_t *pool);
1379
1380/* Set @a REPORT_TARGET to the URI of the resource at which generic
1381 * (path-agnostic) REPORTs should be aimed for @a SESSION.  Use @a
1382 * CONN for any required network communications if it is non-NULL;
1383 * otherwise use the default connection.
1384 *
1385 * All temporary allocations will be made in @a POOL.
1386 */
1387svn_error_t *
1388svn_ra_serf__report_resource(const char **report_target,
1389                             svn_ra_serf__session_t *session,
1390                             svn_ra_serf__connection_t *conn,
1391                             apr_pool_t *pool);
1392
1393/* Set @a REL_PATH to a path (not URI-encoded) relative to the root of
1394 * the repository pointed to by @a SESSION, based on original path
1395 * (URI-encoded) @a ORIG_PATH.  Use @a CONN for any required network
1396 * communications if it is non-NULL; otherwise use the default
1397 * connection.  Use POOL for allocations.  */
1398svn_error_t *
1399svn_ra_serf__get_relative_path(const char **rel_path,
1400                               const char *orig_path,
1401                               svn_ra_serf__session_t *session,
1402                               svn_ra_serf__connection_t *conn,
1403                               apr_pool_t *pool);
1404
1405
1406/* Using the default connection in SESSION (conns[0]), get the youngest
1407   revnum from the server, returning it in *YOUNGEST.
1408
1409   This function operates synchronously.
1410
1411   All temporary allocations are performed in SCRATCH_POOL.  */
1412svn_error_t *
1413svn_ra_serf__get_youngest_revnum(svn_revnum_t *youngest,
1414                                 svn_ra_serf__session_t *session,
1415                                 apr_pool_t *scratch_pool);
1416
1417
1418/* Generate a revision-stable URL.
1419
1420   The RA APIs all refer to user/public URLs that float along with the
1421   youngest revision. In many cases, we do NOT want to work with that URL
1422   since it can change from one moment to the next. Especially if we
1423   attempt to operation against multiple floating URLs -- we could end up
1424   referring to two separate revisions.
1425
1426   The DAV RA provider(s) solve this by generating a URL that is specific
1427   to a revision by using a URL into a "baseline collection".
1428
1429   For a specified SESSION, with an optional CONN (if NULL, then the
1430   session's default connection will be used; specifically SESSION->conns[0]),
1431   generate a revision-stable URL for URL at REVISION. If REVISION is
1432   SVN_INVALID_REVNUM, then the stable URL will refer to the youngest
1433   revision at the time this function was called.
1434
1435   If URL is NULL, then the session root will be used.
1436
1437   The stable URL will be placed into *STABLE_URL, allocated from RESULT_POOL.
1438
1439   If LATEST_REVNUM is not NULL, then the revision used will be placed into
1440   *LATEST_REVNUM. That will be equal to youngest, or the given REVISION.
1441
1442   This function operates synchronously, if any communication to the server
1443   is required. Communication is needed if REVISION is SVN_INVALID_REVNUM
1444   (to get the current youngest revnum), or if the specified REVISION is not
1445   (yet) in our cache of baseline collections.
1446
1447   All temporary allocations are performed in SCRATCH_POOL.  */
1448svn_error_t *
1449svn_ra_serf__get_stable_url(const char **stable_url,
1450                            svn_revnum_t *latest_revnum,
1451                            svn_ra_serf__session_t *session,
1452                            svn_ra_serf__connection_t *conn,
1453                            const char *url,
1454                            svn_revnum_t revision,
1455                            apr_pool_t *result_pool,
1456                            apr_pool_t *scratch_pool);
1457
1458
1459/** RA functions **/
1460
1461/* Implements svn_ra__vtable_t.get_log(). */
1462svn_error_t *
1463svn_ra_serf__get_log(svn_ra_session_t *session,
1464                     const apr_array_header_t *paths,
1465                     svn_revnum_t start,
1466                     svn_revnum_t end,
1467                     int limit,
1468                     svn_boolean_t discover_changed_paths,
1469                     svn_boolean_t strict_node_history,
1470                     svn_boolean_t include_merged_revisions,
1471                     const apr_array_header_t *revprops,
1472                     svn_log_entry_receiver_t receiver,
1473                     void *receiver_baton,
1474                     apr_pool_t *pool);
1475
1476/* Implements svn_ra__vtable_t.get_locations(). */
1477svn_error_t *
1478svn_ra_serf__get_locations(svn_ra_session_t *session,
1479                           apr_hash_t **locations,
1480                           const char *path,
1481                           svn_revnum_t peg_revision,
1482                           const apr_array_header_t *location_revisions,
1483                           apr_pool_t *pool);
1484
1485/* Implements svn_ra__vtable_t.get_location_segments(). */
1486svn_error_t *
1487svn_ra_serf__get_location_segments(svn_ra_session_t *session,
1488                                   const char *path,
1489                                   svn_revnum_t peg_revision,
1490                                   svn_revnum_t start_rev,
1491                                   svn_revnum_t end_rev,
1492                                   svn_location_segment_receiver_t receiver,
1493                                   void *receiver_baton,
1494                                   apr_pool_t *pool);
1495
1496/* Implements svn_ra__vtable_t.do_diff(). */
1497svn_error_t *
1498svn_ra_serf__do_diff(svn_ra_session_t *session,
1499                     const svn_ra_reporter3_t **reporter,
1500                     void **report_baton,
1501                     svn_revnum_t revision,
1502                     const char *diff_target,
1503                     svn_depth_t depth,
1504                     svn_boolean_t ignore_ancestry,
1505                     svn_boolean_t text_deltas,
1506                     const char *versus_url,
1507                     const svn_delta_editor_t *diff_editor,
1508                     void *diff_baton,
1509                     apr_pool_t *pool);
1510
1511/* Implements svn_ra__vtable_t.do_status(). */
1512svn_error_t *
1513svn_ra_serf__do_status(svn_ra_session_t *ra_session,
1514                       const svn_ra_reporter3_t **reporter,
1515                       void **report_baton,
1516                       const char *status_target,
1517                       svn_revnum_t revision,
1518                       svn_depth_t depth,
1519                       const svn_delta_editor_t *status_editor,
1520                       void *status_baton,
1521                       apr_pool_t *pool);
1522
1523/* Implements svn_ra__vtable_t.do_update(). */
1524svn_error_t *
1525svn_ra_serf__do_update(svn_ra_session_t *ra_session,
1526                       const svn_ra_reporter3_t **reporter,
1527                       void **report_baton,
1528                       svn_revnum_t revision_to_update_to,
1529                       const char *update_target,
1530                       svn_depth_t depth,
1531                       svn_boolean_t send_copyfrom_args,
1532                       svn_boolean_t ignore_ancestry,
1533                       const svn_delta_editor_t *update_editor,
1534                       void *update_baton,
1535                       apr_pool_t *result_pool,
1536                       apr_pool_t *scratch_pool);
1537
1538/* Implements svn_ra__vtable_t.do_switch(). */
1539svn_error_t *
1540svn_ra_serf__do_switch(svn_ra_session_t *ra_session,
1541                       const svn_ra_reporter3_t **reporter,
1542                       void **report_baton,
1543                       svn_revnum_t revision_to_switch_to,
1544                       const char *switch_target,
1545                       svn_depth_t depth,
1546                       const char *switch_url,
1547                       svn_boolean_t send_copyfrom_args,
1548                       svn_boolean_t ignore_ancestry,
1549                       const svn_delta_editor_t *switch_editor,
1550                       void *switch_baton,
1551                       apr_pool_t *result_pool,
1552                       apr_pool_t *scratch_pool);
1553
1554/* Implements svn_ra__vtable_t.get_file_revs(). */
1555svn_error_t *
1556svn_ra_serf__get_file_revs(svn_ra_session_t *session,
1557                           const char *path,
1558                           svn_revnum_t start,
1559                           svn_revnum_t end,
1560                           svn_boolean_t include_merged_revisions,
1561                           svn_file_rev_handler_t handler,
1562                           void *handler_baton,
1563                           apr_pool_t *pool);
1564
1565/* Implements svn_ra__vtable_t.get_dated_revision(). */
1566svn_error_t *
1567svn_ra_serf__get_dated_revision(svn_ra_session_t *session,
1568                                svn_revnum_t *revision,
1569                                apr_time_t tm,
1570                                apr_pool_t *pool);
1571
1572/* Implements svn_ra__vtable_t.get_commit_editor(). */
1573svn_error_t *
1574svn_ra_serf__get_commit_editor(svn_ra_session_t *session,
1575                               const svn_delta_editor_t **editor,
1576                               void **edit_baton,
1577                               apr_hash_t *revprop_table,
1578                               svn_commit_callback2_t callback,
1579                               void *callback_baton,
1580                               apr_hash_t *lock_tokens,
1581                               svn_boolean_t keep_locks,
1582                               apr_pool_t *pool);
1583
1584/* Implements svn_ra__vtable_t.get_file(). */
1585svn_error_t *
1586svn_ra_serf__get_file(svn_ra_session_t *session,
1587                      const char *path,
1588                      svn_revnum_t revision,
1589                      svn_stream_t *stream,
1590                      svn_revnum_t *fetched_rev,
1591                      apr_hash_t **props,
1592                      apr_pool_t *pool);
1593
1594/* Implements svn_ra__vtable_t.change_rev_prop(). */
1595svn_error_t *
1596svn_ra_serf__change_rev_prop(svn_ra_session_t *session,
1597                             svn_revnum_t rev,
1598                             const char *name,
1599                             const svn_string_t *const *old_value_p,
1600                             const svn_string_t *value,
1601                             apr_pool_t *pool);
1602
1603/* Implements svn_ra__vtable_t.replay(). */
1604svn_error_t *
1605svn_ra_serf__replay(svn_ra_session_t *ra_session,
1606                    svn_revnum_t revision,
1607                    svn_revnum_t low_water_mark,
1608                    svn_boolean_t text_deltas,
1609                    const svn_delta_editor_t *editor,
1610                    void *edit_baton,
1611                    apr_pool_t *pool);
1612
1613/* Implements svn_ra__vtable_t.replay_range(). */
1614svn_error_t *
1615svn_ra_serf__replay_range(svn_ra_session_t *ra_session,
1616                          svn_revnum_t start_revision,
1617                          svn_revnum_t end_revision,
1618                          svn_revnum_t low_water_mark,
1619                          svn_boolean_t send_deltas,
1620                          svn_ra_replay_revstart_callback_t revstart_func,
1621                          svn_ra_replay_revfinish_callback_t revfinish_func,
1622                          void *replay_baton,
1623                          apr_pool_t *pool);
1624
1625/* Implements svn_ra__vtable_t.lock(). */
1626svn_error_t *
1627svn_ra_serf__lock(svn_ra_session_t *ra_session,
1628                  apr_hash_t *path_revs,
1629                  const char *comment,
1630                  svn_boolean_t force,
1631                  svn_ra_lock_callback_t lock_func,
1632                  void *lock_baton,
1633                  apr_pool_t *pool);
1634
1635/* Implements svn_ra__vtable_t.unlock(). */
1636svn_error_t *
1637svn_ra_serf__unlock(svn_ra_session_t *ra_session,
1638                    apr_hash_t *path_tokens,
1639                    svn_boolean_t force,
1640                    svn_ra_lock_callback_t lock_func,
1641                    void *lock_baton,
1642                    apr_pool_t *pool);
1643
1644/* Implements svn_ra__vtable_t.get_lock(). */
1645svn_error_t *
1646svn_ra_serf__get_lock(svn_ra_session_t *ra_session,
1647                      svn_lock_t **lock,
1648                      const char *path,
1649                      apr_pool_t *pool);
1650
1651/* Implements svn_ra__vtable_t.get_locks(). */
1652svn_error_t *
1653svn_ra_serf__get_locks(svn_ra_session_t *ra_session,
1654                       apr_hash_t **locks,
1655                       const char *path,
1656                       svn_depth_t depth,
1657                       apr_pool_t *pool);
1658
1659/* Request a mergeinfo-report from the URL attached to SESSION,
1660   and fill in the MERGEINFO hash with the results.
1661
1662   Implements svn_ra__vtable_t.get_mergeinfo().
1663 */
1664svn_error_t *
1665svn_ra_serf__get_mergeinfo(svn_ra_session_t *ra_session,
1666                           apr_hash_t **mergeinfo,
1667                           const apr_array_header_t *paths,
1668                           svn_revnum_t revision,
1669                           svn_mergeinfo_inheritance_t inherit,
1670                           svn_boolean_t include_descendants,
1671                           apr_pool_t *pool);
1672
1673/* Exchange capabilities with the server, by sending an OPTIONS
1674 * request announcing the client's capabilities, and by filling
1675 * SERF_SESS->capabilities with the server's capabilities as read from
1676 * the response headers.  Use POOL only for temporary allocation.
1677 *
1678 * If the CORRECTED_URL is non-NULL, allow the OPTIONS response to
1679 * report a server-dictated redirect or relocation (HTTP 301 or 302
1680 * error codes), setting *CORRECTED_URL to the value of the corrected
1681 * repository URL.  Otherwise, such responses from the server will
1682 * generate an error.  (In either case, no capabilities are exchanged
1683 * if there is, in fact, such a response from the server.)
1684 */
1685svn_error_t *
1686svn_ra_serf__exchange_capabilities(svn_ra_serf__session_t *serf_sess,
1687                                   const char **corrected_url,
1688                                   apr_pool_t *pool);
1689
1690/* Implements svn_ra__vtable_t.has_capability(). */
1691svn_error_t *
1692svn_ra_serf__has_capability(svn_ra_session_t *ra_session,
1693                            svn_boolean_t *has,
1694                            const char *capability,
1695                            apr_pool_t *pool);
1696
1697/* Implements svn_ra__vtable_t.get_deleted_rev(). */
1698svn_error_t *
1699svn_ra_serf__get_deleted_rev(svn_ra_session_t *session,
1700                             const char *path,
1701                             svn_revnum_t peg_revision,
1702                             svn_revnum_t end_revision,
1703                             svn_revnum_t *revision_deleted,
1704                             apr_pool_t *pool);
1705
1706/* Implements the get_inherited_props RA layer function. */
1707svn_error_t * svn_ra_serf__get_inherited_props(svn_ra_session_t *session,
1708                                               apr_array_header_t **iprops,
1709                                               const char *path,
1710                                               svn_revnum_t revision,
1711                                               apr_pool_t *result_pool,
1712                                               apr_pool_t *scratch_pool);
1713
1714/* Implements svn_ra__vtable_t.get_repos_root(). */
1715svn_error_t *
1716svn_ra_serf__get_repos_root(svn_ra_session_t *ra_session,
1717                            const char **url,
1718                            apr_pool_t *pool);
1719
1720/* Implements svn_ra__vtable_t.register_editor_shim_callbacks(). */
1721svn_error_t *
1722svn_ra_serf__register_editor_shim_callbacks(svn_ra_session_t *session,
1723                                    svn_delta_shim_callbacks_t *callbacks);
1724
1725/*** Authentication handler declarations ***/
1726
1727/**
1728 * Callback function that loads the credentials for Basic and Digest
1729 * authentications, both for server and proxy authentication.
1730 */
1731apr_status_t
1732svn_ra_serf__credentials_callback(char **username, char **password,
1733                                  serf_request_t *request, void *baton,
1734                                  int code, const char *authn_type,
1735                                  const char *realm,
1736                                  apr_pool_t *pool);
1737
1738
1739/*** General utility functions ***/
1740
1741/**
1742 * Convert an HTTP STATUS_CODE resulting from a WebDAV request against
1743 * PATH to the relevant error code.  Use the response-supplied LOCATION
1744 * where it necessary.
1745 */
1746svn_error_t *
1747svn_ra_serf__error_on_status(int status_code,
1748                             const char *path,
1749                             const char *location);
1750
1751/* ###? */
1752svn_error_t *
1753svn_ra_serf__copy_into_spillbuf(svn_spillbuf_t **spillbuf,
1754                                serf_bucket_t *bkt,
1755                                apr_pool_t *result_pool,
1756                                apr_pool_t *scratch_pool);
1757
1758/* ###? */
1759serf_bucket_t *
1760svn_ra_serf__create_sb_bucket(svn_spillbuf_t *spillbuf,
1761                              serf_bucket_alloc_t *allocator,
1762                              apr_pool_t *result_pool,
1763                              apr_pool_t *scratch_pool);
1764
1765/** Wrap STATUS from an serf function. If STATUS is not serf error code,
1766  * this is equivalent to svn_error_wrap_apr().
1767 */
1768svn_error_t *
1769svn_ra_serf__wrap_err(apr_status_t status,
1770                      const char *fmt,
1771                      ...);
1772
1773
1774#if defined(SVN_DEBUG)
1775/* Wrapper macros to collect file and line information */
1776#define svn_ra_serf__wrap_err \
1777  (svn_error__locate(__FILE__,__LINE__), (svn_ra_serf__wrap_err))
1778
1779#endif
1780
1781#ifdef __cplusplus
1782}
1783#endif /* __cplusplus */
1784
1785#endif /* SVN_LIBSVN_RA_SERF_RA_SERF_H */
1786