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