|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
3 | 3 | import re |
| 4 | +import locale |
4 | 5 | import struct |
5 | 6 | import sys |
6 | 7 | import warnings |
@@ -256,7 +257,34 @@ def setopt(self, option: CurlOpt, value: Any) -> int: |
256 | 257 | lib._curl_easy_setopt(self._curl, CurlOpt.DEBUGFUNCTION, lib.debug_function) |
257 | 258 | option = CurlOpt.DEBUGDATA |
258 | 259 | elif value_type == "char*": |
259 | | - c_value = value.encode() if isinstance(value, str) else value |
| 260 | + if isinstance(value, str): |
| 261 | + # Windows/libcurl expects ANSI code page for file paths (char*). |
| 262 | + # Non-ASCII paths encoded as UTF-8 can trigger ErrCode 77. |
| 263 | + # Encode file-path-like options using the system encoding on Windows. |
| 264 | + filepath_opts = { |
| 265 | + CurlOpt.CAINFO, |
| 266 | + CurlOpt.CAPATH, |
| 267 | + CurlOpt.PROXY_CAINFO, |
| 268 | + CurlOpt.PROXY_CAPATH, |
| 269 | + CurlOpt.SSLCERT, |
| 270 | + CurlOpt.SSLKEY, |
| 271 | + CurlOpt.CRLFILE, |
| 272 | + CurlOpt.ISSUERCERT, |
| 273 | + CurlOpt.SSH_PUBLIC_KEYFILE, |
| 274 | + CurlOpt.SSH_PRIVATE_KEYFILE, |
| 275 | + CurlOpt.COOKIEFILE, |
| 276 | + CurlOpt.COOKIEJAR, |
| 277 | + CurlOpt.NETRC_FILE, |
| 278 | + CurlOpt.UNIX_SOCKET_PATH, |
| 279 | + } |
| 280 | + if sys.platform.startswith("win") and option in filepath_opts: |
| 281 | + # Use the process ANSI code page to match what CRT fopen expects. |
| 282 | + enc = locale.getpreferredencoding(False) |
| 283 | + c_value = value.encode(enc, errors="strict") |
| 284 | + else: |
| 285 | + c_value = value.encode() |
| 286 | + else: |
| 287 | + c_value = value |
260 | 288 | # Must keep a reference, otherwise may be GCed. |
261 | 289 | if option == CurlOpt.POSTFIELDS: |
262 | 290 | self._body_handle = c_value |
|
0 commit comments