-
Notifications
You must be signed in to change notification settings - Fork 27
/
Copy pathseqbox.py
122 lines (106 loc) · 3.92 KB
/
seqbox.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
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
#!/usr/bin/env python3
#--------------------------------------------------------------------------
# Name: seqbox.py
# Purpose: Sequenced Box container
#
# Author: Marco Pontello
#
# Created: 10/02/2017
# Copyright: (c) Mark 2017
# Licence: GPL-something?
#--------------------------------------------------------------------------
import os
import sys
import hashlib
import binascii
import random
class sbxBlock():
"""
Implement a basic SBX block
"""
def __init__(self, ver=1, uid="r"):
self.ver = ver
if ver in [0,1]:
self.blocksize = 512
self.hdrsize = 16
else:
raise version_not_supported #put in a proper exception
self.datasize = self.blocksize - self.hdrsize
self.magic = b'SBx' + ver.to_bytes(1, byteorder='big', signed=True)
self.blocknum = 0
if uid == "r":
random.seed()
self.uid = random.getrandbits(6*8).to_bytes(6, byteorder='big')
else:
self.uid = (b'\x00'*6 + uid)[-6:]
self.parent_uid = 0
self.metadata = {}
self.data = b""
def __str__(self):
return "SBX Block ver: '%i', size: %i, hdr size: %i, data: %i" % \
(self.ver, self.blocksize, self.hdrsize, self.datasize)
def encode(self):
if self.blocknum == 0:
self.data = b""
if "filename" in self.metadata:
bb = self.metadata["filename"].encode()
self.data += b"FNM" + bytes([len(bb)]) + bb
if "sbxname" in self.metadata:
bb = self.metadata["sbxname"].encode()
self.data += b"SNM" + bytes([len(bb)]) + bb
if "filesize" in self.metadata:
bb = self.metadata["filesize"].to_bytes(8, byteorder='big')
self.data += b"FSZ" + bytes([len(bb)]) + bb
if "hash" in self.metadata:
bb = self.metadata["hash"]
self.data += b"HSH" + bytes([len(bb)]) + bb
data = self.data + b'\x1A' * (self.datasize - len(self.data))
buffer = (self.uid +
self.blocknum.to_bytes(4, byteorder='big') +
data)
crc = binascii.crc_hqx(buffer, self.ver).to_bytes(2,byteorder='big')
return (self.magic + crc + buffer)
def decode(self, buffer):
#check the basics
if len(buffer) != self.blocksize:
return False
if buffer[:3] != self.magic[:3]:
return False
print("Magic: OK!")
if not buffer[3] in [0,1]:
return False
print("Version:", buffer[3])
#check CRC of rest of the block
crc = int.from_bytes(buffer[4:6], byteorder='big')
if crc != binascii.crc_hqx(buffer[6:], self.ver):
return False
print("CRC: OK!")
self.uid = buffer[6:12]
self.blocknum = int.from_bytes(buffer[12:16], byteorder='big')
self.data = buffer[16:]
if self.blocknum == 0:
#decode meta data
p = 0
while p < (len(self.data)-3):
metaid = self.data[p:p+3]
p+=3
if metaid == b"\x1a\x1a\x1a":
break
else:
metalen = self.data[p]
metabb = self.data[p+1:p+1+metalen]
p = p + 1 + metalen
if metaid == b'FNM':
self.metadata["filename"] = metabb.decode('utf-8')
if metaid == b'SNM':
self.metadata["sbxname"] = metabb.decode('utf-8')
if metaid == b'FSZ':
self.metadata["filesize"] = int.from_bytes(metabb, byteorder='big')
if metaid == b'HSH':
self.metadata["hash"] = metabb
return True
def main():
print("SeqBox module!")
sys.exit(0)
if __name__ == '__main__':
main()