Compare commits

...

43 commits

Author SHA1 Message Date
Kroese 63d2fe1be5
Update mido.sh 2024-05-17 02:18:53 +02:00
Kroese 4615753e89
Update mido.sh 2024-05-17 02:14:41 +02:00
Kroese 283d23804d
Update install.sh 2024-05-17 02:13:38 +02:00
Kroese 1916f5fae0
Update mido.sh 2024-05-17 02:04:32 +02:00
Kroese d03a3186fb
Update mido.sh 2024-05-17 01:43:34 +02:00
Kroese a850269ef5
Update define.sh 2024-05-17 01:41:13 +02:00
Kroese d373bc04dd
Update mido.sh 2024-05-17 01:32:43 +02:00
Kroese 8a8a3e02e8
Update mido.sh 2024-05-17 01:31:16 +02:00
Kroese de0f92122a
Update mido.sh 2024-05-17 01:27:46 +02:00
Kroese 4b0e0a5bb7
Update define.sh 2024-05-17 01:25:11 +02:00
Kroese a2a8e99c35
Update mido.sh 2024-05-17 01:22:35 +02:00
Kroese 29c21c5da8
Update mido.sh 2024-05-17 00:56:31 +02:00
Kroese f91c55b948
Update mido.sh 2024-05-17 00:50:34 +02:00
Kroese 76dd32f10c
Update mido.sh 2024-05-17 00:43:58 +02:00
Kroese 409bfe3a89
Update mido.sh 2024-05-17 00:37:25 +02:00
Kroese 954e0d4133
Update mido.sh 2024-05-17 00:29:37 +02:00
Kroese 0029bee92e
Update mido.sh 2024-05-17 00:28:18 +02:00
Kroese 00c02c1bf6
Update mido.sh 2024-05-17 00:14:43 +02:00
Kroese 11b09e47d0
Update mido.sh 2024-05-17 00:14:16 +02:00
Kroese cf32552a39
Update mido.sh 2024-05-17 00:03:47 +02:00
Kroese 699fc384d4
Update mido.sh 2024-05-16 23:40:30 +02:00
Kroese 6d707f6672
Update mido.sh 2024-05-16 23:38:23 +02:00
Kroese 645e0f0f9f
Update mido.sh 2024-05-16 23:36:37 +02:00
Kroese 7232ed21a1
Update mido.sh 2024-05-16 23:18:59 +02:00
Kroese a46fad55d3
Update mido.sh 2024-05-16 23:12:42 +02:00
Kroese 26a09808bf
Update mido.sh 2024-05-16 23:05:36 +02:00
Kroese 1708edd80b
Update mido.sh 2024-05-16 23:04:01 +02:00
Kroese 9e1fb816ff
feat: Refactor download code 2024-05-16 22:35:11 +02:00
Kroese c8babc636f
feat: Refactor download code 2024-05-16 22:28:12 +02:00
Kroese 4a3398b440
feat: Refactor download code 2024-05-16 22:25:46 +02:00
Kroese 0234729ecb
Update Dockerfile 2024-05-16 22:17:39 +02:00
Kroese c695181bf0
Update Dockerfile 2024-05-16 22:16:38 +02:00
Kroese 87e56fe0e7
feat: Refactor download code 2024-05-16 21:47:33 +02:00
Kroese 3aee40f160
feat: Refactor download code 2024-05-16 20:36:16 +02:00
Kroese 34f9d45108
feat: Refactor download code 2024-05-16 20:19:17 +02:00
Kroese c1d6ec9ffe
feat: Refactor download code 2024-05-16 20:12:23 +02:00
Kroese e7b39e6ffc
feat: Refactor download code 2024-05-16 20:07:44 +02:00
Kroese fca9072898
feat: Refactor download code 2024-05-16 19:59:16 +02:00
Kroese 558ab47cea
feat: Refactor download code 2024-05-16 19:54:32 +02:00
Kroese 999d57084c
feat: Refactor download code 2024-05-16 19:51:23 +02:00
Kroese bcae60c9ec
feat: Refactor download code 2024-05-16 19:48:47 +02:00
Kroese d664bd0cf7
feat: Refactor download code 2024-05-16 19:48:11 +02:00
Kroese 355455cf13
feat: Refactor download code 2024-05-16 19:45:19 +02:00
4 changed files with 516 additions and 212 deletions

View file

@ -377,51 +377,11 @@ switchEdition() {
return 0
}
getCatalog() {
local id="$1"
local ret="$2"
local url=""
local name=""
local edition=""
case "${id,,}" in
"win11${PLATFORM,,}" )
edition="Professional"
name="Windows 11 Pro"
url="https://go.microsoft.com/fwlink?linkid=2156292"
;;
"win10${PLATFORM,,}" )
edition="Professional"
name="Windows 10 Pro"
url="https://go.microsoft.com/fwlink/?LinkId=841361"
;;
"win11${PLATFORM,,}-enterprise" | "win11${PLATFORM,,}-enterprise-eval")
edition="Enterprise"
name="Windows 11 Enterprise"
url="https://go.microsoft.com/fwlink?linkid=2156292"
;;
"win10${PLATFORM,,}-enterprise" | "win10${PLATFORM,,}-enterprise-eval" )
edition="Enterprise"
name="Windows 10 Enterprise"
url="https://go.microsoft.com/fwlink/?LinkId=841361"
;;
esac
case "${ret,,}" in
"url" ) echo "$url" ;;
"name" ) echo "$name" ;;
"edition" ) echo "$edition" ;;
*) echo "";;
esac
return 0
}
getMido() {
local id="$1"
local ret="$2"
local lang="$2"
local ret="$3"
local sum=""
local size=""
@ -490,7 +450,8 @@ getLink1() {
# Fallbacks for users who cannot connect to the Microsoft servers
local id="$1"
local ret="$2"
local lang="$2"
local ret="$3"
local url=""
local sum=""
local size=""
@ -601,7 +562,8 @@ getLink1() {
getLink2() {
local id="$1"
local ret="$2"
local lang="$2"
local ret="$3"
local url=""
local sum=""
local size=""
@ -692,7 +654,8 @@ getLink2() {
getLink3() {
local id="$1"
local ret="$2"
local lang="$2"
local ret="$3"
local url=""
local sum=""
local size=""
@ -730,7 +693,8 @@ getLink4() {
# Fallbacks for users who cannot connect to the Microsoft servers
local id="$1"
local ret="$2"
local lang="$2"
local ret="$3"
local url=""
local sum=""
local size=""
@ -856,7 +820,8 @@ getLink4() {
getLink5() {
local id="$1"
local ret="$2"
local lang="$2"
local ret="$3"
local url=""
local sum=""
local size=""
@ -897,12 +862,13 @@ getLink5() {
getValue() {
local val=""
local id="$3"
local type="$2"
local id="$2"
local lang="$3"
local type="$4"
local func="getLink$1"
if [ "$1" -gt 0 ] && [ "$1" -le "$MIRRORS" ]; then
val=$($func "$id" "$type")
val=$($func "$id" "$type" "$lang")
fi
echo "$val"
@ -911,8 +877,8 @@ getValue() {
getLink() {
local url=""
url=$(getValue "$1" "" "$2")
local url
url=$(getValue "$1" "$2" "$3" "")
echo "$url"
return 0
@ -920,8 +886,8 @@ getLink() {
getHash() {
local sum=""
sum=$(getValue "$1" "sum" "$2")
local sum
sum=$(getValue "$1" "$2" "$3" "sum")
echo "$sum"
return 0
@ -929,8 +895,8 @@ getHash() {
getSize() {
local size=""
size=$(getValue "$1" "size" "$2")
local size
size=$(getValue "$1" "$2" "$3" "size")
echo "$size"
return 0
@ -939,9 +905,10 @@ getSize() {
isMido() {
local id="$1"
local lang="$2"
local sum
sum=$(getMido "$id" "sum")
sum=$(getMido "$id" "$lang" "sum")
[ -n "$sum" ] && return 0
return 1
@ -950,10 +917,19 @@ isMido() {
isESD() {
local id="$1"
local url
local lang="$2"
url=$(getCatalog "$id" "url")
[ -n "$url" ] && return 0
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" )
return 0
;;
esac
return 1
}
@ -961,14 +937,15 @@ isESD() {
validVersion() {
local id="$1"
local lang="$2"
local url
isESD "$id" && return 0
isMido "$id" && return 0
isESD "$id" "$lang" && return 0
isMido "$id" "$lang" && return 0
for ((i=1;i<=MIRRORS;i++)); do
url=$(getLink "$i" "$id")
url=$(getLink "$i" "$id" "$lang")
[ -n "$url" ] && return 0
done

View file

@ -10,6 +10,7 @@ cd /run
. reset.sh # Initialize system
. define.sh # Define versions
. mido.sh # Download code
. install.sh # Run installation
. disk.sh # Initialize disks
. display.sh # Initialize graphics

View file

@ -209,79 +209,6 @@ detectCustom() {
return 0
}
downloadImage() {
local iso="$1"
local version="$2"
local tried="n"
local url sum size base desc
if [[ "${version,,}" == "http"* ]]; then
base=$(basename "$iso")
desc=$(fromFile "$base")
downloadFile "$iso" "$version" "" "" "$desc" && return 0
return 1
fi
if ! validVersion "$version"; then
error "Invalid VERSION specified, value \"$version\" is not recognized!" && return 1
fi
desc=$(printVersion "$version" "")
if isMido "$version"; then
tried="y"
doMido "$iso" "$version" "$desc" && return 0
fi
switchEdition "$version"
if isESD "$version"; then
if [[ "$tried" != "n" ]]; then
info "Failed to download $desc using Mido, will try a diferent method now..."
fi
tried="y"
if getESD "$TMP/esd" "$version"; then
ISO="${ISO%.*}.esd"
downloadFile "$ISO" "$ESD" "$ESD_SUM" "$ESD_SIZE" "$desc" && return 0
ISO="$iso"
fi
fi
for ((i=1;i<=MIRRORS;i++)); do
url=$(getLink "$i" "$version")
if [ -n "$url" ]; then
if [[ "$tried" != "n" ]]; then
info "Failed to download $desc, will try another mirror now..."
fi
tried="y"
size=$(getSize "$i" "$version")
sum=$(getHash "$i" "$version")
downloadFile "$iso" "$url" "$sum" "$size" "$desc" && return 0
fi
done
return 1
}
removeDownload() {
local iso="$1"
[ ! -f "$iso" ] && return 0
[ -n "$CUSTOM" ] && return 0
! rm -f "$iso" 2> /dev/null && warn "failed to remove $iso !"
return 0
}
extractESD() {
local iso="$1"
@ -415,19 +342,6 @@ extractImage() {
return 0
}
setXML() {
local file="/custom.xml"
[ ! -f "$file" ] || [ ! -s "$file" ] && file="$STORAGE/custom.xml"
[ ! -f "$file" ] || [ ! -s "$file" ] && file="/run/assets/custom.xml"
[ ! -f "$file" ] || [ ! -s "$file" ] && file="$1"
[ ! -f "$file" ] || [ ! -s "$file" ] && file="/run/assets/$DETECTED.xml"
[ ! -f "$file" ] || [ ! -s "$file" ] && return 1
XML="$file"
return 0
}
getPlatform() {
local xml="$1"
@ -447,6 +361,26 @@ getPlatform() {
return 0
}
checkPlatform() {
local xml="$1"
local platform compat
platform=$(getPlatform "$xml")
case "${platform,,}" in
"x86" ) compat="x64" ;;
"x64" ) compat="$platform" ;;
"arm64" ) compat="$platform" ;;
* ) compat="${PLATFORM,,}" ;;
esac
[[ "${compat,,}" == "${PLATFORM,,}" ]] && return 0
error "You cannot boot ${platform^^} images on a $PLATFORM CPU!"
return 1
}
hasVersion() {
local id="$1"
@ -492,26 +426,6 @@ selectVersion() {
return 0
}
checkPlatform() {
local xml="$1"
local platform compat
platform=$(getPlatform "$xml")
case "${platform,,}" in
"x86" ) compat="x64" ;;
"x64" ) compat="$platform" ;;
"arm64" ) compat="$platform" ;;
* ) compat="${PLATFORM,,}" ;;
esac
[[ "${compat,,}" == "${PLATFORM,,}" ]] && return 0
error "You cannot boot ${platform^^} images on a $PLATFORM CPU!"
return 1
}
detectVersion() {
local xml="$1"
@ -526,6 +440,19 @@ detectVersion() {
return 0
}
setXML() {
local file="/custom.xml"
[ ! -f "$file" ] || [ ! -s "$file" ] && file="$STORAGE/custom.xml"
[ ! -f "$file" ] || [ ! -s "$file" ] && file="/run/assets/custom.xml"
[ ! -f "$file" ] || [ ! -s "$file" ] && file="$1"
[ ! -f "$file" ] || [ ! -s "$file" ] && file="/run/assets/$DETECTED.xml"
[ ! -f "$file" ] || [ ! -s "$file" ] && return 1
XML="$file"
return 0
}
detectImage() {
local dir="$1"
@ -746,6 +673,17 @@ updateImage() {
return 0
}
removeDownload() {
local iso="$1"
[ ! -f "$iso" ] && return 0
[ -n "$CUSTOM" ] && return 0
! rm -f "$iso" 2> /dev/null && warn "failed to remove $iso !"
return 0
}
copyOEM() {
local dir="$1"
@ -919,7 +857,7 @@ if ! startInstall; then
fi
if [ ! -s "$ISO" ] || [ ! -f "$ISO" ]; then
if ! downloadImage "$ISO" "$VERSION"; then
if ! downloadImage "$ISO" "$VERSION" "English (United States)"; then
rm -f "$ISO" 2> /dev/null || true
exit 61
fi

View file

@ -1,21 +1,379 @@
#!/usr/bin/env bash
set -Eeuo pipefail
handle_curl_error() {
local error_code="$1"
case "$error_code" in
6) error "Failed to resolve Microsoft servers! Is there an Internet connection?" ;;
7) error "Failed to contact Microsoft servers! Is there an Internet connection or is the server down?" ;;
8) error "Microsoft servers returned a malformed HTTP response!" ;;
22) error "Microsoft servers returned a failing HTTP status code!" ;;
23) error "Failed at writing Windows media to disk! Out of disk space or permission error?" ;;
26) error "Ran out of memory during download!" ;;
28) error "Connection timed out to Microsoft server!" ;;
35) error "SSL connection error from Microsoft server!" ;;
36) error "Failed to continue earlier download!" ;;
52) error "Received no data from the Microsoft server!" ;;
63) error "Microsoft servers returned an unexpectedly large response!" ;;
# POSIX defines exit statuses 1-125 as usable by us
# https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_08_02
$((error_code <= 125)))
# Must be some other server or network error (possibly with this specific request/file)
# This is when accounting for all possible errors in the curl manual assuming a correctly formed curl command and an HTTP(S) request, using only the curl features we're using, and a sane build
error "Miscellaneous server or network error, reason: $error_code"
;;
126 | 127 ) error "Curl command not found!" ;;
# Exit statuses are undefined by POSIX beyond this point
*)
case "$(kill -l "$error_code")" in
# Signals defined to exist by POSIX:
# https://pubs.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html
INT) error "Curl was interrupted!" ;;
# There could be other signals but these are most common
SEGV | ABRT ) error "Curl crashed! Failed exploitation attempt? Please report any core dumps to curl developers." ;;
*) error "Curl terminated due to a fatal signal!" ;;
esac
esac
return 1
}
download_windows() {
local id="$1"
local language="$2"
local sku_id=""
local session_id=""
local browser_version=""
local windows_version=""
local iso_download_link=""
local product_edition_id=""
local iso_download_link_html=""
local iso_download_page_html=""
local language_skuid_table_html=""
case "${id,,}" in
"win11${PLATFORM,,}" ) windows_version="11" ;;
"win10${PLATFORM,,}" ) windows_version="10" ;;
"win81${PLATFORM,,}" ) windows_version="8" ;;
* ) error "Invalid VERSION specified, value \"$id\" is not recognized!" && return 1 ;;
esac
local url="https://www.microsoft.com/en-us/software-download/windows$windows_version"
case "$windows_version" in
8 | 10) url="${url}ISO";;
esac
# Determine approximate latest Firefox release
browser_version="$((124 + ($(date +%s) - 1710892800) / 2419200))"
local user_agent="Mozilla/5.0 (X11; Linux x86_64; rv:${browser_version}.0) Gecko/20100101 Firefox/${browser_version}.0"
# uuidgen: For MacOS (installed by default) and other systems (e.g. with no /proc) that don't have a kernel interface for generating random UUIDs
session_id="$(cat /proc/sys/kernel/random/uuid 2> /dev/null || uuidgen --random)"
# Get product edition ID for latest release of given Windows version
# Product edition ID: This specifies both the Windows release (e.g. 22H2) and edition ("multi-edition" is default, either Home/Pro/Edu/etc., we select "Pro" in the answer files) in one number
# This is the *only* request we make that Fido doesn't. Fido manually maintains a list of all the Windows release/edition product edition IDs in its script (see: $WindowsVersions array). This is helpful for downloading older releases (e.g. Windows 10 1909, 21H1, etc.) but we always want to get the newest release which is why we get this value dynamically
# Also, keeping a "$WindowsVersions" array like Fido does would be way too much of a maintenance burden
# Remove "Accept" header that curl sends by default
[[ "$DEBUG" == [Yy1]* ]] && echo " - Parsing download page: ${url}"
iso_download_page_html="$(curl --silent --max-time 15 --user-agent "$user_agent" --header "Accept:" --max-filesize 1M --fail --proto =https --tlsv1.2 --http1.1 -- "$url")" || {
handle_curl_error $?
return $?
}
[[ "$DEBUG" == [Yy1]* ]] && echo -n " - Getting Product edition ID: "
# tr: Filter for only numerics to prevent HTTP parameter injection
# head -c was recently added to POSIX: https://austingroupbugs.net/view.php?id=407
product_edition_id="$(echo "$iso_download_page_html" | grep -Eo '<option value="[0-9]+">Windows' | cut -d '"' -f 2 | head -n 1 | tr -cd '0-9' | head -c 16)"
[[ "$DEBUG" == [Yy1]* ]] && echo "$product_edition_id"
[[ "$DEBUG" == [Yy1]* ]] && echo " - Permit Session ID: $session_id"
# Permit Session ID
# "org_id" is always the same value
curl --silent --max-time 15 --output /dev/null --user-agent "$user_agent" --header "Accept:" --max-filesize 100K --fail --proto =https --tlsv1.2 --http1.1 -- "https://vlscppe.microsoft.com/tags?org_id=y6jn8c31&session_id=$session_id" || {
# This should only happen if there's been some change to how this API works
handle_curl_error $?
return $?
}
# Extract everything after the last slash
local url_segment_parameter="${url##*/}"
[[ "$DEBUG" == [Yy1]* ]] && echo -n " - Getting language SKU ID: "
# Get language -> skuID association table
# SKU ID: This specifies the language of the ISO. We always use "English (United States)", however, the SKU for this changes with each Windows release
# We must make this request so our next one will be allowed
# --data "" is required otherwise no "Content-Length" header will be sent causing HTTP response "411 Length Required"
language_skuid_table_html="$(curl --silent --max-time 15 --request POST --user-agent "$user_agent" --data "" --header "Accept:" --max-filesize 10K --fail --proto =https --tlsv1.2 --http1.1 -- "https://www.microsoft.com/en-US/api/controls/contentinclude/html?pageId=a8f8f489-4c7f-463a-9ca6-5cff94d8d041&host=www.microsoft.com&segments=software-download,$url_segment_parameter&query=&action=getskuinformationbyproductedition&sessionId=$session_id&productEditionId=$product_edition_id&sdVersion=2")" || {
handle_curl_error $?
return $?
}
[ -z "$language" ] && language="English (United States)"
# Limit untrusted size for input validation
language_skuid_table_html="$(echo "$language_skuid_table_html" | head -c 10240)"
# tr: Filter for only alphanumerics or "-" to prevent HTTP parameter injection
sku_id="$(echo "$language_skuid_table_html" | grep "${language}" | sed 's/&quot;//g' | cut -d ',' -f 1 | cut -d ':' -f 2 | tr -cd '[:alnum:]-' | head -c 16)"
[[ "$DEBUG" == [Yy1]* ]] && echo "$sku_id"
[[ "$DEBUG" == [Yy1]* ]] && echo " - Getting ISO download link..."
# Get ISO download link
# If any request is going to be blocked by Microsoft it's always this last one (the previous requests always seem to succeed)
# --referer: Required by Microsoft servers to allow request
iso_download_link_html="$(curl --silent --max-time 15 --request POST --user-agent "$user_agent" --data "" --referer "$url" --header "Accept:" --max-filesize 100K --fail --proto =https --tlsv1.2 --http1.1 -- "https://www.microsoft.com/en-US/api/controls/contentinclude/html?pageId=6e2a1789-ef16-4f27-a296-74ef7ef5d96b&host=www.microsoft.com&segments=software-download,$url_segment_parameter&query=&action=GetProductDownloadLinksBySku&sessionId=$session_id&skuId=$sku_id&language=English&sdVersion=2")"
if ! [ "$iso_download_link_html" ]; then
# This should only happen if there's been some change to how this API works
error "Microsoft servers gave us an empty response to our request for an automated download."
return 1
fi
if echo "$iso_download_link_html" | grep -q "We are unable to complete your request at this time."; then
error "Microsoft blocked the automated download request based on your IP address."
return 1
fi
# Filter for 64-bit ISO download URL
# sed: HTML decode "&" character
# tr: Filter for only alphanumerics or punctuation
iso_download_link="$(echo "$iso_download_link_html" | grep -o "https://software.download.prss.microsoft.com.*IsoX64" | cut -d '"' -f 1 | sed 's/&amp;/\&/g' | tr -cd '[:alnum:][:punct:]')"
if ! [ "$iso_download_link" ]; then
# This should only happen if there's been some change to the download endpoint web address
error "Microsoft servers gave us no download link to our request for an automated download!"
return 1
fi
MIDO_URL="$iso_download_link"
return 0
}
download_windows_eval() {
local id="$1"
local language="$2"
local windows_version=""
local enterprise_type=""
case "${id,,}" in
"win11${PLATFORM,,}-enterprise-eval" )
windows_version="windows-11-enterprise"
enterprise_type="enterprise"
;;
"win10${PLATFORM,,}-enterprise-eval" )
windows_version="windows-10-enterprise"
enterprise_type="enterprise"
;;
"win10${PLATFORM,,}-enterprise-ltsc-eval" )
windows_version="windows-10-enterprise"
enterprise_type="ltsc"
;;
"win2022-eval" )
windows_version="windows-server-2022"
enterprise_type="server"
;;
"win2019-eval" )
windows_version="windows-server-2019"
enterprise_type="server"
;;
"win2016-eval" )
windows_version="windows-server-2016"
enterprise_type="server"
;;
"win2012r2-eval" )
windows_version="windows-server-2012-r2"
enterprise_type="server"
;;
* )
error "Invalid VERSION specified, value \"$id\" is not recognized!" && return 1 ;;
esac
local iso_download_page_html=""
local url="https://www.microsoft.com/en-us/evalcenter/download-$windows_version"
[[ "$DEBUG" == [Yy1]* ]] && echo " - Parsing download page: ${url}"
iso_download_page_html="$(curl --silent --max-time 15 --location --max-filesize 1M --fail --proto =https --tlsv1.2 --http1.1 -- "$url")" || {
handle_curl_error $?
return $?
}
if ! [ "$iso_download_page_html" ]; then
# This should only happen if there's been some change to where this download page is located
error "Windows server download page gave us an empty response"
return 1
fi
local COUNTRY="US"
local CULTURE="en-us"
case "$language" in
"English (Great Britain)" )
CULTURE="en-gb"
COUNTRY="GB";;
"Chinese (Simplified)" )
CULTURE="zh-cn"
COUNTRY="CN";;
"Chinese (Traditional)" )
CULTURE="zh-tw"
COUNTRY="TW";;
"French" )
CULTURE="fr-fr"
COUNTRY="FR";;
"German" )
CULTURE="de-de"
COUNTRY="DE";;
"Italian" )
CULTURE="it-it"
COUNTRY="IT";;
"Japanese" )
CULTURE="ja-jp"
COUNTRY="JP";;
"Korean" )
CULTURE="ko-kr"
COUNTRY="KR";;
"Portuguese (Brazil)" )
CULTURE="pt-br"
COUNTRY="BR";;
"Spanish" )
CULTURE="es-es"
COUNTRY="ES";;
"Russian" )
CULTURE="ru-ru"
COUNTRY="RU";;
esac
[[ "$DEBUG" == [Yy1]* ]] && echo " - Getting download link.."
iso_download_links="$(echo "$iso_download_page_html" | grep -o "https://go.microsoft.com/fwlink/p/?LinkID=[0-9]\+&clcid=0x[0-9a-z]\+&culture=${CULTURE}&country=${COUNTRY}")" || {
# This should only happen if there's been some change to the download endpoint web address
error "Windows server download page gave us no download link"
return 1
}
# Limit untrusted size for input validation
iso_download_links="$(echo "$iso_download_links" | head -c 1024)"
case "$enterprise_type" in
# Select x64 download link
"enterprise") iso_download_link=$(echo "$iso_download_links" | head -n 2 | tail -n 1) ;;
# Select x64 LTSC download link
"ltsc") iso_download_link=$(echo "$iso_download_links" | head -n 4 | tail -n 1) ;;
*) iso_download_link="$iso_download_links" ;;
esac
# Follow redirect so proceeding log message is useful
# This is a request we make this Fido doesn't
# We don't need to set "--max-filesize" here because this is a HEAD request and the output is to /dev/null anyway
iso_download_link="$(curl --silent --max-time 15 --location --output /dev/null --silent --write-out "%{url_effective}" --head --fail --proto =https --tlsv1.2 --http1.1 -- "$iso_download_link")" || {
# This should only happen if the Microsoft servers are down
handle_curl_error $?
return $?
}
# Limit untrusted size for input validation
iso_download_link="$(echo "$iso_download_link" | head -c 1024)"
MIDO_URL="$iso_download_link"
return 0
}
getWindows() {
local version="$1"
local language="$2"
local desc="$3"
local msg="Requesting $desc from Microsoft server..."
info "$msg" && html "$msg"
case "${version,,}" in
"win81${PLATFORM,,}" | "win10${PLATFORM,,}" | "win11${PLATFORM,,}" )
download_windows "$version" "$language" && return 0
;;
"win11${PLATFORM,,}-enterprise-eval" )
download_windows_eval "$version" "$language" && return 0
;;
"win10${PLATFORM,,}-enterprise-eval" | "win10${PLATFORM,,}-enterprise-ltsc-eval" )
download_windows_eval "$version" "$language" && return 0
;;
"win2022-eval" | "win2019-eval" | "win2016-eval" | "win2012r2-eval" )
download_windows_eval "$version" "$language" && return 0
;;
"win81${PLATFORM,,}-enterprise-eval" )
MIDO_URL="https://download.microsoft.com/download/B/9/9/B999286E-0A47-406D-8B3D-5B5AD7373A4A/9600.17050.WINBLUE_REFRESH.140317-1640_X64FRE_ENTERPRISE_EVAL_EN-US-IR3_CENA_X64FREE_EN-US_DV9.ISO" && return 0
;;
"win2008r2" )
MIDO_URL="https://download.microsoft.com/download/4/1/D/41DEA7E0-B30D-4012-A1E3-F24DC03BA1BB/7601.17514.101119-1850_x64fre_server_eval_en-us-GRMSXEVAL_EN_DVD.iso" && return 0
;;
* ) error "Invalid VERSION specified, value \"$version\" is not recognized!" ;;
esac
MIDO_URL=""
return 1
}
getCatalog() {
local id="$1"
local ret="$2"
local url=""
local name=""
local edition=""
case "${id,,}" in
"win11${PLATFORM,,}" )
edition="Professional"
name="Windows 11 Pro"
url="https://go.microsoft.com/fwlink?linkid=2156292"
;;
"win10${PLATFORM,,}" )
edition="Professional"
name="Windows 10 Pro"
url="https://go.microsoft.com/fwlink/?LinkId=841361"
;;
"win11${PLATFORM,,}-enterprise" | "win11${PLATFORM,,}-enterprise-eval")
edition="Enterprise"
name="Windows 11 Enterprise"
url="https://go.microsoft.com/fwlink?linkid=2156292"
;;
"win10${PLATFORM,,}-enterprise" | "win10${PLATFORM,,}-enterprise-eval" )
edition="Enterprise"
name="Windows 10 Enterprise"
url="https://go.microsoft.com/fwlink/?LinkId=841361"
;;
esac
case "${ret,,}" in
"url" ) echo "$url" ;;
"name" ) echo "$name" ;;
"edition" ) echo "$edition" ;;
*) echo "";;
esac
return 0
}
getESD() {
local dir="$1"
local version="$2"
local language="$3"
local desc="$4"
local editionName
local winCatalog size
if ! isESD "${version,,}"; then
error "Invalid VERSION specified, value \"$version\" is not recognized!" && return 1
fi
winCatalog=$(getCatalog "$version" "url")
editionName=$(getCatalog "$version" "edition")
local msg="Downloading product information from Microsoft..."
if [ -z "$winCatalog" ] || [ -z "$editionName" ]; then
error "Invalid VERSION specified, value \"$version\" is not recognized!" && return 1
fi
local msg="Downloading product information from Microsoft server..."
info "$msg" && html "$msg"
rm -rf "$dir"
@ -108,43 +466,6 @@ verifyFile() {
return 1
}
doMido() {
local iso="$1"
local version="$2"
local desc="$3"
local rc sum size total
rm -f "$iso"
rm -f "$iso.PART"
size=$(getMido "$version" "size")
sum=$(getMido "$version" "sum")
local msg="Downloading $desc..."
info "$msg" && html "$msg"
/run/progress.sh "$iso.PART" "$size" "Downloading $desc ([P])..." &
cd "$TMP"
{ /run/xmido.sh "${version,,}"; rc=$?; } || :
cd /run
fKill "progress.sh"
if (( rc == 0 )) && [ -f "$iso" ]; then
total=$(stat -c%s "$iso")
if [ "$total" -gt 100000000 ]; then
! verifyFile "$iso" "$size" "$total" "$sum" && return 1
html "Download finished successfully..." && return 0
fi
fi
rm -f "$iso"
rm -f "$iso.PART"
return 1
}
downloadFile() {
local iso="$1"
@ -195,4 +516,71 @@ downloadFile() {
return 1
}
downloadImage() {
local iso="$1"
local version="$2"
local language="$3"
local tried="n"
local url sum size base desc
if [[ "${version,,}" == "http"* ]]; then
base=$(basename "$iso")
desc=$(fromFile "$base")
downloadFile "$iso" "$version" "" "" "$desc" && return 0
return 1
fi
if ! validVersion "$version" "$language"; then
error "Invalid VERSION specified, value \"$version\" is not recognized!" && return 1
fi
desc=$(printVersion "$version" "")
if isMido "$version" "$language"; then
tried="y"
if getWindows "$version" "$language" "$desc"; then
size=$(getMido "$version" "$language" "size" )
sum=$(getMido "$version" "$language" "sum")
downloadFile "$iso" "$MIDO_URL" "$sum" "$size" "$desc" && return 0
fi
fi
switchEdition "$version"
if isESD "$version" "$language"; then
if [[ "$tried" != "n" ]]; then
info "Failed to download $desc, will try a diferent method now..."
fi
tried="y"
if getESD "$TMP/esd" "$version" "$language" "$desc"; then
ISO="${ISO%.*}.esd"
downloadFile "$ISO" "$ESD" "$ESD_SUM" "$ESD_SIZE" "$desc" && return 0
ISO="$iso"
fi
fi
for ((i=1;i<=MIRRORS;i++)); do
url=$(getLink "$i" "$version" "$language")
if [ -n "$url" ]; then
if [[ "$tried" != "n" ]]; then
info "Failed to download $desc, will try another mirror now..."
fi
tried="y"
size=$(getSize "$i" "$version" "$language")
sum=$(getHash "$i" "$version" "$language")
downloadFile "$iso" "$url" "$sum" "$size" "$desc" && return 0
fi
done
return 1
}
return 0