mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-14 14:09:28 +01:00
125 lines
4.0 KiB
Python
125 lines
4.0 KiB
Python
# File downloaded from https://github.com/dakhnod/Fossil-HR-SDK/
|
|
|
|
import sys
|
|
import os
|
|
import json
|
|
import crc32c
|
|
import getopt
|
|
|
|
class Packer:
|
|
def __init__(self):
|
|
self.file_block = bytearray()
|
|
|
|
def put_int(self, content, length=4):
|
|
self.file_block.extend(content.to_bytes(length, 'little'))
|
|
|
|
def pack(self, input_dir_path, output_file_path):
|
|
start_path = os.getcwd()
|
|
|
|
if not os.path.isdir(input_dir_path):
|
|
print('cannot find dir %s' % input_dir_path)
|
|
exit()
|
|
os.chdir(input_dir_path)
|
|
|
|
with open('app.json', 'r') as json_file:
|
|
app_meta = json.load(json_file)
|
|
|
|
os.chdir('files')
|
|
|
|
all_files = []
|
|
dir_sizes = {}
|
|
|
|
for files_dir_list in [('code', False), ('icons', False), ('layout', True), ('display_name', True), ('config', True)]:
|
|
dir_size = 0
|
|
files_dir = files_dir_list[0]
|
|
append_null = files_dir_list[1]
|
|
files = os.listdir(files_dir)
|
|
os.chdir(files_dir)
|
|
for file in sorted(files):
|
|
print(f'packing {file}')
|
|
with open(file, 'rb')as f:
|
|
contents = bytearray(f.read())
|
|
if append_null:
|
|
contents.append(0)
|
|
file_size = contents.__len__()
|
|
all_files.append({
|
|
'filename': file,
|
|
'contents': contents,
|
|
'size': file_size
|
|
})
|
|
dir_size = dir_size + file_size + file.__len__() + 4 # null byte + size bytes
|
|
os.chdir(os.pardir)
|
|
dir_sizes[files_dir] = dir_size
|
|
|
|
offset_code = 88
|
|
offset_icons = offset_code + dir_sizes['code']
|
|
offset_layout = offset_icons + dir_sizes['icons']
|
|
offset_display_name = offset_layout + dir_sizes['layout']
|
|
offset_config = offset_display_name + dir_sizes['display_name']
|
|
offset_file_end = offset_config + dir_sizes['config']
|
|
|
|
self.file_block.extend([int(octet) for octet in app_meta['version'].split('.')])
|
|
|
|
self.put_int(0)
|
|
self.put_int(0)
|
|
self.put_int(offset_code)
|
|
self.put_int(offset_icons)
|
|
self.put_int(offset_layout)
|
|
self.put_int(offset_display_name)
|
|
self.put_int(offset_display_name)
|
|
self.put_int(offset_config)
|
|
self.put_int(offset_file_end)
|
|
self.put_int(0)
|
|
self.put_int(0)
|
|
self.put_int(0)
|
|
self.put_int(0)
|
|
self.put_int(0)
|
|
self.put_int(0)
|
|
self.put_int(0)
|
|
self.put_int(0)
|
|
self.put_int(0)
|
|
|
|
for file in all_files:
|
|
filename = file['filename']
|
|
self.put_int(filename.__len__() + 1, 1)
|
|
self.file_block.extend(filename.encode('utf-8'))
|
|
self.put_int(0, 1) # null byte ending
|
|
self.put_int(file['size'], 2)
|
|
self.file_block.extend(file['contents'])
|
|
|
|
os.chdir(start_path)
|
|
|
|
identifier = all_files[0]['filename']
|
|
|
|
full_file = bytearray()
|
|
full_file.extend([0xFE, 0x15]) # file handle
|
|
full_file.extend([0x03, 0x00]) # file version
|
|
full_file.extend(int(0).to_bytes(4, 'little')) # file offset
|
|
full_file.extend(self.file_block.__len__().to_bytes(4, 'little')) # file size
|
|
full_file.extend(self.file_block)
|
|
full_file.extend(crc32c.crc32c(self.file_block).to_bytes(4, 'little'))
|
|
|
|
if output_file_path is None:
|
|
output_file_path = identifier
|
|
|
|
with open(output_file_path, 'wb') as output_file:
|
|
output_file.write(full_file)
|
|
|
|
|
|
|
|
def main():
|
|
packer = Packer()
|
|
input_dir_path = None
|
|
output_file_path = None
|
|
args, remainder = getopt.getopt(sys.argv[1:], 'i:o:', ['input=', 'output='])
|
|
for key, value in args:
|
|
if key in ['-i', '--input']:
|
|
input_dir_path = value
|
|
elif key in ['-o', '--output']:
|
|
output_file_path = value
|
|
packer.pack(input_dir_path, output_file_path)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|