Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure file names are valid before saving #85

Merged
merged 6 commits into from
Oct 12, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 74 additions & 18 deletions Tools/YamlCreate.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,14 @@ Function TestUrlValidity {
return $HTTP_Status
}

# Checks a file name for validity and returns a boolean value
function Test-ValidFileName {
param([string]$FileName)
$IndexOfInvalidChar = $FileName.IndexOfAny([System.IO.Path]::GetInvalidFileNameChars())
# IndexOfAny() returns the value -1 to indicate no such character was found
return $IndexOfInvalidChar -eq -1
}

# Prompts user to enter an Installer URL, Tests the URL to ensure it results in a response code of 200, validates it against the manifest schema
# Returns the validated URL which was entered
Function Request-Installer-Url {
Expand Down Expand Up @@ -373,12 +381,28 @@ Function Read-Installer-Values {
$start_time = Get-Date
Write-Host $NewLine
Write-Host 'Downloading URL. This will take a while...' -ForegroundColor Blue
$WebClient = New-Object System.Net.WebClient
$Filename = [System.IO.Path]::GetFileName($InstallerUrl)
$script:dest = "$env:TEMP\$FileName"

try {
$WebClient.DownloadFile($InstallerUrl, $script:dest)
# Download and store the binary, but do not write to a file yet
$download = Invoke-WebRequest -Uri $InstallerUrl -UserAgent 'winget/1.0' -DisableKeepAlive -TimeoutSec 30 -UseBasicParsing
# Attempt to get the file from the headers
try {
$contentDisposition = [System.Net.Mime.ContentDisposition]::new($download.Headers['Content-Disposition'])
$_Filename = $contentDisposition.FileName
} catch {}
# Validate the headers reurned a valid file name
if (![string]::IsNullOrWhiteSpace($_Filename) -and $(Test-ValidFileName $_Filename)) {
$Filename = $_Filename
}
# If the headers did not return a valid file name, build our own file name
# Attempt to preserve the extension if it exists, otherwise, create our own
else {
$Filename = "$PackageIdentifier v$PackageVersion" + $(if ([System.IO.Path]::HasExtension($_Filename)) { [System.IO.Path]::GetExtension($_Filename) } elseif ([System.IO.Path]::HasExtension($InstallerUrl)) { [System.IO.Path]::GetExtension($InstallerUrl) } else { '.winget-tmp' })
}
# Write File to disk
$script:dest = Join-Path -Path $env:TEMP -ChildPath $Filename
$file = [System.IO.FileStream]::new($script:dest, [System.IO.FileMode]::Create)
$file.Write($download.Content, 0, $download.RawContentLength)
$file.Close()
} catch {
# Here we also want to pass the exception through for potential debugging
throw [System.Net.WebException]::new('The file could not be downloaded. Try running the script again', $_.Exception)
Expand Down Expand Up @@ -754,12 +778,28 @@ Function Read-Installer-Values-Minimal {
# Request user enter the new Installer URL
$_NewInstaller['InstallerUrl'] = Request-Installer-Url

# Download the file at the URL
$WebClient = New-Object System.Net.WebClient
$Filename = [System.IO.Path]::GetFileName($($_NewInstaller.InstallerUrl))
$script:dest = "$env:TEMP\$Filename"
try {
$WebClient.DownloadFile($($_NewInstaller.InstallerUrl), $script:dest)
# Download and store the binary, but do not write to a file yet
$download = Invoke-WebRequest -Uri $_NewInstaller['InstallerUrl'] -UserAgent 'winget/1.0' -DisableKeepAlive -TimeoutSec 30 -UseBasicParsing
# Attempt to get the file from the headers
try {
$contentDisposition = [System.Net.Mime.ContentDisposition]::new($download.Headers['Content-Disposition'])
$_Filename = $contentDisposition.FileName
} catch {}
# Validate the headers reurned a valid file name
if (![string]::IsNullOrWhiteSpace($_Filename) -and $(Test-ValidFileName $_Filename)) {
$Filename = $_Filename
}
# If the headers did not return a valid file name, build our own file name
# Attempt to preserve the extension if it exists, otherwise, create our own
else {
$Filename = "$PackageIdentifier v$PackageVersion" + $(if ([System.IO.Path]::HasExtension($_Filename)) { [System.IO.Path]::GetExtension($_Filename) } elseif ([System.IO.Path]::HasExtension($InstallerUrl)) { [System.IO.Path]::GetExtension($InstallerUrl) } else { '.winget-tmp' })
}
# Write File to disk
$script:dest = Join-Path -Path $env:TEMP -ChildPath $Filename
$file = [System.IO.FileStream]::new($script:dest, [System.IO.FileMode]::Create)
$file.Write($download.Content, 0, $download.RawContentLength)
$file.Close()
} catch {
# Here we also want to pass the exception through for potential debugging
throw [System.Net.WebException]::new('The file could not be downloaded. Try running the script again', $_.Exception)
Expand Down Expand Up @@ -1400,7 +1440,7 @@ Function Enter-PR-Parameters {

# If we are removing a manifest, we need to include the reason
if ($CommitType -eq 'Remove') {
$PrBodyContentReply = @("## $($script:RemovalReason)";'')+$PrBodyContentReply
$PrBodyContentReply = @("## $($script:RemovalReason)"; '') + $PrBodyContentReply
}

# Write the PR using a temporary file
Expand Down Expand Up @@ -2077,10 +2117,10 @@ Switch ($script:Option) {
Write-Host -ForegroundColor 'Green' -Object '[Required] Enter the reason for removing this manifest'
$script:RemovalReason = Read-Host -Prompt 'Reason' | TrimString
# Check the reason for validity. The length requirements are arbitrary, but they have been set to encourage concise yet meaningful reasons
if (String.Validate $script:RemovalReason -MinLength 16 -MaxLength 128 -NotNull) {
if (String.Validate $script:RemovalReason -MinLength 8 -MaxLength 128 -NotNull) {
$script:_returnValue = [ReturnValue]::Success()
} else {
$script:_returnValue = [ReturnValue]::LengthError(16, 128)
$script:_returnValue = [ReturnValue]::LengthError(8, 128)
}
} until ($script:_returnValue.StatusCode -eq [ReturnValue]::Success().StatusCode)

Expand All @@ -2097,12 +2137,28 @@ Switch ($script:Option) {
Write-Host $NewLine
Write-Host 'Updating Manifest Information. This may take a while...' -ForegroundColor Blue
foreach ($_Installer in $script:OldInstallerManifest.Installers) {
# Download the file at the URL
$WebClient = New-Object System.Net.WebClient
$Filename = [System.IO.Path]::GetFileName($($_Installer.InstallerUrl))
$script:dest = "$env:TEMP\$Filename"
try {
$WebClient.DownloadFile($($_Installer.InstallerUrl), $script:dest)
# Download and store the binary, but do not write to a file yet
$download = Invoke-WebRequest -Uri $_Installer.InstallerUrl -UserAgent 'winget/1.0' -DisableKeepAlive -TimeoutSec 30 -UseBasicParsing
# Attempt to get the file from the headers
try {
$contentDisposition = [System.Net.Mime.ContentDisposition]::new($download.Headers['Content-Disposition'])
$_Filename = $contentDisposition.FileName
} catch {}
# Validate the headers reurned a valid file name
if (![string]::IsNullOrWhiteSpace($_Filename) -and $(Test-ValidFileName $_Filename)) {
$Filename = $_Filename
}
# If the headers did not return a valid file name, build our own file name
# Attempt to preserve the extension if it exists, otherwise, create our own
else {
$Filename = "$PackageIdentifier v$PackageVersion" + $(if ([System.IO.Path]::HasExtension($_Filename)) { [System.IO.Path]::GetExtension($_Filename) } elseif ([System.IO.Path]::HasExtension($InstallerUrl)) { [System.IO.Path]::GetExtension($InstallerUrl) } else { '.winget-tmp' })
}
# Write File to disk
$script:dest = Join-Path -Path $env:TEMP -ChildPath $Filename
$file = [System.IO.FileStream]::new($script:dest, [System.IO.FileMode]::Create)
$file.Write($download.Content, 0, $download.RawContentLength)
$file.Close()
} catch {
# Here we also want to pass the exception through for potential debugging
throw [System.Net.WebException]::new('The file could not be downloaded. Try running the script again', $_.Exception)
Expand Down