]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/subversion/subversion/libsvn_ra_serf/ra_serf.h
Merge sendmail 8.16.1 to HEAD: See contrib/sendmail/RELEASE_NOTES for details
[FreeBSD/FreeBSD.git] / contrib / subversion / subversion / libsvn_ra_serf / ra_serf.h
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 \f
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
47 extern "C" {
48 #endif /* __cplusplus */
49
50 \f
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 \f
61 /* Forward declarations. */
62 typedef struct svn_ra_serf__session_t svn_ra_serf__session_t;
63
64 /* A serf connection and optionally associated SSL context.  */
65 typedef 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  */
101 struct 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  */
284 typedef 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
293 static 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
302 static const svn_ra_serf__dav_props_t checked_in_props[] =
303 {
304   { "DAV:", "checked-in" },
305   { NULL }
306 };
307
308 static const svn_ra_serf__dav_props_t baseline_props[] =
309 {
310   { "DAV:", "baseline-collection" },
311   { "DAV:", SVN_DAV__VERSION_NAME },
312   { NULL }
313 };
314
315 static const svn_ra_serf__dav_props_t all_props[] =
316 {
317   { "DAV:", "allprop" },
318   { NULL }
319 };
320
321 static const svn_ra_serf__dav_props_t check_path_props[] =
322 {
323   { "DAV:", "resourcetype" },
324   { NULL }
325 };
326
327 static 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
339 apr_status_t
340 svn_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
346 void
347 svn_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  */
358 apr_status_t
359 svn_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  */
367 apr_status_t
368 svn_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  */
376 svn_error_t *
377 svn_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  */
384 svn_error_t *
385 svn_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 */
392 typedef 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 */
399 typedef 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. */
405 typedef 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. */
413 typedef 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. */
420 typedef 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.  */
427 typedef 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  */
435 typedef 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.  */
546 svn_error_t *
547 svn_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  */
554 void 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.  */
559 typedef 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.  */
563 typedef 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).  */
575 typedef 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.  */
597 typedef 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.  */
612 typedef 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 */
637 typedef 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. */
667 svn_ra_serf__handler_t *
668 svn_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.  */
687 svn_ra_serf__xml_context_t *
688 svn_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. */
698 svn_error_t *
699 svn_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.  */
712 svn_ra_serf__handler_t *
713 svn_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.  */
723 apr_hash_t *
724 svn_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().  */
739 void
740 svn_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.  */
751 apr_pool_t *
752 svn_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  */
757 struct 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  */
782 svn_error_t *
783 svn_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  */
800 svn_error_t *
801 svn_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.  */
821 svn_error_t *
822 svn_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  */
831 svn_error_t *
832 svn_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  */
841 svn_error_t *
842 svn_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  */
853 svn_error_t *
854 svn_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  */
862 apr_status_t
863 svn_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  */
875 void
876 svn_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  */
887 void
888 svn_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  */
904 void
905 svn_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  */
916 void
917 svn_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  */
925 void
926 svn_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  */
937 void
938 svn_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 */
946 void
947 svn_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 */
952 typedef 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  */
964 svn_error_t *
965 svn_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  */
977 svn_error_t *
978 svn_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.  */
1000 svn_error_t *
1001 svn_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.  */
1022 svn_error_t *
1023 svn_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.  */
1037 const char *
1038 svn_ra_serf__svnname_from_wirename(const char *ns,
1039                                    const char *name,
1040                                    apr_pool_t *result_pool);
1041
1042 /** MERGE-related functions **/
1043
1044 void
1045 svn_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.  */
1056 svn_error_t *
1057 svn_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.  */
1071 svn_error_t *
1072 svn_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.  */
1084 svn_error_t *
1085 svn_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.  */
1099 svn_error_t *
1100 svn_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. */
1111 svn_error_t *
1112 svn_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  */
1121 svn_error_t *
1122 svn_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.  */
1131 svn_error_t *
1132 svn_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.  */
1144 svn_error_t *
1145 svn_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.  */
1178 svn_error_t *
1179 svn_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(). */
1191 svn_error_t *
1192 svn_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(). */
1197 svn_error_t *
1198 svn_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(). */
1205 svn_error_t *
1206 svn_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(). */
1220 svn_error_t *
1221 svn_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(). */
1228 svn_error_t *
1229 svn_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(). */
1236 svn_error_t *
1237 svn_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(). */
1245 svn_error_t *
1246 svn_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(). */
1256 svn_error_t *
1257 svn_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(). */
1271 svn_error_t *
1272 svn_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(). */
1283 svn_error_t *
1284 svn_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(). */
1298 svn_error_t *
1299 svn_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(). */
1314 svn_error_t *
1315 svn_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(). */
1325 svn_error_t *
1326 svn_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  */
1337 svn_error_t *
1338 svn_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(). */
1349 svn_error_t *
1350 svn_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(). */
1359 svn_error_t *
1360 svn_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(). */
1370 svn_error_t *
1371 svn_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(). */
1379 svn_error_t *
1380 svn_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(). */
1389 svn_error_t *
1390 svn_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(). */
1401 svn_error_t *
1402 svn_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(). */
1411 svn_error_t *
1412 svn_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(). */
1420 svn_error_t *
1421 svn_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(). */
1427 svn_error_t *
1428 svn_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(). */
1435 svn_error_t *
1436 svn_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  */
1451 svn_error_t *
1452 svn_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  */
1472 svn_error_t *
1473 svn_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(). */
1480 svn_error_t *
1481 svn_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(). */
1487 svn_error_t *
1488 svn_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. */
1496 svn_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(). */
1504 svn_error_t *
1505 svn_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(). */
1510 svn_error_t *
1511 svn_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  */
1520 apr_status_t
1521 svn_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  */
1537 svn_error_t *
1538 svn_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  */
1547 svn_error_t *
1548 svn_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 */
1552 void
1553 svn_ra_serf__unschedule_handler(svn_ra_serf__handler_t *handler);
1554
1555
1556 /* ###? */
1557 svn_error_t *
1558 svn_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 /* ###? */
1564 serf_bucket_t *
1565 svn_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  */
1573 svn_error_t *
1574 svn_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 */
1580 serf_bucket_t *
1581 svn_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. */
1592 svn_error_t *
1593 svn_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. */
1599 void
1600 svn_ra_serf__setup_svndiff_accept_encoding(serf_bucket_t *headers,
1601                                            svn_ra_serf__session_t *session);
1602
1603 svn_boolean_t
1604 svn_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. */
1611 apr_array_header_t *
1612 svn_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. */
1620 typedef 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. */
1626 svn_ra_serf__request_body_t *
1627 svn_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. */
1631 svn_stream_t *
1632 svn_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. */
1635 void
1636 svn_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. */
1644 svn_error_t *
1645 svn_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. */
1651 typedef 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. */
1656 serf_bucket_t *
1657 svn_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 */