]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tool: support UTF-16 command line on Windows
authorMarcel Raad <Marcel.Raad@teamviewer.com>
Fri, 12 Apr 2019 20:59:40 +0000 (22:59 +0200)
committerMarcel Raad <Marcel.Raad@teamviewer.com>
Thu, 14 May 2020 16:13:36 +0000 (18:13 +0200)
- use `wmain` instead of `main` when `_UNICODE` is defined [0]
- define `argv_item_t` as `wchar_t *` in this case
- use the curl_multibyte gear to convert the command-line arguments to
  UTF-8

This makes it possible to pass parameters with characters outside of
the current locale on Windows, which is required for some tests, e.g.
the IDN tests. Out of the box, this currently only works with the
Visual Studio project files, which default to Unicode, and winbuild
with the `ENABLE_UNICODE` option.

[0] https://devblogs.microsoft.com/oldnewthing/?p=40643

Ref: https://github.com/curl/curl/issues/3747
Closes https://github.com/curl/curl/pull/3784

lib/curl_setup_once.h
src/tool_getparam.c
src/tool_main.c
src/tool_operate.c

index 8890f3890dfd73241cea06a879d41a2751d59683..e7c00deabdd596e2c395c2eee1eb060d4ae1527f 100644 (file)
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -481,6 +481,8 @@ typedef int sig_atomic_t;
 
 #ifdef __VMS
 #define argv_item_t  __char_ptr32
+#elif defined(_UNICODE)
+#define argv_item_t wchar_t *
 #else
 #define argv_item_t  char *
 #endif
index c0ab67c3f3975a69fd99d4b10d75f39c2a8208a7..ab2b75289beac185094da017f1b76ba72e53fd74 100644 (file)
@@ -2248,20 +2248,22 @@ ParameterError parse_args(struct GlobalConfig *global, int argc,
   struct OperationConfig *config = global->first;
 
   for(i = 1, stillflags = TRUE; i < argc && !result; i++) {
-    orig_opt = argv[i];
+    orig_opt = curlx_convert_tchar_to_UTF8(argv[i]);
 
-    if(stillflags && ('-' == argv[i][0])) {
+    if(stillflags && ('-' == orig_opt[0])) {
       bool passarg;
-      char *flag = argv[i];
 
-      if(!strcmp("--", argv[i]))
+      if(!strcmp("--", orig_opt))
         /* This indicates the end of the flags and thus enables the
            following (URL) argument to start with -. */
         stillflags = FALSE;
       else {
-        char *nextarg = (i < (argc - 1)) ? argv[i + 1] : NULL;
+        char *nextarg = (i < (argc - 1))
+          ? curlx_convert_tchar_to_UTF8(argv[i + 1])
+          : NULL;
 
-        result = getparameter(flag, nextarg, &passarg, global, config);
+        result = getparameter(orig_opt, nextarg, &passarg, global, config);
+        curlx_unicodefree(nextarg);
         config = global->last;
         if(result == PARAM_NEXT_OPERATION) {
           /* Reset result as PARAM_NEXT_OPERATION is only used here and not
@@ -2297,7 +2299,7 @@ ParameterError parse_args(struct GlobalConfig *global, int argc,
       bool used;
 
       /* Just add the URL please */
-      result = getparameter((char *)"--url", argv[i], &used, global,
+      result = getparameter("--url", orig_opt, &used, global,
                             config);
     }
   }
@@ -2314,5 +2316,6 @@ ParameterError parse_args(struct GlobalConfig *global, int argc,
       helpf(global->errors, "%s\n", reason);
   }
 
+  curlx_unicodefree(orig_opt);
   return result;
 }
index 25042895f8875b7a054af0e6d8c36651b638562f..ccf098e9479b96d779764d9b95a513b94a88d34c 100644 (file)
@@ -273,22 +273,28 @@ static void restore_terminal(void)
 /*
 ** curl tool main function.
 */
+#ifdef _UNICODE
+int wmain(int argc, wchar_t *argv[])
+#else
 int main(int argc, char *argv[])
+#endif
 {
   CURLcode result = CURLE_OK;
   struct GlobalConfig global;
   memset(&global, 0, sizeof(global));
 
 #ifdef WIN32
+#ifdef _tcscmp
   /* Undocumented diagnostic option to list the full paths of all loaded
      modules. This is purposely pre-init. */
-  if(argc == 2 && !strcmp(argv[1], "--dump-module-paths")) {
+  if(argc == 2 && !_tcscmp(argv[1], _T("--dump-module-paths"))) {
     struct curl_slist *item, *head = GetLoadedModulePaths();
     for(item = head; item; item = item->next)
       printf("%s\n", item->data);
     curl_slist_free_all(head);
     return head ? 0 : 1;
   }
+#endif /* _tcscmp */
   /* win32_init must be called before other init routines. */
   result = win32_init();
   if(result) {
index 6d489aa30b7938e28e2e91d62a620d66fe552b8c..0ddcf8ea9e40a9d2bf85152d5710b23447f96691 100644 (file)
@@ -2427,6 +2427,7 @@ static CURLcode run_all_transfers(struct GlobalConfig *global,
 CURLcode operate(struct GlobalConfig *global, int argc, argv_item_t argv[])
 {
   CURLcode result = CURLE_OK;
+  char *first_arg = curlx_convert_tchar_to_UTF8(argv[1]);
 
   /* Setup proper locale from environment */
 #ifdef HAVE_SETLOCALE
@@ -2435,8 +2436,8 @@ CURLcode operate(struct GlobalConfig *global, int argc, argv_item_t argv[])
 
   /* Parse .curlrc if necessary */
   if((argc == 1) ||
-     (!curl_strequal(argv[1], "-q") &&
-      !curl_strequal(argv[1], "--disable"))) {
+     (!curl_strequal(first_arg, "-q") &&
+      !curl_strequal(first_arg, "--disable"))) {
     parseconfig(NULL, global); /* ignore possible failure */
 
     /* If we had no arguments then make sure a url was specified in .curlrc */
@@ -2446,6 +2447,8 @@ CURLcode operate(struct GlobalConfig *global, int argc, argv_item_t argv[])
     }
   }
 
+  curlx_unicodefree(first_arg);
+
   if(!result) {
     /* Parse the command line arguments */
     ParameterError res = parse_args(global, argc, argv);