diff options
author | Yves Fischer <yvesf-git@xapek.org> | 2015-03-07 23:58:35 +0100 |
---|---|---|
committer | Yves Fischer <yvesf-git@xapek.org> | 2015-03-07 23:58:35 +0100 |
commit | 765c89e7b443504cf8aad3a55969127834216307 (patch) | |
tree | b22356469cb08132ce4e679e08e901a273e37414 /parse-pak/parse-pak.sh | |
parent | eccd059accbd307b5e36a95eae3c53694f13f6d3 (diff) | |
download | scripts-765c89e7b443504cf8aad3a55969127834216307.tar.gz scripts-765c89e7b443504cf8aad3a55969127834216307.zip |
pak parser in bash
Diffstat (limited to 'parse-pak/parse-pak.sh')
-rwxr-xr-x | parse-pak/parse-pak.sh | 104 |
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 |