summaryrefslogtreecommitdiffstats
path: root/options.c
diff options
context:
space:
mode:
authorHeiko Hund <heiko.hund@sophos.com>2012-02-10 15:13:42 +0100
committerDavid Sommerseth <davids@redhat.com>2012-02-13 17:11:50 +0100
commit71bbbd76c62630c88441237d72fe5b61f0b45b2a (patch)
tree715f8c8183c6e47bb26f0a10c0f6b14f9b9f83a2 /options.c
parent2ee0dc2bd72ec318fcc227af54e5ca7e1384a6cc (diff)
downloadopenvpn-71bbbd76c62630c88441237d72fe5b61f0b45b2a.tar.gz
openvpn-71bbbd76c62630c88441237d72fe5b61f0b45b2a.tar.xz
openvpn-71bbbd76c62630c88441237d72fe5b61f0b45b2a.zip
handle Windows unicode paths
Openvpn for Windows is not compiled as a Unicode binary and thus cannot handle paths which contain non-ASCII characters using the argv vector. Characters that are not present in the system codepage are simply replaced with a question mark, e.g. if started as 'openvpn --config домой.ovpn' the file '?????.ovpn' is tried to be opened as configuration. The same applies to paths in config files which need to be UTF-8 encoded if they contain non ASCII characters. The option line 'key лев.pem' will lead to openvpn trying to open 'лев.pem' on a system with codepage 1252. This patch makes openvpn read the command line in UCS-2 and convert it to UTF-8 internally. Windows stores names in the filesystem in UCS-2. When using a paths openvpn converts it from UTF-8 to UCS-2 and uses the wide character Windows API function. Signed-off-by: Heiko Hund <heiko.hund@sophos.com> Acked-by: David Sommerseth <davids@redhat.com> Signed-off-by: David Sommerseth <davids@redhat.com>
Diffstat (limited to 'options.c')
-rw-r--r--options.c37
1 files changed, 32 insertions, 5 deletions
diff --git a/options.c b/options.c
index a0b3431..42b0b52 100644
--- a/options.c
+++ b/options.c
@@ -2620,18 +2620,18 @@ check_file_access(const int type, const char *file, const int mode, const char *
char *fullpath = strdup(file); /* POSIX dirname() implementaion may modify its arguments */
char *dirpath = dirname(fullpath);
- if (access (dirpath, mode|X_OK) != 0)
+ if (openvpn_access (dirpath, mode|X_OK) != 0)
errcode = errno;
free(fullpath);
}
/* Is the file itself accessible? */
- if (!errcode && (type & CHKACC_FILE) && (access (file, mode) != 0) )
+ if (!errcode && (type & CHKACC_FILE) && (openvpn_access (file, mode) != 0) )
errcode = errno;
/* If the file exists and is accessible, is it writable? */
- if (!errcode && (type & CHKACC_FILEXSTWR) && (access (file, F_OK) == 0) )
- if (access (file, W_OK) != 0)
+ if (!errcode && (type & CHKACC_FILEXSTWR) && (openvpn_access (file, F_OK) == 0) )
+ if (openvpn_access (file, W_OK) != 0)
errcode = errno;
/* Scream if an error is found */
@@ -3737,7 +3737,7 @@ read_config_file (struct options *options,
if (streq (file, "stdin"))
fp = stdin;
else
- fp = fopen (file, "r");
+ fp = openvpn_fopen (file, "r");
if (fp)
{
line_num = 0;
@@ -3814,6 +3814,33 @@ parse_argv (struct options *options,
{
int i, j;
+#ifdef WIN32
+ /*
+ * Windows replaces Unicode characters in argv[] that are not present
+ * in the current codepage with '?'. Get the wide char command line and
+ * convert it to UTF-8 ourselves.
+ */
+ int wargc;
+ WCHAR **wargv;
+ char **uargv;
+
+ wargv = CommandLineToArgvW (GetCommandLineW (), &wargc);
+ if (wargv == NULL || wargc != argc)
+ usage ();
+
+ uargv = gc_malloc (wargc * sizeof (*uargv), false, &options->gc);
+
+ for (i = 0; i < wargc; i++)
+ {
+ int n = WideCharToMultiByte (CP_UTF8, 0, wargv[i], -1, NULL, 0, NULL, NULL);
+ uargv[i] = gc_malloc (n, false, &options->gc);
+ WideCharToMultiByte (CP_UTF8, 0, wargv[i], -1, uargv[i], n, NULL, NULL);
+ }
+
+ LocalFree (wargv);
+ argv = uargv;
+#endif
+
/* usage message */
if (argc <= 1)
usage ();