Skip to content

Commit 6497f45

Browse files
committed
feat(hander): add par2 directory handler
1 parent 32a9a46 commit 6497f45

File tree

9 files changed

+87
-0
lines changed

9 files changed

+87
-0
lines changed

python/unblob/handlers/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
cab,
77
cpio,
88
dmg,
9+
par2,
910
rar,
1011
sevenzip,
1112
stuffit,
@@ -54,6 +55,7 @@
5455
BUILTIN_HANDLERS: Handlers = (
5556
cramfs.CramFSHandler,
5657
extfs.EXTHandler,
58+
erofs.EROFSHandler,
5759
fat.FATHandler,
5860
jffs2.JFFS2NewHandler,
5961
jffs2.JFFS2OldHandler,
@@ -124,4 +126,5 @@
124126
BUILTIN_DIR_HANDLERS: DirectoryHandlers = (
125127
sevenzip.MultiVolumeSevenZipHandler,
126128
gzip.MultiVolumeGzipHandler,
129+
par2.MultiVolumePAR2Handler,
127130
)
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import hashlib
2+
import io
3+
from pathlib import Path
4+
from typing import Optional
5+
6+
from unblob.file_utils import Endian, StructParser
7+
from unblob.models import (
8+
DirectoryHandler,
9+
Glob,
10+
MultiFile,
11+
)
12+
13+
C_DEFINITIONS = r"""
14+
typedef struct par2_header{
15+
char magic[8];
16+
uint64 packet_length;
17+
char md5_hash[16];
18+
char recovery_set_id[16];
19+
char type[16];
20+
} par2_header_t;
21+
"""
22+
23+
PAR2_MAGIC = b"PAR2\x00PKT"
24+
HEADER_STRUCT = "par2_header_t"
25+
HEADER_PARSER = StructParser(C_DEFINITIONS)
26+
27+
28+
class MultiVolumePAR2Handler(DirectoryHandler):
29+
NAME = "multi-par2"
30+
PATTERN = Glob("*.par2")
31+
EXTRACTOR = None
32+
33+
def is_valid_header(self, file_paths: list) -> bool:
34+
for path in file_paths:
35+
with path.open("rb") as f:
36+
header = HEADER_PARSER.parse(HEADER_STRUCT, f, Endian.LITTLE)
37+
if header.magic != PAR2_MAGIC:
38+
return False
39+
40+
offset_to_recovery_id = 32
41+
# seek to beginning of recovery set ID
42+
f.seek(offset_to_recovery_id, io.SEEK_SET)
43+
packet_content = f.read(
44+
header.packet_length - len(header) + offset_to_recovery_id
45+
)
46+
packet_checksum = hashlib.md5(packet_content).digest() # noqa: S324
47+
48+
if packet_checksum != header.md5_hash:
49+
return False
50+
return True
51+
52+
def calculate_multifile(self, file: Path) -> Optional[MultiFile]:
53+
paths = sorted(
54+
[p for p in file.parent.glob(f"{file.stem}.*") if p.resolve().exists()]
55+
)
56+
57+
if len(paths) <= 1 or not self.is_valid_header(paths):
58+
return None
59+
60+
return MultiFile(
61+
name=file.stem,
62+
paths=paths,
63+
)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:ec6b3ce93cd3dbecf78e67740c4c7592bd2563004f319d63606e984deaadd816
3+
size 20892
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:84ded5e3d5a6676b65f735637532d7d2aa408215603b7044bdf9ee2b8deb3a1a
3+
size 20964
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:456d8113f08c9a6e3a98eb0df3fe0f069461435acc727527b932ee8e9e1e9c69
3+
size 41824
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:2b64b4c8eb00f579ad3370661307073f685bbc3ce2a8ebed413e530f87690090
3+
size 62756
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:acee373d6b04ccacd7414361d3e19a6c42fa4cf6d9cf6bc867060b8777de5b32
3+
size 83832
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:162a4b25d4dba77bf4b059c79c2c361a620dd1cc2e4e46696fb1e97e3009fa48
3+
size 105196
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:f44677b7f3f4b3b811efaf8a4d8646107d1f0c4e8ab35aea854f8090c124e921
3+
size 105484

0 commit comments

Comments
 (0)