summaryrefslogtreecommitdiff
path: root/parse-pak/parse-pak.sh
diff options
context:
space:
mode:
Diffstat (limited to 'parse-pak/parse-pak.sh')
-rwxr-xr-xparse-pak/parse-pak.sh104
1 files changed, 104 insertions, 0 deletions
diff --git a/parse-pak/parse-pak.sh b/parse-pak/parse-pak.sh
new file mode 100755
index 0000000..9b5326e
--- /dev/null
+++ b/parse-pak/parse-pak.sh
@@ -0,0 +1,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