mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-01 00:43:37 +00:00
980e05cc99
Backported 400 revisions from rev 1de4961-8897c5b (2018-2014). Move core/benchmark, core/cmd_line, core/memory, core/profiler and core/timeout to core/optional/* Remove metadata/qt* PORT: Version 2.0a3 (inline with 3.0a3 @ f80c7d5). Basic Support for XMP Packets. tga: improvements to adhere more closely to the spec. pdf: slightly improved parsing. rar: fix TypeError on unknown block types. Add MacRoman win32 codepage. tiff/exif: support SubIFDs and tiled images. Add method to export metadata in dictionary. mpeg_video: don't attempt to parse Stream past length. mpeg_video: parse ESCR correctly, add SCR value. Change centralise CustomFragments. field: don't set parser class if class is None, to enable autodetect. field: add value/display for CustomFragment. parser: inline warning to enable tracebacks in debug mode. Fix empty bytestrings in makePrintable. Fix contentSize in jpeg.py to account for image_data blocks. Fix the ELF parser. Enhance the AR archive parser. elf parser: fix wrong wrong fields order in parsing little endian section flags. elf parser: add s390 as a machine type. Flesh out mp4 parser. PORT: Version 2.0a1 (inline with 3.0a1). Major refactoring and PEP8. Fix ResourceWarning warnings on files. Add a close() method and support for the context manager protocol ("with obj: ...") to parsers, input and output streams. metadata: get comment from ZIP. Support for InputIOStream.read(0). Fix sizeGe when size is None. Remove unused new_seekable_field_set file. Remove parser Mapsforge .map. Remove parser Parallel Realities Starfighter .pak files. sevenzip: fix for newer archives. java: update access flags and modifiers for Java 1.7 and update description text for most recent Java. Support ustar prefix field in tar archives. Remove file_system* parsers. Remove misc parsers 3d0, 3ds, gnome_keyring, msoffice*, mstask, ole*, word*. Remove program parsers macho, nds, prc. Support non-8bit Character subclasses. Python parser supports Python 3.7. Enhance mpeg_ts parser to support MTS/M2TS. Support for creation date in tiff. Change don't hardcode errno constant. PORT: 1.9.1 Internal Only: The following are legacy reference to upstream commit messages. Relevant changes up to b0a115f8. Use integer division. Replace HACHOIR_ERRORS with Exception. Fix metadata.Data: make it sortable. Import fixes from e7de492. PORT: Version 2.0a1 (inline with 3.0a1 @ e9f8fad). Replace hachoir.core.field with hachoir.field Replace hachoir.core.stream with hachoir.stream Remove the compatibility module for PY1.5 to PY2.5. metadata: support TIFF picture. metadata: fix string normalization. metadata: fix datetime regex Fix hachoir bug #57. FileFromInputStream: fix comparison between None and an int. InputIOStream: open the file in binary mode.
194 lines
7.1 KiB
Python
194 lines
7.1 KiB
Python
from hachoir.metadata.metadata_item import QUALITY_BEST, QUALITY_FASTEST
|
|
from hachoir.metadata.safe import fault_tolerant, getValue
|
|
from hachoir.metadata.metadata import (
|
|
RootMetadata, Metadata, MultipleMetadata, registerExtractor)
|
|
from hachoir.parser.archive import (Bzip2Parser, CabFile, GzipParser,
|
|
TarFile, ZipFile, MarFile)
|
|
from hachoir.core.tools import humanUnixAttributes
|
|
from hachoir.core.i18n import _
|
|
|
|
|
|
def maxNbFile(meta):
|
|
if meta.quality <= QUALITY_FASTEST:
|
|
return 0
|
|
if QUALITY_BEST <= meta.quality:
|
|
return None
|
|
return 1 + int(10 * meta.quality)
|
|
|
|
|
|
def computeCompressionRate(meta):
|
|
"""
|
|
Compute compression rate, sizes have to be in byte.
|
|
"""
|
|
if (not meta.has("file_size")
|
|
or not meta.get("compr_size", 0)):
|
|
return
|
|
file_size = meta.get("file_size")
|
|
if not file_size:
|
|
return
|
|
meta.compr_rate = float(file_size) / meta.get("compr_size")
|
|
|
|
|
|
class Bzip2Metadata(RootMetadata):
|
|
def extract(self, zip):
|
|
if "file" in zip:
|
|
self.compr_size = zip["file"].size // 8
|
|
|
|
|
|
class GzipMetadata(RootMetadata):
|
|
def extract(self, gzip):
|
|
self.useHeader(gzip)
|
|
computeCompressionRate(self)
|
|
|
|
@fault_tolerant
|
|
def useHeader(self, gzip):
|
|
self.compression = gzip["compression"].display
|
|
if gzip["mtime"]:
|
|
self.last_modification = gzip["mtime"].value
|
|
self.os = gzip["os"].display
|
|
if gzip["has_filename"].value:
|
|
self.filename = getValue(gzip, "filename")
|
|
if gzip["has_comment"].value:
|
|
self.comment = getValue(gzip, "comment")
|
|
self.compr_size = gzip["file"].size // 8
|
|
self.file_size = gzip["size"].value
|
|
|
|
|
|
class ZipMetadata(MultipleMetadata):
|
|
|
|
def extract(self, zip):
|
|
max_nb = maxNbFile(self)
|
|
for index, field in enumerate(zip.array("file")):
|
|
if max_nb is not None and max_nb <= index:
|
|
self.warning("ZIP archive contains many files, "
|
|
"but only first %s files are processed"
|
|
% max_nb)
|
|
break
|
|
self.processFile(field)
|
|
|
|
self.extract_end_central_directory(zip)
|
|
|
|
@fault_tolerant
|
|
def extract_end_central_directory(self, parser):
|
|
comment = parser['end_central_directory/comment'].value
|
|
if comment:
|
|
self.comment = comment
|
|
|
|
@fault_tolerant
|
|
def processFile(self, field):
|
|
meta = Metadata(self)
|
|
meta.filename = field["filename"].value
|
|
meta.creation_date = field["last_mod"].value
|
|
meta.compression = field["compression"].display
|
|
if "data_desc" in field:
|
|
meta.file_size = field["data_desc/file_uncompressed_size"].value
|
|
if field["data_desc/file_compressed_size"].value:
|
|
meta.compr_size = field["data_desc/file_compressed_size"].value
|
|
else:
|
|
meta.file_size = field["uncompressed_size"].value
|
|
if field["compressed_size"].value:
|
|
meta.compr_size = field["compressed_size"].value
|
|
computeCompressionRate(meta)
|
|
self.addGroup(field.name, meta, "File \"%s\"" % meta.get('filename'))
|
|
|
|
|
|
class TarMetadata(MultipleMetadata):
|
|
def extract(self, tar):
|
|
max_nb = maxNbFile(self)
|
|
for index, field in enumerate(tar.array("file")):
|
|
if max_nb is not None and max_nb <= index:
|
|
self.warning("TAR archive contains many files, "
|
|
"but only first %s files are processed"
|
|
% max_nb)
|
|
break
|
|
meta = Metadata(self)
|
|
self.extractFile(field, meta)
|
|
if meta.has("filename"):
|
|
title = _('File "%s"') % meta.getText('filename')
|
|
else:
|
|
title = _("File")
|
|
self.addGroup(field.name, meta, title)
|
|
|
|
@fault_tolerant
|
|
def extractFile(self, field, meta):
|
|
meta.filename = field["name"].value
|
|
meta.file_attr = humanUnixAttributes(field.getOctal("mode"))
|
|
meta.file_size = field.getOctal("size")
|
|
try:
|
|
if field.getOctal("mtime"):
|
|
meta.last_modification = field.getDatetime()
|
|
except ValueError:
|
|
pass
|
|
meta.file_type = field["type"].display
|
|
meta.author = "%s (uid=%s), group %s (gid=%s)" % \
|
|
(field["uname"].value, field.getOctal("uid"),
|
|
field["gname"].value, field.getOctal("gid"))
|
|
|
|
|
|
class CabMetadata(MultipleMetadata):
|
|
def extract(self, cab):
|
|
if "folder[0]" in cab:
|
|
self.useFolder(cab["folder[0]"])
|
|
self.format_version = "Microsoft Cabinet version %s.%s"\
|
|
% (cab["major_version"].display,
|
|
cab["minor_version"].display)
|
|
self.comment = "%s folders, %s files" % (
|
|
cab["nb_folder"].value, cab["nb_files"].value)
|
|
max_nb = maxNbFile(self)
|
|
for index, field in enumerate(cab.array("file")):
|
|
if max_nb is not None and max_nb <= index:
|
|
self.warning("CAB archive contains many files, "
|
|
"but only first %s files are processed"
|
|
% max_nb)
|
|
break
|
|
self.useFile(field)
|
|
|
|
@fault_tolerant
|
|
def useFolder(self, folder):
|
|
compr = folder["compr_method"].display
|
|
if folder["compr_method"].value != 0:
|
|
compr += " (level %u)" % folder["compr_level"].value
|
|
self.compression = compr
|
|
|
|
@fault_tolerant
|
|
def useFile(self, field):
|
|
meta = Metadata(self)
|
|
meta.filename = field["filename"].value
|
|
meta.file_size = field["filesize"].value
|
|
meta.creation_date = field["timestamp"].value
|
|
attr = field["attributes"].value
|
|
if attr != "(none)":
|
|
meta.file_attr = attr
|
|
if meta.has("filename"):
|
|
title = _("File \"%s\"") % meta.getText('filename')
|
|
else:
|
|
title = _("File")
|
|
self.addGroup(field.name, meta, title)
|
|
|
|
|
|
class MarMetadata(MultipleMetadata):
|
|
def extract(self, mar):
|
|
self.comment = "Contains %s files" % mar["nb_file"].value
|
|
self.format_version = "Microsoft Archive version %s"\
|
|
% mar["version"].value
|
|
max_nb = maxNbFile(self)
|
|
for index, field in enumerate(mar.array("file")):
|
|
if max_nb is not None and max_nb <= index:
|
|
self.warning("MAR archive contains many files, "
|
|
"but only first %s files are processed"
|
|
% max_nb)
|
|
break
|
|
meta = Metadata(self)
|
|
meta.filename = field["filename"].value
|
|
meta.compression = "None"
|
|
meta.file_size = field["filesize"].value
|
|
self.addGroup(field.name, meta,
|
|
"File \"%s\"" % meta.getText('filename'))
|
|
|
|
|
|
registerExtractor(CabFile, CabMetadata)
|
|
registerExtractor(GzipParser, GzipMetadata)
|
|
registerExtractor(Bzip2Parser, Bzip2Metadata)
|
|
registerExtractor(TarFile, TarMetadata)
|
|
registerExtractor(ZipFile, ZipMetadata)
|
|
registerExtractor(MarFile, MarMetadata)
|