diff options
Diffstat (limited to 'subversion/libsvn_subr')
-rw-r--r-- | subversion/libsvn_subr/apr_escape.c | 135 | ||||
-rw-r--r-- | subversion/libsvn_subr/cmdline.c | 101 | ||||
-rw-r--r-- | subversion/libsvn_subr/iter.c | 26 | ||||
-rw-r--r-- | subversion/libsvn_subr/opt.c | 2 | ||||
-rw-r--r-- | subversion/libsvn_subr/version.c | 2 |
5 files changed, 252 insertions, 14 deletions
diff --git a/subversion/libsvn_subr/apr_escape.c b/subversion/libsvn_subr/apr_escape.c new file mode 100644 index 000000000000..caa25d9fc573 --- /dev/null +++ b/subversion/libsvn_subr/apr_escape.c @@ -0,0 +1,135 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* The code in this file is copied from APR (initially from APR 1.7.0) + * to provide compatibility for building against APR < 1.5.0. + */ + +#include "private/svn_dep_compat.h" + +#if !APR_VERSION_AT_LEAST(1,5,0) + +#include <apr_lib.h> +#include <apr_strings.h> + +/* from apr_escape_test_char.h */ +#define T_ESCAPE_SHELL_CMD (1) +#define T_ESCAPE_PATH_SEGMENT (2) +#define T_OS_ESCAPE_PATH (4) +#define T_ESCAPE_ECHO (8) +#define T_ESCAPE_URLENCODED (16) +#define T_ESCAPE_XML (32) +#define T_ESCAPE_LDAP_DN (64) +#define T_ESCAPE_LDAP_FILTER (128) + +static const unsigned char test_char_table[256] = { + 224,222,222,222,222,222,222,222,222,222,223,222,222,222,222,222,222,222,222,222, + 222,222,222,222,222,222,222,222,222,222,222,222,6,16,127,22,17,22,49,17, + 145,145,129,80,80,0,0,18,0,0,0,0,0,0,0,0,0,0,16,87, + 119,16,119,23,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,23,223,23,23,0,23,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,23,23,23,17,222,222,222,222,222,222,222,222,222,222,222,222,222, + 222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, + 222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, + 222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, + 222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, + 222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, + 222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222 +}; + +/* from apr_encode_private.h */ +#if APR_CHARSET_EBCDIC +#error This Subversion compatibility code for APR<1.5 does not support EBCDIC. +#else /* APR_CHARSET_EBCDIC */ +#define ENCODE_TO_ASCII(ch) (ch) +#define ENCODE_TO_NATIVE(ch) (ch) +#endif /* !APR_CHARSET_EBCDIC */ + +/* we assume the folks using this ensure 0 <= c < 256... which means + * you need a cast to (unsigned char) first, you can't just plug a + * char in here and get it to work, because if char is signed then it + * will first be sign extended. + */ +#define TEST_CHAR(c, f) (test_char_table[(unsigned)(c)] & (f)) + +APR_DECLARE(apr_status_t) apr_escape_shell(char *escaped, const char *str, + apr_ssize_t slen, apr_size_t *len) +{ + unsigned char *d; + const unsigned char *s; + apr_size_t size = 1; + int found = 0; + + d = (unsigned char *) escaped; + s = (const unsigned char *) str; + + if (s) { + if (d) { + for (; *s && slen; ++s, slen--) { +#if defined(OS2) || defined(WIN32) + /* + * Newlines to Win32/OS2 CreateProcess() are ill advised. + * Convert them to spaces since they are effectively white + * space to most applications + */ + if (*s == '\r' || *s == '\n') { + if (d) { + *d++ = ' '; + found = 1; + } + continue; + } +#endif + if (TEST_CHAR(*s, T_ESCAPE_SHELL_CMD)) { + *d++ = '\\'; + size++; + found = 1; + } + *d++ = *s; + size++; + } + *d = '\0'; + } + else { + for (; *s && slen; ++s, slen--) { + if (TEST_CHAR(*s, T_ESCAPE_SHELL_CMD)) { + size++; + found = 1; + } + size++; + } + } + } + + if (len) { + *len = size; + } + if (!found) { + return APR_NOTFOUND; + } + + return APR_SUCCESS; +} + +#else /* APR_VERSION_AT_LEAST(1,5,0) */ + +/* Silence OSX ranlib warnings about object files with no symbols. */ +#include <apr.h> +extern const apr_uint32_t svn__fake__apr_escape; +const apr_uint32_t svn__fake__apr_escape = 0xdeadbeef; + +#endif /* !APR_VERSION_AT_LEAST(1,5,0) */ diff --git a/subversion/libsvn_subr/cmdline.c b/subversion/libsvn_subr/cmdline.c index d1aad71b234a..bc27788ec03a 100644 --- a/subversion/libsvn_subr/cmdline.c +++ b/subversion/libsvn_subr/cmdline.c @@ -39,9 +39,15 @@ #include <apr.h> /* for STDIN_FILENO */ #include <apr_errno.h> /* for apr_strerror */ +#include <apr_version.h> +#if APR_VERSION_AT_LEAST(1,5,0) #include <apr_escape.h> +#else +#include "private/svn_dep_compat.h" +#endif #include <apr_general.h> /* for apr_initialize/apr_terminate */ #include <apr_strings.h> /* for apr_snprintf */ +#include <apr_env.h> /* for apr_env_get */ #include <apr_pools.h> #include <apr_signal.h> @@ -1235,38 +1241,84 @@ svn_cmdline__be_interactive(svn_boolean_t non_interactive, /* Helper for the edit_externally functions. Set *EDITOR to some path to an - editor binary. Sources to search include: the EDITOR_CMD argument - (if not NULL), $SVN_EDITOR, the runtime CONFIG variable (if CONFIG + editor binary, in native C string on Unix/Linux platforms and in UTF-8 + string on Windows platform. Sources to search include: the EDITOR_CMD + argument (if not NULL), $SVN_EDITOR, the runtime CONFIG variable (if CONFIG is not NULL), $VISUAL, $EDITOR. Return SVN_ERR_CL_NO_EXTERNAL_EDITOR if no binary can be found. */ static svn_error_t * find_editor_binary(const char **editor, const char *editor_cmd, - apr_hash_t *config) + apr_hash_t *config, + apr_pool_t *pool) { const char *e; + const char *e_cfg; struct svn_config_t *cfg; + apr_status_t status; /* Use the editor specified on the command line via --editor-cmd, if any. */ +#ifdef WIN32 + /* On Windows, editor_cmd is transcoded to the system active code page + because we use main() as a entry point without APR's (or our own) wrapper + in command line tools. */ + if (editor_cmd) + { + SVN_ERR(svn_utf_cstring_to_utf8(&e, editor_cmd, pool)); + } + else + { + e = NULL; + } +#else e = editor_cmd; +#endif /* Otherwise look for the Subversion-specific environment variable. */ if (! e) - e = getenv("SVN_EDITOR"); + { + status = apr_env_get((char **)&e, "SVN_EDITOR", pool); + if (status || ! *e) + { + e = NULL; + } + } /* If not found then fall back on the config file. */ if (! e) { cfg = config ? svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG) : NULL; - svn_config_get(cfg, &e, SVN_CONFIG_SECTION_HELPERS, + svn_config_get(cfg, &e_cfg, SVN_CONFIG_SECTION_HELPERS, SVN_CONFIG_OPTION_EDITOR_CMD, NULL); +#ifdef WIN32 + if (e_cfg) + { + /* On Windows, we assume that config values are set in system active + code page, so we need transcode it here. */ + SVN_ERR(svn_utf_cstring_to_utf8(&e, e_cfg, pool)); + } +#else + e = e_cfg; +#endif } /* If not found yet then try general purpose environment variables. */ if (! e) - e = getenv("VISUAL"); + { + status = apr_env_get((char**)&e, "VISUAL", pool); + if (status || ! *e) + { + e = NULL; + } + } if (! e) - e = getenv("EDITOR"); + { + status = apr_env_get((char**)&e, "EDITOR", pool); + if (status || ! *e) + { + e = NULL; + } + } #ifdef SVN_CLIENT_EDITOR /* If still not found then fall back on the hard-coded default. */ @@ -1400,13 +1452,17 @@ svn_cmdline__edit_file_externally(const char *path, apr_pool_t *pool) { const char *editor, *cmd, *base_dir, *file_name, *base_dir_apr; + const char *file_name_local; +#ifdef WIN32 + const WCHAR *wcmd; +#endif char *old_cwd; int sys_err; apr_status_t apr_err; svn_dirent_split(&base_dir, &file_name, path, pool); - SVN_ERR(find_editor_binary(&editor, editor_cmd, config)); + SVN_ERR(find_editor_binary(&editor, editor_cmd, config, pool)); apr_err = apr_filepath_get(&old_cwd, APR_FILEPATH_NATIVE, pool); if (apr_err) @@ -1423,10 +1479,18 @@ svn_cmdline__edit_file_externally(const char *path, return svn_error_wrap_apr (apr_err, _("Can't change working directory to '%s'"), base_dir); + SVN_ERR(svn_path_cstring_from_utf8(&file_name_local, + escape_path(pool, file_name), pool)); /* editor is explicitly documented as being interpreted by the user's shell, and as such should already be quoted/escaped as needed. */ - cmd = apr_psprintf(pool, "%s %s", editor, escape_path(pool, file_name)); +#ifndef WIN32 + cmd = apr_psprintf(pool, "%s %s", editor, file_name_local); sys_err = system(cmd); +#else + cmd = apr_psprintf(pool, "\"%s %s\"", editor, file_name_local); + SVN_ERR(svn_utf__win32_utf8_to_utf16(&wcmd, cmd, NULL, pool)); + sys_err = _wsystem(wcmd); +#endif apr_err = apr_filepath_set(old_cwd, pool); if (apr_err) @@ -1458,6 +1522,9 @@ svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8! */, { const char *editor; const char *cmd; +#ifdef WIN32 + const WCHAR *wcmd; +#endif apr_file_t *tmp_file; const char *tmpfile_name; const char *tmpfile_native; @@ -1471,7 +1538,7 @@ svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8! */, int sys_err; svn_boolean_t remove_file = TRUE; - SVN_ERR(find_editor_binary(&editor, editor_cmd, config)); + SVN_ERR(find_editor_binary(&editor, editor_cmd, config, pool)); /* Convert file contents from UTF-8/LF if desired. */ if (as_text) @@ -1581,13 +1648,18 @@ svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8! */, goto cleanup; /* Prepare the editor command line. */ - err = svn_utf_cstring_from_utf8(&tmpfile_native, tmpfile_name, pool); + err = svn_utf_cstring_from_utf8(&tmpfile_native, + escape_path(pool, tmpfile_name), pool); if (err) goto cleanup; /* editor is explicitly documented as being interpreted by the user's shell, and as such should already be quoted/escaped as needed. */ - cmd = apr_psprintf(pool, "%s %s", editor, escape_path(pool, tmpfile_native)); +#ifndef WIN32 + cmd = apr_psprintf(pool, "%s %s", editor, tmpfile_native); +#else + cmd = apr_psprintf(pool, "\"%s %s\"", editor, tmpfile_native); +#endif /* If the caller wants us to leave the file around, return the path of the file we'll use, and make a note not to destroy it. */ @@ -1598,7 +1670,12 @@ svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8! */, } /* Now, run the editor command line. */ +#ifndef WIN32 sys_err = system(cmd); +#else + SVN_ERR(svn_utf__win32_utf8_to_utf16(&wcmd, cmd, NULL, pool)); + sys_err = _wsystem(wcmd); +#endif if (sys_err != 0) { /* Extracting any meaning from sys_err is platform specific, so just diff --git a/subversion/libsvn_subr/iter.c b/subversion/libsvn_subr/iter.c index 6d04846e8378..1a303b511945 100644 --- a/subversion/libsvn_subr/iter.c +++ b/subversion/libsvn_subr/iter.c @@ -143,3 +143,29 @@ svn_iter__break(void) { return &internal_break_error; } + +#if !APR_VERSION_AT_LEAST(1, 5, 0) +const void *apr_hash_this_key(apr_hash_index_t *hi) +{ + const void *key; + + apr_hash_this((apr_hash_index_t *)hi, &key, NULL, NULL); + return key; +} + +apr_ssize_t apr_hash_this_key_len(apr_hash_index_t *hi) +{ + apr_ssize_t klen; + + apr_hash_this((apr_hash_index_t *)hi, NULL, &klen, NULL); + return klen; +} + +void *apr_hash_this_val(apr_hash_index_t *hi) +{ + void *val; + + apr_hash_this((apr_hash_index_t *)hi, NULL, NULL, &val); + return val; +} +#endif diff --git a/subversion/libsvn_subr/opt.c b/subversion/libsvn_subr/opt.c index 1a9beb646f89..2832553d1f41 100644 --- a/subversion/libsvn_subr/opt.c +++ b/subversion/libsvn_subr/opt.c @@ -326,7 +326,7 @@ print_command_info3(const svn_opt_subcommand_desc3_t *cmd, } } - if (!verbose) + if (!verbose && global_options && *global_options) SVN_ERR(svn_cmdline_fputs(_("\n(Use '-v' to show global and experimental options.)\n"), stream, pool)); if (have_options) diff --git a/subversion/libsvn_subr/version.c b/subversion/libsvn_subr/version.c index 1c50ad0e7a5d..cbb09f55812d 100644 --- a/subversion/libsvn_subr/version.c +++ b/subversion/libsvn_subr/version.c @@ -143,7 +143,7 @@ svn_version_extended(svn_boolean_t verbose, info->build_time = __TIME__; info->build_host = SVN_BUILD_HOST; info->copyright = apr_pstrdup - (pool, _("Copyright (C) 2020 The Apache Software Foundation.\n" + (pool, _("Copyright (C) 2021 The Apache Software Foundation.\n" "This software consists of contributions made by many people;\n" "see the NOTICE file for more information.\n" "Subversion is open source software, see " |