259
266
apr_pool_t *pool)
261
268
apr_pool_t *sesspool = svn_pool_create(pool);
269
apr_pool_t *scratch_pool = svn_pool_create(sesspool);
262
270
svn_ra_session_t *session;
263
271
const struct ra_lib_defn *defn;
264
272
const svn_ra__vtable_t *vtable = NULL;
265
svn_config_t *servers = NULL;
266
const char *server_group;
267
273
apr_uri_t repos_URI;
268
274
apr_status_t apr_err;
269
276
#ifdef CHOOSABLE_DAV_MODULE
270
277
const char *http_library = DEFAULT_HTTP_LIBRARY;
272
/* Auth caching parameters. */
273
svn_boolean_t store_passwords = SVN_CONFIG_DEFAULT_OPTION_STORE_PASSWORDS;
274
svn_boolean_t store_auth_creds = SVN_CONFIG_DEFAULT_OPTION_STORE_AUTH_CREDS;
275
const char *store_plaintext_passwords
276
= SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS;
277
svn_boolean_t store_pp = SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP;
278
const char *store_pp_plaintext
279
= SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT;
280
const char *corrected_url;
279
svn_auth_baton_t *auth_baton;
282
281
/* Initialize the return variable. */
283
282
*session_p = NULL;
295
294
if (callbacks->auth_baton)
297
/* The 'store-passwords' and 'store-auth-creds' parameters used to
298
* live in SVN_CONFIG_CATEGORY_CONFIG. For backward compatibility,
299
* if values for these parameters have already been set by our
300
* callers, we use those values as defaults.
302
* Note that we can only catch the case where users explicitly set
303
* "store-passwords = no" or 'store-auth-creds = no".
305
* However, since the default value for both these options is
306
* currently (and has always been) "yes", users won't know
307
* the difference if they set "store-passwords = yes" or
308
* "store-auth-creds = yes" -- they'll get the expected behaviour.
311
if (svn_auth_get_parameter(callbacks->auth_baton,
312
SVN_AUTH_PARAM_DONT_STORE_PASSWORDS) != NULL)
313
store_passwords = FALSE;
315
if (svn_auth_get_parameter(callbacks->auth_baton,
316
SVN_AUTH_PARAM_NO_AUTH_CACHE) != NULL)
317
store_auth_creds = FALSE;
295
SVN_ERR(svn_auth__make_session_auth(&auth_baton,
296
callbacks->auth_baton, config,
298
sesspool, scratch_pool));
302
#ifdef CHOOSABLE_DAV_MODULE
305
svn_config_t *servers = NULL;
306
const char *server_group = NULL;
322
308
/* Grab the 'servers' config. */
323
309
servers = svn_hash_gets(config, SVN_CONFIG_CATEGORY_SERVERS);
326
312
/* First, look in the global section. */
328
SVN_ERR(svn_config_get_bool
329
(servers, &store_passwords, SVN_CONFIG_SECTION_GLOBAL,
330
SVN_CONFIG_OPTION_STORE_PASSWORDS,
333
SVN_ERR(svn_config_get_yes_no_ask
334
(servers, &store_plaintext_passwords, SVN_CONFIG_SECTION_GLOBAL,
335
SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSWORDS,
336
SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS));
338
SVN_ERR(svn_config_get_bool
339
(servers, &store_pp, SVN_CONFIG_SECTION_GLOBAL,
340
SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP,
343
SVN_ERR(svn_config_get_yes_no_ask
344
(servers, &store_pp_plaintext,
345
SVN_CONFIG_SECTION_GLOBAL,
346
SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT,
347
SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT));
349
SVN_ERR(svn_config_get_bool
350
(servers, &store_auth_creds, SVN_CONFIG_SECTION_GLOBAL,
351
SVN_CONFIG_OPTION_STORE_AUTH_CREDS,
354
314
/* Find out where we're about to connect to, and
355
315
* try to pick a server group based on the destination. */
356
316
server_group = svn_config_find_group(servers, repos_URI.hostname,
357
317
SVN_CONFIG_SECTION_GROUPS,
362
/* Override global auth caching parameters with the ones
363
* for the server group, if any. */
364
SVN_ERR(svn_config_get_bool(servers, &store_auth_creds,
366
SVN_CONFIG_OPTION_STORE_AUTH_CREDS,
369
SVN_ERR(svn_config_get_bool(servers, &store_passwords,
371
SVN_CONFIG_OPTION_STORE_PASSWORDS,
374
SVN_ERR(svn_config_get_yes_no_ask
375
(servers, &store_plaintext_passwords, server_group,
376
SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSWORDS,
377
store_plaintext_passwords));
379
SVN_ERR(svn_config_get_bool
381
server_group, SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP,
384
SVN_ERR(svn_config_get_yes_no_ask
385
(servers, &store_pp_plaintext, server_group,
386
SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT,
387
store_pp_plaintext));
389
#ifdef CHOOSABLE_DAV_MODULE
390
320
/* Now, which DAV-based RA method do we want to use today? */
392
322
= svn_config_get_server_setting(servers,
399
329
_("Invalid config: unknown HTTP library "
406
if (callbacks->auth_baton)
408
/* Save auth caching parameters in the auth parameter hash. */
409
if (! store_passwords)
410
svn_auth_set_parameter(callbacks->auth_baton,
411
SVN_AUTH_PARAM_DONT_STORE_PASSWORDS, "");
413
svn_auth_set_parameter(callbacks->auth_baton,
414
SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS,
415
store_plaintext_passwords);
418
svn_auth_set_parameter(callbacks->auth_baton,
419
SVN_AUTH_PARAM_DONT_STORE_SSL_CLIENT_CERT_PP,
422
svn_auth_set_parameter(callbacks->auth_baton,
423
SVN_AUTH_PARAM_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT,
426
if (! store_auth_creds)
427
svn_auth_set_parameter(callbacks->auth_baton,
428
SVN_AUTH_PARAM_NO_AUTH_CACHE, "");
431
336
/* Find the library. */
432
337
for (defn = ra_libraries; defn->ra_name != NULL; ++defn)
476
381
session->pool = sesspool;
478
383
/* Ask the library to open the session. */
479
SVN_ERR_W(vtable->open_session(session, &corrected_url, repos_URL,
480
callbacks, callback_baton, config, sesspool),
481
apr_psprintf(pool, "Unable to connect to a repository at URL '%s'",
384
err = vtable->open_session(session, corrected_url_p,
386
callbacks, callback_baton, auth_baton,
387
config, sesspool, scratch_pool);
391
svn_pool_destroy(sesspool); /* Includes scratch_pool */
392
if (err->apr_err == SVN_ERR_RA_SESSION_URL_MISMATCH)
393
return svn_error_trace(err);
395
return svn_error_createf(
396
SVN_ERR_RA_CANNOT_CREATE_SESSION, err,
397
_("Unable to connect to a repository at URL '%s'"),
484
401
/* If the session open stuff detected a server-provided URL
485
402
correction (a 301 or 302 redirect response during the initial
486
403
OPTIONS request), then kill the session so the caller can decide
488
if (corrected_url_p && corrected_url)
405
if (corrected_url_p && *corrected_url_p)
490
if (! svn_path_is_url(corrected_url))
492
/* RFC1945 and RFC2616 state that the Location header's
493
value (from whence this CORRECTED_URL ultimately comes),
494
if present, must be an absolute URI. But some Apache
495
versions (those older than 2.2.11, it seems) transmit
496
only the path portion of the URI. See issue #3775 for
498
apr_uri_t corrected_URI = repos_URI;
499
corrected_URI.path = (char *)corrected_url;
500
corrected_url = apr_uri_unparse(pool, &corrected_URI, 0);
502
*corrected_url_p = svn_uri_canonicalize(corrected_url, pool);
503
svn_pool_destroy(sesspool);
407
/* *session_p = NULL; */
408
*corrected_url_p = apr_pstrdup(pool, *corrected_url_p);
409
svn_pool_destroy(sesspool); /* Includes scratch_pool */
504
410
return SVN_NO_ERROR;
431
svn_pool_destroy(scratch_pool);
525
432
*session_p = session;
526
433
return SVN_NO_ERROR;
437
svn_ra__dup_session(svn_ra_session_t **new_session,
438
svn_ra_session_t *old_session,
439
const char *session_url,
440
apr_pool_t *result_pool,
441
apr_pool_t *scratch_pool)
443
svn_ra_session_t *session;
449
/* This verifies in new_session_url is in the repository */
450
SVN_ERR(svn_ra_get_path_relative_to_root(old_session,
456
SVN_ERR(svn_ra_get_session_url(old_session, &session_url, scratch_pool));
458
/* Create the session object. */
459
session = apr_pcalloc(result_pool, sizeof(*session));
460
session->cancel_func = old_session->cancel_func;
461
session->cancel_baton = old_session->cancel_baton;
462
session->vtable = old_session->vtable;
463
session->pool = result_pool;
465
SVN_ERR(old_session->vtable->dup_session(session,
471
*new_session = session;
529
475
svn_error_t *svn_ra_reparent(svn_ra_session_t *session,
531
477
apr_pool_t *pool)
650
596
return session->vtable->rev_prop(session, rev, name, value, pool);
655
svn_commit_callback2_t original_callback;
656
void *original_baton;
658
svn_ra_session_t *session;
661
/* Wrapper which populates the repos_root field of the commit_info struct */
663
commit_callback_wrapper(const svn_commit_info_t *commit_info,
667
struct ccw_baton *ccwb = baton;
668
svn_commit_info_t *ci = svn_commit_info_dup(commit_info, pool);
670
SVN_ERR(svn_ra_get_repos_root2(ccwb->session, &ci->repos_root, pool));
672
return ccwb->original_callback(ci, ccwb->original_baton, pool);
676
/* Some RA layers do not correctly fill in REPOS_ROOT in commit_info, or
677
they are third-party layers conforming to an older commit_info structure.
678
Interpose a utility function to ensure the field is valid. */
680
remap_commit_callback(svn_commit_callback2_t *callback,
681
void **callback_baton,
682
svn_ra_session_t *session,
683
svn_commit_callback2_t original_callback,
684
void *original_baton,
685
apr_pool_t *result_pool)
687
if (original_callback == NULL)
690
*callback_baton = NULL;
694
/* Allocate this in RESULT_POOL, since the callback will be called
695
long after this function has returned. */
696
struct ccw_baton *ccwb = apr_palloc(result_pool, sizeof(*ccwb));
698
ccwb->session = session;
699
ccwb->original_callback = original_callback;
700
ccwb->original_baton = original_baton;
702
*callback = commit_callback_wrapper;
703
*callback_baton = ccwb;
708
599
svn_error_t *svn_ra_get_commit_editor3(svn_ra_session_t *session,
709
600
const svn_delta_editor_t **editor,
710
601
void **edit_baton,
925
812
svn_dirent_t **dirent,
926
813
apr_pool_t *pool)
928
816
SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
929
return session->vtable->stat(session, path, revision, dirent, pool);
817
err = session->vtable->stat(session, path, revision, dirent, pool);
819
/* svnserve before 1.2 doesn't support the above, so fall back on
820
a far less efficient, but still correct method. */
821
if (err && err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED)
823
/* ### TODO: Find out if we can somehow move this code in libsvn_ra_svn.
825
apr_pool_t *scratch_pool = svn_pool_create(pool);
826
svn_node_kind_t kind;
828
svn_error_clear(err);
830
SVN_ERR(svn_ra_check_path(session, path, revision, &kind, scratch_pool));
832
if (kind != svn_node_none)
834
const char *repos_root_url;
835
const char *session_url;
837
SVN_ERR(svn_ra_get_repos_root2(session, &repos_root_url,
839
SVN_ERR(svn_ra_get_session_url(session, &session_url,
842
if (!svn_path_is_empty(path))
843
session_url = svn_path_url_add_component2(session_url, path,
846
if (strcmp(session_url, repos_root_url) != 0)
848
svn_ra_session_t *parent_session;
849
apr_hash_t *parent_ents;
850
const char *parent_url, *base_name;
852
/* Open another session to the path's parent. This server
853
doesn't support svn_ra_reparent anyway, so don't try it. */
854
svn_uri_split(&parent_url, &base_name, session_url,
857
SVN_ERR(svn_ra__dup_session(&parent_session, session, parent_url,
858
scratch_pool, scratch_pool));
860
/* Get all parent's entries, no props. */
861
SVN_ERR(svn_ra_get_dir2(parent_session, &parent_ents, NULL,
862
NULL, "", revision, SVN_DIRENT_ALL,
865
/* Get the relevant entry. */
866
*dirent = svn_hash_gets(parent_ents, base_name);
869
*dirent = svn_dirent_dup(*dirent, pool);
874
const svn_string_t *val;
876
/* We can't get the directory entry for the repository root,
877
but we can still get the information we want.
878
The created-rev of the repository root must, by definition,
880
*dirent = apr_pcalloc(pool, sizeof(**dirent));
881
(*dirent)->kind = kind;
882
(*dirent)->size = SVN_INVALID_FILESIZE;
884
SVN_ERR(svn_ra_get_dir2(session, NULL, NULL, &props,
885
"", revision, 0 /* no dirent fields */,
887
(*dirent)->has_props = (apr_hash_count(props) != 0);
889
(*dirent)->created_rev = revision;
891
SVN_ERR(svn_ra_rev_proplist(session, revision, &props,
894
val = svn_hash_gets(props, SVN_PROP_REVISION_DATE);
896
SVN_ERR(svn_time_from_cstring(&(*dirent)->time, val->data,
899
val = svn_hash_gets(props, SVN_PROP_REVISION_AUTHOR);
900
(*dirent)->last_author = val ? apr_pstrdup(pool, val->data)
907
svn_pool_clear(scratch_pool);
932
915
svn_error_t *svn_ra_get_uuid2(svn_ra_session_t *session,
1320
1304
apr_pool_t *result_pool,
1321
1305
apr_pool_t *scratch_pool)
1323
svn_boolean_t iprop_capable;
1325
1308
/* Path must be relative. */
1326
1309
SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
1328
SVN_ERR(svn_ra_has_capability(session, &iprop_capable,
1329
SVN_RA_CAPABILITY_INHERITED_PROPS,
1334
SVN_ERR(session->vtable->get_inherited_props(session, iprops, path,
1335
revision, result_pool,
1311
err = session->vtable->get_inherited_props(session, iprops, path,
1312
revision, result_pool,
1315
if (err && err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED)
1317
svn_error_clear(err);
1340
1319
/* Fallback for legacy servers. */
1341
1320
SVN_ERR(svn_ra__get_inherited_props_walk(session, path, revision, iprops,
1342
1321
result_pool, scratch_pool));
1345
1326
return SVN_NO_ERROR;