You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

458 lines
22 KiB

Change core system to improve performance and facilitate multi TV info sources. Change migrate core objects TVShow and TVEpisode and everywhere that these objects affect. Add message to logs and disable ui backlog buttons when no media provider has active and/or scheduled searching enabled. Change views for py3 compat. Change set default runtime of 5 mins if none is given for layout Day by Day. Add OpenSubtitles authentication support to config/Subtitles/Subtitles Plugin. Add "Enforce media hash match" to config/Subtitles Plugin/Opensubtitles for accurate subs if enabled, but if disabled, search failures will fallback to use less reliable subtitle results. Add Apprise 0.8.0 (6aa52c3). Add hachoir_py3 3.0a6 (5b9e05a). Add sgmllib3k 1.0.0 Update soupsieve 1.9.1 (24859cc) to soupsieve_py2 1.9.5 (6a38398) Add soupsieve_py3 2.0.0.dev (69194a2). Add Tornado_py3 Web Server 6.0.3 (ff985fe). Add xmlrpclib_to 0.1.1 (c37db9e). Remove ancient Growl lib 0.1 Remove xmltodict library. Change requirements.txt for Cheetah3 to minimum 3.2.4 Change update sabToSickBeard. Change update autoProcessTV. Change remove Twitter notifier. Update NZBGet Process Media extension, SickGear-NG 1.7 → 2.4 Update Kodi addon 1.0.3 → 1.0.4 Update ADBA for py3. Update Beautiful Soup 4.8.0 (r526) to 4.8.1 (r531). Update Send2Trash 1.3.0 (a568370) to 1.5.0 (66afce7). Update soupsieve 1.9.1 (24859cc) to 1.9.5 (6a38398). Change use GNTP (Growl Notification Transport Protocol) from Apprise. Change add multi host support to Growl notifier. Fix Growl notifier when using empty password. Change update links for Growl notifications. Change deprecate confg/Notifications/Growl password field as these are now stored with host setting. Fix prevent infinite memoryError from a particular jpg data structure. Change subliminal for py3. Change enzyme for py3. Change browser_ua for py3. Change feedparser for py3 (sgmlib is no longer available on py3 as standardlib so added ext lib) Fix Guessit. Fix parse_xml for py3. Fix name parser with multi eps for py3. Fix tvdb_api fixes for py3 (search show). Fix config/media process to only display "pattern is invalid" qtip on "Episode naming" tab if the associated field is actually visible. Also, if the field becomes hidden due to a setting change, hide any previously displayed qtip. Note for Javascript::getelementbyid (or $('tag[id="<name>"')) is required when an id is being searched in the dom due to ":" used in a shows id name. Change download anidb xml files to main cache folder and use adba lib folder as a last resort. Change create get anidb show groups as centralised helper func and consolidate dupe code. Change move anidb related functions to newly renamed anime.py (from blacklistandwhitelist.py). Change str encode hex no longer exits in py3, use codecs.encode(...) instead. Change fix b64decode on py3 returns bytestrings. Change use binary read when downloading log file via browser to prevent any encoding issues. Change add case insensitive ordering to anime black/whitelist. Fix anime groups list not excluding whitelisted stuff. Change add Windows utf8 fix ... see: ytdl-org/youtube-dl#820 Change if no qualities are wanted, exit manual search thread. Fix keepalive for py3 process media. Change add a once a month update of tvinfo show mappings to the daily updater. Change autocorrect ids of new shows by updating from -8 to 31 days of the airdate of episode one. Add next run time to Manage/Show Tasks/Daily show update. Change when fetching imdb data, if imdb id is an episode id then try to find and use real show id. Change delete diskcache db in imdbpie when value error (due to change in Python version). Change during startup, cleanup any _cleaner.pyc/o to prevent issues when switching python versions. Add .pyc cleaner if python version is switched. Change replace deprecated gettz_db_metadata() and gettz. Change rebrand "SickGear PostProcessing script" to "SickGear Process Media extension". Change improve setup guide to use the NZBGet version to minimise displayed text based on version. Change NZBGet versions prior to v17 now told to upgrade as those version are no longer supported - code has actually exit on start up for some time but docs were outdated. Change comment out code and unused option sg_base_path. Change supported Python version 2.7.9-2.7.18 inclusive expanded to 3.7.1-3.8.1 inclusive. Change pidfile creation under Linux 0o644. Make logger accept lists to output continuously using the log_lock instead of split up by other processes. Fix long path issues with Windows process media.
6 years ago
"""
Documents:
* libwx source code: see fib.c source code
* "Microsoft Word 97 Binary File Format"
http://bio.gsi.de/DOCS/AIX/wword8.html
Microsoft Word 97 (aka Version 8) for Windows and Macintosh. From the Office
book, found in the Microsoft Office Development section in the MSDN Online
Library. HTMLified June 1998. Revised Aug 1 1998, added missing Definitions
section. Revised Dec 21 1998, added missing Document Properties (section).
"""
from hachoir_py3.field import (FieldSet, Enum,
Bit, Bits,
UInt8, Int16, UInt16, UInt32, Int32,
NullBytes, Bytes, RawBytes, PascalString8, CString, String,
TimestampMac32, TimestampWin64)
from hachoir_py3.core.text_handler import displayHandler
from hachoir_py3.core.endian import LITTLE_ENDIAN
from hachoir_py3.parser import guessParser
from hachoir_py3.parser.misc.ole2_util import OLE2FragmentParser
from hachoir_py3.parser.common.win32_lang_id import LANGUAGE_ID
CREATOR_ID = {0x6A62: "Microsoft Word"}
class ShortArray(FieldSet):
def createFields(self):
yield UInt16(self, "csw", "Count of fields in the array of shorts")
self._size = self['csw'].value * 16 + 16
yield Enum(UInt16(self, "wMagicCreated", "File creator ID"), CREATOR_ID)
yield Enum(UInt16(self, "wMagicRevised", "File last modifier ID"), CREATOR_ID)
yield UInt16(self, "wMagicCreatePrivate")
yield UInt16(self, "wMagicCreatedPrivate")
yield UInt16(self, "pnFbpChpFirst_W6")
yield UInt16(self, "pnChpFirst_W6")
yield UInt16(self, "cpnBteChp_W6")
yield UInt16(self, "pnFbpPapFirst_W6")
yield UInt16(self, "pnPapFirst_W6")
yield UInt16(self, "cpnBtePap_W6")
yield UInt16(self, "pnFbpLvcFirst_W6")
yield UInt16(self, "pnLvcFirst_W6")
yield UInt16(self, "cpnBteLvc_W6")
yield Enum(UInt16(self, "lidFE", "Language ID if a Far East version of Word was used"), LANGUAGE_ID)
while self.current_size < self.size:
yield Int16(self, "unknown[]")
def buildDateHandler(v):
md, y = divmod(v, 100)
m, d = divmod(md, 100)
if y < 60:
y = 2000 + y
else:
y = 1900 + y
return "%04i-%02i-%02i" % (y, m, d)
class LongArray(FieldSet):
def createFields(self):
yield UInt16(self, "clw", "Count of fields in the array of longs")
self._size = self['clw'].value * 32 + 16
yield Int32(self, "cbMax", "Stream offset of last byte + 1")
yield displayHandler(UInt32(self, "lProductCreated", "Date when the creator program was built"), buildDateHandler)
yield displayHandler(UInt32(self, "lProductRevised", "Date when the last modifier program was built"), buildDateHandler)
yield UInt32(self, "ccpText", "Length of main document text stream")
yield Int32(self, "ccpFtn", "Length of footnote subdocument text stream")
yield Int32(self, "ccpHdr", "Length of header subdocument text stream")
yield Int32(self, "ccpMcr", "Length of macro subdocument text stream")
yield Int32(self, "ccpAtn", "Length of annotation subdocument text stream")
yield Int32(self, "ccpEdn", "Length of endnote subdocument text stream")
yield Int32(self, "ccpTxbx", "Length of textbox subdocument text stream")
yield Int32(self, "ccpHdrTxbx", "Length of header textbox subdocument text stream")
yield Int32(self, "pnFbpChpFirst", "Start of CHPX (Character Property) sector chain (sector = 512-byte 'page')")
yield Int32(self, "pnChpFirst", "First CHPX sector")
yield Int32(self, "cpnBteChp", "Number of CHPX sectors in the file")
yield Int32(self, "pnFbpPapFirst", "Start of PAPX (Paragraph Property) sector chain")
yield Int32(self, "pnPapFirst", "First PAPX sector")
yield Int32(self, "cpnBtePap", "Number of PAPX sectors in the file")
yield Int32(self, "pnFbpLvcFirst", "Start of LVC sector chain")
yield Int32(self, "pnLvcFirst", "First LVC sector")
yield Int32(self, "cpnBteLvc", "Number of LVC sectors in the file")
yield Int32(self, "fcIslandFirst")
yield Int32(self, "fcIslandLim")
while self.current_size < self.size:
yield Int32(self, "unknown[]")
class FCLCB(FieldSet):
static_size = 64
def createFields(self):
yield Int32(self, "fc", "Table Stream Offset")
yield UInt32(self, "lcb", "Byte Count")
def createValue(self):
return (self['fc'].value, self['lcb'].value)
class FCLCBArray(FieldSet):
def createFields(self):
yield UInt16(self, "cfclcb", "Count of fields in the array of FC/LCB pairs")
self._size = self['cfclcb'].value * 64 + 16
yield FCLCB(self, "StshfOrig", "Original STSH allocation")
yield FCLCB(self, "Stshf", "Current STSH allocation")
yield FCLCB(self, "PlcffndRef", "Footnote reference (FRD) PLC")
yield FCLCB(self, "PlcffndTxt", "Footnote text PLC")
yield FCLCB(self, "PlcfandRef", "Annotation reference (ATRD) PLC")
yield FCLCB(self, "PlcfandTxt", "Annotation text PLC")
yield FCLCB(self, "Plcfsed", "Section descriptor (SED) PLC")
yield FCLCB(self, "Plcpad", "No longer used; used to be Plcfpgd (Page descriptor PLC)")
yield FCLCB(self, "Plcfphe", "Paragraph heights (PHE) PLC (only for Complex files)")
yield FCLCB(self, "Sttbfglsy", "Glossary string table")
yield FCLCB(self, "Plcfglsy", "Glossary PLC")
yield FCLCB(self, "Plcfhdd", "Header (HDD) PLC")
yield FCLCB(self, "PlcfbteChpx", "Character property bin table PLC")
yield FCLCB(self, "PlcfbtePapx", "Paragraph property bin table PLC")
yield FCLCB(self, "Plcfsea", "Private Use PLC")
yield FCLCB(self, "Sttbfffn", "Font information STTB")
yield FCLCB(self, "PlcffldMom", "Main document field position (FLD) PLC")
yield FCLCB(self, "PlcffldHdr", "Header subdocument field position (FLD) PLC")
yield FCLCB(self, "PlcffldFtn", "Footnote subdocument field position (FLD) PLC")
yield FCLCB(self, "PlcffldAtn", "Annotation subdocument field position (FLD) PLC")
yield FCLCB(self, "PlcffldMcr", "No longer used")
yield FCLCB(self, "Sttbfbkmk", "Bookmark names STTB")
yield FCLCB(self, "Plcfbkf", "Bookmark begin position (BKF) PLC")
yield FCLCB(self, "Plcfbkl", "Bookmark end position (BKL) PLC")
yield FCLCB(self, "Cmds", "Macro commands")
yield FCLCB(self, "Plcmcr", "No longer used")
yield FCLCB(self, "Sttbfmcr", "No longer used")
yield FCLCB(self, "PrDrvr", "Printer Driver information")
yield FCLCB(self, "PrEnvPort", "Printer environment for Portrait mode")
yield FCLCB(self, "PrEnvLand", "Printer environment for Landscape mode")
yield FCLCB(self, "Wss", "Window Save State")
yield FCLCB(self, "Dop", "Document Property data")
yield FCLCB(self, "SttbfAssoc", "Associated strings STTB")
yield FCLCB(self, "Clx", "Complex file information")
yield FCLCB(self, "PlcfpgdFtn", "Not used")
yield FCLCB(self, "AutosaveSource", "Original filename for Autosave purposes")
yield FCLCB(self, "GrpXstAtnOwners", "String Group for Annotation Owner Names")
yield FCLCB(self, "SttbfAtnbkmk", "Annotation subdocument bookmark names STTB")
yield FCLCB(self, "PlcdoaMom", "No longer used")
yield FCLCB(self, "PlcdoaHdr", "No longer used")
yield FCLCB(self, "PlcspaMom", "Main document File Shape (FSPA) PLC")
yield FCLCB(self, "PlcspaHdr", "Header subdocument FSPA PLC")
yield FCLCB(self, "PlcfAtnbkf", "Annotation subdocument bookmark begin position (BKF) PLC")
yield FCLCB(self, "PlcfAtnbkl", "Annotation subdocument bookmark end position (BKL) PLC")
yield FCLCB(self, "Pms", "Print Merge State")
yield FCLCB(self, "FormFldSttbs", "Form field values STTB")
yield FCLCB(self, "PlcfendRef", "Endnote Reference (FRD) PLC")
yield FCLCB(self, "PlcfendTxt", "Endnote Text PLC")
yield FCLCB(self, "PlcffldEdn", "Endnote subdocument field position (FLD) PLC)")
yield FCLCB(self, "PlcfpgdEdn", "not used")
yield FCLCB(self, "DggInfo", "Office Art Object Table Data")
yield FCLCB(self, "SttbfRMark", "Editor Author Abbreviations STTB")
yield FCLCB(self, "SttbCaption", "Caption Title STTB")
yield FCLCB(self, "SttbAutoCaption", "Auto Caption Title STTB")
yield FCLCB(self, "Plcfwkb", "WKB PLC")
yield FCLCB(self, "Plcfspl", "Spell Check State PLC")
yield FCLCB(self, "PlcftxbxTxt", "Text Box Text PLC")
yield FCLCB(self, "PlcffldTxbx", "Text Box Reference (FLD) PLC")
yield FCLCB(self, "PlcfhdrtxbxTxt", "Header Text Box Text PLC")
yield FCLCB(self, "PlcffldHdrTxbx", "Header Text Box Reference (FLD) PLC")
yield FCLCB(self, "StwUser", "Macro User storage")
yield FCLCB(self, "Sttbttmbd", "Embedded TrueType Font Data")
yield FCLCB(self, "Unused")
yield FCLCB(self, "PgdMother", "Main text page descriptors PLF")
yield FCLCB(self, "BkdMother", "Main text break descriptors PLF")
yield FCLCB(self, "PgdFtn", "Footnote text page descriptors PLF")
yield FCLCB(self, "BkdFtn", "Footnote text break descriptors PLF")
yield FCLCB(self, "PgdEdn", "Endnote text page descriptors PLF")
yield FCLCB(self, "BkdEdn", "Endnote text break descriptors PLF")
yield FCLCB(self, "SttbfIntlFld", "Field keywords STTB")
yield FCLCB(self, "RouteSlip", "Mailer Routing Slip")
yield FCLCB(self, "SttbSavedBy", "STTB of names of users who have saved the document")
yield FCLCB(self, "SttbFnm", "STTB of filenames of documents referenced by this one")
yield FCLCB(self, "PlcfLst", "List Format information PLC")
yield FCLCB(self, "PlfLfo", "List Format Override information PLC")
yield FCLCB(self, "PlcftxbxBkd", "Main document textbox break table (BKD) PLC")
yield FCLCB(self, "PlcftxbxHdrBkd", "Header subdocument textbox break table (BKD) PLC")
yield FCLCB(self, "DocUndo", "Undo/Versioning data")
yield FCLCB(self, "Rgbuse", "Undo/Versioning data")
yield FCLCB(self, "Usp", "Undo/Versioning data")
yield FCLCB(self, "Uskf", "Undo/Versioning data")
yield FCLCB(self, "PlcupcRgbuse", "Undo/Versioning data")
yield FCLCB(self, "PlcupcUsp", "Undo/Versioning data")
yield FCLCB(self, "SttbGlsyStyle", "Glossary entry style names STTB")
yield FCLCB(self, "Plgosl", "Grammar options PL")
yield FCLCB(self, "Plcocx", "OCX data PLC")
yield FCLCB(self, "PlcfbteLvc", "Character property bin table PLC")
if self['../fMac'].value:
yield TimestampMac32(self, "ftModified", "Date last modified")
yield Int32(self, "padding[]")
else:
yield TimestampWin64(self, "ftModified", "Date last modified")
yield FCLCB(self, "Plcflvc", "LVC PLC")
yield FCLCB(self, "Plcasumy", "Autosummary PLC")
yield FCLCB(self, "Plcfgram", "Grammar check PLC")
yield FCLCB(self, "SttbListNames", "List names STTB")
yield FCLCB(self, "SttbfUssr", "Undo/Versioning data")
while self.current_size < self.size:
yield FCLCB(self, "unknown[]")
class FIB(FieldSet):
def createFields(self):
yield UInt16(self, "wIdent", "Magic Number")
yield UInt16(self, "nFib", "File Information Block (FIB) Version")
yield UInt16(self, "nProduct", "Product Version")
yield Enum(UInt16(self, "lid", "Language ID"), LANGUAGE_ID)
yield Int16(self, "pnNext")
yield Bit(self, "fDot", "Is the document a document template?")
yield Bit(self, "fGlsy", "Is the document a glossary?")
yield Bit(self, "fComplex", "Is the document in Complex format?")
yield Bit(self, "fHasPic", "Does the document have embedded images?")
yield Bits(self, "cQuickSaves", 4, "Number of times the document was quick-saved")
yield Bit(self, "fEncrypted", "Is the document encrypted?")
yield Bits(self, "fWhichTblStm", 1, "Which table stream (0Table or 1Table) to use")
yield Bit(self, "fReadOnlyRecommended", "Should the file be opened read-only?")
yield Bit(self, "fWriteReservation", "Is the file write-reserved?")
yield Bit(self, "fExtChar", "Does the file use an extended character set?")
yield Bit(self, "fLoadOverride")
yield Bit(self, "fFarEast")
yield Bit(self, "fCrypto")
yield UInt16(self, "nFibBack", "Document is backwards compatible down to this FIB version")
yield UInt32(self, "lKey", "File encryption key (only if fEncrypted)")
yield Enum(UInt8(self, "envr", "Document creation environment"), {0: 'Word for Windows', 1: 'Macintosh Word'})
yield Bit(self, "fMac", "Was this file last saved on a Mac?")
yield Bit(self, "fEmptySpecial")
yield Bit(self, "fLoadOverridePage")
yield Bit(self, "fFutureSavedUndo")
yield Bit(self, "fWord97Save")
yield Bits(self, "fSpare0", 3)
CHARSET = {0: 'Windows ANSI', 256: 'Macintosh'}
yield Enum(UInt16(self, "chse", "Character set for document text"), CHARSET)
yield Enum(UInt16(self, "chsTables", "Character set for internal table text"), CHARSET)
yield UInt32(self, "fcMin", "File offset for the first character of text")
yield UInt32(self, "fcMax", "File offset for the last character of text + 1")
yield ShortArray(self, "array1", "Array of shorts")
yield LongArray(self, "array2", "Array of longs")
yield FCLCBArray(self, "array3", "Array of File Offset/Byte Count (FC/LCB) pairs")
def getRootParser(ole2):
return guessParser(ole2["root[0]"].getSubIStream())
def getOLE2Parser(ole2, path):
name = path + "[0]"
if name in ole2:
fragment = ole2[name]
else:
fragment = getRootParser(ole2)[name]
return guessParser(fragment.getSubIStream())
class WordDocumentParser(OLE2FragmentParser):
MAGIC = b'\xec\xa5' # 42476
PARSER_TAGS = {
"id": "word_document",
"min_size": 8,
"magic": ((MAGIC, 0),),
"description": "Microsoft Office Word document",
}
endian = LITTLE_ENDIAN
def __init__(self, stream, **args):
OLE2FragmentParser.__init__(self, stream, **args)
def validate(self):
if self.stream.readBytes(0, 2) != self.MAGIC:
return "Invalid magic."
if self['FIB/nFib'].value not in (192, 193):
return "Unknown FIB version."
return True
def createFields(self):
yield FIB(self, "FIB", "File Information Block")
getOLE2Parser(self.ole2, "table" +
str(self["FIB/fWhichTblStm"].value))
padding = (self['FIB/fcMin'].value - self.current_size // 8)
if padding:
yield NullBytes(self, "padding[]", padding)
# Guess whether the file uses UTF16 encoding.
is_unicode = False
if self['FIB/array2/ccpText'].value * 2 == self['FIB/fcMax'].value - self['FIB/fcMin'].value:
is_unicode = True
for fieldname, textname in [('Text', 'text'), ('Ftn', 'text_footnote'),
('Hdr', 'text_header'), ('Mcr',
'text_macro'), ('Atn', 'text_annotation'),
('Edn', 'text_endnote'), ('Txbx', 'text_textbox'), ('HdrTxbx', 'text_header_textbox')]:
size = self['FIB/array2/ccp' + fieldname].value
if size:
if is_unicode:
yield String(self, textname, size * 2, charset="UTF-16-LE")
else:
yield Bytes(self, textname, size)
padding = (self['FIB/fcMax'].value - self.current_size // 8)
if padding:
yield RawBytes(self, "padding[]", padding)
class WidePascalString16(String):
def __init__(self, parent, name, description=None,
strip=None, nbytes=None, truncate=None):
Bytes.__init__(self, parent, name, 1, description)
self._format = "WidePascalString16"
self._strip = strip
self._truncate = truncate
self._character_size = 2
self._charset = "UTF-16-LE"
self._content_offset = 2
self._content_size = self._character_size * self._parent.stream.readBits(
self.absolute_address, self._content_offset * 8, self._parent.endian)
self._size = (self._content_size + self.content_offset) * 8
class TableParsers(object):
class Bte(FieldSet):
'Bin Table Entry'
static_size = 32
def createFields(self):
yield Bits(self, "pn", 22, "Referenced page number")
yield Bits(self, "unused", 10)
def createValue(self):
return self["pn"].value
class Ffn(FieldSet):
'Font Family Name'
def createFields(self):
yield UInt8(self, "size", "Total length of this FFN in bytes, minus 1")
self._size = self["size"].value * 8 + 8
yield Bits(self, "prq", 2, "Pitch request")
yield Bit(self, "fTrueType", "Is font a TrueType font?")
yield Bits(self, "reserved[]", 1)
yield Bits(self, "ff", 3, "Font Family ID")
yield Bits(self, "reserved[]", 1)
yield UInt16(self, "wWeight", "Base weight of font")
yield UInt8(self, "chs", "Character set identifier")
yield UInt8(self, "ixchSzAlt", "Index into name to the name of the alternate font")
yield RawBytes(self, "panose", 10)
yield RawBytes(self, "fs", 24, "Font Signature")
yield CString(self, "name", charset="UTF-16-LE")
if self["ixchSzAlt"].value != 0:
yield CString(self, "nameAlt", charset="UTF-16-LE")
def createValue(self):
return self["name"].value
class Sttbf(FieldSet):
'String Table stored in File'
SttbfAssocDESC = {
0: "FileNext: unused",
1: "Dot: filename of associated template",
2: "Title: title of document",
3: "Subject: subject of document",
4: "KeyWords: keywords of document",
5: "Comments: comments of document",
6: "Author: author of document",
7: "LastRevBy: name of person who last revised the document",
8: "DataDoc: filename of data document",
9: "HeaderDoc: filename of header document",
10: "Criteria1: packed string used by print merge record selection",
11: "Criteria2: packed string used by print merge record selection",
12: "Criteria3: packed string used by print merge record selection",
13: "Criteria4: packed string used by print merge record selection",
14: "Criteria5: packed string used by print merge record selection",
15: "Criteria6: packed string used by print merge record selection",
16: "Criteria7: packed string used by print merge record selection",
17: "Max: maximum number of strings in string table",
}
def createFields(self):
if self.stream.readBytes(self.absolute_address, 2) == b"\xff\xff":
yield Int16(self, "utf16_marker", "If this field is present, the Sttbf contains UTF-16 data.")
self.is_utf16 = True
else:
self.is_utf16 = False
yield UInt16(self, "count", "Number of strings in this Sttbf")
extra_data_field = UInt16(
self, "extra_data_len", "Size of optional extra data after each string")
yield extra_data_field
extra_data_len = extra_data_field.value
for i in range(self["count"].value):
if self.name == "SttbfAssoc":
desc = self.SttbfAssocDESC.get(i, None)
else:
desc = None
if self.name == "Sttbfffn":
yield TableParsers.Ffn(self, "string[]", desc)
elif self.is_utf16:
yield WidePascalString16(self, "string[]", desc)
else:
yield PascalString8(self, "string[]", desc)
if extra_data_len:
yield RawBytes(self, "extra[]", extra_data_len)
class Plcf(FieldSet):
'Plex of CPs/FCs stored in file'
def createFields(self):
if self.size is None:
return
chunk_parser = None
size = None
if self.name.startswith("Plcfbte"):
chunk_parser = TableParsers.Bte
if not chunk_parser:
return
if size is None:
size = chunk_parser.static_size // 8
n = (self.size // 8 - 4) // (4 + size)
for i in range(n + 1):
yield UInt32(self, "cp_fc[]", "CP or FC value")
for i in range(n):
yield chunk_parser(self, "obj[]")
class WordTableParser(OLE2FragmentParser):
def createFields(self):
word_doc = getOLE2Parser(self.ole2, "word_doc")
if word_doc["FIB/fWhichTblStm"].value != int(self.ole2name[0]):
yield RawBytes(self, "inactive_table", self.datasize)
return
for fclcb in word_doc["FIB/array3"]:
if not isinstance(fclcb, FCLCB):
continue
if fclcb["fc"].value < 0 or fclcb["lcb"].value <= 0:
continue
self.seekByte(fclcb["fc"].value, relative=False)
if fclcb.name.startswith("Sttb"):
yield TableParsers.Sttbf(self, fclcb.name, size=fclcb["lcb"].value * 8)
elif fclcb.name.startswith("Plc"):
yield TableParsers.Plcf(self, fclcb.name, size=fclcb["lcb"].value * 8)
else:
yield RawBytes(self, fclcb.name, fclcb["lcb"].value, fclcb.description)