static svn_error_t *ra_svn_handle_add_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const apr_array_header_t *params, ra_svn_driver_state_t *ds) { const char *path, *token, *file_token, *copy_path; svn_revnum_t copy_rev; ra_svn_token_entry_t *entry, *file_entry; SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "ccc(?cr)", &path, &token, &file_token, ©_path, ©_rev)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); ds->file_refs++; path = svn_relpath_canonicalize(path, pool); /* Some operations pass COPY_PATH as a full URL (commits, etc.). Others (replay, e.g.) deliver an fspath. That's ... annoying. */ if (copy_path) { if (svn_path_is_url(copy_path)) copy_path = svn_uri_canonicalize(copy_path, pool); else copy_path = svn_fspath__canonicalize(copy_path, pool); } file_entry = store_token(ds, NULL, file_token, TRUE, ds->file_pool); SVN_CMD_ERR(ds->editor->add_file(path, entry->baton, copy_path, copy_rev, ds->file_pool, &file_entry->baton)); return SVN_NO_ERROR; }
svn_error_t * svn_ra_neon__copy_href(svn_stringbuf_t *dst, const char *src, apr_pool_t *pool) { /* parse the PATH element out of the URL and store it. ### do we want to verify the rest matches the current session? Note: mod_dav does not (currently) use an absolute URL, but simply a server-relative path (i.e. this uri_parse is effectively a no-op). */ apr_uri_t uri; apr_status_t apr_status; /* SRC can have trailing '/' */ if (svn_path_is_url(src)) src = svn_uri_canonicalize(src, pool); else src = svn_urlpath__canonicalize(src, pool); apr_status = apr_uri_parse(pool, src, &uri); if (apr_status != APR_SUCCESS) return svn_error_wrap_apr(apr_status, _("Unable to parse URL '%s'"), src); svn_stringbuf_setempty(dst); svn_stringbuf_appendcstr(dst, uri.path); return SVN_NO_ERROR; }
int main(int argc, const char *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; svn_error_t *err; const char *url; svn_revnum_t revision; const char *propname; svn_string_t *propval; svn_string_t *old_propval; char *digits_end = NULL; svn_boolean_t want_error; const char *config_dir; if (argc != 7) { fprintf(stderr, USAGE_MSG, argv[0], KEY_OLD_PROPVAL, KEY_NEW_PROPVAL); exit(1); } if (apr_initialize() != APR_SUCCESS) { fprintf(stderr, "apr_initialize() failed.\n"); exit(1); } /* set up the global pool */ pool = svn_pool_create(NULL); /* Parse argv. */ url = svn_uri_canonicalize(argv[1], pool); revision = strtol(argv[2], &digits_end, 10); propname = argv[3]; SVN_INT_ERR(extract_values_from_skel(&old_propval, &propval, argv[4], pool)); want_error = !strcmp(argv[5], "1"); config_dir = svn_dirent_canonicalize(argv[6], pool); if ((! SVN_IS_VALID_REVNUM(revision)) || (! digits_end) || *digits_end) SVN_INT_ERR(svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("Invalid revision number supplied"))); /* Do something. */ err = change_rev_prop(url, revision, propname, propval, old_propval, want_error, config_dir, pool); if (err) { svn_handle_error2(err, stderr, FALSE, "atomic-ra-revprop-change: "); svn_error_clear(err); exit_code = EXIT_FAILURE; } /* Clean up, and get outta here */ svn_pool_destroy(pool); apr_terminate(); return exit_code; }
svn_error_t *JNIUtil::preprocessPath(const char *&path, apr_pool_t *pool) { /* URLs and wc-paths get treated differently. */ if (svn_path_is_url(path)) { /* No need to canonicalize a URL's case or path separators. */ /* Convert to URI. */ path = svn_path_uri_from_iri(path, pool); /* Auto-escape some ASCII characters. */ path = svn_path_uri_autoescape(path, pool); /* The above doesn't guarantee a valid URI. */ if (! svn_path_is_uri_safe(path)) return svn_error_createf(SVN_ERR_BAD_URL, NULL, _("URL '%s' is not properly URI-encoded"), path); /* Verify that no backpaths are present in the URL. */ if (svn_path_is_backpath_present(path)) return svn_error_createf(SVN_ERR_BAD_URL, NULL, _("URL '%s' contains a '..' element"), path); /* strip any trailing '/' */ path = svn_uri_canonicalize(path, pool); } else /* not a url, so treat as a path */ { /* Normalize path to subversion internal style */ /* ### In Subversion < 1.6 this method on Windows actually tried to lookup the path on disk to fix possible invalid casings in the passed path. (An extremely expensive operation; especially on network drives). This 'feature'is now removed as it penalizes every correct path passed, and also breaks behavior of e.g. 'svn status .' returns '!' file, because there is only a "File" on disk. But when you then call 'svn status file', you get '? File'. As JavaHL is designed to be platform independent I assume users don't want this broken behavior on non round-trippable paths, nor the performance penalty. */ path = svn_dirent_internal_style(path, pool); /* For kicks and giggles, let's absolutize it. */ SVN_ERR(svn_dirent_get_absolute(&path, path, pool)); } return NULL; }
/* Parse the conflict info fields from SKEL into *VERSION_INFO. */ static svn_error_t * read_node_version_info(const svn_wc_conflict_version_t **version_info, const svn_skel_t *skel, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { int n; const char *repos_root; const char *repos_relpath; svn_revnum_t peg_rev; svn_node_kind_t kind; if (!is_valid_version_info_skel(skel)) return svn_error_create(SVN_ERR_WC_CORRUPT, NULL, _("Invalid version info in tree conflict " "description")); repos_root = apr_pstrmemdup(scratch_pool, skel->children->next->data, skel->children->next->len); if (*repos_root == '\0') { *version_info = NULL; return SVN_NO_ERROR; } /* Apply the Subversion 1.7+ url canonicalization rules to a pre 1.7 url */ repos_root = svn_uri_canonicalize(repos_root, result_pool); peg_rev = SVN_STR_TO_REV(apr_pstrmemdup(scratch_pool, skel->children->next->next->data, skel->children->next->next->len)); repos_relpath = apr_pstrmemdup(result_pool, skel->children->next->next->next->data, skel->children->next->next->next->len); SVN_ERR(read_enum_field(&n, node_kind_map, skel->children->next->next->next->next)); kind = (svn_node_kind_t)n; *version_info = svn_wc_conflict_version_create2(repos_root, NULL, repos_relpath, peg_rev, kind, result_pool); return SVN_NO_ERROR; }
/* This is read_path() for urls. This function does not do the is_canonical test for entries from working copies older than version 10, as since that version the canonicalization of urls has been changed. See issue #2475. If the test is done and fails, read_url returs an error. */ static svn_error_t * read_url(const char **result, char **buf, const char *end, int wc_format, apr_pool_t *pool) { SVN_ERR(read_str(result, buf, end, pool)); /* Always canonicalize the url, as we have stricter canonicalization rules in 1.7+ then before */ if (*result && **result) *result = svn_uri_canonicalize(*result, pool); return SVN_NO_ERROR; }
static PyObject *py_dir_editor_add_directory(PyObject *self, PyObject *args) { PyObject *py_path, *py_copyfrom_path = Py_None; const char *path; const char *copyfrom_path = NULL; svn_revnum_t copyfrom_rev = -1; void *child_baton; EditorObject *editor = (EditorObject *)self; apr_pool_t *subpool; if (!PyArg_ParseTuple(args, "O|Ol", &py_path, &py_copyfrom_path, ©from_rev)) return NULL; if (editor->done) { PyErr_SetString(PyExc_RuntimeError, "directory editor already closed"); return NULL; } if (editor->active_child) { PyErr_SetString(PyExc_RuntimeError, "child is already open"); return NULL; } path = py_object_to_svn_relpath(py_path, editor->pool); if (path == NULL) { return NULL; } if (py_copyfrom_path != Py_None) { copyfrom_path = py_object_to_svn_uri(py_copyfrom_path, editor->pool); if (copyfrom_path == NULL) { return NULL; } } RUN_SVN(editor->editor->add_directory( path, editor->baton, copyfrom_path == NULL?NULL:svn_uri_canonicalize(copyfrom_path, editor->pool), copyfrom_rev, editor->pool, &child_baton)); subpool = Pool(editor->pool); if (subpool == NULL) return NULL; return new_editor_object(editor, editor->editor, child_baton, subpool, &DirectoryEditor_Type, NULL, NULL, NULL); }
/* Canonicalize ACCESS_FILE into *CANONICALIZED_ACCESS_FILE based on the type of argument. Error out on unsupported path types. If WITHIN_TXN is set, ACCESS_FILE has to be a fspath in the repo. Use POOL for allocations. */ static svn_error_t * canonicalize_access_file(const char **canonicalized_access_file, const char *access_file, svn_boolean_t within_txn, apr_pool_t *pool) { if (svn_path_is_repos_relative_url(access_file)) { /* Can't accept repos relative urls since we don't have the path to * the repository. */ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, ("'%s' is a repository relative URL when it " "should be a local path or file:// URL"), access_file); } else if (svn_path_is_url(access_file)) { if (within_txn) { /* Don't allow urls with transaction argument. */ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, ("'%s' is a URL when it should be a " "repository-relative path"), access_file); } *canonicalized_access_file = svn_uri_canonicalize(access_file, pool); } else if (within_txn) { /* Transaction flag means this has to be a fspath to the access file * in the repo. */ *canonicalized_access_file = svn_fspath__canonicalize(access_file, pool); } else { /* If it isn't a URL and there's no transaction flag then it's a * dirent to the access file on local disk. */ *canonicalized_access_file = svn_dirent_internal_style(access_file, pool); } return SVN_NO_ERROR; }
const char* CTSVNPath::GetSVNApiPath(apr_pool_t *pool) const { // This funny-looking 'if' is to avoid a subtle problem with empty paths, whereby // each call to GetSVNApiPath returns a different pointer value. // If you made multiple calls to GetSVNApiPath on the same string, only the last // one would give you a valid pointer to an empty string, because each // call would invalidate the previous call's return. if(IsEmpty()) { return ""; } if(m_sFwdslashPath.IsEmpty()) { SetFwdslashPath(m_sBackslashPath); } if(m_sUTF8FwdslashPath.IsEmpty()) { SetUTF8FwdslashPath(m_sFwdslashPath); } if (svn_path_is_url(m_sUTF8FwdslashPath)) { m_sUTF8FwdslashPathEscaped = CPathUtils::PathEscape(m_sUTF8FwdslashPath); m_sUTF8FwdslashPathEscaped.Replace("file:////", "file://"); m_sUTF8FwdslashPathEscaped = svn_uri_canonicalize(m_sUTF8FwdslashPathEscaped, pool); return m_sUTF8FwdslashPathEscaped; } else { m_sUTF8FwdslashPath = svn_dirent_canonicalize(m_sUTF8FwdslashPath, pool); // for UNC paths that point to the server directly (e.g., \\MYSERVER), not // to a share on the server, the svn_dirent_canonicalize() API returns // a wrong path that asserts when subversion checks that the path is absolute // (it returns /MYSERVER instead of //MYSERVER). // We can't just add the second slash, since that would assert when svn checks // for canonicalized paths. // Since the network server itself isn't interesting anyway but only shares, // we just return an empty path here. if (!svn_dirent_is_absolute(m_sUTF8FwdslashPath)) m_sUTF8FwdslashPath.Empty(); } return m_sUTF8FwdslashPath; }
const char * svn_ra_neon__uri_unparse(const ne_uri *uri, apr_pool_t *pool) { char *unparsed_uri; const char *result; /* Unparse uri. */ unparsed_uri = ne_uri_unparse(uri); /* Copy string to result pool, and make sure it conforms to Subversion rules */ result = svn_uri_canonicalize(unparsed_uri, pool); /* Free neon's allocated copy. */ ne_free(unparsed_uri); /* Return string allocated in result pool. */ return result; }
svn_error_t * svn_opt__arg_canonicalize_url(const char **url_out, const char *url_in, apr_pool_t *pool) { const char *target; /* Convert to URI. */ target = svn_path_uri_from_iri(url_in, pool); /* Auto-escape some ASCII characters. */ target = svn_path_uri_autoescape(target, pool); #if '/' != SVN_PATH_LOCAL_SEPARATOR /* Allow using file:///C:\users\me/repos on Windows, like we did in 1.6 */ if (strchr(target, SVN_PATH_LOCAL_SEPARATOR)) { char *p = apr_pstrdup(pool, target); target = p; /* Convert all local-style separators to the canonical ones. */ for (; *p != '\0'; ++p) if (*p == SVN_PATH_LOCAL_SEPARATOR) *p = '/'; } #endif /* Verify that no backpaths are present in the URL. */ if (svn_path_is_backpath_present(target)) return svn_error_createf(SVN_ERR_BAD_URL, 0, _("URL '%s' contains a '..' element"), target); /* Strip any trailing '/' and collapse other redundant elements. */ target = svn_uri_canonicalize(target, pool); *url_out = target; return SVN_NO_ERROR; }
int main(int argc, const char **argv) { svn_error_t *err = SVN_NO_ERROR; const svn_opt_subcommand_desc2_t *subcommand = NULL; opt_baton_t *opt_baton; svn_revnum_t latest_revision = SVN_INVALID_REVNUM; apr_pool_t *pool = NULL; const char *config_dir = NULL; const char *username = NULL; const char *password = NULL; svn_boolean_t no_auth_cache = FALSE; svn_boolean_t trust_server_cert = FALSE; svn_boolean_t non_interactive = FALSE; apr_array_header_t *config_options = NULL; apr_getopt_t *os; const char *first_arg; apr_array_header_t *received_opts; apr_allocator_t *allocator; int i; if (svn_cmdline_init ("svnrdump", stderr) != EXIT_SUCCESS) return EXIT_FAILURE; /* Create our top-level pool. Use a separate mutexless allocator, * given this application is single threaded. */ if (apr_allocator_create(&allocator)) return EXIT_FAILURE; apr_allocator_max_free_set(allocator, SVN_ALLOCATOR_RECOMMENDED_MAX_FREE); pool = svn_pool_create_ex(NULL, allocator); apr_allocator_owner_set(allocator, pool); opt_baton = apr_pcalloc(pool, sizeof(*opt_baton)); opt_baton->start_revision.kind = svn_opt_revision_unspecified; opt_baton->end_revision.kind = svn_opt_revision_unspecified; opt_baton->url = NULL; SVNRDUMP_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool)); os->interleave = TRUE; /* Options and arguments can be interleaved */ /* Set up our cancellation support. */ apr_signal(SIGINT, signal_handler); #ifdef SIGBREAK /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */ apr_signal(SIGBREAK, signal_handler); #endif #ifdef SIGHUP apr_signal(SIGHUP, signal_handler); #endif #ifdef SIGTERM apr_signal(SIGTERM, signal_handler); #endif #ifdef SIGPIPE /* Disable SIGPIPE generation for the platforms that have it. */ apr_signal(SIGPIPE, SIG_IGN); #endif #ifdef SIGXFSZ /* Disable SIGXFSZ generation for the platforms that have it, otherwise * working with large files when compiled against an APR that doesn't have * large file support will crash the program, which is uncool. */ apr_signal(SIGXFSZ, SIG_IGN); #endif received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); while (1) { int opt; const char *opt_arg; apr_status_t status = apr_getopt_long(os, svnrdump__options, &opt, &opt_arg); if (APR_STATUS_IS_EOF(status)) break; if (status != APR_SUCCESS) { SVNRDUMP_ERR(usage(argv[0], pool)); exit(EXIT_FAILURE); } /* Stash the option code in an array before parsing it. */ APR_ARRAY_PUSH(received_opts, int) = opt; switch(opt) { case 'r': { /* Make sure we've not seen -r already. */ if (opt_baton->start_revision.kind != svn_opt_revision_unspecified) { err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("Multiple revision arguments " "encountered; try '-r N:M' instead " "of '-r N -r M'")); return svn_cmdline_handle_exit_error(err, pool, "svnrdump: "); } /* Parse the -r argument. */ if (svn_opt_parse_revision(&(opt_baton->start_revision), &(opt_baton->end_revision), opt_arg, pool) != 0) { const char *utf8_opt_arg; err = svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool); if (! err) err = svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("Syntax error in revision " "argument '%s'"), utf8_opt_arg); return svn_cmdline_handle_exit_error(err, pool, "svnrdump: "); } } break; case 'q': opt_baton->quiet = TRUE; break; case opt_config_dir: config_dir = opt_arg; break; case opt_version: opt_baton->version = TRUE; break; case 'h': opt_baton->help = TRUE; break; case opt_auth_username: SVNRDUMP_ERR(svn_utf_cstring_to_utf8(&username, opt_arg, pool)); break; case opt_auth_password: SVNRDUMP_ERR(svn_utf_cstring_to_utf8(&password, opt_arg, pool)); break; case opt_auth_nocache: no_auth_cache = TRUE; break; case opt_non_interactive: non_interactive = TRUE; break; case opt_incremental: opt_baton->incremental = TRUE; break; case opt_trust_server_cert: trust_server_cert = TRUE; break; case opt_config_option: if (!config_options) config_options = apr_array_make(pool, 1, sizeof(svn_cmdline__config_argument_t*)); SVNRDUMP_ERR(svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool)); SVNRDUMP_ERR(svn_cmdline__parse_config_option(config_options, opt_arg, pool)); } } if (opt_baton->help) { subcommand = svn_opt_get_canonical_subcommand2(svnrdump__cmd_table, "help"); } if (subcommand == NULL) { if (os->ind >= os->argc) { if (opt_baton->version) { /* Use the "help" subcommand to handle the "--version" option. */ static const svn_opt_subcommand_desc2_t pseudo_cmd = { "--version", help_cmd, {0}, "", { opt_version, /* must accept its own option */ 'q', /* --quiet */ } }; subcommand = &pseudo_cmd; } else { SVNRDUMP_ERR(help_cmd(NULL, NULL, pool)); svn_pool_destroy(pool); exit(EXIT_FAILURE); } } else { first_arg = os->argv[os->ind++]; subcommand = svn_opt_get_canonical_subcommand2(svnrdump__cmd_table, first_arg); if (subcommand == NULL) { const char *first_arg_utf8; err = svn_utf_cstring_to_utf8(&first_arg_utf8, first_arg, pool); if (err) return svn_cmdline_handle_exit_error(err, pool, "svnrdump: "); svn_error_clear(svn_cmdline_fprintf(stderr, pool, _("Unknown command: '%s'\n"), first_arg_utf8)); SVNRDUMP_ERR(help_cmd(NULL, NULL, pool)); svn_pool_destroy(pool); exit(EXIT_FAILURE); } } } /* Check that the subcommand wasn't passed any inappropriate options. */ for (i = 0; i < received_opts->nelts; i++) { int opt_id = APR_ARRAY_IDX(received_opts, i, int); /* All commands implicitly accept --help, so just skip over this when we see it. Note that we don't want to include this option in their "accepted options" list because it would be awfully redundant to display it in every commands' help text. */ if (opt_id == 'h' || opt_id == '?') continue; if (! svn_opt_subcommand_takes_option3(subcommand, opt_id, NULL)) { const char *optstr; const apr_getopt_option_t *badopt = svn_opt_get_option_from_code2(opt_id, svnrdump__options, subcommand, pool); svn_opt_format_option(&optstr, badopt, FALSE, pool); if (subcommand->name[0] == '-') SVN_INT_ERR(help_cmd(NULL, NULL, pool)); else svn_error_clear(svn_cmdline_fprintf( stderr, pool, _("Subcommand '%s' doesn't accept option '%s'\n" "Type 'svnrdump help %s' for usage.\n"), subcommand->name, optstr, subcommand->name)); svn_pool_destroy(pool); return EXIT_FAILURE; } } if (subcommand && strcmp(subcommand->name, "--version") == 0) { SVNRDUMP_ERR(version(argv[0], opt_baton->quiet, pool)); svn_pool_destroy(pool); exit(EXIT_SUCCESS); } if (subcommand && strcmp(subcommand->name, "help") == 0) { SVNRDUMP_ERR(help_cmd(os, opt_baton, pool)); svn_pool_destroy(pool); exit(EXIT_SUCCESS); } /* --trust-server-cert can only be used with --non-interactive */ if (trust_server_cert && !non_interactive) { err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("--trust-server-cert requires " "--non-interactive")); return svn_cmdline_handle_exit_error(err, pool, "svnrdump: "); } /* Expect one more non-option argument: the repository URL. */ if (os->ind != os->argc - 1) { SVNRDUMP_ERR(usage(argv[0], pool)); svn_pool_destroy(pool); exit(EXIT_FAILURE); } else { const char *repos_url; SVNRDUMP_ERR(svn_utf_cstring_to_utf8(&repos_url, os->argv[os->ind], pool)); if (! svn_path_is_url(repos_url)) { err = svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, 0, "Target '%s' is not a URL", repos_url); SVNRDUMP_ERR(err); svn_pool_destroy(pool); exit(EXIT_FAILURE); } opt_baton->url = svn_uri_canonicalize(repos_url, pool); } SVNRDUMP_ERR(init_client_context(&(opt_baton->ctx), non_interactive, username, password, config_dir, no_auth_cache, trust_server_cert, config_options, pool)); SVNRDUMP_ERR(svn_client_open_ra_session(&(opt_baton->session), opt_baton->url, opt_baton->ctx, pool)); /* Have sane opt_baton->start_revision and end_revision defaults if unspecified. */ SVNRDUMP_ERR(svn_ra_get_latest_revnum(opt_baton->session, &latest_revision, pool)); /* Make sure any provided revisions make sense. */ SVNRDUMP_ERR(validate_and_resolve_revisions(opt_baton, latest_revision, pool)); /* Dispatch the subcommand */ SVNRDUMP_ERR((*subcommand->cmd_func)(os, opt_baton, pool)); svn_pool_destroy(pool); return EXIT_SUCCESS; }
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) { apr_pool_t *sesspool = svn_pool_create(pool); svn_ra_session_t *session; const struct ra_lib_defn *defn; const svn_ra__vtable_t *vtable = NULL; svn_config_t *servers = NULL; const char *server_group; apr_uri_t repos_URI; apr_status_t apr_err; #ifdef CHOOSABLE_DAV_MODULE const char *http_library = DEFAULT_HTTP_LIBRARY; #endif /* Auth caching parameters. */ svn_boolean_t store_passwords = SVN_CONFIG_DEFAULT_OPTION_STORE_PASSWORDS; svn_boolean_t store_auth_creds = SVN_CONFIG_DEFAULT_OPTION_STORE_AUTH_CREDS; const char *store_plaintext_passwords = SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS; svn_boolean_t store_pp = SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP; const char *store_pp_plaintext = SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT; const char *corrected_url; /* Initialize the return variable. */ *session_p = NULL; apr_err = apr_uri_parse(sesspool, repos_URL, &repos_URI); /* ### Should apr_uri_parse leave hostname NULL? It doesn't * for "file:///" URLs, only for bogus URLs like "bogus". * If this is the right behavior for apr_uri_parse, maybe we * should have a svn_uri_parse wrapper. */ if (apr_err != APR_SUCCESS || repos_URI.hostname == NULL) return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL, _("Illegal repository URL '%s'"), repos_URL); if (callbacks->auth_baton) { /* The 'store-passwords' and 'store-auth-creds' parameters used to * live in SVN_CONFIG_CATEGORY_CONFIG. For backward compatibility, * if values for these parameters have already been set by our * callers, we use those values as defaults. * * Note that we can only catch the case where users explicitly set * "store-passwords = no" or 'store-auth-creds = no". * * However, since the default value for both these options is * currently (and has always been) "yes", users won't know * the difference if they set "store-passwords = yes" or * "store-auth-creds = yes" -- they'll get the expected behaviour. */ if (svn_auth_get_parameter(callbacks->auth_baton, SVN_AUTH_PARAM_DONT_STORE_PASSWORDS) != NULL) store_passwords = FALSE; if (svn_auth_get_parameter(callbacks->auth_baton, SVN_AUTH_PARAM_NO_AUTH_CACHE) != NULL) store_auth_creds = FALSE; } if (config) { /* Grab the 'servers' config. */ servers = apr_hash_get(config, SVN_CONFIG_CATEGORY_SERVERS, APR_HASH_KEY_STRING); if (servers) { /* First, look in the global section. */ SVN_ERR(svn_config_get_bool (servers, &store_passwords, SVN_CONFIG_SECTION_GLOBAL, SVN_CONFIG_OPTION_STORE_PASSWORDS, store_passwords)); SVN_ERR(svn_config_get_yes_no_ask (servers, &store_plaintext_passwords, SVN_CONFIG_SECTION_GLOBAL, SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSWORDS, SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS)); SVN_ERR(svn_config_get_bool (servers, &store_pp, SVN_CONFIG_SECTION_GLOBAL, SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP, store_pp)); SVN_ERR(svn_config_get_yes_no_ask (servers, &store_pp_plaintext, SVN_CONFIG_SECTION_GLOBAL, SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT, SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT)); SVN_ERR(svn_config_get_bool (servers, &store_auth_creds, SVN_CONFIG_SECTION_GLOBAL, SVN_CONFIG_OPTION_STORE_AUTH_CREDS, store_auth_creds)); /* Find out where we're about to connect to, and * try to pick a server group based on the destination. */ server_group = svn_config_find_group(servers, repos_URI.hostname, SVN_CONFIG_SECTION_GROUPS, sesspool); if (server_group) { /* Override global auth caching parameters with the ones * for the server group, if any. */ SVN_ERR(svn_config_get_bool(servers, &store_auth_creds, server_group, SVN_CONFIG_OPTION_STORE_AUTH_CREDS, store_auth_creds)); SVN_ERR(svn_config_get_bool(servers, &store_passwords, server_group, SVN_CONFIG_OPTION_STORE_PASSWORDS, store_passwords)); SVN_ERR(svn_config_get_yes_no_ask (servers, &store_plaintext_passwords, server_group, SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSWORDS, store_plaintext_passwords)); SVN_ERR(svn_config_get_bool (servers, &store_pp, server_group, SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP, store_pp)); SVN_ERR(svn_config_get_yes_no_ask (servers, &store_pp_plaintext, server_group, SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT, store_pp_plaintext)); } #ifdef CHOOSABLE_DAV_MODULE /* Now, which DAV-based RA method do we want to use today? */ http_library = svn_config_get_server_setting(servers, server_group, /* NULL is OK */ SVN_CONFIG_OPTION_HTTP_LIBRARY, DEFAULT_HTTP_LIBRARY); if (strcmp(http_library, "neon") != 0 && strcmp(http_library, "serf") != 0) return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL, _("Invalid config: unknown HTTP library " "'%s'"), http_library); #endif } } if (callbacks->auth_baton) { /* Save auth caching parameters in the auth parameter hash. */ if (! store_passwords) svn_auth_set_parameter(callbacks->auth_baton, SVN_AUTH_PARAM_DONT_STORE_PASSWORDS, ""); svn_auth_set_parameter(callbacks->auth_baton, SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS, store_plaintext_passwords); if (! store_pp) svn_auth_set_parameter(callbacks->auth_baton, SVN_AUTH_PARAM_DONT_STORE_SSL_CLIENT_CERT_PP, ""); svn_auth_set_parameter(callbacks->auth_baton, SVN_AUTH_PARAM_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT, store_pp_plaintext); if (! store_auth_creds) svn_auth_set_parameter(callbacks->auth_baton, SVN_AUTH_PARAM_NO_AUTH_CACHE, ""); } /* Find the library. */ for (defn = ra_libraries; defn->ra_name != NULL; ++defn) { const char *scheme; if ((scheme = has_scheme_of(defn->schemes, repos_URL))) { svn_ra__init_func_t initfunc = defn->initfunc; #ifdef CHOOSABLE_DAV_MODULE if (defn->schemes == dav_schemes && strcmp(defn->ra_name, http_library) != 0) continue; #endif if (! initfunc) SVN_ERR(load_ra_module(&initfunc, NULL, defn->ra_name, sesspool)); if (! initfunc) /* Library not found. */ continue; SVN_ERR(initfunc(svn_ra_version(), &vtable, sesspool)); SVN_ERR(check_ra_version(vtable->get_version(), scheme)); if (! has_scheme_of(vtable->get_schemes(sesspool), repos_URL)) /* Library doesn't support the scheme at runtime. */ continue; break; } } if (vtable == NULL) return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL, _("Unrecognized URL scheme for '%s'"), repos_URL); /* Create the session object. */ session = apr_pcalloc(sesspool, sizeof(*session)); session->vtable = vtable; session->pool = sesspool; /* Ask the library to open the session. */ SVN_ERR_W(vtable->open_session(session, &corrected_url, repos_URL, callbacks, callback_baton, config, sesspool), apr_psprintf(pool, "Unable to connect to a repository at URL '%s'", repos_URL)); /* If the session open stuff detected a server-provided URL correction (a 301 or 302 redirect response during the initial OPTIONS request), then kill the session so the caller can decide what to do. */ if (corrected_url_p && corrected_url) { if (! svn_path_is_url(corrected_url)) { /* RFC1945 and RFC2616 state that the Location header's value (from whence this CORRECTED_URL ultimately comes), if present, must be an absolute URI. But some Apache versions (those older than 2.2.11, it seems) transmit only the path portion of the URI. See issue #3775 for details. */ apr_uri_t corrected_URI = repos_URI; corrected_URI.path = (char *)corrected_url; corrected_url = apr_uri_unparse(pool, &corrected_URI, 0); } *corrected_url_p = svn_uri_canonicalize(corrected_url, pool); svn_pool_destroy(sesspool); return SVN_NO_ERROR; } /* Check the UUID. */ if (uuid) { const char *repository_uuid; SVN_ERR(vtable->get_uuid(session, &repository_uuid, pool)); if (strcmp(uuid, repository_uuid) != 0) { /* Duplicate the uuid as it is allocated in sesspool */ repository_uuid = apr_pstrdup(pool, repository_uuid); svn_pool_destroy(sesspool); return svn_error_createf(SVN_ERR_RA_UUID_MISMATCH, NULL, _("Repository UUID '%s' doesn't match " "expected UUID '%s'"), repository_uuid, uuid); } } *session_p = session; return SVN_NO_ERROR; }
CStringA CPathUtils::GetAbsoluteURL ( const CStringA& URL , const CStringA& repositoryRootURL , const CStringA& parentPathURL) { CStringA errorResult; SVNPool pool; /* If the URL is already absolute, there is nothing to do. */ const char *canonicalized_url = svn_uri_canonicalize (URL, pool); if (svn_path_is_url (canonicalized_url)) return canonicalized_url; /* Parse the parent directory URL into its parts. */ apr_uri_t parent_dir_parsed_uri; if (apr_uri_parse (pool, parentPathURL, &parent_dir_parsed_uri)) return errorResult; /* If the parent directory URL is at the server root, then the URL may have no / after the hostname so apr_uri_parse() will leave the URL's path as NULL. */ if (! parent_dir_parsed_uri.path) parent_dir_parsed_uri.path = apr_pstrmemdup (pool, "/", 1); /* Handle URLs relative to the current directory or to the repository root. The backpaths may only remove path elements, not the hostname. This allows an external to refer to another repository in the same server relative to the location of this repository, say using SVNParentPath. */ if ((0 == strncmp("../", URL, 3)) || (0 == strncmp("^/", URL, 2))) { apr_array_header_t *base_components = NULL; apr_array_header_t *relative_components = NULL; /* Decompose either the parent directory's URL path or the repository root's URL path into components. */ if (0 == strncmp ("../", URL, 3)) { base_components = svn_path_decompose (parent_dir_parsed_uri.path, pool); relative_components = svn_path_decompose (canonicalized_url, pool); } else { apr_uri_t repos_root_parsed_uri; if (apr_uri_parse(pool, repositoryRootURL, &repos_root_parsed_uri)) return errorResult; /* If the repository root URL is at the server root, then the URL may have no / after the hostname so apr_uri_parse() will leave the URL's path as NULL. */ if (! repos_root_parsed_uri.path) repos_root_parsed_uri.path = apr_pstrmemdup (pool, "/", 1); base_components = svn_path_decompose (repos_root_parsed_uri.path, pool); relative_components = svn_path_decompose (canonicalized_url + 2, pool); } for (int i = 0; i < relative_components->nelts; ++i) { const char *component = APR_ARRAY_IDX(relative_components, i, const char *); if (0 == strcmp("..", component)) { /* Constructing the final absolute URL together with apr_uri_unparse() requires that the path be absolute, so only pop a component if the component being popped is not the component for the root directory. */ if (base_components->nelts > 1) apr_array_pop (base_components); } else APR_ARRAY_PUSH (base_components, const char *) = component; } parent_dir_parsed_uri.path = (char *)svn_path_compose(base_components, pool); parent_dir_parsed_uri.query = NULL; parent_dir_parsed_uri.fragment = NULL; return apr_uri_unparse (pool, &parent_dir_parsed_uri, 0); }
/* NOTE: this is used for upgrading old XML-based entries file. Be wary of removing items. ### many attributes are no longer used within the old-style log files. ### These attrs need to be recognized for old entries, however. For these ### cases, the code will parse the attribute, but not set *MODIFY_FLAGS ### for that particular field. MODIFY_FLAGS is *only* used by the ### log-based entry modification system, and will go way once we ### completely move away from loggy. Set *NEW_ENTRY to a new entry, taking attributes from ATTS, whose keys and values are both char *. Allocate the entry and copy attributes into POOL as needed. */ static svn_error_t * atts_to_entry(svn_wc_entry_t **new_entry, apr_hash_t *atts, apr_pool_t *pool) { svn_wc_entry_t *entry = alloc_entry(pool); const char *name; /* Find the name and set up the entry under that name. */ name = svn_hash_gets(atts, ENTRIES_ATTR_NAME); entry->name = name ? apr_pstrdup(pool, name) : SVN_WC_ENTRY_THIS_DIR; /* Attempt to set revision (resolve_to_defaults may do it later, too) ### not used by loggy; no need to set MODIFY_FLAGS */ { const char *revision_str = svn_hash_gets(atts, ENTRIES_ATTR_REVISION); if (revision_str) entry->revision = SVN_STR_TO_REV(revision_str); else entry->revision = SVN_INVALID_REVNUM; } /* Attempt to set up url path (again, see resolve_to_defaults). ### not used by loggy; no need to set MODIFY_FLAGS */ entry->url = extract_string(atts, ENTRIES_ATTR_URL, pool); if (entry->url) entry->url = svn_uri_canonicalize(entry->url, pool); /* Set up repository root. Make sure it is a prefix of url. ### not used by loggy; no need to set MODIFY_FLAGS */ entry->repos = extract_string(atts, ENTRIES_ATTR_REPOS, pool); if (entry->repos) entry->repos = svn_uri_canonicalize(entry->repos, pool); if (entry->url && entry->repos && !svn_uri__is_ancestor(entry->repos, entry->url)) return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL, _("Entry for '%s' has invalid repository " "root"), name ? name : SVN_WC_ENTRY_THIS_DIR); /* Set up kind. */ /* ### not used by loggy; no need to set MODIFY_FLAGS */ { const char *kindstr = svn_hash_gets(atts, ENTRIES_ATTR_KIND); entry->kind = svn_node_none; if (kindstr) { if (strcmp(kindstr, ENTRIES_VALUE_FILE) == 0) entry->kind = svn_node_file; else if (strcmp(kindstr, ENTRIES_VALUE_DIR) == 0) entry->kind = svn_node_dir; else return svn_error_createf (SVN_ERR_NODE_UNKNOWN_KIND, NULL, _("Entry '%s' has invalid node kind"), (name ? name : SVN_WC_ENTRY_THIS_DIR)); } } /* Look for a schedule attribute on this entry. */ /* ### not used by loggy; no need to set MODIFY_FLAGS */ { const char *schedulestr = svn_hash_gets(atts, ENTRIES_ATTR_SCHEDULE); entry->schedule = svn_wc_schedule_normal; if (schedulestr) { if (strcmp(schedulestr, ENTRIES_VALUE_ADD) == 0) entry->schedule = svn_wc_schedule_add; else if (strcmp(schedulestr, ENTRIES_VALUE_DELETE) == 0) entry->schedule = svn_wc_schedule_delete; else if (strcmp(schedulestr, ENTRIES_VALUE_REPLACE) == 0) entry->schedule = svn_wc_schedule_replace; else if (strcmp(schedulestr, "") == 0) entry->schedule = svn_wc_schedule_normal; else return svn_error_createf( SVN_ERR_ENTRY_ATTRIBUTE_INVALID, NULL, _("Entry '%s' has invalid 'schedule' value"), (name ? name : SVN_WC_ENTRY_THIS_DIR)); } } /* Is this entry in a state of mental torment (conflict)? */ entry->prejfile = extract_string_normalize(atts, ENTRIES_ATTR_PREJFILE, pool); entry->conflict_old = extract_string_normalize(atts, ENTRIES_ATTR_CONFLICT_OLD, pool); entry->conflict_new = extract_string_normalize(atts, ENTRIES_ATTR_CONFLICT_NEW, pool); entry->conflict_wrk = extract_string_normalize(atts, ENTRIES_ATTR_CONFLICT_WRK, pool); /* Is this entry copied? */ /* ### not used by loggy; no need to set MODIFY_FLAGS */ SVN_ERR(do_bool_attr(&entry->copied, atts, ENTRIES_ATTR_COPIED, name)); /* ### not used by loggy; no need to set MODIFY_FLAGS */ entry->copyfrom_url = extract_string(atts, ENTRIES_ATTR_COPYFROM_URL, pool); /* ### not used by loggy; no need to set MODIFY_FLAGS */ { const char *revstr; revstr = svn_hash_gets(atts, ENTRIES_ATTR_COPYFROM_REV); if (revstr) entry->copyfrom_rev = SVN_STR_TO_REV(revstr); } /* Is this entry deleted? ### not used by loggy; no need to set MODIFY_FLAGS */ SVN_ERR(do_bool_attr(&entry->deleted, atts, ENTRIES_ATTR_DELETED, name)); /* Is this entry absent? ### not used by loggy; no need to set MODIFY_FLAGS */ SVN_ERR(do_bool_attr(&entry->absent, atts, ENTRIES_ATTR_ABSENT, name)); /* Is this entry incomplete? ### not used by loggy; no need to set MODIFY_FLAGS */ SVN_ERR(do_bool_attr(&entry->incomplete, atts, ENTRIES_ATTR_INCOMPLETE, name)); /* Attempt to set up timestamps. */ /* ### not used by loggy; no need to set MODIFY_FLAGS */ { const char *text_timestr; text_timestr = svn_hash_gets(atts, ENTRIES_ATTR_TEXT_TIME); if (text_timestr) SVN_ERR(svn_time_from_cstring(&entry->text_time, text_timestr, pool)); /* Note: we do not persist prop_time, so there is no need to attempt to parse a new prop_time value from the log. Certainly, on any recent working copy, there will not be a log record to alter the prop_time value. */ } /* Checksum. */ /* ### not used by loggy; no need to set MODIFY_FLAGS */ entry->checksum = extract_string(atts, ENTRIES_ATTR_CHECKSUM, pool); /* UUID. ### not used by loggy; no need to set MODIFY_FLAGS */ entry->uuid = extract_string(atts, ENTRIES_ATTR_UUID, pool); /* Setup last-committed values. */ { const char *cmt_datestr, *cmt_revstr; cmt_datestr = svn_hash_gets(atts, ENTRIES_ATTR_CMT_DATE); if (cmt_datestr) { SVN_ERR(svn_time_from_cstring(&entry->cmt_date, cmt_datestr, pool)); } else entry->cmt_date = 0; cmt_revstr = svn_hash_gets(atts, ENTRIES_ATTR_CMT_REV); if (cmt_revstr) { entry->cmt_rev = SVN_STR_TO_REV(cmt_revstr); } else entry->cmt_rev = SVN_INVALID_REVNUM; entry->cmt_author = extract_string(atts, ENTRIES_ATTR_CMT_AUTHOR, pool); } /* ### not used by loggy; no need to set MODIFY_FLAGS */ entry->lock_token = extract_string(atts, ENTRIES_ATTR_LOCK_TOKEN, pool); entry->lock_owner = extract_string(atts, ENTRIES_ATTR_LOCK_OWNER, pool); entry->lock_comment = extract_string(atts, ENTRIES_ATTR_LOCK_COMMENT, pool); { const char *cdate_str = svn_hash_gets(atts, ENTRIES_ATTR_LOCK_CREATION_DATE); if (cdate_str) { SVN_ERR(svn_time_from_cstring(&entry->lock_creation_date, cdate_str, pool)); } } /* ----- end of lock handling. */ /* Note: if there are attributes for the (deprecated) has_props, has_prop_mods, cachable_props, or present_props, then we're just going to ignore them. */ /* Translated size */ /* ### not used by loggy; no need to set MODIFY_FLAGS */ { const char *val = svn_hash_gets(atts, ENTRIES_ATTR_WORKING_SIZE); if (val) { /* Cast to off_t; it's safe: we put in an off_t to start with... */ entry->working_size = (apr_off_t)apr_strtoi64(val, NULL, 0); } } *new_entry = entry; return SVN_NO_ERROR; }
static svn_error_t * resolve_relative_external_url(const char **resolved_url, const svn_wc_external_item2_t *item, const char *repos_root_url, const char *parent_dir_url, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { const char *url = item->url; apr_uri_t parent_dir_uri; apr_status_t status; *resolved_url = item->url; /* If the URL is already absolute, there is nothing to do. */ if (svn_path_is_url(url)) { /* "http://server/path" */ *resolved_url = svn_uri_canonicalize(url, result_pool); return SVN_NO_ERROR; } if (url[0] == '/') { /* "/path", "//path", and "///path" */ int num_leading_slashes = 1; if (url[1] == '/') { num_leading_slashes++; if (url[2] == '/') num_leading_slashes++; } /* "//schema-relative" and in some cases "///schema-relative". This last format is supported on file:// schema relative. */ url = apr_pstrcat(scratch_pool, apr_pstrndup(scratch_pool, url, num_leading_slashes), svn_relpath_canonicalize(url + num_leading_slashes, scratch_pool), (char*)NULL); } else { /* "^/path" and "../path" */ url = svn_relpath_canonicalize(url, scratch_pool); } /* Parse the parent directory URL into its parts. */ status = apr_uri_parse(scratch_pool, parent_dir_url, &parent_dir_uri); if (status) return svn_error_createf(SVN_ERR_BAD_URL, 0, "Illegal parent directory URL '%s'", parent_dir_url); /* If the parent directory URL is at the server root, then the URL may have no / after the hostname so apr_uri_parse() will leave the URL's path as NULL. */ if (! parent_dir_uri.path) parent_dir_uri.path = apr_pstrmemdup(scratch_pool, "/", 1); parent_dir_uri.query = NULL; parent_dir_uri.fragment = NULL; /* Handle URLs relative to the current directory or to the repository root. The backpaths may only remove path elements, not the hostname. This allows an external to refer to another repository in the same server relative to the location of this repository, say using SVNParentPath. */ if ((0 == strncmp("../", url, 3)) || (0 == strncmp("^/", url, 2))) { apr_array_header_t *base_components; apr_array_header_t *relative_components; int i; /* Decompose either the parent directory's URL path or the repository root's URL path into components. */ if (0 == strncmp("../", url, 3)) { base_components = svn_path_decompose(parent_dir_uri.path, scratch_pool); relative_components = svn_path_decompose(url, scratch_pool); } else { apr_uri_t repos_root_uri; status = apr_uri_parse(scratch_pool, repos_root_url, &repos_root_uri); if (status) return svn_error_createf(SVN_ERR_BAD_URL, 0, "Illegal repository root URL '%s'", repos_root_url); /* If the repository root URL is at the server root, then the URL may have no / after the hostname so apr_uri_parse() will leave the URL's path as NULL. */ if (! repos_root_uri.path) repos_root_uri.path = apr_pstrmemdup(scratch_pool, "/", 1); base_components = svn_path_decompose(repos_root_uri.path, scratch_pool); relative_components = svn_path_decompose(url + 2, scratch_pool); } for (i = 0; i < relative_components->nelts; ++i) { const char *component = APR_ARRAY_IDX(relative_components, i, const char *); if (0 == strcmp("..", component)) { /* Constructing the final absolute URL together with apr_uri_unparse() requires that the path be absolute, so only pop a component if the component being popped is not the component for the root directory. */ if (base_components->nelts > 1) apr_array_pop(base_components); } else APR_ARRAY_PUSH(base_components, const char *) = component; } parent_dir_uri.path = (char *)svn_path_compose(base_components, scratch_pool); *resolved_url = svn_uri_canonicalize(apr_uri_unparse(scratch_pool, &parent_dir_uri, 0), result_pool); return SVN_NO_ERROR; }