Invoke-Uplift-HTTP.ps1
function Invoke-ToolCmd($fileName, $arguments) { Write-DebugMessage "Tool: $fileName" Write-DebugMessage "Arguments: $arguments" $pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = "$fileName" $pinfo.RedirectStandardError = $true $pinfo.RedirectStandardOutput = $true $pinfo.UseShellExecute = $false $pinfo.Arguments = $arguments $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo Write-DebugMessage "Started process: $fileName" $p.Start() | Out-Null Write-DebugMessage "Waiting for exit..." $p.WaitForExit() Write-DebugMessage "Started process: $fileName" Write-DebugMessage "ExitCode: $($p.ExitCode)" return $p.ExitCode } function Get-DownloadToolAvialablity() { $wgetToolName = "wget"; $curlToolName = "curl"; if($IsWindows -eq $True) { $wgetToolName = "wget.exe"; $curlToolName = "curl.exe"; } $result = New-Object PsObject -Property @{ wget = @{ ToolName = $wgetToolName IsAvailable = ($null -ne (Get-ToolCmd $wgetToolName) ) } curl = @{ ToolName = $curlToolName IsAvailable = ($null -ne (Get-ToolCmd $curlToolName) ) } } return $result; } function Invoke-DownloadFileAsWget($tool, $src, $dst) { # https://www.pair.com/support/kb/paircloud-downloading-files-with-wget/ Write-DebugMessage 'Runnig wget' $cmdString = "-O $dst $src --quiet" $exitCode = Invoke-ToolCmd $tool.ToolName $cmdString if($exitCode -ne 0) { throw "Cannot download file using wget.exe, exit code: $exitCode" } } function Invoke-DownloadFileAsCurl($tool, $src, $dst) { # http://www.compciv.org/recipes/cli/downloading-with-curl/ Write-DebugMessage 'Runnig curl' $cmdString = " ""$src"" --output ""$dst"" --silent" $exitCode = Invoke-ToolCmd $tool.ToolName $cmdString if($exitCode -ne 0) { throw "Cannot download file using curl.exe, exit code: $exitCode" } } function Invoke-DownloadFileAsInvokeWebRequest($src, $dst) { Write-WarningMessage "[~] Downloading using Invoke-RestMethod" Write-WarningMessage " - might not work in large files producing malformed downloads" Write-WarningMessage " - install curl or wget" Write-DebugMessage "Downloading $src" # disable progress, it is also much faster! # https://stackoverflow.com/questions/18770723/hide-progress-of-invoke-webrequest $oldProgressPreference = $progressPreference $progressPreference = 'silentlyContinue' try { $oldProgressPreference = $progressPreference # download to file # always use UseBasicParsing, won't fail on bare new win VM after sysprep Invoke-WebRequest -Uri $src ` -OutFile $dst ` -MaximumRedirection 10 ` -UseBasicParsing } finally { $progressPreference = $oldProgressPreference } } function Invoke-UrlAvialabilityCheck($src) { # https://stackoverflow.com/questions/20259251/powershell-script-to-check-the-status-of-a-url Write-DebugMessage "[~] Checking URL availability: $src" $result = Invoke-WebRequest -Uri $src ` -UseBasicParsing ` -DisableKeepAlive ` -Method HEAD if($result.StatusCode -eq 200) { Write-DebugMessage "[+] StatusCode: $($result.StatusCode)" } else { Write-ErrorMessage "[!] StatusCode: $($result.StatusCode), expected 200!" } return ( ($null -ne $result ) -and ($result.StatusCode -eq 200) ) } function Invoke-DownloadFile($src, $dst, $preferredTool = $null) { try { $tools = Get-DownloadToolAvialablity # check is file evem available? # HEAD must return 200 if( (Invoke-UrlAvialabilityCheck $src) -eq $false) { throw "Cannot validate url, got non-200 result" } if($null -ne $preferredTool) { # using preferred tool $preferredToolValue = $preferredTool.ToLower() Write-DebugMessage "Using preferred tool: $preferredToolValue" if( $preferredToolValue -ilike "*wget*" ) { if( $tools.wget.IsAvailable -eq $True) { Invoke-DownloadFileAsWget $tools.wget $src $dst return } else { throw "Preferred tool is not available: $preferredToolValue" } } elseif( $preferredToolValue -ilike "*curl*" ) { if( $tools.curl.IsAvailable -eq $True) { Invoke-DownloadFileAsCurl $tools.curl $src $dst return } else { throw "Preferred tool is not available: $preferredToolValue" } } elseif( $preferredToolValue -ilike "*InvokeWebRequest*" ) { Invoke-DownloadFileAsInvokeWebRequest $tools.curl $src $dst return } else { throw "Preferred tool is not supported: $preferredToolValue" } } else { # cascading wget -> curl -> InvokeWebRequest Write-DebugMessage "No preferred tool is set, cascading: wget -> curl -> InvokeWebRequest" # is wget available? if( $tools.wget.IsAvailable -eq $True) { Invoke-DownloadFileAsWget $tools.wget $src $dst return } else { Write-DebugMessage "wget is not here, fallback: wget -> curl -> InvokeWebRequest" } # is curl available? if( $tools.curl.IsAvailable -eq $True) { Invoke-DownloadFileAsCurl $tools.curl $src $dst return } else { Write-DebugMessage "curl is not here, fallback: wget -> curl -> InvokeWebRequest" } # default is Invoke-WebRequest # might not work well with large files Invoke-DownloadFileAsInvokeWebRequest $src $dst } } catch { Write-ErrorMessage "Error while downloading file: $($_.Exception)" Write-ErrorMessage $_.Exception throw $_ } } |