#!/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 "&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 "/dev/null)" let i+=1 done