Skip to content

Commit

Permalink
feat: added xiaomi hdr unpacker based on unblob
Browse files Browse the repository at this point in the history
  • Loading branch information
jstucke committed Nov 22, 2024
1 parent f108057 commit deff5d8
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 0 deletions.
Empty file.
Empty file.
50 changes: 50 additions & 0 deletions fact_extractor/plugins/unpacking/xiaomi_hdr/code/xiaomi_hdr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""
This plugin uses unblob to unpack Xiaomi HDR1/2 images.
"""

from __future__ import annotations

import logging
from pathlib import Path

import structlog
from structlog.testing import capture_logs
from unblob.handlers.archive.xiaomi.hdr import HDRExtractor

NAME = 'Xiaomi HDR'
MIME_PATTERNS = ['firmware/xiaomi-hdr1', 'firmware/xiaomi-hdr2']
VERSION = '0.1.0'

structlog.configure(
wrapper_class=structlog.make_filtering_bound_logger(logging.DEBUG),
)


def unpack_function(file_path: str, tmp_dir: str) -> dict:
path = Path(file_path)
with path.open('rb') as fp:
magic = fp.read(4)
if magic in [b'HDR1', b'HDR2']:
extractor = HDRExtractor(f'{magic.decode().lower()}_header_t')
else:
return {'output': ''}

# unblob uses structlog for logging, but we can capture the logs with this convenient testing function
with capture_logs() as log_list:
extractor.extract(path, Path(tmp_dir))
return {'output': _format_logs(log_list)}


def _format_logs(logs: list[dict]) -> str:
output = ''
for entry in logs:
output += '\n'.join(f'{key}: {value}' for key, value in entry.items() if key not in {'_verbosity', 'log_level'})
return output


# ----> Do not edit below this line <----


def setup(unpack_tool):
for item in MIME_PATTERNS:
unpack_tool.register_plugin(item, (unpack_function, NAME, VERSION))
Empty file.
Binary file not shown.
22 changes: 22 additions & 0 deletions fact_extractor/plugins/unpacking/xiaomi_hdr/test/test_hdr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from pathlib import Path

from plugins.unpacking.xiaomi_hdr.code.xiaomi_hdr import MIME_PATTERNS
from test.unit.unpacker.test_unpacker import TestUnpackerBase

TEST_DATA_DIR = Path(__file__).parent / 'data'


class TestXiaomiHdrUnpacker(TestUnpackerBase):
def test_unpacker_selection_generic(self):
for mime in MIME_PATTERNS:
self.check_unpacker_selection(mime, 'Xiaomi HDR')

def test_extraction_hdr(self):
in_file = TEST_DATA_DIR / 'test.hdr1'
assert in_file.is_file(), 'test file is missing'
meta = self.check_unpacking_of_standard_unpack_set(
in_file,
output=True,
)
assert 'output' in meta
assert 'testfile1' in meta['output']

0 comments on commit deff5d8

Please sign in to comment.