#!/usr/bin/env python3 # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # from builtins import range import locale from . import globals from .binarystream import BinaryStream from . import docsprm from . import msodraw def getWordModel(mainStream): model = globals.ModelBase(globals.ModelBase.HostAppType.Word) model.delayStream = mainStream return model class FcCompressed(BinaryStream): """The FcCompressed structure specifies the location of text in the WordDocument Stream.""" def __init__(self, bytes, mainStream, offset, size): BinaryStream.__init__(self, bytes, mainStream=mainStream) self.pos = offset self.size = size buf = self.readuInt32() self.fc = buf & ((2 ** 32 - 1) >> 2) # bits 0..29 self.fCompressed = self.getBit(buf, 30) self.r1 = self.getBit(buf, 31) def dump(self): print('' % (self.pos, self.size)) self.printAndSet("fc", self.fc) self.printAndSet("fCompressed", self.fCompressed) self.printAndSet("r1", self.r1) print('') class Pcd(BinaryStream): """The Pcd structure specifies the location of text in the WordDocument Stream and additional properties for this text.""" def __init__(self, bytes, mainStream, offset, size): BinaryStream.__init__(self, bytes, mainStream=mainStream) self.pos = offset self.size = size buf = self.readuInt16() self.fNoParaLast = self.getBit(buf, 0) self.fR1 = self.getBit(buf, 1) self.fDirty = self.getBit(buf, 2) self.fR2 = buf & (2 ** 13 - 1) self.fc = FcCompressed(self.bytes, self.mainStream, self.pos, 4) self.pos += 4 def dump(self): print('' % (self.pos, self.size)) self.printAndSet("fNoParaLast", self.fNoParaLast) self.printAndSet("fR1", self.fR1) self.printAndSet("fDirty", self.fDirty) self.printAndSet("fR2", self.fR2) self.fc.dump() print('') class PLC: """The PLC structure is an array of character positions followed by an array of data elements.""" def __init__(self, totalSize, structSize): self.totalSize = totalSize self.structSize = structSize def getElements(self): return (self.totalSize - 4) // (4 + self.structSize) # defined by 2.2.2 def getOffset(self, pos, i): return self.getPLCOffset(pos, self.getElements(), self.structSize, i) @staticmethod def getPLCOffset(pos, elements, structSize, i): return pos + (4 * (elements + 1)) + (structSize * i) class BKC(BinaryStream): """The BKC structure contains information about how a bookmark interacts with tables.""" def __init__(self, bkc): self.bkc = bkc def dump(self): print('') self.printAndSet("itcFirst", self.bkc & 0x007f) # 1..7th bits self.printAndSet("fPub", self.getBit(self.bkc, 8)) self.printAndSet("itcLim", (self.bkc & 0x3f00) >> 8) # 9..14th bits self.printAndSet("fNative", self.getBit(self.bkc, 15)) self.printAndSet("fCol", self.getBit(self.bkc, 16)) print('') class FBKF(BinaryStream): """The FBKF structure contains information about a bookmark.""" def __init__(self, plcfAtnBkf, offset): BinaryStream.__init__(self, plcfAtnBkf.bytes) self.pos = offset def dump(self): print('' % self.pos) self.printAndSet("ibkl", self.readuInt16()) BKC(self.readuInt16()).dump() print('') class PlcfBkf(BinaryStream, PLC): """A PLCFBKF is a PLC whose data elements are FBKF structures.""" def __init__(self, mainStream, offset, size): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) PLC.__init__(self, size, 4) # 4 is defined by 2.8.10 self.pos = offset self.size = size self.aCP = [] self.aFBKF = [] def dump(self): print('' % (self.pos, self.size)) pos = self.pos for i in range(self.getElements()): # aCp start = self.getuInt32(pos=pos) self.aCP.append(start) print('' % (i, start)) pos += 4 # aFBKF aFBKF = FBKF(self, self.getOffset(self.pos, i)) aFBKF.dump() self.aFBKF.append(aFBKF) print('') print('') class FBKFD(BinaryStream): """Specified by [MS-DOC] 2.9.71, contains information about a bookmark.""" def __init__(self, parent, offset): BinaryStream.__init__(self, parent.bytes) self.pos = offset def dump(self): print('' % self.pos) FBKF(self, self.pos).dump() self.pos += 4 self.printAndSet("cDepth", self.readInt16()) print('') class PlcfBkfd(BinaryStream, PLC): """Specified by [MS-DOC] 2.8.11, a PLC whose data elements are FBKFD structures.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) PLC.__init__(self, mainStream.lcbPlcfBkfFactoid, 6) # 6 is defined by 2.8.10 self.pos = mainStream.fcPlcfBkfFactoid self.size = mainStream.lcbPlcfBkfFactoid self.aCP = [] self.aFBKFD = [] def dump(self): print('' % (self.pos, self.size)) pos = self.pos for i in range(self.getElements()): # aCp start = self.getuInt32(pos=pos) self.aCP.append(start) print('' % (i, start)) pos += 4 # aFBKFD aFBKFD = FBKFD(self, self.getOffset(self.pos, i)) aFBKFD.dump() self.aFBKFD.append(aFBKFD) print('') print('') class FBKLD(BinaryStream): """Specified by [MS-DOC] 2.9.72, contains information about a bookmark.""" def __init__(self, parent, offset): BinaryStream.__init__(self, parent.bytes) self.pos = offset def dump(self): print('' % self.pos) self.printAndSet("ibkf", self.readuInt16()) self.printAndSet("cDepth", self.readuInt16()) print('') class PlcfBkld(BinaryStream, PLC): """Specified by [MS-DOC] 2.8.13, a PLC whose data elements are FBKLD structures.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) PLC.__init__(self, mainStream.lcbPlcfBklFactoid, 4) # 4 is defined by the spec self.pos = mainStream.fcPlcfBklFactoid self.size = mainStream.lcbPlcfBklFactoid self.aCP = [] self.aFBKLD = [] def dump(self): print('' % (self.pos, self.size)) pos = self.pos for i in range(self.getElements()): # aCp start = self.getuInt32(pos=pos) self.aCP.append(start) print('' % (i, start)) pos += 4 # aFBKLD aFBKLD = FBKLD(self, self.getOffset(self.pos, i)) aFBKLD.dump() self.aFBKLD.append(aFBKLD) print('') print('') class FactoidSpls(BinaryStream): """Specified by [MS-DOC] 2.9.67, an SPLS structure that specifies the state of the smart tag recognizer over a range of text.""" def __init__(self, parent, offset): BinaryStream.__init__(self, parent.bytes) self.pos = offset def dump(self): print('' % self.pos) SPLS("spls", self, self.pos).dump() print('') class Plcffactoid(BinaryStream, PLC): """Specified by [MS-DOC] 2.8.18, a PLC whose data elements are FactoidSpls structures.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) PLC.__init__(self, mainStream.lcbPlcffactoid, 2) # 2 is defined by the spec self.pos = mainStream.fcPlcffactoid self.size = mainStream.lcbPlcffactoid self.aCPs = [] self.aFactoidSpls = [] def dump(self): print('' % (self.pos, self.size)) pos = self.pos for i in range(self.getElements() + 1): # aCp aCp = self.getuInt32(pos=pos) self.aCPs.append(aCp) print('' % (i, aCp)) pos += 4 if i < self.getElements(): # aFactoidSpls aFactoidSpls = FactoidSpls(self, self.getOffset(self.pos, i)) aFactoidSpls.dump() self.aFactoidSpls.append(aFactoidSpls) print('') print('') class Fldch(BinaryStream): """The fldch structure determines the type of the field character.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.parent = parent def dump(self): print('' % self.pos) buf = self.readuInt8() self.printAndSet("ch", buf & 0x1f) # 1..5th bits self.printAndSet("reserved", (buf & 0xe0) >> 5) # 6..8th bits print('') self.parent.pos = self.pos class Fld(BinaryStream): """The Fld structure specifies a field character.""" def __init__(self, parent, offset): BinaryStream.__init__(self, parent.bytes) self.pos = offset def dump(self): print('' % self.pos) self.fldch = Fldch(self) self.fldch.dump() self.printAndSet("grffld", self.readuInt8()) # TODO parse flt and grffldEnd print('') class PlcFld(BinaryStream, PLC): """The Plcfld structure specifies the location of fields in the document.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) PLC.__init__(self, mainStream.lcbPlcfFldMom, 2) # 2 is defined by 2.8.25 self.pos = mainStream.fcPlcfFldMom self.size = mainStream.lcbPlcfFldMom def dump(self): print('' % (self.pos, self.size)) pos = self.pos aFlds = [] for i in range(self.getElements()): # aCp value = self.getuInt32(pos=pos) print('' % (i, value)) pos += 4 # aFld aFld = Fld(self, self.getOffset(self.pos, i)) aFld.dump() # This is a separator and the previous was a start: display the field instructions. if aFld.fldch.ch == 0x14 and aFlds[-1][1].fldch.ch == 0x13: print('' % self.quoteAttr(self.mainStream.retrieveCPs(aFlds[-1][0] + 1, value))) # This is an end and the previous was a separator: display the field result. elif aFld.fldch.ch == 0x15 and aFlds[-1][1].fldch.ch == 0x14: print('' % self.quoteAttr(self.mainStream.retrieveCPs(aFlds[-1][0] + 1, value))) aFlds.append((value, aFld)) print('') print('') class PlcfBkl(BinaryStream, PLC): """The Plcfbkl structure is a PLC that contains only CPs and no additional data.""" def __init__(self, mainStream, offset, size, start): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) PLC.__init__(self, size, 0) # 0 is defined by 2.8.12 self.pos = offset self.size = size self.start = start def dump(self): print('' % (self.pos, self.size)) pos = self.pos for i in range(self.getElements()): # aCp end = self.getuInt32(pos=pos) print('' % (i, end)) start = self.start.aCP[self.start.aFBKF[i].ibkl] print('' % self.quoteAttr(self.mainStream.retrieveCPs(start, end))) pos += 4 print('') print('') class PlcPcd(BinaryStream, PLC): """The PlcPcd structure is a PLC whose data elements are Pcds (8 bytes each).""" def __init__(self, bytes, mainStream, offset, size): BinaryStream.__init__(self, bytes, mainStream=mainStream) PLC.__init__(self, size, 8) # 8 is defined by 2.8.35 self.pos = offset self.size = size self.aCp = [] self.aPcd = [] self.ranges = [] pos = self.pos for i in range(self.getElements()): # aCp start = self.getuInt32(pos=pos) end = self.getuInt32(pos=pos + 4) self.ranges.append((start, end)) self.aCp.append(start) pos += 4 # aPcd aPcd = Pcd(self.bytes, self.mainStream, self.getOffset(self.pos, i), 8) self.aPcd.append(aPcd) def dump(self): print('' % (self.pos, self.size)) for i in range(self.getElements()): start, end = self.ranges[i] print('' % (i, start, end)) self.aPcd[i].dump() print('' % self.quoteAttr(self.mainStream.retrieveCPs(start, end))) print('') print('') class Sepx(BinaryStream): """The Sepx structure specifies an array of Prl structures and the size of the array.""" def __init__(self, sed): BinaryStream.__init__(self, sed.plcfSed.mainStream.bytes) self.pos = sed.fcSepx def dump(self): print('' % self.pos) self.printAndSet("cb", self.readInt16()) pos = self.pos while (self.cb - (pos - self.pos)) > 0: prl = Prl(self, pos) prl.dump() pos += prl.getSize() print('') class Sed(BinaryStream): """The Sed structure specifies the location of the section properties.""" size = 12 # defined by 2.8.26 def __init__(self, plcfSed, offset): BinaryStream.__init__(self, plcfSed.bytes) self.pos = offset self.plcfSed = plcfSed def dump(self): print('' % (self.pos, Sed.size)) self.printAndSet("fn", self.readuInt16()) self.printAndSet("fcSepx", self.readuInt32()) if self.fcSepx != 0xffffffff: Sepx(self).dump() self.printAndSet("fnMpr", self.readuInt16()) self.printAndSet("fcMpr", self.readuInt32()) print('') class PlcfSed(BinaryStream, PLC): """The PlcfSed structure is a PLC structure where the data elements are Sed structures.""" def __init__(self, mainStream, offset, size): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) PLC.__init__(self, size, Sed.size) self.pos = offset self.size = size def dump(self): print('' % (self.pos, self.size)) pos = self.pos for i in range(self.getElements()): # aCp start = self.getuInt32(pos=pos) end = self.getuInt32(pos=pos + 4) print('' % (i, start, end)) pos += 4 # aSed aSed = Sed(self, self.getOffset(self.pos, i)) aSed.dump() print('' % self.quoteAttr(self.mainStream.retrieveCPs(start, end))) print('') print('') class Tcg(BinaryStream): """The Tcg structure specifies command-related customizations.""" def __init__(self, mainStream, offset, size): BinaryStream.__init__(self, mainStream.getTableStream().bytes) self.pos = offset self.size = size def dump(self): print('' % (self.pos, self.size)) self.printAndSet("nTcgVer", self.readuInt8()) self.printAndSet("chTerminator", self.readuInt8()) if self.chTerminator != 0x40: print('') print('') class Sty(BinaryStream): """The Sty structure specifies the type of the selection that was made.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.parent = parent def dump(self): value = self.readuInt16() styMap = { 0x0000: "styNil", 0x0001: "styChar", 0x0002: "styWord", 0x0003: "stySent", 0x0004: "styPara", 0x0005: "styLine", 0x000C: "styCol", 0x000D: "styRow", 0x000E: "styColAll", 0x000F: "styWholeTable", 0x001B: "styPrefix", } print('' % (styMap[value], hex(value))) self.parent.pos = self.pos class Selsf(BinaryStream): size = 36 # defined by 2.9.241 """The Selsf structure specifies the last selection that was made to the document.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes) self.pos = mainStream.fcWss self.size = mainStream.lcbWss self.mainStream = mainStream def dump(self): print('' % (self.pos, self.size)) buf = self.readuInt16() self.printAndSet("fRightward", self.getBit(buf, 0)) self.printAndSet("unused1", self.getBit(buf, 1)) self.printAndSet("fWithinCell", self.getBit(buf, 2)) self.printAndSet("fTableAnchor", self.getBit(buf, 3)) self.printAndSet("fTableSelNonShrink", self.getBit(buf, 4)) self.printAndSet("unused2", self.getBit(buf, 5)) self.printAndSet("fDiscontiguous", self.getBit(buf, 6)) self.printAndSet("fPrefix", self.getBit(buf, 7)) self.printAndSet("fShape", self.getBit(buf, 8)) self.printAndSet("fFrame", self.getBit(buf, 9)) self.printAndSet("fColumn", self.getBit(buf, 10)) self.printAndSet("fTable", self.getBit(buf, 11)) self.printAndSet("fGraphics", self.getBit(buf, 12)) self.printAndSet("fBlock", self.getBit(buf, 13)) self.printAndSet("unused3", self.getBit(buf, 14)) self.printAndSet("fIns", self.getBit(buf, 15)) buf = self.readuInt8() self.printAndSet("fForward", buf & 0x7f) # 1..7th bits self.printAndSet("fPrefixW2007", self.getBit(buf, 7)) self.printAndSet("fInsEnd", self.readuInt8()) self.printAndSet("cpFirst", self.readuInt32()) self.printAndSet("cpLim", self.readuInt32()) self.printAndSet("unused4", self.readuInt32()) self.printAndSet("blktblSel", self.readuInt32()) self.printAndSet("cpAnchor", self.readuInt32()) Sty(self).dump() self.printAndSet("unused5", self.readuInt16()) self.printAndSet("cpAnchorShrink", self.readuInt32()) self.printAndSet("xaTableLeft", self.readInt16()) self.printAndSet("xaTableRight", self.readInt16()) assert self.pos == self.mainStream.fcWss + Selsf.size print('') class COLORREF(BinaryStream): """The COLORREF structure specifies a color in terms of its red, green, and blue components.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.red = self.readuInt8() self.green = self.readuInt8() self.blue = self.readuInt8() self.fAuto = self.readuInt8() parent.pos = self.pos def dump(self, name): print('<%s type="COLORREF">' % name) self.printAndSet("red", self.red) self.printAndSet("green", self.green) self.printAndSet("blue", self.blue) self.printAndSet("fAuto", self.fAuto) print('' % name) class BRC(BinaryStream): """The Brc structure specifies a border.""" def __init__(self, parent, name="brc"): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.parent = parent self.name = name self.posOrig = self.pos self.cv = COLORREF(self) self.dptLineWidth = self.readuInt8() self.brcType = self.readuInt8() buf = self.readuInt16() self.dptSpace = buf & 0x1f # 1..5th bits self.fShadow = self.getBit(buf, 5) self.fFrame = self.getBit(buf, 6) self.fReserved = (buf & 0xff80) >> 7 # 8..16th bits def dump(self): print('<%s type="BRC" offset="%d">' % (self.name, self.posOrig)) self.cv.dump("cv") self.printAndSet("dptLineWidth", self.dptLineWidth) self.printAndSet("brcType", self.brcType, dict=BrcType) self.printAndSet("dptSpace", self.dptSpace) self.printAndSet("fShadow", self.fShadow) self.printAndSet("fFrame", self.fFrame) self.printAndSet("fReserved", self.fReserved) print('' % self.name) self.parent.pos = self.pos class PChgTabsDel(BinaryStream): """The PChgTabsDel structure specifies the locations at which custom tab stops are ignored.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = parent.pos def dump(self): print('' % self.pos) self.printAndSet("cTabs", self.readuInt8()) for i in range(self.cTabs): print('' % (i, self.readInt16())) print('') self.parent.pos = self.pos class PChgTabsDelClose(BinaryStream): """The PChgTabsDelClose structure specifies the locations at which custom tab stops are ignored.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = parent.pos def dump(self): print('' % self.pos) self.printAndSet("cTabs", self.readuInt8()) for i in range(self.cTabs): print('' % (i, self.readInt16())) for i in range(self.cTabs): print('' % (i, self.readInt16())) print('') self.parent.pos = self.pos class PChgTabsAdd(BinaryStream): """The PChgTabsAdd structure specifies the locations and properties of custom tab stops.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = parent.pos def dump(self): print('' % self.pos) self.printAndSet("cTabs", self.readuInt8()) for i in range(self.cTabs): print('' % (i, self.readInt16())) for i in range(self.cTabs): print('' % (i, self.readuInt8())) print('') self.parent.pos = self.pos class LSPD(BinaryStream): """Specifies the spacing between lines in a paragraph.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos def dump(self): print('' % self.pos) self.printAndSet("dyaLine", self.readuInt16()) self.printAndSet("fMultLinespace", self.readuInt16()) print('') class PChgTabsPapxOperand(BinaryStream): """The PChgTabsPapxOperand structure is used by sprmPChgTabsPapx to specify custom tab stops to be added or ignored.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos def dump(self): print('' % self.pos) self.printAndSet("cb", self.readuInt8()) PChgTabsDel(self).dump() PChgTabsAdd(self).dump() print('') class PChgTabsOperand(BinaryStream): """The PChgTabsOperand structure is used by sprmPChgTabs to specify a list of custom tab stops to add and another list of custom tab stops to ignore.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos def dump(self): print('' % self.pos) self.printAndSet("cb", self.readuInt8()) PChgTabsDelClose(self).dump() PChgTabsAdd(self).dump() print('') # The Ico structure specifies an entry in the color palette that is listed in the following table. Ico = { 0x00: "Red: 0x00, Green: 0x00, Blue: 0x00, fAuto: 0xFF", 0x01: "Red: 0x00, Green: 0x00, Blue: 0x00, fAuto: 0x00", 0x02: "Red: 0x00, Green: 0x00, Blue: 0xFF, fAuto: 0x00", 0x03: "Red: 0x00, Green: 0xFF, Blue: 0xFF, fAuto: 0x00", 0x04: "Red: 0x00, Green: 0xFF, Blue: 0x00, fAuto: 0x00", 0x05: "Red: 0xFF, Green: 0x00, Blue: 0xFF, fAuto: 0x00", 0x06: "Red: 0xFF, Green: 0x00, Blue: 0x00, fAuto: 0x00", 0x07: "Red: 0xFF, Green: 0xFF, Blue: 0x00, fAuto: 0x00", 0x08: "Red: 0xFF, Green: 0xFF, Blue: 0xFF, fAuto: 0x00", 0x09: "Red: 0x00, Green: 0x00, Blue: 0x80, fAuto: 0x00", 0x0A: "Red: 0x00, Green: 0x80, Blue: 0x80, fAuto: 0x00", 0x0B: "Red: 0x00, Green: 0x80, Blue: 0x00, fAuto: 0x00", 0x0C: "Red: 0x80, Green: 0x00, Blue: 0x80, fAuto: 0x00", 0x0D: "Red: 0x80, Green: 0x00, Blue: 0x80, fAuto: 0x00", 0x0E: "Red: 0x80, Green: 0x80, Blue: 0x00, fAuto: 0x00", 0x0F: "Red: 0x80, Green: 0x80, Blue: 0x80, fAuto: 0x00", 0x10: "Red: 0xC0, Green: 0xC0, Blue: 0xC0, fAuto: 0x00", } # The Ipat enumeration is an index to a shading pattern. Ipat = { 0x0000: "ipatAuto", 0x0001: "ipatSolid", 0x0002: "ipatPct5", 0x0003: "ipatPct10", 0x0004: "ipatPct20", 0x0005: "ipatPct25", 0x0006: "ipatPct30", 0x0007: "ipatPct40", 0x0008: "ipatPct50", 0x0009: "ipatPct60", 0x000A: "ipatPct70", 0x000B: "ipatPct75", 0x000C: "ipatPct80", 0x000D: "ipatPct90", 0x000E: "ipatDkHorizontal", 0x000F: "ipatDkVertical", 0x0010: "ipatDkForeDiag", 0x0011: "ipatDkBackDiag", 0x0012: "ipatDkCross", 0x0013: "ipatDkDiagCross", 0x0014: "ipatHorizontal", 0x0015: "ipatVertical", 0x0016: "ipatForeDiag", 0x0017: "ipatBackDiag", 0x0018: "ipatCross", 0x0019: "ipatDiagCross", 0x0023: "ipatPctNew2", 0x0024: "ipatPctNew7", 0x0025: "ipatPctNew12", 0x0026: "ipatPctNew15", 0x0027: "ipatPctNew17", 0x0028: "ipatPctNew22", 0x0029: "ipatPctNew27", 0x002A: "ipatPctNew32", 0x002B: "ipatPctNew35", 0x002C: "ipatPctNew37", 0x002D: "ipatPctNew42", 0x002E: "ipatPctNew45", 0x002F: "ipatPctNew47", 0x0030: "ipatPctNew52", 0x0031: "ipatPctNew55", 0x0032: "ipatPctNew57", 0x0033: "ipatPctNew62", 0x0034: "ipatPctNew65", 0x0035: "ipatPctNew67", 0x0036: "ipatPctNew72", 0x0037: "ipatPctNew77", 0x0038: "ipatPctNew82", 0x0039: "ipatPctNew85", 0x003A: "ipatPctNew87", 0x003B: "ipatPctNew92", 0x003C: "ipatPctNew95", 0x003D: "ipatPctNew97", 0xFFFF: "ipatNil" } class Shd80(BinaryStream): """The Shd80 structure specifies the colors and pattern that are used for background shading.""" size = 2 # in bytes, see 2.9.245 def __init__(self, parent, index): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.parent = parent self.index = index def dump(self): print('' % (self.pos, self.index)) buf = self.readuInt16() self.printAndSet("icoFore", buf & 0x001f, dict=Ico) # 1..5th bits self.printAndSet("icoBack", (buf & 0x03e0) >> 5, dict=Ico) # 6..10th bits self.printAndSet("ipat", (buf & 0xfc00) >> 10, dict=Ipat) # 11.16th bits print('') self.parent.pos = self.pos class DefTableShd80Operand(BinaryStream): """The DefTableSdh800Operand structure is an operand that is used by several Table Sprms to specify each style of background shading that is applied to each of the cells in a single row.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos def dump(self): print('' % self.pos) self.printAndSet("cb", self.readuInt8()) for i in range(round(self.cb / Shd80.size)): Shd80(self, i).dump() print('') class CMajorityOperand(BinaryStream): """The CMajorityOperand structure is used by sprmCMajority to specify which character properties of the text to reset to match that of the underlying paragraph style.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos def dump(self): print('' % self.pos) self.printAndSet("cb", self.readuInt8()) pos = 0 print('' % (self.pos, self.cb)) while self.cb - pos > 0: prl = Prl(self, self.pos + pos) prl.dump() pos += prl.getSize() print('') print('') class BrcCvOperand(BinaryStream): """The BrcCvOperand structure specifies border colors.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos def dump(self): print('' % self.pos) self.printAndSet("cb", self.readuInt8()) pos = self.pos print('' % (self.pos, self.cb)) while self.pos - pos < self.cb: COLORREF(self).dump("cv") print('') print('') # The PgbApplyTo enumeration is used to specify the pages to which a page border applies. PgbApplyTo = { 0x0: "pgbAllPages", 0x1: "pgbFirstPage", 0x2: "pgbAllButFirst" } # The PgbOffsetFrom enumeration is used to specify the location from which the offset of a page # border is measured. PgbOffsetFrom = { 0x0: "pgbFromText", 0x1: "pgbFromEdge" } # The PgbPageDepth enumeration is used to specify the "depth" of a page border in relation to other # page elements. PgbPageDepth = { 0x0: "pgbAtFront", 0x1: "pgbAtBack", } class SPgbPropOperand(BinaryStream): """The SPgbPropOperand structure is the operand to sprmSPgbProp. It specifies the properties of a page border.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos def dump(self): print('' % self.pos) buf = self.readuInt8() self.printAndSet("pgbApplyTo", buf & 0x7, dict=PgbApplyTo) # 1..3rd bits self.printAndSet("pgbPageDepth", (buf & 0x18) >> 3, dict=PgbPageDepth) # 4..5th bits self.printAndSet("pgbOffsetFrom", (buf & 0xe0) >> 5, dict=PgbOffsetFrom) # 6..8th bits self.printAndSet("reserved", self.readuInt8()) print('') class MFPF(BinaryStream): """The MFPF structure specifies the type of picture data that is stored.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.parent = parent def dump(self): mmDict = { 0x0064: "MM_SHAPE", 0x0066: "MM_SHAPEFILE", } print('' % self.pos) self.printAndSet("mm", self.readInt16(), dict=mmDict, default="todo") self.printAndSet("xExt", self.readuInt16()) self.printAndSet("yExt", self.readuInt16()) self.printAndSet("swHMF", self.readuInt16()) self.parent.pos = self.pos print('') class PICF_Shape(BinaryStream): """The PICF_Shape structure specifies additional header information for pictures of type MM_SHAPE or MM_SHAPEFILE.""" def __init__(self, parent, name): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.parent = parent self.name = name def dump(self): print('<%s type="PICF_Shape" offset="%d">' % (self.name, self.pos)) self.printAndSet("grf", self.readuInt32()) self.printAndSet("padding1", self.readuInt32()) self.printAndSet("mmpm", self.readuInt16()) self.printAndSet("padding2", self.readuInt32()) self.parent.pos = self.pos print('' % self.name) # BrcType is an unsigned integer that specifies the type of border. BrcType = { 0x00: "none", 0x01: "single", 0x03: "double", 0x05: "A thin single solid line.", 0x06: "dotted", 0x07: "dashed", 0x08: "dotDash", 0x09: "dotDotDash", 0x0A: "triple", 0x0B: "thinThickSmallGap", 0x0C: "thickThinSmallGap", 0x0D: "thinThickThinSmallGap", 0x0E: "thinThickMediumGap", 0x0F: "thickThinMediumGap", 0x10: "thinThickThinMediumGap", 0x11: "thinThickLargeGap", 0x12: "thickThinLargeGap", 0x13: "thinThickThinLargeGap", 0x14: "wave", 0x15: "doubleWave", 0x16: "dashSmallGap", 0x17: "dashDotStroked", 0x18: "threeDEmboss", 0x19: "threeDEngrave", 0x1A: "outset", 0x1B: "inset", 0x40: "apples", 0x41: "archedScallops", 0x42: "babyPacifier", 0x43: "babyRattle", 0x44: "balloons3Colors", 0x45: "balloonsHotAir", 0x46: "basicBlackDashes", 0x47: "basicBlackDots", 0x48: "basicBlackSquares", 0x49: "basicThinLines", 0x4A: "basicWhiteDashes", 0x4B: "basicWhiteDots", 0x4C: "basicWhiteSquares", 0x4D: "basicWideInline", 0x4E: "basicWideMidline", 0x4F: "basicWideOutline", 0x50: "bats", 0x51: "birds", 0x52: "birdsFlight", 0x53: "cabins", 0x54: "cakeSlice", 0x55: "candyCorn", 0x56: "celticKnotwork", 0x57: "certificateBanner", 0x58: "chainLink", 0x59: "champagneBottle", 0x5A: "checkedBarBlack", 0x5B: "checkedBarColor", 0x5C: "checkered", 0x5D: "christmasTree", 0x5E: "circlesLines", 0x5F: "circlesRectangles", 0x60: "classicalWave", 0x61: "clocks", 0x62: "compass", 0x63: "confetti", 0x64: "confettiGrays", 0x65: "confettiOutline", 0x66: "confettiStreamers", 0x67: "confettiWhite", 0x68: "cornerTriangles", 0x69: "couponCutoutDashes", 0x6A: "couponCutoutDots", 0x6B: "crazyMaze", 0x6C: "creaturesButterfly", 0x6D: "creaturesFish", 0x6E: "creaturesInsects", 0x6F: "creaturesLadyBug", 0x70: "crossStitch", 0x71: "cup", 0x72: "decoArch", 0x73: "decoArchColor", 0x74: "decoBlocks", 0x75: "diamondsGray", 0x76: "doubleD", 0x77: "doubleDiamonds", 0x78: "earth1", 0x79: "earth2", 0x7A: "eclipsingSquares1", 0x7B: "eclipsingSquares2", 0x7C: "eggsBlack", 0x7D: "fans", 0x7E: "film", 0x7F: "firecrackers", 0x80: "flowersBlockPrint", 0x81: "flowersDaisies", 0x82: "flowersModern1", 0x83: "flowersModern2", 0x84: "flowersPansy", 0x85: "flowersRedRose", 0x86: "flowersRoses", 0x87: "flowersTeacup", 0x88: "flowersTiny", 0x89: "gems", 0x8A: "gingerbreadMan", 0x8B: "gradient", 0x8C: "handmade1", 0x8D: "handmade2", 0x8E: "heartBalloon", 0x8F: "heartGray", 0x90: "hearts", 0x91: "heebieJeebies", 0x92: "holly", 0x93: "houseFunky", 0x94: "hypnotic", 0x95: "iceCreamCones", 0x96: "lightBulb", 0x97: "lightning1", 0x98: "lightning2", 0x99: "mapPins", 0x9A: "mapleLeaf", 0x9B: "mapleMuffins", 0x9C: "marquee", 0x9D: "marqueeToothed", 0x9E: "moons", 0x9F: "mosaic", 0xA0: "musicNotes", 0xA1: "northwest", 0xA2: "ovals", 0xA3: "packages", 0xA4: "palmsBlack", 0xA5: "palmsColor", 0xA6: "paperClips", 0xA7: "papyrus", 0xA8: "partyFavor", 0xA9: "partyGlass", 0xAA: "pencils", 0xAB: "people", 0xAC: "peopleWaving", 0xAD: "peopleHats", 0xAE: "poinsettias", 0xAF: "postageStamp", 0xB0: "pumpkin1", 0xB1: "pushPinNote2", 0xB2: "pushPinNote1", 0xB3: "pyramids", 0xB4: "pyramidsAbove", 0xB5: "quadrants", 0xB6: "rings", 0xB7: "safari", 0xB8: "sawtooth", 0xB9: "sawtoothGray", 0xBA: "scaredCat", 0xBB: "seattle", 0xBC: "shadowedSquares", 0xBD: "sharksTeeth", 0xBE: "shorebirdTracks", 0xBF: "skyrocket", 0xC0: "snowflakeFancy", 0xC1: "snowflakes", 0xC2: "sombrero", 0xC3: "southwest", 0xC4: "stars", 0xC5: "starsTop", 0xC6: "stars3d", 0xC7: "starsBlack", 0xC8: "starsShadowed", 0xC9: "sun", 0xCA: "swirligig", 0xCB: "tornPaper", 0xCC: "tornPaperBlack", 0xCD: "trees", 0xCE: "triangleParty", 0xCF: "triangles", 0xD0: "tribal1", 0xD1: "tribal2", 0xD2: "tribal3", 0xD3: "tribal4", 0xD4: "tribal5", 0xD5: "tribal6", 0xD6: "twistedLines1", 0xD7: "twistedLines2", 0xD8: "vine", 0xD9: "waveline", 0xDA: "weavingAngles", 0xDB: "weavingBraid", 0xDC: "weavingRibbon", 0xDD: "weavingStrips", 0xDE: "whiteFlowers", 0xDF: "woodwork", 0xE0: "xIllusions", 0xE1: "zanyTriangles", 0xE2: "zigZag", 0xE3: "zigZagStitch" } class Brc80(BinaryStream): """The Brc80 structure describes a border.""" def __init__(self, parent, name): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.parent = parent self.name = name def dump(self): buf = self.readuInt32() print('<%s type="Brc80" offset="%d">' % (self.name, self.pos)) self.printAndSet("dptLineWidth", buf & 0x000000ff) # 1..8th bits self.printAndSet("brcType", (buf & 0x0000ff00) >> 8, dict=BrcType) # 9..16th bits self.printAndSet("ico", (buf & 0x00ff0000) >> 16, dict=Ico) # 17..24th bits self.printAndSet("dptSpace", (buf & 0x1f000000) >> 24) # 25..29th bits self.printAndSet("fShadow", self.getBit(buf, 29)) self.printAndSet("fFrame", self.getBit(buf, 30)) self.printAndSet("reserved", self.getBit(buf, 31)) print('' % self.name) self.parent.pos = self.pos class Brc80MayBeNil(BinaryStream): """The Brc80MayBeNil structure is a Brc80 structure. When all bits are set, this structure specifies that the region in question has no border.""" def __init__(self, parent, name): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.parent = parent self.name = name def dump(self): buf = self.getuInt32() if buf == 0xFFFFFFFF: print('<%s type="Brc80MayBeNil" offset="%d" value="%s"/>' % (self.name, self.pos, hex(buf))) self.pos += 4 else: print('<%s type="Brc80MayBeNil" offset="%d">' % (self.name, self.pos)) Brc80(self, self.name).dump() print('' % self.name) self.parent.pos = self.pos class PICMID(BinaryStream): """The PICMID structure specifies the size and border information for a picture.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.parent = parent def dump(self): print('' % self.pos) self.printAndSet("dxaGoal", self.readuInt16()) self.printAndSet("dyaGoal", self.readuInt16()) self.printAndSet("mx", self.readuInt16()) self.printAndSet("my", self.readuInt16()) self.printAndSet("dxaReserved1", self.readuInt16()) self.printAndSet("dyaReserved1", self.readuInt16()) self.printAndSet("dxaReserved2", self.readuInt16()) self.printAndSet("dyaReserved2", self.readuInt16()) self.printAndSet("fReserved", self.readuInt8()) self.printAndSet("bpp", self.readuInt8()) Brc80(self, "brcTop80").dump() Brc80(self, "brcLeft80").dump() Brc80(self, "brcBottom80").dump() Brc80(self, "brcRight80").dump() self.printAndSet("dxaReserved3", self.readuInt16()) self.printAndSet("dyaReserved3", self.readuInt16()) self.parent.pos = self.pos print('') class PICF(BinaryStream): """The PICF structure specifies the type of a picture, as well as the size of the picture and information about its border.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.parent = parent def dump(self): print('' % self.pos) posOrig = self.pos self.printAndSet("lcb", self.readInt32()) self.printAndSet("cbHeader", self.readInt16()) assert self.cbHeader == 0x44 self.mfpf = MFPF(self) self.mfpf.dump() if self.mfpf.mm == 0x0064: # MM_SHAPEFILE PICF_Shape(self, "innerHeader").dump() PICMID(self).dump() self.printAndSet("cProps", self.readuInt16()) else: self.pos = posOrig + self.cbHeader self.parent.pos = self.pos print('') IType = { 0: "iTypeText", 1: "iTypeChck", 2: "iTypeDrop" } ITypeTxt = { 0: "iTypeTxtReg", 1: "iTypeTxtNum", 2: "iTypeTxtDate", 3: "iTypeTxtCurDate", 4: "iTypeTxtCurTime", 5: "iTypeTxtCalc" } class FFDataBits(BinaryStream): """The FFDataBits structure specifies the type and properties for a form field that is specified by a FFData.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.parent = parent def dump(self): print('') buf = self.readuInt8() self.printAndSet("iType", buf & 0x0003, dict=IType) # 1..2nd bits self.printAndSet("iRes", (buf & 0x007c) >> 2) # 3..7th bits self.printAndSet("fOwnHelp", self.getBit(buf, 8)) buf = self.readuInt8() self.printAndSet("fOwnStat", self.getBit(buf, 1)) self.printAndSet("fProt", self.getBit(buf, 2)) self.printAndSet("iSize", self.getBit(buf, 3)) self.printAndSet("iTypeTxt", (buf & 0x0038) >> 3, dict=ITypeTxt) # 4..6th bits self.printAndSet("fRecalc", self.getBit(buf, 7)) self.printAndSet("fHasListBox", self.getBit(buf, 8)) print('') self.parent.pos = self.pos class FFData(BinaryStream): """The FFData structure specifies form field data for a text box, check box, or drop-down list box. (Page 348 of [MS-DOC] spec.)""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.parent = parent def dump(self): print('') self.printAndSet("version", self.readuInt32()) self.bits = FFDataBits(self) self.bits.dump() self.printAndSet("cch", self.readuInt16()) self.printAndSet("hps", self.readuInt16()) xstzName = Xstz(self, "xstzName") xstzName.dump() self.pos = xstzName.pos xstzTextDef = Xstz(self, "xstzTextDef") xstzTextDef.dump() self.pos = xstzTextDef.pos if self.bits.iType == 1 or self.bits.iType == 2: # iTypeChck or iTypeDrop self.printAndSet("wDef", self.readuInt16()) xstzTextFormat = Xstz(self, "xstzTextFormat") xstzTextFormat.dump() self.pos = xstzTextFormat.pos xstzHelpText = Xstz(self, "xstzHelpText") xstzHelpText.dump() self.pos = xstzHelpText.pos xstzStatText = Xstz(self, "xstzStatText") xstzStatText.dump() self.pos = xstzStatText.pos xstzEntryMcr = Xstz(self, "xstzEntryMcr") xstzEntryMcr.dump() self.pos = xstzEntryMcr.pos xstzExitMcr = Xstz(self, "xstzExitMcr") xstzExitMcr.dump() self.pos = xstzExitMcr.pos if self.bits.iType == 2: # iTypeDrop print('') print('') class NilPICFAndBinData(BinaryStream): """The NilPICFAndBinData structure that holds header information and binary data for a hyperlink, form field, or add-in field. The NilPICFAndBinData structure MUST be stored in the Data Stream.""" def __init__(self, parent): dataStream = parent.mainStream.doc.getDirectoryStreamByName(b"Data") BinaryStream.__init__(self, dataStream.bytes) self.pos = parent.operand self.parent = parent def dump(self): print('') # self -> sprm -> prl -> chpx -> chpxFkp chpxFkp = self.parent.parent.parent.parent self.printAndSet("lcb", self.readInt32()) self.printAndSet("cbHeader", self.readInt16()) self.printAndSet("ignored0", self.readInt32()) self.printAndSet("ignored1", self.readInt32()) self.printAndSet("ignored2", self.readInt32()) self.printAndSet("ignored3", self.readInt32()) self.printAndSet("ignored4", self.readInt32()) self.printAndSet("ignored5", self.readInt32()) self.printAndSet("ignored6", self.readInt32()) self.printAndSet("ignored7", self.readInt32()) self.printAndSet("ignored8", self.readInt32()) self.printAndSet("ignored9", self.readInt32()) self.printAndSet("ignored10", self.readInt32()) self.printAndSet("ignored11", self.readInt32()) self.printAndSet("ignored12", self.readInt32()) self.printAndSet("ignored13", self.readInt32()) self.printAndSet("ignored14", self.readInt32()) self.printAndSet("ignored15", self.readInt16()) if len(chpxFkp.transformeds) > 1: fieldType = chpxFkp.transformeds[-2] else: fieldType = ")-MISSING-(" if fieldType == " FORMTEXT ": FFData(self).dump() else: print('' % fieldType) print('') class PICFAndOfficeArtData(BinaryStream): """The PICFAndOfficeArtData structure specifies header information and binary data for a picture.""" def __init__(self, parent): dataStream = parent.mainStream.doc.getDirectoryStreamByName(b"Data") BinaryStream.__init__(self, dataStream.bytes) self.pos = parent.operand self.parent = parent def dump(self): print('') found = False for prl in self.parent.parent.parent.prls: if prl.sprm.sprm in (0x0806, 0x080a): # sprmCFData, sprmCFOle2 found = True break if not found: pos = self.pos picf = PICF(self) picf.dump() assert self.pos == pos + 68 if picf.mfpf.mm == 0x0066: # MM_SHAPEFILE print('') elif picf.mfpf.mm == 0x0064: # MM_SHAPE remaining = picf.lcb - (self.pos - pos) msodraw.InlineSpContainer(self, remaining).dumpXml(self, getWordModel(self.parent.mainStream)) else: print('' % picf.mfpf.mm) else: print('') print('') # The TextFlow enumeration specifies the rotation settings for a block of text and for the individual # East Asian characters in each line of the block. TextFlow = { 0x0000: "grpfTFlrtb", 0x0001: "grpfTFtbrl", 0x0003: "grpfTFbtlr", 0x0004: "grpfTFlrtbv", 0x0005: "grpfTFtbrlv" } # The VerticalMergeFlag enumeration provides a 2-bit value that specifies whether a table cell is # merged with the cells above or below it. VerticalMergeFlag = { 0x00: "fvmClear", 0x01: "fvmMerge", 0x03: "fvmRestart" } # The VerticalAlign enumeration specifies the vertical alignment of content within table cells. VerticalAlign = { 0x00: "vaTop", 0x01: "vaCenter", 0x02: "vaBottom", } # The Fts enumeration specifies how the preferred width for a table, table indent, table cell, cell # margin, or cell spacing is defined. Fts = { 0x00: "ftsNil", 0x01: "ftsAuto", 0x02: "ftsPercent", 0x03: "ftsDxa", 0x13: "ftsDxaSys" } class SHD(BinaryStream): """The Shd structure specifies the colors and pattern that are used for background shading.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = parent.pos def dump(self): print('' % self.pos) COLORREF(self).dump("cvFore") COLORREF(self).dump("cvBack") self.printAndSet("ipat", self.readuInt16(), dict=Ipat) print('') class TCGRF(BinaryStream): """A TCGRF structure specifies the text layout and cell merge properties for a single cell in a table.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = parent.pos def dump(self): print('' % self.pos) buf = self.readuInt16() self.printAndSet("horzMerge", buf & 0x0003) # 1..2nd bits self.printAndSet("textFlow", (buf & 0x001c) >> 2, dict=TextFlow, default="todo") # 3..6th bits self.printAndSet("vertMerge", (buf & 0x0060) >> 6, dict=VerticalMergeFlag) # 7..8th bits self.printAndSet("vertAlign", (buf & 0x0180) >> 8, dict=VerticalAlign) # 9..10th bits self.printAndSet("ftsWidth", (buf & 0x0e00) >> 10, dict=Fts) # 11..12th bits self.printAndSet("fFitText", self.getBit(buf, 12)) self.printAndSet("fNoWrap", self.getBit(buf, 13)) self.printAndSet("fHideMark", self.getBit(buf, 14)) self.printAndSet("fUnused", self.getBit(buf, 15)) print('') self.parent.pos = self.pos class TC80(BinaryStream): """The TC80 structure specifies the border and other formatting for a single cell in a table.""" def __init__(self, parent, index): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = parent.pos self.index = index def dump(self): print('' % self.index) TCGRF(self).dump() self.printAndSet("wWidth", self.readuInt16(), hexdump=False) Brc80MayBeNil(self, "brcTop").dump() Brc80MayBeNil(self, "brcLeft").dump() Brc80MayBeNil(self, "brcBottom").dump() Brc80MayBeNil(self, "brcRight").dump() print('') self.parent.pos = self.pos class TDefTableOperand(BinaryStream): """The TDefTableOperand structure is the operand that is used by the sprmTDefTable value. It specifies the initial layout of the columns in the current table row.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos def dump(self): print('') self.printAndSet("cb", self.readuInt16()) size = self.pos + self.cb - 1 self.printAndSet("NumberOfColumns", self.readuInt8()) for i in range(self.NumberOfColumns + 1): print('' % (i, self.readInt16())) i = 0 while self.pos < size: TC80(self, i).dump() i += 1 print('') class TableBordersOperand(BinaryStream): """The TableBordersOperand structure specifies a set of borders for a table row.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos def dump(self): print('') self.printAndSet("cb", self.readuInt8()) posOrig = self.pos BRC(self, "brcTop").dump() BRC(self, "brcLeft").dump() BRC(self, "brcBottom").dump() BRC(self, "brcRight").dump() BRC(self, "brcHorizontalInside").dump() BRC(self, "brcVerticalInside").dump() assert self.pos == posOrig + 0x30 print('') class TableBordersOperand80(BinaryStream): """The TableBordersOperand80 structure is an operand that specifies the borders which are applied to a row of table cells.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos def dump(self): print('') self.printAndSet("cb", self.readuInt8()) posOrig = self.pos Brc80MayBeNil(self, "brcTop").dump() Brc80MayBeNil(self, "brcLeft").dump() Brc80MayBeNil(self, "brcBottom").dump() Brc80MayBeNil(self, "brcRight").dump() Brc80MayBeNil(self, "brcHorizontalInside").dump() Brc80MayBeNil(self, "brcVerticalInside").dump() assert self.pos == posOrig + 0x18 print('') class SHDOperand(BinaryStream): """The SDHOperand structure is an operand that is used by several Sprm structures to specify the background shading to be applied.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos def dump(self): print('') self.printAndSet("cb", self.readuInt8()) SHD(self).dump() print('') class BrcOperand(BinaryStream): """The BrcOperand structure is the operand to several SPRMs that control borders.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.posOrig = self.pos self.cb = self.readuInt8() self.brc = BRC(self) def dump(self): print('' % self.posOrig) self.brc.dump() print('') class Sprm(BinaryStream): """The Sprm structure specifies a modification to a property of a character, paragraph, table, or section.""" def __init__(self, parent, mainStream=None, transformed=None): BinaryStream.__init__(self, parent.bytes, mainStream=mainStream) self.parent = parent self.transformed = transformed self.pos = parent.pos self.operandSizeMap = { 0: 1, 1: 1, 2: 2, 3: 4, 4: 2, 5: 2, 7: 3, } self.sprm = self.readuInt16() self.ispmd = (self.sprm & 0x1ff) # 1-9th bits self.fSpec = (self.sprm & 0x200) >> 9 # 10th bit self.sgc = (self.sprm & 0x1c00) >> 10 # 11-13th bits self.spra = (self.sprm & 0xe000) >> 13 # 14-16th bits self.ct = False # If it's a complex type, it can't be dumped as a simple string. self.operand = "todo" if self.getOperandSize() == 1: self.operand = self.getuInt8() elif self.getOperandSize() == 2: self.operand = self.getuInt16() if self.sprm == 0x522f: self.ct = SPgbPropOperand(self) elif self.getOperandSize() == 3: self.operand = self.getuInt24() elif self.getOperandSize() == 4: self.operand = self.getuInt32() if self.sprm == 0x6a03 and transformed == r"\x01": # sprmCPicLocation # Can't decide right now, depends on if there will be an sprmCFData later or not. self.ct = True elif self.sprm == 0x6646: # sprmPHugePapx dataStream = mainStream.doc.getDirectoryStreamByName(b"Data") dataStream.pos = self.operand self.ct = PrcData(dataStream) elif self.sprm == 0x6412: self.ct = LSPD(self) elif self.getOperandSize() == 7: self.operand = self.getuInt64() & 0x0fffffff elif self.getOperandSize() == 9: # top, left, bottom and right page / paragraph borders if self.sprm in (0xd234, 0xd235, 0xd236, 0xd237, 0xc64e, 0xc64f, 0xc650, 0xc651): self.ct = BrcOperand(self) elif self.sprm == 0xc60d: self.ct = PChgTabsPapxOperand(self) elif self.sprm == 0xc615: self.ct = PChgTabsOperand(self) elif self.sprm == 0xd609: self.ct = DefTableShd80Operand(self) elif self.sprm == 0xca47: self.ct = CMajorityOperand(self) elif self.sprm in (0xD61A, 0xD61B, 0xD61C, 0xD61D): self.ct = BrcCvOperand(self) else: print('' % hex(self.sprm)) else: if self.sprm == 0xd608: self.ct = TDefTableOperand(self) elif self.sprm == 0xca71: self.ct = SHDOperand(self) elif self.sprm == 0xd613: self.ct = TableBordersOperand(self) elif self.sprm == 0xd605: self.ct = TableBordersOperand80(self) elif self.sprm == 0xc60d: self.ct = PChgTabsPapxOperand(self) else: print('' % (self.getOperandSize(), hex(self.sprm))) def dump(self): sgcmap = { 1: 'paragraph', 2: 'character', 3: 'picture', 4: 'section', 5: 'table' } nameMap = { 1: docsprm.parMap, 2: docsprm.chrMap, 3: docsprm.picMap, 4: docsprm.secMap, 5: docsprm.tblMap, } attrs = [] close = False attrs.append('value="%s"' % hex(self.sprm)) attrs.append('ispmd="%s"' % hex(self.ispmd)) attrs.append('fSpec="%s"' % hex(self.fSpec)) if self.sgc in sgcmap: attrs.append('sgc="%s"' % sgcmap[self.sgc]) attrs.append('spra="%s"' % self.spra) if self.sgc in nameMap and self.sprm in nameMap[self.sgc]: attrs.append('name="%s"' % nameMap[self.sgc][self.sprm]) attrs.append('operandSize="%s"' % self.getOperandSize()) if not self.ct: close = True if self.operand == "todo": attrs.append('operand=""') else: attrs.append('operand="%s"' % hex(self.operand)) print('' % (" ".join(attrs), {True: "/", False: ""}[close])) if self.ct: if type(self.ct) == bool: if self.sprm == 0x6a03 and self.transformed == r"\x01": haveCFData = False for prl in self.parent.parent.prls: if prl.sprm.sprm == 0x0806: # sprmCFData haveCFData = True break if haveCFData: self.ct = NilPICFAndBinData(self) else: self.ct = PICFAndOfficeArtData(self) self.ct.dump() print('') def getOperandSize(self): if self.spra == 6: # variable if self.sprm not in [0xD608, 0xC615]: # sprmTDefTable, sprmPChgTabs # these structures are prefixed with their size return self.getuInt8() + 1 elif self.sprm == 0xD608: return self.getuInt16() + 1 elif self.sprm == 0xC615: cb = self.getuInt8() if cb < 255: return cb + 1 else: raise Exception("PChgTabsOperand: cb is 255") raise Exception("No idea what is the size of SPRM %s" % hex(self.sprm)) return self.operandSizeMap[self.spra] class Prl(BinaryStream): """The Prl structure is a Sprm that is followed by an operand.""" def __init__(self, parent, offset, mainStream=None, transformed=None, index=None): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = offset self.posOrig = self.pos self.sprm = Sprm(self, mainStream, transformed) self.pos += 2 self.index = index def dump(self): indexstr = "" if self.index is not None: indexstr = ' index="%d"' % self.index print('' % (self.posOrig, indexstr)) self.sprm.dump() print('') def getSize(self): return 2 + self.sprm.getOperandSize() class GrpPrlAndIstd(BinaryStream): """The GrpPrlAndIstd structure specifies the style and properties that are applied to a paragraph, a table row, or a table cell.""" def __init__(self, bytes, offset, size, mainStream=None): BinaryStream.__init__(self, bytes, mainStream=mainStream) self.pos = offset self.size = size def dump(self): print('' % (self.pos, self.size)) pos = self.pos self.printAndSet("istd", self.getuInt16()) pos += 2 while (self.size - (pos - self.pos)) > 0: prl = Prl(self, pos, mainStream=self.mainStream) prl.dump() pos += prl.getSize() print('') class Chpx(BinaryStream): """The Chpx structure specifies a set of properties for text.""" def __init__(self, parent, mainStream, offset, transformed=None): BinaryStream.__init__(self, parent.bytes, mainStream=mainStream) self.parent = parent self.pos = offset self.transformed = transformed self.cb = self.readuInt8() pos = self.pos index = 0 self.prls = [] while (self.cb - (pos - self.pos)) > 0: prl = Prl(self, pos, self.mainStream, self.transformed, index) self.prls.append(prl) pos += prl.getSize() index += 1 def dump(self): print('' % self.pos) self.printAndSet("cb", self.cb) for prl in self.prls: prl.dump() print('') class PapxInFkp(BinaryStream): """The PapxInFkp structure specifies a set of text properties.""" def __init__(self, bytes, mainStream, offset): BinaryStream.__init__(self, bytes, mainStream=mainStream) self.pos = offset def dump(self): print('' % self.pos) self.printAndSet("cb", self.readuInt8()) if self.cb == 0: self.printAndSet("cb_", self.readuInt8()) grpPrlAndIstd = GrpPrlAndIstd(self.bytes, self.pos, 2 * self.cb_, mainStream=self.mainStream) else: grpPrlAndIstd = GrpPrlAndIstd(self.bytes, self.pos, 2 * self.cb - 1, mainStream=self.mainStream) grpPrlAndIstd.dump() print('') class BxPap(BinaryStream): """The BxPap structure specifies the offset of a PapxInFkp in PapxFkp.""" size = 13 # in bytes, see 2.9.23 def __init__(self, bytes, mainStream, offset, parentoffset): BinaryStream.__init__(self, bytes, mainStream=mainStream) self.pos = offset self.parentpos = parentoffset def dump(self): print('' % (self.pos, self.size)) self.printAndSet("bOffset", self.readuInt8()) papxInFkp = PapxInFkp(self.bytes, self.mainStream, self.parentpos + self.bOffset * 2) papxInFkp.dump() print('') class ChpxFkp(BinaryStream): """The ChpxFkp structure maps text to its character properties.""" def __init__(self, pnFkpChpx, offset, size): BinaryStream.__init__(self, pnFkpChpx.mainStream.bytes, mainStream=pnFkpChpx.mainStream) self.pos = offset self.size = size self.pnFkpChpx = pnFkpChpx def dump(self): print('' % (self.pos, self.size)) self.crun = self.getuInt8(pos=self.pos + self.size - 1) pos = self.pos self.transformeds = [] for i in range(self.crun): # rgfc start = self.getuInt32(pos=pos) end = self.getuInt32(pos=pos + 4) print('' % (i, start, end)) self.transformed = self.quoteAttr(self.pnFkpChpx.mainStream.retrieveOffset(start, end)) print('' % self.transformed) self.transformeds.append(self.transformed) pos += 4 # rgbx offset = PLC.getPLCOffset(self.pos, self.crun, 1, i) chpxOffset = self.getuInt8(pos=offset) * 2 chpx = Chpx(self, self.mainStream, self.pos + chpxOffset, self.transformed) chpx.dump() print('') self.printAndSet("crun", self.crun) print('') class PapxFkp(BinaryStream): """The PapxFkp structure maps paragraphs, table rows, and table cells to their properties.""" def __init__(self, bytes, mainStream, offset, size): BinaryStream.__init__(self, mainStream.bytes, mainStream=mainStream) self.pos = offset self.size = size def dump(self): print('' % (self.pos, self.size)) self.cpara = self.getuInt8(pos=self.pos + self.size - 1) pos = self.pos for i in range(self.cpara): # rgfc start = self.getuInt32(pos=pos) end = self.getuInt32(pos=pos + 4) print('' % (i, start, end)) print('' % self.quoteAttr(self.mainStream.retrieveOffset(start, end))) pos += 4 # rgbx offset = PLC.getPLCOffset(self.pos, self.cpara, BxPap.size, i) bxPap = BxPap(self.bytes, self.mainStream, offset, self.pos) bxPap.dump() print('') self.printAndSet("cpara", self.cpara) print('') class PnFkpChpx(BinaryStream): """The PnFkpChpx structure specifies the location in the WordDocument Stream of a ChpxFkp structure.""" def __init__(self, plcBteChpx, offset, size, name): BinaryStream.__init__(self, plcBteChpx.bytes, mainStream=plcBteChpx.mainStream) self.pos = offset self.size = size self.name = name self.plcBteChpx = plcBteChpx def dump(self): print('<%s type="PnFkpChpx" offset="%d" size="%d bytes">' % (self.name, self.pos, self.size)) buf = self.readuInt32() self.printAndSet("pn", buf & (2 ** 22 - 1)) chpxFkp = ChpxFkp(self, self.pn * 512, 512) chpxFkp.dump() print('' % self.name) class LPXCharBuffer9(BinaryStream): """The LPXCharBuffer9 structure is a length-prefixed buffer for up to 9 Unicode characters.""" def __init__(self, parent, name): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.name = name def dump(self): print('<%s type="LPXCharBuffer9" offset="%d" size="20 bytes">' % (self.name, self.pos)) self.printAndSet("cch", self.readuInt16()) self.printAndSet("xcharArray", self.bytes[self.pos:self.pos + (self.cch * 2)].decode('utf-16'), hexdump=False) print('' % self.name) class ATRDPre10(BinaryStream): """The ATRDPre10 structure contains information about a comment in the document.""" def __init__(self, aPlcfandRef, offset): BinaryStream.__init__(self, aPlcfandRef.bytes) self.pos = offset def dump(self): print('' % self.pos) xstUsrInitl = LPXCharBuffer9(self, "xstUsrInitl") xstUsrInitl.dump() self.pos += 20 self.printAndSet("ibst", self.readuInt16()) self.printAndSet("bitsNotUsed", self.readuInt16()) self.printAndSet("grfNotUsed", self.readuInt16()) self.printAndSet("ITagBkmk", self.readInt32()) print('') class PnFkpPapx(BinaryStream): """The PnFkpPapx structure specifies the offset of a PapxFkp in the WordDocument Stream.""" def __init__(self, bytes, mainStream, offset, size, name): BinaryStream.__init__(self, bytes, mainStream=mainStream) self.pos = offset self.size = size self.name = name def dump(self): print('<%s type="PnFkpPapx" offset="%d" size="%d bytes">' % (self.name, self.pos, self.size)) buf = self.readuInt32() self.printAndSet("pn", buf & (2 ** 22 - 1)) papxFkp = PapxFkp(self.bytes, self.mainStream, self.pn * 512, 512) papxFkp.dump() print('' % self.name) class PlcBteChpx(BinaryStream, PLC): """The PlcBteChpx structure is a PLC that maps the offsets of text in the WordDocument stream to the character properties of that text.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) PLC.__init__(self, mainStream.lcbPlcfBteChpx, 4) self.pos = mainStream.fcPlcfBteChpx self.size = mainStream.lcbPlcfBteChpx def dump(self): print('' % (self.pos, self.size)) pos = self.pos for i in range(self.getElements()): # aFC start = self.getuInt32(pos=pos) end = self.getuInt32(pos=pos + 4) print('' % (i, start, end)) pos += 4 # aPnBteChpx aPnBteChpx = PnFkpChpx(self, self.getOffset(self.pos, i), 4, "aPnBteChpx") aPnBteChpx.dump() print('') print('') class PlcfHdd(BinaryStream, PLC): """The Plcfhdd structure is a PLC that contains only CPs and no additional data. It specifies where header document stories begin and end.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) PLC.__init__(self, mainStream.lcbPlcfHdd, 0) self.pos = mainStream.fcPlcfHdd self.size = mainStream.lcbPlcfHdd def getContents(self, i): if i <= 5: contentsMap = { 0: "Footnote separator", 1: "Footnote continuation separator", 2: "Footnote continuation notice", 3: "Endnote separator", 4: "Endnote continuation separator", 5: "Endnote continuation notice", } return contentsMap[i] else: contentsMap = { 0: "Even page header", 1: "Odd page header", 2: "Even page footer", 3: "Odd page footer", 4: "First page header", 5: "First page footer", } sectionIndex = i / 6 contentsIndex = i % 6 return "%s (section #%s)" % (contentsMap[contentsIndex], sectionIndex) def dump(self): print('' % (self.pos, self.size)) offset = self.mainStream.getHeaderOffset() pos = self.pos for i in range(self.getElements() - 1): start = self.getuInt32(pos=pos) end = self.getuInt32(pos=pos + 4) print('' % (i, self.getContents(i), start, end)) print('' % self.quoteAttr(self.mainStream.retrieveCPs(offset + start, offset + end))) pos += 4 print('') print('') class PlcfandTxt(BinaryStream, PLC): """The PlcfandTxt structure is a PLC that contains only CPs and no additional data.""" def __init__(self, mainStream, offset, size): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) PLC.__init__(self, size, 0) self.pos = offset self.size = size def dump(self): print('' % (self.pos, self.size)) offset = self.mainStream.getCommentOffset() pos = self.pos for i in range(self.getElements() - 1): start = self.getuInt32(pos=pos) end = self.getuInt32(pos=pos + 4) print('' % (i, start, end)) print('' % self.quoteAttr(self.mainStream.retrieveCPs(offset + start, offset + end))) pos += 4 print('') print('') class PlcfandRef(BinaryStream, PLC): """The PlcfandRef structure is a PLC whose data elements are ATRDPre10 structures.""" def __init__(self, mainStream, offset, size): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) PLC.__init__(self, size, 30) self.pos = offset self.size = size def dump(self): print('' % (self.pos, self.size)) pos = self.pos for i in range(self.getElements()): start = self.getuInt32(pos=pos) print('' % (i, start)) print('' % self.quoteAttr(self.mainStream.retrieveCP(start))) pos += 4 # aATRDPre10 aATRDPre10 = ATRDPre10(self, self.getOffset(self.pos, i)) aATRDPre10.dump() print('') print('') class PlcBtePapx(BinaryStream, PLC): """The PlcBtePapx structure is a PLC that specifies paragraph, table row, or table cell properties.""" def __init__(self, bytes, mainStream, offset, size): BinaryStream.__init__(self, bytes, mainStream=mainStream) PLC.__init__(self, size, 4) self.pos = offset self.size = size def dump(self): print('' % (self.pos, self.size)) pos = self.pos for i in range(self.getElements()): # aFC start = self.getuInt32(pos=pos) end = self.getuInt32(pos=pos + 4) print('' % (i, start, end)) pos += 4 # aPnBtePapx aPnBtePapx = PnFkpPapx(self.bytes, self.mainStream, self.getOffset(self.pos, i), 4, "aPnBtePapx") aPnBtePapx.dump() print('') print('') class Pcdt(BinaryStream): """The Pcdt structure contains a PlcPcd structure and specifies its size.""" def __init__(self, bytes, mainStream, offset, size): BinaryStream.__init__(self, bytes, mainStream=mainStream) self.pos = offset self.size = size self.clxt = self.readuInt8() self.lcb = self.readuInt32() self.plcPcd = PlcPcd(self.bytes, self.mainStream, self.pos, self.lcb) def dump(self): print('' % (self.pos, self.size)) self.printAndSet("clxt", self.clxt) self.printAndSet("lcb", self.lcb) self.plcPcd.dump() print('') class PrcData(BinaryStream): """The PrcData structure specifies an array of Prl elements and the size of the array.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.cbGrpprl = self.readInt16() pos = 0 self.prls = [] while self.cbGrpprl - pos > 0: prl = Prl(self, self.pos + pos) pos += prl.getSize() self.prls.append(prl) self.pos += self.cbGrpprl parent.pos = self.pos def dump(self): print('') self.printAndSet("cbGrpprl", self.cbGrpprl) print('') for i in self.prls: i.dump() print('') print('') class Prc(BinaryStream): """The Prc structure specifies a set of properties for document content that is referenced by a Pcd structure.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.clxt = self.readuInt8() self.prcData = PrcData(self) parent.pos = self.pos def dump(self, index): print('' % index) self.prcData.dump() print('') class Clx(BinaryStream): def __init__(self, bytes, mainStream, offset, size): BinaryStream.__init__(self, bytes, mainStream=mainStream) self.pos = offset self.size = size self.firstByte = self.getuInt8() self.prcs = [] while True: self.firstByte = self.getuInt8() if self.firstByte != 0x01: break self.prcs.append(Prc(self)) self.pcdt = Pcdt(self.bytes, self.mainStream, self.pos, self.size) def dump(self): print('' % (self.pos, self.size)) for index, elem in enumerate(self.prcs): elem.dump(index) self.pcdt.dump() print('') class Copts60(BinaryStream): """The Copts60 structure specifies compatibility options.""" def __init__(self, dop): BinaryStream.__init__(self, dop.bytes) self.pos = dop.pos def dump(self): print('' % self.pos) # Copts60 first byte buf = self.readuInt8() self.printAndSet("fNoTabForInd", self.getBit(buf, 0)) self.printAndSet("fNoSpaceRaiseLower", self.getBit(buf, 1)) self.printAndSet("fSuppressSpBfAfterPgBrk", self.getBit(buf, 2)) self.printAndSet("fWrapTrailSpaces", self.getBit(buf, 3)) self.printAndSet("fMapPrintTextColor", self.getBit(buf, 4)) self.printAndSet("fNoColumnBalance", self.getBit(buf, 5)) self.printAndSet("fConvMailMergeEsc", self.getBit(buf, 6)) self.printAndSet("fSuppressTopSpacing", self.getBit(buf, 7)) # Copts60 second byte buf = self.readuInt8() self.printAndSet("fOrigWordTableRules", self.getBit(buf, 0)) self.printAndSet("unused14", self.getBit(buf, 1)) self.printAndSet("fShowBreaksInFrames", self.getBit(buf, 2)) self.printAndSet("fSwapBordersFacingPgs", self.getBit(buf, 3)) self.printAndSet("fLeaveBackslashAlone", self.getBit(buf, 4)) self.printAndSet("fExpShRtn", self.getBit(buf, 5)) self.printAndSet("fDntULTrlSpc", self.getBit(buf, 6)) self.printAndSet("fDntBlnSbDbWid", self.getBit(buf, 7)) print('') class DTTM(BinaryStream): """The DTTM structure specifies date and time.""" def __init__(self, parent, name): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = parent.pos self.name = name def dump(self): buf = self.readuInt32() print('<%s type="DTTM" offset="%d" size="4 bytes">' % (self.name, self.pos)) self.printAndSet("mint", buf & 0x0000003f) # 1..6th bits self.printAndSet("hr", (buf & 0x000007c0) >> 6) # 7..11th bits self.printAndSet("dom", (buf & 0x0000f800) >> 11) # 12..16th bits self.printAndSet("mon", (buf & 0x000f0000) >> 16) # 17..20th bits self.printAndSet("yr", (buf & 0x1ff00000) >> 20) # 21..29th bits self.printAndSet("wdy", (buf & 0xe0000000) >> 29) # 30..32th bits print('' % (1900 + self.yr, self.mon, self.dom, self.hr, self.mint)) print('' % self.name) self.parent.pos = self.pos class GRFSTD(BinaryStream): """The GRFSTD structure specifies the general properties of a style.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = parent.pos def dump(self): print('' % self.pos) buf = self.readuInt8() self.printAndSet("fAutoRedef", self.getBit(buf, 0)) self.printAndSet("fHidden", self.getBit(buf, 1)) self.printAndSet("f97LidsSet", self.getBit(buf, 2)) self.printAndSet("fCopyLang", self.getBit(buf, 3)) self.printAndSet("fPersonalCompose", self.getBit(buf, 4)) self.printAndSet("fPersonalReply", self.getBit(buf, 5)) self.printAndSet("fPersonal", self.getBit(buf, 6)) self.printAndSet("fNoHtmlExport", self.getBit(buf, 7)) buf = self.readuInt8() self.printAndSet("fSemiHidden", self.getBit(buf, 0)) self.printAndSet("fLocked", self.getBit(buf, 1)) self.printAndSet("fInternalUse", self.getBit(buf, 2)) self.printAndSet("fUnhideWhenUsed", self.getBit(buf, 3)) self.printAndSet("fQFormat", self.getBit(buf, 4)) self.printAndSet("fReserved", (buf & 0xe0) >> 5) # 6..8th bits print('') self.parent.pos = self.pos class DopBase(BinaryStream): """The DopBase structure contains document and compatibility settings.""" size = 84 def __init__(self, dop): BinaryStream.__init__(self, dop.bytes) self.pos = dop.pos self.dop = dop def dump(self): print('' % (self.pos, 84)) buf = self.readuInt8() self.printAndSet("fFacingPages", self.getBit(buf, 0)) self.printAndSet("unused1", self.getBit(buf, 1)) self.printAndSet("fPMHMainDoc", self.getBit(buf, 2)) self.printAndSet("unused2", (buf & 0x18) >> 3) # 4..5th bits self.printAndSet("fpc", (buf & 0x60) >> 5) # 6..7th bits self.printAndSet("unused3", self.getBit(buf, 7)) self.printAndSet("unused4", self.readuInt8()) buf = self.readuInt16() self.printAndSet("rncFtn", buf & 0x03) # 1..2nd bits self.printAndSet("nFtn", (buf & 0xfffc) >> 2) # 3..16th bits buf = self.readuInt8() self.printAndSet("unused5", self.getBit(buf, 0)) self.printAndSet("unused6", self.getBit(buf, 1)) self.printAndSet("unused7", self.getBit(buf, 2)) self.printAndSet("unused8", self.getBit(buf, 3)) self.printAndSet("unused9", self.getBit(buf, 4)) self.printAndSet("unused10", self.getBit(buf, 5)) self.printAndSet("fSplAllDone", self.getBit(buf, 6)) self.printAndSet("fSplAllClean", self.getBit(buf, 7)) buf = self.readuInt8() self.printAndSet("fSplHideErrors", self.getBit(buf, 0)) self.printAndSet("fGramHideErrors", self.getBit(buf, 1)) self.printAndSet("fLabelDoc", self.getBit(buf, 2)) self.printAndSet("fHyphCapitals", self.getBit(buf, 3)) self.printAndSet("fAutoHyphen", self.getBit(buf, 4)) self.printAndSet("fFormNoFields", self.getBit(buf, 5)) self.printAndSet("fLinkStyles", self.getBit(buf, 6)) self.printAndSet("fRevMarking", self.getBit(buf, 7)) buf = self.readuInt8() self.printAndSet("unused11", self.getBit(buf, 0)) self.printAndSet("fExactCWords", self.getBit(buf, 1)) self.printAndSet("fPagHidden", self.getBit(buf, 2)) self.printAndSet("fPagResults", self.getBit(buf, 3)) self.printAndSet("fLockAtn", self.getBit(buf, 4)) self.printAndSet("fMirrorMargins", self.getBit(buf, 5)) self.printAndSet("fWord97Compat", self.getBit(buf, 6)) self.printAndSet("unused12", self.getBit(buf, 7)) buf = self.readuInt8() self.printAndSet("unused13", self.getBit(buf, 0)) self.printAndSet("fProtEnabled", self.getBit(buf, 1)) self.printAndSet("fDispFormFldSel", self.getBit(buf, 2)) self.printAndSet("fRMView", self.getBit(buf, 3)) self.printAndSet("fRMPrint", self.getBit(buf, 4)) self.printAndSet("fLockVbaProj", self.getBit(buf, 5)) self.printAndSet("fLockRev", self.getBit(buf, 6)) self.printAndSet("fEmbedFonts", self.getBit(buf, 7)) copts60 = Copts60(self) copts60.dump() self.pos += 2 self.printAndSet("dxaTab", self.readuInt16()) self.printAndSet("cpgWebOpt", self.readuInt16()) self.printAndSet("dxaHotZ", self.readuInt16()) self.printAndSet("cConsecHypLim", self.readuInt16()) self.printAndSet("wSpare2", self.readuInt16()) DTTM(self, "dttmCreated").dump() DTTM(self, "dttmRevised").dump() DTTM(self, "dttmLastprint").dump() self.printAndSet("nRevision", self.readInt16()) self.printAndSet("tmEdited", self.readInt32()) self.printAndSet("cWords", self.readInt32()) self.printAndSet("cCh", self.readInt32()) self.printAndSet("cPg", self.readInt16()) self.printAndSet("cParas", self.readInt32()) buf = self.readuInt16() self.printAndSet("rncEdn", buf & 0x0003) # 1..2nd bits self.printAndSet("nEdn", (buf & 0xfffc) >> 2) # 3..16th bits buf = self.readuInt16() self.printAndSet("epc", buf & 0x0003) # 1..2nd bits self.printAndSet("unused14", (buf & 0x003c) >> 2) # 3..6th bits self.printAndSet("unused15", (buf & 0x03c0) >> 6) # 7..10th bits self.printAndSet("fPrintFormData", self.getBit(buf, 10)) self.printAndSet("fSaveFormData", self.getBit(buf, 11)) self.printAndSet("fShadeFormData", self.getBit(buf, 12)) self.printAndSet("fShadeMergeFields", self.getBit(buf, 13)) self.printAndSet("reserved2", self.getBit(buf, 14)) self.printAndSet("fIncludeSubdocsInStats", self.getBit(buf, 15)) self.printAndSet("cLines", self.readInt32()) self.printAndSet("cWordsWithSubdocs", self.readInt32()) self.printAndSet("cChWithSubdocs", self.readInt32()) self.printAndSet("cPgWithSubdocs", self.readInt16()) self.printAndSet("cParasWithSubdocs", self.readInt32()) self.printAndSet("cLinesWithSubdocs", self.readInt32()) self.printAndSet("lKeyProtDoc", self.readInt32()) buf = self.readuInt16() self.printAndSet("wvkoSaved", buf & 0x0007) # 1..3rd bits self.printAndSet("pctWwdSaved", (buf & 0x0ff8) >> 3) # 4..12th bits self.printAndSet("zkSaved", (buf & 0x3000) >> 12) # 13..14th bits self.printAndSet("unused16", self.getBit(buf, 14)) self.printAndSet("iGutterPos", self.getBit(buf, 15)) print('') assert self.pos == self.dop.pos + DopBase.size self.dop.pos = self.pos class Copts80(BinaryStream): """The Copts80 structure specifies compatibility options.""" def __init__(self, dop): BinaryStream.__init__(self, dop.bytes) self.pos = dop.pos def dump(self): print('' % self.pos) Copts60(self).dump() self.pos += 2 buf = self.readuInt8() self.printAndSet("fSuppressTopSpacingMac5", self.getBit(buf, 0)) self.printAndSet("fTruncDxaExpand", self.getBit(buf, 1)) self.printAndSet("fPrintBodyBeforeHdr", self.getBit(buf, 2)) self.printAndSet("fNoExtLeading", self.getBit(buf, 3)) self.printAndSet("fDontMakeSpaceForUL", self.getBit(buf, 4)) self.printAndSet("fMWSmallCaps", self.getBit(buf, 5)) self.printAndSet("f2ptExtLeadingOnly", self.getBit(buf, 6)) self.printAndSet("fTruncFontHeight", self.getBit(buf, 7)) buf = self.readuInt8() self.printAndSet("fSubOnSize", self.getBit(buf, 0)) self.printAndSet("fLineWrapLikeWord6", self.getBit(buf, 1)) self.printAndSet("fWW6BorderRules", self.getBit(buf, 2)) self.printAndSet("fExactOnTop", self.getBit(buf, 3)) self.printAndSet("fExtraAfter", self.getBit(buf, 4)) self.printAndSet("fWPSpace", self.getBit(buf, 5)) self.printAndSet("fWPJust", self.getBit(buf, 6)) self.printAndSet("fPrintMet", self.getBit(buf, 7)) print('') class Copts(BinaryStream): """A structure that specifies compatibility options.""" size = 32 def __init__(self, dop): BinaryStream.__init__(self, dop.bytes) self.pos = dop.pos self.dop = dop def dump(self): print('' % (self.pos, Copts.size)) Copts80(self).dump() self.pos += 4 buf = self.readuInt8() self.printAndSet("fSpLayoutLikeWW8", self.getBit(buf, 0)) self.printAndSet("fFtnLayoutLikeWW8", self.getBit(buf, 1)) self.printAndSet("fDontUseHTMLParagraphAutoSpacing", self.getBit(buf, 2)) self.printAndSet("fDontAdjustLineHeightInTable", self.getBit(buf, 3)) self.printAndSet("fForgetLastTabAlign", self.getBit(buf, 4)) self.printAndSet("fUseAutospaceForFullWidthAlpha", self.getBit(buf, 5)) self.printAndSet("fAlignTablesRowByRow", self.getBit(buf, 6)) self.printAndSet("fLayoutRawTableWidth", self.getBit(buf, 7)) buf = self.readuInt8() self.printAndSet("fLayoutTableRowsApart", self.getBit(buf, 0)) self.printAndSet("fUseWord97LineBreakingRules", self.getBit(buf, 1)) self.printAndSet("fDontBreakWrappedTables", self.getBit(buf, 2)) self.printAndSet("fDontSnapToGridInCell", self.getBit(buf, 3)) self.printAndSet("fDontAllowFieldEndSelect", self.getBit(buf, 4)) self.printAndSet("fApplyBreakingRules", self.getBit(buf, 5)) self.printAndSet("fDontWrapTextWithPunct", self.getBit(buf, 6)) self.printAndSet("fDontUseAsianBreakRules", self.getBit(buf, 7)) buf = self.readuInt8() self.printAndSet("fUseWord2002TableStyleRules", self.getBit(buf, 0)) self.printAndSet("fGrowAutoFit", self.getBit(buf, 1)) self.printAndSet("fUseNormalStyleForList", self.getBit(buf, 2)) self.printAndSet("fDontUseIndentAsNumberingTabStop", self.getBit(buf, 3)) self.printAndSet("fFELineBreak11", self.getBit(buf, 4)) self.printAndSet("fAllowSpaceOfSameStyleInTable", self.getBit(buf, 5)) self.printAndSet("fWW11IndentRules", self.getBit(buf, 6)) self.printAndSet("fDontAutofitConstrainedTables", self.getBit(buf, 7)) buf = self.readuInt8() self.printAndSet("fAutofitLikeWW11", self.getBit(buf, 0)) self.printAndSet("fUnderlineTabInNumList", self.getBit(buf, 1)) self.printAndSet("fHangulWidthLikeWW11", self.getBit(buf, 2)) self.printAndSet("fSplitPgBreakAndParaMark", self.getBit(buf, 3)) self.printAndSet("fDontVertAlignCellWithSp", self.getBit(buf, 4)) self.printAndSet("fDontBreakConstrainedForcedTables", self.getBit(buf, 5)) self.printAndSet("fDontVertAlignInTxbx", self.getBit(buf, 6)) self.printAndSet("fWord11KerningPairs", self.getBit(buf, 7)) buf = self.readuInt32() self.printAndSet("fCachedColBalance", self.getBit(buf, 0)) self.printAndSet("empty1", (buf & 0xfffffffe) >> 1) # 2..32th bits self.printAndSet("empty2", self.readuInt32()) self.printAndSet("empty3", self.readuInt32()) self.printAndSet("empty4", self.readuInt32()) self.printAndSet("empty5", self.readuInt32()) self.printAndSet("empty6", self.readuInt32()) print('') assert self.pos == self.dop.pos + Copts.size self.dop.pos = self.pos class Dop95(BinaryStream): """The Dop95 structure contains document and compatibility settings.""" size = 88 def __init__(self, dop, dopSize): BinaryStream.__init__(self, dop.bytes) self.pos = dop.pos self.dop = dop self.dopSize = dopSize def dump(self): print('' % self.pos) pos = self.pos dopBase = DopBase(self) dopBase.dump() if self.pos >= pos + self.dopSize: print('') self.dop.pos = self.pos return Copts80(self).dump() self.pos += 4 print('') assert self.pos == self.dop.pos + Dop95.size self.dop.pos = self.pos class DopTypography(BinaryStream): """The DopTypography structure contains East Asian language typography settings.""" size = 310 def __init__(self, dop): BinaryStream.__init__(self, dop.bytes) self.pos = dop.pos self.dop = dop def dump(self): print('' % self.pos) buf = self.readuInt16() self.printAndSet("fKerningPunct", self.getBit(buf, 0)) self.printAndSet("iJustification", (buf & 0x0006) >> 1) # 2..3rd bits self.printAndSet("iLevelOfKinsoku", (buf & 0x0018) >> 1) # 4..5th bits self.printAndSet("f2on1", self.getBit(buf, 5)) self.printAndSet("unused", self.getBit(buf, 6)) self.printAndSet("iCustomKsu", (buf & 0x0380) >> 7) # 8..10th bits self.printAndSet("fJapaneseUseLevel2", self.getBit(buf, 10)) self.printAndSet("reserved", (buf & 0xf800) >> 11) # 12..16th bits self.printAndSet("cchFollowingPunct", self.readInt16()) self.printAndSet("cchLeadingPunct", self.readInt16()) self.printAndSet("rgxchFPunct", self.getString(self.cchFollowingPunct), hexdump=False) self.pos += 202 self.printAndSet("rgxchLPunct", self.getString(self.cchLeadingPunct), hexdump=False) self.pos += 102 print('') assert self.pos == self.dop.pos + DopTypography.size self.dop.pos = self.pos class Dogrid(BinaryStream): """The Dogrid structure specifies parameters for the drawn object properties of the document.""" size = 10 def __init__(self, dop): BinaryStream.__init__(self, dop.bytes) self.pos = dop.pos self.dop = dop def dump(self): print('' % (self.pos, Dogrid.size)) self.printAndSet("xaGrid", self.readuInt16()) self.printAndSet("yaGrid", self.readuInt16()) self.printAndSet("dxaGrid", self.readuInt16()) self.printAndSet("dyaGrid", self.readuInt16()) buf = self.readuInt8() self.printAndSet("dyGridDisplay", (buf & 0x7f)) # 1..7th bits self.printAndSet("unused", self.getBit(buf, 7)) buf = self.readuInt8() self.printAndSet("dxGridDisplay", (buf & 0x7f)) # 1..7th bits self.printAndSet("fFollowMargins", self.getBit(buf, 7)) print('') assert self.pos == self.dop.pos + Dogrid.size self.dop.pos = self.pos class Asumyi(BinaryStream): """The Asumyi structure specifies AutoSummary state information""" def __init__(self, dop): BinaryStream.__init__(self, dop.bytes) self.pos = dop.pos def dump(self): print('' % self.pos) buf = self.readuInt16() self.printAndSet("fValid", self.getBit(buf, 0)) self.printAndSet("fView", self.getBit(buf, 1)) self.printAndSet("iViewBy", (buf & 0x0c) >> 2) # 3..4th bits self.printAndSet("fUpdateProps", self.getBit(buf, 4)) self.printAndSet("reserved", (buf & 0xffe0) >> 5) # 6..16th bits self.printAndSet("wDlgLevel", self.readuInt16()) self.printAndSet("lHighestLevel", self.readuInt32()) self.printAndSet("lCurrentLevel", self.readuInt32()) print('') class Dop97(BinaryStream): """The Dop97 structure contains document and compatibility settings.""" size = 500 def __init__(self, dop, dopSize): BinaryStream.__init__(self, dop.bytes) self.pos = dop.pos self.dop = dop self.dopSize = dopSize def dump(self): print('' % (self.pos, Dop97.size)) pos = self.pos dop95 = Dop95(self, self.dopSize) dop95.dump() if self.pos >= pos + self.dopSize: print('') self.dop.pos = self.pos return self.printAndSet("adt", self.readuInt16()) dopTypography = DopTypography(self) dopTypography.dump() dogrid = Dogrid(self) dogrid.dump() buf = self.readuInt8() self.printAndSet("unused1", self.getBit(buf, 0)) self.printAndSet("lvlDop", (buf & 0x1e) >> 1) # 2..5th bits self.printAndSet("fGramAllDone", self.getBit(buf, 5)) self.printAndSet("fGramAllClean", self.getBit(buf, 6)) self.printAndSet("fSubsetFonts", self.getBit(buf, 7)) buf = self.readuInt8() self.printAndSet("unused2", self.getBit(buf, 0)) self.printAndSet("fHtmlDoc", self.getBit(buf, 1)) self.printAndSet("fDiskLvcInvalid", self.getBit(buf, 2)) self.printAndSet("fSnapBorder", self.getBit(buf, 3)) self.printAndSet("fIncludeHeader", self.getBit(buf, 4)) self.printAndSet("fIncludeFooter", self.getBit(buf, 5)) self.printAndSet("unused3", self.getBit(buf, 6)) self.printAndSet("unused4", self.getBit(buf, 7)) self.printAndSet("unused5", self.readuInt16()) Asumyi(self).dump() self.pos += 12 self.printAndSet("cChWS", self.readuInt32()) self.printAndSet("cChWSWithSubdocs", self.readuInt32()) self.printAndSet("grfDocEvents", self.readuInt32()) buf = self.readuInt32() self.printAndSet("fVirusPrompted", self.getBit(buf, 0)) self.printAndSet("fVirusLoadSafe", self.getBit(buf, 1)) self.printAndSet("KeyVirusSession30", (buf & 0xfffffffc) >> 2) self.printAndSet("space1", self.readuInt32()) self.printAndSet("space2", self.readuInt32()) self.printAndSet("space3", self.readuInt32()) self.printAndSet("space4", self.readuInt32()) self.printAndSet("space5", self.readuInt32()) self.printAndSet("space6", self.readuInt32()) self.printAndSet("space7", self.readuInt32()) self.printAndSet("space8", self.readuInt16()) self.printAndSet("cpMaxListCacheMainDoc", self.readuInt32()) self.printAndSet("ilfoLastBulletMain", self.readuInt16()) self.printAndSet("ilfoLastNumberMain", self.readuInt16()) self.printAndSet("cDBC", self.readuInt32()) self.printAndSet("cDBCWithSubdocs", self.readuInt32()) self.printAndSet("reserved3a", self.readuInt32()) self.printAndSet("nfcFtnRef", self.readuInt16()) self.printAndSet("nfcEdnRef", self.readuInt16()) self.printAndSet("hpsZoomFontPag", self.readuInt16()) self.printAndSet("dywDispPag", self.readuInt16()) print('') assert self.pos == self.dop.pos + Dop97.size self.dop.pos = self.pos class Dop2000(BinaryStream): """The Dop2000 structure contains document and compatibility settings.""" size = 544 def __init__(self, dop, dopSize): BinaryStream.__init__(self, dop.bytes) self.pos = dop.pos self.dop = dop self.dopSize = dopSize def dump(self): print('' % self.pos) dop97 = Dop97(self, self.dopSize) dop97.dump() if self.pos == self.size: print('') print('') self.dop.pos = self.pos return self.printAndSet("ilvlLastBulletMain", self.readuInt8()) self.printAndSet("ilvlLastNumberMain", self.readuInt8()) self.printAndSet("istdClickParaType", self.readuInt16()) buf = self.readuInt8() self.printAndSet("fLADAllDone", self.getBit(buf, 0)) self.printAndSet("fEnvelopeVis", self.getBit(buf, 1)) self.printAndSet("fMaybeTentativeListInDoc", self.getBit(buf, 2)) self.printAndSet("fMaybeFitText", self.getBit(buf, 3)) self.printAndSet("empty1", (buf & 0xf0) >> 4) # 5..8th bits buf = self.readuInt8() self.printAndSet("fFCCAllDone", self.getBit(buf, 0)) self.printAndSet("fRelyOnCSS_WebOpt", self.getBit(buf, 1)) self.printAndSet("fRelyOnVML_WebOpt", self.getBit(buf, 2)) self.printAndSet("fAllowPNG_WebOpt", self.getBit(buf, 3)) self.printAndSet("screenSize_WebOpt", (buf & 0xf0) >> 4) # 5..8th bits buf = self.readuInt16() self.printAndSet("fOrganizeInFolder_WebOpt", self.getBit(buf, 0)) self.printAndSet("fUseLongFileNames_WebOpt", self.getBit(buf, 1)) self.printAndSet("iPixelsPerInch_WebOpt", (buf & 0x0ffc) >> 2) # 3..12th bits self.printAndSet("fWebOptionsInit", self.getBit(buf, 12)) self.printAndSet("fMaybeFEL", self.getBit(buf, 12)) self.printAndSet("fCharLineUnits", self.getBit(buf, 12)) self.printAndSet("unused1", self.getBit(buf, 12)) copts = Copts(self) copts.dump() self.printAndSet("verCompatPre10", self.readuInt16()) buf = self.readuInt8() self.printAndSet("fNoMargPgvwSaved", self.getBit(buf, 0)) self.printAndSet("unused2", self.getBit(buf, 1)) self.printAndSet("unused3", self.getBit(buf, 2)) self.printAndSet("unused4", self.getBit(buf, 3)) self.printAndSet("fBulletProofed", self.getBit(buf, 4)) self.printAndSet("empty2", self.getBit(buf, 5)) self.printAndSet("fSaveUim", self.getBit(buf, 6)) self.printAndSet("fFilterPrivacy", self.getBit(buf, 7)) buf = self.readuInt8() self.printAndSet("empty3", self.getBit(buf, 0)) self.printAndSet("fSeenRepairs", self.getBit(buf, 1)) self.printAndSet("fHasXML", self.getBit(buf, 2)) self.printAndSet("unused5", self.getBit(buf, 3)) self.printAndSet("fValidateXML", self.getBit(buf, 4)) self.printAndSet("fSaveInvalidXML", self.getBit(buf, 5)) self.printAndSet("fShowXMLErrors", self.getBit(buf, 6)) self.printAndSet("fAlwaysMergeEmptyNamespace", self.getBit(buf, 7)) print('') assert self.pos == self.dop.pos + Dop2000.size self.dop.pos = self.pos class Dop2002(BinaryStream): """The Dop2002 structure contains document and compatibility settings.""" size = 594 def __init__(self, dop, dopSize): BinaryStream.__init__(self, dop.bytes) self.pos = dop.pos self.dop = dop self.dopSize = dopSize def dump(self): print('' % (self.pos, Dop2002.size)) dop2000 = Dop2000(self, self.dopSize) dop2000.dump() self.printAndSet("unused", self.readuInt32()) buf = self.readuInt8() self.printAndSet("fDoNotEmbedSystemFont", self.getBit(buf, 0)) self.printAndSet("fWordCompat", self.getBit(buf, 1)) self.printAndSet("fLiveRecover", self.getBit(buf, 2)) self.printAndSet("fEmbedFactoids", self.getBit(buf, 3)) self.printAndSet("fFactoidXML", self.getBit(buf, 4)) self.printAndSet("fFactoidAllDone", self.getBit(buf, 5)) self.printAndSet("fFolioPrint", self.getBit(buf, 6)) self.printAndSet("fReverseFolio", self.getBit(buf, 7)) buf = self.readuInt8() self.printAndSet("iTextLineEnding", (buf & 0x7)) # 1..3rd bits self.printAndSet("fHideFcc", self.getBit(buf, 3)) self.printAndSet("fAcetateShowMarkup", self.getBit(buf, 4)) self.printAndSet("fAcetateShowAtn", self.getBit(buf, 5)) self.printAndSet("fAcetateShowInsDel", self.getBit(buf, 6)) self.printAndSet("fAcetateShowProps", self.getBit(buf, 7)) self.printAndSet("istdTableDflt", self.readuInt16()) self.printAndSet("verCompat", self.readuInt16()) self.printAndSet("grfFmtFilter", self.readuInt16()) self.printAndSet("iFolioPages", self.readuInt16()) self.printAndSet("cpgText", self.readuInt32()) self.printAndSet("cpMinRMText", self.readuInt32()) self.printAndSet("cpMinRMFtn", self.readuInt32()) self.printAndSet("cpMinRMHdd", self.readuInt32()) self.printAndSet("cpMinRMAtn", self.readuInt32()) self.printAndSet("cpMinRMEdn", self.readuInt32()) self.printAndSet("cpMinRmTxbx", self.readuInt32()) self.printAndSet("cpMinRmHdrTxbx", self.readuInt32()) self.printAndSet("rsidRoot", self.readuInt32()) print('') assert self.pos == self.dop.pos + Dop2002.size self.dop.pos = self.pos class Dop2003(BinaryStream): """The Dop2003 structure contains document and compatibility settings.""" size = 616 def __init__(self, dop, dopSize): BinaryStream.__init__(self, dop.bytes) self.pos = dop.pos self.dop = dop self.dopSize = dopSize def dump(self): print('' % self.pos) dop2002 = Dop2002(self, self.dopSize) dop2002.dump() buf = self.readuInt8() self.printAndSet("fTreatLockAtnAsReadOnly", self.getBit(buf, 0)) self.printAndSet("fStyleLock", self.getBit(buf, 1)) self.printAndSet("fAutoFmtOverride", self.getBit(buf, 2)) self.printAndSet("fRemoveWordML", self.getBit(buf, 3)) self.printAndSet("fApplyCustomXForm", self.getBit(buf, 4)) self.printAndSet("fStyleLockEnforced", self.getBit(buf, 5)) self.printAndSet("fFakeLockAtn", self.getBit(buf, 6)) self.printAndSet("fIgnoreMixedContent", self.getBit(buf, 7)) buf = self.readuInt8() self.printAndSet("fShowPlaceholderText", self.getBit(buf, 0)) self.printAndSet("unused", self.getBit(buf, 1)) self.printAndSet("fWord97Doc", self.getBit(buf, 2)) self.printAndSet("fStyleLockTheme", self.getBit(buf, 3)) self.printAndSet("fStyleLockQFSet", self.getBit(buf, 4)) self.printAndSet("empty1", (buf & 0xe0) >> 5) # 6..8th bits self.printAndSet("empty1_", self.readuInt16()) buf = self.readuInt8() self.printAndSet("fReadingModeInkLockDown", self.getBit(buf, 0)) self.printAndSet("fAcetateShowInkAtn", self.getBit(buf, 1)) self.printAndSet("fFilterDttm", self.getBit(buf, 2)) self.printAndSet("fEnforceDocProt", self.getBit(buf, 3)) self.printAndSet("iDocProtCur", (buf & 0x70) >> 4) # 5..7th bits self.printAndSet("fDispBkSpSaved", self.getBit(buf, 7)) self.printAndSet("empty2", self.readuInt8()) self.printAndSet("dxaPageLock", self.readuInt32()) self.printAndSet("dyaPageLock", self.readuInt32()) self.printAndSet("pctFontLock", self.readuInt32()) self.printAndSet("grfitbid", self.readuInt8()) self.printAndSet("empty3", self.readuInt8()) self.printAndSet("ilfoMacAtCleanup", self.readuInt16()) print('') assert self.pos == self.dop.pos + Dop2003.size self.dop.pos = self.pos class DopMth(BinaryStream): """The DopMth structure specifies document-wide math settings.""" def __init__(self, dop): BinaryStream.__init__(self, dop.bytes) self.pos = dop.pos def dump(self): print('' % self.pos) buf = self.readuInt32() self.printAndSet("mthbrk", (buf & 0x03)) # 1..2nd bits self.printAndSet("mthbrkSub", (buf & 0xc) >> 2) # 3..4th bits self.printAndSet("mthbpjc", (buf & 0x70) >> 4) # 5..7th bits self.printAndSet("reserved1", self.getBit(buf, 7)) self.printAndSet("fMathSmallFrac", self.getBit(buf, 8)) self.printAndSet("fMathIntLimUndOvr", self.getBit(buf, 9)) self.printAndSet("fMathNaryLimUndOvr", self.getBit(buf, 10)) self.printAndSet("fMathWrapAlignLeft", self.getBit(buf, 11)) self.printAndSet("fMathUseDispDefaults", self.getBit(buf, 12)) self.printAndSet("reserved2", (buf & 0xffffe000) >> 13) # 14..32th bits self.printAndSet("ftcMath", self.readuInt16()) self.printAndSet("dxaLeftMargin", self.readuInt32()) self.printAndSet("dxaRightMargin", self.readuInt32()) self.printAndSet("empty1", self.readuInt32()) self.printAndSet("empty2", self.readuInt32()) self.printAndSet("empty3", self.readuInt32()) self.printAndSet("empty4", self.readuInt32()) self.printAndSet("dxaIndentWrapped", self.readuInt32()) print('') class Dop2007(BinaryStream): """The Dop2007 structure contains document and compatibility settings.""" def __init__(self, dop, dopSize): BinaryStream.__init__(self, dop.bytes) self.pos = dop.pos self.dop = dop self.dopSize = dopSize def dump(self): print('' % self.pos) dop2003 = Dop2003(self, self.dopSize) dop2003.dump() self.printAndSet("reserved1", self.readuInt32()) buf = self.readuInt16() self.printAndSet("fRMTrackFormatting", self.getBit(buf, 0)) self.printAndSet("fRMTrackMoves", self.getBit(buf, 1)) self.printAndSet("reserved2", self.getBit(buf, 2)) self.printAndSet("empty1", self.getBit(buf, 3)) self.printAndSet("empty2", self.getBit(buf, 4)) self.printAndSet("ssm", (buf & 0x01e0) >> 5) # 6..9th bits self.printAndSet("fReadingModeInkLockDownActualPage", self.getBit(buf, 9)) self.printAndSet("fAutoCompressPictures", self.getBit(buf, 10)) self.printAndSet("reserved3", (buf & 0xf800) >> 11) # 12..16th bits self.printAndSet("reserved3_", self.readuInt16()) self.printAndSet("empty3", self.readuInt32()) self.printAndSet("empty4", self.readuInt32()) self.printAndSet("empty5", self.readuInt32()) self.printAndSet("empty6", self.readuInt32()) DopMth(self).dump() self.pos += 34 print('') class RC4EncryptionHeader(BinaryStream): """The encryption header structure used for RC4 encryption.""" def __init__(self, fib, pos, size): BinaryStream.__init__(self, fib.getTableStream().bytes) self.fib = fib self.pos = pos self.size = size def dump(self): print('') self.Salt = self.readBytes(16) print('' % globals.encodeName(self.Salt)) self.EncryptedVerifier = self.readBytes(16) print('' % globals.encodeName(self.EncryptedVerifier)) self.EncryptedVerifierHash = self.readBytes(16) print('' % globals.encodeName(self.EncryptedVerifierHash)) print('') assert self.pos == self.size class Dop(BinaryStream): """The Dop structure contains the document and compatibility settings for the document.""" def __init__(self, fib): BinaryStream.__init__(self, fib.getTableStream().bytes) self.pos = fib.fcDop self.size = fib.lcbDop self.fib = fib def dump(self): print('' % (self.pos, self.size)) if self.fib.nFibNew == 0: Dop97(self, self.size).dump() elif self.fib.nFibNew == 0x00d9: Dop2000(self, self.size).dump() elif self.fib.nFibNew == 0x0101: Dop2002(self, self.size).dump() elif self.fib.nFibNew == 0x0112: Dop2007(self, self.size).dump() else: print("""""" % hex(self.fib.nFibNew)) print('') class FFID(BinaryStream): """The FFID structure specifies the font family and character pitch for a font.""" def __init__(self, bytes, offset): BinaryStream.__init__(self, bytes) self.pos = offset self.unused1 = None self.unused2 = None def dump(self): self.ffid = self.readuInt8() self.prq = (self.ffid & 0x3) # first two bits self.fTrueType = (self.ffid & 0x4) >> 2 # 3rd bit self.unused1 = (self.ffid & 0x8) >> 3 # 4th bit self.ff = (self.ffid & 0x70) >> 4 # 5-7th bits self.unused2 = (self.ffid & 0x80) >> 7 # 8th bit print('' % (hex(self.ffid), hex(self.prq), self.fTrueType, hex(self.ff))) class PANOSE(BinaryStream): """The PANOSE structure defines the PANOSE font classification values for a TrueType font.""" def __init__(self, bytes, offset): BinaryStream.__init__(self, bytes) self.pos = offset def dump(self): print('' % self.pos) for i in ["bFamilyType", "bSerifStyle", "bWeight", "bProportion", "bContrast", "bStrokeVariation", "bArmStyle", "bLetterform", "bMidline", "bHeight"]: self.printAndSet(i, self.readuInt8()) print('') class FontSignature(BinaryStream): """Contains information identifying the code pages and Unicode subranges for which a given font provides glyphs.""" def __init__(self, bytes, offset): BinaryStream.__init__(self, bytes) self.pos = offset def dump(self): fsUsb1 = self.readuInt32() fsUsb2 = self.readuInt32() fsUsb3 = self.readuInt32() fsUsb4 = self.readuInt32() fsCsb1 = self.readuInt32() fsCsb2 = self.readInt32() print('' % (hex(fsUsb1), hex(fsUsb2), hex(fsUsb3), hex(fsUsb4), hex(fsCsb1), hex(fsCsb2)) ) class FFN(BinaryStream): """The FFN structure specifies information about a font that is used in the document.""" def __init__(self, bytes, mainStream, offset, size): BinaryStream.__init__(self, bytes, mainStream=mainStream) self.pos = offset self.size = size def dump(self): print('' % (self.pos, self.size)) FFID(self.bytes, self.pos).dump() self.pos += 1 self.printAndSet("wWeight", self.readInt16(), hexdump=False) self.printAndSet("chs", self.readuInt8(), hexdump=False) self.printAndSet("ixchSzAlt", self.readuInt8()) PANOSE(self.bytes, self.pos).dump() self.pos += 10 FontSignature(self.bytes, self.pos).dump() self.pos += 24 print('' % self.readString().replace('\\x00', '')) print('') class SttbfFfn(BinaryStream): """The SttbfFfn structure is an STTB whose strings are FFN records that specify details of system fonts.""" def __init__(self, bytes, mainStream, offset, size): BinaryStream.__init__(self, bytes, mainStream=mainStream) self.pos = offset self.size = size def dump(self): print('' % (self.pos, self.size)) self.printAndSet("cData", self.readuInt16()) self.printAndSet("cbExtra", self.readuInt16()) for i in range(self.cData): cchData = self.readuInt8() print('' % (i, self.pos, cchData)) FFN(self.bytes, self.mainStream, self.pos, cchData).dump() self.pos += cchData print('') print('') class GrpXstAtnOwners(BinaryStream): """This array contains the names of authors of comments in the document.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes) self.pos = mainStream.fcGrpXstAtnOwners self.size = mainStream.lcbGrpXstAtnOwners self.mainStream = mainStream def dump(self): posOrig = self.pos print('' % (self.pos, self.size)) while self.pos < posOrig + self.size: xst = Xst(self) xst.dump() self.pos = xst.pos print('') class SttbfAssoc(BinaryStream): """The SttbfAssoc structure is an STTB that contains strings which are associated with this document.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes) self.pos = mainStream.fcSttbfAssoc self.size = mainStream.lcbSttbfAssoc self.mainStream = mainStream def dump(self): indexMap = { 0x00: "Unused. MUST be ignored.", 0x01: "The path of the associated document template (2), if it is not the default Normal template.", 0x02: "The title of the document.", 0x03: "The subject of the document.", 0x04: "Key words associated with the document.", 0x05: "Unused. This index MUST be ignored.", 0x06: "The author of the document.", 0x07: "The user who last revised the document.", 0x08: "The path of the associated mail merge data source.", 0x09: "The path of the associated mail merge header document.", 0x0A: "Unused. This index MUST be ignored.", 0x0B: "Unused. This index MUST be ignored.", 0x0C: "Unused. This index MUST be ignored.", 0x0D: "Unused. This index MUST be ignored.", 0x0E: "Unused. This index MUST be ignored.", 0x0F: "Unused. This index MUST be ignored.", 0x10: "Unused. This index MUST be ignored.", 0x11: "The write-reservation password of the document.", } print('' % (self.pos, self.size)) self.printAndSet("fExtend", self.readuInt16()) self.printAndSet("cData", self.readuInt16()) self.printAndSet("cbExtra", self.readuInt16()) for i in range(self.cData): cchData = self.readuInt16() if i in indexMap.keys(): meaning = indexMap[i] else: meaning = "unknown" if self.pos + 2 * cchData > self.size: self.cData = 0 print('') break print('' % (hex(i), meaning, self.pos, cchData)) print('' % globals.encodeName(self.bytes[self.pos:self.pos + 2 * cchData].decode('utf-16'), lowOnly=True)) self.pos += 2 * cchData print('') # Probably this was cleared manually. if self.cData != 0: assert self.pos == self.mainStream.fcSttbfAssoc + self.size print('') class SttbfRMark(BinaryStream): """The SttbfRMark structure is an STTB structure where the strings specify the names of the authors of the revision marks, comments, and e-mail messages in the document.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes) self.pos = mainStream.fcSttbfRMark self.size = mainStream.lcbSttbfRMark self.mainStream = mainStream def dump(self): print('' % (self.pos, self.size)) self.printAndSet("fExtend", self.readuInt16()) self.printAndSet("cData", self.readuInt16()) self.printAndSet("cbExtra", self.readuInt16()) for i in range(self.cData): cchData = self.readuInt16() print('' % (i, self.pos, cchData)) print('' % globals.encodeName(self.bytes[self.pos:self.pos + 2 * cchData].decode('utf-16'), lowOnly=True)) self.pos += 2 * cchData print('') if self.cData != 0: assert self.pos == self.mainStream.fcSttbfRMark + self.size print('') class OfficeArtWordDrawing(BinaryStream): """The OfficeArtWordDrawing structure specifies information about the drawings in the document.""" def __init__(self, officeArtContent): BinaryStream.__init__(self, officeArtContent.bytes) self.pos = officeArtContent.pos self.officeArtContent = officeArtContent def dump(self): print('' % self.pos) self.printAndSet("dgglbl", self.readuInt8()) msodraw.DgContainer(self, "container").dumpXml(self, getWordModel(self.officeArtContent.mainStream)) print('') self.officeArtContent.pos = self.pos class OfficeArtContent(BinaryStream): """The OfficeArtContent structure specifies information about a drawing in the document.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes) self.pos = mainStream.fcDggInfo self.size = mainStream.lcbDggInfo self.mainStream = mainStream def dump(self): print('' % (self.pos, self.size)) msodraw.DggContainer(self, "DrawingGroupData").dumpXml(self, getWordModel(self.mainStream)) print('' % self.pos) OfficeArtWordDrawing(self).dump() print('') if self.pos < self.mainStream.fcDggInfo + self.size: print('' % self.pos) OfficeArtWordDrawing(self).dump() print('') assert self.pos == self.mainStream.fcDggInfo + self.size print('') class ATNBE(BinaryStream): """The ATNBE structure contains information about an annotation bookmark in the document.""" size = 10 # in bytes, see 2.9.4 def __init__(self, sttbfAtnBkmk): BinaryStream.__init__(self, sttbfAtnBkmk.bytes) self.pos = sttbfAtnBkmk.pos def dump(self): print('') self.printAndSet("bmc", self.readuInt16()) self.printAndSet("ITag", self.readuInt32()) self.printAndSet("ITagOld", self.readuInt32()) print('') class SttbfAtnBkmk(BinaryStream): """The SttbfAtnBkmk structure is an STTB whose strings are all of zero length.""" def __init__(self, mainStream, offset, size): BinaryStream.__init__(self, mainStream.getTableStream().bytes) self.pos = offset self.size = size def dump(self): print('' % (self.pos, self.size)) self.printAndSet("fExtended", self.readuInt16()) self.printAndSet("cData", self.readuInt16()) self.printAndSet("cbExtra", self.readuInt16()) for i in range(self.cData): cchData = self.readuInt16() print('' % (i, self.pos, cchData)) print('' % (i, self.pos, ATNBE.size)) atnbe = ATNBE(self) atnbe.dump() self.pos += ATNBE.size print('') print('') class Stshif(BinaryStream): """The Stshif structure specifies general stylesheet information.""" def __init__(self, bytes, mainStream, offset): BinaryStream.__init__(self, bytes, mainStream=mainStream) self.pos = offset self.size = 18 def dump(self): print('' % (self.pos, self.size)) self.printAndSet("cstd", self.readuInt16()) self.printAndSet("cbSTDBaseInFile", self.readuInt16()) buf = self.readuInt16() self.printAndSet("fStdStylenamesWritten", buf & 1) # first bit self.printAndSet("fReserved", (buf & 0xfe) >> 1) # 2..16th bits self.printAndSet("stiMaxWhenSaved", self.readuInt16()) self.printAndSet("istdMaxFixedWhenSaved", self.readuInt16()) self.printAndSet("nVerBuiltInNamesWhenSaved", self.readuInt16()) self.printAndSet("ftcAsci", self.readuInt16()) self.printAndSet("ftcFE", self.readuInt16()) self.printAndSet("ftcOther", self.readuInt16()) print('') class LSD(BinaryStream): """The LSD structure specifies the properties to be used for latent application-defined styles (see StshiLsd) when they are created.""" def __init__(self, bytes, offset): BinaryStream.__init__(self, bytes) self.pos = offset def dump(self): buf = self.readuInt16() self.printAndSet("fLocked", self.getBit(buf, 1)) self.printAndSet("fSemiHidden", self.getBit(buf, 2)) self.printAndSet("fUnhideWhenUsed", self.getBit(buf, 3)) self.printAndSet("fQFormat", self.getBit(buf, 4)) self.printAndSet("iPriority", (buf & 0xfff0) >> 4) # 5-16th bits self.printAndSet("fReserved", self.readuInt16()) class StshiLsd(BinaryStream): """The StshiLsd structure specifies latent style data for application-defined styles.""" def __init__(self, bytes, stshi, offset): BinaryStream.__init__(self, bytes) self.stshi = stshi self.pos = offset def dump(self): print('' % (self.pos)) self.printAndSet("cbLSD", self.readuInt16()) for i in range(self.stshi.stshif.stiMaxWhenSaved): print('' % i) LSD(self.bytes, self.pos).dump() print('') self.pos += self.cbLSD print('') class STSHI(BinaryStream): """The STSHI structure specifies general stylesheet and related information.""" def __init__(self, bytes, mainStream, offset, size): BinaryStream.__init__(self, bytes, mainStream=mainStream) self.pos = offset self.size = size def dump(self): print('' % (self.pos, self.size)) posOrig = self.pos self.stshif = Stshif(self.bytes, self.mainStream, self.pos) self.stshif.dump() self.pos += self.stshif.size if self.pos - posOrig < self.size: self.printAndSet("ftcBi", self.readuInt16()) if self.pos - posOrig < self.size: stshiLsd = StshiLsd(self.bytes, self, self.pos) stshiLsd.dump() print('') class LPStshi(BinaryStream): """The LPStshi structure specifies general stylesheet information.""" def __init__(self, bytes, mainStream, offset): BinaryStream.__init__(self, bytes, mainStream=mainStream) self.pos = offset def dump(self): print('' % self.pos) self.printAndSet("cbStshi", self.readuInt16(), hexdump=False) self.stshi = STSHI(self.bytes, self.mainStream, self.pos, self.cbStshi) self.stshi.dump() self.pos += self.cbStshi print('') class StdfBase(BinaryStream): """The Stdf structure specifies general information about the style.""" def __init__(self, bytes, mainStream, offset): BinaryStream.__init__(self, bytes, mainStream=mainStream) self.pos = offset self.size = 10 def dump(self): print('' % (self.pos, self.size)) buf = self.readuInt16() self.printAndSet("sti", buf & 0x0fff) # 1..12th bits self.printAndSet("fScratch", self.getBit(buf, 13)) self.printAndSet("fInvalHeight", self.getBit(buf, 14)) self.printAndSet("fHasUpe", self.getBit(buf, 15)) self.printAndSet("fMassCopy", self.getBit(buf, 16)) buf = self.readuInt16() self.stk = buf & 0x000f # 1..4th bits stkmap = { 1: "paragraph", 2: "character", 3: "table", 4: "numbering" } print('' % (self.stk, stkmap[self.stk])) self.printAndSet("istdBase", (buf & 0xfff0) >> 4) # 5..16th bits buf = self.readuInt16() self.printAndSet("cupx", buf & 0x000f) # 1..4th bits self.printAndSet("istdNext", (buf & 0xfff0) >> 4) # 5..16th bits self.printAndSet("bchUpe", self.readuInt16(), hexdump=False) GRFSTD(self).dump() print('') class StdfPost2000(BinaryStream): """The StdfPost2000 structure specifies general information about a style.""" def __init__(self, stdf): BinaryStream.__init__(self, stdf.bytes, mainStream=stdf.mainStream) self.pos = stdf.pos self.size = 8 def dump(self): print('' % (self.pos, self.size)) buf = self.readuInt16() self.printAndSet("istdLink", buf & 0xfff) # 1..12th bits self.printAndSet("fHasOriginalStyle", self.getBit(buf, 13)) # 13th bit self.printAndSet("fSpare", (buf & 0xe000) >> 13) # 14..16th bits self.printAndSet("rsid", self.readuInt32()) buf = self.readuInt16() self.printAndSet("iftcHtml", buf & 0x7) # 1..3rd bits self.printAndSet("unused", self.getBit(buf, 4)) self.printAndSet("iPriority", (buf & 0xfff0) >> 4) # 5..16th bits print('') class Stdf(BinaryStream): """The Stdf structure specifies general information about the style.""" def __init__(self, std): BinaryStream.__init__(self, std.bytes, mainStream=std.mainStream) self.std = std self.pos = std.pos def dump(self): print('' % self.pos) self.stdfBase = StdfBase(self.bytes, self.mainStream, self.pos) self.stdfBase.dump() self.pos += self.stdfBase.size if self.pos - self.std.pos < self.std.size: stsh = self.std.lpstd.stsh # root of the stylesheet table cbSTDBaseInFile = stsh.lpstshi.stshi.stshif.cbSTDBaseInFile print('' % hex(cbSTDBaseInFile)) if cbSTDBaseInFile == 0x0012: stdfPost2000 = StdfPost2000(self) stdfPost2000.dump() self.pos = stdfPost2000.pos print('') print('') class Xst(BinaryStream): """The Xst structure is a string. The string is prepended by its length and is not null-terminated.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos def dump(self): print('' % self.pos) self.printAndSet("cch", self.readuInt16()) lowOnly = locale.getdefaultlocale()[1] == "UTF-8" print('' % globals.encodeName(self.bytes[self.pos:self.pos + 2 * self.cch].decode('utf-16'), lowOnly=lowOnly)) self.pos += 2 * self.cch print('') class Xstz(BinaryStream): """The Xstz structure is a string. The string is prepended by its length and is null-terminated.""" def __init__(self, parent, name="xstz"): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.name = name def dump(self): print('<%s type="Xstz" offset="%d">' % (self.name, self.pos)) xst = Xst(self) xst.dump() self.pos = xst.pos self.printAndSet("chTerm", self.readuInt16()) print('' % self.name) class UpxPapx(BinaryStream): """The UpxPapx structure specifies the paragraph formatting properties that differ from the parent""" def __init__(self, lPUpxPapx): BinaryStream.__init__(self, lPUpxPapx.bytes) self.lPUpxPapx = lPUpxPapx self.pos = lPUpxPapx.pos def dump(self): print('' % self.pos) self.printAndSet("istd", self.readuInt16()) size = self.lPUpxPapx.cbUpx - 2 pos = 0 print('' % (self.pos, size)) while size - pos > 0: prl = Prl(self, self.pos + pos) prl.dump() pos += prl.getSize() print('') print('') class UpxChpx(BinaryStream): """The UpxChpx structure specifies the character formatting properties that differ from the parent""" def __init__(self, lPUpxChpx): BinaryStream.__init__(self, lPUpxChpx.bytes) self.lPUpxChpx = lPUpxChpx self.pos = lPUpxChpx.pos def dump(self): print('' % self.pos) size = self.lPUpxChpx.cbUpx pos = 0 print('' % (self.pos, size)) while size - pos > 0: prl = Prl(self, self.pos + pos) prl.dump() pos += prl.getSize() print('') print('') class UpxTapx(BinaryStream): """The UpxTapx structure specifies the table formatting properties that differ from the parent""" def __init__(self, lPUpxTapx): BinaryStream.__init__(self, lPUpxTapx.bytes) self.lPUpxTapx = lPUpxTapx self.pos = lPUpxTapx.pos def dump(self): print('' % self.pos) size = self.lPUpxTapx.cbUpx pos = 0 print('' % (self.pos, size)) while size - pos > 0: prl = Prl(self, self.pos + pos) prl.dump() pos += prl.getSize() print('') print('') class UPXPadding: """The UPXPadding structure specifies the padding that is used to pad the UpxPapx/Chpx/Tapx structures if any of them are an odd number of bytes in length.""" def __init__(self, parent): self.parent = parent self.pos = parent.pos def pad(self): if self.parent.cbUpx % 2 == 1: self.pos += 1 class LPUpxPapx(BinaryStream): """The LPUpxPapx structure specifies paragraph formatting properties.""" def __init__(self, stkParaGRLPUPX): BinaryStream.__init__(self, stkParaGRLPUPX.bytes) self.pos = stkParaGRLPUPX.pos def dump(self): print('' % self.pos) self.printAndSet("cbUpx", self.readuInt16()) upxPapx = UpxPapx(self) upxPapx.dump() self.pos += self.cbUpx uPXPadding = UPXPadding(self) uPXPadding.pad() self.pos = uPXPadding.pos print('') class LPUpxChpx(BinaryStream): """The LPUpxChpx structure specifies character formatting properties.""" def __init__(self, stkParaGRLPUPX): BinaryStream.__init__(self, stkParaGRLPUPX.bytes) self.pos = stkParaGRLPUPX.pos def dump(self): print('' % self.pos) self.printAndSet("cbUpx", self.readuInt16()) upxChpx = UpxChpx(self) upxChpx.dump() self.pos += self.cbUpx uPXPadding = UPXPadding(self) uPXPadding.pad() self.pos = uPXPadding.pos print('') class LPUpxTapx(BinaryStream): """The LPUpxTapx structure specifies table formatting properties.""" def __init__(self, stkParaGRLPUPX): BinaryStream.__init__(self, stkParaGRLPUPX.bytes) self.pos = stkParaGRLPUPX.pos def dump(self): print('' % self.pos) self.printAndSet("cbUpx", self.readuInt16()) upxTapx = UpxTapx(self) upxTapx.dump() self.pos += self.cbUpx uPXPadding = UPXPadding(self) uPXPadding.pad() self.pos = uPXPadding.pos print('') class StkListGRLPUPX(BinaryStream): """The StkListGRLPUPX structure that specifies the formatting properties for a list style.""" def __init__(self, grLPUpxSw): BinaryStream.__init__(self, grLPUpxSw.bytes) self.grLPUpxSw = grLPUpxSw self.pos = grLPUpxSw.pos def dump(self): print('' % self.pos) lpUpxPapx = LPUpxPapx(self) lpUpxPapx.dump() self.pos = lpUpxPapx.pos print('') class StkTableGRLPUPX(BinaryStream): """The StkTableGRLPUPX structure that specifies the formatting properties for a table style.""" def __init__(self, grLPUpxSw): BinaryStream.__init__(self, grLPUpxSw.bytes) self.grLPUpxSw = grLPUpxSw self.pos = grLPUpxSw.pos def dump(self): print('' % self.pos) lpUpxTapx = LPUpxTapx(self) lpUpxTapx.dump() self.pos = lpUpxTapx.pos lpUpxPapx = LPUpxPapx(self) lpUpxPapx.dump() self.pos = lpUpxPapx.pos lpUpxChpx = LPUpxChpx(self) lpUpxChpx.dump() self.pos = lpUpxChpx.pos print('') class StkCharGRLPUPX(BinaryStream): """The StkCharGRLPUPX structure that specifies the formatting properties for a character style.""" def __init__(self, grLPUpxSw): BinaryStream.__init__(self, grLPUpxSw.bytes) self.grLPUpxSw = grLPUpxSw self.pos = grLPUpxSw.pos self.grLPUpxSw = grLPUpxSw def dump(self): print('' % self.pos) if self.grLPUpxSw.std.stdf.stdfBase.cupx == 1: lpUpxChpx = LPUpxChpx(self) lpUpxChpx.dump() self.pos = lpUpxChpx.pos else: print('') print('') class StkParaGRLPUPX(BinaryStream): """The StkParaGRLPUPX structure that specifies the formatting properties for a paragraph style.""" def __init__(self, grLPUpxSw): BinaryStream.__init__(self, grLPUpxSw.bytes) self.grLPUpxSw = grLPUpxSw self.pos = grLPUpxSw.pos self.grLPUpxSw = grLPUpxSw def dump(self): print('' % self.pos) if self.grLPUpxSw.std.stdf.stdfBase.cupx == 2: lPUpxPapx = LPUpxPapx(self) lPUpxPapx.dump() self.pos = lPUpxPapx.pos lpUpxChpx = LPUpxChpx(self) lpUpxChpx.dump() self.pos = lpUpxChpx.pos else: print('') print('') class GrLPUpxSw(BinaryStream): """The GrLPUpxSw structure is an array of variable-size structures that specify the formatting of the style.""" def __init__(self, std): BinaryStream.__init__(self, std.bytes) self.std = std self.pos = std.pos def dump(self): stkMap = { 1: StkParaGRLPUPX, 2: StkCharGRLPUPX, 3: StkTableGRLPUPX, 4: StkListGRLPUPX } child = stkMap[self.std.stdf.stdfBase.stk](self) child.dump() self.pos = child.pos class STD(BinaryStream): """The STD structure specifies a style definition.""" def __init__(self, lpstd): BinaryStream.__init__(self, lpstd.bytes, mainStream=lpstd.mainStream) self.lpstd = lpstd self.pos = lpstd.pos self.posOrig = self.pos self.size = lpstd.cbStd def dump(self): print('' % (self.pos, self.size)) self.stdf = Stdf(self) self.stdf.dump() self.pos = self.stdf.pos if self.pos - self.posOrig < self.size: xstzName = Xstz(self) xstzName.dump() self.pos = xstzName.pos grLPUpxSw = GrLPUpxSw(self) grLPUpxSw.dump() self.pos = grLPUpxSw.pos print('') class LPStd(BinaryStream): """The LPStd structure specifies a length-prefixed style definition.""" def __init__(self, stsh): BinaryStream.__init__(self, stsh.bytes, mainStream=stsh.mainStream) self.stsh = stsh self.pos = stsh.pos def dump(self): self.printAndSet("cbStd", self.readuInt16()) posOrig = self.pos if self.cbStd > 0: std = STD(self) std.dump() self.pos = std.pos self.pos = posOrig + self.cbStd class STSH(BinaryStream): """The STSH structure specifies the stylesheet for a document.""" def __init__(self, bytes, mainStream, offset, size): BinaryStream.__init__(self, bytes, mainStream=mainStream) self.pos = offset self.size = size def dump(self): print('' % (self.pos, self.size)) self.lpstshi = LPStshi(self.bytes, self.mainStream, self.pos) self.lpstshi.dump() self.pos = self.lpstshi.pos for i in range(self.lpstshi.stshi.stshif.cstd): print('' % (i, self.pos)) lpstd = LPStd(self) lpstd.dump() self.pos = lpstd.pos print('') print('') class Rca(BinaryStream): """The Rca structure is used to define the coordinates of a rectangular area in the document.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = parent.pos def dump(self): print('' % self.pos) self.printAndSet("left", self.readuInt32()) self.printAndSet("top", self.readuInt32()) self.printAndSet("right", self.readuInt32()) self.printAndSet("bottom", self.readuInt32()) print('') self.parent.pos = self.pos class SPA(BinaryStream): """The Spa structure specifies information about the shapes and drawings that the document contains.""" size = 26 # defined by 2.8.37 def __init__(self, parent, offset): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = offset def dump(self): pos = self.pos print('' % (self.pos, SPA.size)) self.printAndSet("lid", self.readuInt32()) Rca(self).dump() buf = self.readuInt16() self.printAndSet("fHdr", self.getBit(buf, 0)) # 1st bit self.printAndSet("bx", (buf & 0x6) >> 1) # 2..3rd bits self.printAndSet("by", (buf & 0x18) >> 3) # 4..5th bits self.printAndSet("wr", (buf & 0x1e0) >> 5) # 6..9th bits self.printAndSet("wrk", (buf & 0x1e00) >> 9) # 10..13th bits self.printAndSet("fRcaSimple", self.getBit(buf, 13)) # 14th bit self.printAndSet("fBelowText", self.getBit(buf, 14)) # 15th bit self.printAndSet("fAnchorLock", self.getBit(buf, 15)) # 16th bit self.printAndSet("cTxbx", self.readuInt32()) print('') assert pos + SPA.size == self.pos class SPLS(BinaryStream): """The SPLS structure specifies the current state of a range of text with regard to one of the language checking features.""" size = 2 # defined by 2.9.253 def __init__(self, name, plcfSpl, offset): BinaryStream.__init__(self, plcfSpl.bytes) self.name = name self.plcfSpl = plcfSpl self.pos = offset def dump(self): splfMap = { 0x1: "splfPending", 0x2: "splfMaybeDirty", 0x3: "splfDirty", 0x4: "splfEdit", 0x5: "splfForeign", 0x7: "splfClean", 0x8: "splfNoLAD", 0xA: "splfErrorMin", 0xB: "splfRepeatWord", 0xC: "splfUnknownWord", } buf = self.readuInt16() print('' % (self.pos, SPLS.size, hex(buf))) self.printAndSet("splf", buf & 0x000f, end=False) # 1..4th bits if self.splf in splfMap: print('' % splfMap[self.splf]) print('') self.printAndSet("fError", self.getBit(buf, 4)) self.printAndSet("fExtend", self.getBit(buf, 5)) self.printAndSet("fTypo", self.getBit(buf, 6)) self.printAndSet("unused", (buf & 0xff80) >> 7) # 8..16th bits print('') class PlcfSpl(BinaryStream, PLC): """The Plcfspl structure is a Plc structure whose data elements are SpellingSpls structures.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) PLC.__init__(self, mainStream.lcbPlcfSpl, 2) # 2 is defined by 2.8.28 self.pos = mainStream.fcPlcfSpl self.size = mainStream.lcbPlcfSpl def dump(self): print('' % (self.pos, self.size)) pos = self.pos for i in range(self.getElements()): # aCp start = self.getuInt32(pos=pos) end = self.getuInt32(pos=pos + 4) print('' % (i, start, end)) pos += 4 # aSpellingSpls aSpellingSpls = SPLS("SpellingSpls", self, self.getOffset(self.pos, i)) aSpellingSpls.dump() print('' % self.quoteAttr(self.mainStream.retrieveCPs(start, end))) print('') print('') class FTXBXNonReusable(BinaryStream): """The FTXBXNonReusable structure is used within the FTXBXS structure when that structure describes a real textbox. A real textbox is any shape object into which text is added, and that is the first or only shape in a linked chain.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = parent.pos def dump(self): print('' % (self.pos)) self.printAndSet("cTxbx", self.readuInt32()) self.printAndSet("cTxbxEdit", self.readuInt32()) print('') self.parent.pos = self.pos class FTXBXSReusable(BinaryStream): """The FTXBXSReusable structure is used within the FTXBXS structure when it describes a spare structure that can be reused by the application and converted into an actual textbox.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = parent.pos def dump(self): print('' % (self.pos)) self.printAndSet("iNextReuse", self.readuInt32()) self.printAndSet("cReusable", self.readuInt32()) print('') self.parent.pos = self.pos class FTXBXS(BinaryStream): """Associates ranges of text from the Textboxes Document and the Header Textboxes Document, with shape objects.""" size = 22 # 2.8.32 def __init__(self, parent, offset): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = self.posOrig = offset def dump(self): print('' % (self.pos, FTXBXS.size)) self.fReusable = self.getuInt16(pos=self.pos + 8) if self.fReusable: FTXBXSReusable(self).dump() else: FTXBXNonReusable(self).dump() self.printAndSet("fReusable", self.readuInt16()) self.printAndSet("itxbxsDest", self.readuInt32()) self.printAndSet("lid", self.readuInt32()) self.printAndSet("txidUndo", self.readuInt32()) print('') if not self.fReusable: assert self.posOrig + FTXBXS.size == self.pos class PlcftxbxTxt(BinaryStream, PLC): """Specifies which ranges of text are contained in which textboxes.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) PLC.__init__(self, mainStream.lcbPlcftxbxTxt, FTXBXS.size) self.pos = mainStream.fcPlcftxbxTxt self.size = mainStream.lcbPlcftxbxTxt def dump(self): print('' % (self.pos, self.size)) offset = self.mainStream.getHeaderOffset() pos = self.pos for i in range(self.getElements() - 1): # aCp start = self.getuInt32(pos=pos) end = self.getuInt32(pos=pos + 4) print('' % (i, start, end)) pos += 4 # aFTXBXS aFTXBXS = FTXBXS(self, self.getOffset(self.pos, i)) aFTXBXS.dump() print('' % self.quoteAttr(self.mainStream.retrieveCPs(offset + start, offset + end))) print('') print('') class Tbkd(BinaryStream): """The Tbkd structure is used by the PlcftxbxBkd and PlcfTxbxHdrBkd structures to associate ranges of text from the Textboxes Document and the Header Textboxes Document with FTXBXS objects.""" size = 6 # 2.9.309 def __init__(self, parent, offset): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = self.posOrig = offset def dump(self): print('' % (self.pos, Tbkd.size)) self.printAndSet("itxbxs", self.readuInt16()) self.printAndSet("dcpDepend", self.readuInt16()) buf = self.readuInt16() self.printAndSet("reserved1", buf & 0x03ff) # 1..10th bits self.printAndSet("fMarkDelete", self.getBit(buf, 10)) self.printAndSet("fUnk", self.getBit(buf, 11)) self.printAndSet("fTextOverflow", self.getBit(buf, 12)) self.printAndSet("reserved2", (buf & 0xe000) >> 13) # 14..16th bits print('') assert self.posOrig + Tbkd.size == self.pos class PlcftxbxBkd(BinaryStream, PLC): """Specifies which ranges of text go inside which textboxes.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) PLC.__init__(self, mainStream.lcbPlcfTxbxBkd, 6) self.pos = mainStream.fcPlcfTxbxBkd self.size = mainStream.lcbPlcfTxbxBkd def dump(self): print('' % (self.pos, self.size)) offset = self.mainStream.getHeaderOffset() pos = self.pos for i in range(self.getElements()): # aCp start = self.getuInt32(pos=pos) end = self.getuInt32(pos=pos + 4) print('' % (i, start, end)) pos += 4 # aTbkd Tbkd(self, self.getOffset(self.pos, i)).dump() print('' % self.quoteAttr(self.mainStream.retrieveCPs(offset + start, offset + end))) print('') print('') class PlcfSpa(BinaryStream, PLC): """The PlcfSpa structure is a PLC structure in which the data elements are SPA structures.""" def __init__(self, mainStream, pos, size): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) PLC.__init__(self, size, 26) # 2.8.37 self.pos = pos self.size = size def dump(self): print('' % (self.pos, self.size)) pos = self.pos for i in range(self.getElements()): # aCp start = self.getuInt32(pos=pos) end = self.getuInt32(pos=pos + 4) print('' % (i, start, end)) pos += 4 # aSpa aSpa = SPA(self, self.getOffset(self.pos, i)) aSpa.dump() print('' % self.quoteAttr(self.mainStream.retrieveCPs(start, end))) print('') print('') class PlcfGram(BinaryStream, PLC): """The PlcfGram structure is a Plc structure whose data elements are GrammarSpls structures.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) PLC.__init__(self, mainStream.lcbPlcfGram, 2) # 2 is defined by 2.8.21 self.pos = mainStream.fcPlcfGram self.size = mainStream.lcbPlcfGram def dump(self): print('' % (self.pos, self.size)) pos = self.pos for i in range(self.getElements()): # aCp start = self.getuInt32(pos=pos) end = self.getuInt32(pos=pos + 4) print('' % (i, start, end)) pos += 4 # aGrammarSpls aGrammarSpls = SPLS("GrammarSpls", self, self.getOffset(self.pos, i)) aGrammarSpls.dump() print('' % self.quoteAttr(self.mainStream.retrieveCPs(start, end))) print('') print('') class Grfhic(BinaryStream): """The grfhic structure is a set of HTML incompatibility flags that specify the HTML incompatibilities of a list structure.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.pos = parent.pos self.parent = parent def dump(self): print('') buf = self.readuInt8() self.printAndSet("fhicChecked", self.getBit(buf, 0)) self.printAndSet("fhicFormat", self.getBit(buf, 1)) self.printAndSet("fhicListText", self.getBit(buf, 2)) self.printAndSet("fhicPeriod", self.getBit(buf, 3)) self.printAndSet("fhicLeft1", self.getBit(buf, 4)) self.printAndSet("fhicListTab", self.getBit(buf, 5)) self.printAndSet("unused", self.getBit(buf, 6)) self.printAndSet("fhicBullet", self.getBit(buf, 7)) self.parent.pos = self.pos print('') class LSTF(BinaryStream): """The LSTF structure contains formatting properties that apply to an entire list.""" def __init__(self, plfLst, index): BinaryStream.__init__(self, plfLst.bytes) self.pos = plfLst.pos self.size = 28 self.index = index def dump(self): print('' % (self.index, self.pos, self.size)) self.printAndSet("lsid", self.readInt32()) self.printAndSet("tplc", self.readInt32()) for i in range(9): print('' % (i, self.readInt16())) buf = self.readuInt8() self.printAndSet("fSimpleList", self.getBit(buf, 0)) self.printAndSet("unused1", self.getBit(buf, 1)) self.printAndSet("fAutoNum", self.getBit(buf, 2)) self.printAndSet("unused2", self.getBit(buf, 3)) self.printAndSet("fHybrid", self.getBit(buf, 4)) self.printAndSet("reserved1", (buf & 0xe0) >> 5) # 6..8th bits Grfhic(self).dump() print('') class LVLF(BinaryStream): """The LVLF structure contains formatting properties for an individual level in a list.""" def __init__(self, lvl): BinaryStream.__init__(self, lvl.bytes) self.pos = lvl.pos def dump(self): print('' % self.pos) self.printAndSet("iStartAt", self.readInt32()) self.printAndSet("nfc", self.readuInt8()) buf = self.readuInt8() self.printAndSet("jc", buf & 0x3) # 1..2nd bits self.printAndSet("fLegal", self.getBit(buf, 2)) self.printAndSet("fNoRestart", self.getBit(buf, 3)) self.printAndSet("fIndentSav", self.getBit(buf, 4)) self.printAndSet("fConverted", self.getBit(buf, 5)) self.printAndSet("unused1", self.getBit(buf, 6)) self.printAndSet("fTentative", self.getBit(buf, 7)) for i in range(9): print('' % (i, self.readuInt8())) self.printAndSet("ixchFollow", self.readuInt8()) self.printAndSet("dxaIndentSav", self.readInt32()) self.printAndSet("unused2", self.readuInt32()) self.printAndSet("cbGrpprlChpx", self.readuInt8()) self.printAndSet("cbGrpprlPapx", self.readuInt8()) self.printAndSet("ilvlRestartLim", self.readuInt8()) Grfhic(self).dump() print('') class LVL(BinaryStream): """The LVL structure contains formatting information about a specific level in a list.""" def __init__(self, plfLst, index): BinaryStream.__init__(self, plfLst.bytes) self.pos = plfLst.pos self.index = index def dump(self): print('' % (self.index, self.pos)) lvlf = LVLF(self) lvlf.dump() self.pos = lvlf.pos print('' % self.pos) pos = self.pos while (lvlf.cbGrpprlPapx - (pos - self.pos)) > 0: prl = Prl(self, pos) prl.dump() pos += prl.getSize() self.pos = pos print('') print('' % self.pos) pos = self.pos while (lvlf.cbGrpprlChpx - (pos - self.pos)) > 0: prl = Prl(self, pos) prl.dump() pos += prl.getSize() self.pos = pos print('') xst = Xst(self) xst.dump() self.pos = xst.pos print('') class PlfLst(BinaryStream): """The PlfLst structure contains the list formatting information for the document.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) self.pos = mainStream.fcPlfLst self.size = mainStream.lcbPlfLst def dump(self): print('' % (self.pos, self.size)) self.printAndSet("cLst", self.readInt16()) cLvl = 0 for i in range(self.cLst): rgLstf = LSTF(self, i) rgLstf.dump() if rgLstf.fSimpleList: cLvl += 1 else: cLvl += 9 self.pos = rgLstf.pos for i in range(cLvl): lvl = LVL(self, i) lvl.dump() self.pos = lvl.pos print('') class LFO(BinaryStream): """The LFO structure specifies the LSTF element that corresponds to a list that contains a paragraph.""" def __init__(self, plfLfo, name, index): BinaryStream.__init__(self, plfLfo.bytes) self.pos = plfLfo.pos self.name = name self.index = index def dump(self): print('<%s type="LFO" index="%s" offset="%d">' % (self.name, self.index, self.pos)) self.printAndSet("lsid", self.readInt32()) self.printAndSet("unused1", self.readuInt32()) self.printAndSet("unused2", self.readuInt32()) self.printAndSet("clfolvl", self.readuInt8()) self.printAndSet("ibstFltAutoNum", self.readuInt8()) Grfhic(self).dump() self.printAndSet("unused3", self.readuInt8()) print('' % self.name) class LFOData(BinaryStream): """The LFOData structure contains the Main Document CP of the corresponding LFO.""" def __init__(self, plfLfo, lfo): BinaryStream.__init__(self, plfLfo.bytes) self.pos = plfLfo.pos self.lfo = lfo def dump(self): print('' % self.pos) self.printAndSet("cp", self.readuInt32()) if self.lfo.clfolvl > 0: print('') print('') class PlfLfo(BinaryStream): """The PlfLfo structure contains the list format override data for the document.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) self.pos = mainStream.fcPlfLfo self.size = mainStream.lcbPlfLfo def dump(self): print('' % (self.pos, self.size)) self.printAndSet("lfoMac", self.readInt32()) lfos = [] for i in range(self.lfoMac): lfo = LFO(self, "rgLfo", i) lfos.append(lfo) lfo.dump() self.pos = lfo.pos for i in range(self.lfoMac): lfoData = LFOData(self, lfos[i]) lfoData.dump() self.pos = lfoData.pos print('') class SttbListNames(BinaryStream): """The SttbListNames structure is an STTB structure whose strings are the names used by the LISTNUM field.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) self.pos = mainStream.fcSttbListNames self.size = mainStream.lcbSttbListNames def dump(self): print('' % (self.pos, self.size)) self.printAndSet("fExtend", self.readuInt16()) self.printAndSet("cData", self.readuInt16()) self.printAndSet("cbExtra", self.readuInt16()) for i in range(self.cData): cchData = self.readuInt16() print('' % (i, self.pos, cchData)) print('' % globals.encodeName(self.bytes[self.pos:self.pos + 2 * cchData].decode('utf-16'), lowOnly=True)) self.pos += 2 * cchData print('') print('') class PBString(BinaryStream): """Specified by [MS-OSHARED] 2.3.4.5, specifies a null-terminated string.""" def __init__(self, parent, name, index=None): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = parent.pos self.name = name self.index = index def dump(self): if self.index is None: print('<%s type="PBString">' % self.name) else: print('<%s type="PBString" index="%s">' % (self.name, self.index)) buf = self.readuInt16() self.printAndSet("cch", buf & 0x7fff) # bits 1..15 self.printAndSet("fAnsiString", self.getBit(buf, 15)) bytes = [] if self.fAnsiString: cch = self.cch else: cch = self.cch * 2 for dummy in range(cch): c = self.readuInt8() bytes.append(c) if self.fAnsiString == 1: encoding = "ascii" else: encoding = "utf-16" self.printAndSet("rgxch", globals.encodeName("".join(map(lambda c: chr(c), bytes)).decode(encoding), lowOnly=True).encode('utf-8'), hexdump=False) print('' % self.name) self.parent.pos = self.pos class FactoidType(BinaryStream): """Specified by [MS-OSHARED] 2.3.4.2, specifies the type of smart tag.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = parent.pos def dump(self): print('') self.printAndSet("cbFactoid", self.readuInt32()) self.printAndSet("id", self.readuInt32()) self.rgbUri = PBString(self, "rgbUri") self.rgbUri.dump() self.rgbTag = PBString(self, "rgbTag") self.rgbTag.dump() self.rgbDownLoadURL = PBString(self, "rgbDownLoadURL") self.rgbDownLoadURL.dump() print('') self.parent.pos = self.pos class PropertyBagStore(BinaryStream): """Specified by [MS-OSHARED] 2.3.4.1, specifies the shared data for the smart tags embedded in the document.""" def __init__(self, parent): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = parent.pos def dump(self): print('' % self.pos) self.printAndSet("cFactoidType", self.readuInt32()) print('') self.factoidTypes = [] for i in range(self.cFactoidType): factoidType = FactoidType(self) factoidType.dump() self.factoidTypes.append(factoidType) print('') self.printAndSet("cbHdr", self.readuInt16()) assert self.cbHdr == 0xc self.printAndSet("sVer", self.readuInt16()) assert self.sVer == 0x0100 self.printAndSet("cfactoid", self.readuInt32()) self.printAndSet("cste", self.readuInt32()) print('') self.stringTable = [] for i in range(self.cste): string = PBString(self, "stringTable", index=i) string.dump() self.stringTable.append(string) print('') print('') self.parent.pos = self.pos class Property(BinaryStream): """Specified by [MS-OSHARED] 2.3.4.4, specifies the indexes into the string table entries of the stringTable field.""" def __init__(self, parent, index): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = parent.pos self.index = index def dump(self): print('' % (self.pos, self.index)) self.printAndSet("keyIndex", self.readuInt32(), hexdump=False) self.printAndSet("valueIndex", self.readuInt32(), hexdump=False) print('') self.parent.pos = self.pos class PropertyBag(BinaryStream): """Specified by [MS-OSHARED] 2.3.4.3, specifies the smart tag data.""" def __init__(self, parent, index): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = parent.pos self.index = index def dump(self): print('' % (self.pos, self.index)) self.printAndSet("id", self.readuInt16()) self.printAndSet("cProp", self.readuInt16()) self.printAndSet("cbUnknown", self.readuInt16()) for i in range(self.cProp): Property(self, i).dump() print('') self.parent.pos = self.pos class SmartTagData(BinaryStream): """Specified by [MS-DOC] 2.9.251, stores information about all the smart tags in the document.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) self.pos = mainStream.fcFactoidData self.size = mainStream.lcbFactoidData def dump(self): posOrig = self.pos print('' % (self.pos, self.size)) self.propBagStore = PropertyBagStore(self) self.propBagStore.dump() i = 0 while self.pos < posOrig + self.size: self.propBag = PropertyBag(self, i) self.propBag.dump() i += 1 print('') class SttbSavedBy(BinaryStream): """The SttbSavedBy structure is an STTB structure that specifies the save history of this document.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes, mainStream=mainStream) self.pos = mainStream.fcSttbSavedBy self.size = mainStream.lcbSttbSavedBy def dump(self): print('' % (self.pos, self.size)) self.printAndSet("fExtend", self.readuInt16()) self.printAndSet("cData", self.readuInt16()) self.printAndSet("cbExtra", self.readuInt16()) for i in range(self.cData): cchData = self.readuInt16() print('' % (i, self.pos, cchData)) print('' % globals.encodeName(self.bytes[self.pos:self.pos + 2 * cchData].decode('utf-16'), lowOnly=True)) self.pos += 2 * cchData print('') # Probably this was cleared manually. if self.cData != 0: assert self.pos == self.mainStream.fcSttbSavedBy + self.size print('') class SttbfBkmk(BinaryStream): """The SttbfBkmk structure is an STTB structure whose strings specify the names of bookmarks.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes) self.pos = mainStream.fcSttbfBkmk self.size = mainStream.lcbSttbfBkmk self.mainStream = mainStream def dump(self): print('' % (self.pos, self.size)) self.printAndSet("fExtended", self.readuInt16()) self.printAndSet("cData", self.readuInt16()) self.printAndSet("cbExtra", self.readuInt16()) for i in range(self.cData): cchData = self.readuInt16() print('' % (i, self.pos, cchData)) print('' % globals.encodeName(self.bytes[self.pos:self.pos + 2 * cchData].decode('utf-16'), lowOnly=True)) self.pos += 2 * cchData print('') assert self.pos == self.mainStream.fcSttbfBkmk + self.size print('') # The FTO enumerated type identifies the feature that is responsible to create # a given smart tag in a document. FTO = { 0x0000: "ftoUnknown", 0x0001: "ftoGrammar", 0x0002: "ftoScanDll", 0x0003: "ftoVB" } class FACTOIDINFO(BinaryStream): """Specified by [MS-DOC] 2.9.66, contains information about a smart tag bookmark in the document.""" def __init__(self, parent, index): BinaryStream.__init__(self, parent.bytes) self.parent = parent self.pos = parent.pos self.index = index def dump(self): print('' % self.index) self.printAndSet("dwId", self.readuInt32()) buf = self.readuInt16() self.printAndSet("fSubEntry", self.getBit(buf, 0)) self.printAndSet("fUnused", (buf & 0xfffe) >> 1) # 2..16th bits self.printAndSet("fto", self.readuInt16(), dict=FTO) self.printAndSet("pfpb", self.readuInt32()) print('') self.parent.pos = self.pos class SttbfBkmkFactoid(BinaryStream): """Specified by [MS-DOC] 2.9.281, an STTB whose strings are FACTOIDINFO structures.""" def __init__(self, mainStream): BinaryStream.__init__(self, mainStream.getTableStream().bytes) self.pos = mainStream.fcSttbfBkmkFactoid self.size = mainStream.lcbSttbfBkmkFactoid self.mainStream = mainStream def dump(self): print('' % (self.pos, self.size)) self.printAndSet("fExtended", self.readuInt16()) assert self.fExtended == 0xffff self.printAndSet("cData", self.readuInt16()) self.printAndSet("cbExtra", self.readuInt16()) assert self.cbExtra == 0 for i in range(self.cData): self.printAndSet("cchData", self.readuInt16()) assert self.cchData == 0x6 FACTOIDINFO(self, i).dump() assert self.pos == self.mainStream.fcSttbfBkmkFactoid + self.size print('') # vim:set filetype=python shiftwidth=4 softtabstop=4 expandtab: