From 95e88b4d47fc815a882560d865706de9637315e2 Mon Sep 17 00:00:00 2001 From: Kroese Date: Sat, 18 May 2024 15:17:57 +0200 Subject: [PATCH] Update install.sh --- src/install.sh | 430 ++++++++++++++++++------------------------------- 1 file changed, 159 insertions(+), 271 deletions(-) diff --git a/src/install.sh b/src/install.sh index b4eeb27..93a225c 100644 --- a/src/install.sh +++ b/src/install.sh @@ -73,6 +73,16 @@ startInstall() { : "${file//+/ }"; printf -v file '%b' "${_//%/\\x}" file=$(echo "$file" | sed -e 's/[^A-Za-z0-9._-]/_/g') + else + + local language + language=$(getLanguage "$LANGUAGE" "culture") + language="${language%%-*}" + + if [ -n "$language" ] && [[ "${language,,}" != "en" ]]; then + file="${VERSION/\//}_${language,,}.iso" + fi + fi BOOT="$STORAGE/$file" @@ -209,236 +219,6 @@ detectCustom() { return 0 } -getESD() { - - local dir="$1" - local version="$2" - 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..." - info "$msg" && html "$msg" - - rm -rf "$dir" - mkdir -p "$dir" - - local wFile="catalog.cab" - local xFile="products.xml" - local eFile="esd_edition.xml" - local fFile="products_filter.xml" - - { wget "$winCatalog" -O "$dir/$wFile" -q --timeout=10; rc=$?; } || : - (( rc != 0 )) && error "Failed to download $winCatalog , reason: $rc" && return 1 - - cd "$dir" - - if ! cabextract "$wFile" > /dev/null; then - cd /run - error "Failed to extract $wFile!" && return 1 - fi - - cd /run - - if [ ! -s "$dir/$xFile" ]; then - error "Failed to find $xFile in $wFile!" && return 1 - fi - - local esdLang="en-us" - local edQuery='//File[Architecture="'${PLATFORM}'"][Edition="'${editionName}'"]' - - echo -e '' > "$dir/$fFile" - xmllint --nonet --xpath "${edQuery}" "$dir/$xFile" >> "$dir/$fFile" 2>/dev/null - echo -e ''>> "$dir/$fFile" - xmllint --nonet --xpath '//File[LanguageCode="'${esdLang}'"]' "$dir/$fFile" >"$dir/$eFile" - - size=$(stat -c%s "$dir/$eFile") - if ((size<20)); then - error "Failed to find Windows product in $eFile!" && return 1 - fi - - local tag="FilePath" - ESD=$(xmllint --nonet --xpath "//$tag" "$dir/$eFile" | sed -E -e "s/<[\/]?$tag>//g") - - if [ -z "$ESD" ]; then - error "Failed to find ESD URL in $eFile!" && return 1 - fi - - tag="Sha1" - ESD_SUM=$(xmllint --nonet --xpath "//$tag" "$dir/$eFile" | sed -E -e "s/<[\/]?$tag>//g") - tag="Size" - ESD_SIZE=$(xmllint --nonet --xpath "//$tag" "$dir/$eFile" | sed -E -e "s/<[\/]?$tag>//g") - - rm -rf "$dir" - return 0 -} - -verifyFile() { - - local iso="$1" - local size="$2" - local total="$3" - local check="$4" - - if [ -n "$size" ] && [[ "$total" != "$size" ]] && [[ "$size" != "0" ]]; then - warn "The downloaded file has an unexpected size: $total bytes, while expected value was: $size bytes. Please report this at $SUPPORT/issues" - fi - - local hash="" - local algo="SHA256" - - [ -z "$check" ] && return 0 - [[ "$VERIFY" != [Yy1]* ]] && return 0 - [[ "${#check}" == "40" ]] && algo="SHA1" - - local msg="Verifying downloaded ISO..." - info "$msg" && html "$msg" - - if [[ "${algo,,}" != "sha256" ]]; then - hash=$(sha1sum "$iso" | cut -f1 -d' ') - else - hash=$(sha256sum "$iso" | cut -f1 -d' ') - fi - - if [[ "$hash" == "$check" ]]; then - info "Succesfully verified ISO!" && return 0 - fi - - error "The downloaded file has an invalid $algo checksum: $hash , while expected value was: $check. Please report this at $SUPPORT/issues" - - rm -f "$iso" - return 1 -} - -downloadFile() { - - local iso="$1" - local url="$2" - local sum="$3" - local size="$4" - local desc="$5" - local rc total progress domain dots - - rm -f "$iso" - - # Check if running with interactive TTY or redirected to docker log - if [ -t 1 ]; then - progress="--progress=bar:noscroll" - else - progress="--progress=dot:giga" - fi - - local msg="Downloading $desc..." - html "$msg" - - domain=$(echo "$url" | awk -F/ '{print $3}') - dots=$(echo "$domain" | tr -cd '.' | wc -c) - (( dots > 1 )) && domain=$(expr "$domain" : '.*\.\(.*\..*\)') - - if [ -n "$domain" ] && [[ "${domain,,}" != *"microsoft.com" ]]; then - msg="Downloading $desc from $domain..." - fi - - info "$msg" - /run/progress.sh "$iso" "$size" "Downloading $desc ([P])..." & - - { wget "$url" -O "$iso" -q --timeout=10 --show-progress "$progress"; rc=$?; } || : - - 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 - - error "Failed to download $url , reason: $rc" - - rm -f "$iso" - return 1 -} - -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" @@ -572,19 +352,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" @@ -604,6 +371,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" @@ -649,26 +436,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" @@ -683,11 +450,51 @@ detectVersion() { return 0 } +detectLanguage() { + + local xml="$1" + local lang="" + + if [[ "$xml" == *"LANGUAGE>"* ]]; then + lang="${xml#*LANGUAGE>}" + lang="${lang%%<*}" + else + if [[ "$xml" == *"FALLBACK>"* ]]; then + lang="${xml#*FALLBACK>}" + lang="${lang%%<*}" + fi + fi + + if [ -z "$lang" ]; then + warn "Language could not be detected from ISO!" && return 0 + fi + + local culture + culture=$(getLanguage "$lang" "culture") + [ -n "$culture" ] && LANGUAGE="$lang" && return 0 + + warn "Invalid language detected: \"$lang\"" + 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" local version="$2" - local desc msg + local desc msg language XML="" @@ -750,6 +557,12 @@ detectImage() { fi desc=$(printEdition "$DETECTED" "$DETECTED") + detectLanguage "$info" + + if [[ "${LANGUAGE,,}" != "en" ]] && [[ "${LANGUAGE,,}" != "en-"* ]]; then + language=$(getLanguage "$LANGUAGE" "desc") + desc="$desc ($language)" + fi info "Detected: $desc" setXML "" && return 0 @@ -773,6 +586,12 @@ prepareImage() { local dir="$2" local missing + case "${DETECTED,,}" in + "winxp"* | "winvistax86"* | "win7x86"* ) + MACHINE="pc-q35-2.10" + ;; + esac + case "${DETECTED,,}" in "winxp"* ) BOOT_MODE="windows_legacy" @@ -801,15 +620,62 @@ prepareImage() { return 1 } +updateXML() { + + local asset="$1" + local language="$2" + local culture region keyboard + + culture=$(getLanguage "$language" "culture") + + if [ -n "$culture" ] && [[ "${culture,,}" != "en-us" ]]; then + sed -i "s/en-US<\/UILanguage>/$culture<\/UILanguage>/g" "$asset" + fi + + region="$REGION" + [ -z "$region" ] && region="$culture" + + if [ -n "$region" ] && [[ "${region,,}" != "en-us" ]]; then + sed -i "s/en-US<\/UserLocale>/$region<\/UserLocale>/g" "$asset" + sed -i "s/en-US<\/SystemLocale>/$region<\/SystemLocale>/g" "$asset" + fi + + keyboard="$KEYBOARD" + [ -z "$keyboard" ] && keyboard="$culture" + + if [ -n "$keyboard" ] && [[ "${keyboard,,}" != "en-us" ]]; then + sed -i "s/en-US<\/InputLocale>/$keyboard<\/InputLocale>/g" "$asset" + sed -i "s/0409:00000409<\/InputLocale>/$keyboard<\/InputLocale>/g" "$asset" + fi + + if [ -n "$USERNAME" ]; then + sed -i "s/where name=\"Docker\"/where name=\"$USERNAME\"/g" "$asset" + sed -i "s/Docker<\/Name>/$USERNAME<\/Name>/g" "$asset" + sed -i "s/Docker<\/FullName>/$USERNAME<\/FullName>/g" "$asset" + sed -i "s/Docker<\/Username>/$USERNAME<\/Username>/g" "$asset" + fi + + if [ -n "$PASSWORD" ]; then + sed -i "s/password<\/Value>/$PASSWORD<\/Value>/g" "$asset" + sed -z "s/.........../\n $PASSWORD<\/Value>/g" -i "$asset" + sed -z "s/.............../\n $PASSWORD<\/Value>/g" -i "$asset" + fi + + return 0 +} + updateImage() { local dir="$1" local asset="$2" + local language="$3" local file="autounattend.xml" local org="${file/.xml/.org}" local dat="${file/.xml/.dat}" local desc path src loc xml index result + [[ "${DETECTED,,}" == "winxp"* ]] && return 0 + if [ ! -s "$asset" ] || [ ! -f "$asset" ]; then asset="" if [[ "$MANUAL" != [Yy1]* ]]; then @@ -858,13 +724,19 @@ updateImage() { xml=$(basename "$asset") info "Adding $xml for automatic installation..." - if ! wimlib-imagex update "$loc" "$index" --command "add $asset /$file" > /dev/null; then + local answer="$TMP/$xml" + cp "$asset" "$answer" + updateXML "$answer" "$language" + + if ! wimlib-imagex update "$loc" "$index" --command "add $answer /$file" > /dev/null; then MANUAL="Y" warn "failed to add answer file ($xml) to ISO image, $FB" else - wimlib-imagex update "$loc" "$index" --command "add $asset /$dat" > /dev/null || true + wimlib-imagex update "$loc" "$index" --command "add $answer /$dat" > /dev/null || true fi + rm -f "$answer" + fi if [[ "$MANUAL" == [Yy1]* ]]; then @@ -875,9 +747,10 @@ updateImage() { if ! wimlib-imagex update "$loc" "$index" --command "add $TMP/$org /$file" > /dev/null; then warn "failed to restore original answer file ($org)." fi - rm -f "$TMP/$org" fi + rm -f "$TMP/$org" + fi local find="$file" @@ -895,11 +768,22 @@ 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" local folder="/oem" - local src + local src dest file [ ! -d "$folder" ] && folder="/OEM" [ ! -d "$folder" ] && folder="$STORAGE/oem" @@ -915,13 +799,16 @@ copyOEM() { error "failed to locate 'sources' folder in ISO image!" && return 1 fi - local dest="$src/\$OEM\$/\$1/" + dest="$src/\$OEM\$/\$1/" mkdir -p "$dest" if ! cp -r "$folder" "$dest"; then error "Failed to copy OEM folder!" && return 1 fi + file=$(find "$dest" -maxdepth 1 -type f -iname install.bat | head -n 1) + [ -f "$file" ] && unix2dos -q "$file" + return 0 } @@ -1057,6 +944,7 @@ bootWindows() { ###################################### ! parseVersion && exit 58 +! parseLanguage && exit 56 ! detectCustom && exit 59 if ! startInstall; then @@ -1065,7 +953,7 @@ if ! startInstall; then fi if [ ! -s "$ISO" ] || [ ! -f "$ISO" ]; then - if ! downloadImage "$ISO" "$VERSION"; then + if ! downloadImage "$ISO" "$VERSION" "$LANGUAGE"; then rm -f "$ISO" 2> /dev/null || true exit 61 fi @@ -1086,7 +974,7 @@ if ! prepareImage "$ISO" "$DIR"; then exit 60 fi -if ! updateImage "$DIR" "$XML"; then +if ! updateImage "$DIR" "$XML" "$LANGUAGE"; then abortInstall "$ISO" && return 0 exit 60 fi