Skip to content

Commit d03c636

Browse files
committed
fix(ecwolf): enhance Wolf3D version detection with hash validation and add known IWAD hashes [skip ci]
1 parent 9212833 commit d03c636

1 file changed

Lines changed: 106 additions & 4 deletions

File tree

archive_later/ecwolf/component_launcher.sh

Lines changed: 106 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,12 @@ detect_wolf3d_version() {
5353
vswap_file=$(find "$folder" -maxdepth 1 -type f -iname "vswap.$version" -print -quit 2>/dev/null)
5454

5555
if [[ -n "$gamemaps_file" && -n "$maphead_file" && -n "$vswap_file" ]]; then
56-
printf '%s' "$version"
57-
return 0
56+
if validate_wolf3d_version_hash "$folder" "$version"; then
57+
printf '%s' "$version"
58+
return 0
59+
else
60+
log d "Version '$version' rejected for '$folder' because hash validation failed"
61+
fi
5862
fi
5963
done
6064

@@ -76,6 +80,99 @@ pretty_wolf3d_version() {
7680
esac
7781
}
7882

83+
# Known IWAD hash fixtures for core file trio to avoid false positives in mod folders.
84+
# (Source: ECWolf docs, checked on Wolfenstein 3D / Spear of Destiny / Noah's Ark)
85+
declare -A wolf3d_data_hashes
86+
wolf3d_data_hashes=(
87+
[wl6.gamemaps]="a4e73706e100dc0cadfb02d23de46481"
88+
[wl6.maphead]="b8d2a78bc7c50da7ec9ab1d94f7975e1"
89+
# Support both canonical and alternate WL6 vswap variants observed in field
90+
[wl6.vswap]="b8ff4997461bafa5ef2a94c11f9de001 a6d901dfb455dfac96db5e4705837cdb"
91+
92+
[wl1.gamemaps]="30fecd7cce6bc70402651ec922d2da3d"
93+
[wl1.maphead]="7b6dd4e55c33c33a41d1600be5df3228"
94+
[wl1.vswap]="6efa079414b817c97db779cecfb081c9"
95+
96+
[sdm.gamemaps]="4eb2f538aab6e4061dadbc3b73837762"
97+
[sdm.maphead]="40fa03caf7a1a4dbd22da4321c6e10d4"
98+
[sdm.vswap]="35afda760bea840b547d686a930322dc"
99+
100+
[sod.gamemaps]="04f16534235b4b57fc379d5709f88f4a"
101+
[sod.maphead]="276c79a4a6419db6b23e7699e41cb9fa"
102+
[sod.vswap]="b1dac0a8786c7cdbb09331a4eba00652"
103+
104+
[sd2.gamemaps]="d55508cd58e2e61076ac81b98aeb9269"
105+
[sd2.maphead]="25d92ac0ba012a1e9335c747eb4ab177"
106+
[sd2.vswap]="fa5752c5b1e25ee5c4a9ec0e9d4013a9"
107+
108+
[sd3.gamemaps]="4219d83568d770b1c6ac9c2d4d1dfb9e"
109+
[sd3.maphead]="52fd50245a77e61dc1df91110c186195"
110+
[sd3.vswap]="e3e87518f51414872c454b7d72a45af6"
111+
112+
[sd3-alt.gamemaps]="29860b87c31348e163e10f8aa6f19295"
113+
[sd3-alt.maphead]="a8b24dd3d3271e0b7fc6f2f995915f27"
114+
[sd3-alt.vswap]="94aeef7980ef640c448087f92be16d83"
115+
116+
[n3d.gamemaps]="d35ce2257a4fb56f61529df5f7f77adb"
117+
[n3d.maphead]="2eaab4dd50856abeaebe75a8bcbbab42"
118+
[n3d.vswap]="8c61a9b3bb38a598990ccb743d2679fa"
119+
)
120+
121+
expected_wolf3d_hash() {
122+
local version="$1" file="$2" key
123+
key="$version.$file"
124+
# support alternate sd3 variant too
125+
[[ -n "${wolf3d_data_hashes[$key]:-}" ]] && printf '%s' "${wolf3d_data_hashes[$key]}" && return 0
126+
if [[ "$version" == "sd3" ]]; then
127+
key="sd3-alt.$file"
128+
[[ -n "${wolf3d_data_hashes[$key]:-}" ]] && printf '%s' "${wolf3d_data_hashes[$key]}" && return 0
129+
fi
130+
return 1
131+
}
132+
133+
validate_wolf3d_version_hash() {
134+
local folder="$1" version="$2"
135+
local md5cmd
136+
md5cmd=$(command -v md5sum || true)
137+
if [[ -z "$md5cmd" ]]; then
138+
log w "md5sum not found, version detection will proceed by filenames only"
139+
return 0
140+
fi
141+
142+
for file in gamemaps maphead vswap; do
143+
# case-insensitive path resolution, because actual files may use uppercase extensions/names
144+
local path
145+
path=$(find "$folder" -maxdepth 1 -type f -iname "${file}.${version}" -print -quit 2>/dev/null)
146+
[[ -n "$path" ]] || return 1
147+
148+
local expected
149+
expected=$(expected_wolf3d_hash "$version" "$file")
150+
if [[ -z "$expected" ]]; then
151+
log d "Hash not available for $file.$version, rejecting wildcard match to avoid mod false positive"
152+
return 1
153+
fi
154+
155+
local actual
156+
actual=$($md5cmd "$path" | awk '{print tolower($1)}')
157+
158+
local match=0
159+
for allowed in $expected; do
160+
if [[ "$actual" == "$allowed" ]]; then
161+
match=1
162+
break
163+
fi
164+
done
165+
166+
if (( match == 0 )); then
167+
log d "Hash mismatch for $path ($version): expected one of [$expected], got $actual"
168+
return 1
169+
fi
170+
done
171+
172+
# If we reached here, all three core files matched expected hashes
173+
return 0
174+
}
175+
79176
# Normalize user-provided Wolf3D version keys from .wolf data= values.
80177
normalize_wolf3d_version_key() {
81178
local input="${1,,}"
@@ -211,12 +308,13 @@ if [[ -f "$input_path" && "${input_path##*.}" == "wolf" ]]; then
211308
wolf3d_data_version_pretty="$(pretty_wolf3d_version "$version")"
212309
log i "Mod mode: base IWAD set to '$iwad_folder' (found $wolf3d_data_version_pretty)"
213310

311+
requested_mod_files=()
214312
if [[ ${#mod_files[@]} -gt 0 ]]; then
215313
for mod_entry in "${mod_files[@]}"; do
216314
if [[ "$mod_entry" == /* ]]; then
217-
args+=( --file "$mod_entry" )
315+
requested_mod_files+=( --file "$mod_entry" )
218316
else
219-
args+=( --file "$mod_folder/$mod_entry" )
317+
requested_mod_files+=( --file "$mod_folder/$mod_entry" )
220318
fi
221319
done
222320
launch_folder="$iwad_folder"
@@ -278,6 +376,10 @@ fi
278376
# Always use requested base options and preserved args.
279377
args=( "${raw_args[@]}" )
280378

379+
if [[ ${#requested_mod_files[@]} -gt 0 ]]; then
380+
args+=( "${requested_mod_files[@]}" )
381+
fi
382+
281383
if [[ -n "$main_game" ]]; then
282384
args+=( "$main_game" )
283385
fi

0 commit comments

Comments
 (0)