-
Notifications
You must be signed in to change notification settings - Fork 1
/
unqar.py
executable file
·93 lines (70 loc) · 2.24 KB
/
unqar.py
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
#!/usr/bin/env python3
import os
import pathlib
import struct
import sys
import zlib
class BinaryEOFException(Exception):
def __init__(self):
pass
def __str__(self):
return 'Premature end of file.'
class BinaryReader:
def __init__(self, file_name):
self.file = open(file_name, 'rb')
def unpack(self, type_format):
type_size = struct.calcsize(type_format)
value = self.file.read(type_size)
if type_size != len(value):
raise BinaryEOFException
return struct.unpack(type_format, value)[0]
def __del__(self):
self.file.close()
def print_usage():
print("Usage: %s [-l] <qar file> [<output path>]" % sys.argv[0])
print("-l list files in qar file")
if len(sys.argv) < 2:
print_usage()
exit(1)
listFiles = False
if (sys.argv[1]) == '-l':
if len(sys.argv) < 3:
print_usage()
exit(1)
else:
listFiles = True
binaryReader = None
try:
binaryReader = BinaryReader(sys.argv[2] if listFiles else sys.argv[1])
except Exception as e:
print("Error: File not found: %s" % sys.argv[2] if listFiles else sys.argv[1])
print_usage()
exit(1)
output_path = pathlib.Path.cwd()
if not listFiles and len(sys.argv) > 2:
output_path = str(sys.argv[2])
try:
magic = binaryReader.unpack('<H') # 71 02
if magic != 0x0271:
print("Not a supported qar file.")
print_usage()
exit(2)
file_count = binaryReader.unpack('<H')
print("Going to extract %d files." % file_count)
for i in range(0, file_count):
data_len = binaryReader.unpack('<I')
unknown2 = binaryReader.unpack('<H') # 00 07 or 00 7f
name_len = binaryReader.unpack('<H')
name = binaryReader.unpack('<%ds' % name_len).decode('utf-8')
data = binaryReader.unpack('<%ds' % data_len)
extracted = zlib.decompress(data)
if listFiles:
print("%s" % name)
else:
p = pathlib.Path(output_path).joinpath(name)
os.makedirs(os.path.dirname(p), exist_ok=True)
with p.open('wb') as fh:
fh.write(extracted)
print("extracted file: %s" % p)
except BinaryEOFException:
print("Error: Possibly corrupted file.")