Modified: subversion/branches/addremove/subversion/libsvn_ra/deprecated.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra/deprecated.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra/deprecated.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra/deprecated.c Sat May 23 14:16:56 2020 @@ -151,6 +151,19 @@ static svn_ra_reporter2_t reporter_3in2_ abort_report }; +svn_error_t *svn_ra_open4(svn_ra_session_t **session_p, + const char **corrected_url_p, + const char *repos_URL, + const char *uuid, + const svn_ra_callbacks2_t *callbacks, + void *callback_baton, + apr_hash_t *config, + apr_pool_t *pool) +{ + return svn_ra_open5(session_p, corrected_url_p, NULL, repos_URL, uuid, + callbacks, callback_baton, config, pool); +} + svn_error_t *svn_ra_open3(svn_ra_session_t **session_p, const char *repos_URL, const char *uuid,
Modified: subversion/branches/addremove/subversion/libsvn_ra/ra_loader.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra/ra_loader.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra/ra_loader.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra/ra_loader.c Sat May 23 14:16:56 2020 @@ -243,7 +243,7 @@ svn_error_t *svn_ra_initialize(apr_pool_ /* Please note: the implementation of svn_ra_create_callbacks is * duplicated in libsvn_ra/wrapper_template.h:compat_open() . This * duplication is intentional, is there to avoid a circular - * dependancy, and is justified in great length in the code of + * dependency, and is justified in great length in the code of * compat_open() in libsvn_ra/wrapper_template.h. If you modify the * implementation of svn_ra_create_callbacks(), be sure to keep the * code in wrapper_template.h:compat_open() in sync with your @@ -256,8 +256,9 @@ svn_ra_create_callbacks(svn_ra_callbacks return SVN_NO_ERROR; } -svn_error_t *svn_ra_open4(svn_ra_session_t **session_p, +svn_error_t *svn_ra_open5(svn_ra_session_t **session_p, const char **corrected_url_p, + const char **redirect_url_p, const char *repos_URL, const char *uuid, const svn_ra_callbacks2_t *callbacks, @@ -381,7 +382,7 @@ svn_error_t *svn_ra_open4(svn_ra_session session->pool = sesspool; /* Ask the library to open the session. */ - err = vtable->open_session(session, corrected_url_p, + err = vtable->open_session(session, corrected_url_p, redirect_url_p, repos_URL, callbacks, callback_baton, auth_baton, config, sesspool, scratch_pool); @@ -406,12 +407,14 @@ svn_error_t *svn_ra_open4(svn_ra_session { /* *session_p = NULL; */ *corrected_url_p = apr_pstrdup(pool, *corrected_url_p); + if (redirect_url_p && *redirect_url_p) + *redirect_url_p = apr_pstrdup(pool, *redirect_url_p); svn_pool_destroy(sesspool); /* Includes scratch_pool */ return SVN_NO_ERROR; } if (vtable->set_svn_ra_open) - SVN_ERR(vtable->set_svn_ra_open(session, svn_ra_open4)); + SVN_ERR(vtable->set_svn_ra_open(session, svn_ra_open5)); /* Check the UUID. */ if (uuid) @@ -472,7 +475,7 @@ svn_ra__dup_session(svn_ra_session_t **n scratch_pool)); if (session->vtable->set_svn_ra_open) - SVN_ERR(session->vtable->set_svn_ra_open(session, svn_ra_open4)); + SVN_ERR(session->vtable->set_svn_ra_open(session, svn_ra_open5)); *new_session = session; return SVN_NO_ERROR; Modified: subversion/branches/addremove/subversion/libsvn_ra/ra_loader.h URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra/ra_loader.h?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra/ra_loader.h (original) +++ subversion/branches/addremove/subversion/libsvn_ra/ra_loader.h Sat May 23 14:16:56 2020 @@ -42,6 +42,7 @@ extern "C" { handed to the ra api to allow opening other ra sessions. */ typedef svn_error_t * (*svn_ra__open_func_t)(svn_ra_session_t **session_p, const char **corrected_url, + const char **redirect_url, const char *repos_URL, const char *uuid, const svn_ra_callbacks2_t *callbacks, @@ -64,11 +65,12 @@ typedef struct svn_ra__vtable_t { /* Implementations of the public API functions. */ - /* See svn_ra_open4(). */ + /* See svn_ra_open5(). */ /* All fields in SESSION, except priv, have been initialized by the time this is called. SESSION->priv may be set by this function. */ svn_error_t *(*open_session)(svn_ra_session_t *session, const char **corrected_url, + const char **redirect_url, const char *session_URL, const svn_ra_callbacks2_t *callbacks, void *callback_baton, @@ -326,7 +328,7 @@ typedef struct svn_ra__vtable_t { svn_revnum_t revision, apr_pool_t *result_pool, apr_pool_t *scratch_pool); - /* If not NULL, receives a pointer to svn_ra_open, to alllow opening + /* If not NULL, receives a pointer to svn_ra_open, to allow opening a new ra session from inside the ra layer without a circular library dependency*/ svn_error_t *(*set_svn_ra_open)(svn_ra_session_t *session, Modified: subversion/branches/addremove/subversion/libsvn_ra/util.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra/util.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra/util.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra/util.c Sat May 23 14:16:56 2020 @@ -216,7 +216,7 @@ svn_ra__get_operational_lock(const svn_s /* Did we get a value from the repository? We'll check to see if it matches our token. If so, we call it success. If not and we're told to steal locks, we remember the existing lock - token and fall through to the locking code; othewise, we + token and fall through to the locking code; otherwise, we sleep and retry. */ if (reposlocktoken) { Modified: subversion/branches/addremove/subversion/libsvn_ra/wrapper_template.h URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra/wrapper_template.h?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra/wrapper_template.h (original) +++ subversion/branches/addremove/subversion/libsvn_ra/wrapper_template.h Sat May 23 14:16:56 2020 @@ -61,9 +61,9 @@ static svn_error_t *compat_open(void **s { /* Here, we should be calling svn_ra_create_callbacks to initialize * the svn_ra_callbacks2_t structure. However, doing that - * introduces a circular dependancy between libsvn_ra and + * introduces a circular dependency between libsvn_ra and * libsvn_ra_{local,neon,serf,svn}, which include - * wrapper_template.h. In turn, circular dependancies break the + * wrapper_template.h. In turn, circular dependencies break the * build on win32 (and possibly other systems). * * In order to avoid this happening at all, the code of @@ -90,7 +90,7 @@ static svn_error_t *compat_open(void **s callbacks2->progress_func = NULL; callbacks2->progress_baton = NULL; - SVN_ERR(VTBL.open_session(sess, &session_url, repos_URL, + SVN_ERR(VTBL.open_session(sess, &session_url, NULL, repos_URL, callbacks2, callback_baton, callbacks ? callbacks->auth_baton : NULL, config, sesspool, sesspool)); Modified: subversion/branches/addremove/subversion/libsvn_ra_local/ra_plugin.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_local/ra_plugin.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_local/ra_plugin.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra_local/ra_plugin.c Sat May 23 14:16:56 2020 @@ -554,6 +554,7 @@ ignore_warnings(void *baton, static svn_error_t * svn_ra_local__open(svn_ra_session_t *session, const char **corrected_url, + const char **redirect_url, const char *repos_URL, const svn_ra_callbacks2_t *callbacks, void *callback_baton, @@ -576,6 +577,8 @@ svn_ra_local__open(svn_ra_session_t *ses /* We don't support redirections in ra-local. */ if (corrected_url) *corrected_url = NULL; + if (redirect_url) + *redirect_url = NULL; /* Allocate and stash the session_sess args we have already. */ sess = apr_pcalloc(pool, sizeof(*sess)); @@ -1387,7 +1390,7 @@ svn_ra_local__get_dir(svn_ra_session_t * { /* size */ if (fs_entry->kind == svn_node_dir) - entry->size = 0; + entry->size = SVN_INVALID_FILESIZE; else SVN_ERR(svn_fs_file_length(&(entry->size), root, fullpath, iterpool)); @@ -1751,7 +1754,7 @@ static svn_error_t * svn_ra_local__register_editor_shim_callbacks(svn_ra_session_t *session, svn_delta_shim_callbacks_t *callbacks) { - /* This is currenly a no-op, since we don't provide our own editor, just + /* This is currently a no-op, since we don't provide our own editor, just use the one the libsvn_repos hands back to us. */ return SVN_NO_ERROR; } Modified: subversion/branches/addremove/subversion/libsvn_ra_serf/commit.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_serf/commit.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_serf/commit.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra_serf/commit.c Sat May 23 14:16:56 2020 @@ -311,7 +311,7 @@ checkout_node(const char **working_url, fails due to an SVN_ERR_APMOD_BAD_BASELINE error return from the server. - See http://subversion.tigris.org/issues/show_bug.cgi?id=4127 for + See https://issues.apache.org/jira/browse/SVN-4127 for details. */ static svn_error_t * @@ -677,7 +677,7 @@ write_prop_xml(const proppatch_context_t explicitly deleted in this commit already, then mod_dav removed its lock token when it fielded the DELETE request, so we don't want to set the lock precondition again. (See - http://subversion.tigris.org/issues/show_bug.cgi?id=3674 for details.) + https://issues.apache.org/jira/browse/SVN-3674 for details.) */ static svn_error_t * maybe_set_lock_token_header(serf_bucket_t *headers, @@ -687,7 +687,7 @@ maybe_set_lock_token_header(serf_bucket_ { const char *token; - if (! (*relpath && commit_ctx->lock_tokens)) + if (! commit_ctx->lock_tokens) return SVN_NO_ERROR; if (! svn_hash_gets(commit_ctx->deleted_entries, relpath)) @@ -1211,7 +1211,7 @@ post_response_handler(serf_request_t *re /* Then see which ones we can discover. */ serf_bucket_headers_do(hdrs, post_headers_iterator_callback, prc); - /* Execute the 'real' response handler to XML-parse the repsonse body. */ + /* Execute the 'real' response handler to XML-parse the response body. */ return svn_ra_serf__expect_empty_body(request, response, prc->handler, scratch_pool); } Modified: subversion/branches/addremove/subversion/libsvn_ra_serf/get_file.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_serf/get_file.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_serf/get_file.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra_serf/get_file.c Sat May 23 14:16:56 2020 @@ -137,7 +137,7 @@ cancel_fetch(serf_request_t *request, * using SESSION->wc_callbacks->get_wc_contents() if sha1 property is * present in PROPS. * - * Sets *FOUND_P to TRUE if file contents was successfuly fetched. + * Sets *FOUND_P to TRUE if file contents was successfully fetched. * * Performs all temporary allocations in POOL. */ Modified: subversion/branches/addremove/subversion/libsvn_ra_serf/inherited_props.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_serf/inherited_props.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_serf/inherited_props.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra_serf/inherited_props.c Sat May 23 14:16:56 2020 @@ -340,7 +340,7 @@ get_iprops_via_more_requests(svn_ra_sess new_iprop = apr_palloc(result_pool, sizeof(*new_iprop)); new_iprop->path_or_url = apr_pstrdup(result_pool, rq->relpath); new_iprop->prop_hash = svn_prop_hash_dup(node_props, result_pool); - svn_sort__array_insert(*iprops, &new_iprop, 0); + SVN_ERR(svn_sort__array_insert2(*iprops, &new_iprop, 0)); } return SVN_NO_ERROR; Modified: subversion/branches/addremove/subversion/libsvn_ra_serf/lock.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_serf/lock.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_serf/lock.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra_serf/lock.c Sat May 23 14:16:56 2020 @@ -354,7 +354,7 @@ run_locks(svn_ra_serf__session_t *sess, SVN_ERR(cb_err); waittime_left = sess->timeout; - svn_sort__array_delete(lock_ctxs, i, 1); + SVN_ERR(svn_sort__array_delete2(lock_ctxs, i, 1)); i--; svn_pool_destroy(ctx->pool); Modified: subversion/branches/addremove/subversion/libsvn_ra_serf/options.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_serf/options.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_serf/options.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra_serf/options.c Sat May 23 14:16:56 2020 @@ -71,6 +71,9 @@ typedef struct options_context_t { svn_ra_serf__response_handler_t inner_handler; void *inner_baton; + /* Have we received any DAV headers at all? */ + svn_boolean_t received_dav_header; + const char *activity_collection; svn_revnum_t youngest_rev; @@ -165,6 +168,8 @@ capabilities_headers_iterator_callback(v apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE, opt_ctx->pool); + opt_ctx->received_dav_header = TRUE; + /* Right now we only have a few capabilities to detect, so just seek for them directly. This could be written slightly more efficiently, but that wouldn't be worth it until we have many @@ -232,6 +237,11 @@ capabilities_headers_iterator_callback(v advertise this capability (Subversion 1.10 and greater). */ session->supports_svndiff1 = TRUE; } + if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_LIST, vals)) + { + svn_hash_sets(session->capabilities, + SVN_RA_CAPABILITY_LIST, capability_yes); + } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_SVNDIFF2, vals)) { /* Same for svndiff2. */ @@ -384,11 +394,26 @@ options_response_handler(serf_request_t capability_no); svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE, capability_no); + svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_LIST, + capability_no); /* Then see which ones we can discover. */ serf_bucket_headers_do(hdrs, capabilities_headers_iterator_callback, opt_ctx); + /* Bail out early if we're not talking to a DAV server. + Note that this check is only valid if we've received a success + response; redirects and errors don't count. */ + if (opt_ctx->handler->sline.code >= 200 + && opt_ctx->handler->sline.code < 300 + && !opt_ctx->received_dav_header) + { + return svn_error_createf + (SVN_ERR_RA_DAV_OPTIONS_REQ_FAILED, NULL, + _("The server at '%s' does not support the HTTP/DAV protocol"), + session->session_url_str); + } + /* Assume mergeinfo capability unsupported, if didn't receive information about server or repository mergeinfo capability. */ if (!svn_hash_gets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO)) @@ -521,6 +546,7 @@ svn_ra_serf__v1_get_activity_collection( svn_error_t * svn_ra_serf__exchange_capabilities(svn_ra_serf__session_t *serf_sess, const char **corrected_url, + const char **redirect_url, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -528,6 +554,8 @@ svn_ra_serf__exchange_capabilities(svn_r if (corrected_url) *corrected_url = NULL; + if (redirect_url) + *redirect_url = NULL; /* This routine automatically fills in serf_sess->capabilities */ SVN_ERR(create_options_req(&opt_ctx, serf_sess, scratch_pool)); @@ -550,8 +578,11 @@ svn_ra_serf__exchange_capabilities(svn_r } else if (svn_path_is_url(opt_ctx->handler->location)) { - *corrected_url = svn_uri_canonicalize(opt_ctx->handler->location, - result_pool); + SVN_ERR(svn_uri_canonicalize_safe(corrected_url, NULL, + opt_ctx->handler->location, result_pool, scratch_pool)); + if (redirect_url) + *redirect_url = apr_pstrdup(result_pool, + opt_ctx->handler->location); } else { @@ -562,11 +593,14 @@ svn_ra_serf__exchange_capabilities(svn_r See issue #3775 for details. */ apr_uri_t corrected_URI = serf_sess->session_url; + char *absolute_uri; corrected_URI.path = (char *)corrected_url; - *corrected_url = svn_uri_canonicalize( - apr_uri_unparse(scratch_pool, &corrected_URI, 0), - result_pool); + absolute_uri = apr_uri_unparse(scratch_pool, &corrected_URI, 0); + SVN_ERR(svn_uri_canonicalize_safe(corrected_url, NULL, + absolute_uri, result_pool, scratch_pool)); + if (redirect_url) + *redirect_url = apr_pstrdup(result_pool, absolute_uri); } return SVN_NO_ERROR; @@ -674,7 +708,8 @@ svn_ra_serf__has_capability(svn_ra_sessi /* If any capability is unknown, they're all unknown, so ask. */ if (cap_result == NULL) - SVN_ERR(svn_ra_serf__exchange_capabilities(serf_sess, NULL, pool, pool)); + SVN_ERR(svn_ra_serf__exchange_capabilities(serf_sess, NULL, NULL, + pool, pool)); /* Try again, now that we've fetched the capabilities. */ cap_result = svn_hash_gets(serf_sess->capabilities, capability); Modified: subversion/branches/addremove/subversion/libsvn_ra_serf/property.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_serf/property.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_serf/property.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra_serf/property.c Sat May 23 14:16:56 2020 @@ -205,7 +205,7 @@ propfind_closed(svn_ra_serf__xml_estate_ if (leaving_state == MULTISTATUS) { - /* We've gathered all the data from the reponse. Add this item + /* We've gathered all the data from the response. Add this item onto the "done list". External callers will then know this request has been completed (tho stray response bytes may still arrive). */ Modified: subversion/branches/addremove/subversion/libsvn_ra_serf/ra_serf.h URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_serf/ra_serf.h?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_serf/ra_serf.h (original) +++ subversion/branches/addremove/subversion/libsvn_ra_serf/ra_serf.h Sat May 23 14:16:56 2020 @@ -379,7 +379,7 @@ svn_ra_serf__context_run_wait(svn_boolea apr_pool_t *scratch_pool); /* Run the context once. Manage waittime_left to handle timing out when - nothing happens over the session->timout. + nothing happens over the session->timeout. */ svn_error_t * svn_ra_serf__context_run(svn_ra_serf__session_t *sess, @@ -716,7 +716,7 @@ svn_ra_serf__create_expat_handler(svn_ra apr_pool_t *result_pool); -/* Allocated within XES->STATE_POOL. Changes are not allowd (callers +/* Allocated within XES->STATE_POOL. Changes are not allowed (callers should make a deep copy if they need to make changes). The resulting hash maps char* names to char* values. */ @@ -1431,6 +1431,18 @@ svn_ra_serf__get_locks(svn_ra_session_t svn_depth_t depth, apr_pool_t *pool); +/* Implements svn_ra__vtable_t.list(). */ +svn_error_t * +svn_ra_serf__list(svn_ra_session_t *ra_session, + const char *path, + svn_revnum_t revision, + const apr_array_header_t *patterns, + svn_depth_t depth, + apr_uint32_t dirent_fields, + svn_ra_dirent_receiver_t receiver, + void *receiver_baton, + apr_pool_t *scratch_pool); + /* Request a mergeinfo-report from the URL attached to SESSION, and fill in the MERGEINFO hash with the results. @@ -1460,6 +1472,7 @@ svn_ra_serf__get_mergeinfo(svn_ra_sessio svn_error_t * svn_ra_serf__exchange_capabilities(svn_ra_serf__session_t *serf_sess, const char **corrected_url, + const char **redirect_url, apr_pool_t *result_pool, apr_pool_t *scratch_pool); @@ -1590,6 +1603,16 @@ svn_ra_serf__setup_svndiff_accept_encodi svn_boolean_t svn_ra_serf__is_low_latency_connection(svn_ra_serf__session_t *session); +/* Return an APR array of svn_ra_serf__dav_props_t containing the + * properties (names and namespaces) corresponding to the flegs set + * in DIRENT_FIELDS. If SESSION does not support deadprops, only + * the generic "DAV:allprop" will be returned. Allocate the result + * in RESULT_POOL. */ +apr_array_header_t * +svn_ra_serf__get_dirent_props(apr_uint32_t dirent_fields, + svn_ra_serf__session_t *session, + apr_pool_t *result_pool); + /* Default limit for in-memory size of a request body. */ #define SVN_RA_SERF__REQUEST_BODY_IN_MEM_SIZE 256 * 1024 Modified: subversion/branches/addremove/subversion/libsvn_ra_serf/replay.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_serf/replay.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_serf/replay.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra_serf/replay.c Sat May 23 14:16:56 2020 @@ -666,7 +666,7 @@ svn_ra_serf__replay_range(svn_ra_session apr_pool_t *subpool = svn_pool_create(scratch_pool); if (session->http20) { - /* ### Auch... this doesn't work yet... + /* ### Auch... this doesn't work yet... This code relies on responses coming in in an exact order, while http2 does everything to deliver responses as fast as possible. @@ -701,7 +701,7 @@ svn_ra_serf__replay_range(svn_ra_session wish for the best. See issue #4287: - http://subversion.tigris.org/issues/show_bug.cgi?id=4287 + https://issues.apache.org/jira/browse/SVN-4287 */ if (session->supports_rev_rsrc_replay) { Modified: subversion/branches/addremove/subversion/libsvn_ra_serf/serf.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_serf/serf.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_serf/serf.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra_serf/serf.c Sat May 23 14:16:56 2020 @@ -363,7 +363,7 @@ load_config(svn_ra_serf__session_t *sess { apr_int64_t timeout; svn_error_t *err; - + err = svn_cstring_strtoi64(&timeout, timeout_str, 0, APR_INT64_MAX, 10); if (err) return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, err, @@ -476,6 +476,7 @@ get_user_agent_string(apr_pool_t *pool) static svn_error_t * svn_ra_serf__open(svn_ra_session_t *session, const char **corrected_url, + const char **redirect_url, const char *session_URL, const svn_ra_callbacks2_t *callbacks, void *callback_baton, @@ -492,6 +493,8 @@ svn_ra_serf__open(svn_ra_session_t *sess if (corrected_url) *corrected_url = NULL; + if (redirect_url) + *redirect_url = NULL; serf_sess = apr_pcalloc(result_pool, sizeof(*serf_sess)); serf_sess->pool = result_pool; @@ -588,7 +591,7 @@ svn_ra_serf__open(svn_ra_session_t *sess Luckily our caller now passes us two pools which handle this case. */ #if defined(SVN_DEBUG) && !SERF_VERSION_AT_LEAST(1,4,0) - /* Currently ensured by svn_ra_open4(). + /* Currently ensured by svn_ra_open5(). If failing causes segfault in basic_tests.py 48, "basic auth test" */ SVN_ERR_ASSERT((serf_sess->pool != scratch_pool) && apr_pool_is_ancestor(serf_sess->pool, scratch_pool)); @@ -599,6 +602,7 @@ svn_ra_serf__open(svn_ra_session_t *sess serf_sess->conn_latency = -1; err = svn_ra_serf__exchange_capabilities(serf_sess, corrected_url, + redirect_url, result_pool, scratch_pool); /* serf should produce a usable error code instead of APR_EGENERAL */ @@ -691,7 +695,7 @@ ra_serf_dup_session(svn_ra_session_t *ne if (new_sess->proxy_password) { - new_sess->proxy_username + new_sess->proxy_password = apr_pstrdup(result_pool, new_sess->proxy_password); } @@ -1063,7 +1067,7 @@ static const svn_ra__vtable_t serf_vtabl svn_ra_serf__get_deleted_rev, svn_ra_serf__get_inherited_props, NULL /* set_svn_ra_open */, - NULL /* svn_ra_list */, + svn_ra_serf__list, svn_ra_serf__register_editor_shim_callbacks, NULL /* commit_ev2 */, NULL /* replay_range_ev2 */ Modified: subversion/branches/addremove/subversion/libsvn_ra_serf/stat.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_serf/stat.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_serf/stat.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra_serf/stat.c Sat May 23 14:16:56 2020 @@ -216,64 +216,8 @@ get_dirent_props(apr_uint32_t dirent_fie apr_pool_t *pool) { svn_ra_serf__dav_props_t *prop; - apr_array_header_t *props = apr_array_make - (pool, 7, sizeof(svn_ra_serf__dav_props_t)); - - if (session->supports_deadprop_count != svn_tristate_false - || ! (dirent_fields & SVN_DIRENT_HAS_PROPS)) - { - if (dirent_fields & SVN_DIRENT_KIND) - { - prop = apr_array_push(props); - prop->xmlns = "DAV:"; - prop->name = "resourcetype"; - } - - if (dirent_fields & SVN_DIRENT_SIZE) - { - prop = apr_array_push(props); - prop->xmlns = "DAV:"; - prop->name = "getcontentlength"; - } - - if (dirent_fields & SVN_DIRENT_HAS_PROPS) - { - prop = apr_array_push(props); - prop->xmlns = SVN_DAV_PROP_NS_DAV; - prop->name = "deadprop-count"; - } - - if (dirent_fields & SVN_DIRENT_CREATED_REV) - { - svn_ra_serf__dav_props_t *p = apr_array_push(props); - p->xmlns = "DAV:"; - p->name = SVN_DAV__VERSION_NAME; - } - - if (dirent_fields & SVN_DIRENT_TIME) - { - prop = apr_array_push(props); - prop->xmlns = "DAV:"; - prop->name = SVN_DAV__CREATIONDATE; - } - - if (dirent_fields & SVN_DIRENT_LAST_AUTHOR) - { - prop = apr_array_push(props); - prop->xmlns = "DAV:"; - prop->name = "creator-displayname"; - } - } - else - { - /* We found an old subversion server that can't handle - the deadprop-count property in the way we expect. - - The neon behavior is to retrieve all properties in this case */ - prop = apr_array_push(props); - prop->xmlns = "DAV:"; - prop->name = "allprop"; - } + apr_array_header_t *props = svn_ra_serf__get_dirent_props(dirent_fields, + session, pool); prop = apr_array_push(props); prop->xmlns = NULL; Modified: subversion/branches/addremove/subversion/libsvn_ra_serf/update.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_serf/update.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_serf/update.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra_serf/update.c Sat May 23 14:16:56 2020 @@ -603,7 +603,7 @@ get_best_connection(report_context_t *ct ### simply can't handle the way ra_serf violates the editor v1 ### drive ordering requirements. ### - ### See http://subversion.tigris.org/issues/show_bug.cgi?id=4116. + ### See https://issues.apache.org/jira/browse/SVN-4116. */ if (ctx->report_received && (ctx->sess->max_connections > 2)) first_conn = 0; @@ -2223,7 +2223,7 @@ process_buffer(update_delay_baton_t *udb } -/* Delaying wrapping reponse handler, to avoid creating too many +/* Delaying wrapping response handler, to avoid creating too many requests to deliver efficiently */ static svn_error_t * update_delay_handler(serf_request_t *request, Modified: subversion/branches/addremove/subversion/libsvn_ra_serf/util.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_serf/util.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_serf/util.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra_serf/util.c Sat May 23 14:16:56 2020 @@ -756,6 +756,9 @@ handle_client_cert_pw(void *data, if (creds) { + /* At this stage we are unable to check whether the password + is correct; if it is incorrect serf will fail to establish + an SSL connection and will return a generic SSL error. */ svn_auth_cred_ssl_client_cert_pw_t *pw_creds; pw_creds = creds; *password = pw_creds->password; @@ -795,7 +798,7 @@ apr_status_t svn_ra_serf__handle_client_ * * If CONTENT_TYPE is not-NULL, it will be sent as the Content-Type header. * - * If DAV_HEADERS is non-zero, it will add standard DAV capabilites headers + * If DAV_HEADERS is non-zero, it will add standard DAV capabilities headers * to request. * * REQUEST_POOL should live for the duration of the request. Serf will @@ -994,7 +997,7 @@ svn_ra_serf__context_run_wait(svn_boolea /* Ensure that a handler is no longer scheduled on the connection. Eventually serf will have a reliable way to cancel existing requests, - but currently it doesn't even have a way to relyable identify a request + but currently it doesn't even have a way to reliable identify a request after rescheduling, for auth reasons. So the only thing we can do today is reset the connection, which @@ -1113,19 +1116,17 @@ response_get_location(serf_bucket_t *res return NULL; /* Replace the path path with what we got */ - uri.path = (char*)svn_urlpath__canonicalize(location, scratch_pool); + uri.path = apr_pstrdup(scratch_pool, location); /* And make APR produce a proper full url for us */ - location = apr_uri_unparse(scratch_pool, &uri, 0); - - /* Fall through to ensure our canonicalization rules */ + return apr_uri_unparse(result_pool, &uri, 0); } else if (!svn_path_is_url(location)) { return NULL; /* Any other formats we should support? */ } - return svn_uri_canonicalize(location, result_pool); + return apr_pstrdup(result_pool, location); } @@ -1445,6 +1446,23 @@ handle_response(serf_request_t *request, process_body: + /* A client cert file password was obtained and worked (any HTTP + response means that the SSL connection was established.) */ + if (handler->conn->ssl_client_pw_auth_state) + { + SVN_ERR(svn_auth_save_credentials(handler->conn->ssl_client_pw_auth_state, + handler->session->pool)); + handler->conn->ssl_client_pw_auth_state = NULL; + } + if (handler->conn->ssl_client_auth_state) + { + /* The cert file provider doesn't have any code to save creds so + this is currently a no-op. */ + SVN_ERR(svn_auth_save_credentials(handler->conn->ssl_client_auth_state, + handler->session->pool)); + handler->conn->ssl_client_auth_state = NULL; + } + /* We've been instructed to ignore the body. Drain whatever is present. */ if (handler->discard_body) { @@ -1532,7 +1550,7 @@ handle_response_cb(serf_request_t *reque If we would return an error outer-status the connection would have to be restarted. With scheduled still TRUE destroying the handler's pool will still reset the - connection, avoiding the posibility of returning + connection, avoiding the possibility of returning an error for this handler when a new request is scheduled. */ outer_status = APR_EAGAIN; /* Exit context loop */ @@ -2065,3 +2083,72 @@ svn_ra_serf__is_low_latency_connection(s return session->conn_latency >= 0 && session->conn_latency < apr_time_from_msec(5); } + +apr_array_header_t * +svn_ra_serf__get_dirent_props(apr_uint32_t dirent_fields, + svn_ra_serf__session_t *session, + apr_pool_t *result_pool) +{ + svn_ra_serf__dav_props_t *prop; + apr_array_header_t *props = apr_array_make + (result_pool, 7, sizeof(svn_ra_serf__dav_props_t)); + + if (session->supports_deadprop_count != svn_tristate_false + || ! (dirent_fields & SVN_DIRENT_HAS_PROPS)) + { + if (dirent_fields & SVN_DIRENT_KIND) + { + prop = apr_array_push(props); + prop->xmlns = "DAV:"; + prop->name = "resourcetype"; + } + + if (dirent_fields & SVN_DIRENT_SIZE) + { + prop = apr_array_push(props); + prop->xmlns = "DAV:"; + prop->name = "getcontentlength"; + } + + if (dirent_fields & SVN_DIRENT_HAS_PROPS) + { + prop = apr_array_push(props); + prop->xmlns = SVN_DAV_PROP_NS_DAV; + prop->name = "deadprop-count"; + } + + if (dirent_fields & SVN_DIRENT_CREATED_REV) + { + svn_ra_serf__dav_props_t *p = apr_array_push(props); + p->xmlns = "DAV:"; + p->name = SVN_DAV__VERSION_NAME; + } + + if (dirent_fields & SVN_DIRENT_TIME) + { + prop = apr_array_push(props); + prop->xmlns = "DAV:"; + prop->name = SVN_DAV__CREATIONDATE; + } + + if (dirent_fields & SVN_DIRENT_LAST_AUTHOR) + { + prop = apr_array_push(props); + prop->xmlns = "DAV:"; + prop->name = "creator-displayname"; + } + } + else + { + /* We found an old subversion server that can't handle + the deadprop-count property in the way we expect. + + The neon behavior is to retrieve all properties in this case */ + prop = apr_array_push(props); + prop->xmlns = "DAV:"; + prop->name = "allprop"; + } + + return props; +} + Modified: subversion/branches/addremove/subversion/libsvn_ra_svn/client.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_svn/client.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_svn/client.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra_svn/client.c Sat May 23 14:16:56 2020 @@ -561,8 +561,8 @@ static svn_error_t *make_tunnel(const ch return SVN_NO_ERROR; } -/* Parse URL inot URI, validating it and setting the default port if none - was given. Allocate the URI fileds out of POOL. */ +/* Parse URL into URI, validating it and setting the default port if none + was given. Allocate the URI fields out of POOL. */ static svn_error_t *parse_url(const char *url, apr_uri_t *uri, apr_pool_t *pool) { @@ -841,6 +841,7 @@ is_valid_hostinfo(const char *hostinfo) static svn_error_t *ra_svn_open(svn_ra_session_t *session, const char **corrected_url, + const char **redirect_url, const char *url, const svn_ra_callbacks2_t *callbacks, void *callback_baton, @@ -858,6 +859,8 @@ static svn_error_t *ra_svn_open(svn_ra_s /* We don't support server-prescribed redirections in ra-svn. */ if (corrected_url) *corrected_url = NULL; + if (redirect_url) + *redirect_url = NULL; SVN_ERR(parse_url(url, &uri, sess_pool)); @@ -913,7 +916,7 @@ static svn_error_t *ra_svn_dup_session(s { svn_ra_svn__session_baton_t *old_sess = old_session->priv; - SVN_ERR(ra_svn_open(new_session, NULL, new_session_url, + SVN_ERR(ra_svn_open(new_session, NULL, NULL, new_session_url, old_sess->callbacks, old_sess->callbacks_baton, old_sess->auth_baton, old_sess->config, result_pool, scratch_pool)); @@ -1613,7 +1616,7 @@ static svn_error_t *ra_svn_get_dir(svn_r Note: they should NOT be "fixed" to send NULL, as that would break any older clients which received that NULL. But we may as well - be defensive against a malicous server. */ + be defensive against a malicious server. */ if (cdate == NULL) dirent->time = 0; else @@ -3105,6 +3108,7 @@ ra_svn_get_deleted_rev(svn_ra_session_t { svn_ra_svn__session_baton_t *sess_baton = session->priv; svn_ra_svn_conn_t *conn = sess_baton->conn; + svn_error_t *err; path = reparent_path(session, path, pool); @@ -3116,8 +3120,20 @@ ra_svn_get_deleted_rev(svn_ra_session_t SVN_ERR(handle_unsupported_cmd(handle_auth_request(sess_baton, pool), N_("'get-deleted-rev' not implemented"))); - return svn_error_trace(svn_ra_svn__read_cmd_response(conn, pool, "r", - revision_deleted)); + err = svn_error_trace(svn_ra_svn__read_cmd_response(conn, pool, "r", + revision_deleted)); + /* The protocol does not allow for a reply of SVN_INVALID_REVNUM directly. + Instead, a new enough server returns SVN_ERR_ENTRY_MISSING_REVISION to + indicate the answer to the query is SVN_INVALID_REVNUM. (An older server + closes the connection and returns SVN_ERR_RA_SVN_CONNECTION_CLOSED.) */ + if (err && err->apr_err == SVN_ERR_ENTRY_MISSING_REVISION) + { + *revision_deleted = SVN_INVALID_REVNUM; + svn_error_clear(err); + } + else + SVN_ERR(err); + return SVN_NO_ERROR; } static svn_error_t * Modified: subversion/branches/addremove/subversion/libsvn_ra_svn/cyrus_auth.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_svn/cyrus_auth.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_svn/cyrus_auth.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra_svn/cyrus_auth.c Sat May 23 14:16:56 2020 @@ -277,7 +277,7 @@ void svn_ra_svn__default_secprops(sasl_s secprops->max_ssf = 256; /* Set maxbufsize to the maximum amount of data we can read at any one time. - This value needs to be commmunicated to the peer if a security layer + This value needs to be communicated to the peer if a security layer is negotiated. */ secprops->maxbufsize = SVN_RA_SVN__READBUF_SIZE; Modified: subversion/branches/addremove/subversion/libsvn_ra_svn/editorp.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_svn/editorp.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_svn/editorp.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra_svn/editorp.c Sat May 23 14:16:56 2020 @@ -118,7 +118,7 @@ make_token(char type, char buffer[1 + SVN_INT64_BUFFER_SIZE]; buffer[0] = type; len = 1 + svn__ui64toa(&buffer[1], eb->next_token++); - + return svn_string_ncreate(buffer, len, pool); } @@ -351,17 +351,9 @@ static svn_error_t *ra_svn_apply_textdel svn_stream_set_write(diff_stream, ra_svn_svndiff_handler); svn_stream_set_close(diff_stream, ra_svn_svndiff_close_handler); - /* If the connection does not support SVNDIFF1 or if we don't want to use - * compression, use the non-compressing "version 0" implementation */ - /* ### TODO: Check SVN_RA_SVN_CAP_SVNDIFF2_ACCEPTED and decide between - * ### svndiff1[at compression_level] and svndiff2 */ - if ( svn_ra_svn_compression_level(b->conn) > 0 - && svn_ra_svn_has_capability(b->conn, SVN_RA_SVN_CAP_SVNDIFF1)) - svn_txdelta_to_svndiff3(wh, wh_baton, diff_stream, 1, - b->conn->compression_level, pool); - else - svn_txdelta_to_svndiff3(wh, wh_baton, diff_stream, 0, - b->conn->compression_level, pool); + svn_txdelta_to_svndiff3(wh, wh_baton, diff_stream, + svn_ra_svn__svndiff_version(b->conn), + b->conn->compression_level, pool); return SVN_NO_ERROR; } Modified: subversion/branches/addremove/subversion/libsvn_ra_svn/marshal.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_svn/marshal.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_svn/marshal.c (original) +++ subversion/branches/addremove/subversion/libsvn_ra_svn/marshal.c Sat May 23 14:16:56 2020 @@ -265,6 +265,24 @@ svn_ra_svn__set_capabilities(svn_ra_svn_ return SVN_NO_ERROR; } +int +svn_ra_svn__svndiff_version(svn_ra_svn_conn_t *conn) +{ + /* If we don't want to use compression, use the non-compressing + * "version 0" implementation. */ + if (svn_ra_svn_compression_level(conn) <= 0) + return 0; + + /* Prefer SVNDIFF2 over SVNDIFF1. */ + if (svn_ra_svn_has_capability(conn, SVN_RA_SVN_CAP_SVNDIFF2_ACCEPTED)) + return 2; + if (svn_ra_svn_has_capability(conn, SVN_RA_SVN_CAP_SVNDIFF1)) + return 1; + + /* The connection does not support SVNDIFF1/2; default to "version 0". */ + return 0; +} + apr_pool_t * svn_ra_svn__get_pool(svn_ra_svn_conn_t *conn) { @@ -1870,7 +1888,7 @@ svn_ra_svn__has_command(svn_boolean_t *h { svn_error_t *err; - /* Don't make whitespace between commands trigger I/O limitiations. */ + /* Don't make whitespace between commands trigger I/O limitations. */ svn_ra_svn__reset_command_io_counters(conn); err = svn_ra_svn__has_item(has_command, conn, pool); Modified: subversion/branches/addremove/subversion/libsvn_ra_svn/protocol URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_ra_svn/protocol?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_ra_svn/protocol (original) +++ subversion/branches/addremove/subversion/libsvn_ra_svn/protocol Sat May 23 14:16:56 2020 @@ -342,7 +342,7 @@ second place for auth-request point as n stat params: ( path:string [ rev:number ] ) response: ( ? entry:dirent ) - dirent: ( name:string kind:node-kind size:number has-props:bool + dirent: ( kind:node-kind size:number has-props:bool created-rev:number [ created-date:string ] [ last-author:string ] ) New in svn 1.2. If path is non-existent, an empty response is returned. Modified: subversion/branches/addremove/subversion/libsvn_repos/authz.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_repos/authz.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_repos/authz.c (original) +++ subversion/branches/addremove/subversion/libsvn_repos/authz.c Sat May 23 14:16:56 2020 @@ -81,11 +81,11 @@ typedef struct limited_rights_t */ path_access_t access; - /* Minimal access rights that the user has on this or any other node in + /* Minimal access rights that the user has on this or any other node in * the sub-tree. This does not take inherited rights into account. */ authz_access_t min_rights; - /* Maximal access rights that the user has on this or any other node in + /* Maximal access rights that the user has on this or any other node in * the sub-tree. This does not take inherited rights into account. */ authz_access_t max_rights; @@ -369,7 +369,7 @@ ensure_node_in_array(apr_array_header_t * Create one and insert it into the sorted array. */ entry.node = create_node(segment, result_pool); entry.next = NULL; - svn_sort__array_insert(*array, &entry, idx); + svn_error_clear(svn_sort__array_insert2(*array, &entry, idx)); return entry.node; } @@ -889,7 +889,7 @@ create_user_authz(authz_full_t *authz, /* Use a separate sub-pool to keep memory usage tight. */ apr_pool_t *subpool = svn_pool_create(scratch_pool); - /* Find all ACLs for REPOSITORY. + /* Find all ACLs for REPOSITORY. * Note that repo-specific rules replace global rules, * even if they don't apply to the current user. */ apr_array_header_t *acls = apr_array_make(subpool, authz->acls->nelts, @@ -947,7 +947,7 @@ create_user_authz(authz_full_t *authz, svn_pool_clear(subpool); trim_tree(root, NO_SEQUENCE_NUMBER, subpool); - /* Calculate recursive rights. + /* Calculate recursive rights. * * This is a bottom-up calculation of the range of access rights * specified anywhere in the respective sub-tree, including the base @@ -999,7 +999,7 @@ static lookup_state_t * create_lookup_state(apr_pool_t *result_pool) { lookup_state_t *state = apr_pcalloc(result_pool, sizeof(*state)); - + state->next = apr_array_make(result_pool, 4, sizeof(node_t *)); state->current = apr_array_make(result_pool, 4, sizeof(node_t *)); @@ -1548,6 +1548,8 @@ authz_read(authz_full_t **authz_p, const char *groups_path, svn_boolean_t must_exist, svn_repos_t *repos_hint, + svn_repos_authz_warning_func_t warning_func, + void *warning_baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -1587,7 +1589,8 @@ authz_read(authz_full_t **authz_p, /* Parse the configuration(s) and construct the full authz model * from it. */ err = svn_authz__parse(authz_p, rules_stream, groups_stream, - item_pool, scratch_pool); + warning_func, warning_baton, + item_pool, scratch_pool); if (err != SVN_NO_ERROR) { /* That pool would otherwise never get destroyed. */ @@ -1611,11 +1614,11 @@ authz_read(authz_full_t **authz_p, { /* Parse the configuration(s) and construct the full authz model from * it. */ - err = svn_error_quick_wrapf(svn_authz__parse(authz_p, rules_stream, - groups_stream, - result_pool, scratch_pool), - "Error while parsing authz file: '%s':", - path); + err = svn_error_quick_wrapf( + svn_authz__parse(authz_p, rules_stream, groups_stream, + warning_func, warning_baton, + result_pool, scratch_pool), + "Error while parsing authz file: '%s':", path); } svn_repos__destroy_config_access(config_access); @@ -1628,11 +1631,13 @@ authz_read(authz_full_t **authz_p, /*** Public functions. ***/ svn_error_t * -svn_repos_authz_read3(svn_authz_t **authz_p, +svn_repos_authz_read4(svn_authz_t **authz_p, const char *path, const char *groups_path, svn_boolean_t must_exist, svn_repos_t *repos_hint, + svn_repos_authz_warning_func_t warning_func, + void *warning_baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -1640,7 +1645,8 @@ svn_repos_authz_read3(svn_authz_t **auth authz->pool = result_pool; SVN_ERR(authz_read(&authz->full, &authz->authz_id, path, groups_path, - must_exist, repos_hint, result_pool, scratch_pool)); + must_exist, repos_hint, warning_func, warning_baton, + result_pool, scratch_pool)); *authz_p = authz; return SVN_NO_ERROR; @@ -1648,18 +1654,21 @@ svn_repos_authz_read3(svn_authz_t **auth svn_error_t * -svn_repos_authz_parse(svn_authz_t **authz_p, svn_stream_t *stream, - svn_stream_t *groups_stream, apr_pool_t *pool) +svn_repos_authz_parse2(svn_authz_t **authz_p, + svn_stream_t *stream, + svn_stream_t *groups_stream, + svn_repos_authz_warning_func_t warning_func, + void *warning_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - apr_pool_t *scratch_pool = svn_pool_create(pool); - svn_authz_t *authz = apr_pcalloc(pool, sizeof(*authz)); - authz->pool = pool; + svn_authz_t *authz = apr_pcalloc(result_pool, sizeof(*authz)); + authz->pool = result_pool; /* Parse the configuration and construct the full authz model from it. */ - SVN_ERR(svn_authz__parse(&authz->full, stream, groups_stream, pool, - scratch_pool)); - - svn_pool_destroy(scratch_pool); + SVN_ERR(svn_authz__parse(&authz->full, stream, groups_stream, + warning_func, warning_baton, + result_pool, scratch_pool)); *authz_p = authz; return SVN_NO_ERROR; Modified: subversion/branches/addremove/subversion/libsvn_repos/authz.h URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_repos/authz.h?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_repos/authz.h (original) +++ subversion/branches/addremove/subversion/libsvn_repos/authz.h Sat May 23 14:16:56 2020 @@ -139,6 +139,10 @@ typedef struct authz_full_t svn_boolean_t has_authn_rights; authz_global_rights_t authn_rights; + /* Globally accumulated rights from inverted selectors. */ + svn_boolean_t has_neg_rights; + authz_global_rights_t neg_rights; + /* Globally accumulated rights, for all concrete users mentioned in the authz file. The key is the user name, the value is an authz_global_rights_t*. */ @@ -257,14 +261,19 @@ typedef struct authz_acl_t /* The parsed rule. */ authz_rule_t rule; - /* Access rights for anonymous users */ + + /* Access rights for anonymous users. */ svn_boolean_t has_anon_access; authz_access_t anon_access; - /* Access rights for authenticated users */ + /* Access rights for authenticated users. */ svn_boolean_t has_authn_access; authz_access_t authn_access; + /* Access rights from inverted selectors. */ + svn_boolean_t has_neg_access; + authz_access_t neg_access; + /* All other user- or group-specific access rights. Aliases are replaced with their definitions, rules for the same user or group are merged. */ @@ -303,6 +312,8 @@ svn_error_t * svn_authz__parse(authz_full_t **authz, svn_stream_t *rules, svn_stream_t *groups, + svn_repos_authz_warning_func_t warning_func, + void *warning_baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool); Modified: subversion/branches/addremove/subversion/libsvn_repos/authz_info.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_repos/authz_info.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_repos/authz_info.c (original) +++ subversion/branches/addremove/subversion/libsvn_repos/authz_info.c Sat May 23 14:16:56 2020 @@ -148,37 +148,50 @@ svn_authz__get_global_rights(authz_right { /* Check if we have explicit rights for anonymous access. */ if (authz->has_anon_rights) - return resolve_global_rights(rights_p, &authz->anon_rights, repos); + { + return resolve_global_rights(rights_p, &authz->anon_rights, repos); + } + else + { + /* Return the implicit rights, i.e., none. */ + rights_p->min_access = authz_access_none; + rights_p->max_access = authz_access_none; + return FALSE; + } } else { + svn_boolean_t combine_user_rights = FALSE; + svn_boolean_t access = FALSE; + /* Check if we have explicit rights for this user. */ const authz_global_rights_t *const user_rights = svn_hash_gets(authz->user_rights, user); if (user_rights) { - svn_boolean_t explicit - = resolve_global_rights(rights_p, user_rights, repos); - - /* Rights given to _any_ authenticated user may apply, too. */ - if (authz->has_authn_rights) - { - authz_rights_t authn; - explicit |= resolve_global_rights(&authn, &authz->authn_rights, - repos); - combine_rights(rights_p, rights_p, &authn); - } - return explicit; + access = resolve_global_rights(rights_p, user_rights, repos); + combine_user_rights = TRUE; + } + else if (authz->has_neg_rights) + { + /* Check if inverted-rule rights apply */ + access = resolve_global_rights(rights_p, &authz->neg_rights, repos); + combine_user_rights = TRUE; } - /* Check if we have explicit rights for authenticated access. */ + /* Rights given to _any_ authenticated user may apply, too. */ if (authz->has_authn_rights) - return resolve_global_rights(rights_p, &authz->authn_rights, repos); - } + { + authz_rights_t authn; + access |= resolve_global_rights(&authn, &authz->authn_rights, repos); - /* Fall-through: return the implicit rights, i.e., none. */ - rights_p->min_access = authz_access_none; - rights_p->max_access = authz_access_none; - return FALSE; + if (combine_user_rights) + combine_rights(rights_p, rights_p, &authn); + else + *rights_p = authn; + } + + return access; + } } Modified: subversion/branches/addremove/subversion/libsvn_repos/authz_parse.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_repos/authz_parse.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_repos/authz_parse.c (original) +++ subversion/branches/addremove/subversion/libsvn_repos/authz_parse.c Sat May 23 14:16:56 2020 @@ -83,7 +83,7 @@ typedef struct ctor_baton_t same immutable string multiple times, we reduce the size of the authz representation in the result pool. - N.B.: Whilst the strings are allocated from teh result pool, the + N.B.: Whilst the strings are allocated from the result pool, the hash table itself is not. */ apr_hash_t *strings; @@ -127,6 +127,10 @@ typedef struct ctor_baton_t svn_membuf_t rule_path_buffer; svn_stringbuf_t *rule_string_buffer; + /* The warning callback and its baton. */ + svn_repos_authz_warning_func_t warning_func; + void *warning_baton; + /* The parser's scratch pool. This may not be the same pool as passed to the constructor callbacks, that is supposed to be an iteration pool maintained by the generic parser. @@ -154,6 +158,8 @@ static const char anon_access_token[] = /* The authenticated access token. */ static const char authn_access_token[] = "$authenticated"; +/* Fake token for inverted rights. */ +static const char neg_access_token[] = "~~$inverted"; /* Initialize a rights structure. The minimum rights start with all available access and are later @@ -191,15 +197,19 @@ insert_default_acl(ctor_baton_t *cb) acl->acl.has_anon_access = TRUE; acl->acl.authn_access = authz_access_none; acl->acl.has_authn_access = TRUE; + acl->acl.neg_access = authz_access_none; + acl->acl.has_neg_access = TRUE; acl->acl.user_access = NULL; acl->aces = svn_hash__make(cb->parser_pool); acl->alias_aces = svn_hash__make(cb->parser_pool); } -/* Initialize a constuctor baton. */ +/* Initialize a constructor baton. */ static ctor_baton_t * -create_ctor_baton(apr_pool_t *result_pool, +create_ctor_baton(svn_repos_authz_warning_func_t warning_func, + void *warning_baton, + apr_pool_t *result_pool, apr_pool_t *scratch_pool) { apr_pool_t *const parser_pool = svn_pool_create(scratch_pool); @@ -208,6 +218,7 @@ create_ctor_baton(apr_pool_t *result_poo authz_full_t *const authz = apr_pcalloc(result_pool, sizeof(*authz)); init_global_rights(&authz->anon_rights, anon_access_token, result_pool); init_global_rights(&authz->authn_rights, authn_access_token, result_pool); + init_global_rights(&authz->neg_rights, neg_access_token, result_pool); authz->user_rights = svn_hash__make(result_pool); authz->pool = result_pool; @@ -229,6 +240,9 @@ create_ctor_baton(apr_pool_t *result_poo svn_membuf__create(&cb->rule_path_buffer, 0, parser_pool); cb->rule_string_buffer = svn_stringbuf_create_empty(parser_pool); + cb->warning_func = warning_func; + cb->warning_baton = warning_baton; + cb->parser_pool = parser_pool; insert_default_acl(cb); @@ -237,6 +251,25 @@ create_ctor_baton(apr_pool_t *result_poo } +/* Emit a warning. Clears ERROR */ +static void +emit_parser_warning(const ctor_baton_t *cb, + svn_error_t *error, + apr_pool_t *scratch_pool) +{ + if (cb->warning_func) + cb->warning_func(cb->warning_baton, error, scratch_pool); + svn_error_clear(error); +} + +/* Avoid creating an error struct if there is no warning function. */ +#define SVN_AUTHZ_PARSE_WARN(cb, err, pool) \ + do { \ + if ((cb) && (cb)->warning_func) \ + emit_parser_warning((cb), (err), (pool)); \ + } while(0) + + /* Create and store per-user global rights. The USER string must be interned or statically initialized. */ static void @@ -536,7 +569,7 @@ parse_rule_path(authz_rule_t *rule, || (pattern->len == 2 && pattern->data[1] == '*')) { /* Process * and **, applying normalization as per - https://wiki.apache.org/subversion/AuthzImprovements. */ + https://cwiki.apache.org/confluence/display/SVN/Authz+Improvements. */ authz_rule_segment_t *const prev = (nseg > 1 ? segment - 1 : NULL); @@ -758,6 +791,8 @@ rules_open_section(void *baton, svn_stri acl.acl.has_anon_access = FALSE; acl.acl.authn_access = authz_access_none; acl.acl.has_authn_access = FALSE; + acl.acl.neg_access = authz_access_none; + acl.acl.has_neg_access = FALSE; acl.acl.user_access = NULL; acl.aces = svn_hash__make(cb->parser_pool); @@ -930,7 +965,7 @@ add_access_entry(ctor_baton_t *cb, svn_s { /* The inversion tag must be part of the key in the hash table, otherwise we can't tell regular and inverted - entries appart. */ + entries apart. */ const char *key = (inverted ? name - 1 : name); const apr_size_t key_len = (inverted ? name_len + 1 : name_len); const svn_boolean_t aliased = (*name == '&'); @@ -958,6 +993,14 @@ add_access_entry(ctor_baton_t *cb, svn_s if (!aliased && *ace->name != '@') prepare_global_rights(cb, ace->name); } + + /* Propagate rights for inverted selectors to the global rights, otherwise + an access check can bail out early. See: SVN-4793 */ + if (inverted) + { + acl->acl.has_neg_access = TRUE; + acl->acl.neg_access |= access; + } } return SVN_NO_ERROR; @@ -996,7 +1039,8 @@ close_section(void *baton, svn_stringbuf /* Add a user to GROUP. - GROUP is never internalized, but USER always is. */ + GROUP is never internalized, but USER always is. + Adding a NULL user will create an empty group, if it doesn't exist. */ static void add_to_group(ctor_baton_t *cb, const char *group, const char *user) { @@ -1007,7 +1051,8 @@ add_to_group(ctor_baton_t *cb, const cha members = svn_hash__make(cb->authz->pool); svn_hash_sets(cb->expanded_groups, group, members); } - svn_hash_sets(members, user, interned_empty_string); + if (user) + svn_hash_sets(members, user, interned_empty_string); } @@ -1023,8 +1068,15 @@ expand_group_callback(void *baton, ctor_baton_t *const cb = baton; const char *const group = key; apr_array_header_t *members = value; - int i; + + if (0 == members->nelts) + { + /* Create the group with no members. */ + add_to_group(cb, group, NULL); + return SVN_NO_ERROR; + } + for (i = 0; i < members->nelts; ++i) { const char *member = APR_ARRAY_IDX(members, i, const char*); @@ -1058,14 +1110,15 @@ expand_group_callback(void *baton, else { /* Recursively expand the group membership */ - members = svn_hash_gets(cb->parsed_groups, member); - if (!members) + apr_array_header_t *member_members + = svn_hash_gets(cb->parsed_groups, member); + if (!member_members) return svn_error_createf( SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, _("Undefined group '%s'"), member); SVN_ERR(expand_group_callback(cb, key, klen, - members, scratch_pool)); + member_members, scratch_pool)); } } return SVN_NO_ERROR; @@ -1153,10 +1206,24 @@ array_insert_ace(void *baton, SVN_ERR_ASSERT(ace->members == NULL); ace->members = svn_hash_gets(iab->cb->expanded_groups, ace->name); if (!ace->members) - return svn_error_createf( - SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, - _("Access entry refers to undefined group '%s'"), - ace->name); + { + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Access entry refers to undefined group '%s'"), + ace->name); + } + else if (0 == apr_hash_count(ace->members)) + { + /* An ACE for an empty group has no effect, so ignore it. */ + SVN_AUTHZ_PARSE_WARN( + iab->cb, + svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Ignoring access entry for empty group '%s'"), + ace->name), + scratch_pool); + return SVN_NO_ERROR; + } } APR_ARRAY_PUSH(iab->ace_array, authz_ace_t) = *ace; @@ -1270,6 +1337,12 @@ expand_acl_callback(void *baton, update_global_rights(&cb->authz->authn_rights, acl->rule.repos, acl->authn_access); } + if (acl->has_neg_access) + { + cb->authz->has_neg_rights = TRUE; + update_global_rights(&cb->authz->neg_rights, + acl->rule.repos, acl->neg_access); + } SVN_ERR(svn_iter_apr_hash(NULL, cb->authz->user_rights, update_user_rights, acl, scratch_pool)); return SVN_NO_ERROR; @@ -1296,10 +1369,13 @@ svn_error_t * svn_authz__parse(authz_full_t **authz, svn_stream_t *rules, svn_stream_t *groups, + svn_repos_authz_warning_func_t warning_func, + void *warning_baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - ctor_baton_t *const cb = create_ctor_baton(result_pool, scratch_pool); + ctor_baton_t *const cb = create_ctor_baton(warning_func, warning_baton, + result_pool, scratch_pool); /* * Pass 1: Parse the authz file. Modified: subversion/branches/addremove/subversion/libsvn_repos/commit.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_repos/commit.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_repos/commit.c (original) +++ subversion/branches/addremove/subversion/libsvn_repos/commit.c Sat May 23 14:16:56 2020 @@ -124,7 +124,7 @@ struct dir_baton svn_revnum_t base_rev; /* the revision I'm based on */ svn_boolean_t was_copied; /* was this directory added with history? */ apr_pool_t *pool; /* my personal pool, in which I am allocated. */ - svn_boolean_t checked_write; /* TRUE after successfull write check */ + svn_boolean_t checked_write; /* TRUE after successful write check */ }; @@ -132,7 +132,7 @@ struct file_baton { struct edit_baton *edit_baton; const char *path; /* the -absolute- path to this file in the fs */ - svn_boolean_t checked_write; /* TRUE after successfull write check */ + svn_boolean_t checked_write; /* TRUE after successful write check */ }; @@ -189,7 +189,7 @@ check_out_of_date(struct edit_baton *eb, else if (base_rev > created_rev) { if (base_rev > svn_fs_txn_base_revision(eb->txn)) - return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL, + return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL, _("No such revision %ld"), base_rev); } @@ -306,13 +306,14 @@ add_file_or_directory(const char *path, struct edit_baton *eb = pb->edit_baton; apr_pool_t *subpool = svn_pool_create(pool); svn_boolean_t was_copied = FALSE; - const char *full_path; + const char *full_path, *canonicalized_path; /* Reject paths which contain control characters (related to issue #4340). */ SVN_ERR(svn_path_check_valid(path, pool)); - full_path = svn_fspath__join(eb->base_path, - svn_relpath_canonicalize(path, pool), pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL, path, + pool, pool)); + full_path = svn_fspath__join(eb->base_path, canonicalized_path, pool); /* Sanity check. */ if (copy_path && (! SVN_IS_VALID_REVNUM(copy_revision))) @@ -477,10 +478,11 @@ delete_entry(const char *path, struct edit_baton *eb = parent->edit_baton; svn_node_kind_t kind; svn_repos_authz_access_t required = svn_authz_write; - const char *full_path; + const char *full_path, *canonicalized_path; - full_path = svn_fspath__join(eb->base_path, - svn_relpath_canonicalize(path, pool), pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL, path, + pool, pool)); + full_path = svn_fspath__join(eb->base_path, canonicalized_path, pool); /* Check PATH in our transaction. */ SVN_ERR(svn_fs_check_path(&kind, eb->txn_root, full_path, pool)); @@ -538,10 +540,11 @@ open_directory(const char *path, struct dir_baton *pb = parent_baton; struct edit_baton *eb = pb->edit_baton; svn_node_kind_t kind; - const char *full_path; + const char *full_path, *canonicalized_path; - full_path = svn_fspath__join(eb->base_path, - svn_relpath_canonicalize(path, pool), pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL, path, + pool, pool)); + full_path = svn_fspath__join(eb->base_path, canonicalized_path, pool); /* Check PATH in our transaction. If it does not exist, return a 'Path not present' error. */ @@ -611,10 +614,11 @@ open_file(const char *path, struct edit_baton *eb = pb->edit_baton; svn_revnum_t cr_rev; apr_pool_t *subpool = svn_pool_create(pool); - const char *full_path; + const char *full_path, *canonicalized_path; - full_path = svn_fspath__join(eb->base_path, - svn_relpath_canonicalize(path, pool), pool); + SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL, path, + pool, pool)); + full_path = svn_fspath__join(eb->base_path, canonicalized_path, pool); /* Check for read authorization. */ SVN_ERR(check_authz(eb, full_path, eb->txn_root, @@ -637,7 +641,7 @@ open_file(const char *path, *file_baton = new_fb; - /* Destory the work subpool. */ + /* Destroy the work subpool. */ svn_pool_destroy(subpool); return SVN_NO_ERROR; Modified: subversion/branches/addremove/subversion/libsvn_repos/compat.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_repos/compat.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_repos/compat.c (original) +++ subversion/branches/addremove/subversion/libsvn_repos/compat.c Sat May 23 14:16:56 2020 @@ -98,7 +98,7 @@ log4_path_change_receiver(void *baton, : svn_tristate_false; /* Auto-create the CHANGES container (happens for each first change - * in any revison. */ + * in any revision. */ if (b->changes == NULL) b->changes = svn_hash__make(b->changes_pool); Modified: subversion/branches/addremove/subversion/libsvn_repos/config_file.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_repos/config_file.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_repos/config_file.c (original) +++ subversion/branches/addremove/subversion/libsvn_repos/config_file.c Sat May 23 14:16:56 2020 @@ -342,7 +342,7 @@ svn_repos__create_config_access(svn_repo return result; } -void +void svn_repos__destroy_config_access(config_access_t *access) { svn_pool_destroy(access->pool); Modified: subversion/branches/addremove/subversion/libsvn_repos/config_file.h URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_repos/config_file.h?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_repos/config_file.h (original) +++ subversion/branches/addremove/subversion/libsvn_repos/config_file.h Sat May 23 14:16:56 2020 @@ -48,7 +48,7 @@ svn_repos__create_config_access(svn_repo apr_pool_t *result_pool); /* Release all resources allocated while using ACCESS. */ -void +void svn_repos__destroy_config_access(config_access_t *access); /* Using ACCESS as a helper object, access the textual configuration at PATH, Modified: subversion/branches/addremove/subversion/libsvn_repos/delta.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_repos/delta.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_repos/delta.c (original) +++ subversion/branches/addremove/subversion/libsvn_repos/delta.c Sat May 23 14:16:56 2020 @@ -215,7 +215,7 @@ svn_repos_dir_delta2(svn_fs_root_t *src_ { void *root_baton = NULL; struct context c; - const char *src_fullpath; + const char *src_fullpath, *canonicalized_path; svn_node_kind_t src_kind, tgt_kind; svn_revnum_t rootrev; svn_fs_node_relation_t relation; @@ -223,14 +223,22 @@ svn_repos_dir_delta2(svn_fs_root_t *src_ /* SRC_PARENT_DIR must be valid. */ if (src_parent_dir) - src_parent_dir = svn_relpath_canonicalize(src_parent_dir, pool); + { + SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL, + src_parent_dir, pool, pool)); + src_parent_dir = canonicalized_path; + } else return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, 0, "Invalid source parent directory '(null)'"); /* TGT_FULLPATH must be valid. */ if (tgt_fullpath) - tgt_fullpath = svn_relpath_canonicalize(tgt_fullpath, pool); + { + SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL, + tgt_fullpath, pool, pool)); + tgt_fullpath = canonicalized_path; + } else return svn_error_create(SVN_ERR_FS_PATH_SYNTAX, 0, _("Invalid target path")); Modified: subversion/branches/addremove/subversion/libsvn_repos/deprecated.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_repos/deprecated.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_repos/deprecated.c (original) +++ subversion/branches/addremove/subversion/libsvn_repos/deprecated.c Sat May 23 14:16:56 2020 @@ -1273,6 +1273,21 @@ svn_repos_fs_begin_txn_for_update(svn_fs /*** From authz.c ***/ svn_error_t * +svn_repos_authz_read3(svn_authz_t **authz_p, + const char *path, + const char *groups_path, + svn_boolean_t must_exist, + svn_repos_t *repos_hint, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + return svn_error_trace(svn_repos_authz_read4(authz_p, path, groups_path, + must_exist, repos_hint, + NULL, NULL, result_pool, + scratch_pool)); +} + +svn_error_t * svn_repos_authz_read2(svn_authz_t **authz_p, const char *path, const char *groups_path, @@ -1300,3 +1315,17 @@ svn_repos_authz_read(svn_authz_t **authz return svn_error_trace(svn_repos_authz_read2(authz_p, file, NULL, must_exist, pool)); } + +svn_error_t * +svn_repos_authz_parse(svn_authz_t **authz_p, + svn_stream_t *stream, + svn_stream_t *groups_stream, + apr_pool_t *pool) +{ + apr_pool_t *scratch_pool = svn_pool_create(pool); + svn_error_t *err = svn_repos_authz_parse2(authz_p, stream, groups_stream, + NULL, NULL, pool, scratch_pool); + svn_pool_destroy(scratch_pool); + + return svn_error_trace(err); +} Modified: subversion/branches/addremove/subversion/libsvn_repos/dump.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_repos/dump.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_repos/dump.c (original) +++ subversion/branches/addremove/subversion/libsvn_repos/dump.c Sat May 23 14:16:56 2020 @@ -44,6 +44,7 @@ #include "private/svn_sorts_private.h" #include "private/svn_utf_private.h" #include "private/svn_cache.h" +#include "private/svn_fspath.h" #define ARE_VALID_COPY_ARGS(p,r) ((p) && SVN_IS_VALID_REVNUM(r)) @@ -512,6 +513,30 @@ svn_repos__dump_headers(svn_stream_t *st } svn_error_t * +svn_repos__dump_magic_header_record(svn_stream_t *dump_stream, + int version, + apr_pool_t *pool) +{ + SVN_ERR(svn_stream_printf(dump_stream, pool, + SVN_REPOS_DUMPFILE_MAGIC_HEADER ": %d\n\n", + version)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_repos__dump_uuid_header_record(svn_stream_t *dump_stream, + const char *uuid, + apr_pool_t *pool) +{ + if (uuid) + { + SVN_ERR(svn_stream_printf(dump_stream, pool, SVN_REPOS_DUMPFILE_UUID + ": %s\n\n", uuid)); + } + return SVN_NO_ERROR; +} + +svn_error_t * svn_repos__dump_revision_record(svn_stream_t *dump_stream, svn_revnum_t revision, apr_hash_t *extra_headers, @@ -713,8 +738,9 @@ struct dir_baton or NULL if this is the top-level directory of the edit. Perform all allocations in POOL. */ -static struct dir_baton * -make_dir_baton(const char *path, +static struct svn_error_t * +make_dir_baton(struct dir_baton **dbp, + const char *path, const char *cmp_path, svn_revnum_t cmp_rev, void *edit_baton, @@ -723,10 +749,10 @@ make_dir_baton(const char *path, { struct edit_baton *eb = edit_baton; struct dir_baton *new_db = apr_pcalloc(pool, sizeof(*new_db)); - const char *full_path; + const char *full_path, *canonicalized_path; /* A path relative to nothing? I don't think so. */ - SVN_ERR_ASSERT_NO_RETURN(!path || pb); + SVN_ERR_ASSERT(!path || pb); /* Construct the full path of this node. */ if (pb) @@ -736,7 +762,11 @@ make_dir_baton(const char *path, /* Remove leading slashes from copyfrom paths. */ if (cmp_path) - cmp_path = svn_relpath_canonicalize(cmp_path, pool); + { + SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL, + cmp_path, pool, pool)); + cmp_path = canonicalized_path; + } new_db->edit_baton = eb; new_db->path = full_path; @@ -747,7 +777,8 @@ make_dir_baton(const char *path, new_db->check_name_collision = FALSE; new_db->pool = pool; - return new_db; + *dbp = new_db; + return SVN_NO_ERROR; } static svn_error_t * @@ -1143,7 +1174,12 @@ dump_node(struct edit_baton *eb, /* Remove leading slashes from copyfrom paths. */ if (cmp_path) - cmp_path = svn_relpath_canonicalize(cmp_path, pool); + { + const char *canonicalized_path; + SVN_ERR(svn_relpath_canonicalize_safe(&canonicalized_path, NULL, + cmp_path, pool, pool)); + cmp_path = canonicalized_path; + } /* Validate the comparison path/rev. */ if (ARE_VALID_COPY_ARGS(cmp_path, cmp_rev)) @@ -1513,9 +1549,9 @@ open_root(void *edit_baton, apr_pool_t *pool, void **root_baton) { - *root_baton = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM, - edit_baton, NULL, pool); - return SVN_NO_ERROR; + return svn_error_trace(make_dir_baton((struct dir_baton **)root_baton, + NULL, NULL, SVN_INVALID_REVNUM, + edit_baton, NULL, pool)); } @@ -1547,8 +1583,10 @@ add_directory(const char *path, struct edit_baton *eb = pb->edit_baton; void *was_deleted; svn_boolean_t is_copy = FALSE; - struct dir_baton *new_db - = make_dir_baton(path, copyfrom_path, copyfrom_rev, eb, pb, pool); + struct dir_baton *new_db; + + SVN_ERR(make_dir_baton(&new_db, path, copyfrom_path, copyfrom_rev, eb, + pb, pool)); /* This might be a replacement -- is the path already deleted? */ was_deleted = svn_hash_gets(pb->deleted_entries, path); @@ -1605,7 +1643,7 @@ open_directory(const char *path, cmp_rev = pb->cmp_rev; } - new_db = make_dir_baton(path, cmp_path, cmp_rev, eb, pb, pool); + SVN_ERR(make_dir_baton(&new_db, path, cmp_path, cmp_rev, eb, pb, pool)); *child_baton = new_db; return SVN_NO_ERROR; } @@ -1936,25 +1974,11 @@ write_revision_record(svn_stream_t *stre apr_pool_t *pool) { apr_hash_t *props; - apr_time_t timetemp; - svn_string_t *datevalue; if (include_revprops) { SVN_ERR(svn_repos_fs_revision_proplist(&props, repos, rev, authz_func, authz_baton, pool)); - - /* Run revision date properties through the time conversion to - canonicalize them. */ - /* ### Remove this when it is no longer needed for sure. */ - datevalue = svn_hash_gets(props, SVN_PROP_REVISION_DATE); - if (datevalue) - { - SVN_ERR(svn_time_from_cstring(&timetemp, datevalue->data, pool)); - datevalue = svn_string_create(svn_time_to_cstring(timetemp, pool), - pool); - svn_hash_sets(props, SVN_PROP_REVISION_DATE, datevalue); - } } else { @@ -1986,6 +2010,11 @@ dump_filter_authz_func(svn_boolean_t *al { dump_filter_baton_t *b = baton; + /* For some nodes (e.g. files under copied directory) PATH may be + * non-canonical (missing leading '/'). Canonicalize PATH before + * passing it to FILTER_FUNC. */ + path = svn_fspath__canonicalize(path, pool); + return svn_error_trace(b->filter_func(allowed, root, path, b->filter_baton, pool)); } @@ -2076,11 +2105,8 @@ svn_repos_dump_fs4(svn_repos_t *repos, /* Write out "general" metadata for the dumpfile. In this case, a magic header followed by a dumpfile format version. */ - SVN_ERR(svn_stream_printf(stream, pool, - SVN_REPOS_DUMPFILE_MAGIC_HEADER ": %d\n\n", - version)); - SVN_ERR(svn_stream_printf(stream, pool, SVN_REPOS_DUMPFILE_UUID - ": %s\n\n", uuid)); + SVN_ERR(svn_repos__dump_magic_header_record(stream, version, pool)); + SVN_ERR(svn_repos__dump_uuid_header_record(stream, uuid, pool)); /* Create a notify object that we can reuse in the loop. */ if (notify_func) Modified: subversion/branches/addremove/subversion/libsvn_repos/fs-wrap.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_repos/fs-wrap.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_repos/fs-wrap.c (original) +++ subversion/branches/addremove/subversion/libsvn_repos/fs-wrap.c Sat May 23 14:16:56 2020 @@ -282,7 +282,7 @@ svn_repos__normalize_prop(const svn_stri } else { - *result_p = svn_string_dup(value, result_pool); + *result_p = value; if (normalized_p) *normalized_p = FALSE; } @@ -1106,7 +1106,7 @@ svn_repos_fs_get_inherited_props(apr_arr apr_pstrdup(result_pool, parent_path + 1); i_props->prop_hash = parent_properties; /* Build the output array in depth-first order. */ - svn_sort__array_insert(inherited_props, &i_props, 0); + SVN_ERR(svn_sort__array_insert2(inherited_props, &i_props, 0)); } } } Modified: subversion/branches/addremove/subversion/libsvn_repos/hooks.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_repos/hooks.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_repos/hooks.c (original) +++ subversion/branches/addremove/subversion/libsvn_repos/hooks.c Sat May 23 14:16:56 2020 @@ -668,7 +668,7 @@ svn_repos__hooks_pre_revprop_change(svn_ { /* If the pre- hook doesn't exist at all, then default to MASSIVE PARANOIA. Changing revision properties is a lossy - operation; so unless the repository admininstrator has + operation; so unless the repository administrator has *deliberately* created the pre-hook, disallow all changes. */ return svn_error_create Modified: subversion/branches/addremove/subversion/libsvn_repos/list.c URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/libsvn_repos/list.c?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/libsvn_repos/list.c (original) +++ subversion/branches/addremove/subversion/libsvn_repos/list.c Sat May 23 14:16:56 2020 @@ -50,6 +50,8 @@ fill_dirent(svn_dirent_t *dirent, if (dirent->kind == svn_node_file) SVN_ERR(svn_fs_file_length(&(dirent->size), root, path, scratch_pool)); + else + dirent->size = SVN_INVALID_FILESIZE; SVN_ERR(svn_fs_node_has_props(&dirent->has_props, root, path, scratch_pool)); @@ -322,7 +324,7 @@ svn_repos_list(svn_fs_root_t *root, svn_membuf__create(&scratch_buffer, 256, scratch_pool); /* Actually report PATH, if it passes the filters. */ - if (matches_any(svn_dirent_dirname(path, scratch_pool), patterns, + if (matches_any(svn_dirent_basename(path, scratch_pool), patterns, &scratch_buffer)) SVN_ERR(report_dirent(root, path, kind, path_info_only, receiver, receiver_baton, scratch_pool));
