xref: /trueos/contrib/subversion/subversion/libsvn_ra_serf/ra_serf.h (revision 7cfbe47f2542407346168136f8e33b5015eda94f)
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
48 extern "C" {
49 #endif /* __cplusplus */
50 
51 
52 /* Enforce the minimum version of serf. */
53 #if !SERF_VERSION_AT_LEAST(1, 2, 1)
54 #error Please update your version of serf to at least 1.2.1.
55 #endif
56 
57 /** Use this to silence compiler warnings about unused parameters. */
58 #define UNUSED_CTX(x) ((void)(x))
59 
60 /** Wait duration (in microseconds) used in calls to serf_context_run() */
61 #define SVN_RA_SERF__CONTEXT_RUN_DURATION 500000
62 
63 
64 
65 /* Forward declarations. */
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 */
1789