blob: 9b5326e4ed57b4890ce0b5cc18665494c05b4b43 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
#!/bin/bash
# Parse google-chrome .pak resourcefiles
parse_int() {
( echo "ibase=16; "; cat; echo -e "\n") | bc
}
endian_conversion() {
if [[ "$1" == "little" ]]; then
tac
else
cat
fi
}
read_bytes() {
local length=$1
local endian=$2
local i=0
while [ $i -lt $length ]; do
read -r -d ' ' byte
[ "$byte" == "" ] && read -r -d ' ' byte
echo $byte
let i+=1
done \
| endian_conversion "$endian" \
| tr -d '\n'
}
parse() {
local format=$1
local endian=big
local i=0
while [[ $i -lt ${#format} ]]; do
case "${format:$i:1}" in
"<") endian="little";;
">") endian="big";;
"I") read_bytes "4" "$endian" | parse_int; let offset+=4;;
"H") read_bytes "2" "$endian" | parse_int; let offset+=2;;
"B") read_bytes "1" "$endian" | parse_int; let offset+=1;;
*)
echo "Invalid format: ${format:$i:1}" >&2;;
esac
let i+=1
done | tr '\n' ' '
}
read_file() {
local file=$1
local offset=$2
local format=$3
dd if=$file bs=1 skip=$offset count=$(format_len "$format") 2>/dev/null \
| od --output-duplicates --format=x1 --address-radix=n \
| tr 'a-z' 'A-Z' | tr -d '\n'
}
parse_file() {
read_file "$1" "$2" "$3" | parse "$3"
}
format_len() {
local format=$1
local len=0
local i=0
while [[ $i -lt ${#format} ]]; do
case "${format:$i:1}" in
"I") let len+=4 ;;
"H") let len+=2 ;;
"B") let len+=1 ;;
"<"|">") ;;
*) echo "Invalid format: ${format:$i:1}" >&2;;
esac
let i+=1
done
echo "$len"
}
##################
INPUT=$1
[ -e "$INPUT" ] || exit 1
header_size=$(format_len "<IIB")
entry_size=$(format_len "<HI")
read -r version num_entries encoding < \
<(parse_file "$INPUT" 0 "<IIB")
if [ "$version" != "4" ]; then
echo "Invalid version: $version" >&2
exit 1
fi
if [ "$encoding" != "1" ]; then
echo "Invalid encoding: $encoding" >&2
exit 1
fi
pos=$header_size
i=0
while [ $i -lt $num_entries ]; do
read -r id offset next_id next_offset < <(parse_file "$INPUT" $pos "<HIHI")
let pos+=entry_size
let entry_len=next_offset-offset
echo "$id: $(dd if=$INPUT bs=1 count=$entry_len skip=$offset 2>/dev/null)"
let i+=1
done
|