180 changed files with 7085 additions and 2472 deletions
@ -1,2 +1,2 @@ |
|||||
from lib.hachoir_core.version import VERSION as __version__, PACKAGE, WEBSITE, LICENSE |
from hachoir_core.version import VERSION as __version__, PACKAGE, WEBSITE, LICENSE |
||||
|
|
||||
|
@ -1,11 +1,11 @@ |
|||||
from lib.hachoir_core.endian import BIG_ENDIAN, LITTLE_ENDIAN |
from hachoir_core.endian import BIG_ENDIAN, LITTLE_ENDIAN |
||||
from lib.hachoir_core.stream.stream import StreamError |
from hachoir_core.stream.stream import StreamError |
||||
from lib.hachoir_core.stream.input import ( |
from hachoir_core.stream.input import ( |
||||
InputStreamError, |
InputStreamError, |
||||
InputStream, InputIOStream, StringInputStream, |
InputStream, InputIOStream, StringInputStream, |
||||
InputSubStream, InputFieldStream, |
InputSubStream, InputFieldStream, |
||||
FragmentedStream, ConcatStream) |
FragmentedStream, ConcatStream) |
||||
from lib.hachoir_core.stream.input_helper import FileInputStream, guessStreamCharset |
from hachoir_core.stream.input_helper import FileInputStream, guessStreamCharset |
||||
from lib.hachoir_core.stream.output import (OutputStreamError, |
from hachoir_core.stream.output import (OutputStreamError, |
||||
FileOutputStream, StringOutputStream, OutputStream) |
FileOutputStream, StringOutputStream, OutputStream) |
||||
|
|
||||
|
@ -1,5 +1,5 @@ |
|||||
PACKAGE = "hachoir-core" |
PACKAGE = "hachoir-core" |
||||
VERSION = "1.3.3" |
VERSION = "1.3.4" |
||||
WEBSITE = 'http://bitbucket.org/haypo/hachoir/wiki/hachoir-core' |
WEBSITE = 'http://bitbucket.org/haypo/hachoir/wiki/hachoir-core' |
||||
LICENSE = 'GNU GPL v2' |
LICENSE = 'GNU GPL v2' |
||||
|
|
||||
|
@ -1,15 +1,15 @@ |
|||||
from lib.hachoir_metadata.version import VERSION as __version__ |
from hachoir_metadata.version import VERSION as __version__ |
||||
from lib.hachoir_metadata.metadata import extractMetadata |
from hachoir_metadata.metadata import extractMetadata |
||||
|
|
||||
# Just import the module, |
# Just import the module, |
||||
# each module use registerExtractor() method |
# each module use registerExtractor() method |
||||
import lib.hachoir_metadata.archive |
import hachoir_metadata.archive |
||||
import lib.hachoir_metadata.audio |
import hachoir_metadata.audio |
||||
import lib.hachoir_metadata.file_system |
import hachoir_metadata.file_system |
||||
import lib.hachoir_metadata.image |
import hachoir_metadata.image |
||||
import lib.hachoir_metadata.jpeg |
import hachoir_metadata.jpeg |
||||
import lib.hachoir_metadata.misc |
import hachoir_metadata.misc |
||||
import lib.hachoir_metadata.program |
import hachoir_metadata.program |
||||
import lib.hachoir_metadata.riff |
import hachoir_metadata.riff |
||||
import lib.hachoir_metadata.video |
import hachoir_metadata.video |
||||
|
|
||||
|
@ -1,64 +0,0 @@ |
|||||
<ui version="4.0" > |
|
||||
<class>Form</class> |
|
||||
<widget class="QWidget" name="Form" > |
|
||||
<property name="geometry" > |
|
||||
<rect> |
|
||||
<x>0</x> |
|
||||
<y>0</y> |
|
||||
<width>441</width> |
|
||||
<height>412</height> |
|
||||
</rect> |
|
||||
</property> |
|
||||
<property name="windowTitle" > |
|
||||
<string>hachoir-metadata</string> |
|
||||
</property> |
|
||||
<layout class="QVBoxLayout" name="verticalLayout" > |
|
||||
<item> |
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" > |
|
||||
<item> |
|
||||
<widget class="QPushButton" name="open_button" > |
|
||||
<property name="text" > |
|
||||
<string>Open</string> |
|
||||
</property> |
|
||||
</widget> |
|
||||
</item> |
|
||||
<item> |
|
||||
<widget class="QComboBox" name="files_combo" > |
|
||||
<property name="sizePolicy" > |
|
||||
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" > |
|
||||
<horstretch>0</horstretch> |
|
||||
<verstretch>0</verstretch> |
|
||||
</sizepolicy> |
|
||||
</property> |
|
||||
</widget> |
|
||||
</item> |
|
||||
</layout> |
|
||||
</item> |
|
||||
<item> |
|
||||
<widget class="QTableWidget" name="metadata_table" > |
|
||||
<property name="alternatingRowColors" > |
|
||||
<bool>true</bool> |
|
||||
</property> |
|
||||
<property name="showGrid" > |
|
||||
<bool>false</bool> |
|
||||
</property> |
|
||||
<property name="rowCount" > |
|
||||
<number>0</number> |
|
||||
</property> |
|
||||
<property name="columnCount" > |
|
||||
<number>0</number> |
|
||||
</property> |
|
||||
</widget> |
|
||||
</item> |
|
||||
<item> |
|
||||
<widget class="QPushButton" name="quit_button" > |
|
||||
<property name="text" > |
|
||||
<string>Quit</string> |
|
||||
</property> |
|
||||
</widget> |
|
||||
</item> |
|
||||
</layout> |
|
||||
</widget> |
|
||||
<resources/> |
|
||||
<connections/> |
|
||||
</ui> |
|
@ -1,52 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
|
|
||||
# Form implementation generated from reading ui file 'hachoir_metadata/qt/dialog.ui' |
|
||||
# |
|
||||
# Created: Mon Jul 26 03:10:06 2010 |
|
||||
# by: PyQt4 UI code generator 4.7.3 |
|
||||
# |
|
||||
# WARNING! All changes made in this file will be lost! |
|
||||
|
|
||||
from PyQt4 import QtCore, QtGui |
|
||||
|
|
||||
class Ui_Form(object): |
|
||||
def setupUi(self, Form): |
|
||||
Form.setObjectName("Form") |
|
||||
Form.resize(441, 412) |
|
||||
self.verticalLayout = QtGui.QVBoxLayout(Form) |
|
||||
self.verticalLayout.setObjectName("verticalLayout") |
|
||||
self.horizontalLayout_2 = QtGui.QHBoxLayout() |
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2") |
|
||||
self.open_button = QtGui.QPushButton(Form) |
|
||||
self.open_button.setObjectName("open_button") |
|
||||
self.horizontalLayout_2.addWidget(self.open_button) |
|
||||
self.files_combo = QtGui.QComboBox(Form) |
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) |
|
||||
sizePolicy.setHorizontalStretch(0) |
|
||||
sizePolicy.setVerticalStretch(0) |
|
||||
sizePolicy.setHeightForWidth(self.files_combo.sizePolicy().hasHeightForWidth()) |
|
||||
self.files_combo.setSizePolicy(sizePolicy) |
|
||||
self.files_combo.setObjectName("files_combo") |
|
||||
self.horizontalLayout_2.addWidget(self.files_combo) |
|
||||
self.verticalLayout.addLayout(self.horizontalLayout_2) |
|
||||
self.metadata_table = QtGui.QTableWidget(Form) |
|
||||
self.metadata_table.setAlternatingRowColors(True) |
|
||||
self.metadata_table.setShowGrid(False) |
|
||||
self.metadata_table.setRowCount(0) |
|
||||
self.metadata_table.setColumnCount(0) |
|
||||
self.metadata_table.setObjectName("metadata_table") |
|
||||
self.metadata_table.setColumnCount(0) |
|
||||
self.metadata_table.setRowCount(0) |
|
||||
self.verticalLayout.addWidget(self.metadata_table) |
|
||||
self.quit_button = QtGui.QPushButton(Form) |
|
||||
self.quit_button.setObjectName("quit_button") |
|
||||
self.verticalLayout.addWidget(self.quit_button) |
|
||||
|
|
||||
self.retranslateUi(Form) |
|
||||
QtCore.QMetaObject.connectSlotsByName(Form) |
|
||||
|
|
||||
def retranslateUi(self, Form): |
|
||||
Form.setWindowTitle(QtGui.QApplication.translate("Form", "hachoir-metadata", None, QtGui.QApplication.UnicodeUTF8)) |
|
||||
self.open_button.setText(QtGui.QApplication.translate("Form", "Open", None, QtGui.QApplication.UnicodeUTF8)) |
|
||||
self.quit_button.setText(QtGui.QApplication.translate("Form", "Quit", None, QtGui.QApplication.UnicodeUTF8)) |
|
||||
|
|
@ -1,7 +1,7 @@ |
|||||
from lib.hachoir_parser.version import __version__ |
from hachoir_parser.version import __version__ |
||||
from lib.hachoir_parser.parser import ValidateError, HachoirParser, Parser |
from hachoir_parser.parser import ValidateError, HachoirParser, Parser |
||||
from lib.hachoir_parser.parser_list import ParserList, HachoirParserList |
from hachoir_parser.parser_list import ParserList, HachoirParserList |
||||
from lib.hachoir_parser.guess import (QueryParser, guessParser, createParser) |
from hachoir_parser.guess import (QueryParser, guessParser, createParser) |
||||
from lib.hachoir_parser import (archive, audio, container, |
from hachoir_parser import (archive, audio, container, |
||||
file_system, image, game, misc, network, program, video) |
file_system, image, game, misc, network, program, video) |
||||
|
|
||||
|
@ -1,12 +1,13 @@ |
|||||
from lib.hachoir_parser.archive.ace import AceFile |
from hachoir_parser.archive.ace import AceFile |
||||
from lib.hachoir_parser.archive.ar import ArchiveFile |
from hachoir_parser.archive.ar import ArchiveFile |
||||
from lib.hachoir_parser.archive.bzip2_parser import Bzip2Parser |
from hachoir_parser.archive.bzip2_parser import Bzip2Parser |
||||
from lib.hachoir_parser.archive.cab import CabFile |
from hachoir_parser.archive.cab import CabFile |
||||
from lib.hachoir_parser.archive.gzip_parser import GzipParser |
from hachoir_parser.archive.gzip_parser import GzipParser |
||||
from lib.hachoir_parser.archive.tar import TarFile |
from hachoir_parser.archive.tar import TarFile |
||||
from lib.hachoir_parser.archive.zip import ZipFile |
from hachoir_parser.archive.zip import ZipFile |
||||
from lib.hachoir_parser.archive.rar import RarFile |
from hachoir_parser.archive.rar import RarFile |
||||
from lib.hachoir_parser.archive.rpm import RpmFile |
from hachoir_parser.archive.rpm import RpmFile |
||||
from lib.hachoir_parser.archive.sevenzip import SevenZipParser |
from hachoir_parser.archive.sevenzip import SevenZipParser |
||||
from lib.hachoir_parser.archive.mar import MarFile |
from hachoir_parser.archive.mar import MarFile |
||||
|
from hachoir_parser.archive.mozilla_ar import MozillaArchive |
||||
|
from hachoir_parser.archive.zlib import ZlibData |
||||
|
@ -0,0 +1,267 @@ |
|||||
|
"""LZX data stream parser. |
||||
|
|
||||
|
Also includes a decompression function (slow!!) which can decompress |
||||
|
LZX data stored in a Hachoir stream. |
||||
|
|
||||
|
Author: Robert Xiao |
||||
|
Creation date: July 18, 2007 |
||||
|
""" |
||||
|
from hachoir_parser import Parser |
||||
|
from hachoir_core.field import (FieldSet, |
||||
|
UInt32, Bit, Bits, PaddingBits, |
||||
|
RawBytes, ParserError) |
||||
|
from hachoir_core.endian import MIDDLE_ENDIAN, LITTLE_ENDIAN |
||||
|
from hachoir_core.tools import paddingSize, alignValue |
||||
|
from hachoir_parser.archive.zlib import build_tree, HuffmanCode, extend_data |
||||
|
from hachoir_core.bits import str2long |
||||
|
import new # for instancemethod |
||||
|
|
||||
|
class LZXPreTreeEncodedTree(FieldSet): |
||||
|
def __init__(self, parent, name, num_elements, *args, **kwargs): |
||||
|
FieldSet.__init__(self, parent, name, *args, **kwargs) |
||||
|
self.num_elements = num_elements |
||||
|
|
||||
|
def createFields(self): |
||||
|
for i in xrange(20): |
||||
|
yield Bits(self, "pretree_lengths[]", 4) |
||||
|
pre_tree = build_tree([self['pretree_lengths[%d]'%x].value for x in xrange(20)]) |
||||
|
if not hasattr(self.root, "lzx_tree_lengths_"+self.name): |
||||
|
self.lengths = [0] * self.num_elements |
||||
|
setattr(self.root, "lzx_tree_lengths_"+self.name, self.lengths) |
||||
|
else: |
||||
|
self.lengths = getattr(self.root, "lzx_tree_lengths_"+self.name) |
||||
|
i = 0 |
||||
|
while i < self.num_elements: |
||||
|
field = HuffmanCode(self, "tree_code[]", pre_tree) |
||||
|
if field.realvalue <= 16: |
||||
|
self.lengths[i] = (self.lengths[i] - field.realvalue) % 17 |
||||
|
field._description = "Literal tree delta length %i (new length value %i for element %i)" % ( |
||||
|
field.realvalue, self.lengths[i], i) |
||||
|
i += 1 |
||||
|
yield field |
||||
|
elif field.realvalue == 17: |
||||
|
field._description = "Tree Code 17: Zeros for 4-19 elements" |
||||
|
yield field |
||||
|
extra = Bits(self, "extra[]", 4) |
||||
|
zeros = 4 + extra.value |
||||
|
extra._description = "Extra bits: zeros for %i elements (elements %i through %i)" % (zeros, i, i+zeros-1) |
||||
|
yield extra |
||||
|
self.lengths[i:i+zeros] = [0] * zeros |
||||
|
i += zeros |
||||
|
elif field.realvalue == 18: |
||||
|
field._description = "Tree Code 18: Zeros for 20-51 elements" |
||||
|
yield field |
||||
|
extra = Bits(self, "extra[]", 5) |
||||
|
zeros = 20 + extra.value |
||||
|
extra._description = "Extra bits: zeros for %i elements (elements %i through %i)" % (zeros, i, i+zeros-1) |
||||
|
yield extra |
||||
|
self.lengths[i:i+zeros] = [0] * zeros |
||||
|
i += zeros |
||||
|
elif field.realvalue == 19: |
||||
|
field._description = "Tree Code 19: Same code for 4-5 elements" |
||||
|
yield field |
||||
|
extra = Bits(self, "extra[]", 1) |
||||
|
run = 4 + extra.value |
||||
|
extra._description = "Extra bits: run for %i elements (elements %i through %i)" % (run, i, i+run-1) |
||||
|
yield extra |
||||
|
newfield = HuffmanCode(self, "tree_code[]", pre_tree) |
||||
|
assert newfield.realvalue <= 16 |
||||
|
newfield._description = "Literal tree delta length %i (new length value %i for elements %i through %i)" % ( |
||||
|
newfield.realvalue, self.lengths[i], i, i+run-1) |
||||
|
self.lengths[i:i+run] = [(self.lengths[i] - newfield.realvalue) % 17] * run |
||||
|
i += run |
||||
|
yield newfield |
||||
|
|
||||
|
class LZXBlock(FieldSet): |
||||
|
WINDOW_SIZE = {15:30, |
||||
|
16:32, |
||||
|
17:34, |
||||
|
18:36, |
||||
|
19:38, |
||||
|
20:42, |
||||
|
21:50} |
||||
|
POSITION_SLOTS = {0:(0,0,0), |
||||
|
1:(1,1,0), |
||||
|
2:(2,2,0), |
||||
|
3:(3,3,0), |
||||
|
4:(4,5,1), |
||||
|
5:(6,7,1), |
||||
|
6:(8,11,2), |
||||
|
7:(12,15,2), |
||||
|
8:(16,23,3), |
||||
|
9:(24,31,3), |
||||
|
10:(32,47,4), |
||||
|
11:(48,63,4), |
||||
|
12:(64,95,5), |
||||
|
13:(96,127,5), |
||||
|
14:(128,191,6), |
||||
|
15:(192,255,6), |
||||
|
16:(256,383,7), |
||||
|
17:(384,511,7), |
||||
|
18:(512,767,8), |
||||
|
19:(768,1023,8), |
||||
|
20:(1024,1535,9), |
||||
|
21:(1536,2047,9), |
||||
|
22:(2048,3071,10), |
||||
|
23:(3072,4095,10), |
||||
|
24:(4096,6143,11), |
||||
|
25:(6144,8191,11), |
||||
|
26:(8192,12287,12), |
||||
|
27:(12288,16383,12), |
||||
|
28:(16384,24575,13), |
||||
|
29:(24576,32767,13), |
||||
|
30:(32768,49151,14), |
||||
|
31:(49152,65535,14), |
||||
|
32:(65536,98303,15), |
||||
|
33:(98304,131071,15), |
||||
|
34:(131072,196607,16), |
||||
|
35:(196608,262143,16), |
||||
|
36:(262144,393215,17), |
||||
|
37:(393216,524287,17), |
||||
|
38:(524288,655359,17), |
||||
|
39:(655360,786431,17), |
||||
|
40:(786432,917503,17), |
||||
|
41:(917504,1048575,17), |
||||
|
42:(1048576,1179647,17), |
||||
|
43:(1179648,1310719,17), |
||||
|
44:(1310720,1441791,17), |
||||
|
45:(1441792,1572863,17), |
||||
|
46:(1572864,1703935,17), |
||||
|
47:(1703936,1835007,17), |
||||
|
48:(1835008,1966079,17), |
||||
|
49:(1966080,2097151,17), |
||||
|
} |
||||
|
def createFields(self): |
||||
|
yield Bits(self, "block_type", 3) |
||||
|
yield Bits(self, "block_size", 24) |
||||
|
self.uncompressed_size = self["block_size"].value |
||||
|
self.compression_level = self.root.compr_level |
||||
|
self.window_size = self.WINDOW_SIZE[self.compression_level] |
||||
|
self.block_type = self["block_type"].value |
||||
|
curlen = len(self.parent.uncompressed_data) |
||||
|
if self.block_type in (1, 2): # Verbatim or aligned offset block |
||||
|
if self.block_type == 2: |
||||
|
for i in xrange(8): |
||||
|
yield Bits(self, "aligned_len[]", 3) |
||||
|
aligned_tree = build_tree([self['aligned_len[%d]'%i].value for i in xrange(8)]) |
||||
|
yield LZXPreTreeEncodedTree(self, "main_tree_start", 256) |
||||
|
yield LZXPreTreeEncodedTree(self, "main_tree_rest", self.window_size * 8) |
||||
|
main_tree = build_tree(self["main_tree_start"].lengths + self["main_tree_rest"].lengths) |
||||
|
yield LZXPreTreeEncodedTree(self, "length_tree", 249) |
||||
|
length_tree = build_tree(self["length_tree"].lengths) |
||||
|
current_decoded_size = 0 |
||||
|
while current_decoded_size < self.uncompressed_size: |
||||
|
if (curlen+current_decoded_size) % 32768 == 0 and (curlen+current_decoded_size) != 0: |
||||
|
padding = paddingSize(self.address + self.current_size, 16) |
||||
|
if padding: |
||||
|
yield PaddingBits(self, "padding[]", padding) |
||||
|
field = HuffmanCode(self, "main_code[]", main_tree) |
||||
|
if field.realvalue < 256: |
||||
|
field._description = "Literal value %r" % chr(field.realvalue) |
||||
|
current_decoded_size += 1 |
||||
|
self.parent.uncompressed_data += chr(field.realvalue) |
||||
|
yield field |
||||
|
continue |
||||
|
position_header, length_header = divmod(field.realvalue - 256, 8) |
||||
|
info = self.POSITION_SLOTS[position_header] |
||||
|
if info[2] == 0: |
||||
|
if info[0] == 0: |
||||
|
position = self.parent.r0 |
||||
|
field._description = "Position Slot %i, Position [R0] (%i)" % (position_header, position) |
||||
|
elif info[0] == 1: |
||||
|
position = self.parent.r1 |
||||
|
self.parent.r1 = self.parent.r0 |
||||
|
self.parent.r0 = position |
||||
|
field._description = "Position Slot %i, Position [R1] (%i)" % (position_header, position) |
||||
|
elif info[0] == 2: |
||||
|
position = self.parent.r2 |
||||
|
self.parent.r2 = self.parent.r0 |
||||
|
self.parent.r0 = position |
||||
|
field._description = "Position Slot %i, Position [R2] (%i)" % (position_header, position) |
||||
|
else: |
||||
|
position = info[0] - 2 |
||||
|
self.parent.r2 = self.parent.r1 |
||||
|
self.parent.r1 = self.parent.r0 |
||||
|
self.parent.r0 = position |
||||
|
field._description = "Position Slot %i, Position %i" % (position_header, position) |
||||
|
else: |
||||
|
field._description = "Position Slot %i, Positions %i to %i" % (position_header, info[0] - 2, info[1] - 2) |
||||
|
if length_header == 7: |
||||
|
field._description += ", Length Values 9 and up" |
||||
|
yield field |
||||
|
length_field = HuffmanCode(self, "length_code[]", length_tree) |
||||
|
length = length_field.realvalue + 9 |
||||
|
length_field._description = "Length Code %i, total length %i" % (length_field.realvalue, length) |
||||
|
yield length_field |
||||
|
else: |
||||
|
field._description += ", Length Value %i (Huffman Code %i)"%(length_header + 2, field.value) |
||||
|
yield field |
||||
|
length = length_header + 2 |
||||
|
if info[2]: |
||||
|
if self.block_type == 1 or info[2] < 3: # verbatim |
||||
|
extrafield = Bits(self, "position_extra[%s" % field.name.split('[')[1], info[2]) |
||||
|
position = extrafield.value + info[0] - 2 |
||||
|
extrafield._description = "Position Extra Bits (%i), total position %i"%(extrafield.value, position) |
||||
|
yield extrafield |
||||
|
else: # aligned offset |
||||
|
position = info[0] - 2 |
||||
|
if info[2] > 3: |
||||
|
extrafield = Bits(self, "position_verbatim[%s" % field.name.split('[')[1], info[2]-3) |
||||
|
position += extrafield.value*8 |
||||
|
extrafield._description = "Position Verbatim Bits (%i), added position %i"%(extrafield.value, extrafield.value*8) |
||||
|
yield extrafield |
||||
|
if info[2] >= 3: |
||||
|
extrafield = HuffmanCode(self, "position_aligned[%s" % field.name.split('[')[1], aligned_tree) |
||||
|
position += extrafield.realvalue |
||||
|
extrafield._description = "Position Aligned Bits (%i), total position %i"%(extrafield.realvalue, position) |
||||
|
yield extrafield |
||||
|
self.parent.r2 = self.parent.r1 |
||||
|
self.parent.r1 = self.parent.r0 |
||||
|
self.parent.r0 = position |
||||
|
self.parent.uncompressed_data = extend_data(self.parent.uncompressed_data, length, position) |
||||
|
current_decoded_size += length |
||||
|
elif self.block_type == 3: # Uncompressed block |
||||
|
padding = paddingSize(self.address + self.current_size, 16) |
||||
|
if padding: |
||||
|
yield PaddingBits(self, "padding[]", padding) |
||||
|
else: |
||||
|
yield PaddingBits(self, "padding[]", 16) |
||||
|
self.endian = LITTLE_ENDIAN |
||||
|
yield UInt32(self, "r[]", "New value of R0") |
||||
|
yield UInt32(self, "r[]", "New value of R1") |
||||
|
yield UInt32(self, "r[]", "New value of R2") |
||||
|
self.parent.r0 = self["r[0]"].value |
||||
|
self.parent.r1 = self["r[1]"].value |
||||
|
self.parent.r2 = self["r[2]"].value |
||||
|
yield RawBytes(self, "data", self.uncompressed_size) |
||||
|
self.parent.uncompressed_data+=self["data"].value |
||||
|
if self["block_size"].value % 2: |
||||
|
yield PaddingBits(self, "padding", 8) |
||||
|
else: |
||||
|
raise ParserError("Unknown block type %d!"%self.block_type) |
||||
|
|
||||
|
class LZXStream(Parser): |
||||
|
endian = MIDDLE_ENDIAN |
||||
|
def createFields(self): |
||||
|
self.uncompressed_data = "" |
||||
|
self.r0 = 1 |
||||
|
self.r1 = 1 |
||||
|
self.r2 = 1 |
||||
|
yield Bit(self, "filesize_indicator") |
||||
|
if self["filesize_indicator"].value: |
||||
|
yield UInt32(self, "filesize") |
||||
|
while self.current_size < self.size: |
||||
|
block = LZXBlock(self, "block[]") |
||||
|
yield block |
||||
|
if self.size - self.current_size < 16: |
||||
|
padding = paddingSize(self.address + self.current_size, 16) |
||||
|
if padding: |
||||
|
yield PaddingBits(self, "padding[]", padding) |
||||
|
break |
||||
|
|
||||
|
def lzx_decompress(stream, window_bits): |
||||
|
data = LZXStream(stream) |
||||
|
data.compr_level = window_bits |
||||
|
for unused in data: |
||||
|
pass |
||||
|
return data.uncompressed_data |
@ -0,0 +1,60 @@ |
|||||
|
"""MAR (Mozilla ARchive) parser |
||||
|
|
||||
|
Author: Robert Xiao |
||||
|
Creation date: July 10, 2007 |
||||
|
|
||||
|
""" |
||||
|
|
||||
|
from hachoir_core.endian import BIG_ENDIAN |
||||
|
from hachoir_core.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 = "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) |
@ -0,0 +1,301 @@ |
|||||
|
"""Detailed ZLIB parser |
||||
|
|
||||
|
Author: Robert Xiao |
||||
|
Creation date: July 9 2007 |
||||
|
|
||||
|
""" |
||||
|
|
||||
|
from hachoir_parser import Parser |
||||
|
from hachoir_core.field import (Bit, Bits, Field, Int16, UInt32, |
||||
|
Enum, FieldSet, GenericFieldSet, |
||||
|
PaddingBits, ParserError, RawBytes) |
||||
|
from hachoir_core.endian import LITTLE_ENDIAN |
||||
|
from hachoir_core.text_handler import textHandler, hexadecimal |
||||
|
from hachoir_core.tools import paddingSize, alignValue |
||||
|
|
||||
|
def extend_data(data, length, offset): |
||||
|
"""Extend data using a length and an offset.""" |
||||
|
if length >= offset: |
||||
|
new_data = data[-offset:] * (alignValue(length, offset) // offset) |
||||
|
return data + new_data[:length] |
||||
|
else: |
||||
|
return data + data[-offset:-offset+length] |
||||
|
|
||||
|
def build_tree(lengths): |
||||
|
"""Build a Huffman tree from a list of lengths. |
||||
|
The ith entry of the input list is the length of the Huffman code corresponding to |
||||
|
integer i, or 0 if the integer i is unused.""" |
||||
|
max_length = max(lengths) + 1 |
||||
|
bit_counts = [0]*max_length |
||||
|
next_code = [0]*max_length |
||||
|
tree = {} |
||||
|
for i in lengths: |
||||
|
if i: |
||||
|
bit_counts[i] += 1 |
||||
|
code = 0 |
||||
|
for i in xrange(1, len(bit_counts)): |
||||
|
next_code[i] = code = (code + bit_counts[i-1]) << 1 |
||||
|
for i, ln in enumerate(lengths): |
||||
|
if ln: |
||||
|
tree[(ln, next_code[ln])] = i |
||||
|
next_code[ln] += 1 |
||||
|
return tree |
||||
|
|
||||
|
class HuffmanCode(Field): |
||||
|
"""Huffman code. Uses tree parameter as the Huffman tree.""" |
||||
|
def __init__(self, parent, name, tree, description=None): |
||||
|
Field.__init__(self, parent, name, 0, description) |
||||
|
|
||||
|
endian = self.parent.endian |
||||
|
stream = self.parent.stream |
||||
|
addr = self.absolute_address |
||||
|
|
||||
|
value = 0 |
||||
|
while (self.size, value) not in tree: |
||||
|
if self.size > 256: |
||||
|
raise ParserError("Huffman code too long!") |
||||
|
bit = stream.readBits(addr, 1, endian) |
||||
|
value <<= 1 |
||||
|
value += bit |
||||
|
self._size += 1 |
||||
|
addr += 1 |
||||
|
self.huffvalue = value |
||||
|
self.realvalue = tree[(self.size, value)] |
||||
|
def createValue(self): |
||||
|
return self.huffvalue |
||||
|
|
||||
|
class DeflateBlock(FieldSet): |
||||
|
# code: (min, max, extrabits) |
||||
|
LENGTH_SYMBOLS = {257:(3,3,0), |
||||
|
258:(4,4,0), |
||||
|
259:(5,5,0), |
||||
|
260:(6,6,0), |
||||
|
261:(7,7,0), |
||||
|
262:(8,8,0), |
||||
|
263:(9,9,0), |
||||
|
264:(10,10,0), |
||||
|
265:(11,12,1), |
||||
|
266:(13,14,1), |
||||
|
267:(15,16,1), |
||||
|
268:(17,18,1), |
||||
|
269:(19,22,2), |
||||
|
270:(23,26,2), |
||||
|
271:(27,30,2), |
||||
|
272:(31,34,2), |
||||
|
273:(35,42,3), |
||||
|
274:(43,50,3), |
||||
|
275:(51,58,3), |
||||
|
276:(59,66,3), |
||||
|
277:(67,82,4), |
||||
|
278:(83,98,4), |
||||
|
279:(99,114,4), |
||||
|
280:(115,130,4), |
||||
|
281:(131,162,5), |
||||
|
282:(163,194,5), |
||||
|
283:(195,226,5), |
||||
|
284:(227,257,5), |
||||
|
285:(258,258,0) |
||||
|
} |
||||
|
DISTANCE_SYMBOLS = {0:(1,1,0), |
||||
|
1:(2,2,0), |
||||
|
2:(3,3,0), |
||||
|
3:(4,4,0), |
||||
|
4:(5,6,1), |
||||
|
5:(7,8,1), |
||||
|
6:(9,12,2), |
||||
|
7:(13,16,2), |
||||
|
8:(17,24,3), |
||||
|
9:(25,32,3), |
||||
|
10:(33,48,4), |
||||
|
11:(49,64,4), |
||||
|
12:(65,96,5), |
||||
|
13:(97,128,5), |
||||
|
14:(129,192,6), |
||||
|
15:(193,256,6), |
||||
|
16:(257,384,7), |
||||
|
17:(385,512,7), |
||||
|
18:(513,768,8), |
||||
|
19:(769,1024,8), |
||||
|
20:(1025,1536,9), |
||||
|
21:(1537,2048,9), |
||||
|
22:(2049,3072,10), |
||||
|
23:(3073,4096,10), |
||||
|
24:(4097,6144,11), |
||||
|
25:(6145,8192,11), |
||||
|
26:(8193,12288,12), |
||||
|
27:(12289,16384,12), |
||||
|
28:(16385,24576,13), |
||||
|
29:(24577,32768,13), |
||||
|
} |
||||
|
CODE_LENGTH_ORDER = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15] |
||||
|
def __init__(self, parent, name, uncomp_data="", *args, **kwargs): |
||||
|
FieldSet.__init__(self, parent, name, *args, **kwargs) |
||||
|
self.uncomp_data = uncomp_data |
||||
|
|
||||
|
def createFields(self): |
||||
|
yield Bit(self, "final", "Is this the final block?") # BFINAL |
||||
|
yield Enum(Bits(self, "compression_type", 2), # BTYPE |
||||
|
{0:"None", 1:"Fixed Huffman", 2:"Dynamic Huffman", 3:"Reserved"}) |
||||
|
if self["compression_type"].value == 0: # no compression |
||||
|
padding = paddingSize(self.current_size + self.absolute_address, 8) # align on byte boundary |
||||
|
if padding: |
||||
|
yield PaddingBits(self, "padding[]", padding) |
||||
|
yield Int16(self, "len") |
||||
|
yield Int16(self, "nlen", "One's complement of len") |
||||
|
if self["len"].value != ~self["nlen"].value: |
||||
|
raise ParserError("len must be equal to the one's complement of nlen!") |
||||
|
if self["len"].value: # null stored blocks produced by some encoders (e.g. PIL) |
||||
|
yield RawBytes(self, "data", self["len"].value, "Uncompressed data") |
||||
|
return |
||||
|
elif self["compression_type"].value == 1: # Fixed Huffman |
||||
|
length_tree = {} # (size, huffman code): value |
||||
|
distance_tree = {} |
||||
|
for i in xrange(144): |
||||
|
length_tree[(8, i+48)] = i |
||||
|
for i in xrange(144, 256): |
||||
|
length_tree[(9, i+256)] = i |
||||
|
for i in xrange(256, 280): |
||||
|
length_tree[(7, i-256)] = i |
||||
|
for i in xrange(280, 288): |
||||
|
length_tree[(8, i-88)] = i |
||||
|
for i in xrange(32): |
||||
|
distance_tree[(5, i)] = i |
||||
|
elif self["compression_type"].value == 2: # Dynamic Huffman |
||||
|
yield Bits(self, "huff_num_length_codes", 5, "Number of Literal/Length Codes, minus 257") |
||||
|
yield Bits(self, "huff_num_distance_codes", 5, "Number of Distance Codes, minus 1") |
||||
|
yield Bits(self, "huff_num_code_length_codes", 4, "Number of Code Length Codes, minus 4") |
||||
|
code_length_code_lengths = [0]*19 # confusing variable name... |
||||
|
for i in self.CODE_LENGTH_ORDER[:self["huff_num_code_length_codes"].value+4]: |
||||
|
field = Bits(self, "huff_code_length_code[%i]" % i, 3, "Code lengths for the code length alphabet") |
||||
|
yield field |
||||
|
code_length_code_lengths[i] = field.value |
||||
|
code_length_tree = build_tree(code_length_code_lengths) |
||||
|
length_code_lengths = [] |
||||
|
distance_code_lengths = [] |
||||
|
for numcodes, name, lengths in ( |
||||
|
(self["huff_num_length_codes"].value + 257, "length", length_code_lengths), |
||||
|
(self["huff_num_distance_codes"].value + 1, "distance", distance_code_lengths)): |
||||
|
while len(lengths) < numcodes: |
||||
|
field = HuffmanCode(self, "huff_%s_code[]" % name, code_length_tree) |
||||
|
value = field.realvalue |
||||
|
if value < 16: |
||||
|
prev_value = value |
||||
|
field._description = "Literal Code Length %i (Huffman Code %i)" % (value, field.value) |
||||
|
yield field |
||||
|
lengths.append(value) |
||||
|
else: |
||||
|
info = {16: (3,6,2), |
||||
|
17: (3,10,3), |
||||
|
18: (11,138,7)}[value] |
||||
|
if value == 16: |
||||
|
repvalue = prev_value |
||||
|
else: |
||||
|
repvalue = 0 |
||||
|
field._description = "Repeat Code %i, Repeating value (%i) %i to %i times (Huffman Code %i)" % (value, repvalue, info[0], info[1], field.value) |
||||
|
yield field |
||||
|
extrafield = Bits(self, "huff_%s_code_extra[%s" % (name, field.name.split('[')[1]), info[2]) |
||||
|
num_repeats = extrafield.value+info[0] |
||||
|
extrafield._description = "Repeat Extra Bits (%i), total repeats %i"%(extrafield.value, num_repeats) |
||||
|
yield extrafield |
||||
|
lengths += [repvalue]*num_repeats |
||||
|
length_tree = build_tree(length_code_lengths) |
||||
|
distance_tree = build_tree(distance_code_lengths) |
||||
|
else: |
||||
|
raise ParserError("Unsupported compression type 3!") |
||||
|
while True: |
||||
|
field = HuffmanCode(self, "length_code[]", length_tree) |
||||
|
value = field.realvalue |
||||
|
if value < 256: |
||||
|
field._description = "Literal Code %r (Huffman Code %i)" % (chr(value), field.value) |
||||
|
yield field |
||||
|
self.uncomp_data += chr(value) |
||||
|
if value == 256: |
||||
|
field._description = "Block Terminator Code (256) (Huffman Code %i)" % field.value |
||||
|
yield field |
||||
|
break |
||||
|
elif value > 256: |
||||
|
info = self.LENGTH_SYMBOLS[value] |
||||
|
if info[2] == 0: |
||||
|
field._description = "Length Code %i, Value %i (Huffman Code %i)" % (value, info[0], field.value) |
||||
|
length = info[0] |
||||
|
yield field |
||||
|
else: |
||||
|
field._description = "Length Code %i, Values %i to %i (Huffman Code %i)" % (value, info[0], info[1], field.value) |
||||
|
yield field |
||||
|
extrafield = Bits(self, "length_extra[%s" % field.name.split('[')[1], info[2]) |
||||
|
length = extrafield.value + info[0] |
||||
|
extrafield._description = "Length Extra Bits (%i), total length %i"%(extrafield.value, length) |
||||
|
yield extrafield |
||||
|
field = HuffmanCode(self, "distance_code[]", distance_tree) |
||||
|
value = field.realvalue |
||||
|
info = self.DISTANCE_SYMBOLS[value] |
||||
|
if info[2] == 0: |
||||
|
field._description = "Distance Code %i, Value %i (Huffman Code %i)" % (value, info[0], field.value) |
||||
|
distance = info[0] |
||||
|
yield field |
||||
|
else: |
||||
|
field._description = "Distance Code %i, Values %i to %i (Huffman Code %i)" % (value, info[0], info[1], field.value) |
||||
|
yield field |
||||
|
extrafield = Bits(self, "distance_extra[%s" % field.name.split('[')[1], info[2]) |
||||
|
distance = extrafield.value + info[0] |
||||
|
extrafield._description = "Distance Extra Bits (%i), total length %i"%(extrafield.value, distance) |
||||
|
yield extrafield |
||||
|
self.uncomp_data = extend_data(self.uncomp_data, length, distance) |
||||
|
|
||||
|
class DeflateData(GenericFieldSet): |
||||
|
endian = LITTLE_ENDIAN |
||||
|
def createFields(self): |
||||
|
uncomp_data = "" |
||||
|
blk=DeflateBlock(self, "compressed_block[]", uncomp_data) |
||||
|
yield blk |
||||
|
uncomp_data = blk.uncomp_data |
||||
|
while not blk["final"].value: |
||||
|
blk=DeflateBlock(self, "compressed_block[]", uncomp_data) |
||||
|
yield blk |
||||
|
uncomp_data = blk.uncomp_data |
||||
|
padding = paddingSize(self.current_size + self.absolute_address, 8) # align on byte boundary |
||||
|
if padding: |
||||
|
yield PaddingBits(self, "padding[]", padding) |
||||
|
self.uncompressed_data = uncomp_data |
||||
|
|
||||
|
class ZlibData(Parser): |
||||
|
PARSER_TAGS = { |
||||
|
"id": "zlib", |
||||
|
"category": "archive", |
||||
|
"file_ext": ("zlib",), |
||||
|
"min_size": 8*8, |
||||
|
"description": "ZLIB Data", |
||||
|
} |
||||
|
endian = LITTLE_ENDIAN |
||||
|
|
||||
|
def validate(self): |
||||
|
if self["compression_method"].value != 8: |
||||
|
return "Incorrect compression method" |
||||
|
if ((self["compression_info"].value << 12) + |
||||
|
(self["compression_method"].value << 8) + |
||||
|
(self["flag_compression_level"].value << 6) + |
||||
|
(self["flag_dictionary_present"].value << 5) + |
||||
|
(self["flag_check_bits"].value)) % 31 != 0: |
||||
|
return "Invalid flag check value" |
||||
|
return True |
||||
|
|
||||
|
def createFields(self): |
||||
|
yield Enum(Bits(self, "compression_method", 4), {8:"deflate", 15:"reserved"}) # CM |
||||
|
yield Bits(self, "compression_info", 4, "base-2 log of the window size") # CINFO |
||||
|
yield Bits(self, "flag_check_bits", 5) # FCHECK |
||||
|
yield Bit(self, "flag_dictionary_present") # FDICT |
||||
|
yield Enum(Bits(self, "flag_compression_level", 2), # FLEVEL |
||||
|
{0:"Fastest", 1:"Fast", 2:"Default", 3:"Maximum, Slowest"}) |
||||
|
if self["flag_dictionary_present"].value: |
||||
|
yield textHandler(UInt32(self, "dict_checksum", "ADLER32 checksum of dictionary information"), hexadecimal) |
||||
|
yield DeflateData(self, "data", self.stream, description = "Compressed Data") |
||||
|
yield textHandler(UInt32(self, "data_checksum", "ADLER32 checksum of compressed data"), hexadecimal) |
||||
|
|
||||
|
def zlib_inflate(stream, wbits=None, prevdata=""): |
||||
|
if wbits is None or wbits >= 0: |
||||
|
return ZlibData(stream)["data"].uncompressed_data |
||||
|
else: |
||||
|
data = DeflateData(None, "root", stream, "", stream.askSize(None)) |
||||
|
for unused in data: |
||||
|
pass |
||||
|
return data.uncompressed_data |
@ -1,126 +0,0 @@ |
|||||
""" |
|
||||
Audio Interchange File Format (AIFF) parser. |
|
||||
|
|
||||
Author: Victor Stinner |
|
||||
Creation: 27 december 2006 |
|
||||
""" |
|
||||
|
|
||||
from lib.hachoir_parser import Parser |
|
||||
from lib.hachoir_core.field import (FieldSet, |
|
||||
UInt16, UInt32, Float80, TimestampMac32, |
|
||||
RawBytes, NullBytes, |
|
||||
String, Enum, PascalString32) |
|
||||
from lib.hachoir_core.endian import BIG_ENDIAN |
|
||||
from lib.hachoir_core.text_handler import filesizeHandler |
|
||||
from lib.hachoir_core.tools import alignValue |
|
||||
from lib.hachoir_parser.audio.id3 import ID3v2 |
|
||||
|
|
||||
CODEC_NAME = { |
|
||||
'ACE2': u"ACE 2-to-1", |
|
||||
'ACE8': u"ACE 8-to-3", |
|
||||
'MAC3': u"MAC 3-to-1", |
|
||||
'MAC6': u"MAC 6-to-1", |
|
||||
'NONE': u"None", |
|
||||
'sowt': u"Little-endian, no compression", |
|
||||
} |
|
||||
|
|
||||
class Comment(FieldSet): |
|
||||
def createFields(self): |
|
||||
yield TimestampMac32(self, "timestamp") |
|
||||
yield PascalString32(self, "text") |
|
||||
|
|
||||
def parseText(self): |
|
||||
yield String(self, "text", self["size"].value) |
|
||||
|
|
||||
def parseID3(self): |
|
||||
yield ID3v2(self, "id3v2", size=self["size"].value*8) |
|
||||
|
|
||||
def parseComment(self): |
|
||||
yield UInt16(self, "nb_comment") |
|
||||
for index in xrange(self["nb_comment"].value): |
|
||||
yield Comment(self, "comment[]") |
|
||||
|
|
||||
def parseCommon(self): |
|
||||
yield UInt16(self, "nb_channel") |
|
||||
yield UInt32(self, "nb_sample") |
|
||||
yield UInt16(self, "sample_size") |
|
||||
yield Float80(self, "sample_rate") |
|
||||
yield Enum(String(self, "codec", 4, strip="\0", charset="ASCII"), CODEC_NAME) |
|
||||
|
|
||||
def parseVersion(self): |
|
||||
yield TimestampMac32(self, "timestamp") |
|
||||
|
|
||||
def parseSound(self): |
|
||||
yield UInt32(self, "offset") |
|
||||
yield UInt32(self, "block_size") |
|
||||
size = (self.size - self.current_size) // 8 |
|
||||
if size: |
|
||||
yield RawBytes(self, "data", size) |
|
||||
|
|
||||
class Chunk(FieldSet): |
|
||||
TAG_INFO = { |
|
||||
'COMM': ('common', "Common chunk", parseCommon), |
|
||||
'COMT': ('comment', "Comment", parseComment), |
|
||||
'NAME': ('name', "Name", parseText), |
|
||||
'AUTH': ('author', "Author", parseText), |
|
||||
'FVER': ('version', "Version", parseVersion), |
|
||||
'SSND': ('sound', "Sound data", parseSound), |
|
||||
'ID3 ': ('id3', "ID3", parseID3), |
|
||||
} |
|
||||
|
|
||||
def __init__(self, *args): |
|
||||
FieldSet.__init__(self, *args) |
|
||||
self._size = (8 + alignValue(self["size"].value, 2)) * 8 |
|
||||
tag = self["type"].value |
|
||||
if tag in self.TAG_INFO: |
|
||||
self._name, self._description, self._parser = self.TAG_INFO[tag] |
|
||||
else: |
|
||||
self._parser = None |
|
||||
|
|
||||
def createFields(self): |
|
||||
yield String(self, "type", 4, "Signature (FORM)", charset="ASCII") |
|
||||
yield filesizeHandler(UInt32(self, "size")) |
|
||||
size = self["size"].value |
|
||||
if size: |
|
||||
if self._parser: |
|
||||
for field in self._parser(self): |
|
||||
yield field |
|
||||
if size % 2: |
|
||||
yield NullBytes(self, "padding", 1) |
|
||||
else: |
|
||||
yield RawBytes(self, "data", size) |
|
||||
|
|
||||
class HeightSVX(Parser): |
|
||||
PARSER_TAGS = { |
|
||||
"id": "8svx", |
|
||||
"category": "audio", |
|
||||
"file_ext": ("8svx",), |
|
||||
"mime": (u"audio/x-aiff",), |
|
||||
"min_size": 12*8, |
|
||||
"description": "8SVX (audio) format" |
|
||||
} |
|
||||
endian = BIG_ENDIAN |
|
||||
|
|
||||
def validate(self): |
|
||||
if self.stream.readBytes(0, 4) != "FORM": |
|
||||
return "Invalid signature" |
|
||||
if self.stream.readBytes(8*8, 4) != "8SVX": |
|
||||
return "Invalid type" |
|
||||
return True |
|
||||
|
|
||||
def createFields(self): |
|
||||
yield String(self, "signature", 4, "Signature (FORM)", charset="ASCII") |
|
||||
yield filesizeHandler(UInt32(self, "filesize")) |
|
||||
yield String(self, "type", 4, "Form type (AIFF or AIFC)", charset="ASCII") |
|
||||
while not self.eof: |
|
||||
yield Chunk(self, "chunk[]") |
|
||||
|
|
||||
def createDescription(self): |
|
||||
if self["type"].value == "AIFC": |
|
||||
return "Audio Interchange File Format Compressed (AIFC)" |
|
||||
else: |
|
||||
return "Audio Interchange File Format (AIFF)" |
|
||||
|
|
||||
def createContentSize(self): |
|
||||
return self["filesize"].value * 8 |
|
||||
|
|
@ -1,12 +1,12 @@ |
|||||
from lib.hachoir_parser.audio.aiff import AiffFile |
from hachoir_parser.audio.aiff import AiffFile |
||||
from lib.hachoir_parser.audio.au import AuFile |
from hachoir_parser.audio.au import AuFile |
||||
from lib.hachoir_parser.audio.itunesdb import ITunesDBFile |
from hachoir_parser.audio.itunesdb import ITunesDBFile |
||||
from lib.hachoir_parser.audio.midi import MidiFile |
from hachoir_parser.audio.midi import MidiFile |
||||
from lib.hachoir_parser.audio.mpeg_audio import MpegAudioFile |
from hachoir_parser.audio.mpeg_audio import MpegAudioFile |
||||
from lib.hachoir_parser.audio.real_audio import RealAudioFile |
from hachoir_parser.audio.real_audio import RealAudioFile |
||||
from lib.hachoir_parser.audio.xm import XMModule |
from hachoir_parser.audio.xm import XMModule |
||||
from lib.hachoir_parser.audio.s3m import S3MModule |
from hachoir_parser.audio.s3m import S3MModule |
||||
from lib.hachoir_parser.audio.s3m import PTMModule |
from hachoir_parser.audio.s3m import PTMModule |
||||
from lib.hachoir_parser.audio.mod import AmigaModule |
from hachoir_parser.audio.mod import AmigaModule |
||||
from lib.hachoir_parser.audio.flac import FlacParser |
from hachoir_parser.audio.flac import FlacParser |
||||
|
|
||||
|
@ -1,7 +1,7 @@ |
|||||
from lib.hachoir_parser.container.asn1 import ASN1File |
from hachoir_parser.container.asn1 import ASN1File |
||||
from lib.hachoir_parser.container.mkv import MkvFile |
from hachoir_parser.container.mkv import MkvFile |
||||
from lib.hachoir_parser.container.ogg import OggFile, OggStream |
from hachoir_parser.container.ogg import OggFile, OggStream |
||||
from lib.hachoir_parser.container.riff import RiffFile |
from hachoir_parser.container.riff import RiffFile |
||||
from lib.hachoir_parser.container.swf import SwfFile |
from hachoir_parser.container.swf import SwfFile |
||||
from lib.hachoir_parser.container.realmedia import RealMediaFile |
from hachoir_parser.container.realmedia import RealMediaFile |
||||
|
|
||||
|
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue