ra_serf.h revision 362181
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 <apr_uri.h>
30
31#include "svn_types.h"
32#include "svn_string.h"
33#include "svn_pools.h"
34#include "svn_ra.h"
35#include "svn_delta.h"
36#include "svn_version.h"
37#include "svn_dav.h"
38#include "svn_dirent_uri.h"
39
40#include "private/svn_dav_protocol.h"
41#include "private/svn_subr_private.h"
42#include "private/svn_editor.h"
43
44#include "blncache.h"
45
46#ifdef __cplusplus
47extern "C" {
48#endif /* __cplusplus */
49
50
51/* Enforce the minimum version of serf. */
52#if !SERF_VERSION_AT_LEAST(1, 2, 1)
53#error Please update your version of serf to at least 1.2.1.
54#endif
55
56/** Wait duration (in microseconds) used in calls to serf_context_run() */
57#define SVN_RA_SERF__CONTEXT_RUN_DURATION 500000
58
59
60
61/* Forward declarations. */
62typedef struct svn_ra_serf__session_t svn_ra_serf__session_t;
63
64/* A serf connection and optionally associated SSL context.  */
65typedef struct svn_ra_serf__connection_t {
66  /* Our connection to a server. */
67  serf_connection_t *conn;
68
69  /* Bucket allocator for this connection. */
70  serf_bucket_alloc_t *bkt_alloc;
71
72  /* Collected cert failures in chain.  */
73  int server_cert_failures;
74
75  /* What was the last HTTP status code we got on this connection? */
76  int last_status_code;
77
78  /* Optional SSL context for this connection. */
79  serf_ssl_context_t *ssl_context;
80  svn_auth_iterstate_t *ssl_client_auth_state;
81  svn_auth_iterstate_t *ssl_client_pw_auth_state;
82
83  svn_ra_serf__session_t *session;
84
85} svn_ra_serf__connection_t;
86
87/** Maximum value we'll allow for the http-max-connections config option.
88 *
89 * Note: minimum 2 connections are required for ra_serf to function
90 * correctly!
91 */
92#define SVN_RA_SERF__MAX_CONNECTIONS_LIMIT 8
93
94/*
95 * The master serf RA session.
96 *
97 * This is stored in the ra session ->priv field.
98 *
99 * ### Check ra_serf_dup_session when adding fields.
100 */
101struct svn_ra_serf__session_t {
102  /* Pool for allocations during this session */
103  apr_pool_t *pool;
104  apr_hash_t *config; /* For duplicating */
105
106  /* The current context */
107  serf_context_t *context;
108
109  /* The maximum number of connections we'll use for parallelized
110     fetch operations (updates, etc.) */
111  apr_int64_t max_connections;
112
113  /* Are we using ssl */
114  svn_boolean_t using_ssl;
115
116  /* Tristate flag that indicates if we should use compression for
117     network transmissions.  If svn_tristate_true or svn_tristate_false,
118     the compression should be enabled and disabled, respectively.
119     If svn_tristate_unknown, determine this automatically based
120     on network parameters. */
121  svn_tristate_t using_compression;
122
123  /* The user agent string */
124  const char *useragent;
125
126  /* The current connection */
127  svn_ra_serf__connection_t *conns[SVN_RA_SERF__MAX_CONNECTIONS_LIMIT];
128  int num_conns;
129  int cur_conn;
130
131  /* The URL that was passed into _open() */
132  apr_uri_t session_url;
133  const char *session_url_str;
134
135  /* The actual discovered root; may be NULL until we know it. */
136  apr_uri_t repos_root;
137  const char *repos_root_str;
138
139  /* The server is not Apache/mod_dav_svn (directly) and only supports
140     HTTP/1.0. Thus, we cannot send chunked requests.  */
141  svn_boolean_t http10;
142
143  /* We are talking to the server via http/2. Responses of scheduled
144     requests may come in any order */
145  svn_boolean_t http20;
146
147  /* Should we use Transfer-Encoding: chunked for HTTP/1.1 servers. */
148  svn_boolean_t using_chunked_requests;
149
150  /* Do we need to detect whether the connection supports chunked requests?
151     i.e. is there a (reverse) proxy that does not support them?  */
152  svn_boolean_t detect_chunking;
153
154  /* Our Version-Controlled-Configuration; may be NULL until we know it. */
155  const char *vcc_url;
156
157  /* Authentication related properties. */
158  svn_auth_iterstate_t *auth_state;
159  int auth_attempts;
160
161  /* Callback functions to get info from WC */
162  const svn_ra_callbacks2_t *wc_callbacks;
163  void *wc_callback_baton;
164  svn_auth_baton_t *auth_baton;
165
166  /* Callback function to send progress info to the client */
167  svn_ra_progress_notify_func_t progress_func;
168  void *progress_baton;
169
170  /* Callback function to handle cancellation */
171  svn_cancel_func_t cancel_func;
172  void *cancel_baton;
173
174  /* Ev2 shim callbacks */
175  svn_delta_shim_callbacks_t *shim_callbacks;
176
177  /* Error that we've received but not yet returned upstream. */
178  svn_error_t *pending_error;
179
180  /* List of authn types supported by the client.*/
181  int authn_types;
182
183  /* Maps SVN_RA_CAPABILITY_foo keys to "yes" or "no" values.
184     If a capability is not yet discovered, it is absent from the table.
185     The table itself is allocated in the svn_ra_serf__session_t's pool;
186     keys and values must have at least that lifetime.  Most likely
187     the keys and values are constants anyway (and sufficiently
188     well-informed internal code may just compare against those
189     constants' addresses, therefore). */
190  apr_hash_t *capabilities;
191
192  /* Activity collection URL.  (Cached from the initial OPTIONS
193     request when run against HTTPv1 servers.)  */
194  const char *activity_collection_url;
195
196  /* Are we using a proxy? */
197  svn_boolean_t using_proxy;
198
199  const char *proxy_username;
200  const char *proxy_password;
201  int proxy_auth_attempts;
202
203  /* SSL server certificates */
204  svn_boolean_t trust_default_ca;
205  const char *ssl_authorities;
206
207  /* Repository UUID */
208  const char *uuid;
209
210  /* Connection timeout value */
211  apr_interval_time_t timeout;
212
213  /* HTTPv1 flags */
214  svn_tristate_t supports_deadprop_count;
215
216  /*** HTTP v2 protocol stuff. ***
217   *
218   * We assume that if mod_dav_svn sends one of the special v2 OPTIONs
219   * response headers, it has sent all of them.  Specifically, we'll
220   * be looking at the presence of the "me resource" as a flag that
221   * the server supports v2 of our HTTP protocol.
222   */
223
224  /* The "me resource".  Typically used as a target for REPORTs that
225     are path-agnostic.  If we have this, we can speak HTTP v2 to the
226     server.  */
227  const char *me_resource;
228
229  /* Opaque URL "stubs".  If the OPTIONS response returns these, then
230     we know we're using HTTP protocol v2. */
231  const char *rev_stub;         /* for accessing revisions (i.e. revprops) */
232  const char *rev_root_stub;    /* for accessing REV/PATH pairs */
233  const char *txn_stub;         /* for accessing transactions (i.e. txnprops) */
234  const char *txn_root_stub;    /* for accessing TXN/PATH pairs */
235  const char *vtxn_stub;        /* for accessing transactions (i.e. txnprops) */
236  const char *vtxn_root_stub;   /* for accessing TXN/PATH pairs */
237
238  /* Hash mapping const char * server-supported POST types to
239     disinteresting-but-non-null values. */
240  apr_hash_t *supported_posts;
241
242  /*** End HTTP v2 stuff ***/
243
244  svn_ra_serf__blncache_t *blncache;
245
246  /* Trisate flag that indicates user preference for using bulk updates
247     (svn_tristate_true) with all the properties and content in the
248     update-report response. If svn_tristate_false, request a skelta
249     update-report with inlined properties. If svn_tristate_unknown then use
250     server preference. */
251  svn_tristate_t bulk_updates;
252
253  /* Indicates if the server wants bulk update requests (Prefer) or only
254     accepts skelta requests (Off). If this value is On both options are
255     allowed. */
256  const char *server_allows_bulk;
257
258  /* Indicates if the server supports sending inlined props in update editor
259   * in skelta mode (send-all == 'false'). */
260  svn_boolean_t supports_inline_props;
261
262  /* Indicates whether the server supports issuing replay REPORTs
263     against rev resources (children of `rev_stub', elsestruct). */
264  svn_boolean_t supports_rev_rsrc_replay;
265
266  /* Indicates whether the server can understand svndiff version 1. */
267  svn_boolean_t supports_svndiff1;
268
269  /* Indicates whether the server can understand svndiff version 2. */
270  svn_boolean_t supports_svndiff2;
271
272  /* Indicates whether the server sends the result checksum in the response
273   * to a successful PUT request. */
274  svn_boolean_t supports_put_result_checksum;
275
276  apr_interval_time_t conn_latency;
277};
278
279#define SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(sess) ((sess)->me_resource != NULL)
280
281/*
282 * Structure which represents a DAV element with a NAMESPACE and NAME.
283 */
284typedef struct svn_ra_serf__dav_props_t {
285  /* Element namespace */
286  const char *xmlns;
287  /* Element name */
288  const char *name;
289} svn_ra_serf__dav_props_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/* Run the context once. Manage waittime_left to handle timing out when
382   nothing happens over the session->timout.
383 */
384svn_error_t *
385svn_ra_serf__context_run(svn_ra_serf__session_t *sess,
386                         apr_interval_time_t *waittime_left,
387                         apr_pool_t *scratch_pool);
388
389
390
391/* Callback for response handlers */
392typedef svn_error_t *
393(*svn_ra_serf__response_handler_t)(serf_request_t *request,
394                                   serf_bucket_t *response,
395                                   void *handler_baton,
396                                   apr_pool_t *scratch_pool);
397
398/* Callback when the request is done */
399typedef svn_error_t *
400(*svn_ra_serf__response_done_delegate_t)(serf_request_t *request,
401                                         void *done_baton,
402                                         apr_pool_t *scratch_pool);
403
404/* Callback for when a request body is needed. */
405typedef svn_error_t *
406(*svn_ra_serf__request_body_delegate_t)(serf_bucket_t **body_bkt,
407                                        void *baton,
408                                        serf_bucket_alloc_t *alloc,
409                                        apr_pool_t *request_pool,
410                                        apr_pool_t *scratch_pool);
411
412/* Callback for when request headers are needed. */
413typedef svn_error_t *
414(*svn_ra_serf__request_header_delegate_t)(serf_bucket_t *headers,
415                                          void *baton,
416                                          apr_pool_t *request_pool,
417                                          apr_pool_t *scratch_pool);
418
419/* Callback for when a response has an error. */
420typedef svn_error_t *
421(*svn_ra_serf__response_error_t)(serf_request_t *request,
422                                 serf_bucket_t *response,
423                                 int status_code,
424                                 void *baton);
425
426/* ### we should reorder the types in this file.  */
427typedef struct svn_ra_serf__server_error_t svn_ra_serf__server_error_t;
428
429/*
430 * Structure that can be passed to our default handler to guide the
431 * execution of the request through its lifecycle.
432 *
433 * Use svn_ra_serf__create_handler() to create instances of this struct.
434 */
435typedef struct svn_ra_serf__handler_t {
436  /* The HTTP method string of the request */
437  const char *method;
438
439  /* The resource to the execute the method on. */
440  const char *path;
441
442  /* The content-type of the request body. */
443  const char *body_type;
444
445  /* If TRUE then default Accept-Encoding request header is not configured for
446     request. If FALSE then 'gzip' accept encoding will be used if compression
447     enabled. */
448  svn_boolean_t custom_accept_encoding;
449
450  /* If TRUE then default DAV: capabilities request headers is not configured
451     for request. */
452  svn_boolean_t no_dav_headers;
453
454  /* If TRUE doesn't fail requests on HTTP error statuses like 405, 408, 500
455     (see util.c response_done()) */
456  svn_boolean_t no_fail_on_http_failure_status;
457
458  /* If TRUE doesn't fail requests on HTTP redirect statuses like 301, 307 */
459  svn_boolean_t no_fail_on_http_redirect_status;
460
461  /* Has the request/response been completed?  */
462  svn_boolean_t done;
463  svn_boolean_t scheduled; /* Is the request scheduled in a context */
464
465  /* If we captured an error from the server, then this will be non-NULL.
466     It will be allocated from HANDLER_POOL.  */
467  svn_ra_serf__server_error_t *server_error;
468
469  /* The handler and baton pair for our handler. */
470  svn_ra_serf__response_handler_t response_handler;
471  void *response_baton;
472
473  /* When REPONSE_HANDLER is invoked, the following fields will be set
474     based on the response header. HANDLER_POOL must be non-NULL for these
475     values to be filled in. SLINE.REASON and LOCATION will be allocated
476     within HANDLER_POOL.  */
477  serf_status_line sline;  /* The parsed Status-Line  */
478  const char *location;  /* The Location: header, if any  */
479
480  /* This function and baton pair allows handling the completion of request.
481   *
482   * The default handler is responsible for the HTTP failure processing.
483   *
484   * If no_fail_on_http_failure_status is not TRUE, then the callback will
485   * return recorded server errors or if there is none and the http status
486   * specifies an error returns an error for that.
487   *
488   * The default baton is the handler itself.
489   */
490  svn_ra_serf__response_done_delegate_t done_delegate;
491  void *done_delegate_baton;
492
493  /* The handler and baton pair to be executed when a non-recoverable error
494   * is detected.  If it is NULL in the presence of an error, an abort() may
495   * be triggered.
496   */
497  svn_ra_serf__response_error_t response_error;
498  void *response_error_baton;
499
500  /* This function and baton pair allows for custom request headers to
501   * be set.
502   *
503   * It will be executed after the request has been set up but before it is
504   * delivered.
505   */
506  svn_ra_serf__request_header_delegate_t header_delegate;
507  void *header_delegate_baton;
508
509  /* This function and baton pair allows a body to be created right before
510   * delivery.
511   *
512   * It will be executed after the request has been set up but before it is
513   * delivered.
514   *
515   * May be NULL if there is no body to send.
516   *
517   */
518  svn_ra_serf__request_body_delegate_t body_delegate;
519  void *body_delegate_baton;
520
521  /* The connection and session to be used for this request. */
522  svn_ra_serf__connection_t *conn;
523  svn_ra_serf__session_t *session;
524
525  /* Internal flag to indicate we've parsed the headers.  */
526  svn_boolean_t reading_body;
527
528  /* When this flag will be set, the core handler will discard any unread
529     portion of the response body. The registered response handler will
530     no longer be called.  */
531  svn_boolean_t discard_body;
532
533  /* Pool for allocating SLINE.REASON and LOCATION. If this pool is NULL,
534     then the requestor does not care about SLINE and LOCATION.  */
535  apr_pool_t *handler_pool;
536} svn_ra_serf__handler_t;
537
538
539/* Run one request and process the response.
540
541   Similar to context_run_wait(), but this creates the request for HANDLER
542   and then waits for it to complete.
543
544   WARNING: context_run_wait() does NOT create a request, whereas this
545   function DOES. Avoid a double-create.  */
546svn_error_t *
547svn_ra_serf__context_run_one(svn_ra_serf__handler_t *handler,
548                             apr_pool_t *scratch_pool);
549
550
551/*
552 * Helper function to queue a request in the @a handler's connection.
553 */
554void svn_ra_serf__request_create(svn_ra_serf__handler_t *handler);
555
556/* v2 of the XML parsing functions  */
557
558/* The XML parsing context.  */
559typedef struct svn_ra_serf__xml_context_t svn_ra_serf__xml_context_t;
560
561
562/* An opaque structure for the XML parse element/state.  */
563typedef struct svn_ra_serf__xml_estate_t svn_ra_serf__xml_estate_t;
564
565/* Called just after the parser moves into ENTERED_STATE. The tag causing
566   the transition is passed in TAG.
567
568   This callback is applied to a parsing context by using the
569   svn_ra_serf__xml_context_customize() function.
570
571   NOTE: this callback, when set, will be invoked on *every* transition.
572   The callback must examine ENTERED_STATE to determine if any action
573   must be taken. The original state is not provided, but must be derived
574   from ENTERED_STATE and/or the TAG causing the transition (if needed).  */
575typedef svn_error_t *
576(*svn_ra_serf__xml_opened_t)(svn_ra_serf__xml_estate_t *xes,
577                             void *baton,
578                             int entered_state,
579                             const svn_ra_serf__dav_props_t *tag,
580                             apr_pool_t *scratch_pool);
581
582
583/* Called just before the parser leaves LEAVING_STATE.
584
585   If cdata collection was enabled for this state, then CDATA will be
586   non-NULL and contain the collected cdata.
587
588   If attribute collection was enabled for this state, then ATTRS will
589   contain the attributes collected for this element only, along with
590   any values stored via svn_ra_serf__xml_note().
591
592   Use svn_ra_serf__xml_gather_since() to gather up data from outer states.
593
594   ATTRS is char* -> char*.
595
596   Temporary allocations may be made in SCRATCH_POOL.  */
597typedef svn_error_t *
598(*svn_ra_serf__xml_closed_t)(svn_ra_serf__xml_estate_t *xes,
599                             void *baton,
600                             int leaving_state,
601                             const svn_string_t *cdata,
602                             apr_hash_t *attrs,
603                             apr_pool_t *scratch_pool);
604
605
606/* Called for all states that are not using the builtin cdata collection.
607   This callback is (only) appropriate for unbounded-size cdata content.
608
609   CURRENT_STATE may be used to decide what to do with the data.
610
611   Temporary allocations may be made in SCRATCH_POOL.  */
612typedef svn_error_t *
613(*svn_ra_serf__xml_cdata_t)(svn_ra_serf__xml_estate_t *xes,
614                            void *baton,
615                            int current_state,
616                            const char *data,
617                            apr_size_t len,
618                            apr_pool_t *scratch_pool);
619
620
621/* Magic state value for the initial state in a svn_ra_serf__xml_transition_t
622   table */
623#define XML_STATE_INITIAL 0
624
625/* State transition table.
626
627   When the XML Context is constructed, it is in state 0. User states are
628   positive integers.
629
630   In a list of transitions, use { 0 } to indicate the end. Specifically,
631   the code looks for NS == NULL.
632
633   The initial state for each transition table is XML_STATE_INITIAL.
634
635   ### more docco
636*/
637typedef struct svn_ra_serf__xml_transition_t {
638  /* This transition applies when in this state  */
639  int from_state;
640
641  /* And when this tag is observed  */
642  const char *ns;
643  const char *name;
644
645  /* Moving to this state  */
646  int to_state;
647
648  /* Should the cdata of NAME be collected? Note that CUSTOM_CLOSE should
649     be TRUE in order to capture this cdata.  */
650  svn_boolean_t collect_cdata;
651
652  /* Which attributes of NAME should be collected? Terminate with NULL.
653     Maximum of 10 attributes may be collected. Note that attribute
654     namespaces are ignored at this time.
655
656     Attribute names beginning with "?" are optional. Other names must
657     exist on the element, or SVN_ERR_XML_ATTRIB_NOT_FOUND will be raised.  */
658  const char *collect_attrs[11];
659
660  /* When NAME is closed, should the callback be invoked?  */
661  svn_boolean_t custom_close;
662
663} svn_ra_serf__xml_transition_t;
664
665/* Constructor for svn_ra_serf__handler_t. Initializes a new handler
666   with default settings for SESSION. */
667svn_ra_serf__handler_t *
668svn_ra_serf__create_handler(svn_ra_serf__session_t *session,
669                            apr_pool_t *result_pool);
670
671/* Construct an XML parsing context, based on the TTABLE transition table.
672   As content is parsed, the CLOSED_CB callback will be invoked according
673   to the definition in the table.
674
675   If OPENED_CB is not NULL, then it will be invoked for *every* tag-open
676   event. The callback will need to use the ENTERED_STATE and TAG parameters
677   to decide what it would like to do.
678
679   If CDATA_CB is not NULL, then it will be called for all cdata that is
680   not be automatically collected (based on the transition table record's
681   COLLECT_CDATA flag). It will be called in every state, so the callback
682   must examine the CURRENT_STATE parameter to decide what to do.
683
684   The same BATON value will be passed to all three callbacks.
685
686   The context will be created within RESULT_POOL.  */
687svn_ra_serf__xml_context_t *
688svn_ra_serf__xml_context_create(
689  const svn_ra_serf__xml_transition_t *ttable,
690  svn_ra_serf__xml_opened_t opened_cb,
691  svn_ra_serf__xml_closed_t closed_cb,
692  svn_ra_serf__xml_cdata_t cdata_cb,
693  void *baton,
694  apr_pool_t *result_pool);
695
696/* Verifies if the parsing completed successfully and destroys
697   all subpools. */
698svn_error_t *
699svn_ra_serf__xml_context_done(svn_ra_serf__xml_context_t *xmlctx);
700
701/* Construct a handler with the response function/baton set up to parse
702   a response body using the given XML context. The handler and its
703   internal structures are allocated in RESULT_POOL.
704
705   As part of the handling the http status value is compared to 200, or
706   if EXPECTED_STATUS is not NULL to all the values in EXPECTED_STATUS.
707   EXPECTED_STATUS is expected to be a list of integers ending with a 0
708   that lives at least as long as RESULT_POOL. If the status doesn't
709   match the request has failed and will be parsed as en error response.
710
711   This also initializes HANDLER_POOL to the given RESULT_POOL.  */
712svn_ra_serf__handler_t *
713svn_ra_serf__create_expat_handler(svn_ra_serf__session_t *session,
714                                  svn_ra_serf__xml_context_t *xmlctx,
715                                  const int *expected_status,
716                                  apr_pool_t *result_pool);
717
718
719/* Allocated within XES->STATE_POOL. Changes are not allowd (callers
720   should make a deep copy if they need to make changes).
721
722   The resulting hash maps char* names to char* values.  */
723apr_hash_t *
724svn_ra_serf__xml_gather_since(svn_ra_serf__xml_estate_t *xes,
725                              int stop_state);
726
727
728/* Attach the NAME/VALUE pair onto this/parent state identified by STATE.
729   The name and value will be copied into the target state's pool.
730
731   These values will be available to the CLOSED_CB for the target state,
732   or part of the gathered state via xml_gather_since().
733
734   Typically, this function is used by a child state's close callback,
735   or within an opening callback to store additional data.
736
737   Note: if the state is not found, then a programmer error has occurred,
738   so the function will invoke SVN_ERR_MALFUNCTION().  */
739void
740svn_ra_serf__xml_note(svn_ra_serf__xml_estate_t *xes,
741                      int state,
742                      const char *name,
743                      const char *value);
744
745
746/* Returns XES->STATE_POOL for allocating structures that should live
747   as long as the state identified by XES.
748
749   Note: a state pool is created upon demand, so only use this function
750   when memory is required for a given state.  */
751apr_pool_t *
752svn_ra_serf__xml_state_pool(svn_ra_serf__xml_estate_t *xes);
753
754/*
755 * Parses a server-side error message into a local Subversion error.
756 */
757struct svn_ra_serf__server_error_t {
758  apr_pool_t *pool;
759
760  /* XML parser and namespace used to parse the remote response */
761  svn_ra_serf__xml_context_t *xmlctx;
762
763  svn_ra_serf__response_handler_t response_handler;
764  void *response_baton;
765
766  /* The partial errors to construct the final error from */
767  apr_array_header_t *items;
768
769  /* The hooked handler */
770  svn_ra_serf__handler_t *handler;
771};
772
773/*
774 * Handler that discards the entire @a response body associated with a
775 * @a request.  Implements svn_ra_serf__response_handler_t.
776 *
777 * If @a baton is a svn_ra_serf__server_error_t (i.e. non-NULL) and an
778 * error is detected, it will be populated for later detection.
779 *
780 * All temporary allocations will be made in a @a pool.
781 */
782svn_error_t *
783svn_ra_serf__handle_discard_body(serf_request_t *request,
784                                 serf_bucket_t *response,
785                                 void *baton,
786                                 apr_pool_t *pool);
787
788
789/*
790 * Handler that retrieves the embedded XML multistatus response from the
791 * the @a RESPONSE body associated with a @a REQUEST.
792 *
793 * Implements svn_ra_serf__response_handler_t.
794 *
795 * The @a BATON should be of type svn_ra_serf__handler_t. When the request
796 * is complete, the handler's DONE flag will be set to TRUE.
797 *
798 * All temporary allocations will be made in a @a scratch_pool.
799 */
800svn_error_t *
801svn_ra_serf__handle_multistatus_only(serf_request_t *request,
802                                     serf_bucket_t *response,
803                                     void *baton,
804                                     apr_pool_t *scratch_pool);
805
806
807/* Handler that expects an empty body.
808
809   If a body IS present, and it is text/xml, then it will be parsed for
810   a server-side error.
811
812   BATON should be the svn_ra_serf__handler_t running REQUEST.
813
814   Status line information will be in HANDLER->SLINE.
815
816   Any parsed errors will be left in HANDLER->SERVER_ERROR. That member
817   may be NULL if no body was present, or a problem occurred trying to
818   parse the body.
819
820   All temporary allocations will be made in SCRATCH_POOL.  */
821svn_error_t *
822svn_ra_serf__expect_empty_body(serf_request_t *request,
823                               serf_bucket_t *response,
824                               void *baton,
825                               apr_pool_t *scratch_pool);
826
827
828/*
829 * This function sets up error parsing for an existing request
830 */
831svn_error_t *
832svn_ra_serf__setup_error_parsing(svn_ra_serf__server_error_t **server_err,
833                                 svn_ra_serf__handler_t *handler,
834                                 svn_boolean_t expect_207_only,
835                                 apr_pool_t *result_pool,
836                                 apr_pool_t *scratch_pool);
837
838/*
839 * Forwards response data to the server error parser
840 */
841svn_error_t *
842svn_ra_serf__handle_server_error(svn_ra_serf__server_error_t *server_error,
843                                 svn_ra_serf__handler_t *handler,
844                                 serf_request_t *request,
845                                 serf_bucket_t *response,
846                                 apr_status_t *serf_status,
847                                 apr_pool_t *scratch_pool);
848
849/*
850 * Creates the svn_error_t * instance from the error recorded in
851 * HANDLER->server_error
852 */
853svn_error_t *
854svn_ra_serf__server_error_create(svn_ra_serf__handler_t *handler,
855                                 apr_pool_t *scratch_pool);
856
857/* serf_response_handler_t implementation that completely discards
858 * the response.
859 *
860 * All temporary allocations will be made in @a pool.
861 */
862apr_status_t
863svn_ra_serf__response_discard_handler(serf_request_t *request,
864                                      serf_bucket_t *response,
865                                      void *baton,
866                                      apr_pool_t *pool);
867
868
869/*
870 * Add the appropriate serf buckets to @a agg_bucket represented by
871 * the XML * @a tag and @a value.
872 *
873 * The bucket will be allocated from @a bkt_alloc.
874 */
875void
876svn_ra_serf__add_tag_buckets(serf_bucket_t *agg_bucket,
877                             const char *tag,
878                             const char *value,
879                             serf_bucket_alloc_t *bkt_alloc);
880
881/*
882 * Add the appropriate serf buckets to AGG_BUCKET with standard XML header:
883 *  <?xml version="1.0" encoding="utf-8"?>
884 *
885 * The bucket will be allocated from BKT_ALLOC.
886 */
887void
888svn_ra_serf__add_xml_header_buckets(serf_bucket_t *agg_bucket,
889                                    serf_bucket_alloc_t *bkt_alloc);
890
891/*
892 * Add the appropriate serf buckets to AGG_BUCKET representing the XML
893 * open tag with name TAG.
894 *
895 * Take the tag's attributes from varargs, a NULL-terminated list of
896 * alternating <tt>char *</tt> key and <tt>char *</tt> val.  Attribute
897 * will be ignored if it's value is NULL.
898 *
899 * NOTE: Callers are responsible for XML-escaping attribute values as
900 * necessary.
901 *
902 * The bucket will be allocated from BKT_ALLOC.
903 */
904void
905svn_ra_serf__add_open_tag_buckets(serf_bucket_t *agg_bucket,
906                                  serf_bucket_alloc_t *bkt_alloc,
907                                  const char *tag,
908                                  ...) SVN_NEEDS_SENTINEL_NULL;
909
910/*
911 * Add the appropriate serf buckets to AGG_BUCKET representing xml tag close
912 * with name TAG.
913 *
914 * The bucket will be allocated from BKT_ALLOC.
915 */
916void
917svn_ra_serf__add_close_tag_buckets(serf_bucket_t *agg_bucket,
918                                   serf_bucket_alloc_t *bkt_alloc,
919                                   const char *tag);
920
921/* Add the appropriate serf buckets to AGG_BUCKET representing the XML
922 * open tag with name TAG, and then immediately closes the tag using the />
923 * notation
924 */
925void
926svn_ra_serf__add_empty_tag_buckets(serf_bucket_t *agg_bucket,
927                                   serf_bucket_alloc_t *bkt_alloc,
928                                   const char *tag,
929                                   ...) SVN_NEEDS_SENTINEL_NULL;
930
931/*
932 * Add the appropriate serf buckets to AGG_BUCKET with xml-escaped
933 * version of DATA.
934 *
935 * The bucket will be allocated from BKT_ALLOC.
936 */
937void
938svn_ra_serf__add_cdata_len_buckets(serf_bucket_t *agg_bucket,
939                                   serf_bucket_alloc_t *bkt_alloc,
940                                   const char *data, apr_size_t len);
941
942
943/** PROPFIND-related functions **/
944
945/* Removes all non regular properties from PROPS */
946void
947svn_ra_serf__keep_only_regular_props(apr_hash_t *props,
948                                     apr_pool_t *scratch_pool);
949
950
951/* Callback used via svn_ra_serf__deliver_props2 */
952typedef svn_error_t *
953(*svn_ra_serf__prop_func_t)(void *baton,
954                            const char *path,
955                            const char *ns,
956                            const char *name,
957                            const svn_string_t *value,
958                            apr_pool_t *scratch_pool);
959
960/*
961 * Implementation of svn_ra_serf__prop_func_t that just delivers svn compatible
962 * properties  in the apr_hash_t * that is used as baton.
963 */
964svn_error_t *
965svn_ra_serf__deliver_svn_props(void *baton,
966                               const char *path,
967                               const char *ns,
968                               const char *name,
969                               const svn_string_t *value,
970                               apr_pool_t *scratch_pool);
971
972/*
973 * This function will create a handler for a PROPFIND request, which will deliver
974 * properties to PROP_FUNC() with PROP_BATON for the properties listed in LOOKUP_PROPS
975 * at URL for DEPTH ("0","1","infinity").
976 */
977svn_error_t *
978svn_ra_serf__create_propfind_handler(svn_ra_serf__handler_t **handler,
979                                     svn_ra_serf__session_t *session,
980                                     const char *path,
981                                     svn_revnum_t rev,
982                                     const char *depth,
983                                     const svn_ra_serf__dav_props_t *find_props,
984                                     svn_ra_serf__prop_func_t prop_func,
985                                     void *prop_func_baton,
986                                     apr_pool_t *result_pool);
987
988
989/* Using SESSION, fetch the properties specified by WHICH_PROPS using CONN
990   for URL at REVISION. The resulting properties are placed into a 2-level
991   hash in RESULTS, mapping NAMESPACE -> hash<PROPNAME, PROPVALUE>, which
992   is allocated in RESULT_POOL.
993
994   If REVISION is SVN_INVALID_REVNUM, then the properties are fetched
995   from HEAD for URL.
996
997   This function performs the request synchronously.
998
999   Temporary allocations are made in SCRATCH_POOL.  */
1000svn_error_t *
1001svn_ra_serf__fetch_node_props(apr_hash_t **results,
1002                              svn_ra_serf__session_t *session,
1003                              const char *url,
1004                              svn_revnum_t revision,
1005                              const svn_ra_serf__dav_props_t *which_props,
1006                              apr_pool_t *result_pool,
1007                              apr_pool_t *scratch_pool);
1008
1009
1010/* Using SESSION, fetch a DAV: property from the resource identified by URL
1011   within REVISION. The PROPNAME may be one of:
1012
1013     "checked-in"
1014     "href"
1015
1016   The resulting value will be allocated in RESULT_POOL, and may be NULL
1017   if the property does not exist (note: "href" always exists).
1018
1019   This function performs the request synchronously.
1020
1021   Temporary allocations are made in SCRATCH_POOL.  */
1022svn_error_t *
1023svn_ra_serf__fetch_dav_prop(const char **value,
1024                            svn_ra_serf__session_t *session,
1025                            const char *url,
1026                            svn_revnum_t revision,
1027                            const char *propname,
1028                            apr_pool_t *result_pool,
1029                            apr_pool_t *scratch_pool);
1030
1031/* Map a property name, as passed over the wire, into its corresponding
1032   Subversion-internal name. The returned name will be a static value,
1033   or allocated within RESULT_POOL.
1034
1035   If the property should be ignored (eg. some DAV properties), then NULL
1036   will be returned.  */
1037const char *
1038svn_ra_serf__svnname_from_wirename(const char *ns,
1039                                   const char *name,
1040                                   apr_pool_t *result_pool);
1041
1042/** MERGE-related functions **/
1043
1044void
1045svn_ra_serf__merge_lock_token_list(apr_hash_t *lock_tokens,
1046                                   const char *parent,
1047                                   serf_bucket_t *body,
1048                                   serf_bucket_alloc_t *alloc,
1049                                   apr_pool_t *pool);
1050
1051/* Create an MERGE request aimed at the SESSION url, requesting the
1052   merge of the resource identified by MERGE_RESOURCE_URL.
1053   LOCK_TOKENS is a hash mapping paths to lock tokens owned by the
1054   client.  If KEEP_LOCKS is set, instruct the server to not release
1055   locks set on the paths included in this commit.  */
1056svn_error_t *
1057svn_ra_serf__run_merge(const svn_commit_info_t **commit_info,
1058                       svn_ra_serf__session_t *session,
1059                       const char *merge_resource_url,
1060                       apr_hash_t *lock_tokens,
1061                       svn_boolean_t keep_locks,
1062                       apr_pool_t *result_pool,
1063                       apr_pool_t *scratch_pool);
1064
1065
1066/** OPTIONS-related functions **/
1067
1068/* When running with a proxy, we may need to detect and correct for problems.
1069   This probing function will send a simple OPTIONS request to detect problems
1070   with the connection.  */
1071svn_error_t *
1072svn_ra_serf__probe_proxy(svn_ra_serf__session_t *serf_sess,
1073                         apr_pool_t *scratch_pool);
1074
1075
1076/* On HTTPv2 connections, run an OPTIONS request over CONN to fetch the
1077   current youngest revnum, returning it in *YOUNGEST.
1078
1079   (the revnum is headers of the OPTIONS response)
1080
1081   This function performs the request synchronously.
1082
1083   All temporary allocations will be made in SCRATCH_POOL.  */
1084svn_error_t *
1085svn_ra_serf__v2_get_youngest_revnum(svn_revnum_t *youngest,
1086                                    svn_ra_serf__session_t *session,
1087                                    apr_pool_t *scratch_pool);
1088
1089
1090/* On HTTPv1 connections, run an OPTIONS request over CONN to fetch the
1091   activity collection set and return it in *ACTIVITY_URL, allocated
1092   from RESULT_POOL.
1093
1094   (the activity-collection-set is in the body of the OPTIONS response)
1095
1096   This function performs the request synchronously.
1097
1098   All temporary allocations will be made in SCRATCH_POOL.  */
1099svn_error_t *
1100svn_ra_serf__v1_get_activity_collection(const char **activity_url,
1101                                        svn_ra_serf__session_t *session,
1102                                        apr_pool_t *result_pool,
1103                                        apr_pool_t *scratch_pool);
1104
1105
1106/* Set @a VCC_URL to the default VCC for our repository based on @a
1107 * ORIG_PATH for the session @a SESSION, ensuring that the VCC URL and
1108 * repository root URLs are cached in @a SESSION.
1109 *
1110 * All temporary allocations will be made in @a SCRATCH_POOL. */
1111svn_error_t *
1112svn_ra_serf__discover_vcc(const char **vcc_url,
1113                          svn_ra_serf__session_t *session,
1114                          apr_pool_t *scratch_pool);
1115
1116/* Set @a REPORT_TARGET to the URI of the resource at which generic
1117 * (path-agnostic) REPORTs should be aimed for @a SESSION.
1118 *
1119 * All temporary allocations will be made in @a POOL.
1120 */
1121svn_error_t *
1122svn_ra_serf__report_resource(const char **report_target,
1123                             svn_ra_serf__session_t *session,
1124                             apr_pool_t *pool);
1125
1126/* Set @a REL_PATH to a path (not URI-encoded) relative to the root of
1127 * the repository pointed to by @a SESSION, based on original path
1128 * (URI-encoded) @a ORIG_PATH.  Use @a CONN for any required network
1129 * communications if it is non-NULL; otherwise use the default
1130 * connection.  Use POOL for allocations.  */
1131svn_error_t *
1132svn_ra_serf__get_relative_path(const char **rel_path,
1133                               const char *orig_path,
1134                               svn_ra_serf__session_t *session,
1135                               apr_pool_t *pool);
1136
1137
1138/* Using the default connection in SESSION (conns[0]), get the youngest
1139   revnum from the server, returning it in *YOUNGEST.
1140
1141   This function operates synchronously.
1142
1143   All temporary allocations are performed in SCRATCH_POOL.  */
1144svn_error_t *
1145svn_ra_serf__get_youngest_revnum(svn_revnum_t *youngest,
1146                                 svn_ra_serf__session_t *session,
1147                                 apr_pool_t *scratch_pool);
1148
1149
1150/* Generate a revision-stable URL.
1151
1152   The RA APIs all refer to user/public URLs that float along with the
1153   youngest revision. In many cases, we do NOT want to work with that URL
1154   since it can change from one moment to the next. Especially if we
1155   attempt to operation against multiple floating URLs -- we could end up
1156   referring to two separate revisions.
1157
1158   The DAV RA provider(s) solve this by generating a URL that is specific
1159   to a revision by using a URL into a "baseline collection".
1160
1161   For a specified SESSION, generate a revision-stable URL for URL at
1162   REVISION. If REVISION is    SVN_INVALID_REVNUM, then the stable URL will
1163   refer to the youngest revision at the time this function was called.
1164
1165   If URL is NULL, then the session root will be used.
1166
1167   The stable URL will be placed into *STABLE_URL, allocated from RESULT_POOL.
1168
1169   If LATEST_REVNUM is not NULL, then the revision used will be placed into
1170   *LATEST_REVNUM. That will be equal to youngest, or the given REVISION.
1171
1172   This function operates synchronously, if any communication to the server
1173   is required. Communication is needed if REVISION is SVN_INVALID_REVNUM
1174   (to get the current youngest revnum), or if the specified REVISION is not
1175   (yet) in our cache of baseline collections.
1176
1177   All temporary allocations are performed in SCRATCH_POOL.  */
1178svn_error_t *
1179svn_ra_serf__get_stable_url(const char **stable_url,
1180                            svn_revnum_t *latest_revnum,
1181                            svn_ra_serf__session_t *session,
1182                            const char *url,
1183                            svn_revnum_t revision,
1184                            apr_pool_t *result_pool,
1185                            apr_pool_t *scratch_pool);
1186
1187
1188/** RA functions **/
1189
1190/* Implements svn_ra__vtable_t.reparent(). */
1191svn_error_t *
1192svn_ra_serf__reparent(svn_ra_session_t *ra_session,
1193                      const char *url,
1194                      apr_pool_t *pool);
1195
1196/* Implements svn_ra__vtable_t.rev_prop(). */
1197svn_error_t *
1198svn_ra_serf__rev_prop(svn_ra_session_t *session,
1199                      svn_revnum_t rev,
1200                      const char *name,
1201                      svn_string_t **value,
1202                      apr_pool_t *pool);
1203
1204/* Implements svn_ra__vtable_t.get_log(). */
1205svn_error_t *
1206svn_ra_serf__get_log(svn_ra_session_t *session,
1207                     const apr_array_header_t *paths,
1208                     svn_revnum_t start,
1209                     svn_revnum_t end,
1210                     int limit,
1211                     svn_boolean_t discover_changed_paths,
1212                     svn_boolean_t strict_node_history,
1213                     svn_boolean_t include_merged_revisions,
1214                     const apr_array_header_t *revprops,
1215                     svn_log_entry_receiver_t receiver,
1216                     void *receiver_baton,
1217                     apr_pool_t *pool);
1218
1219/* Implements svn_ra__vtable_t.check_path(). */
1220svn_error_t *
1221svn_ra_serf__check_path(svn_ra_session_t *ra_session,
1222                        const char *rel_path,
1223                        svn_revnum_t revision,
1224                        svn_node_kind_t *kind,
1225                        apr_pool_t *pool);
1226
1227/* Implements svn_ra__vtable_t.stat(). */
1228svn_error_t *
1229svn_ra_serf__stat(svn_ra_session_t *ra_session,
1230                  const char *rel_path,
1231                  svn_revnum_t revision,
1232                  svn_dirent_t **dirent,
1233                  apr_pool_t *pool);
1234
1235/* Implements svn_ra__vtable_t.get_locations(). */
1236svn_error_t *
1237svn_ra_serf__get_locations(svn_ra_session_t *session,
1238                           apr_hash_t **locations,
1239                           const char *path,
1240                           svn_revnum_t peg_revision,
1241                           const apr_array_header_t *location_revisions,
1242                           apr_pool_t *pool);
1243
1244/* Implements svn_ra__vtable_t.get_location_segments(). */
1245svn_error_t *
1246svn_ra_serf__get_location_segments(svn_ra_session_t *session,
1247                                   const char *path,
1248                                   svn_revnum_t peg_revision,
1249                                   svn_revnum_t start_rev,
1250                                   svn_revnum_t end_rev,
1251                                   svn_location_segment_receiver_t receiver,
1252                                   void *receiver_baton,
1253                                   apr_pool_t *pool);
1254
1255/* Implements svn_ra__vtable_t.do_diff(). */
1256svn_error_t *
1257svn_ra_serf__do_diff(svn_ra_session_t *session,
1258                     const svn_ra_reporter3_t **reporter,
1259                     void **report_baton,
1260                     svn_revnum_t revision,
1261                     const char *diff_target,
1262                     svn_depth_t depth,
1263                     svn_boolean_t ignore_ancestry,
1264                     svn_boolean_t text_deltas,
1265                     const char *versus_url,
1266                     const svn_delta_editor_t *diff_editor,
1267                     void *diff_baton,
1268                     apr_pool_t *pool);
1269
1270/* Implements svn_ra__vtable_t.do_status(). */
1271svn_error_t *
1272svn_ra_serf__do_status(svn_ra_session_t *ra_session,
1273                       const svn_ra_reporter3_t **reporter,
1274                       void **report_baton,
1275                       const char *status_target,
1276                       svn_revnum_t revision,
1277                       svn_depth_t depth,
1278                       const svn_delta_editor_t *status_editor,
1279                       void *status_baton,
1280                       apr_pool_t *pool);
1281
1282/* Implements svn_ra__vtable_t.do_update(). */
1283svn_error_t *
1284svn_ra_serf__do_update(svn_ra_session_t *ra_session,
1285                       const svn_ra_reporter3_t **reporter,
1286                       void **report_baton,
1287                       svn_revnum_t revision_to_update_to,
1288                       const char *update_target,
1289                       svn_depth_t depth,
1290                       svn_boolean_t send_copyfrom_args,
1291                       svn_boolean_t ignore_ancestry,
1292                       const svn_delta_editor_t *update_editor,
1293                       void *update_baton,
1294                       apr_pool_t *result_pool,
1295                       apr_pool_t *scratch_pool);
1296
1297/* Implements svn_ra__vtable_t.do_switch(). */
1298svn_error_t *
1299svn_ra_serf__do_switch(svn_ra_session_t *ra_session,
1300                       const svn_ra_reporter3_t **reporter,
1301                       void **report_baton,
1302                       svn_revnum_t revision_to_switch_to,
1303                       const char *switch_target,
1304                       svn_depth_t depth,
1305                       const char *switch_url,
1306                       svn_boolean_t send_copyfrom_args,
1307                       svn_boolean_t ignore_ancestry,
1308                       const svn_delta_editor_t *switch_editor,
1309                       void *switch_baton,
1310                       apr_pool_t *result_pool,
1311                       apr_pool_t *scratch_pool);
1312
1313/* Implements svn_ra__vtable_t.get_file_revs(). */
1314svn_error_t *
1315svn_ra_serf__get_file_revs(svn_ra_session_t *session,
1316                           const char *path,
1317                           svn_revnum_t start,
1318                           svn_revnum_t end,
1319                           svn_boolean_t include_merged_revisions,
1320                           svn_file_rev_handler_t handler,
1321                           void *handler_baton,
1322                           apr_pool_t *pool);
1323
1324/* Implements svn_ra__vtable_t.get_dated_revision(). */
1325svn_error_t *
1326svn_ra_serf__get_dated_revision(svn_ra_session_t *session,
1327                                svn_revnum_t *revision,
1328                                apr_time_t tm,
1329                                apr_pool_t *pool);
1330
1331/* Implements svn_ra__vtable_t.get_commit_editor().
1332 *
1333 * Note: Like other commit editors, the returned editor requires that the
1334 * @c copyfrom_path parameter passed to its @c add_file and @c add_directory
1335 * methods is a URL, not a relative path.
1336 */
1337svn_error_t *
1338svn_ra_serf__get_commit_editor(svn_ra_session_t *session,
1339                               const svn_delta_editor_t **editor,
1340                               void **edit_baton,
1341                               apr_hash_t *revprop_table,
1342                               svn_commit_callback2_t callback,
1343                               void *callback_baton,
1344                               apr_hash_t *lock_tokens,
1345                               svn_boolean_t keep_locks,
1346                               apr_pool_t *pool);
1347
1348/* Implements svn_ra__vtable_t.get_file(). */
1349svn_error_t *
1350svn_ra_serf__get_file(svn_ra_session_t *session,
1351                      const char *path,
1352                      svn_revnum_t revision,
1353                      svn_stream_t *stream,
1354                      svn_revnum_t *fetched_rev,
1355                      apr_hash_t **props,
1356                      apr_pool_t *pool);
1357
1358/* Implements svn_ra__vtable_t.get_dir(). */
1359svn_error_t *
1360svn_ra_serf__get_dir(svn_ra_session_t *ra_session,
1361                     apr_hash_t **dirents,
1362                     svn_revnum_t *fetched_rev,
1363                     apr_hash_t **ret_props,
1364                     const char *rel_path,
1365                     svn_revnum_t revision,
1366                     apr_uint32_t dirent_fields,
1367                     apr_pool_t *result_pool);
1368
1369/* Implements svn_ra__vtable_t.change_rev_prop(). */
1370svn_error_t *
1371svn_ra_serf__change_rev_prop(svn_ra_session_t *session,
1372                             svn_revnum_t rev,
1373                             const char *name,
1374                             const svn_string_t *const *old_value_p,
1375                             const svn_string_t *value,
1376                             apr_pool_t *pool);
1377
1378/* Implements svn_ra__vtable_t.replay(). */
1379svn_error_t *
1380svn_ra_serf__replay(svn_ra_session_t *ra_session,
1381                    svn_revnum_t revision,
1382                    svn_revnum_t low_water_mark,
1383                    svn_boolean_t text_deltas,
1384                    const svn_delta_editor_t *editor,
1385                    void *edit_baton,
1386                    apr_pool_t *pool);
1387
1388/* Implements svn_ra__vtable_t.replay_range(). */
1389svn_error_t *
1390svn_ra_serf__replay_range(svn_ra_session_t *ra_session,
1391                          svn_revnum_t start_revision,
1392                          svn_revnum_t end_revision,
1393                          svn_revnum_t low_water_mark,
1394                          svn_boolean_t send_deltas,
1395                          svn_ra_replay_revstart_callback_t revstart_func,
1396                          svn_ra_replay_revfinish_callback_t revfinish_func,
1397                          void *replay_baton,
1398                          apr_pool_t *pool);
1399
1400/* Implements svn_ra__vtable_t.lock(). */
1401svn_error_t *
1402svn_ra_serf__lock(svn_ra_session_t *ra_session,
1403                  apr_hash_t *path_revs,
1404                  const char *comment,
1405                  svn_boolean_t force,
1406                  svn_ra_lock_callback_t lock_func,
1407                  void *lock_baton,
1408                  apr_pool_t *pool);
1409
1410/* Implements svn_ra__vtable_t.unlock(). */
1411svn_error_t *
1412svn_ra_serf__unlock(svn_ra_session_t *ra_session,
1413                    apr_hash_t *path_tokens,
1414                    svn_boolean_t force,
1415                    svn_ra_lock_callback_t lock_func,
1416                    void *lock_baton,
1417                    apr_pool_t *pool);
1418
1419/* Implements svn_ra__vtable_t.get_lock(). */
1420svn_error_t *
1421svn_ra_serf__get_lock(svn_ra_session_t *ra_session,
1422                      svn_lock_t **lock,
1423                      const char *path,
1424                      apr_pool_t *pool);
1425
1426/* Implements svn_ra__vtable_t.get_locks(). */
1427svn_error_t *
1428svn_ra_serf__get_locks(svn_ra_session_t *ra_session,
1429                       apr_hash_t **locks,
1430                       const char *path,
1431                       svn_depth_t depth,
1432                       apr_pool_t *pool);
1433
1434/* Implements svn_ra__vtable_t.list(). */
1435svn_error_t *
1436svn_ra_serf__list(svn_ra_session_t *ra_session,
1437                  const char *path,
1438                  svn_revnum_t revision,
1439                  const apr_array_header_t *patterns,
1440                  svn_depth_t depth,
1441                  apr_uint32_t dirent_fields,
1442                  svn_ra_dirent_receiver_t receiver,
1443                  void *receiver_baton,
1444                  apr_pool_t *scratch_pool);
1445
1446/* Request a mergeinfo-report from the URL attached to SESSION,
1447   and fill in the MERGEINFO hash with the results.
1448
1449   Implements svn_ra__vtable_t.get_mergeinfo().
1450 */
1451svn_error_t *
1452svn_ra_serf__get_mergeinfo(svn_ra_session_t *ra_session,
1453                           apr_hash_t **mergeinfo,
1454                           const apr_array_header_t *paths,
1455                           svn_revnum_t revision,
1456                           svn_mergeinfo_inheritance_t inherit,
1457                           svn_boolean_t include_descendants,
1458                           apr_pool_t *pool);
1459
1460/* Exchange capabilities with the server, by sending an OPTIONS
1461 * request announcing the client's capabilities, and by filling
1462 * SERF_SESS->capabilities with the server's capabilities as read from
1463 * the response headers.  Use POOL only for temporary allocation.
1464 *
1465 * If the CORRECTED_URL is non-NULL, allow the OPTIONS response to
1466 * report a server-dictated redirect or relocation (HTTP 301 or 302
1467 * error codes), setting *CORRECTED_URL to the value of the corrected
1468 * repository URL.  Otherwise, such responses from the server will
1469 * generate an error.  (In either case, no capabilities are exchanged
1470 * if there is, in fact, such a response from the server.)
1471 */
1472svn_error_t *
1473svn_ra_serf__exchange_capabilities(svn_ra_serf__session_t *serf_sess,
1474                                   const char **corrected_url,
1475                                   const char **redirect_url,
1476                                   apr_pool_t *result_pool,
1477                                   apr_pool_t *scratch_pool);
1478
1479/* Implements svn_ra__vtable_t.has_capability(). */
1480svn_error_t *
1481svn_ra_serf__has_capability(svn_ra_session_t *ra_session,
1482                            svn_boolean_t *has,
1483                            const char *capability,
1484                            apr_pool_t *pool);
1485
1486/* Implements svn_ra__vtable_t.get_deleted_rev(). */
1487svn_error_t *
1488svn_ra_serf__get_deleted_rev(svn_ra_session_t *session,
1489                             const char *path,
1490                             svn_revnum_t peg_revision,
1491                             svn_revnum_t end_revision,
1492                             svn_revnum_t *revision_deleted,
1493                             apr_pool_t *pool);
1494
1495/* Implements the get_inherited_props RA layer function. */
1496svn_error_t * svn_ra_serf__get_inherited_props(svn_ra_session_t *session,
1497                                               apr_array_header_t **iprops,
1498                                               const char *path,
1499                                               svn_revnum_t revision,
1500                                               apr_pool_t *result_pool,
1501                                               apr_pool_t *scratch_pool);
1502
1503/* Implements svn_ra__vtable_t.get_repos_root(). */
1504svn_error_t *
1505svn_ra_serf__get_repos_root(svn_ra_session_t *ra_session,
1506                            const char **url,
1507                            apr_pool_t *pool);
1508
1509/* Implements svn_ra__vtable_t.register_editor_shim_callbacks(). */
1510svn_error_t *
1511svn_ra_serf__register_editor_shim_callbacks(svn_ra_session_t *session,
1512                                    svn_delta_shim_callbacks_t *callbacks);
1513
1514/*** Authentication handler declarations ***/
1515
1516/**
1517 * Callback function that loads the credentials for Basic and Digest
1518 * authentications, both for server and proxy authentication.
1519 */
1520apr_status_t
1521svn_ra_serf__credentials_callback(char **username, char **password,
1522                                  serf_request_t *request, void *baton,
1523                                  int code, const char *authn_type,
1524                                  const char *realm,
1525                                  apr_pool_t *pool);
1526
1527
1528/*** General utility functions ***/
1529
1530/**
1531 * Convert an HTTP STATUS_CODE resulting from a WebDAV request against
1532 * PATH to the relevant error code.  Use the response-supplied LOCATION
1533 * where it necessary.
1534 *
1535 * Returns SVN_NO_ERROR if sline doesn't specify an error condition
1536 */
1537svn_error_t *
1538svn_ra_serf__error_on_status(serf_status_line sline,
1539                             const char *path,
1540                             const char *location);
1541
1542/**
1543 * Convert an unexpected HTTP STATUS_CODE from a request to the relevant error
1544 * code. Unlike svn_ra_serf__error_on_status() this function creates an error
1545 * for any result
1546 */
1547svn_error_t *
1548svn_ra_serf__unexpected_status(svn_ra_serf__handler_t *handler);
1549
1550/* Make sure handler is no longer scheduled on its connection. Resetting
1551   the connection if necessary */
1552void
1553svn_ra_serf__unschedule_handler(svn_ra_serf__handler_t *handler);
1554
1555
1556/* ###? */
1557svn_error_t *
1558svn_ra_serf__copy_into_spillbuf(svn_spillbuf_t **spillbuf,
1559                                serf_bucket_t *bkt,
1560                                apr_pool_t *result_pool,
1561                                apr_pool_t *scratch_pool);
1562
1563/* ###? */
1564serf_bucket_t *
1565svn_ra_serf__create_sb_bucket(svn_spillbuf_t *spillbuf,
1566                              serf_bucket_alloc_t *allocator,
1567                              apr_pool_t *result_pool,
1568                              apr_pool_t *scratch_pool);
1569
1570/** Wrap STATUS from an serf function. If STATUS is not serf error code,
1571  * this is equivalent to svn_error_wrap_apr().
1572 */
1573svn_error_t *
1574svn_ra_serf__wrap_err(apr_status_t status,
1575                      const char *fmt,
1576                      ...);
1577
1578/* Create a bucket that just returns DATA (with length LEN) and then returns
1579   the APR_EAGAIN status */
1580serf_bucket_t *
1581svn_ra_serf__create_bucket_with_eagain(const char *data,
1582                                       apr_size_t len,
1583                                       serf_bucket_alloc_t *allocator);
1584
1585/* Parse a given URL_STR, fill in all supplied fields of URI
1586 * structure.
1587 *
1588 * This function is a compatibility wrapper around apr_uri_parse().
1589 * Different apr-util versions set apr_uri_t.path to either NULL or ""
1590 * for root paths, and serf expects to see "/". This function always
1591 * sets URI.path to "/" for these paths. */
1592svn_error_t *
1593svn_ra_serf__uri_parse(apr_uri_t *uri,
1594                       const char *url_str,
1595                       apr_pool_t *result_pool);
1596
1597/* Setup the "Accept-Encoding" header value for requests that expect
1598   svndiff-encoded deltas, depending on the SESSION state. */
1599void
1600svn_ra_serf__setup_svndiff_accept_encoding(serf_bucket_t *headers,
1601                                           svn_ra_serf__session_t *session);
1602
1603svn_boolean_t
1604svn_ra_serf__is_low_latency_connection(svn_ra_serf__session_t *session);
1605
1606/* Return an APR array of svn_ra_serf__dav_props_t containing the
1607 * properties (names and namespaces) corresponding to the flegs set
1608 * in DIRENT_FIELDS.  If SESSION does not support deadprops, only
1609 * the generic "DAV:allprop" will be returned.  Allocate the result
1610 * in RESULT_POOL. */
1611apr_array_header_t *
1612svn_ra_serf__get_dirent_props(apr_uint32_t dirent_fields,
1613                              svn_ra_serf__session_t *session,
1614                              apr_pool_t *result_pool);
1615
1616/* Default limit for in-memory size of a request body. */
1617#define SVN_RA_SERF__REQUEST_BODY_IN_MEM_SIZE 256 * 1024
1618
1619/* An opaque structure used to prepare a request body. */
1620typedef struct svn_ra_serf__request_body_t svn_ra_serf__request_body_t;
1621
1622/* Constructor for svn_ra_serf__request_body_t.  Creates a new writable
1623   buffer for the request body.  Request bodies under IN_MEMORY_SIZE
1624   bytes will be held in memory, otherwise, the body content will be
1625   spilled to a temporary file. */
1626svn_ra_serf__request_body_t *
1627svn_ra_serf__request_body_create(apr_size_t in_memory_size,
1628                                 apr_pool_t *result_pool);
1629
1630/* Get the writable stream associated with BODY. */
1631svn_stream_t *
1632svn_ra_serf__request_body_get_stream(svn_ra_serf__request_body_t *body);
1633
1634/* Get a svn_ra_serf__request_body_delegate_t and baton for BODY. */
1635void
1636svn_ra_serf__request_body_get_delegate(svn_ra_serf__request_body_delegate_t *del,
1637                                       void **baton,
1638                                       svn_ra_serf__request_body_t *body);
1639
1640/* Release intermediate resources associated with BODY.  These resources
1641   (such as open file handles) will be automatically released when the
1642   pool used to construct BODY is cleared or destroyed, but this optional
1643   function allows doing that explicitly. */
1644svn_error_t *
1645svn_ra_serf__request_body_cleanup(svn_ra_serf__request_body_t *body,
1646                                  apr_pool_t *scratch_pool);
1647
1648/* Callback used in svn_ra_serf__create_stream_bucket().  ERR will be
1649   will be cleared and becomes invalid after the callback returns,
1650   use svn_error_dup() to preserve it. */
1651typedef void
1652(*svn_ra_serf__stream_bucket_errfunc_t)(void *baton, svn_error_t *err);
1653
1654/* Create a bucket that wraps a generic readable STREAM.  This function
1655   takes ownership of the passed-in stream, and will close it. */
1656serf_bucket_t *
1657svn_ra_serf__create_stream_bucket(svn_stream_t *stream,
1658                                  serf_bucket_alloc_t *allocator,
1659                                  svn_ra_serf__stream_bucket_errfunc_t errfunc,
1660                                  void *errfunc_baton);
1661
1662#if defined(SVN_DEBUG)
1663/* Wrapper macros to collect file and line information */
1664#define svn_ra_serf__wrap_err \
1665  (svn_error__locate(__FILE__,__LINE__), (svn_ra_serf__wrap_err))
1666
1667#endif
1668
1669#ifdef __cplusplus
1670}
1671#endif /* __cplusplus */
1672
1673#endif /* SVN_LIBSVN_RA_SERF_RA_SERF_H */
1674