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