ra_serf.h revision 262253
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/** Wait duration (in microseconds) used in calls to serf_context_run() */
61#define SVN_RA_SERF__CONTEXT_RUN_DURATION 500000
62
63
64
65/* Forward declarations. */
66typedef struct svn_ra_serf__session_t svn_ra_serf__session_t;
67
68/* A serf connection and optionally associated SSL context.  */
69typedef struct svn_ra_serf__connection_t {
70  /* Our connection to a server. */
71  serf_connection_t *conn;
72
73  /* Bucket allocator for this connection. */
74  serf_bucket_alloc_t *bkt_alloc;
75
76  /* Collected cert failures in chain.  */
77  int server_cert_failures;
78
79  /* What was the last HTTP status code we got on this connection? */
80  int last_status_code;
81
82  /* Optional SSL context for this connection. */
83  serf_ssl_context_t *ssl_context;
84  svn_auth_iterstate_t *ssl_client_auth_state;
85  svn_auth_iterstate_t *ssl_client_pw_auth_state;
86
87  svn_ra_serf__session_t *session;
88
89} svn_ra_serf__connection_t;
90
91/** Maximum value we'll allow for the http-max-connections config option.
92 *
93 * Note: minimum 2 connections are required for ra_serf to function
94 * correctly!
95 */
96#define SVN_RA_SERF__MAX_CONNECTIONS_LIMIT 8
97
98/*
99 * The master serf RA session.
100 *
101 * This is stored in the ra session ->priv field.
102 */
103struct svn_ra_serf__session_t {
104  /* Pool for allocations during this session */
105  apr_pool_t *pool;
106
107  /* The current context */
108  serf_context_t *context;
109
110  /* The maximum number of connections we'll use for parallelized
111     fetch operations (updates, etc.) */
112  apr_int64_t max_connections;
113
114  /* Are we using ssl */
115  svn_boolean_t using_ssl;
116
117  /* Should we ask for compressed responses? */
118  svn_boolean_t using_compression;
119
120  /* The user agent string */
121  const char *useragent;
122
123  /* The current connection */
124  svn_ra_serf__connection_t *conns[SVN_RA_SERF__MAX_CONNECTIONS_LIMIT];
125  int num_conns;
126  int cur_conn;
127
128  /* The URL that was passed into _open() */
129  apr_uri_t session_url;
130  const char *session_url_str;
131
132  /* The actual discovered root; may be NULL until we know it. */
133  apr_uri_t repos_root;
134  const char *repos_root_str;
135
136  /* The server is not Apache/mod_dav_svn (directly) and only supports
137     HTTP/1.0. Thus, we cannot send chunked requests.  */
138  svn_boolean_t http10;
139
140  /* Should we use Transfer-Encoding: chunked for HTTP/1.1 servers. */
141  svn_boolean_t using_chunked_requests;
142
143  /* Do we need to detect whether the connection supports chunked requests?
144     i.e. is there a (reverse) proxy that does not support them?  */
145  svn_boolean_t detect_chunking;
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  svn_boolean_t 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
656
657/* v2 of the XML parsing functions  */
658
659/* The XML parsing context.  */
660typedef struct svn_ra_serf__xml_context_t svn_ra_serf__xml_context_t;
661
662
663/* An opaque structure for the XML parse element/state.  */
664typedef struct svn_ra_serf__xml_estate_t svn_ra_serf__xml_estate_t;
665
666/* Called just after the parser moves into ENTERED_STATE. The tag causing
667   the transition is passed in TAG.
668
669   This callback is applied to a parsing context by using the
670   svn_ra_serf__xml_context_customize() function.
671
672   NOTE: this callback, when set, will be invoked on *every* transition.
673   The callback must examine ENTERED_STATE to determine if any action
674   must be taken. The original state is not provided, but must be derived
675   from ENTERED_STATE and/or the TAG causing the transition (if needed).  */
676typedef svn_error_t *
677(*svn_ra_serf__xml_opened_t)(svn_ra_serf__xml_estate_t *xes,
678                             void *baton,
679                             int entered_state,
680                             const svn_ra_serf__dav_props_t *tag,
681                             apr_pool_t *scratch_pool);
682
683
684/* Called just before the parser leaves LEAVING_STATE.
685
686   If cdata collection was enabled for this state, then CDATA will be
687   non-NULL and contain the collected cdata.
688
689   If attribute collection was enabled for this state, then ATTRS will
690   contain the attributes collected for this element only, along with
691   any values stored via svn_ra_serf__xml_note().
692
693   Use svn_ra_serf__xml_gather_since() to gather up data from outer states.
694
695   ATTRS is char* -> char*.
696
697   Temporary allocations may be made in SCRATCH_POOL.  */
698typedef svn_error_t *
699(*svn_ra_serf__xml_closed_t)(svn_ra_serf__xml_estate_t *xes,
700                             void *baton,
701                             int leaving_state,
702                             const svn_string_t *cdata,
703                             apr_hash_t *attrs,
704                             apr_pool_t *scratch_pool);
705
706
707/* Called for all states that are not using the builtin cdata collection.
708   This callback is (only) appropriate for unbounded-size cdata content.
709
710   CURRENT_STATE may be used to decide what to do with the data.
711
712   Temporary allocations may be made in SCRATCH_POOL.  */
713typedef svn_error_t *
714(*svn_ra_serf__xml_cdata_t)(svn_ra_serf__xml_estate_t *xes,
715                            void *baton,
716                            int current_state,
717                            const char *data,
718                            apr_size_t len,
719                            apr_pool_t *scratch_pool);
720
721
722/* State transition table.
723
724   When the XML Context is constructed, it is in state 0. User states are
725   positive integers.
726
727   In a list of transitions, use { 0 } to indicate the end. Specifically,
728   the code looks for NS == NULL.
729
730   ### more docco
731*/
732typedef struct svn_ra_serf__xml_transition_t {
733  /* This transition applies when in this state  */
734  int from_state;
735
736  /* And when this tag is observed  */
737  const char *ns;
738  const char *name;
739
740  /* Moving to this state  */
741  int to_state;
742
743  /* Should the cdata of NAME be collected? Note that CUSTOM_CLOSE should
744     be TRUE in order to capture this cdata.  */
745  svn_boolean_t collect_cdata;
746
747  /* Which attributes of NAME should be collected? Terminate with NULL.
748     Maximum of 10 attributes may be collected. Note that attribute
749     namespaces are ignored at this time.
750
751     Attribute names beginning with "?" are optional. Other names must
752     exist on the element, or SVN_ERR_XML_ATTRIB_NOT_FOUND will be raised.  */
753  const char *collect_attrs[11];
754
755  /* When NAME is closed, should the callback be invoked?  */
756  svn_boolean_t custom_close;
757
758} svn_ra_serf__xml_transition_t;
759
760
761/* Construct an XML parsing context, based on the TTABLE transition table.
762   As content is parsed, the CLOSED_CB callback will be invoked according
763   to the definition in the table.
764
765   If OPENED_CB is not NULL, then it will be invoked for *every* tag-open
766   event. The callback will need to use the ENTERED_STATE and TAG parameters
767   to decide what it would like to do.
768
769   If CDATA_CB is not NULL, then it will be called for all cdata that is
770   not be automatically collected (based on the transition table record's
771   COLLECT_CDATA flag). It will be called in every state, so the callback
772   must examine the CURRENT_STATE parameter to decide what to do.
773
774   The same BATON value will be passed to all three callbacks.
775
776   The context will be created within RESULT_POOL.  */
777svn_ra_serf__xml_context_t *
778svn_ra_serf__xml_context_create(
779  const svn_ra_serf__xml_transition_t *ttable,
780  svn_ra_serf__xml_opened_t opened_cb,
781  svn_ra_serf__xml_closed_t closed_cb,
782  svn_ra_serf__xml_cdata_t cdata_cb,
783  void *baton,
784  apr_pool_t *result_pool);
785
786/* Destroy all subpools for this structure. */
787void
788svn_ra_serf__xml_context_destroy(
789  svn_ra_serf__xml_context_t *xmlctx);
790
791/* Construct a handler with the response function/baton set up to parse
792   a response body using the given XML context. The handler and its
793   internal structures are allocated in RESULT_POOL.
794
795   This also initializes HANDLER_POOL to the given RESULT_POOL.  */
796svn_ra_serf__handler_t *
797svn_ra_serf__create_expat_handler(svn_ra_serf__xml_context_t *xmlctx,
798                                  apr_pool_t *result_pool);
799
800
801/* Allocated within XES->STATE_POOL. Changes are not allowd (callers
802   should make a deep copy if they need to make changes).
803
804   The resulting hash maps char* names to char* values.  */
805apr_hash_t *
806svn_ra_serf__xml_gather_since(svn_ra_serf__xml_estate_t *xes,
807                              int stop_state);
808
809
810/* Attach the NAME/VALUE pair onto this/parent state identified by STATE.
811   The name and value will be copied into the target state's pool.
812
813   These values will be available to the CLOSED_CB for the target state,
814   or part of the gathered state via xml_gather_since().
815
816   Typically, this function is used by a child state's close callback,
817   or within an opening callback to store additional data.
818
819   Note: if the state is not found, then a programmer error has occurred,
820   so the function will invoke SVN_ERR_MALFUNCTION().  */
821void
822svn_ra_serf__xml_note(svn_ra_serf__xml_estate_t *xes,
823                      int state,
824                      const char *name,
825                      const char *value);
826
827
828/* Returns XES->STATE_POOL for allocating structures that should live
829   as long as the state identified by XES.
830
831   Note: a state pool is created upon demand, so only use this function
832   when memory is required for a given state.  */
833apr_pool_t *
834svn_ra_serf__xml_state_pool(svn_ra_serf__xml_estate_t *xes);
835
836
837/* Any XML parser may be used. When an opening tag is seen, call this
838   function to feed the information into XMLCTX.  */
839svn_error_t *
840svn_ra_serf__xml_cb_start(svn_ra_serf__xml_context_t *xmlctx,
841                          const char *raw_name,
842                          const char *const *attrs);
843
844
845/* When a close tag is seen, call this function to feed the information
846   into XMLCTX.  */
847svn_error_t *
848svn_ra_serf__xml_cb_end(svn_ra_serf__xml_context_t *xmlctx,
849                        const char *raw_name);
850
851
852/* When cdata is parsed by the wrapping XML parser, call this function to
853   feed the cdata into the XMLCTX.  */
854svn_error_t *
855svn_ra_serf__xml_cb_cdata(svn_ra_serf__xml_context_t *xmlctx,
856                          const char *data,
857                          apr_size_t len);
858
859
860/*
861 * Parses a server-side error message into a local Subversion error.
862 */
863struct svn_ra_serf__server_error_t {
864  /* Our local representation of the error. */
865  svn_error_t *error;
866
867  /* Are we done with the response? */
868  svn_boolean_t done;
869
870  /* Have we seen an error tag? */
871  svn_boolean_t in_error;
872
873  /* Have we seen a HTTP "412 Precondition Failed" error? */
874  svn_boolean_t contains_precondition_error;
875
876  /* Should we be collecting the XML cdata? */
877  svn_boolean_t collect_cdata;
878
879  /* Collected cdata. NULL if cdata not needed. */
880  svn_stringbuf_t *cdata;
881
882  /* XML parser and namespace used to parse the remote response */
883  svn_ra_serf__xml_parser_t parser;
884};
885
886
887/*
888 * Handler that discards the entire @a response body associated with a
889 * @a request.  Implements svn_ra_serf__response_handler_t.
890 *
891 * If @a baton is a svn_ra_serf__server_error_t (i.e. non-NULL) and an
892 * error is detected, it will be populated for later detection.
893 *
894 * All temporary allocations will be made in a @a pool.
895 */
896svn_error_t *
897svn_ra_serf__handle_discard_body(serf_request_t *request,
898                                 serf_bucket_t *response,
899                                 void *baton,
900                                 apr_pool_t *pool);
901
902
903/*
904 * Handler that retrieves the embedded XML multistatus response from the
905 * the @a RESPONSE body associated with a @a REQUEST.
906 *
907 * Implements svn_ra_serf__response_handler_t.
908 *
909 * The @a BATON should be of type svn_ra_serf__handler_t. When the request
910 * is complete, the handler's DONE flag will be set to TRUE.
911 *
912 * All temporary allocations will be made in a @a scratch_pool.
913 */
914svn_error_t *
915svn_ra_serf__handle_multistatus_only(serf_request_t *request,
916                                     serf_bucket_t *response,
917                                     void *baton,
918                                     apr_pool_t *scratch_pool);
919
920
921/* Handler that expects an empty body.
922
923   If a body IS present, and it is text/xml, then it will be parsed for
924   a server-side error.
925
926   BATON should be the svn_ra_serf__handler_t running REQUEST.
927
928   Status line information will be in HANDLER->SLINE.
929
930   Any parsed errors will be left in HANDLER->SERVER_ERROR. That member
931   may be NULL if no body was present, or a problem occurred trying to
932   parse the body.
933
934   All temporary allocations will be made in SCRATCH_POOL.  */
935svn_error_t *
936svn_ra_serf__expect_empty_body(serf_request_t *request,
937                               serf_bucket_t *response,
938                               void *baton,
939                               apr_pool_t *scratch_pool);
940
941
942/*
943 * This function will feed the RESPONSE body into XMLP.  When parsing is
944 * completed (i.e. an EOF is received), *DONE is set to TRUE.
945 * Implements svn_ra_serf__response_handler_t.
946 *
947 * If an error occurs during processing RESP_ERR is invoked with the
948 * RESP_ERR_BATON.
949 *
950 * Temporary allocations are made in POOL.
951 */
952svn_error_t *
953svn_ra_serf__handle_xml_parser(serf_request_t *request,
954                               serf_bucket_t *response,
955                               void *handler_baton,
956                               apr_pool_t *pool);
957
958/* serf_response_handler_t implementation that completely discards
959 * the response.
960 *
961 * All temporary allocations will be made in @a pool.
962 */
963apr_status_t
964svn_ra_serf__response_discard_handler(serf_request_t *request,
965                                      serf_bucket_t *response,
966                                      void *baton,
967                                      apr_pool_t *pool);
968
969
970/** XML helper functions. **/
971
972/*
973 * Advance the internal XML @a parser to the @a state.
974 */
975void
976svn_ra_serf__xml_push_state(svn_ra_serf__xml_parser_t *parser,
977                            int state);
978
979/*
980 * Return to the previous internal XML @a parser state.
981 */
982void
983svn_ra_serf__xml_pop_state(svn_ra_serf__xml_parser_t *parser);
984
985
986svn_error_t *
987svn_ra_serf__process_pending(svn_ra_serf__xml_parser_t *parser,
988                             svn_boolean_t *network_eof,
989                             apr_pool_t *scratch_pool);
990
991
992/*
993 * Add the appropriate serf buckets to @a agg_bucket represented by
994 * the XML * @a tag and @a value.
995 *
996 * The bucket will be allocated from @a bkt_alloc.
997 */
998void
999svn_ra_serf__add_tag_buckets(serf_bucket_t *agg_bucket,
1000                             const char *tag,
1001                             const char *value,
1002                             serf_bucket_alloc_t *bkt_alloc);
1003
1004/*
1005 * Add the appropriate serf buckets to AGG_BUCKET with standard XML header:
1006 *  <?xml version="1.0" encoding="utf-8"?>
1007 *
1008 * The bucket will be allocated from BKT_ALLOC.
1009 */
1010void
1011svn_ra_serf__add_xml_header_buckets(serf_bucket_t *agg_bucket,
1012                                    serf_bucket_alloc_t *bkt_alloc);
1013
1014/*
1015 * Add the appropriate serf buckets to AGG_BUCKET representing the XML
1016 * open tag with name TAG.
1017 *
1018 * Take the tag's attributes from varargs, a NULL-terminated list of
1019 * alternating <tt>char *</tt> key and <tt>char *</tt> val.  Attribute
1020 * will be ignored if it's value is NULL.
1021 *
1022 * NOTE: Callers are responsible for XML-escaping attribute values as
1023 * necessary.
1024 *
1025 * The bucket will be allocated from BKT_ALLOC.
1026 */
1027void
1028svn_ra_serf__add_open_tag_buckets(serf_bucket_t *agg_bucket,
1029                                  serf_bucket_alloc_t *bkt_alloc,
1030                                  const char *tag,
1031                                  ...);
1032
1033/*
1034 * Add the appropriate serf buckets to AGG_BUCKET representing xml tag close
1035 * with name TAG.
1036 *
1037 * The bucket will be allocated from BKT_ALLOC.
1038 */
1039void
1040svn_ra_serf__add_close_tag_buckets(serf_bucket_t *agg_bucket,
1041                                   serf_bucket_alloc_t *bkt_alloc,
1042                                   const char *tag);
1043
1044/*
1045 * Add the appropriate serf buckets to AGG_BUCKET with xml-escaped
1046 * version of DATA.
1047 *
1048 * The bucket will be allocated from BKT_ALLOC.
1049 */
1050void
1051svn_ra_serf__add_cdata_len_buckets(serf_bucket_t *agg_bucket,
1052                                   serf_bucket_alloc_t *bkt_alloc,
1053                                   const char *data, apr_size_t len);
1054/*
1055 * Look up the @a attrs array for namespace definitions and add each one
1056 * to the @a ns_list of namespaces.
1057 *
1058 * New namespaces will be allocated in RESULT_POOL.
1059 */
1060void
1061svn_ra_serf__define_ns(svn_ra_serf__ns_t **ns_list,
1062                       const char *const *attrs,
1063                       apr_pool_t *result_pool);
1064
1065/*
1066 * Look up @a name in the @a ns_list list for previously declared namespace
1067 * definitions.
1068 *
1069 * Return (in @a *returned_prop_name) a #svn_ra_serf__dav_props_t tuple
1070 * representing the expanded name.
1071 */
1072void
1073svn_ra_serf__expand_ns(svn_ra_serf__dav_props_t *returned_prop_name,
1074                       const svn_ra_serf__ns_t *ns_list,
1075                       const char *name);
1076
1077
1078/** PROPFIND-related functions **/
1079
1080/*
1081 * This function will deliver a PROP_CTX PROPFIND request in the SESS
1082 * serf context for the properties listed in LOOKUP_PROPS at URL for
1083 * DEPTH ("0","1","infinity").
1084 *
1085 * This function will not block waiting for the response. Callers are
1086 * expected to call svn_ra_serf__wait_for_props().
1087 */
1088svn_error_t *
1089svn_ra_serf__deliver_props(svn_ra_serf__handler_t **propfind_handler,
1090                           apr_hash_t *prop_vals,
1091                           svn_ra_serf__session_t *sess,
1092                           svn_ra_serf__connection_t *conn,
1093                           const char *url,
1094                           svn_revnum_t rev,
1095                           const char *depth,
1096                           const svn_ra_serf__dav_props_t *lookup_props,
1097                           svn_ra_serf__list_t **done_list,
1098                           apr_pool_t *pool);
1099
1100/*
1101 * This helper function will block until PROPFIND_HANDLER indicates that is
1102 * done or another error is returned.
1103 */
1104svn_error_t *
1105svn_ra_serf__wait_for_props(svn_ra_serf__handler_t *handler,
1106                            apr_pool_t *scratch_pool);
1107
1108/* This is a blocking version of deliver_props.
1109
1110   The properties are fetched and placed into RESULTS, allocated in
1111   RESULT_POOL.
1112
1113   ### more docco about the other params.
1114
1115   Temporary allocations are made in SCRATCH_POOL.
1116*/
1117svn_error_t *
1118svn_ra_serf__retrieve_props(apr_hash_t **results,
1119                            svn_ra_serf__session_t *sess,
1120                            svn_ra_serf__connection_t *conn,
1121                            const char *url,
1122                            svn_revnum_t rev,
1123                            const char *depth,
1124                            const svn_ra_serf__dav_props_t *props,
1125                            apr_pool_t *result_pool,
1126                            apr_pool_t *scratch_pool);
1127
1128
1129/* Using CONN, fetch the properties specified by WHICH_PROPS using CONN
1130   for URL at REVISION. The resulting properties are placed into a 2-level
1131   hash in RESULTS, mapping NAMESPACE -> hash<PROPNAME, PROPVALUE>, which
1132   is allocated in RESULT_POOL.
1133
1134   If REVISION is SVN_INVALID_REVNUM, then the properties are fetched
1135   from HEAD for URL.
1136
1137   This function performs the request synchronously.
1138
1139   Temporary allocations are made in SCRATCH_POOL.  */
1140svn_error_t *
1141svn_ra_serf__fetch_node_props(apr_hash_t **results,
1142                              svn_ra_serf__connection_t *conn,
1143                              const char *url,
1144                              svn_revnum_t revision,
1145                              const svn_ra_serf__dav_props_t *which_props,
1146                              apr_pool_t *result_pool,
1147                              apr_pool_t *scratch_pool);
1148
1149
1150/* Using CONN, fetch a DAV: property from the resource identified by URL
1151   within REVISION. The PROPNAME may be one of:
1152
1153     "checked-in"
1154     "href"
1155
1156   The resulting value will be allocated in RESULT_POOL, and may be NULL
1157   if the property does not exist (note: "href" always exists).
1158
1159   This function performs the request synchronously.
1160
1161   Temporary allocations are made in SCRATCH_POOL.  */
1162svn_error_t *
1163svn_ra_serf__fetch_dav_prop(const char **value,
1164                            svn_ra_serf__connection_t *conn,
1165                            const char *url,
1166                            svn_revnum_t revision,
1167                            const char *propname,
1168                            apr_pool_t *result_pool,
1169                            apr_pool_t *scratch_pool);
1170
1171
1172/* Set PROPS for PATH at REV revision with a NS:NAME VAL.
1173 *
1174 * The POOL governs allocation.
1175 */
1176void
1177svn_ra_serf__set_ver_prop(apr_hash_t *props,
1178                          const char *path, svn_revnum_t rev,
1179                          const char *ns, const char *name,
1180                          const svn_string_t *val, apr_pool_t *pool);
1181#define svn_ra_serf__set_rev_prop svn_ra_serf__set_ver_prop
1182
1183/** Property walker functions **/
1184
1185typedef svn_error_t *
1186(*svn_ra_serf__walker_visitor_t)(void *baton,
1187                                 const char *ns,
1188                                 const char *name,
1189                                 const svn_string_t *val,
1190                                 apr_pool_t *pool);
1191
1192svn_error_t *
1193svn_ra_serf__walk_all_props(apr_hash_t *props,
1194                            const char *name,
1195                            svn_revnum_t rev,
1196                            svn_ra_serf__walker_visitor_t walker,
1197                            void *baton,
1198                            apr_pool_t *pool);
1199
1200
1201/* Like walk_all_props(), but a 2-level hash.  */
1202svn_error_t *
1203svn_ra_serf__walk_node_props(apr_hash_t *props,
1204                             svn_ra_serf__walker_visitor_t walker,
1205                             void *baton,
1206                             apr_pool_t *scratch_pool);
1207
1208
1209typedef svn_error_t *
1210(*svn_ra_serf__path_rev_walker_t)(void *baton,
1211                                  const char *path, apr_ssize_t path_len,
1212                                  const char *ns, apr_ssize_t ns_len,
1213                                  const char *name, apr_ssize_t name_len,
1214                                  const svn_string_t *val,
1215                                  apr_pool_t *pool);
1216svn_error_t *
1217svn_ra_serf__walk_all_paths(apr_hash_t *props,
1218                            svn_revnum_t rev,
1219                            svn_ra_serf__path_rev_walker_t walker,
1220                            void *baton,
1221                            apr_pool_t *pool);
1222
1223
1224/* Map a property name, as passed over the wire, into its corresponding
1225   Subversion-internal name. The returned name will be a static value,
1226   or allocated within RESULT_POOL.
1227
1228   If the property should be ignored (eg. some DAV properties), then NULL
1229   will be returned.  */
1230const char *
1231svn_ra_serf__svnname_from_wirename(const char *ns,
1232                                   const char *name,
1233                                   apr_pool_t *result_pool);
1234
1235
1236/* Select the basic revision properties from the set of "all" properties.
1237   Return these in *REVPROPS, allocated from RESULT_POOL.  */
1238svn_error_t *
1239svn_ra_serf__select_revprops(apr_hash_t **revprops,
1240                             const char *name,
1241                             svn_revnum_t rev,
1242                             apr_hash_t *all_revprops,
1243                             apr_pool_t *result_pool,
1244                             apr_pool_t *scratch_pool);
1245
1246
1247/* PROPS is nested hash tables mapping NS -> NAME -> VALUE.
1248   This function takes the NS:NAME:VALUE hashes and flattens them into a set of
1249   names to VALUE. The names are composed of NS:NAME, with specific
1250   rewrite from wire names (DAV) to SVN names. This mapping is managed
1251   by the svn_ra_serf__set_baton_props() function.
1252
1253   FLAT_PROPS is allocated in RESULT_POOL.
1254   ### right now, we do a shallow copy from PROPS to FLAT_PROPS. therefore,
1255   ### the names and values in PROPS must be in the proper pool.
1256
1257   Temporary allocations are made in SCRATCH_POOL.  */
1258svn_error_t *
1259svn_ra_serf__flatten_props(apr_hash_t **flat_props,
1260                           apr_hash_t *props,
1261                           apr_pool_t *result_pool,
1262                           apr_pool_t *scratch_pool);
1263
1264
1265/* Return the property value for PATH at REV revision with a NS:NAME.
1266 * PROPS is a four-level nested hash: (svn_revnum_t => char *path =>
1267 * char *ns => char *name => svn_string_t *). */
1268const svn_string_t *
1269svn_ra_serf__get_ver_prop_string(apr_hash_t *props,
1270                                 const char *path, svn_revnum_t rev,
1271                                 const char *ns, const char *name);
1272
1273/* Same as svn_ra_serf__get_ver_prop_string(), but returns a C string. */
1274const char *
1275svn_ra_serf__get_ver_prop(apr_hash_t *props,
1276                          const char *path, svn_revnum_t rev,
1277                          const char *ns, const char *name);
1278
1279/* Same as svn_ra_serf__get_ver_prop_string(), but for the unknown revision. */
1280const svn_string_t *
1281svn_ra_serf__get_prop_string(apr_hash_t *props,
1282                             const char *path,
1283                             const char *ns,
1284                             const char *name);
1285
1286/* Same as svn_ra_serf__get_ver_prop(), but for the unknown revision. */
1287const char *
1288svn_ra_serf__get_prop(apr_hash_t *props,
1289                      const char *path,
1290                      const char *ns,
1291                      const char *name);
1292
1293/* Same as svn_ra_serf__set_rev_prop(), but for the unknown revision. */
1294void
1295svn_ra_serf__set_prop(apr_hash_t *props, const char *path,
1296                      const char *ns, const char *name,
1297                      const svn_string_t *val, apr_pool_t *pool);
1298
1299svn_error_t *
1300svn_ra_serf__get_resource_type(svn_node_kind_t *kind,
1301                               apr_hash_t *props);
1302
1303
1304/** MERGE-related functions **/
1305
1306void
1307svn_ra_serf__merge_lock_token_list(apr_hash_t *lock_tokens,
1308                                   const char *parent,
1309                                   serf_bucket_t *body,
1310                                   serf_bucket_alloc_t *alloc,
1311                                   apr_pool_t *pool);
1312
1313/* Create an MERGE request aimed at the SESSION url, requesting the
1314   merge of the resource identified by MERGE_RESOURCE_URL.
1315   LOCK_TOKENS is a hash mapping paths to lock tokens owned by the
1316   client.  If KEEP_LOCKS is set, instruct the server to not release
1317   locks set on the paths included in this commit.  */
1318svn_error_t *
1319svn_ra_serf__run_merge(const svn_commit_info_t **commit_info,
1320                       int *response_code,
1321                       svn_ra_serf__session_t *session,
1322                       svn_ra_serf__connection_t *conn,
1323                       const char *merge_resource_url,
1324                       apr_hash_t *lock_tokens,
1325                       svn_boolean_t keep_locks,
1326                       apr_pool_t *result_pool,
1327                       apr_pool_t *scratch_pool);
1328
1329
1330/** OPTIONS-related functions **/
1331
1332/* When running with a proxy, we may need to detect and correct for problems.
1333   This probing function will send a simple OPTIONS request to detect problems
1334   with the connection.  */
1335svn_error_t *
1336svn_ra_serf__probe_proxy(svn_ra_serf__session_t *serf_sess,
1337                         apr_pool_t *scratch_pool);
1338
1339
1340/* On HTTPv2 connections, run an OPTIONS request over CONN to fetch the
1341   current youngest revnum, returning it in *YOUNGEST.
1342
1343   (the revnum is headers of the OPTIONS response)
1344
1345   This function performs the request synchronously.
1346
1347   All temporary allocations will be made in SCRATCH_POOL.  */
1348svn_error_t *
1349svn_ra_serf__v2_get_youngest_revnum(svn_revnum_t *youngest,
1350                                    svn_ra_serf__connection_t *conn,
1351                                    apr_pool_t *scratch_pool);
1352
1353
1354/* On HTTPv1 connections, run an OPTIONS request over CONN to fetch the
1355   activity collection set and return it in *ACTIVITY_URL, allocated
1356   from RESULT_POOL.
1357
1358   (the activity-collection-set is in the body of the OPTIONS response)
1359
1360   This function performs the request synchronously.
1361
1362   All temporary allocations will be made in SCRATCH_POOL.  */
1363svn_error_t *
1364svn_ra_serf__v1_get_activity_collection(const char **activity_url,
1365                                        svn_ra_serf__connection_t *conn,
1366                                        apr_pool_t *result_pool,
1367                                        apr_pool_t *scratch_pool);
1368
1369
1370/* Set @a VCC_URL to the default VCC for our repository based on @a
1371 * ORIG_PATH for the session @a SESSION, ensuring that the VCC URL and
1372 * repository root URLs are cached in @a SESSION.  Use @a CONN for any
1373 * required network communications if it is non-NULL; otherwise use the
1374 * default connection.
1375 *
1376 * All temporary allocations will be made in @a POOL. */
1377svn_error_t *
1378svn_ra_serf__discover_vcc(const char **vcc_url,
1379                          svn_ra_serf__session_t *session,
1380                          svn_ra_serf__connection_t *conn,
1381                          apr_pool_t *pool);
1382
1383/* Set @a REPORT_TARGET to the URI of the resource at which generic
1384 * (path-agnostic) REPORTs should be aimed for @a SESSION.  Use @a
1385 * CONN for any required network communications if it is non-NULL;
1386 * otherwise use the default connection.
1387 *
1388 * All temporary allocations will be made in @a POOL.
1389 */
1390svn_error_t *
1391svn_ra_serf__report_resource(const char **report_target,
1392                             svn_ra_serf__session_t *session,
1393                             svn_ra_serf__connection_t *conn,
1394                             apr_pool_t *pool);
1395
1396/* Set @a REL_PATH to a path (not URI-encoded) relative to the root of
1397 * the repository pointed to by @a SESSION, based on original path
1398 * (URI-encoded) @a ORIG_PATH.  Use @a CONN for any required network
1399 * communications if it is non-NULL; otherwise use the default
1400 * connection.  Use POOL for allocations.  */
1401svn_error_t *
1402svn_ra_serf__get_relative_path(const char **rel_path,
1403                               const char *orig_path,
1404                               svn_ra_serf__session_t *session,
1405                               svn_ra_serf__connection_t *conn,
1406                               apr_pool_t *pool);
1407
1408
1409/* Using the default connection in SESSION (conns[0]), get the youngest
1410   revnum from the server, returning it in *YOUNGEST.
1411
1412   This function operates synchronously.
1413
1414   All temporary allocations are performed in SCRATCH_POOL.  */
1415svn_error_t *
1416svn_ra_serf__get_youngest_revnum(svn_revnum_t *youngest,
1417                                 svn_ra_serf__session_t *session,
1418                                 apr_pool_t *scratch_pool);
1419
1420
1421/* Generate a revision-stable URL.
1422
1423   The RA APIs all refer to user/public URLs that float along with the
1424   youngest revision. In many cases, we do NOT want to work with that URL
1425   since it can change from one moment to the next. Especially if we
1426   attempt to operation against multiple floating URLs -- we could end up
1427   referring to two separate revisions.
1428
1429   The DAV RA provider(s) solve this by generating a URL that is specific
1430   to a revision by using a URL into a "baseline collection".
1431
1432   For a specified SESSION, with an optional CONN (if NULL, then the
1433   session's default connection will be used; specifically SESSION->conns[0]),
1434   generate a revision-stable URL for URL at REVISION. If REVISION is
1435   SVN_INVALID_REVNUM, then the stable URL will refer to the youngest
1436   revision at the time this function was called.
1437
1438   If URL is NULL, then the session root will be used.
1439
1440   The stable URL will be placed into *STABLE_URL, allocated from RESULT_POOL.
1441
1442   If LATEST_REVNUM is not NULL, then the revision used will be placed into
1443   *LATEST_REVNUM. That will be equal to youngest, or the given REVISION.
1444
1445   This function operates synchronously, if any communication to the server
1446   is required. Communication is needed if REVISION is SVN_INVALID_REVNUM
1447   (to get the current youngest revnum), or if the specified REVISION is not
1448   (yet) in our cache of baseline collections.
1449
1450   All temporary allocations are performed in SCRATCH_POOL.  */
1451svn_error_t *
1452svn_ra_serf__get_stable_url(const char **stable_url,
1453                            svn_revnum_t *latest_revnum,
1454                            svn_ra_serf__session_t *session,
1455                            svn_ra_serf__connection_t *conn,
1456                            const char *url,
1457                            svn_revnum_t revision,
1458                            apr_pool_t *result_pool,
1459                            apr_pool_t *scratch_pool);
1460
1461
1462/** RA functions **/
1463
1464/* Implements svn_ra__vtable_t.get_log(). */
1465svn_error_t *
1466svn_ra_serf__get_log(svn_ra_session_t *session,
1467                     const apr_array_header_t *paths,
1468                     svn_revnum_t start,
1469                     svn_revnum_t end,
1470                     int limit,
1471                     svn_boolean_t discover_changed_paths,
1472                     svn_boolean_t strict_node_history,
1473                     svn_boolean_t include_merged_revisions,
1474                     const apr_array_header_t *revprops,
1475                     svn_log_entry_receiver_t receiver,
1476                     void *receiver_baton,
1477                     apr_pool_t *pool);
1478
1479/* Implements svn_ra__vtable_t.get_locations(). */
1480svn_error_t *
1481svn_ra_serf__get_locations(svn_ra_session_t *session,
1482                           apr_hash_t **locations,
1483                           const char *path,
1484                           svn_revnum_t peg_revision,
1485                           const apr_array_header_t *location_revisions,
1486                           apr_pool_t *pool);
1487
1488/* Implements svn_ra__vtable_t.get_location_segments(). */
1489svn_error_t *
1490svn_ra_serf__get_location_segments(svn_ra_session_t *session,
1491                                   const char *path,
1492                                   svn_revnum_t peg_revision,
1493                                   svn_revnum_t start_rev,
1494                                   svn_revnum_t end_rev,
1495                                   svn_location_segment_receiver_t receiver,
1496                                   void *receiver_baton,
1497                                   apr_pool_t *pool);
1498
1499/* Implements svn_ra__vtable_t.do_diff(). */
1500svn_error_t *
1501svn_ra_serf__do_diff(svn_ra_session_t *session,
1502                     const svn_ra_reporter3_t **reporter,
1503                     void **report_baton,
1504                     svn_revnum_t revision,
1505                     const char *diff_target,
1506                     svn_depth_t depth,
1507                     svn_boolean_t ignore_ancestry,
1508                     svn_boolean_t text_deltas,
1509                     const char *versus_url,
1510                     const svn_delta_editor_t *diff_editor,
1511                     void *diff_baton,
1512                     apr_pool_t *pool);
1513
1514/* Implements svn_ra__vtable_t.do_status(). */
1515svn_error_t *
1516svn_ra_serf__do_status(svn_ra_session_t *ra_session,
1517                       const svn_ra_reporter3_t **reporter,
1518                       void **report_baton,
1519                       const char *status_target,
1520                       svn_revnum_t revision,
1521                       svn_depth_t depth,
1522                       const svn_delta_editor_t *status_editor,
1523                       void *status_baton,
1524                       apr_pool_t *pool);
1525
1526/* Implements svn_ra__vtable_t.do_update(). */
1527svn_error_t *
1528svn_ra_serf__do_update(svn_ra_session_t *ra_session,
1529                       const svn_ra_reporter3_t **reporter,
1530                       void **report_baton,
1531                       svn_revnum_t revision_to_update_to,
1532                       const char *update_target,
1533                       svn_depth_t depth,
1534                       svn_boolean_t send_copyfrom_args,
1535                       svn_boolean_t ignore_ancestry,
1536                       const svn_delta_editor_t *update_editor,
1537                       void *update_baton,
1538                       apr_pool_t *result_pool,
1539                       apr_pool_t *scratch_pool);
1540
1541/* Implements svn_ra__vtable_t.do_switch(). */
1542svn_error_t *
1543svn_ra_serf__do_switch(svn_ra_session_t *ra_session,
1544                       const svn_ra_reporter3_t **reporter,
1545                       void **report_baton,
1546                       svn_revnum_t revision_to_switch_to,
1547                       const char *switch_target,
1548                       svn_depth_t depth,
1549                       const char *switch_url,
1550                       svn_boolean_t send_copyfrom_args,
1551                       svn_boolean_t ignore_ancestry,
1552                       const svn_delta_editor_t *switch_editor,
1553                       void *switch_baton,
1554                       apr_pool_t *result_pool,
1555                       apr_pool_t *scratch_pool);
1556
1557/* Implements svn_ra__vtable_t.get_file_revs(). */
1558svn_error_t *
1559svn_ra_serf__get_file_revs(svn_ra_session_t *session,
1560                           const char *path,
1561                           svn_revnum_t start,
1562                           svn_revnum_t end,
1563                           svn_boolean_t include_merged_revisions,
1564                           svn_file_rev_handler_t handler,
1565                           void *handler_baton,
1566                           apr_pool_t *pool);
1567
1568/* Implements svn_ra__vtable_t.get_dated_revision(). */
1569svn_error_t *
1570svn_ra_serf__get_dated_revision(svn_ra_session_t *session,
1571                                svn_revnum_t *revision,
1572                                apr_time_t tm,
1573                                apr_pool_t *pool);
1574
1575/* Implements svn_ra__vtable_t.get_commit_editor(). */
1576svn_error_t *
1577svn_ra_serf__get_commit_editor(svn_ra_session_t *session,
1578                               const svn_delta_editor_t **editor,
1579                               void **edit_baton,
1580                               apr_hash_t *revprop_table,
1581                               svn_commit_callback2_t callback,
1582                               void *callback_baton,
1583                               apr_hash_t *lock_tokens,
1584                               svn_boolean_t keep_locks,
1585                               apr_pool_t *pool);
1586
1587/* Implements svn_ra__vtable_t.get_file(). */
1588svn_error_t *
1589svn_ra_serf__get_file(svn_ra_session_t *session,
1590                      const char *path,
1591                      svn_revnum_t revision,
1592                      svn_stream_t *stream,
1593                      svn_revnum_t *fetched_rev,
1594                      apr_hash_t **props,
1595                      apr_pool_t *pool);
1596
1597/* Implements svn_ra__vtable_t.change_rev_prop(). */
1598svn_error_t *
1599svn_ra_serf__change_rev_prop(svn_ra_session_t *session,
1600                             svn_revnum_t rev,
1601                             const char *name,
1602                             const svn_string_t *const *old_value_p,
1603                             const svn_string_t *value,
1604                             apr_pool_t *pool);
1605
1606/* Implements svn_ra__vtable_t.replay(). */
1607svn_error_t *
1608svn_ra_serf__replay(svn_ra_session_t *ra_session,
1609                    svn_revnum_t revision,
1610                    svn_revnum_t low_water_mark,
1611                    svn_boolean_t text_deltas,
1612                    const svn_delta_editor_t *editor,
1613                    void *edit_baton,
1614                    apr_pool_t *pool);
1615
1616/* Implements svn_ra__vtable_t.replay_range(). */
1617svn_error_t *
1618svn_ra_serf__replay_range(svn_ra_session_t *ra_session,
1619                          svn_revnum_t start_revision,
1620                          svn_revnum_t end_revision,
1621                          svn_revnum_t low_water_mark,
1622                          svn_boolean_t send_deltas,
1623                          svn_ra_replay_revstart_callback_t revstart_func,
1624                          svn_ra_replay_revfinish_callback_t revfinish_func,
1625                          void *replay_baton,
1626                          apr_pool_t *pool);
1627
1628/* Implements svn_ra__vtable_t.lock(). */
1629svn_error_t *
1630svn_ra_serf__lock(svn_ra_session_t *ra_session,
1631                  apr_hash_t *path_revs,
1632                  const char *comment,
1633                  svn_boolean_t force,
1634                  svn_ra_lock_callback_t lock_func,
1635                  void *lock_baton,
1636                  apr_pool_t *pool);
1637
1638/* Implements svn_ra__vtable_t.unlock(). */
1639svn_error_t *
1640svn_ra_serf__unlock(svn_ra_session_t *ra_session,
1641                    apr_hash_t *path_tokens,
1642                    svn_boolean_t force,
1643                    svn_ra_lock_callback_t lock_func,
1644                    void *lock_baton,
1645                    apr_pool_t *pool);
1646
1647/* Implements svn_ra__vtable_t.get_lock(). */
1648svn_error_t *
1649svn_ra_serf__get_lock(svn_ra_session_t *ra_session,
1650                      svn_lock_t **lock,
1651                      const char *path,
1652                      apr_pool_t *pool);
1653
1654/* Implements svn_ra__vtable_t.get_locks(). */
1655svn_error_t *
1656svn_ra_serf__get_locks(svn_ra_session_t *ra_session,
1657                       apr_hash_t **locks,
1658                       const char *path,
1659                       svn_depth_t depth,
1660                       apr_pool_t *pool);
1661
1662/* Request a mergeinfo-report from the URL attached to SESSION,
1663   and fill in the MERGEINFO hash with the results.
1664
1665   Implements svn_ra__vtable_t.get_mergeinfo().
1666 */
1667svn_error_t *
1668svn_ra_serf__get_mergeinfo(svn_ra_session_t *ra_session,
1669                           apr_hash_t **mergeinfo,
1670                           const apr_array_header_t *paths,
1671                           svn_revnum_t revision,
1672                           svn_mergeinfo_inheritance_t inherit,
1673                           svn_boolean_t include_descendants,
1674                           apr_pool_t *pool);
1675
1676/* Exchange capabilities with the server, by sending an OPTIONS
1677 * request announcing the client's capabilities, and by filling
1678 * SERF_SESS->capabilities with the server's capabilities as read from
1679 * the response headers.  Use POOL only for temporary allocation.
1680 *
1681 * If the CORRECTED_URL is non-NULL, allow the OPTIONS response to
1682 * report a server-dictated redirect or relocation (HTTP 301 or 302
1683 * error codes), setting *CORRECTED_URL to the value of the corrected
1684 * repository URL.  Otherwise, such responses from the server will
1685 * generate an error.  (In either case, no capabilities are exchanged
1686 * if there is, in fact, such a response from the server.)
1687 */
1688svn_error_t *
1689svn_ra_serf__exchange_capabilities(svn_ra_serf__session_t *serf_sess,
1690                                   const char **corrected_url,
1691                                   apr_pool_t *pool);
1692
1693/* Implements svn_ra__vtable_t.has_capability(). */
1694svn_error_t *
1695svn_ra_serf__has_capability(svn_ra_session_t *ra_session,
1696                            svn_boolean_t *has,
1697                            const char *capability,
1698                            apr_pool_t *pool);
1699
1700/* Implements svn_ra__vtable_t.get_deleted_rev(). */
1701svn_error_t *
1702svn_ra_serf__get_deleted_rev(svn_ra_session_t *session,
1703                             const char *path,
1704                             svn_revnum_t peg_revision,
1705                             svn_revnum_t end_revision,
1706                             svn_revnum_t *revision_deleted,
1707                             apr_pool_t *pool);
1708
1709/* Implements the get_inherited_props RA layer function. */
1710svn_error_t * svn_ra_serf__get_inherited_props(svn_ra_session_t *session,
1711                                               apr_array_header_t **iprops,
1712                                               const char *path,
1713                                               svn_revnum_t revision,
1714                                               apr_pool_t *result_pool,
1715                                               apr_pool_t *scratch_pool);
1716
1717/* Implements svn_ra__vtable_t.get_repos_root(). */
1718svn_error_t *
1719svn_ra_serf__get_repos_root(svn_ra_session_t *ra_session,
1720                            const char **url,
1721                            apr_pool_t *pool);
1722
1723/* Implements svn_ra__vtable_t.register_editor_shim_callbacks(). */
1724svn_error_t *
1725svn_ra_serf__register_editor_shim_callbacks(svn_ra_session_t *session,
1726                                    svn_delta_shim_callbacks_t *callbacks);
1727
1728/*** Authentication handler declarations ***/
1729
1730/**
1731 * Callback function that loads the credentials for Basic and Digest
1732 * authentications, both for server and proxy authentication.
1733 */
1734apr_status_t
1735svn_ra_serf__credentials_callback(char **username, char **password,
1736                                  serf_request_t *request, void *baton,
1737                                  int code, const char *authn_type,
1738                                  const char *realm,
1739                                  apr_pool_t *pool);
1740
1741
1742/*** General utility functions ***/
1743
1744/**
1745 * Convert an HTTP STATUS_CODE resulting from a WebDAV request against
1746 * PATH to the relevant error code.  Use the response-supplied LOCATION
1747 * where it necessary.
1748 */
1749svn_error_t *
1750svn_ra_serf__error_on_status(serf_status_line sline,
1751                             const char *path,
1752                             const char *location);
1753
1754/* ###? */
1755svn_error_t *
1756svn_ra_serf__copy_into_spillbuf(svn_spillbuf_t **spillbuf,
1757                                serf_bucket_t *bkt,
1758                                apr_pool_t *result_pool,
1759                                apr_pool_t *scratch_pool);
1760
1761/* ###? */
1762serf_bucket_t *
1763svn_ra_serf__create_sb_bucket(svn_spillbuf_t *spillbuf,
1764                              serf_bucket_alloc_t *allocator,
1765                              apr_pool_t *result_pool,
1766                              apr_pool_t *scratch_pool);
1767
1768/** Wrap STATUS from an serf function. If STATUS is not serf error code,
1769  * this is equivalent to svn_error_wrap_apr().
1770 */
1771svn_error_t *
1772svn_ra_serf__wrap_err(apr_status_t status,
1773                      const char *fmt,
1774                      ...);
1775
1776
1777#if defined(SVN_DEBUG)
1778/* Wrapper macros to collect file and line information */
1779#define svn_ra_serf__wrap_err \
1780  (svn_error__locate(__FILE__,__LINE__), (svn_ra_serf__wrap_err))
1781
1782#endif
1783
1784#ifdef __cplusplus
1785}
1786#endif /* __cplusplus */
1787
1788#endif /* SVN_LIBSVN_RA_SERF_RA_SERF_H */
1789