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