diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index 7627362cdca0f..184250b0f6b60 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -639,12 +639,14 @@ end downloadcmd = nothing if Sys.iswindows() + downloadcmd = :powershell function download(url::AbstractString, filename::AbstractString) - res = ccall((:URLDownloadToFileW,:urlmon),stdcall,Cuint, - (Ptr{Cvoid},Cwstring,Cwstring,Cuint,Ptr{Cvoid}),C_NULL,url,filename,0,C_NULL) - if res != 0 - error("automatic download failed (error: $res): $url") - end + ps = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" + tls12 = "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12" + client = "New-Object System.Net.Webclient" + # in the following we escape ' with '' (see https://ss64.com/ps/syntax-esc.html) + downloadfile = "($client).DownloadFile('$(replace(url, "'" => "''"))', '$(replace(filename, "'" => "''"))')" + run(`$ps -NoProfile -Command "$tls12; $downloadfile"`) filename end else diff --git a/test/download.jl b/test/download.jl index e982dbfbcc53f..5fa3eef9597b3 100644 --- a/test/download.jl +++ b/test/download.jl @@ -19,6 +19,13 @@ mktempdir() do temp_dir @test_throws ErrorException download("http://httpbin.org/status/404", missing_file) @test !isfile(missing_file) + # Make sure we properly handle metachar ' + metachar_file = joinpath(temp_dir, "metachar") + download("https://httpbin.org/get?test='^'", metachar_file) + metachar_string = read(metachar_file, String) + m = match(r"\"url\"\s*:\s*\"(.*)\"", metachar_string) + @test m.captures[1] == "https://httpbin.org/get?test='^'" + # Use a TEST-NET (192.0.2.0/24) address which shouldn't be bound invalid_host_file = joinpath(temp_dir, "invalid_host") @test_throws ErrorException download("http://192.0.2.1", invalid_host_file)