@@ -1,6 +1,6 @@
#
#
# Fido v1.35 - Feature ISO Downloader, for retail Windows images and UEFI Shell
# Fido v1.46 - Feature ISO Downloader, for retail Windows images and UEFI Shell
# Copyright © 2019-2022 Pete Batard <pete@akeo.ie>
# Copyright © 2019-2023 Pete Batard <pete@akeo.ie>
# Command line support: Copyright © 2021 flx5
# Command line support: Copyright © 2021 flx5
# ConvertTo-ImageSource: Copyright © 2016 Chris Carter
# ConvertTo-ImageSource: Copyright © 2016 Chris Carter
#
#
@@ -24,9 +24,11 @@
#region Parameters
#region Parameters
param (
param (
# (Optional) The title to display on the application window.
# (Optional) The title to display on the application window.
[ string ] $AppTitle = " Fido - Retail Windows ISO Downloader " ,
[ string ] $AppTitle = " Fido - Feature ISO Downloader " ,
# (Optional) '|' separated UI localization strings.
# (Optional) '|' separated UI localization strings.
[ string ] $LocData ,
[ string ] $LocData ,
# (Optional) Forced locale
[ string ] $Locale = " en-US " ,
# (Optional) Path to a file that should be used for the UI icon.
# (Optional) Path to a file that should be used for the UI icon.
[ string ] $Icon ,
[ string ] $Icon ,
# (Optional) Name of a pipe the download URL should be sent to.
# (Optional) Name of a pipe the download URL should be sent to.
@@ -43,9 +45,9 @@ param(
# (Optional) Specify Windows architecture [Toggles commandline mode]
# (Optional) Specify Windows architecture [Toggles commandline mode]
[ string ] $Arch ,
[ string ] $Arch ,
# (Optional) Only display the download URL [Toggles commandline mode]
# (Optional) Only display the download URL [Toggles commandline mode]
[ switch ] $GetUrl = $F alse ,
[ switch ] $GetUrl = $f alse ,
# (Optional) Increase verbosity
# (Optional) Increase verbosity
[ switch ] $Verbose = $F alse
[ switch ] $Verbose = $f alse
)
)
#endregion
#endregion
@@ -53,42 +55,78 @@ try {
[ Console ] :: OutputEncoding = [ System.Text.Encoding ] :: UTF8
[ Console ] :: OutputEncoding = [ System.Text.Encoding ] :: UTF8
} catch { }
} catch { }
$Cmd = $F alse
$Cmd = $f alse
if ( $Win -or $Rel -or $Ed -or $Lang -or $Arch -or $GetUrl ) {
if ( $Win -or $Rel -or $Ed -or $Lang -or $Arch -or $GetUrl ) {
$Cmd = $T rue
$Cmd = $t rue
}
# Return a decimal Windows version that we can then check for platform support.
# Note that because we don't want to have to support this script on anything
# other than Windows, this call returns 0.0 for PowerShell running on Linux/Mac.
function Get-Platform-Version ( )
{
$version = 0.0
$platform = [ string][System.Environment ] :: OSVersion . Platform
# This will filter out non Windows platforms
if ( $platform . StartsWith ( " Win " ) ) {
# Craft a decimal numeric version of Windows
$version = [ System.Environment ] :: OSVersion . Version . Major * 1.0 + [ System.Environment ] :: OSVersion . Version . Minor * 0.1
}
return $version
}
$winver = Get-Platform -Version
# The default TLS for Windows 8.x doesn't work with Microsoft's servers so we must force it
if ( $winver -lt 10.0 ) {
[ Net.ServicePointManager ] :: SecurityProtocol = [ Net.SecurityProtocolType ] :: Tls -bor [ Net.SecurityProtocolType ] :: Tls11 -bor [ Net.SecurityProtocolType ] :: Tls12
}
}
#region Assembly Types
#region Assembly Types
$code = @"
$Drawing_Assembly = " System.Drawing "
[ D l l I m p o r t ( " s h e l l 3 2 . d l l " , C h a r S e t = C h a r S e t . A u t o , S e t L a s t E r r o r = t r u e , B e s t F i t M a p p i n g = f a l s e , T h r o w O n U n m a p p a b l e C h a r = t r u e ) ]
# PowerShell 7 altered the name of the Drawing assembly...
i n t e r n a l s t a t i c e x t e r n i n t E x t r a c t I c o n E x ( s t r i n g s F i l e , i n t i I n d e x , o u t I n t P t r p i L a r g e V e r s i o n , o u t I n t P t r p i S m a l l V e r s i o n , i n t a m o u n t I c o n s ) ;
if ( $host . version -ge " 7.0 " ) {
[ D l l I m p o r t ( " u s e r 3 2 . d l l " ) ]
$Drawing_Assembly + = " .Common "
p u b l i c s t a t i c e x t e r n b o o l S h o w W i n d o w ( I n t P t r h a n d l e , i n t s t a t e ) ;
}
/ / E x t r a c t a n i c o n f r o m a D L L
$Signature = @ {
p u b l i c s t a t i c I c o n E x t r a c t I c o n ( s t r i n g f i l e , i n t n u m b e r , b o o l l a r g e I c o n )
Namespace = " WinAPI "
{
Name = " Utils "
I n t P t r l a r g e , s m a l l ;
Language = " CSharp "
E x t r a c t I c o n E x ( f i l e , n u m b e r , o u t l a r g e , o u t s m a l l , 1 ) ;
UsingNamespace = " System.Runtime " , " System.IO " , " System.Text " , " System.Drawing " , " System.Globalization "
t r y {
ReferencedAssemblies = $Drawing_Assembly
r e t u r n I c o n . F r o m H a n d l e ( l a r g e I c o n ? l a r g e : s m a l l ) ;
ErrorAction = " Stop "
} c a t c h {
WarningAction = " Ignore "
r e t u r n n u l l ;
MemberDefinition = @"
[ D l l I m p o r t ( " s h e l l 3 2 . d l l " , C h a r S e t = C h a r S e t . A u t o , S e t L a s t E r r o r = t r u e , B e s t F i t M a p p i n g = f a l s e , T h r o w O n U n m a p p a b l e C h a r = t r u e ) ]
i n t e r n a l s t a t i c e x t e r n i n t E x t r a c t I c o n E x ( s t r i n g s F i l e , i n t i I n d e x , o u t I n t P t r p i L a r g e V e r s i o n , o u t I n t P t r p i S m a l l V e r s i o n , i n t a m o u n t I c o n s ) ;
[ D l l I m p o r t ( " u s e r 3 2 . d l l " ) ]
p u b l i c s t a t i c e x t e r n b o o l S h o w W i n d o w ( I n t P t r h a n d l e , i n t s t a t e ) ;
/ / E x t r a c t a n i c o n f r o m a D L L
p u b l i c s t a t i c I c o n E x t r a c t I c o n ( s t r i n g f i l e , i n t n u m b e r , b o o l l a r g e I c o n ) {
I n t P t r l a r g e , s m a l l ;
E x t r a c t I c o n E x ( f i l e , n u m b e r , o u t l a r g e , o u t s m a l l , 1 ) ;
t r y {
r e t u r n I c o n . F r o m H a n d l e ( l a r g e I c o n ? l a r g e : s m a l l ) ;
} c a t c h {
r e t u r n n u l l ;
}
}
}
}
"@
"@
}
if ( ! $Cmd ) {
if ( ! $Cmd ) {
Write-Host Please Wait . . .
Write-Host Please Wait . . .
$Drawing_Assembly = " System.Drawing "
# PowerShell 7 altered the name of the Drawing assembly...
if ( ! ( " WinAPI.Utils " -as [ type ] ) )
if ( $host . version -ge " 7.0 " ) {
{
$Drawing_Assembly + = " .Common "
Add-Type @Signature
}
}
Add-Type -ErrorAction Stop -WarningAction Ignore -IgnoreWarnings -MemberDefinition $code -Namespace Gui -UsingNamespace System . Runtime , System . IO , System . Text , System . Drawing , System . Globalization -ReferencedAssemblies $Drawing_Assembly -Name Utils
Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName PresentationFramework
# Hide the powershell window: https://stackoverflow.com/a/27992426/1069307
# Hide the powershell window: https://stackoverflow.com/a/27992426/1069307
[ Gui .Utils] :: ShowWindow ( ( [ System.Diagnostics.Process ] :: GetCurrentProcess ( ) | Get-Process ) . MainWindowHandle , 0 ) | Out-Null
[ WinAPI .Utils] :: ShowWindow ( ( [ System.Diagnostics.Process ] :: GetCurrentProcess ( ) | Get-Process ) . MainWindowHandle , 0 ) | Out-Null
}
}
#endregion
#endregion
@@ -103,11 +141,6 @@ $WindowsVersions = @(
@ ( " Windows 11 Home/Pro/Edu " , 2370 ) ,
@ ( " Windows 11 Home/Pro/Edu " , 2370 ) ,
@ ( " Windows 11 Home China " , ( $zh + 2371 ) )
@ ( " Windows 11 Home China " , ( $zh + 2371 ) )
) ,
) ,
@ (
" 22H2 (Build 22621.382 - 2022.09) " ,
@ ( " Windows 11 Home/Pro/Edu " , 2360 ) ,
@ ( " Windows 11 Home China " , ( $zh + 2361 ) )
) ,
@ (
@ (
" 21H2 v1 (Build 22000.318 - 2021.11) " ,
" 21H2 v1 (Build 22000.318 - 2021.11) " ,
@ ( " Windows 11 Home/Pro/Edu " , 2093 ) ,
@ ( " Windows 11 Home/Pro/Edu " , 2093 ) ,
@@ -121,12 +154,11 @@ $WindowsVersions = @(
) ,
) ,
@ (
@ (
@ ( " Windows 10 " , " Windows10ISO " ) ,
@ ( " Windows 10 " , " Windows10ISO " ) ,
# Not yet enabled by Microsoft...
@ (
# @(
" 22H2 (Build 19045.2006 - 2022.10) " ,
# "22H2 (Build 1904?.???? - 2022.10)" ,
@ ( " Windows 10 Home/Pro/Edu " , 2377 ) ,
# @(" Windows 10 Home/Pro/Edu", 2377),
@ ( " Windows 10 Home China " , ( $zh + 2378 ) )
# @("Windows 10 Home China ", ($zh + 2378))
) ,
# ),
@ (
@ (
" 21H2 (Build 19044.1288 - 2021.11) " ,
" 21H2 (Build 19044.1288 - 2021.11) " ,
@ ( " Windows 10 Home/Pro/Edu " , 2084 ) ,
@ ( " Windows 10 Home/Pro/Edu " , 2084 ) ,
@@ -279,17 +311,13 @@ $WindowsVersions = @(
@ ( " Windows 8.1 KN " , ( $ko + 62 ) )
@ ( " Windows 8.1 KN " , ( $ko + 62 ) )
)
)
) ,
) ,
@ (
@ ( " Windows 7 " , " WIN7 " ) ,
@ (
" with SP1 (build 7601) " ,
@ ( " Windows 7 Ultimate " , 0 ) ,
@ ( " Windows 7 Professional " , 1 ) ,
@ ( " Windows 7 Home Premium " , 2 )
)
) ,
@ (
@ (
@ ( " UEFI Shell 2.2 " , " UEFI_SHELL 2.2 " ) ,
@ ( " UEFI Shell 2.2 " , " UEFI_SHELL 2.2 " ) ,
@ (
" 22H2 (edk2-stable202211) " ,
@ ( " Release " , 0 ) ,
@ ( " Debug " , 1 )
) ,
@ (
@ (
" 22H1 (edk2-stable202205) " ,
" 22H1 (edk2-stable202205) " ,
@ ( " Release " , 0 ) ,
@ ( " Release " , 0 ) ,
@@ -319,42 +347,6 @@ $WindowsVersions = @(
)
)
)
)
)
)
$Windows7Versions = @ (
# 0: Windows 7 Ultimate
@ (
# Need a dummy to prevent PS from coalescing single array entries
@ ( " " ) ,
@ ( " English (US) " , " en-us " ,
@ (
@ ( " x64 " , " https://download.microsoft.com/download/5/1/9/5195A765-3A41-4A72-87D8-200D897CBE21/7601.24214.180801-1700.win7sp1_ldr_escrow_CLIENT_ULTIMATE_x64FRE_en-us.iso " ) ,
@ ( " x86 " , " https://download.microsoft.com/download/1/E/6/1E6B4803-DD2A-49DF-8468-69C0E6E36218/7601.24214.180801-1700.win7sp1_ldr_escrow_CLIENT_ULTIMATE_x86FRE_en-us.iso " )
)
)
) ,
# 1: Windows 7 Profesional
@ (
@ ( " " ) ,
@ ( " English (US) " , " en-us " ,
@ (
@ ( " x64 " , " https://download.microsoft.com/download/0/6/3/06365375-C346-4D65-87C7-EE41F55F736B/7601.24214.180801-1700.win7sp1_ldr_escrow_CLIENT_PROFESSIONAL_x64FRE_en-us.iso " ) ,
@ ( " x86 " , " https://download.microsoft.com/download/C/0/6/C067D0CD-3785-4727-898E-60DC3120BB14/7601.24214.180801-1700.win7sp1_ldr_escrow_CLIENT_PROFESSIONAL_x86FRE_en-us.iso " )
)
)
) ,
# 2: Windows 7 Home Premium
@ (
@ ( " " ) ,
@ ( " English (US) " , " en-us " ,
@ (
@ ( " x64 " , " https://download.microsoft.com/download/E/A/8/EA804D86-C3DF-4719-9966-6A66C9306598/7601.24214.180801-1700.win7sp1_ldr_escrow_CLIENT_HOMEPREMIUM_x64FRE_en-us.iso " ) ,
@ ( " x86 " , " https://download.microsoft.com/download/E/D/A/EDA6B508-7663-4E30-86F9-949932F443D0/7601.24214.180801-1700.win7sp1_ldr_escrow_CLIENT_HOMEPREMIUM_x86FRE_en-us.iso " )
)
)
)
)
#endregion
#endregion
#region Functions
#region Functions
@@ -404,9 +396,9 @@ function Select-Language([string]$LangName)
( $SysLocale . StartsWith ( " tr " ) -and $LangName -like " *Turk* " ) -or `
( $SysLocale . StartsWith ( " tr " ) -and $LangName -like " *Turk* " ) -or `
( $SysLocale . StartsWith ( " uk " ) -and $LangName -like " *Ukrain* " ) -or `
( $SysLocale . StartsWith ( " uk " ) -and $LangName -like " *Ukrain* " ) -or `
( $SysLocale . StartsWith ( " vi " ) -and $LangName -like " *Vietnam* " ) ) {
( $SysLocale . StartsWith ( " vi " ) -and $LangName -like " *Vietnam* " ) ) {
return $T rue
return $t rue
}
}
return $F alse
return $f alse
}
}
function Add-Entry([int]$pos , [ string ] $Name , [ array ] $Items , [ string ] $DisplayName )
function Add-Entry([int]$pos , [ string ] $Name , [ array ] $Items , [ string ] $DisplayName )
@@ -498,8 +490,8 @@ function ConvertTo-ImageSource
function Throw-Error([object]$Req , [ string ] $Alt )
function Throw-Error([object]$Req , [ string ] $Alt )
{
{
$Err = $ ( GetElementById -Request $r -Id " errorModalMessage " ) . innerText
$Err = $ ( GetElementById -Request $Req -Id " errorModalMessage " ) . innerText -replace " <[^>]+> " -replace " \s+ " , " "
if ( -not $Err ) {
if ( ! $Err ) {
$Err = $Alt
$Err = $Alt
} else {
} else {
$Err = [ System.Text.Encoding ] :: UTF8 . GetString ( [ byte[]][char[] ] $Err )
$Err = [ System.Text.Encoding ] :: UTF8 . GetString ( [ byte[]][char[] ] $Err )
@@ -510,7 +502,7 @@ function Throw-Error([object]$Req, [string]$Alt)
# Translate a message string
# Translate a message string
function Get-Translation([string]$Text )
function Get-Translation([string]$Text )
{
{
if ( -not $English -contains $Text ) {
if ( ! ( $English -contains $Text ) ) {
Write-Host " Error: ' $Text ' is not a translatable string "
Write-Host " Error: ' $Text ' is not a translatable string "
return " (Untranslated) "
return " (Untranslated) "
}
}
@@ -548,7 +540,7 @@ function Error([string]$ErrorMessage)
if ( ! $Cmd ) {
if ( ! $Cmd ) {
$XMLForm . Title = $ ( Get-Translation ( " Error " ) ) + " : " + $ErrorMessage
$XMLForm . Title = $ ( Get-Translation ( " Error " ) ) + " : " + $ErrorMessage
Refresh-Control ( $XMLForm )
Refresh-Control ( $XMLForm )
$XMLGrid . Children [ 2 * $script:Stage + 1 ] . IsEnabled = $T rue
$XMLGrid . Children [ 2 * $script:Stage + 1 ] . IsEnabled = $t rue
$UserInput = [ System.Windows.MessageBox ] :: Show ( $XMLForm . Title , $ ( Get-Translation ( " Error " ) ) , " OK " , " Error " )
$UserInput = [ System.Windows.MessageBox ] :: Show ( $XMLForm . Title , $ ( Get-Translation ( " Error " ) ) , " OK " , " Error " )
$script:ExitCode = $script:Stage - -
$script:ExitCode = $script:Stage - -
} else {
} else {
@@ -594,14 +586,14 @@ if ($Cmd) {
$MaxStage = 4
$MaxStage = 4
$SessionId = [ guid ] :: NewGuid ( )
$SessionId = [ guid ] :: NewGuid ( )
$ExitCode = 100
$ExitCode = 100
$Locale = " en-US "
$Locale = $Locale
$RequestData = @ { }
$RequestData = @ { }
# This GUID applies to all visitors, regardless of their locale
# This GUID applies to all visitors, regardless of their locale
$RequestData [ " GetLangs " ] = @ ( " a8f8f489-4c7f-463a-9ca6-5cff94d8d041 " , " getskuinformationbyproductedition " )
$RequestData [ " GetLangs " ] = @ ( " a8f8f489-4c7f-463a-9ca6-5cff94d8d041 " , " getskuinformationbyproductedition " )
# This GUID applies to visitors of the en-US download page. Other locales may get a different GUID.
# This GUID applies to visitors of the en-US download page. Other locales may get a different GUID.
$RequestData [ " GetLinks " ] = @ ( " 6e2a1789-ef16-4f27-a296-74ef7ef5d96b " , " GetProductDownloadLinksBySku " )
$RequestData [ " GetLinks " ] = @ ( " 6e2a1789-ef16-4f27-a296-74ef7ef5d96b " , " GetProductDownloadLinksBySku " )
# Create a semi-random Linux User-Agent string
# Create a semi-random Linux User-Agent string
$FirefoxVersion = Get-Random -Minimum 5 0 -Maximum 9 0
$FirefoxVersion = Get-Random -Minimum 9 0 -Maximum 11 0
$FirefoxDate = Get-RandomDate
$FirefoxDate = Get-RandomDate
$UserAgent = " Mozilla/5.0 (X11; Linux i586; rv: $FirefoxVersion .0) Gecko/ $FirefoxDate Firefox/ $FirefoxVersion .0 "
$UserAgent = " Mozilla/5.0 (X11; Linux i586; rv: $FirefoxVersion .0) Gecko/ $FirefoxDate Firefox/ $FirefoxVersion .0 "
$Verbosity = 2
$Verbosity = 2
@@ -616,30 +608,25 @@ if ($Cmd) {
# Localization
# Localization
$EnglishMessages = " en-US|Version|Release|Edition|Language|Architecture|Download|Continue|Back|Close|Cancel|Error|Please wait...| " +
$EnglishMessages = " en-US|Version|Release|Edition|Language|Architecture|Download|Continue|Back|Close|Cancel|Error|Please wait...| " +
" Download using a browser|Temporarily banned by Microsoft for requesting too many downloads - Please try again later.. .| " +
" Download using a browser|Download of Windows ISOs is unavailable due to Microsoft having altered their website to prevent it .| " +
" PowerShell 3.0 or later is required to run this script.|Do you want to go online and download it? "
" PowerShell 3.0 or later is required to run this script.|Do you want to go online and download it?| " +
" This feature is not available on this platform. "
[ string[] ] $English = $EnglishMessages . Split ( '|' )
[ string[] ] $English = $EnglishMessages . Split ( '|' )
[ string[] ] $Localized = $null
[ string[] ] $Localized = $null
if ( $LocData -and ( -not $LocData . StartsWith ( " en-US " ) ) ) {
if ( $LocData -and ! $LocData . StartsWith ( " en-US " ) ) {
$Localized = $LocData . Split ( '|' )
$Localized = $LocData . Split ( '|' )
if ( $Localized . Length -ne $English . Length ) {
# Adjust the $Localized array if we have more or fewer strings than in $EnglishMessages
Write-Host " Error: Missing or extra translated messages provided ( $ ( $Localized . Length) / $( $English . Length ) ) "
if ($Localized . Length -lt $English . Length ) {
exit 101
while ( $Localized . Length -ne $English . Length ) {
$Localized + = $English [ $Localized . Length ]
}
} elseif ( $Localized . Length -gt $English . Length ) {
$Localized = $LocData . Split ( '|' ) [ 0 . . ( $English . Length - 1 ) ]
}
}
$Locale = $Localized [ 0 ]
$Locale = $Localized [ 0 ]
}
}
$QueryLocale = $Locale
$QueryLocale = $Locale
# Make sure PowerShell 3.0 or later is used (for Invoke-WebRequest)
if ( $PSVersionTable . PSVersion . Major -lt 3 ) {
Write-Host Error : PowerShell 3.0 or later is required to run this script .
$Msg = " $( Get-Translation ( $English [ 15 ] ) ) `n $( Get-Translation ( $English [ 16 ] ) ) "
if ( [ System.Windows.MessageBox ] :: Show ( $Msg , $ ( Get-Translation ( " Error " ) ) , " YesNo " , " Error " ) -eq " Yes " ) {
Start-Process -FilePath https : / / www . microsoft . com / download / details . aspx ? id = 34595
}
exit 102
}
# Convert a size in bytes to a human readable string
# Convert a size in bytes to a human readable string
function Size-To-Human-Readable([uint64]$size )
function Size-To-Human-Readable([uint64]$size )
{
{
@@ -653,7 +640,8 @@ function Size-To-Human-Readable([uint64]$size)
}
}
# Check if the locale we want is available - Fall back to en-US otherwise
# Check if the locale we want is available - Fall back to en-US otherwise
function Check-Locale {
function Check-Locale
{
try {
try {
$url = " https://www.microsoft.com/ " + $QueryLocale + " /software-download/ "
$url = " https://www.microsoft.com/ " + $QueryLocale + " /software-download/ "
if ( $Verbosity -ge 2 ) {
if ( $Verbosity -ge 2 ) {
@@ -709,6 +697,17 @@ function Get-Windows-Languages([int]$SelectedVersion, [int]$SelectedEdition)
} elseif ( $WindowsVersions [ $SelectedVersion ] [ 0 ] [ 1 ] . StartsWith ( " UEFI_SHELL " ) ) {
} elseif ( $WindowsVersions [ $SelectedVersion ] [ 0 ] [ 1 ] . StartsWith ( " UEFI_SHELL " ) ) {
$languages + = @ ( New-Object PsObject -Property @ { DisplayLanguage = " English (US) " ; Language = " en-us " ; Id = 0 } )
$languages + = @ ( New-Object PsObject -Property @ { DisplayLanguage = " English (US) " ; Language = " en-us " ; Id = 0 } )
} else {
} else {
# Microsoft download protection now requires the sessionId to be whitelisted through vlscppe.microsoft.com/tags
$url = " https://vlscppe.microsoft.com/tags?org_id=y6jn8c31&session_id= " + $SessionId
if ( $Verbosity -ge 2 ) {
Write-Host Querying $url
}
try {
Invoke-WebRequest -UseBasicParsing -MaximumRedirection 0 -UserAgent $UserAgent $url | Out-Null
} catch {
Error ( $_ . Exception . Message )
return @ ( )
}
$url = " https://www.microsoft.com/ " + $QueryLocale + " /api/controls/contentinclude/html "
$url = " https://www.microsoft.com/ " + $QueryLocale + " /api/controls/contentinclude/html "
$url + = " ?pageId= " + $RequestData [ " GetLangs " ] [ 0 ]
$url + = " ?pageId= " + $RequestData [ " GetLangs " ] [ 0 ]
$url + = " &host=www.microsoft.com "
$url + = " &host=www.microsoft.com "
@@ -723,11 +722,12 @@ function Get-Windows-Languages([int]$SelectedVersion, [int]$SelectedEdition)
$script:SelectedIndex = 0
$script:SelectedIndex = 0
try {
try {
$r = Invoke-WebRequest -UseBasicParsing -UserAgent $UserAgent -SessionVariable " Session " $url
$r = Invoke-WebRequest -Method Post -UseBasicParsing -UserAgent $UserAgent -SessionVariable " Session " $url
if ( $r -match " errorModalMessage " ) {
if ( $r -match " errorModalMessage " ) {
Throw-Error -Req $r -Alt " Could not retrieve languages from server "
Throw-Error -Req $r -Alt " Could not retrieve languages from server "
}
}
$pattern = '(?s)<select id="product-languages">(.*)?</select>'
$r = $r -replace " `n " -replace " `r "
$pattern = '.*<select id="product-languages"[^>]*>(.*)</select>.*'
$html = [ regex ] :: Match ( $r , $pattern ) . Groups [ 1 ] . Value
$html = [ regex ] :: Match ( $r , $pattern ) . Groups [ 1 ] . Value
# Go through an XML conversion to keep all PowerShells happy...
# Go through an XML conversion to keep all PowerShells happy...
$html = $html . Replace ( " selected value " , " value " )
$html = $html . Replace ( " selected value " , " value " )
@@ -810,20 +810,18 @@ function Get-Windows-Download-Links([int]$SelectedVersion, [int]$SelectedRelease
try {
try {
$Is64 = [ Environment ] :: Is64BitOperatingSystem
$Is64 = [ Environment ] :: Is64BitOperatingSystem
# Must add a referer for POST requests , else Microsoft's servers will deny them
# Must add a referer for this request, else Microsoft's servers will deny i t
$ref = " https://www.microsoft.com/software-download/windows11 "
$ref = " https://www.microsoft.com/software-download/windows11 "
$w r = [ System.Net.WebRequest ] :: Create ( $url )
$r = Invoke-WebRequest -Method Post -Headers @ { " Referer " = $ref } -UseBasicParsing -UserAgent $UserAgent -WebSession $Session $url
# Windows 7 PowerShell doesn't support 'Invoke-WebRequest -Headers @{"Referer" = $ref}'
# (produces "The 'Referer' header must be modified using the appropriate property or method")
# so we use StreamReader() with GetResponseStream() and do this whole gymkhana instead...
$wr . Method = " POST "
$wr . Referer = $ref
$wr . UserAgent = $UserAgent
$wr . ContentLength = 0
$sr = New-Object System . IO . StreamReader ( $wr . GetResponse ( ) . GetResponseStream ( ) )
$r = $sr . ReadToEnd ( )
if ( $r -match " errorModalMessage " ) {
if ( $r -match " errorModalMessage " ) {
Throw-Error -Req $r -Alt " Could not retrieve architectures from server "
$Alt = [ regex ] :: Match ( $r . Content , '<p id="errorModalMessage">(.+?)<\/p>' ) . Groups [ 1 ] . Value -replace " <[^>]+> " -replace " \s+ " , " " -replace " \?\?\? " , " - "
$Alt = [ System.Text.Encoding ] :: UTF8 . GetString ( [ byte[]][char[] ] $Alt )
if ( ! $Alt ) {
$Alt = " Could not retrieve architectures from server "
} elseif ( $Alt -match " 715-123130 " ) {
$Alt + = " " + $SessionId + " . "
}
Throw-Error -Req $r -Alt $Alt
}
}
$pattern = '(?s)(<input.*?></input>)'
$pattern = '(?s)(<input.*?></input>)'
ForEach-Object { [ regex ] :: Matches ( $r , $pattern ) } | ForEach-Object { $html + = $_ . Groups [ 1 ] . value }
ForEach-Object { [ regex ] :: Matches ( $r , $pattern ) } | ForEach-Object { $html + = $_ . Groups [ 1 ] . value }
@@ -838,7 +836,7 @@ function Get-Windows-Download-Links([int]$SelectedVersion, [int]$SelectedRelease
foreach ( $var in $xml . inputs . input ) {
foreach ( $var in $xml . inputs . input ) {
$json = $var . value | ConvertFrom-Json ;
$json = $var . value | ConvertFrom-Json ;
if ( $json ) {
if ( $json ) {
if ( ( $Is64 -and $json . DownloadType -eq " x64 " ) -or ( -not $Is64 -and $json . DownloadType -eq " x86 " ) ) {
if ( ( $Is64 -and $json . DownloadType -eq " x64 " ) -or ( ! $Is64 -and $json . DownloadType -eq " x86 " ) ) {
$script:SelectedIndex = $i
$script:SelectedIndex = $i
}
}
$links + = @ ( New-Object PsObject -Property @ { Type = $json . DownloadType ; Link = $json . Uri } )
$links + = @ ( New-Object PsObject -Property @ { Type = $json . DownloadType ; Link = $json . Uri } )
@@ -860,7 +858,7 @@ function Get-Windows-Download-Links([int]$SelectedVersion, [int]$SelectedRelease
function Process-Download-Link([string]$Url )
function Process-Download-Link([string]$Url )
{
{
try {
try {
if ( $PipeName -and -not $Check . IsChecked ) {
if ( $PipeName -and ! $Check . IsChecked ) {
Send-Message -PipeName $PipeName -Message $Url
Send-Message -PipeName $PipeName -Message $Url
} else {
} else {
if ( $Cmd ) {
if ( $Cmd ) {
@@ -871,7 +869,7 @@ function Process-Download-Link([string]$Url)
$tmp_size = [ uint64 ] :: Parse ( $str_size )
$tmp_size = [ uint64 ] :: Parse ( $str_size )
$Size = Size-To -Human -Readable $tmp_size
$Size = Size-To -Human -Readable $tmp_size
Write-Host " Downloading ' $File ' ( $Size )... "
Write-Host " Downloading ' $File ' ( $Size )... "
Invoke-WebRequest -UseBasicParsing -Uri $Url -OutFile $File
Start-BitsTransfer -Source $Url -Destination $File
} else {
} else {
Write-Host Download Link : $Url
Write-Host Download Link : $Url
Start-Process -FilePath $Url
Start-Process -FilePath $Url
@@ -892,6 +890,12 @@ if ($Cmd) {
$winLanguageName = $null
$winLanguageName = $null
$winLink = $null
$winLink = $null
# Windows 7 and non Windows platforms are too much of a liability
if ( $winver -le 6.1 ) {
Error ( Get-Translation ( " This feature is not available on this platform. " ) )
exit 403
}
$i = 0
$i = 0
$Selected = " "
$Selected = " "
if ( $Win -eq " List " ) {
if ( $Win -eq " List " ) {
@@ -952,7 +956,7 @@ if ($Cmd) {
if ( ! $Ed -and $Verbosity -ge 1 ) {
if ( ! $Ed -and $Verbosity -ge 1 ) {
Write-Host " No edition specified (-Ed). Defaulting to ' $( $edition . Edition ) '. "
Write-Host " No edition specified (-Ed). Defaulting to ' $( $edition . Edition ) '. "
}
}
$Selected + = " , " + $edition . Edition -replace " Windows [0-9\.]* " , " "
$Selected + = " , " + $edition . Edition -replace " Windows [0-9\.]* "
$winEditionId = $edition . Id
$winEditionId = $edition . Id
break ;
break ;
}
}
@@ -1050,7 +1054,7 @@ $XMLForm.Title = $AppTitle
if ( $Icon ) {
if ( $Icon ) {
$XMLForm . Icon = $Icon
$XMLForm . Icon = $Icon
} else {
} else {
$XMLForm . Icon = [ Gui .Utils] :: ExtractIcon ( " shell32 .dll" , -41 , $true ) | ConvertTo-ImageSource
$XMLForm . Icon = [ WinAPI .Utils] :: ExtractIcon ( " imageres .dll" , -5205 , $true ) | ConvertTo-ImageSource
}
}
if ( $Locale . StartsWith ( " ar " ) -or $Locale . StartsWith ( " fa " ) -or $Locale . StartsWith ( " he " ) ) {
if ( $Locale . StartsWith ( " ar " ) -or $Locale . StartsWith ( " fa " ) -or $Locale . StartsWith ( " he " ) ) {
$XMLForm . FlowDirection = " RightToLeft "
$XMLForm . FlowDirection = " RightToLeft "
@@ -1059,6 +1063,12 @@ $WindowsVersionTitle.Text = Get-Translation("Version")
$Continue . Content = Get-Translation ( " Continue " )
$Continue . Content = Get-Translation ( " Continue " )
$Back . Content = Get-Translation ( " Close " )
$Back . Content = Get-Translation ( " Close " )
# Windows 7 and non Windows platforms are too much of a liability
if ( $winver -le 6.1 ) {
Error ( Get-Translation ( " This feature is not available on this platform. " ) )
exit 403
}
# Populate the Windows versions
# Populate the Windows versions
$i = 0
$i = 0
$versions = @ ( )
$versions = @ ( )
@@ -1072,9 +1082,9 @@ $WindowsVersion.DisplayMemberPath = "Version"
# Button Action
# Button Action
$Continue . add_click ( {
$Continue . add_click ( {
$script:Stage + +
$script:Stage + +
$XMLGrid . Children [ 2 * $Stage + 1 ] . IsEnabled = $F alse
$XMLGrid . Children [ 2 * $Stage + 1 ] . IsEnabled = $f alse
$Continue . IsEnabled = $F alse
$Continue . IsEnabled = $f alse
$Back . IsEnabled = $F alse
$Back . IsEnabled = $f alse
Refresh-Control ( $Continue )
Refresh-Control ( $Continue )
Refresh-Control ( $Back )
Refresh-Control ( $Back )
@@ -1083,7 +1093,7 @@ $Continue.add_click({
1 { # Windows Version selection
1 { # Windows Version selection
$XMLForm . Title = Get-Translation ( $English [ 12 ] )
$XMLForm . Title = Get-Translation ( $English [ 12 ] )
Refresh-Control ( $XMLForm )
Refresh-Control ( $XMLForm )
if ( $WindowsVersion . SelectedValue . Version . StartsWith ( " Windows " ) -and $WindowsVersion . SelectedValue . Version -ne " Windows 7 " ) {
if ( $WindowsVersion . SelectedValue . Version . StartsWith ( " Windows " ) ) {
Check-Locale
Check-Locale
}
}
$releases = Get-Windows -Releases $WindowsVersion . SelectedValue . Index
$releases = Get-Windows -Releases $WindowsVersion . SelectedValue . Index
@@ -1142,9 +1152,9 @@ $Continue.add_click({
$XMLForm . Close ( )
$XMLForm . Close ( )
}
}
}
}
$Continue . IsEnabled = $T rue
$Continue . IsEnabled = $t rue
if ( $Stage -ge 0 ) {
if ( $Stage -ge 0 ) {
$Back . IsEnabled = $T rue
$Back . IsEnabled = $t rue
}
}
} )
} )
@@ -1154,7 +1164,7 @@ $Back.add_click({
} else {
} else {
$XMLGrid . Children . RemoveAt ( 2 * $Stage + 3 )
$XMLGrid . Children . RemoveAt ( 2 * $Stage + 3 )
$XMLGrid . Children . RemoveAt ( 2 * $Stage + 2 )
$XMLGrid . Children . RemoveAt ( 2 * $Stage + 2 )
$XMLGrid . Children [ 2 * $Stage + 1 ] . IsEnabled = $T rue
$XMLGrid . Children [ 2 * $Stage + 1 ] . IsEnabled = $t rue
$dh2 = $dh
$dh2 = $dh
if ( $Stage -eq 4 -and $PipeName ) {
if ( $Stage -eq 4 -and $PipeName ) {
$Check . Visibility = " Collapsed "
$Check . Visibility = " Collapsed "
@@ -1179,7 +1189,7 @@ $Back.add_click({
} )
} )
# Display the dialog
# Display the dialog
$XMLForm . Add_Loaded ( { $XMLForm . Activate ( ) } )
$XMLForm . Add_Loaded ( { $XMLForm . Activate ( ) } )
$XMLForm . ShowDialog ( ) | Out-Null
$XMLForm . ShowDialog ( ) | Out-Null
# Clean up & exit
# Clean up & exit
@@ -1188,8 +1198,8 @@ exit $ExitCode
# SIG # Begin signature block
# SIG # Begin signature block
# MIIkWQYJKoZIhvcNAQcCoIIkSjCCJEYCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# MIIkWQYJKoZIhvcNAQcCoIIkSjCCJEYCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBY/5IAG/GViBcd
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAXwtxm+mYAZToF
# 1JTY1vmyD3aBIuP9LO6GCK/ojLlAlK CCElkwggVvMIIEV6ADAgECAhBI/JO0YFWU
# MN/W9BVxYssBdJgHpUBa5KaOnXxeka CCElkwggVvMIIEV6ADAgECAhBI/JO0YFWU
# jTanyYqJ1pQWMA0GCSqGSIb3DQEBDAUAMHsxCzAJBgNVBAYTAkdCMRswGQYDVQQI
# jTanyYqJ1pQWMA0GCSqGSIb3DQEBDAUAMHsxCzAJBgNVBAYTAkdCMRswGQYDVQQI
# DBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoM
# DBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoM
# EUNvbW9kbyBDQSBMaW1pdGVkMSEwHwYDVQQDDBhBQUEgQ2VydGlmaWNhdGUgU2Vy
# EUNvbW9kbyBDQSBMaW1pdGVkMSEwHwYDVQQDDBhBQUEgQ2VydGlmaWNhdGUgU2Vy
@@ -1292,23 +1302,23 @@ exit $ExitCode
# aWMgQ29kZSBTaWduaW5nIENBIEVWIFIzNgIRAL+xUAG79ZLUlip3l+pzb6MwDQYJ
# aWMgQ29kZSBTaWduaW5nIENBIEVWIFIzNgIRAL+xUAG79ZLUlip3l+pzb6MwDQYJ
# YIZIAWUDBAIBBQCgfDAQBgorBgEEAYI3AgEMMQIwADAZBgkqhkiG9w0BCQMxDAYK
# YIZIAWUDBAIBBQCgfDAQBgorBgEEAYI3AgEMMQIwADAZBgkqhkiG9w0BCQMxDAYK
# KwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG
# KwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG
# 9w0BCQQxIgQgNcSdxNkDC+T0P75/9E4SzKGSNuqQIeqogrTBOhm8Qic wDQYJKoZI
# 9w0BCQQxIgQgkLJ7KpFnRXWMO8X7vU/I7Q3jtnRJIa2M3A+9pgWOFio wDQYJKoZI
# hvcNAQEBBQAEggIABeOCwDNendZb+8jZ1AhX5gYbY2KMZiCzIFV1XcegsgAkEaHx
# hvcNAQEBBQAEggIAQGV7TPwZw904Z5j2/ahvb7kpVdcm89xya4cTxreS6h0S11+T
# k7nr6A8EePp1AApRrsD11l4Ldc13tIkcgE48FgT98yPqJVQdNm7eTgmNE/hbGW1v
# DHXNDzKE9RkE8i3WaHcJyUKOAGXSeD27Vn4xcAvHOSGv2OxaST3/BN+rpxccngPd
# fTX1SjBmeDgahx/XQszCMZ3c6+po7OQPbACt0ovzDXWnu5mQHuvqSrCw8G/uN/zb
# PhGOY8YIp9AWtCupGOanWxgUlr9ixSFgYZmd3pxNz8fgNi9sTU0uRwIlXd0Mjj3m
# N6uu6FlN+nM7MCPQkbf4x9IOWyfiVziUTmM8XO7JtySCt1oa49RtimRYYSbI2zZh
# a7svCTZhs2gKYDwSwVuHDG3EV4oOEKF2SvdIcACWO4uedi0M7VebGdgQ+H8+b26Z
# uiqrl4pmdB86g8atK4BhedU1g6fKp23Qk+qo+w8eHSGTfPrz5YsGQtpTgpZxp50T
# y6C8WPG3BUk/qlkqjusfB11WfKMlYrlnYhGfdnM1VrBQKQEODaNHszYoOtL92Pen
# pkcbj96entuv/hbj4Vn/j1xB0rwnQRCtGeSYgZMDYFIC8FHFz19TvlwAsDOGBTK/
# 8mGqRZUMQCU+Hwb9ArtHckaHDAYXTgwNzqlqQOZlhfxiuwEssGjVE45oQabv8fRq
# Q2e1/yMctzT6YX6k5K7eIk0p6tWh1kqd6AZB+3kjJv52wJQ+cvaVgmI+hWoyQYJ6
# rQfwI4oYM9Y1WEjlTBvTi3GQgb/NuvWKOh8YnbFWWq+QFRG73Egn/uicrPxIgDoy
# O7gC0MG0d+ohF2YuUEyhBQRn+QJ/9u+g4KiFoqBTXr697viAIaTeY//hpbL1S1RI
# wt8PE09PGhJQ+qVyhqrUeeSF+j0evA6E2pUmP49ZLBsKthhYEI1h5JPMBgxkuXC4
# IdDbAr063jxYOykSIhdydRWhrw01slvIKr1o13s/6iDgSPTRd723Wv3dld/I6w5/
# 5ZfkVCALwOZ/LD4vRMZBghXQbAI5WvjB+iObSEO9MtoI/MPMDKyOfEueYDb2nroL
# zIoa+3PpyxoYb8RvP5eqgEAbHEteBc8KuNp55WaFUKb8K6UlHDHGsgAgcZboD2T5
# d3R98omGWCLoCCr+BLg+XjZQWliSUs8L/sNAUlBb1S0kWwpSND+NUHed4VEnS14H
# 6N0FOz+v1Cznbsv0USQdynh4DQSAcIB9klcOkkoAlsgQH74k4EyusV/29iW hgg49
# Rtn3Cx2H7WgHeQSfiOPDcYtTqHz48RHuhd2C+v+NiPKgkOtTxLH7H6BlW96 hgg49
# MIIOOQYKKwYBBAGCNwMDATGCDikwgg4lBgkqhkiG9w0BBwKggg4WMIIOEgIBAzEN
# MIIOOQYKKwYBBAGCNwMDATGCDikwgg4lBgkqhkiG9w0BBwKggg4WMIIOEgIBAzEN
# MAsGCWCGSAFlAwQCATCCAQ8GCyqGSIb3DQEJEAEEoIH/BIH8MIH5AgEBBgtghkgB
# MAsGCWCGSAFlAwQCATCCAQ8GCyqGSIb3DQEJEAEEoIH/BIH8MIH5AgEBBgtghkgB
# hvhFAQcXAzAxMA0GCWCGSAFlAwQCAQUABCAmmVONt91+fvut9U75MR5SgbgybtGV
# hvhFAQcXAzAxMA0GCWCGSAFlAwQCAQUABCAafKvrRkdVxwCF6brdFdzfTfKcBENE
# mK0CngIkWNBScQIVAPwPX0skCWZcVxSwVijYEseWntqDGA8yMDIyMTAwMTEyNTQ0
# HXM7VdQTxnUxUwIVANS/ey8tLSQ9LlI0IgAcicapMC63GA8yMDIzMDUxNTEwNDE1
# M1 owAwIBHqCBhqSBgzCBgDELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVj
# NF owAwIBHqCBhqSBgzCBgDELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVj
# IENvcnBvcmF0aW9uMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTEw
# IENvcnBvcmF0aW9uMR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3JrMTEw
# LwYDVQQDEyhTeW1hbnRlYyBTSEEyNTYgVGltZVN0YW1waW5nIFNpZ25lciAtIEcz
# LwYDVQQDEyhTeW1hbnRlYyBTSEEyNTYgVGltZVN0YW1waW5nIFNpZ25lciAtIEcz
# oIIKizCCBTgwggQgoAMCAQICEHsFsdRJaFFE98mJ0pwZnRIwDQYJKoZIhvcNAQEL
# oIIKizCCBTgwggQgoAMCAQICEHsFsdRJaFFE98mJ0pwZnRIwDQYJKoZIhvcNAQEL
@@ -1371,13 +1381,13 @@ exit $ExitCode
# BgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYDVQQLExZTeW1hbnRlYyBU
# BgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMR8wHQYDVQQLExZTeW1hbnRlYyBU
# cnVzdCBOZXR3b3JrMSgwJgYDVQQDEx9TeW1hbnRlYyBTSEEyNTYgVGltZVN0YW1w
# cnVzdCBOZXR3b3JrMSgwJgYDVQQDEx9TeW1hbnRlYyBTSEEyNTYgVGltZVN0YW1w
# aW5nIENBAhB71OWvuswHP6EBIwQiQU0SMAsGCWCGSAFlAwQCAaCBpDAaBgkqhkiG
# aW5nIENBAhB71OWvuswHP6EBIwQiQU0SMAsGCWCGSAFlAwQCAaCBpDAaBgkqhkiG
# 9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTIyMTAwMTEyNTQ0
# 9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTIzMDUxNTEwNDE1
# M1 owLwYJKoZIhvcNAQkEMSIEIN6q/xtR2+ZALUnoqNXx196zuj9xFk7Ajyd8CrCr
# NF owLwYJKoZIhvcNAQkEMSIEIL8/K60mXh1FyzaYk4hwVgMOGPKp8M9K7pisnqDz
# WmI8 MDcGCyqGSIb3DQEJEAIvMSgwJjAkMCIEIMR0znYAfQI5Tg2l5N58FMaA+eKC
# cLTt MDcGCyqGSIb3DQEJEAIvMSgwJjAkMCIEIMR0znYAfQI5Tg2l5N58FMaA+eKC
# ATz+9lPvXbcf32H4MAsGCSqGSIb3DQEBAQSCAQAxZTurueFa0gsxsKPdVmcoAp3k
# ATz+9lPvXbcf32H4MAsGCSqGSIb3DQEBAQSCAQBJj/OBxctaK11U1/Cv0rxP4fgV
# EEqW9x41BRlxKV1s0uqV1DEEozXmnJnoqSDm/bLx4xGTZujjPe2UrdOk5445lev8
# 9KKW7nWieer5TbP7QJXiJx88gBo4sF5yg+DfkvALpDWujtDdGSq6d0DweNnRADB7
# JkIRwKJ+LmMb7DtzNkkNPvXi11PD4y/B7J0EVlQ0QCnU+CU8tW3GnAu28whQHk/X
# x8uHhGybC0+sQwbWe8haUL9qSaqEVOQ2LQxQ2TFXtXJEx+hIHvwbtL64dy1nD57W
# 5Fs4jRIaxmBSrDspa3yGsrlqjUpmsF6tA5UEQi+fA5JmvVq6CpiUaXf9JGLQgfGz
# BdhVf3Sgud0YgpA7B7x4bARWFiz9KQY9AhUq/cZN9OWYTq59T2f4l3zDBAf7d3ni
# zt8XVyLcXJEXMS1lA54z8R8XiJzrT9bOoHZxwSlRZswDAosfe3PAWbS9sKnatYCX
# JAF5Omx4OEsWzfbvEwe3WxtWenFk4QhlaDlj4xVQzJQgYDOeebd74uFjRpY+ohnJ
# LgWGsxXn040/9cei5szi4Z4ltGUYI7gdNTYafRS/mCRbgfITpfzlpAzk07II
# 0RSC2IMQzxz1bvdGx1tO8NpFgJy6E7JoWEqiZA+PgpqWoUy7EaErjArL7Htt
# SIG # End signature block
# SIG # End signature block