[Libreoffice-commits] mso-dumper.git: 11 commits - src/docrecord.py src/msodraw.py test/doc

Miklos Vajna vmiklos at kemper.freedesktop.org
Fri Jul 19 04:12:08 PDT 2013


 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 <vmiklos at 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 <vmiklos at 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 <vmiklos at 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 <vmiklos at 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 <vmiklos at 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 <vmiklos at 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 <vmiklos at 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 <vmiklos at 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 <vmiklos at 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 <vmiklos at 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 <vmiklos at 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:


More information about the Libreoffice-commits mailing list