src/docrecord.py | 139 ++++++++++++++++++++++++++++++++++++++++++++++----- src/msodraw.py | 113 ++++++++++++++++++++++++++++++++++++++++- test/doc/picture.doc |binary test/doc/test.py | 11 ++++ 4 files changed, 250 insertions(+), 13 deletions(-)
New commits: commit 791c8e3aefaf5ea4c15900bc2724564b8e616d0d Author: Miklos Vajna <vmik...@suse.cz> Date: Fri Jul 19 12:58:07 2013 +0200 msodraw: dump BlipPng diff --git a/src/msodraw.py b/src/msodraw.py index 5e84489..8126ab9 100644 --- a/src/msodraw.py +++ b/src/msodraw.py @@ -73,6 +73,7 @@ class RecordHeader: FClientAnchor = 0xF010 FClientData = 0xF011 FConnectorRule = 0xF012 + BlipPNG = 0xF01E FDGSL = 0xF119 SplitMenuColorContainer = 0xF11E TertiaryFOPT = 0xF122 @@ -94,6 +95,7 @@ class RecordHeader: Type.FSP: 'OfficeArtFSP', Type.FSPGR: 'OfficeArtFSPGR', Type.FConnectorRule: 'OfficeArtFConnectorRule', + Type.BlipPNG: 'OfficeArtBlipPng', Type.FDGSL: 'OfficeArtFDGSL', Type.SplitMenuColorContainer: 'OfficeArtSplitMenuColorContainer' } @@ -304,6 +306,34 @@ class FDGSL: for shape in self.shapesSelected: recHdl.appendLine(" ID of shape selected: %d"%shape) +class BlipPNG: + def __init__(self, strm): + self.strm = strm + + def __parseBytes(self, rh): + pos = self.strm.pos + self.rgbUid1 = self.strm.readBytes(16) + if rh.recInstance == 0x06E1: + self.rgbUid2 = self.strm.readBytes(16) + else: + self.rgbUid2 = None + self.tag = self.strm.readUnsignedInt(1) + header = self.strm.pos - pos + data = rh.recLen - header + self.BLIPFileData = self.strm.readBytes(data) + + def appendLines(self, recHdl, rh): + pass + + def dumpXml(self, recHdl, model, rh): + recHdl.appendLine('<blipPng type="OfficeArtBlipPng">') + self.__parseBytes(rh) + recHdl.appendLine('<rgbUid1 value="%s"/>' % hexdump(self.rgbUid1)) + if self.rgbUid2: + recHdl.appendLine('<rgbUid2 value="%s"/>' % hexdump(self.rgbUid2)) + recHdl.appendLine('<tag value="%s"/>' % self.tag) + recHdl.appendLine('<BLIPFileData value="%s"/>' % hexdump(self.BLIPFileData)) + recHdl.appendLine('</blipPng>') class FOPT: """property table for a shape instance""" @@ -1227,6 +1257,7 @@ recData = { RecordHeader.Type.FDGGBlock: FDGGBlock, RecordHeader.Type.FConnectorRule: FConnectorRule, RecordHeader.Type.FDGSL: FDGSL, + RecordHeader.Type.BlipPNG: BlipPNG, RecordHeader.Type.FClientAnchor: FClientAnchorSheet, RecordHeader.Type.FClientData: FClientData, RecordHeader.Type.FClientTextbox: FClientTextbox, diff --git a/test/doc/picture.doc b/test/doc/picture.doc new file mode 100644 index 0000000..78c8aa7 Binary files /dev/null and b/test/doc/picture.doc differ diff --git a/test/doc/test.py b/test/doc/test.py index 97951cb..da0de0a 100755 --- a/test/doc/test.py +++ b/test/doc/test.py @@ -185,6 +185,17 @@ class Test(unittest.TestCase): def test_abi1157(self): self.dump('abi1157-1') + def test_picture(self): + self.dump('picture') + + runs = self.getRuns() + self.assertEqual(3, len(runs)) + + # make sure the correct PNG data is dumped + expected = "89504e470d0a1a0a0000000d4948445200000010000000100802000000909168360000015049444154789c9592c14a02511486bf99714ccb322d7521140541cb6a11448b164150fb8a363d41f4083d40cba0655044d0a637a837682fd1a6a2488b10b23475bcb77b671c491dc1cee23077e67cf7fcff39139252f29f08b59e3e1dae8b4c45998ff501a82e070f5cbd3366733acb5c6fa609fc0872651236df0deeca7d002a6cc33d1b941a146ab49ca937e37610e0c590c5c92b67f926a07243b293613f8b1108a8a84aadb01575c9799edd0c895010a0ae71048e77b99b6a92e53861a387a48a6033c5d208c297a43ca8a3697601d217b010632dd9a9f34be09968021698bea4c76ab72f5dd0d6216c3211e1bec2a0c5e59bce9303baa770c7bd38aca7d729692bcd4d512b53bb3b7cc2f45dd604ab098e67b499366025ce5e96a317fd2162e2d76bbbb725bdcd80b12a603aca4581e7aade97e14ec2916ca719ed96e4c54692f5241f755de7019641eacfaff10b469261dc6a800dd30000000049454e44ae426082" + actual = runs[1].findall('chpx/prl[@index="0"]/sprm/PICFAndOfficeArtData/inlineSpContainer/fbse/blipPng/BLIPFileData')[0].attrib['value'] + self.assertEqual(expected, actual) + if __name__ == '__main__': unittest.main() commit 787b518be36118741204d89905c0d61719f7ced9 Author: Miklos Vajna <vmik...@suse.cz> Date: Fri Jul 19 13:06:33 2013 +0200 add index to Prl dumper diff --git a/src/docrecord.py b/src/docrecord.py index 9d0d027..b73fba4 100644 --- a/src/docrecord.py +++ b/src/docrecord.py @@ -978,15 +978,19 @@ class Sprm(DOCDirStream): class Prl(DOCDirStream): """The Prl structure is a Sprm that is followed by an operand.""" - def __init__(self, bytes, offset, mainStream = None, transformed = None): + def __init__(self, bytes, offset, mainStream = None, transformed = None, index = None): DOCDirStream.__init__(self, bytes) self.pos = offset self.posOrig = self.pos self.sprm = Sprm(self.bytes, self.pos, mainStream, transformed) self.pos += 2 + self.index = index def dump(self): - print '<prl type="Prl" offset="%d">' % self.posOrig + indexstr = "" + if self.index != None: + indexstr = ' index="%d"' % self.index + print '<prl type="Prl" offset="%d"%s>' % (self.posOrig, indexstr) self.sprm.dump() print '</prl>' @@ -1022,10 +1026,12 @@ class Chpx(DOCDirStream): print '<chpx type="Chpx" offset="%d">' % self.pos self.printAndSet("cb", self.readuInt8()) pos = self.pos + index = 0 while (self.cb - (pos - self.pos)) > 0: - prl = Prl(self.bytes, pos, self.mainStream, self.transformed) + prl = Prl(self.bytes, pos, self.mainStream, self.transformed, index) prl.dump() pos += prl.getSize() + index += 1 print '</chpx>' class PapxInFkp(DOCDirStream): commit 566624c10883396e239a20ac87e5f3ac5b5ce8a4 Author: Miklos Vajna <vmik...@suse.cz> Date: Fri Jul 19 12:38:07 2013 +0200 FBSE: handle non-empty embeddedBlip diff --git a/src/msodraw.py b/src/msodraw.py index 0badb4f..5e84489 100644 --- a/src/msodraw.py +++ b/src/msodraw.py @@ -1049,7 +1049,14 @@ class FBSE: if self.cbName != 0: recHdl.appendLine('<todo what="FBSE::dumpXml(): cbName != 0"/>') if self.strm.pos < self.posOrig + rh.recLen: - recHdl.appendLine('<todo what="FBSE::dumpXml(): non-empty embeddedBlip"/>') + rh = RecordHeader(self.strm) + rh.dumpXml(recHdl) + if rh.recType in recData: + child = recData[rh.recType](self.strm) + child.dumpXml(self.strm, model, rh) + else: + recHdl.appendLine('<todo what="FBSE::dumpXml(): recType = %s unhandled (size: %d bytes)"/>' % (hex(rh.recType), rh.recLen)) + self.strm.pos += rh.recLen recHdl.appendLine('</fbse>') class FClientAnchorSheet: commit 0f002aabf189d479bf62bec803175342ee45ad73 Author: Miklos Vajna <vmik...@suse.cz> Date: Fri Jul 19 11:46:18 2013 +0200 msodraw: dump InlineSpContainer diff --git a/src/docrecord.py b/src/docrecord.py index 93e46ac..9d0d027 100644 --- a/src/docrecord.py +++ b/src/docrecord.py @@ -753,7 +753,8 @@ class PICFAndOfficeArtData(DOCDirStream): assert self.pos == pos + 68 if picf.mfpf.mm == 0x0066: print '<todo what="PICFAndOfficeArtData::dump(): picf.mfpf.mm == MM_SHAPEFILE is unhandled"/>' - # TODO dump OfficeArtInlineSpContainer + remaining = picf.lcb - (self.pos - pos) + msodraw.InlineSpContainer(self, remaining).dumpXml(self, globals.ModelBase(globals.ModelBase.HostAppType.Word)) print '</PICFAndOfficeArtData>' # The TextFlow enumeration specifies the rotation settings for a block of text and for the individual diff --git a/src/msodraw.py b/src/msodraw.py index 6b46aa3..0badb4f 100644 --- a/src/msodraw.py +++ b/src/msodraw.py @@ -963,6 +963,7 @@ class BStoreContainerFileBlock: child.dumpXml(self.strm, model, rh) else: recHdl.appendLine('<todo what="BStoreContainerFileBlock: recType = %s unhandled (size: %d bytes)"/>' % (hex(rh.recType), rh.recLen)) + self.strm.pos += rh.recLen class BStoreContainer: def __init__ (self, strm): @@ -1181,6 +1182,21 @@ class DgContainer(MSODrawHandler): def __init__(self, officeArtContent, name): MSODrawHandler.__init__(self, officeArtContent.bytes, officeArtContent, name, "OfficeArtDgContainer") +class InlineSpContainer: + """The OfficeArtInlineSpContainer record specifies a container for inline shapes.""" + def __init__(self, officeArtContent, size): + self.strm = officeArtContent + self.size = size + + def dumpXml (self, recHdl, model): + recHdl.appendLine('<inlineSpContainer>') + pos = self.strm.pos + shape = SpContainer(self.strm) + shape.dumpXml(recHdl, model) + while self.size > self.strm.pos - pos: + bStoreContainerFileBlock = BStoreContainerFileBlock(self) + bStoreContainerFileBlock.dumpXml(recHdl, model) + recHdl.appendLine('</inlineSpContainer>') class SpContainer(MSODrawHandler): """The OfficeArtSpContainer record specifies a shape container.""" commit 50e25edf526e921951c5d48dc1115fc0964f93d0 Author: Miklos Vajna <vmik...@suse.cz> Date: Fri Jul 19 11:23:22 2013 +0200 finish dumping PICFAndOfficeArtData diff --git a/src/docrecord.py b/src/docrecord.py index 03be1e5..93e46ac 100644 --- a/src/docrecord.py +++ b/src/docrecord.py @@ -729,7 +729,8 @@ class PICF(DOCDirStream): self.printAndSet("lcb", self.readInt32()) self.printAndSet("cbHeader", self.readInt16()) assert self.cbHeader == 0x44 - MFPF(self).dump() + self.mfpf = MFPF(self) + self.mfpf.dump() PICF_Shape(self, "innerHeader").dump() PICMID(self).dump() self.printAndSet("cProps", self.readuInt16()) @@ -747,9 +748,12 @@ class PICFAndOfficeArtData(DOCDirStream): def dump(self): print '<PICFAndOfficeArtData>' pos = self.pos - PICF(self).dump() + picf = PICF(self) + picf.dump() assert self.pos == pos + 68 - # TODO cchPicName and others + if picf.mfpf.mm == 0x0066: + print '<todo what="PICFAndOfficeArtData::dump(): picf.mfpf.mm == MM_SHAPEFILE is unhandled"/>' + # TODO dump OfficeArtInlineSpContainer print '</PICFAndOfficeArtData>' # The TextFlow enumeration specifies the rotation settings for a block of text and for the individual commit f49c8d611f1bd86b8bff634d6f55c759cae7e2ae Author: Miklos Vajna <vmik...@suse.cz> Date: Fri Jul 19 11:18:27 2013 +0200 dump PICMID diff --git a/src/docrecord.py b/src/docrecord.py index 3e3960f..03be1e5 100644 --- a/src/docrecord.py +++ b/src/docrecord.py @@ -688,6 +688,33 @@ class PICF_Shape(DOCDirStream): self.parent.pos = self.pos print '</%s>' % self.name +class PICMID(DOCDirStream): + """The PICMID structure specifies the size and border information for a picture.""" + def __init__(self, parent): + DOCDirStream.__init__(self, parent.bytes) + self.pos = parent.pos + self.parent = parent + + def dump(self): + print '<picmid type="PICMID" offset="%d">' % 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()) + self.printAndSet("brcTop80", self.readuInt32()) # TODO dump Brc80 + self.printAndSet("brcLeft80", self.readuInt32()) + self.printAndSet("brcBottom80", self.readuInt32()) + self.printAndSet("brcRight80", self.readuInt32()) + self.printAndSet("dxaReserved3", self.readuInt16()) + self.printAndSet("dyaReserved3", self.readuInt16()) + self.parent.pos = self.pos + print '</picmid>' class PICF(DOCDirStream): """The PICF structure specifies the type of a picture, as well as the size @@ -704,8 +731,7 @@ class PICF(DOCDirStream): assert self.cbHeader == 0x44 MFPF(self).dump() PICF_Shape(self, "innerHeader").dump() - # TODO PICMID - self.pos += 38 + PICMID(self).dump() self.printAndSet("cProps", self.readuInt16()) self.parent.pos = self.pos print '</picf>' commit a6416f7c4dc0b9ad3cef17b4ceb16f9f7d142146 Author: Miklos Vajna <vmik...@suse.cz> Date: Fri Jul 19 11:10:15 2013 +0200 dump PICF_Shape This is probably the most useless structure I've seen so far: all of its fields must be ignored... diff --git a/src/docrecord.py b/src/docrecord.py index 59bdd39..3e3960f 100644 --- a/src/docrecord.py +++ b/src/docrecord.py @@ -670,6 +670,25 @@ class MFPF(DOCDirStream): self.parent.pos = self.pos print '</mfpf>' +class PICF_Shape(DOCDirStream): + """The PICF_Shape structure specifies additional header information for + pictures of type MM_SHAPE or MM_SHAPEFILE.""" + def __init__(self, parent, name): + DOCDirStream.__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 '</%s>' % self.name + + class PICF(DOCDirStream): """The PICF structure specifies the type of a picture, as well as the size of the picture and information about its border.""" @@ -684,8 +703,7 @@ class PICF(DOCDirStream): self.printAndSet("cbHeader", self.readInt16()) assert self.cbHeader == 0x44 MFPF(self).dump() - # TODO PICF_Shape - self.pos += 14 + PICF_Shape(self, "innerHeader").dump() # TODO PICMID self.pos += 38 self.printAndSet("cProps", self.readuInt16()) commit f1cd0863861573b37ca1432ef7cf87865b40e166 Author: Miklos Vajna <vmik...@suse.cz> Date: Fri Jul 19 11:05:17 2013 +0200 dump MFPF diff --git a/src/docrecord.py b/src/docrecord.py index 4f8dd1e..59bdd39 100644 --- a/src/docrecord.py +++ b/src/docrecord.py @@ -650,6 +650,26 @@ class SPgbPropOperand(DOCDirStream): self.printAndSet("reserved", self.readuInt8()) print '</sPgbPropOperand>' +class MFPF(DOCDirStream): + """The MFPF structure specifies the type of picture data that is stored.""" + def __init__(self, parent): + DOCDirStream.__init__(self, parent.bytes) + self.pos = parent.pos + self.parent = parent + + def dump(self): + mmDict = { + 0x0064: "MM_SHAPE", + 0x0066: "MM_SHAPEFILE", + } + print '<mfpf type="MFPF" offset="%d">' % self.pos + self.printAndSet("mm", self.readInt16(), dict = mmDict) + self.printAndSet("xExt", self.readuInt16()) + self.printAndSet("yExt", self.readuInt16()) + self.printAndSet("swHMF", self.readuInt16()) + self.parent.pos = self.pos + print '</mfpf>' + class PICF(DOCDirStream): """The PICF structure specifies the type of a picture, as well as the size of the picture and information about its border.""" @@ -663,8 +683,7 @@ class PICF(DOCDirStream): self.printAndSet("lcb", self.readInt32()) self.printAndSet("cbHeader", self.readInt16()) assert self.cbHeader == 0x44 - # TODO MFPF - self.pos += 8 + MFPF(self).dump() # TODO PICF_Shape self.pos += 14 # TODO PICMID commit cc3d2bd28f0274ab0d9a653fb18ca615af5ae190 Author: Miklos Vajna <vmik...@suse.cz> Date: Fri Jul 19 10:59:22 2013 +0200 initial PICF diff --git a/src/docrecord.py b/src/docrecord.py index d4584ea..4f8dd1e 100644 --- a/src/docrecord.py +++ b/src/docrecord.py @@ -650,6 +650,29 @@ class SPgbPropOperand(DOCDirStream): self.printAndSet("reserved", self.readuInt8()) print '</sPgbPropOperand>' +class PICF(DOCDirStream): + """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): + DOCDirStream.__init__(self, parent.bytes) + self.pos = parent.pos + self.parent = parent + + def dump(self): + print '<picf type="PICF" offset="%d">' % self.pos + self.printAndSet("lcb", self.readInt32()) + self.printAndSet("cbHeader", self.readInt16()) + assert self.cbHeader == 0x44 + # TODO MFPF + self.pos += 8 + # TODO PICF_Shape + self.pos += 14 + # TODO PICMID + self.pos += 38 + self.printAndSet("cProps", self.readuInt16()) + self.parent.pos = self.pos + print '</picf>' + class PICFAndOfficeArtData(DOCDirStream): """The PICFAndOfficeArtData structure specifies header information and binary data for a picture.""" @@ -660,7 +683,10 @@ class PICFAndOfficeArtData(DOCDirStream): def dump(self): print '<PICFAndOfficeArtData>' - # TODO PICF and others + pos = self.pos + PICF(self).dump() + assert self.pos == pos + 68 + # TODO cchPicName and others print '</PICFAndOfficeArtData>' # The TextFlow enumeration specifies the rotation settings for a block of text and for the individual commit 84a4e7458d322a5202a0f976c9ee63fd19d3bc49 Author: Miklos Vajna <vmik...@suse.cz> Date: Fri Jul 19 10:50:56 2013 +0200 initial PICFAndOfficeArtData diff --git a/src/docrecord.py b/src/docrecord.py index 87ece9d..d4584ea 100644 --- a/src/docrecord.py +++ b/src/docrecord.py @@ -650,6 +650,19 @@ class SPgbPropOperand(DOCDirStream): self.printAndSet("reserved", self.readuInt8()) print '</sPgbPropOperand>' +class PICFAndOfficeArtData(DOCDirStream): + """The PICFAndOfficeArtData structure specifies header information and + binary data for a picture.""" + def __init__(self, parent): + dataStream = parent.mainStream.doc.getDirectoryStreamByName("Data") + DOCDirStream.__init__(self, dataStream.bytes) + self.pos = parent.operand + + def dump(self): + print '<PICFAndOfficeArtData>' + # TODO PICF and others + print '</PICFAndOfficeArtData>' + # 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 = { @@ -763,8 +776,8 @@ class BrcOperand(DOCDirStream): class Sprm(DOCDirStream): """The Sprm structure specifies a modification to a property of a character, paragraph, table, or section.""" - def __init__(self, bytes, offset): - DOCDirStream.__init__(self, bytes) + def __init__(self, bytes, offset, mainStream = None, transformed = None): + DOCDirStream.__init__(self, bytes, mainStream = mainStream) self.pos = offset self.operandSizeMap = { 0: 1, @@ -795,6 +808,8 @@ class Sprm(DOCDirStream): self.operand = self.getuInt24() elif self.getOperandSize() == 4: self.operand = self.getuInt32() + if self.sprm == 0x6a03 and transformed == r"\x01": + self.ct = PICFAndOfficeArtData(self) elif self.getOperandSize() == 7: self.operand = self.getuInt64() & 0x0fffffff elif self.getOperandSize() == 9: @@ -869,11 +884,11 @@ class Sprm(DOCDirStream): class Prl(DOCDirStream): """The Prl structure is a Sprm that is followed by an operand.""" - def __init__(self, bytes, offset): + def __init__(self, bytes, offset, mainStream = None, transformed = None): DOCDirStream.__init__(self, bytes) self.pos = offset self.posOrig = self.pos - self.sprm = Sprm(self.bytes, self.pos) + self.sprm = Sprm(self.bytes, self.pos, mainStream, transformed) self.pos += 2 def dump(self): @@ -904,16 +919,17 @@ class GrpPrlAndIstd(DOCDirStream): class Chpx(DOCDirStream): """The Chpx structure specifies a set of properties for text.""" - def __init__(self, bytes, mainStream, offset): - DOCDirStream.__init__(self, bytes) + def __init__(self, bytes, mainStream, offset, transformed = None): + DOCDirStream.__init__(self, bytes, mainStream = mainStream) self.pos = offset + self.transformed = transformed def dump(self): print '<chpx type="Chpx" offset="%d">' % self.pos self.printAndSet("cb", self.readuInt8()) pos = self.pos while (self.cb - (pos - self.pos)) > 0: - prl = Prl(self.bytes, pos) + prl = Prl(self.bytes, pos, self.mainStream, self.transformed) prl.dump() pos += prl.getSize() print '</chpx>' @@ -953,7 +969,7 @@ class BxPap(DOCDirStream): class ChpxFkp(DOCDirStream): """The ChpxFkp structure maps text to its character properties.""" def __init__(self, pnFkpChpx, offset, size): - DOCDirStream.__init__(self, pnFkpChpx.mainStream.bytes) + DOCDirStream.__init__(self, pnFkpChpx.mainStream.bytes, mainStream = pnFkpChpx.mainStream) self.pos = offset self.size = size self.pnFkpChpx = pnFkpChpx @@ -967,13 +983,14 @@ class ChpxFkp(DOCDirStream): start = self.getuInt32(pos = pos) end = self.getuInt32(pos = pos + 4) print '<rgfc index="%d" start="%d" end="%d">' % (i, start, end) - print '<transformed value="%s"/>' % self.quoteAttr(self.pnFkpChpx.mainStream.retrieveOffset(start, end)) + self.transformed = self.quoteAttr(self.pnFkpChpx.mainStream.retrieveOffset(start, end)) + print '<transformed value="%s"/>' % self.transformed pos += 4 # rgbx offset = PLC.getPLCOffset(self.pos, self.crun, 1, i) chpxOffset = self.getuInt8(pos = offset) * 2 - chpx = Chpx(self.bytes, self.mainStream, self.pos + chpxOffset) + chpx = Chpx(self.bytes, self.mainStream, self.pos + chpxOffset, self.transformed) chpx.dump() print '</rgfc>' commit 0056eeede3735b8360338f4cf6f2fbb517ebd4ef Author: Miklos Vajna <vmik...@suse.cz> Date: Fri Jul 19 09:59:22 2013 +0200 dump FBSE diff --git a/src/msodraw.py b/src/msodraw.py index fb8cd24..6b46aa3 100644 --- a/src/msodraw.py +++ b/src/msodraw.py @@ -64,6 +64,7 @@ class RecordHeader: spContainer = 0xF004 solverContainer = 0xF005 FDGGBlock = 0xF006 + FBSE = 0xF007 FDG = 0xF008 FSPGR = 0xF009 FSP = 0xF00A @@ -85,6 +86,7 @@ class RecordHeader: Type.solverContainer: 'OfficeArtSolverContainer', Type.FDG: 'OfficeArtFDG', Type.FDGGBlock: 'OfficeArtFDGGBlock', + Type.FBSE: 'OfficeArtFBSE', Type.FOPT: 'OfficeArtFOPT', Type.FClientTextbox: 'OfficeArtClientTextbox', Type.FClientAnchor: 'OfficeArtClientAnchor', @@ -957,8 +959,8 @@ class BStoreContainerFileBlock: rh = RecordHeader(self.strm) rh.dumpXml(recHdl) if rh.recType in recData: - child = recData[rh.recType](self) - child.dumpXml(self, model, rh) + child = recData[rh.recType](self.strm) + child.dumpXml(self.strm, model, rh) else: recHdl.appendLine('<todo what="BStoreContainerFileBlock: recType = %s unhandled (size: %d bytes)"/>' % (hex(rh.recType), rh.recLen)) @@ -996,6 +998,58 @@ class SplitMenuColorContainer: recHdl.appendLine('</smca>') recHdl.appendLine('</splitColors>') +MSOBLIPTYPE = { + 0x00: 'msoblipERROR', + 0x01: 'msoblipUNKNOWN', + 0x02: 'msoblipEMF', + 0x03: 'msoblipWMF', + 0x04: 'msoblipPICT', + 0x05: 'msoblipJPEG', + 0x06: 'msoblipPNG', + 0x07: 'msoblipDIB', + 0x11: 'msoblipTIFF', + 0x12: 'msoblipCMYKJPEG', + } + +class FBSE: + """2.2.32 The OfficeArtFBSE record specifies a File BLIP Store Entry (FBSE) + that contains information about the BLIP.""" + def __init__(self, strm): + self.strm = strm + self.posOrig = strm.pos + self.btWin32 = strm.readUnsignedInt(1) + self.btMacOS = strm.readUnsignedInt(1) + self.rgbUid = strm.readBytes(16) + self.tag = strm.readUnsignedInt(2) + self.size = strm.readUnsignedInt(4) + self.cRef = strm.readUnsignedInt(4) + self.foDelay = strm.readUnsignedInt(4) + self.unused1 = strm.readUnsignedInt(1) + self.cbName = strm.readUnsignedInt(1) + self.unused2 = strm.readUnsignedInt(1) + self.unused3 = strm.readUnsignedInt(1) + + def appendLines (self, recHdl, rh): + pass + + def dumpXml(self, recHdl, model, rh): + recHdl.appendLine('<fbse>') + recHdl.appendLine('<btWin32 value="%s" name="%s"/>' % (self.btWin32, globals.getValueOrUnknown(MSOBLIPTYPE, self.btWin32, "todo"))) + recHdl.appendLine('<btMacOS value="%s" name="%s"/>' % (self.btMacOS, globals.getValueOrUnknown(MSOBLIPTYPE, self.btMacOS, "todo"))) + recHdl.appendLine('<rgbUid value="%s"/>' % hexdump(self.rgbUid)) + recHdl.appendLine('<tag value="%s"/>' % self.tag) + recHdl.appendLine('<size value="%s"/>' % self.size) + recHdl.appendLine('<cRef value="%s"/>' % self.cRef) + recHdl.appendLine('<foDelay value="%s"/>' % hex(self.foDelay)) + recHdl.appendLine('<unused1 value="%s"/>' % self.unused1) + recHdl.appendLine('<cbName value="%s"/>' % self.cbName) + recHdl.appendLine('<unused2 value="%s"/>' % self.unused2) + recHdl.appendLine('<unused3 value="%s"/>' % self.unused3) + if self.cbName != 0: + recHdl.appendLine('<todo what="FBSE::dumpXml(): cbName != 0"/>') + if self.strm.pos < self.posOrig + rh.recLen: + recHdl.appendLine('<todo what="FBSE::dumpXml(): non-empty embeddedBlip"/>') + recHdl.appendLine('</fbse>') class FClientAnchorSheet: """Excel-specific anchor data (OfficeArtClientAnchorSheet)""" @@ -1156,6 +1210,7 @@ recData = { RecordHeader.Type.SplitMenuColorContainer: SplitMenuColorContainer, RecordHeader.Type.TertiaryFOPT: TertiaryFOPT, RecordHeader.Type.BStoreContainer: BStoreContainer, + RecordHeader.Type.FBSE: FBSE, } # vim:set filetype=python shiftwidth=4 softtabstop=4 expandtab: _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits