mirror of
https://github.com/dockur/windows.git
synced 2026-07-27 21:42:36 +07:00
feat: Improve Windows media detection and selection (#1946)
This commit is contained in:
@@ -22,6 +22,7 @@ RUN <<EOF
|
||||
wimtools \
|
||||
dos2unix \
|
||||
cabextract \
|
||||
icu-devtools \
|
||||
libxml2-utils \
|
||||
libarchive-tools
|
||||
|
||||
|
||||
+136
-6
@@ -235,6 +235,40 @@ validateDomainName() {
|
||||
return 0
|
||||
}
|
||||
|
||||
markGeneratedXML() {
|
||||
|
||||
local file="$1"
|
||||
local marker='<!-- generated-answer-file: do not reuse as a template -->'
|
||||
|
||||
[ -s "$file" ] || return 1
|
||||
|
||||
if head -n 1 "$file" | grep -q '^<?xml'; then
|
||||
sed -i "1a$marker" "$file" || return 1
|
||||
else
|
||||
sed -i "1i$marker" "$file" || return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
removeGeneratedXML() {
|
||||
|
||||
local file="$1"
|
||||
|
||||
[ -n "$file" ] || return 0
|
||||
[ -f "$file" ] || return 0
|
||||
|
||||
head -n 5 "$file" |
|
||||
grep -Fqi 'generated-answer-file' || return 0
|
||||
|
||||
if ! rm -f "$file"; then
|
||||
error "Failed to remove generated answer file: $file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
generateEvalXML() {
|
||||
|
||||
# Evaluation templates are generated from their normal counterpart so
|
||||
@@ -247,6 +281,8 @@ generateEvalXML() {
|
||||
local index="$detected_index" tmp
|
||||
|
||||
[[ "${id,,}" == *"-eval" ]] || return 1
|
||||
|
||||
removeGeneratedXML "$source" || return 1
|
||||
[ -s "$source" ] || return 1
|
||||
|
||||
if [ -n "$index" ] && [[ ! "$index" =~ ^[1-9][0-9]*$ ]]; then
|
||||
@@ -307,7 +343,8 @@ generateEvalXML() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! xmllint --nonet --noout "$tmp"; then
|
||||
if ! markGeneratedXML "$tmp" ||
|
||||
! xmllint --nonet --noout "$tmp"; then
|
||||
rm -f "$tmp"
|
||||
error "Generated evaluation answer file is invalid!"
|
||||
return 1
|
||||
@@ -322,10 +359,81 @@ generateEvalXML() {
|
||||
return 0
|
||||
}
|
||||
|
||||
generateFallbackXML() {
|
||||
|
||||
# Fallback templates are generated from the generic version so unsupported
|
||||
# editions can use the detected WIM index without inheriting a product key.
|
||||
|
||||
local id="$1"
|
||||
local index="${2:-}"
|
||||
local source="/run/assets/${id%%-*}.xml"
|
||||
local target="/run/assets/$id.xml"
|
||||
local tmp
|
||||
|
||||
[ "$source" != "$target" ] || return 1
|
||||
|
||||
removeGeneratedXML "$source" || return 1
|
||||
[ -s "$source" ] || return 1
|
||||
|
||||
if [ -n "$index" ] && [[ ! "$index" =~ ^[1-9][0-9]*$ ]]; then
|
||||
error "Invalid fallback image index: $index"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! tmp=$(mktemp -p /run/assets ".${id}.XXXXXX"); then
|
||||
error "Failed to create a temporary fallback answer file!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! sed \
|
||||
-e '/<InstallFrom>.*<\/InstallFrom>/d' \
|
||||
-e '/<ProductKey>.*<\/ProductKey>/d' \
|
||||
-e '/<InstallFrom>/,/<\/InstallFrom>/d' \
|
||||
-e '/<ProductKey>/,/<\/ProductKey>/d' \
|
||||
"$source" > "$tmp"; then
|
||||
rm -f "$tmp"
|
||||
error "Failed to generate fallback answer file from $source!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -n "$index" ]; then
|
||||
if ! sed -i \
|
||||
'0,/<InstallTo>/{ /<InstallTo>/i\
|
||||
<InstallFrom>\
|
||||
<MetaData wcm:action="add">\
|
||||
<Key>/IMAGE/INDEX</Key>\
|
||||
<Value>'"$index"'</Value>\
|
||||
</MetaData>\
|
||||
</InstallFrom>
|
||||
}' "$tmp"; then
|
||||
rm -f "$tmp"
|
||||
error "Failed to select fallback image index $index!"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! markGeneratedXML "$tmp" ||
|
||||
! xmllint --nonet --noout "$tmp"; then
|
||||
rm -f "$tmp"
|
||||
error "Generated fallback answer file is invalid!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! chmod 644 "$tmp" || ! mv -f "$tmp" "$target"; then
|
||||
rm -f "$tmp"
|
||||
error "Failed to create fallback answer file: $target"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
setXML() {
|
||||
|
||||
local file
|
||||
local index="${2:-}"
|
||||
local target="/run/assets/$DETECTED.xml"
|
||||
|
||||
local custom_files=(
|
||||
"/custom.xml"
|
||||
"$STORAGE/custom.xml"
|
||||
@@ -334,6 +442,8 @@ setXML() {
|
||||
|
||||
CUSTOM_XML=""
|
||||
|
||||
removeGeneratedXML "$target" || return 1
|
||||
|
||||
if [ -d "${custom_files[0]}" ]; then
|
||||
error "The bind ${custom_files[0]} maps to a file that does not exist!"
|
||||
exit 67
|
||||
@@ -347,6 +457,22 @@ setXML() {
|
||||
fi
|
||||
done
|
||||
|
||||
# Known Server editions normally share one answer file. When the image
|
||||
# contains only one uniquely detected Server edition and no explicit
|
||||
# EDITION was requested, generate a keyless answer file using that index.
|
||||
if [ -n "$index" ] && [ -z "${EDITION:-}" ] &&
|
||||
[[ "${DETECTED,,}" == win20* && "${DETECTED,,}" != *-* ]] &&
|
||||
[ -s "$target" ]; then
|
||||
|
||||
file="/run/assets/$DETECTED-selected.xml"
|
||||
|
||||
removeGeneratedXML "$file" || return 1
|
||||
generateFallbackXML "$DETECTED-selected" "$index" || return 1
|
||||
|
||||
XML="$file"
|
||||
return 0
|
||||
fi
|
||||
|
||||
file="$1"
|
||||
|
||||
if [[ "${DETECTED,,}" == *"-eval" ]]; then
|
||||
@@ -356,7 +482,10 @@ setXML() {
|
||||
fi
|
||||
|
||||
if [ ! -f "$file" ] || [ ! -s "$file" ]; then
|
||||
file="/run/assets/$DETECTED.xml"
|
||||
file="$target"
|
||||
elif [[ "$file" != "$target" ]]; then
|
||||
generateFallbackXML "$DETECTED" "$index" || return 1
|
||||
file="$target"
|
||||
fi
|
||||
|
||||
[ -f "$file" ] && [ -s "$file" ] || return 1
|
||||
@@ -710,13 +839,14 @@ updateXML() {
|
||||
fi
|
||||
|
||||
if [ -n "${EDITION:-}" ]; then
|
||||
case "${EDITION,,}" in
|
||||
"core" ) edition="STANDARDCORE" ;;
|
||||
* ) edition="${EDITION^^}" ;;
|
||||
esac
|
||||
|
||||
edition=$(normalizeServerEdition "$EDITION") || return 1
|
||||
edition="${edition//-/}"
|
||||
edition="${edition^^}"
|
||||
|
||||
edition=$(escapeXMLSed "$edition") || return 1
|
||||
sed -i "s|SERVERSTANDARD</Value>|SERVER$edition</Value>|g" "$asset" || return 1
|
||||
|
||||
fi
|
||||
|
||||
if [ -n "${KEY:-}" ]; then
|
||||
|
||||
+428
-150
@@ -54,11 +54,9 @@ parseVersion() {
|
||||
;;
|
||||
"11l" | "11ltsc" | "ltsc11" | "win11l" | "win11-ltsc" | "win11x64-ltsc" )
|
||||
VERSION="win11x64-enterprise-ltsc-eval"
|
||||
SUGGEST="win11x64-ltsc"
|
||||
;;
|
||||
"11i" | "11iot" | "iot11" | "win11i" | "win11-iot" | "win11x64-iot" )
|
||||
VERSION="win11x64-enterprise-iot-eval"
|
||||
SUGGEST="win11x64-iot"
|
||||
;;
|
||||
"10" | "10p" | "win10" | "pro10" | "win10p" | "windows10" | "windows 10" )
|
||||
VERSION="win10x64"
|
||||
@@ -68,11 +66,9 @@ parseVersion() {
|
||||
;;
|
||||
"10l" | "10ltsc" | "ltsc10" | "win10l" | "win10-ltsc" | "win10x64-ltsc" )
|
||||
VERSION="win10x64-enterprise-ltsc-eval"
|
||||
SUGGEST="win10x64-ltsc"
|
||||
;;
|
||||
"10i" | "10iot" | "iot10" | "win10i" | "win10-iot" | "win10x64-iot" )
|
||||
VERSION="win10x64-enterprise-iot-eval"
|
||||
SUGGEST="win10x64-iot"
|
||||
;;
|
||||
"8" | "8p" | "81" | "81p" | "pro8" | "8.1" | "win8" | "win8p" | "win81" | "win81p" | "windows 8" )
|
||||
VERSION="win81x64"
|
||||
@@ -82,7 +78,6 @@ parseVersion() {
|
||||
;;
|
||||
"7" | "win7" | "windows7" | "windows 7" )
|
||||
VERSION="win7x64"
|
||||
SUGGEST="win7x64-ultimate"
|
||||
;;
|
||||
"7u" | "win7u" | "windows7u" | "windows 7u" )
|
||||
VERSION="win7x64-ultimate"
|
||||
@@ -92,7 +87,6 @@ parseVersion() {
|
||||
;;
|
||||
"7x86" | "win7x86" | "win732" | "windows7x86" )
|
||||
VERSION="win7x86"
|
||||
SUGGEST="win7x86-ultimate"
|
||||
;;
|
||||
"7ux86" | "7u32" | "win7x86-ultimate" )
|
||||
VERSION="win7x86-ultimate"
|
||||
@@ -102,7 +96,6 @@ parseVersion() {
|
||||
;;
|
||||
"vista" | "vs" | "6" | "winvista" | "windowsvista" | "windows vista" )
|
||||
VERSION="winvistax64"
|
||||
SUGGEST="winvistax64-ultimate"
|
||||
;;
|
||||
"vistu" | "vu" | "6u" | "winvistu" )
|
||||
VERSION="winvistax64-ultimate"
|
||||
@@ -112,7 +105,6 @@ parseVersion() {
|
||||
;;
|
||||
"vistax86" | "vista32" | "6x86" | "winvistax86" | "windowsvistax86" )
|
||||
VERSION="winvistax86"
|
||||
SUGGEST="winvistax86-ultimate"
|
||||
;;
|
||||
"vux86" | "vu32" | "winvistax86-ultimate" )
|
||||
VERSION="winvistax86-ultimate"
|
||||
@@ -164,20 +156,46 @@ parseVersion() {
|
||||
;;
|
||||
"tiny10" | "tiny 10" )
|
||||
VERSION="tiny10"
|
||||
SUGGEST="win10x64-ltsc"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$SUGGEST" ]; then
|
||||
case "${VERSION,,}" in
|
||||
*"-enterprise-ltsc-eval" )
|
||||
SUGGEST="${VERSION%-enterprise-ltsc-eval}-ltsc" ;;
|
||||
*"-enterprise-iot-eval" )
|
||||
SUGGEST="${VERSION%-enterprise-iot-eval}-iot" ;;
|
||||
*"-eval" )
|
||||
SUGGEST="${VERSION%-eval}" ;;
|
||||
esac
|
||||
fi
|
||||
SUGGEST=$(getSuggestedVersion "$VERSION")
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
getSuggestedVersion() {
|
||||
|
||||
local id="${1,,}"
|
||||
|
||||
[[ "$id" == http* ]] && return 0
|
||||
|
||||
case "$id" in
|
||||
"win10x64" | "win11x64" )
|
||||
echo "$id"
|
||||
;;
|
||||
"win7x64" | "win7x86" | "winvistax64" | "winvistax86" )
|
||||
echo "$id-ultimate"
|
||||
;;
|
||||
"tiny10" )
|
||||
echo "win10x64-ltsc"
|
||||
;;
|
||||
*"-enterprise-ltsc-eval" )
|
||||
echo "${id%-enterprise-ltsc-eval}-ltsc"
|
||||
;;
|
||||
*"-enterprise-iot-eval" )
|
||||
echo "${id%-enterprise-iot-eval}-iot"
|
||||
;;
|
||||
*"-enterprise-ltsc" )
|
||||
echo "${id%-enterprise-ltsc}-ltsc"
|
||||
;;
|
||||
*"-enterprise-iot" )
|
||||
echo "${id%-enterprise-iot}-iot"
|
||||
;;
|
||||
*"-eval" )
|
||||
echo "${id%-eval}"
|
||||
;;
|
||||
esac
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -388,7 +406,8 @@ parseLanguage() {
|
||||
"danish" | "dk" | "danske" ) LANGUAGE="da" ;;
|
||||
"dutch" | "nederlands" ) LANGUAGE="nl" ;;
|
||||
"english" ) LANGUAGE="en" ;;
|
||||
"british" | "gb" ) LANGUAGE="en-gb" ;; "estonian" | "eesti" ) LANGUAGE="et" ;;
|
||||
"british" | "gb" ) LANGUAGE="en-gb" ;;
|
||||
"estonian" | "eesti" ) LANGUAGE="et" ;;
|
||||
"finnish" | "suomi" ) LANGUAGE="fi" ;;
|
||||
"french" | "français" | "francais" ) LANGUAGE="fr" ;;
|
||||
"german" | "deutsch" ) LANGUAGE="de" ;;
|
||||
@@ -491,59 +510,103 @@ printVariant() {
|
||||
return 0
|
||||
}
|
||||
|
||||
formatEdition() {
|
||||
|
||||
local edition="${1//-/ }"
|
||||
local result="" word
|
||||
|
||||
for word in $edition; do
|
||||
if [ "$word" == "for" ]; then
|
||||
word="for"
|
||||
elif [ "${#word}" -eq 1 ]; then
|
||||
word="${word^^}"
|
||||
else
|
||||
word="${word^}"
|
||||
fi
|
||||
|
||||
result+="${result:+ }$word"
|
||||
done
|
||||
|
||||
echo "$result"
|
||||
return 0
|
||||
}
|
||||
|
||||
printEdition() {
|
||||
|
||||
local id="$1"
|
||||
local desc="$2"
|
||||
local show_eval="${3:-N}"
|
||||
local result="" edition=""
|
||||
local normalized="${id,,}"
|
||||
local result="" edition="" suffix=""
|
||||
|
||||
result=$(printVersion "$id" "x")
|
||||
[[ "$result" == "x" ]] && echo "$desc" && return 0
|
||||
|
||||
case "${id,,}" in
|
||||
*"-home" )
|
||||
edition="Home"
|
||||
;;
|
||||
*"-starter" )
|
||||
edition="Starter"
|
||||
;;
|
||||
*"-ultimate" )
|
||||
edition="Ultimate"
|
||||
;;
|
||||
*"-enterprise" | *"-enterprise-eval" )
|
||||
edition="Enterprise"
|
||||
;;
|
||||
*"-education" )
|
||||
edition="Education"
|
||||
;;
|
||||
*"-hv" )
|
||||
edition="2019"
|
||||
;;
|
||||
*"-iot" | *"-iot-eval" )
|
||||
edition="IoT Enterprise LTSC"
|
||||
;;
|
||||
*"-ltsc" | *"-ltsc-eval" )
|
||||
edition="Enterprise LTSC"
|
||||
;;
|
||||
"win7"* )
|
||||
edition="Professional"
|
||||
;;
|
||||
"win8"* | "win10"* | "win11"* )
|
||||
edition="Pro"
|
||||
normalized="${normalized%-eval}"
|
||||
|
||||
case "$normalized" in
|
||||
"winvista"* | "win7"* | "win8"* | "win10"* | "win11"* )
|
||||
[[ "$normalized" == *"-"* ]] && suffix="${normalized#*-}"
|
||||
|
||||
case "$suffix" in
|
||||
"" )
|
||||
case "$normalized" in
|
||||
"winvista"* ) edition="Business" ;;
|
||||
"win7"* ) edition="Professional" ;;
|
||||
* ) edition="Pro" ;;
|
||||
esac
|
||||
;;
|
||||
"home" )
|
||||
edition="Home"
|
||||
;;
|
||||
"starter" )
|
||||
edition="Starter"
|
||||
;;
|
||||
"ultimate" )
|
||||
edition="Ultimate"
|
||||
;;
|
||||
"enterprise" )
|
||||
edition="Enterprise"
|
||||
;;
|
||||
"education" )
|
||||
edition="Education"
|
||||
;;
|
||||
"n" )
|
||||
case "$normalized" in
|
||||
"win7"* ) edition="Professional N" ;;
|
||||
* ) edition="Pro N" ;;
|
||||
esac
|
||||
;;
|
||||
"iot" | "enterprise-iot" )
|
||||
edition="IoT Enterprise LTSC"
|
||||
;;
|
||||
"ltsc" | "enterprise-ltsc" )
|
||||
edition="Enterprise LTSC"
|
||||
;;
|
||||
* )
|
||||
edition=$(formatEdition "$suffix")
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
"winxp"* )
|
||||
edition="Professional"
|
||||
;;
|
||||
"winvista"* )
|
||||
edition="Business"
|
||||
"win2019-hv"* )
|
||||
edition="2019"
|
||||
;;
|
||||
"win2025"* | "win2022"* | "win2019"* | "win2016"* | "win2012"* | "win2008"* | "win2003"* )
|
||||
case "${EDITION^^}" in
|
||||
*"DATACENTER"* ) edition="Datacenter" ;;
|
||||
"CORE" | "STANDARDCORE" ) edition="Core" ;;
|
||||
* ) edition="Standard" ;;
|
||||
esac
|
||||
"win2025"* | "win2022"* | "win2019"* | "win2016"* | \
|
||||
"win2012"* | "win2008"* | "win2003"* )
|
||||
[[ "$normalized" == *"-"* ]] && suffix="${normalized#*-}"
|
||||
|
||||
if [ -n "$suffix" ]; then
|
||||
edition=$(formatEdition "$suffix")
|
||||
else
|
||||
case "${EDITION^^}" in
|
||||
*"DATACENTER"* ) edition="Datacenter" ;;
|
||||
"CORE" | "STANDARDCORE" ) edition="Core" ;;
|
||||
* ) edition="Standard" ;;
|
||||
esac
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -678,9 +741,223 @@ fromName() {
|
||||
return 0
|
||||
}
|
||||
|
||||
normalizeEdition() {
|
||||
|
||||
local source="${1,,}"
|
||||
local edition
|
||||
|
||||
source="${source//evaluation/}"
|
||||
|
||||
source=$(printf '%s' "$source" |
|
||||
uconv -x 'Any-Latin; Latin-ASCII' 2>/dev/null) || return 1
|
||||
|
||||
edition=$(sed -E \
|
||||
-e 's/[^a-z0-9]+/-/g' \
|
||||
-e 's/^-+//' \
|
||||
-e 's/-+$//' \
|
||||
<<< "$source")
|
||||
|
||||
echo "$edition"
|
||||
return 0
|
||||
}
|
||||
|
||||
normalizeEditionID() {
|
||||
|
||||
local edition
|
||||
local id="$2"
|
||||
|
||||
edition=$(normalizeEdition "$1")
|
||||
|
||||
case "$edition" in
|
||||
"pro" | "professional" | "business" )
|
||||
edition=""
|
||||
;;
|
||||
"pro-n" | "professional-n" )
|
||||
edition="n"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "${id,,}" in
|
||||
"winvista"* )
|
||||
case "$edition" in
|
||||
"business" )
|
||||
edition=""
|
||||
;;
|
||||
"home-basic" | "home-premium" )
|
||||
edition="home"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
"win7"* )
|
||||
case "$edition" in
|
||||
"home-basic" | "home-premium" )
|
||||
edition="home"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
"win10"* | "win11"* )
|
||||
case "$edition" in
|
||||
"iot-enterprise-ltsc" | \
|
||||
"iot-enterprise-ltsc-"[0-9][0-9][0-9][0-9] )
|
||||
edition="iot"
|
||||
;;
|
||||
"enterprise-ltsc" | \
|
||||
"enterprise-ltsc-"[0-9][0-9][0-9][0-9] )
|
||||
edition="ltsc"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "$edition"
|
||||
return 0
|
||||
}
|
||||
|
||||
getEditionID() {
|
||||
|
||||
local name="${1,,}"
|
||||
local id="${2,,}"
|
||||
local edition=""
|
||||
|
||||
case "$id" in
|
||||
"winvista"* )
|
||||
edition="${name#*vista}"
|
||||
;;
|
||||
"win7"* )
|
||||
edition="${name#*7}"
|
||||
;;
|
||||
"win8"* )
|
||||
if [[ "$name" == *"8.1"* ]]; then
|
||||
edition="${name#*8.1}"
|
||||
else
|
||||
edition="${name#*8}"
|
||||
fi
|
||||
;;
|
||||
"win10"* )
|
||||
edition="${name#*10}"
|
||||
;;
|
||||
"win11"* )
|
||||
edition="${name#*11}"
|
||||
;;
|
||||
* )
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
edition=$(normalizeEditionID "$edition" "$id")
|
||||
|
||||
echo "$edition"
|
||||
return 0
|
||||
}
|
||||
|
||||
normalizeServerEdition() {
|
||||
|
||||
local edition
|
||||
|
||||
edition=$(normalizeEdition "$1") || return 1
|
||||
edition="${edition#r2-}"
|
||||
|
||||
case "$edition" in
|
||||
"core" | "core-installation" | "server-core-installation" )
|
||||
edition="standard-core"
|
||||
;;
|
||||
"desktop-experience" | "server-with-a-gui" | "full-installation" )
|
||||
edition="standard"
|
||||
;;
|
||||
*"-server-core-installation" )
|
||||
edition="${edition%-server-core-installation}-core"
|
||||
;;
|
||||
*"-core-installation" )
|
||||
edition="${edition%-core-installation}-core"
|
||||
;;
|
||||
*"-desktop-experience" )
|
||||
edition="${edition%-desktop-experience}"
|
||||
;;
|
||||
*"-server-with-a-gui" )
|
||||
edition="${edition%-server-with-a-gui}"
|
||||
;;
|
||||
*"-full-installation" )
|
||||
edition="${edition%-full-installation}"
|
||||
;;
|
||||
esac
|
||||
|
||||
edition="${edition#server-}"
|
||||
edition="${edition#server}"
|
||||
|
||||
[ "$edition" == "core" ] && edition="standard-core"
|
||||
|
||||
echo "$edition"
|
||||
return 0
|
||||
}
|
||||
|
||||
normalizeServerEditionID() {
|
||||
|
||||
local edition
|
||||
|
||||
edition=$(normalizeServerEdition "$1") || return 1
|
||||
|
||||
case "$edition" in
|
||||
"" | "core" | \
|
||||
"standard" | "standard-core" | "standardcore" | \
|
||||
"serverstandard" | "serverstandardcore" | \
|
||||
"datacenter" | "datacenter-core" | "datacentercore" | \
|
||||
"serverdatacenter" | "serverdatacentercore" | \
|
||||
"enterprise" | "enterprise-core" | "enterprisecore" | \
|
||||
"serverenterprise" | "serverenterprisecore" | \
|
||||
"web" | "web-core" | "webcore" | \
|
||||
"serverweb" | "serverwebcore" | \
|
||||
"foundation" | "serverfoundation" | \
|
||||
"essentials" | "serveressentials" )
|
||||
edition=""
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "$edition"
|
||||
return 0
|
||||
}
|
||||
|
||||
getServerEditionID() {
|
||||
|
||||
local name="${1,,}"
|
||||
local id="${2,,}"
|
||||
local edition=""
|
||||
|
||||
case "$id" in
|
||||
"win2025"* )
|
||||
edition="${name#*server 2025}"
|
||||
;;
|
||||
"win2022"* )
|
||||
edition="${name#*server 2022}"
|
||||
;;
|
||||
"win2019"* )
|
||||
edition="${name#*server 2019}"
|
||||
;;
|
||||
"win2016"* )
|
||||
edition="${name#*server 2016}"
|
||||
;;
|
||||
"win2012"* )
|
||||
edition="${name#*server 2012}"
|
||||
;;
|
||||
"win2008"* )
|
||||
edition="${name#*server 2008}"
|
||||
;;
|
||||
"win2003"* )
|
||||
edition="${name#*server 2003}"
|
||||
;;
|
||||
* )
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
edition=$(normalizeServerEditionID "$edition")
|
||||
|
||||
echo "$edition"
|
||||
return 0
|
||||
}
|
||||
|
||||
getVersion() {
|
||||
|
||||
local id
|
||||
local id edition
|
||||
local name="$1"
|
||||
local arch="$2"
|
||||
local evaluation=""
|
||||
@@ -689,34 +966,20 @@ getVersion() {
|
||||
[[ "${name,,}" == *"evaluation"* ]] && evaluation="-eval"
|
||||
|
||||
case "${id,,}" in
|
||||
"win7"* | "winvista"* )
|
||||
case "${name,,}" in
|
||||
*" home"* ) id="$id-home" ;;
|
||||
*" starter"* ) id="$id-starter" ;;
|
||||
*" ultimate"* ) id="$id-ultimate" ;;
|
||||
*" enterprise"* ) id="$id-enterprise$evaluation" ;;
|
||||
esac
|
||||
;;
|
||||
"win8"* )
|
||||
case "${name,,}" in
|
||||
*" enterprise"* ) id="$id-enterprise$evaluation" ;;
|
||||
esac
|
||||
;;
|
||||
"win10"* | "win11"* )
|
||||
case "${name,,}" in
|
||||
*" iot"* ) id="$id-iot$evaluation" ;;
|
||||
*" ltsc"* ) id="$id-ltsc$evaluation" ;;
|
||||
*" home"* ) id="$id-home" ;;
|
||||
*" education"* ) id="$id-education" ;;
|
||||
*" enterprise"* ) id="$id-enterprise$evaluation" ;;
|
||||
esac
|
||||
"winvista"* | "win7"* | "win8"* | "win10"* | "win11"* )
|
||||
if edition=$(getEditionID "$name" "$id"); then
|
||||
[ -n "$edition" ] && id+="-$edition"
|
||||
[ -n "$evaluation" ] && id+="$evaluation"
|
||||
fi
|
||||
;;
|
||||
"win2025"* | "win2022"* | "win2019"* | "win2016"* | \
|
||||
"win2012"* | "win2008"* | "win2003"* )
|
||||
case "${name,,}" in
|
||||
*"hyper-v server"* ) id="$id-hv" ;;
|
||||
*"evaluation"* ) id="$id-eval" ;;
|
||||
esac
|
||||
if [[ "${name,,}" == *"hyper-v server"* ]]; then
|
||||
id+="-hv"
|
||||
elif edition=$(getServerEditionID "$name" "$id"); then
|
||||
[ -n "$edition" ] && id+="-$edition"
|
||||
[ -n "$evaluation" ] && id+="$evaluation"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -724,6 +987,21 @@ getVersion() {
|
||||
return 0
|
||||
}
|
||||
|
||||
switchEdition() {
|
||||
|
||||
local -n id="$1"
|
||||
|
||||
[[ "${id,,}" == *"-eval" ]] || return 1
|
||||
|
||||
id="${id::-5}"
|
||||
|
||||
if ! enabled "${DETECTED_ORG:-}"; then
|
||||
DETECTED="${SUGGEST:-$id}"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
getMido() {
|
||||
|
||||
local id="$1"
|
||||
@@ -832,72 +1110,72 @@ getLink1() {
|
||||
[[ "${lang,,}" != "en" && "${lang,,}" != "en-us" ]] && return 0
|
||||
|
||||
case "${id,,}" in
|
||||
"win11x64" | "win11x64-enterprise" | "win11x64-enterprise-eval" )
|
||||
"win11x64" | "win11x64-enterprise" )
|
||||
size=6927149056
|
||||
sum="f5ffe9313eebc6299fba9e6eeb2971007264e6c6be013073a89b5ae9bd85bfb3"
|
||||
url="11/en-us_windows_11_25h2_x64.iso"
|
||||
;;
|
||||
"win11x64-ltsc" | "win11x64-enterprise-ltsc" | "win11x64-enterprise-ltsc-eval" )
|
||||
"win11x64-ltsc" | "win11x64-enterprise-ltsc" )
|
||||
size=5144817664
|
||||
sum="4f59662a96fc1da48c1b415d6c369d08af55ddd64e8f1c84e0166d9e50405d7a"
|
||||
url="11/X23-81951_26100.1742.240906-0331.ge_release_svc_refresh_CLIENT_ENTERPRISES_OEM_x64FRE_en-us.iso"
|
||||
;;
|
||||
"win11x64-iot" | "win11x64-enterprise-iot" | "win11x64-enterprise-iot-eval" )
|
||||
"win11x64-iot" | "win11x64-enterprise-iot" )
|
||||
size=5144817664
|
||||
sum="4f59662a96fc1da48c1b415d6c369d08af55ddd64e8f1c84e0166d9e50405d7a"
|
||||
url="11/X23-81951_26100.1742.240906-0331.ge_release_svc_refresh_CLIENT_ENTERPRISES_OEM_x64FRE_en-us.iso"
|
||||
;;
|
||||
"win10x64" | "win10x64-enterprise" | "win10x64-enterprise-eval" )
|
||||
"win10x64" | "win10x64-enterprise" )
|
||||
size=5723299840
|
||||
sum="316f718f21fc9b386d81dadd62dc60268a1cfd65b184ac6a052875a454c3431b"
|
||||
url="10/en-us_windows_10_22h2_x64.iso"
|
||||
;;
|
||||
"win10x64-ltsc" | "win10x64-enterprise-ltsc" | "win10x64-enterprise-ltsc-eval" )
|
||||
"win10x64-ltsc" | "win10x64-enterprise-ltsc" )
|
||||
size=4899461120
|
||||
sum="c90a6df8997bf49e56b9673982f3e80745058723a707aef8f22998ae6479597d"
|
||||
url="10/en-us_windows_10_enterprise_ltsc_2021_x64_dvd_d289cf96.iso"
|
||||
;;
|
||||
"win10x64-iot" | "win10x64-enterprise-iot" | "win10x64-enterprise-iot-eval" )
|
||||
"win10x64-iot" | "win10x64-enterprise-iot" )
|
||||
size=4851668992
|
||||
sum="a0334f31ea7a3e6932b9ad7206608248f0bd40698bfb8fc65f14fc5e4976c160"
|
||||
url="10/en-us_windows_10_iot_enterprise_ltsc_2021_x64_dvd_257ad90f.iso"
|
||||
;;
|
||||
;;
|
||||
"win81x64" )
|
||||
size=4320526336
|
||||
sum="d8333cf427eb3318ff6ab755eb1dd9d433f0e2ae43745312c1cd23e83ca1ce51"
|
||||
url="8.x/8.1/en_windows_8.1_with_update_x64_dvd_6051480.iso"
|
||||
;;
|
||||
"win81x64-enterprise" | "win81x64-enterprise-eval" )
|
||||
"win81x64-enterprise" )
|
||||
size=4139163648
|
||||
sum="c3c604c03677504e8905090a8ce5bb1dde76b6fd58e10f32e3a25bef21b2abe1"
|
||||
url="8.x/8.1/en_windows_8.1_enterprise_with_update_x64_dvd_6054382.iso"
|
||||
;;
|
||||
"win2025" | "win2025-eval" )
|
||||
"win2025" )
|
||||
size=7571058688
|
||||
sum="d273d0a85565ffbc06a3d46313f619103e2830a3373306ddbb9a08b8824f509d"
|
||||
url="server/2025/en-us_windows_server_2025_updated_oct_2025_x64_dvd_6c0c5aa8.iso"
|
||||
;;
|
||||
"win2022" | "win2022-eval" )
|
||||
"win2022" )
|
||||
size=6023239680
|
||||
sum="5d6d91efa972cbdd6701d78db1dcf6a34c7024ca931c1718e7cb3d0c6dd54e88"
|
||||
url="server/2022/en-us_windows_server_2022_updated_oct_2025_x64_dvd_26e9af36.iso"
|
||||
;;
|
||||
"win2019" | "win2019-eval" )
|
||||
"win2019" )
|
||||
size=5575774208
|
||||
sum="0067afe7fdc4e61f677bd8c35a209082aa917df9c117527fc4b2b52a447e89bb"
|
||||
url="server/2019/en-us_windows_server_2019_updated_aug_2021_x64_dvd_a6431a28.iso"
|
||||
;;
|
||||
"win2016" | "win2016-eval" )
|
||||
"win2016" )
|
||||
size=6006587392
|
||||
sum="af06e5483c786c023123e325cea4775050324d9e1366f46850b515ae43f764be"
|
||||
url="server/2016/en_windows_server_2016_updated_feb_2018_x64_dvd_11636692.iso"
|
||||
;;
|
||||
"win2012r2" | "win2012r2-eval" )
|
||||
"win2012r2" )
|
||||
size=5397889024
|
||||
sum="f351e89eb88a96af4626ceb3450248b8573e3ed5924a4e19ea891e6003b62e4e"
|
||||
url="server/2012r2/en_windows_server_2012_r2_with_update_x64_dvd_6052708-004.iso"
|
||||
;;
|
||||
"win2008r2" | "win2008r2-eval" )
|
||||
"win2008r2" )
|
||||
size=3166584832
|
||||
sum="dfd9890881b7e832a927c38310fb415b7ea62ac5a896671f2ce2a111998f0df8"
|
||||
url="server/2008r2/en_windows_server_2008_r2_with_sp1_x64_dvd_617601-018.iso"
|
||||
@@ -907,7 +1185,7 @@ getLink1() {
|
||||
sum="0b738b55a5ea388ad016535a5c8234daf2e5715a0638488ddd8a228a836055a1"
|
||||
url="7/en_windows_7_with_sp1_x64.iso"
|
||||
;;
|
||||
"win7x64-enterprise" | "win7x64-enterprise-eval" )
|
||||
"win7x64-enterprise" )
|
||||
size=3182604288
|
||||
sum="ee69f3e9b86ff973f632db8e01700c5724ef78420b175d25bae6ead90f6805a7"
|
||||
url="7/en_windows_7_enterprise_with_sp1_x64_dvd_u_677651.iso"
|
||||
@@ -917,7 +1195,7 @@ getLink1() {
|
||||
sum="99f3369c90160816be07093dbb0ac053e0a84e52d6ed1395c92ae208ccdf67e5"
|
||||
url="7/en_windows_7_with_sp1_x86.iso"
|
||||
;;
|
||||
"win7x86-enterprise" | "win7x86-enterprise-eval" )
|
||||
"win7x86-enterprise" )
|
||||
size=2434502656
|
||||
sum="8bdd46ff8cb8b8de9c4aba02706629c8983c45e87da110e64e13be17c8434dad"
|
||||
url="7/en_windows_7_enterprise_with_sp1_x86_dvd_u_677710.iso"
|
||||
@@ -976,17 +1254,17 @@ getLink2() {
|
||||
sum="d8333cf427eb3318ff6ab755eb1dd9d433f0e2ae43745312c1cd23e83ca1ce51"
|
||||
url="Windows%208.1%20with%20Update/en_windows_8.1_with_update_x64_dvd_6051480.iso"
|
||||
;;
|
||||
"win81x64-enterprise" | "win81x64-enterprise-eval" )
|
||||
"win81x64-enterprise" )
|
||||
size=4139163648
|
||||
sum="c3c604c03677504e8905090a8ce5bb1dde76b6fd58e10f32e3a25bef21b2abe1"
|
||||
url="Windows%208.1%20with%20Update/en_windows_8.1_enterprise_with_update_x64_dvd_6054382.iso"
|
||||
;;
|
||||
"win2012r2" | "win2012r2-eval" )
|
||||
"win2012r2" )
|
||||
size=5397889024
|
||||
sum="f351e89eb88a96af4626ceb3450248b8573e3ed5924a4e19ea891e6003b62e4e"
|
||||
url="Windows%20Server%202012%20R2%20with%20Update/en_windows_server_2012_r2_with_update_x64_dvd_6052708.iso"
|
||||
;;
|
||||
"win2008r2" | "win2008r2-eval" )
|
||||
"win2008r2" )
|
||||
size=3166584832
|
||||
sum="dfd9890881b7e832a927c38310fb415b7ea62ac5a896671f2ce2a111998f0df8"
|
||||
url="Windows%20Server%202008%20R2/en_windows_server_2008_r2_with_sp1_x64_dvd_617601.iso"
|
||||
@@ -996,7 +1274,7 @@ getLink2() {
|
||||
sum="36f4fa2416d0982697ab106e3a72d2e120dbcdb6cc54fd3906d06120d0653808"
|
||||
url="Windows%207/en_windows_7_ultimate_with_sp1_x64_dvd_u_677332.iso"
|
||||
;;
|
||||
"win7x64-enterprise" | "win7x64-enterprise-eval" )
|
||||
"win7x64-enterprise" )
|
||||
size=3182604288
|
||||
sum="ee69f3e9b86ff973f632db8e01700c5724ef78420b175d25bae6ead90f6805a7"
|
||||
url="Windows%207/en_windows_7_enterprise_with_sp1_x64_dvd_u_677651.iso"
|
||||
@@ -1006,7 +1284,7 @@ getLink2() {
|
||||
sum="e2c009a66d63a742941f5087acae1aa438dcbe87010bddd53884b1af6b22c940"
|
||||
url="Windows%207/en_windows_7_ultimate_with_sp1_x86_dvd_u_677460.iso"
|
||||
;;
|
||||
"win7x86-enterprise" | "win7x86-enterprise-eval" )
|
||||
"win7x86-enterprise" )
|
||||
size=2434502656
|
||||
sum="8bdd46ff8cb8b8de9c4aba02706629c8983c45e87da110e64e13be17c8434dad"
|
||||
url="Windows%207/en_windows_7_enterprise_with_sp1_x86_dvd_u_677710.iso"
|
||||
@@ -1065,57 +1343,37 @@ getLink3() {
|
||||
[[ "${lang,,}" != "en" && "${lang,,}" != "en-us" ]] && return 0
|
||||
|
||||
case "${id,,}" in
|
||||
"nano11" )
|
||||
size=2463565824
|
||||
sum="a1e0614372768cbe2d24de74b78a4a97bc1017ea5080dfed1d2125e4a527eb1a"
|
||||
url="nano11_25h2/nano11%2025h2.iso"
|
||||
;;
|
||||
"core11" )
|
||||
size=3304132608
|
||||
sum="c0e0252b24144b8defb6c7ded2bc09f9297daf1fb8369b16c5b85382331eb47f"
|
||||
url="tiny11_25H2/tiny11core_25H2_Nov25.iso"
|
||||
;;
|
||||
"tiny11" )
|
||||
size=5730246656
|
||||
sum="7b24815845684add7250808b3b0027ba4e94cf52c62e9ef40d5b965dd304d6ca"
|
||||
url="tiny11_25H2/tiny11_25H2_Nov25.iso"
|
||||
;;
|
||||
"tiny10" )
|
||||
size=3839819776
|
||||
sum="a11116c0645d892d6a5a7c585ecc1fa13aa66f8c7cc6b03bf1f27bd16860cc35"
|
||||
url="tiny-10-23-h2/tiny10%20x64%2023h2.iso"
|
||||
;;
|
||||
"win11x64" )
|
||||
size=7736125440
|
||||
sum="d141f6030fed50f75e2b03e1eb2e53646c4b21e5386047cb860af5223f102a32"
|
||||
url="W11x64_26200.6584/26200.6584.250915-1905.25h2_ge_release_svc_refresh_CLIENT_CONSUMER_x64FRE_en-us.iso"
|
||||
;;
|
||||
"win11x64-enterprise" | "win11x64-enterprise-eval" )
|
||||
"win11x64-enterprise" )
|
||||
size=7620513792
|
||||
sum="2b65df49334b64e9341dc404e9c527bf1b2a9a105e95314a347fd29ac9900581"
|
||||
url="massgrave.dev-windows-x64-and-x86-archive/en-us_windows_11_business_editions_version_25h2_x64_dvd_41c521e7.iso"
|
||||
;;
|
||||
"win11x64-ltsc" | "win11x64-enterprise-ltsc" | "win11x64-enterprise-ltsc-eval" )
|
||||
"win11x64-ltsc" | "win11x64-enterprise-ltsc" )
|
||||
size=5144817664
|
||||
sum="4f59662a96fc1da48c1b415d6c369d08af55ddd64e8f1c84e0166d9e50405d7a"
|
||||
url="Windows11LTSC/X23-81951_26100.1742.240906-0331.ge_release_svc_refresh_CLIENT_ENTERPRISES_OEM_x64FRE_en-us.iso"
|
||||
;;
|
||||
"win11x64-iot" | "win11x64-enterprise-iot" | "win11x64-enterprise-iot-eval" )
|
||||
"win11x64-iot" | "win11x64-enterprise-iot" )
|
||||
size=5144817664
|
||||
sum="4f59662a96fc1da48c1b415d6c369d08af55ddd64e8f1c84e0166d9e50405d7a"
|
||||
url="Windows11LTSC/X23-81951_26100.1742.240906-0331.ge_release_svc_refresh_CLIENT_ENTERPRISES_OEM_x64FRE_en-us.iso"
|
||||
;;
|
||||
"win10x64" | "win10x64-enterprise" | "win10x64-enterprise-eval" )
|
||||
"win10x64" | "win10x64-enterprise" )
|
||||
size=6985445376
|
||||
sum="2c23bc8b95a9314f15ebff881dcbea49651f52a96a0327d7aaf523aa66043765"
|
||||
url="windows_10_version_2004/Windows%2010%2C%20version%2022H2/Updated%20October%202025%20%2819045.6456%29/en-us_windows_10_business_editions_version_22h2_updated_oct_2025_x64_dvd_d2eef4b0.iso"
|
||||
url="windows-10-business-editions-version-22h2-updated-oct-2025-en-us/en-us_windows_10_business_editions_version_22h2_updated_oct_2025_x64_dvd_d2eef4b0.iso"
|
||||
;;
|
||||
"win10x64-ltsc" | "win10x64-enterprise-ltsc" | "win10x64-enterprise-ltsc-eval" )
|
||||
"win10x64-ltsc" | "win10x64-enterprise-ltsc" )
|
||||
size=4899461120
|
||||
sum="c90a6df8997bf49e56b9673982f3e80745058723a707aef8f22998ae6479597d"
|
||||
url="en-us_windows_10_enterprise_ltsc_2021_x64_dvd_d289cf96_202302/en-us_windows_10_enterprise_ltsc_2021_x64_dvd_d289cf96.iso"
|
||||
;;
|
||||
"win10x64-iot" | "win10x64-enterprise-iot" | "win10x64-enterprise-iot-eval" )
|
||||
"win10x64-iot" | "win10x64-enterprise-iot" )
|
||||
size=4851668992
|
||||
sum="a0334f31ea7a3e6932b9ad7206608248f0bd40698bfb8fc65f14fc5e4976c160"
|
||||
url="en-us_windows_10_iot_enterprise_ltsc_2021_x64_dvd_257ad90f_202411/en-us_windows_10_iot_enterprise_ltsc_2021_x64_dvd_257ad90f.iso"
|
||||
@@ -1125,37 +1383,37 @@ getLink3() {
|
||||
sum="d8333cf427eb3318ff6ab755eb1dd9d433f0e2ae43745312c1cd23e83ca1ce51"
|
||||
url="en_windows_8.1_with_update_x64_dvd_6051480/en_windows_8.1_with_update_x64_dvd_6051480.iso"
|
||||
;;
|
||||
"win81x64-enterprise" | "win81x64-enterprise-eval" )
|
||||
"win81x64-enterprise" )
|
||||
size=4139163648
|
||||
sum="c3c604c03677504e8905090a8ce5bb1dde76b6fd58e10f32e3a25bef21b2abe1"
|
||||
url="en_windows_8.1_enterprise_with_update_x64_dvd/en_windows_8.1_enterprise_with_update_x64_dvd_6054382.iso"
|
||||
;;
|
||||
"win2025" | "win2025-eval" )
|
||||
"win2025" )
|
||||
size=8145395712
|
||||
sum="f3e277e75acdb793e6f08f4880b514ae0046cedf618c22f727890e54367075e6"
|
||||
url="massgrave.dev-windows-x64-and-x86-archive/en-us_windows_server_2025_updated_dec_2025_x64_dvd_c54ab58b.iso"
|
||||
;;
|
||||
"win2022" | "win2022-eval" )
|
||||
"win2022" )
|
||||
size=6023239680
|
||||
sum="5d6d91efa972cbdd6701d78db1dcf6a34c7024ca931c1718e7cb3d0c6dd54e88"
|
||||
url="massgrave.dev-windows-x64-and-x86-archive/en-us_windows_server_2022_updated_oct_2025_x64_dvd_26e9af36.iso"
|
||||
;;
|
||||
"win2019" | "win2019-eval" )
|
||||
"win2019" )
|
||||
size=5651695616
|
||||
sum="ea247e5cf4df3e5829bfaaf45d899933a2a67b1c700a02ee8141287a8520261c"
|
||||
url="massgrave.dev-windows-x64-and-x86-archive/en-us_windows_server_2019_x64_dvd_f9475476.iso"
|
||||
;;
|
||||
"win2016" | "win2016-eval" )
|
||||
"win2016" )
|
||||
size=6006587392
|
||||
sum="af06e5483c786c023123e325cea4775050324d9e1366f46850b515ae43f764be"
|
||||
url="en_windows_server_2016_updated_feb_2018_x64_dvd_11636692/en_windows_server_2016_updated_feb_2018_x64_dvd_11636692.iso"
|
||||
;;
|
||||
"win2012r2" | "win2012r2-eval" )
|
||||
"win2012r2" )
|
||||
size=5397889024
|
||||
sum="f351e89eb88a96af4626ceb3450248b8573e3ed5924a4e19ea891e6003b62e4e"
|
||||
url="en_windows_server_2012_r2_with_update_x64_dvd_6052708_202006/en_windows_server_2012_r2_with_update_x64_dvd_6052708.iso"
|
||||
;;
|
||||
"win2008r2" | "win2008r2-eval" )
|
||||
"win2008r2" )
|
||||
size=3166584832
|
||||
sum="dfd9890881b7e832a927c38310fb415b7ea62ac5a896671f2ce2a111998f0df8"
|
||||
url="en_windows_server_2008_r2_with_sp1_x64_dvd_617601_202006/en_windows_server_2008_r2_with_sp1_x64_dvd_617601.iso"
|
||||
@@ -1165,7 +1423,7 @@ getLink3() {
|
||||
sum="36f4fa2416d0982697ab106e3a72d2e120dbcdb6cc54fd3906d06120d0653808"
|
||||
url="win7-ult-sp1-english/Win7_Ult_SP1_English_x64.iso"
|
||||
;;
|
||||
"win7x64-enterprise" | "win7x64-enterprise-eval" )
|
||||
"win7x64-enterprise" )
|
||||
size=3182604288
|
||||
sum="ee69f3e9b86ff973f632db8e01700c5724ef78420b175d25bae6ead90f6805a7"
|
||||
url="en_windows_7_enterprise_with_sp1_x64_dvd_u_677651_202006/en_windows_7_enterprise_with_sp1_x64_dvd_u_677651.iso"
|
||||
@@ -1175,7 +1433,7 @@ getLink3() {
|
||||
sum="e2c009a66d63a742941f5087acae1aa438dcbe87010bddd53884b1af6b22c940"
|
||||
url="win7-ult-sp1-english/Win7_Ult_SP1_English_x32.iso"
|
||||
;;
|
||||
"win7x86-enterprise" | "win7x86-enterprise-eval" )
|
||||
"win7x86-enterprise" )
|
||||
size=2434502656
|
||||
sum="8bdd46ff8cb8b8de9c4aba02706629c8983c45e87da110e64e13be17c8434dad"
|
||||
url="en_windows_7_enterprise_with_sp1_x86_dvd_u_677710_202006/en_windows_7_enterprise_with_sp1_x86_dvd_u_677710.iso"
|
||||
@@ -1220,6 +1478,26 @@ getLink3() {
|
||||
sum="e3816f6e80b66ff686ead03eeafffe9daf020a5e4717b8bd4736b7c51733ba22"
|
||||
url="MicrosoftWindows2000BuildCollection/5.00.2195.6717_x86fre_client-professional_retail_en-us-ZRMPFPP_EN.iso"
|
||||
;;
|
||||
"nano11" )
|
||||
size=2463565824
|
||||
sum="a1e0614372768cbe2d24de74b78a4a97bc1017ea5080dfed1d2125e4a527eb1a"
|
||||
url="nano11_25h2/nano11%2025h2.iso"
|
||||
;;
|
||||
"core11" )
|
||||
size=3304132608
|
||||
sum="c0e0252b24144b8defb6c7ded2bc09f9297daf1fb8369b16c5b85382331eb47f"
|
||||
url="tiny11_25H2/tiny11core_25H2_Nov25.iso"
|
||||
;;
|
||||
"tiny11" )
|
||||
size=5730246656
|
||||
sum="7b24815845684add7250808b3b0027ba4e94cf52c62e9ef40d5b965dd304d6ca"
|
||||
url="tiny11_25H2/tiny11_25H2_Nov25.iso"
|
||||
;;
|
||||
"tiny10" )
|
||||
size=3839819776
|
||||
sum="a11116c0645d892d6a5a7c585ecc1fa13aa66f8c7cc6b03bf1f27bd16860cc35"
|
||||
url="tiny-10-23-h2/tiny10%20x64%2023h2.iso"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "${ret,,}" in
|
||||
@@ -1296,13 +1574,10 @@ isESD() {
|
||||
disabled "${ESD:-}" && return 1
|
||||
|
||||
case "${id,,}" in
|
||||
"win11${PLATFORM,,}" | "win10${PLATFORM,,}" )
|
||||
return 0
|
||||
;;
|
||||
"win11${PLATFORM,,}-enterprise" | "win11${PLATFORM,,}-enterprise-eval")
|
||||
return 0
|
||||
;;
|
||||
"win10${PLATFORM,,}-enterprise" | "win10${PLATFORM,,}-enterprise-eval" )
|
||||
"win11${PLATFORM,,}" | \
|
||||
"win10${PLATFORM,,}" | \
|
||||
"win11${PLATFORM,,}-enterprise" | \
|
||||
"win10${PLATFORM,,}-enterprise" )
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
@@ -1316,9 +1591,12 @@ validVersion() {
|
||||
local lang="$2"
|
||||
local url i=0
|
||||
|
||||
isESD "$id" "$lang" && return 0
|
||||
isMido "$id" "$lang" && return 0
|
||||
|
||||
[[ "${id,,}" == *"-eval" ]] && id="${id::-5}"
|
||||
|
||||
isESD "$id" "$lang" && return 0
|
||||
|
||||
for ((i=1;i<=MIRRORS;i++)); do
|
||||
|
||||
url=$(getLink "$i" "$id" "$lang")
|
||||
|
||||
+196
-77
@@ -8,13 +8,24 @@ getPlatform() {
|
||||
local platform="x64"
|
||||
local arch
|
||||
|
||||
arch=$(sed -n "/$tag/{s/.*<$tag>\(.*\)<\/$tag>.*/\1/;p}" <<< "$xml")
|
||||
local -a arches=()
|
||||
|
||||
case "${arch,,}" in
|
||||
"0" ) platform="x86" ;;
|
||||
"9" ) platform="x64" ;;
|
||||
"12" ) platform="arm64" ;;
|
||||
esac
|
||||
mapfile -t arches < <(
|
||||
sed -n "/$tag/{s/.*<$tag>\(.*\)<\/$tag>.*/\1/;p}" <<< "$xml" |
|
||||
sort -u
|
||||
)
|
||||
|
||||
if [ "${#arches[@]}" -gt 1 ]; then
|
||||
platform="mixed"
|
||||
elif [ "${#arches[@]}" -eq 1 ]; then
|
||||
arch="${arches[0]}"
|
||||
|
||||
case "${arch,,}" in
|
||||
"0" ) platform="x86" ;;
|
||||
"9" ) platform="x64" ;;
|
||||
"12" ) platform="arm64" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo "$platform"
|
||||
return 0
|
||||
@@ -31,6 +42,10 @@ checkPlatform() {
|
||||
"x86" ) compat="x64" ;;
|
||||
"x64" ) compat="$platform" ;;
|
||||
"arm64" ) compat="$platform" ;;
|
||||
"mixed" )
|
||||
error "Windows images with mixed architectures are not supported!"
|
||||
return 1
|
||||
;;
|
||||
* ) compat="${PLATFORM,,}" ;;
|
||||
esac
|
||||
|
||||
@@ -86,10 +101,11 @@ hasVersion() {
|
||||
fi
|
||||
fi
|
||||
|
||||
# Client editions without a dedicated template can use the generic
|
||||
# template. updateImage() makes that copy edition-neutral.
|
||||
# Editions without a dedicated template can use the generic template.
|
||||
case "${selected_id,,}" in
|
||||
"win7"* | "win8"* | "win10"* | "win11"* | "winvista"* )
|
||||
"win7"* | "win8"* | "win10"* | "win11"* | "winvista"* | \
|
||||
"win2003"* | "win2008"* | "win2012"* | "win2016"* | \
|
||||
"win2019"* | "win2022"* | "win2025"* )
|
||||
file="/run/assets/${selected_id%%-*}.xml"
|
||||
|
||||
if [ -s "$file" ]; then
|
||||
@@ -104,19 +120,80 @@ hasVersion() {
|
||||
return 1
|
||||
}
|
||||
|
||||
selectVersion() {
|
||||
getVersionPriority() {
|
||||
|
||||
local tag="$1"
|
||||
local xml="$2"
|
||||
local platform="$3"
|
||||
local suggested="${4:-}"
|
||||
local id="${1%-eval}"
|
||||
local base="$2"
|
||||
local edition="${id#"$base"}"
|
||||
|
||||
local name id base prefer match suffix actual
|
||||
edition="${edition#-}"
|
||||
|
||||
case "$edition" in
|
||||
"iot" | "iot-"* | "enterprise-iot" | "enterprise-iot-"* )
|
||||
echo "iot"
|
||||
;;
|
||||
"ltsc" | "ltsc-"* | "enterprise-ltsc" | "enterprise-ltsc-"* )
|
||||
echo "ltsc"
|
||||
;;
|
||||
"enterprise" | "enterprise-"* )
|
||||
echo "enterprise"
|
||||
;;
|
||||
"ultimate" | "ultimate-"* )
|
||||
echo "ultimate"
|
||||
;;
|
||||
"education" | "education-"* | "pro-education" | "pro-education-"* )
|
||||
echo "education"
|
||||
;;
|
||||
"home" | "home-"* )
|
||||
echo "home"
|
||||
;;
|
||||
"starter" | "starter-"* )
|
||||
echo "starter"
|
||||
;;
|
||||
"hv" | "hv-"* )
|
||||
echo "hv"
|
||||
;;
|
||||
"" | "n" | "pro" | "pro-"* | "professional" | "professional-"* | \
|
||||
"business" | "business-"* )
|
||||
echo "default"
|
||||
;;
|
||||
* )
|
||||
echo "other"
|
||||
;;
|
||||
esac
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
detectVersion() {
|
||||
|
||||
local xml="$1"
|
||||
local suggested="${2:-}"
|
||||
|
||||
local tag name id base prefer match platform
|
||||
local priority actual edition suffix i
|
||||
local tried=""
|
||||
|
||||
local -a tags=(
|
||||
"DISPLAYNAME"
|
||||
"PRODUCTNAME"
|
||||
"NAME"
|
||||
)
|
||||
local -a versions=()
|
||||
local -a bases=()
|
||||
local -a groups=()
|
||||
local -a priorities=(
|
||||
"enterprise"
|
||||
"ultimate"
|
||||
"default"
|
||||
"iot"
|
||||
"ltsc"
|
||||
"education"
|
||||
"home"
|
||||
"starter"
|
||||
"hv"
|
||||
)
|
||||
local -a suffixes=(
|
||||
"-enterprise"
|
||||
"-ultimate"
|
||||
""
|
||||
@@ -128,44 +205,55 @@ selectVersion() {
|
||||
"-hv"
|
||||
)
|
||||
|
||||
while IFS= read -r name; do
|
||||
[[ "$name" == *"Operating System"* ]] && continue
|
||||
[ -z "$name" ] && continue
|
||||
platform=$(getPlatform "$xml")
|
||||
|
||||
base=$(fromName "$name" "$platform")
|
||||
id=$(getVersion "$name" "$platform")
|
||||
for tag in "${tags[@]}"; do
|
||||
while IFS= read -r name; do
|
||||
[[ "$name" == *"Operating System"* ]] && continue
|
||||
[ -z "$name" ] && continue
|
||||
|
||||
if [ -z "$base" ] || [ -z "$id" ]; then
|
||||
warn "Unknown ${tag,,}: '$name'"
|
||||
continue
|
||||
fi
|
||||
base=$(fromName "$name" "$platform")
|
||||
id=$(getVersion "$name" "$platform")
|
||||
|
||||
versions+=("$id")
|
||||
bases+=("$base")
|
||||
done < <(
|
||||
sed -n \
|
||||
"/$tag/{s/.*<$tag>\(.*\)<\/$tag>.*/\1/;p}" \
|
||||
<<< "$xml"
|
||||
)
|
||||
if [ -z "$base" ] || [ -z "$id" ]; then
|
||||
warn "Unknown ${tag,,}: '$name'"
|
||||
continue
|
||||
fi
|
||||
|
||||
versions+=("$id")
|
||||
bases+=("$base")
|
||||
groups+=("$(getVersionPriority "$id" "$base")")
|
||||
done < <(
|
||||
sed -n \
|
||||
"/$tag/{s/.*<$tag>\(.*\)<\/$tag>.*/\1/;p}" \
|
||||
<<< "$xml"
|
||||
)
|
||||
done
|
||||
|
||||
[ "${#versions[@]}" -eq 0 ] && return 0
|
||||
|
||||
if [ -n "$EDITION" ]; then
|
||||
|
||||
for base in "${bases[@]}"; do
|
||||
[[ "${base,,}" == win20* ]] && continue
|
||||
|
||||
tried="Y"
|
||||
case "${base,,}" in
|
||||
"win2003"* | "win2008"* | "win2012"* | "win2016"* | \
|
||||
"win2019"* | "win2022"* | "win2025"* )
|
||||
edition=$(normalizeServerEditionID "$EDITION")
|
||||
|
||||
case "${EDITION,,}" in
|
||||
"pro" | "professional" | "business" )
|
||||
prefer="$base"
|
||||
# Known Server editions continue using the generic Server ID.
|
||||
# updateXML() applies Standard, Datacenter or Core to that template.
|
||||
[ -z "$edition" ] && continue
|
||||
;;
|
||||
* )
|
||||
prefer="$base-${EDITION,,}"
|
||||
edition=$(normalizeEditionID "$EDITION" "$base")
|
||||
;;
|
||||
esac
|
||||
|
||||
tried="Y"
|
||||
prefer="$base"
|
||||
[ -n "$edition" ] && prefer+="-$edition"
|
||||
|
||||
if match=$(hasVersion "$prefer" "${versions[@]}"); then
|
||||
echo "$match"
|
||||
return 0
|
||||
@@ -173,7 +261,7 @@ selectVersion() {
|
||||
done
|
||||
|
||||
if [ -n "$tried" ]; then
|
||||
warn "Edition '$EDITION' is not supported by this image, using automatic selection instead."
|
||||
warn "edition '$EDITION' is not supported by this image, using automatic selection instead."
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -187,60 +275,56 @@ selectVersion() {
|
||||
fi
|
||||
fi
|
||||
|
||||
# Preserve the existing preference for Enterprise, Ultimate, and the
|
||||
# normal Pro/Professional/Business edition. The remaining entries provide
|
||||
# deterministic selection when those editions are absent.
|
||||
for suffix in "${priorities[@]}"; do
|
||||
# Prefer the normal edition within each selection family. hasVersion()
|
||||
# still allows its Evaluation counterpart when the normal variant is absent.
|
||||
for suffix in "${suffixes[@]}"; do
|
||||
for base in "${bases[@]}"; do
|
||||
prefer="$base$suffix"
|
||||
|
||||
# Automatic selection must prefer an edition that is actually present.
|
||||
for actual in "${versions[@]}"; do
|
||||
[[ "${actual%-eval}" == "${prefer%-eval}" ]] || continue
|
||||
|
||||
if match=$(hasVersion "$prefer" "${versions[@]}"); then
|
||||
echo "$match"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
if match=$(hasVersion "$prefer" "${versions[@]}"); then
|
||||
echo "$match"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# Future or unusual edition that getVersion() recognizes but which is not
|
||||
# included in the priority list: use the first recognized WIM image.
|
||||
# When the normal edition is absent, select another compatible member of
|
||||
# that family, such as N, Workstations, or a future dynamic variant.
|
||||
for priority in "${priorities[@]}"; do
|
||||
for (( i=0; i<${#versions[@]}; i++ )); do
|
||||
[[ "${groups[$i]}" == "$priority" ]] || continue
|
||||
|
||||
actual="${versions[$i]}"
|
||||
|
||||
if match=$(hasVersion "$actual" "${versions[@]}"); then
|
||||
echo "$match"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# Future or unusual editions that do not belong to a known selection
|
||||
# family use the first recognized WIM image.
|
||||
echo "${versions[0]}"
|
||||
return 0
|
||||
}
|
||||
|
||||
detectVersion() {
|
||||
|
||||
local xml="$1"
|
||||
local suggested="${2:-}"
|
||||
local id platform
|
||||
|
||||
platform=$(getPlatform "$xml")
|
||||
id=$(selectVersion "DISPLAYNAME" "$xml" "$platform" "$suggested")
|
||||
[ -z "$id" ] &&
|
||||
id=$(selectVersion "PRODUCTNAME" "$xml" "$platform" "$suggested")
|
||||
[ -z "$id" ] &&
|
||||
id=$(selectVersion "NAME" "$xml" "$platform" "$suggested")
|
||||
|
||||
echo "$id"
|
||||
return 0
|
||||
}
|
||||
|
||||
getImageIndex() {
|
||||
|
||||
local xml="$1"
|
||||
local wanted="$2"
|
||||
local platform tag index name id
|
||||
|
||||
local -a matches=()
|
||||
|
||||
[ -z "$wanted" ] && return 1
|
||||
|
||||
platform=$(getPlatform "$xml")
|
||||
|
||||
for tag in DISPLAYNAME PRODUCTNAME NAME; do
|
||||
|
||||
matches=()
|
||||
|
||||
while IFS=$'\t' read -r index name; do
|
||||
[ -n "$index" ] || continue
|
||||
[[ "$name" == *"Operating System"* ]] && continue
|
||||
@@ -249,8 +333,7 @@ getImageIndex() {
|
||||
id=$(getVersion "$name" "$platform")
|
||||
[[ "${id,,}" == "${wanted,,}" ]] || continue
|
||||
|
||||
echo "$index"
|
||||
return 0
|
||||
matches+=("$index")
|
||||
done < <(
|
||||
awk -v tag="$tag" '
|
||||
/<IMAGE INDEX="/ {
|
||||
@@ -272,6 +355,21 @@ getImageIndex() {
|
||||
' <<< "$xml"
|
||||
)
|
||||
|
||||
case "${#matches[@]}" in
|
||||
0 )
|
||||
continue
|
||||
;;
|
||||
1 )
|
||||
echo "${matches[0]}"
|
||||
return 0
|
||||
;;
|
||||
* )
|
||||
# The current field is ambiguous, so try the remaining WIM fields
|
||||
# before concluding that no unique image index can be determined.
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
|
||||
done
|
||||
|
||||
return 1
|
||||
@@ -426,7 +524,7 @@ detectImage() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
local src wim info index suggested
|
||||
local src wim info index suggested edition rc=0
|
||||
src=$(find "$dir" -maxdepth 1 -type d -iname sources -print -quit)
|
||||
|
||||
if [ ! -d "$src" ]; then
|
||||
@@ -442,11 +540,17 @@ detectImage() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! info=$(wimlib-imagex info -xml "$wim" |
|
||||
iconv -f UTF-16LE -t UTF-8); then
|
||||
info=$(wimlib-imagex info -xml "$wim" |
|
||||
iconv -f UTF-16LE -t UTF-8) || {
|
||||
rc=$?
|
||||
|
||||
if (( rc >= 129 )); then
|
||||
exit "$rc"
|
||||
fi
|
||||
|
||||
warn "failed to read Windows image information, $FB"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
checkPlatform "$info" || exit 67
|
||||
|
||||
@@ -458,6 +562,21 @@ detectImage() {
|
||||
|
||||
DETECTED=$(detectVersion "$info" "$suggested")
|
||||
|
||||
if [ -n "$EDITION" ]; then
|
||||
case "${DETECTED,,}" in
|
||||
"win2003"* | "win2008"* | "win2012"* | "win2016"* | \
|
||||
"win2019"* | "win2022"* | "win2025"* )
|
||||
edition=$(normalizeServerEditionID "$EDITION")
|
||||
|
||||
if [ -n "$edition" ] &&
|
||||
[[ "${DETECTED,,}" != *"-${edition,,}" &&
|
||||
"${DETECTED,,}" != *"-${edition,,}-eval" ]]; then
|
||||
EDITION=""
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ -z "$DETECTED" ]; then
|
||||
msg="Failed to determine Windows version from image"
|
||||
|
||||
@@ -493,7 +612,7 @@ detectImage() {
|
||||
msg="the answer file for $desc was not found ($DETECTED.xml)"
|
||||
local fallback="/run/assets/${DETECTED%%-*}.xml"
|
||||
|
||||
if setXML "$fallback" || enabled "$MANUAL"; then
|
||||
if setXML "$fallback" "$index" || enabled "$MANUAL"; then
|
||||
! enabled "$MANUAL" && warn "${msg}."
|
||||
else
|
||||
MANUAL="Y"
|
||||
|
||||
+5
-17
@@ -1013,23 +1013,7 @@ updateImage() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
local fallback="/run/assets/${DETECTED%%-*}.xml"
|
||||
|
||||
if [[ "$DETECTED" != win20* &&
|
||||
"$asset" == "$fallback" &&
|
||||
"$asset" != "/run/assets/$DETECTED.xml" ]]; then
|
||||
|
||||
if ! sed -i \
|
||||
-e '/<InstallFrom>.*<\/InstallFrom>/d' \
|
||||
-e '/<ProductKey>.*<\/ProductKey>/d' \
|
||||
-e '/<InstallFrom>/,/<\/InstallFrom>/d' \
|
||||
-e '/<ProductKey>/,/<\/ProductKey>/d' \
|
||||
"$answer"; then
|
||||
error "Failed to make answer file edition-neutral: $answer"
|
||||
return 1
|
||||
fi
|
||||
|
||||
fi
|
||||
removeGeneratedXML "$asset" || return 1
|
||||
|
||||
if [ -n "${CUSTOM_XML:-}" ]; then
|
||||
|
||||
@@ -1058,6 +1042,8 @@ updateImage() {
|
||||
|
||||
if enabled "$MANUAL"; then
|
||||
|
||||
removeGeneratedXML "$asset" || return 1
|
||||
|
||||
wimlib-imagex update "$wim" "$idx" --command "delete --force /$xml" > /dev/null || true
|
||||
|
||||
if wimlib-imagex extract "$wim" "$idx" "/$bak" "--dest-dir=$tmp" >/dev/null 2>&1; then
|
||||
@@ -1204,6 +1190,8 @@ bootWindows() {
|
||||
! parseLanguage && exit 56
|
||||
! detectCustom && exit 59
|
||||
|
||||
testImages
|
||||
|
||||
if ! startInstall; then
|
||||
bootWindows && return 0
|
||||
exit 68
|
||||
|
||||
+259
-6
@@ -853,8 +853,8 @@ verifyFile() {
|
||||
fi
|
||||
fi
|
||||
|
||||
local hash=""
|
||||
local algo="SHA256"
|
||||
local hash="" rc=0
|
||||
|
||||
[ -z "$check" ] && return 0
|
||||
! enabled "$VERIFY" && return 0
|
||||
@@ -864,15 +864,31 @@ verifyFile() {
|
||||
info "$msg" && html "$msg"
|
||||
|
||||
if [[ "${algo,,}" != "sha256" ]]; then
|
||||
if ! hash=$(sha1sum "$iso" | cut -f1 -d' '); then
|
||||
|
||||
hash=$(sha1sum "$iso" | cut -f1 -d' ') || {
|
||||
rc=$?
|
||||
|
||||
if (( rc >= 129 )); then
|
||||
exit "$rc"
|
||||
fi
|
||||
|
||||
error "Failed to calculate SHA1 checksum for $iso!"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
else
|
||||
if ! hash=$(sha256sum "$iso" | cut -f1 -d' '); then
|
||||
|
||||
hash=$(sha256sum "$iso" | cut -f1 -d' ') || {
|
||||
rc=$?
|
||||
|
||||
if (( rc >= 129 )); then
|
||||
exit "$rc"
|
||||
fi
|
||||
|
||||
error "Failed to calculate SHA256 checksum for $iso!"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
fi
|
||||
|
||||
if [[ "$hash" == "$check" ]]; then
|
||||
@@ -993,11 +1009,237 @@ fallbackEnglish() {
|
||||
downloadImage "$iso" "$version" "$LANGUAGE"
|
||||
}
|
||||
|
||||
testDownload() {
|
||||
|
||||
local file="$1"
|
||||
local url="$2"
|
||||
local sum="$3"
|
||||
local size="$4"
|
||||
local desc="$5"
|
||||
local web_desc="$6"
|
||||
local total failed=""
|
||||
|
||||
if ! rm -f -- "$file" "$file.aria2"; then
|
||||
error "Failed to remove previous test download: $file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Call downloadFile() directly so downloadRetry(), delays and retries
|
||||
# from the normal installation path are not used.
|
||||
if ! downloadFile \
|
||||
"$file" \
|
||||
"$url" \
|
||||
"$size" \
|
||||
"$desc" \
|
||||
"$web_desc" \
|
||||
"${CONNECTIONS:-1}"; then
|
||||
failed="Y"
|
||||
elif ! total=$(stat -c%s -- "$file" 2>/dev/null); then
|
||||
error "Failed to determine downloaded file size: $file"
|
||||
failed="Y"
|
||||
else
|
||||
|
||||
if [ -n "$size" ] && [[ "$size" != "0" && "$total" != "$size" ]]; then
|
||||
error "The downloaded file has a different size ( $total bytes) than expected ( $size bytes)."
|
||||
failed="Y"
|
||||
fi
|
||||
|
||||
# Size was checked strictly above. Passing an empty expected size avoids
|
||||
# the normal warning-only size handling while still verifying the hash.
|
||||
if ! verifyFile "$file" "" "$total" "$sum"; then
|
||||
failed="Y"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if ! rm -f -- "$file" "$file.aria2"; then
|
||||
error "Failed to remove test download: $file"
|
||||
failed="Y"
|
||||
fi
|
||||
|
||||
[ -z "$failed" ]
|
||||
}
|
||||
|
||||
downloadTest() {
|
||||
|
||||
local version="$1"
|
||||
local lang="$2"
|
||||
local normal="$version"
|
||||
local dir="$STORAGE/tmp/download-test"
|
||||
local file="$dir/test.iso"
|
||||
local tested=0 failed=0
|
||||
local url sum size base desc web_desc language i
|
||||
|
||||
# Dynamically scoped, so verifyFile() validates every available checksum.
|
||||
local VERIFY="Y"
|
||||
|
||||
if ! rm -rf -- "$dir" || ! makeDir "$dir"; then
|
||||
error "Failed to create download test directory: $dir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ "${version,,}" == "http"* ]]; then
|
||||
|
||||
base=$(basename "${version%%\?*}")
|
||||
desc=$(fromFile "$base")
|
||||
web_desc="$desc"
|
||||
tested=$((tested + 1))
|
||||
|
||||
info "Testing custom download..."
|
||||
|
||||
if ! testDownload "$file" "$version" "" "" "$desc" "$web_desc"; then
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
if ! validVersion "$version" "en"; then
|
||||
error "Invalid VERSION specified, value \"$version\" is not recognized!"
|
||||
rm -rf -- "$dir" 2>/dev/null || true
|
||||
return 1
|
||||
fi
|
||||
|
||||
desc=$(printVariant "$version" "" "Y")
|
||||
web_desc=$(printVariant "$version" "")
|
||||
|
||||
if [[ "${lang,,}" != "en" && "${lang,,}" != "en-"* ]]; then
|
||||
language=$(getLanguage "$lang" "desc")
|
||||
desc+=" in $language"
|
||||
web_desc+=" in $language"
|
||||
fi
|
||||
|
||||
if isMido "$version" "$lang"; then
|
||||
|
||||
tested=$((tested + 1))
|
||||
MIDO_URL=""
|
||||
|
||||
info "Testing MIDO download..."
|
||||
|
||||
if ! getWindows "$version" "$lang" "$desc" "$web_desc" ||
|
||||
[ -z "$MIDO_URL" ]; then
|
||||
failed=$((failed + 1))
|
||||
else
|
||||
|
||||
url=$(getMido "$version" "$lang" "")
|
||||
sum=""
|
||||
size=""
|
||||
|
||||
# Skip static verification if Microsoft returned a different URL.
|
||||
if [[ "${MIDO_URL%%\?*}" == "${url%%\?*}" ]]; then
|
||||
size=$(getMido "$version" "$lang" "size")
|
||||
sum=$(getMido "$version" "$lang" "sum")
|
||||
fi
|
||||
|
||||
if ! testDownload \
|
||||
"$file" \
|
||||
"$MIDO_URL" \
|
||||
"$sum" \
|
||||
"$size" \
|
||||
"$desc" \
|
||||
"$web_desc"; then
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# Evaluation media only exists through MIDO. ESD and mirrors use the
|
||||
# corresponding normal version.
|
||||
[[ "${normal,,}" == *"-eval" ]] && normal="${normal::-5}"
|
||||
|
||||
desc=$(printVariant "$normal" "" "Y")
|
||||
web_desc=$(printVariant "$normal" "")
|
||||
|
||||
if [[ "${lang,,}" != "en" && "${lang,,}" != "en-"* ]]; then
|
||||
desc+=" in $language"
|
||||
web_desc+=" in $language"
|
||||
fi
|
||||
|
||||
if isESD "$normal" "$lang"; then
|
||||
|
||||
tested=$((tested + 1))
|
||||
ESD=""
|
||||
|
||||
info "Testing ESD download..."
|
||||
|
||||
if ! getESD "$dir/esd" "$normal" "$lang" "$desc"; then
|
||||
failed=$((failed + 1))
|
||||
elif ! testDownload \
|
||||
"$dir/test.esd" \
|
||||
"$ESD" \
|
||||
"$ESD_SUM" \
|
||||
"$ESD_SIZE" \
|
||||
"$desc" \
|
||||
"$web_desc"; then
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
for ((i=1;i<=MIRRORS;i++)); do
|
||||
|
||||
url=$(getLink "$i" "$normal" "$lang")
|
||||
[ -z "$url" ] && continue
|
||||
|
||||
tested=$((tested + 1))
|
||||
size=$(getSize "$i" "$normal" "$lang")
|
||||
sum=$(getHash "$i" "$normal" "$lang")
|
||||
|
||||
info "Testing download mirror $i: $(getHost "$url")..."
|
||||
|
||||
if ! testDownload \
|
||||
"$file" \
|
||||
"$url" \
|
||||
"$sum" \
|
||||
"$size" \
|
||||
"$desc" \
|
||||
"$web_desc"; then
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
fi
|
||||
|
||||
if ! rm -rf -- "$dir"; then
|
||||
error "Failed to remove download test directory: $dir"
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
|
||||
if (( tested == 0 )); then
|
||||
error "No download methods are available for $version."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if (( failed > 0 )); then
|
||||
error "$failed of $tested download methods failed."
|
||||
return 1
|
||||
fi
|
||||
|
||||
info "All $tested download methods completed successfully."
|
||||
return 0
|
||||
}
|
||||
|
||||
testImages() {
|
||||
|
||||
disabled "${TEST:-}" && return 0
|
||||
|
||||
if downloadTest "$VERSION" "$LANGUAGE"; then
|
||||
info "Download test completed successfully."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
error "Download test failed."
|
||||
exit 61
|
||||
}
|
||||
|
||||
downloadImage() {
|
||||
|
||||
local iso="$1"
|
||||
local version="$2"
|
||||
local lang="$3"
|
||||
local requested="$version"
|
||||
local tried="n"
|
||||
local success="n"
|
||||
local seconds="5"
|
||||
@@ -1073,6 +1315,17 @@ downloadImage() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if switchEdition version; then
|
||||
|
||||
desc=$(printVariant "$DETECTED" "" "Y")
|
||||
web_desc=$(printVariant "$DETECTED" "")
|
||||
|
||||
if [[ "${lang,,}" != "en" && "${lang,,}" != "en-"* ]]; then
|
||||
desc+=" in $language"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if isESD "$version" "$lang"; then
|
||||
|
||||
if [[ "$tried" != "n" ]]; then
|
||||
@@ -1122,7 +1375,7 @@ downloadImage() {
|
||||
done
|
||||
|
||||
if [[ "${lang,,}" != "en" && "${lang,,}" != "en-"* ]]; then
|
||||
if fallbackEnglish "$iso" "$version" "$lang" "$desc" "$web_desc"; then
|
||||
if fallbackEnglish "$iso" "$requested" "$lang" "$desc" "$web_desc"; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user