mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-26 20:53:38 +00:00
66 lines
2.4 KiB
Python
66 lines
2.4 KiB
Python
|
"""MAR (Mozilla ARchive) parser
|
||
|
|
||
|
Author: Robert Xiao
|
||
|
Creation date: July 10, 2007
|
||
|
|
||
|
"""
|
||
|
|
||
|
from hachoir.core.endian import BIG_ENDIAN
|
||
|
from hachoir.field import (RootSeekableFieldSet, FieldSet,
|
||
|
String, CString, UInt32, RawBytes)
|
||
|
from hachoir.core.text_handler import displayHandler, filesizeHandler
|
||
|
from hachoir.core.tools import humanUnixAttributes
|
||
|
from hachoir.parser import HachoirParser
|
||
|
|
||
|
|
||
|
class IndexEntry(FieldSet):
|
||
|
|
||
|
def createFields(self):
|
||
|
yield UInt32(self, "offset", "Offset in bytes relative to start of archive")
|
||
|
yield filesizeHandler(UInt32(self, "length", "Length in bytes"))
|
||
|
yield displayHandler(UInt32(self, "flags"), humanUnixAttributes)
|
||
|
yield CString(self, "name", "Filename (byte array)")
|
||
|
|
||
|
def createDescription(self):
|
||
|
return 'File %s, Size %s, Mode %s' % (
|
||
|
self["name"].display, self["length"].display, self["flags"].display)
|
||
|
|
||
|
|
||
|
class MozillaArchive(HachoirParser, RootSeekableFieldSet):
|
||
|
MAGIC = b"MAR1"
|
||
|
PARSER_TAGS = {
|
||
|
"id": "mozilla_ar",
|
||
|
"category": "archive",
|
||
|
"file_ext": ("mar",),
|
||
|
"min_size": (8 + 4 + 13) * 8, # Header, Index Header, 1 Index Entry
|
||
|
"magic": ((MAGIC, 0),),
|
||
|
"description": "Mozilla Archive",
|
||
|
}
|
||
|
endian = BIG_ENDIAN
|
||
|
|
||
|
def __init__(self, stream, **args):
|
||
|
RootSeekableFieldSet.__init__(
|
||
|
self, None, "root", stream, None, stream.askSize(self))
|
||
|
HachoirParser.__init__(self, stream, **args)
|
||
|
|
||
|
def validate(self):
|
||
|
if self.stream.readBytes(0, 4) != self.MAGIC:
|
||
|
return "Invalid magic"
|
||
|
return True
|
||
|
|
||
|
def createFields(self):
|
||
|
yield String(self, "magic", 4, "File signature (MAR1)", charset="ASCII")
|
||
|
yield UInt32(self, "index_offset", "Offset to index relative to file start")
|
||
|
self.seekByte(self["index_offset"].value, False)
|
||
|
yield UInt32(self, "index_size", "size of index in bytes")
|
||
|
current_index_size = 0 # bytes
|
||
|
while current_index_size < self["index_size"].value:
|
||
|
# plus 4 compensates for index_size
|
||
|
self.seekByte(self["index_offset"].value +
|
||
|
current_index_size + 4, False)
|
||
|
entry = IndexEntry(self, "index_entry[]")
|
||
|
yield entry
|
||
|
current_index_size += entry.size // 8
|
||
|
self.seekByte(entry["offset"].value, False)
|
||
|
yield RawBytes(self, "file[]", entry["length"].value)
|