wangzhibo
4 天以前 ae6f40460dcd56af6c5f60ba52c883854c3bac55
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# 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()