Ticket #138: ole2.3.diff

File ole2.3.diff, 47.3 kB (added by nneonneo <nneonneo@gmail.com>, 1 year ago)

More minor changes to the ole2 parser suite.

  • msoffice.py

    old new  
    1 from hachoir_parser import HachoirParser 
    2 from hachoir_core.field import FieldSet, RootSeekableFieldSet, RawBytes 
    3 from hachoir_core.endian import LITTLE_ENDIAN 
    4 from hachoir_core.stream import StringInputStream 
    5 from hachoir_parser.misc.msoffice_summary import Summary, CompObj 
     1""" 
     2Parsers for the different streams and fragments found in an OLE2 file. 
    63 
    7 PROPERTY_NAME = { 
    8     u"\5DocumentSummaryInformation": "doc_summary", 
    9     u"\5SummaryInformation": "summary", 
    10 
     4Documents: 
     5 - goffice source code 
    116 
    12 class OfficeRootEntry(HachoirParser, RootSeekableFieldSet): 
    13     tags = { 
    14         "description": "Microsoft Office document subfragments", 
     7Author: Robert Xiao, Victor Stinner 
     8Creation: 8 january 2005 
     9""" 
     10 
     11from hachoir_core.field import (SubFile, FieldSet, RootSeekableFieldSet, 
     12    UInt8, UInt16, UInt32, Int32, Enum, String, 
     13    PascalString32, Bits, Bytes, RawBytes, NullBytes) 
     14from hachoir_core.log import log 
     15from hachoir_core.text_handler import textHandler, hexadecimal 
     16from hachoir_parser.common.win32 import GUID, PascalStringWin32 
     17from hachoir_parser.misc.ole2_util import OLE2FragmentParser, RawParser, CustomFragment 
     18from hachoir_parser.misc.msoffice_summary import Summary 
     19 
     20class CompObj(OLE2FragmentParser): 
     21    OS_VERSION = { 
     22        0x0a03: "Windows 3.1", 
    1523    } 
    16     endian = LITTLE_ENDIAN 
     24    ENDIAN_CHECK=True 
     25    OS_CHECK=True 
     26    def createFields(self): 
     27        # Header 
     28        yield UInt16(self, "version", "Version (=1)") 
     29        yield Bytes(self, "endian", 2, "Endian (\\xfe\\xff for little endian)") 
     30        yield UInt8(self, "os_version") 
     31        yield UInt8(self, "os_revision") 
     32        yield Enum(UInt16(self, "os"), self.OS_NAME) 
     33        yield Int32(self, "unused[]", "(=-1)") 
     34        yield GUID(self, "clsid") 
    1735 
    18     def __init__(self, stream, **args): 
    19         RootSeekableFieldSet.__init__(self, None, "root", stream, None, stream.askSize(self)) 
    20         HachoirParser.__init__(self, stream, **args) 
     36        # User type 
     37        yield PascalString32(self, "user_type", strip="\0") 
    2138 
    22     def validate(self): 
    23         return True 
     39        # Clipboard format 
     40        if self["os"].value == self.OS_MAC: 
     41            yield Int32(self, "unused[]", "(=-2)") 
     42            yield String(self, "clipboard_format", 4) 
     43        else: 
     44            yield PascalString32(self, "clipboard_format", strip="\0") 
     45        if self._current_size // 8 == self.datasize: 
     46            return 
    2447 
     48        #-- OLE 2.01 --- 
     49 
     50        # Program ID 
     51        yield PascalString32(self, "prog_id", strip="\0") 
     52 
     53        if self["os"].value != self.OS_MAC: 
     54            # Magic number 
     55            yield textHandler(UInt32(self, "magic", "Magic number (0x71B239F4)"), hexadecimal) 
     56 
     57            # Unicode version 
     58            yield PascalStringWin32(self, "user_type_unicode", strip="\0") 
     59            yield PascalStringWin32(self, "clipboard_format_unicode", strip="\0") 
     60            yield PascalStringWin32(self, "prog_id_unicode", strip="\0") 
     61 
     62        size = self.datasize - (self._current_size // 8) # _current_size because current_size returns _current_max_size 
     63        if size: 
     64            yield NullBytes(self, "end_padding", size) 
     65 
     66        if self.datasize<self.size//8: yield RawBytes(self,"slack_space",(self.size//8)-self.datasize) 
     67 
     68class RootEntry(OLE2FragmentParser): 
     69    ENDIAN_CHECK=False 
     70    OS_CHECK=False 
     71 
    2572    def createFields(self): 
    2673        for index, property in enumerate(self.ole2.properties): 
    2774            if index == 0: 
    2875                continue 
    2976            try: 
    30                 name = PROPERTY_NAME[property["name"].value] 
     77                name,parser = PROPERTY_NAME[property["name"].value] 
    3178            except LookupError: 
    3279                name = property.name+"content" 
    33             for field in self.parseProperty(index, property, name): 
     80                parser = RawParser 
     81            for field in self.parseProperty(property, name, parser): 
    3482                yield field 
     83    def seekSBlock(self, block): 
     84        self.seekBit(block * self.ole2.ss_size) 
    3585 
    36     def parseProperty(self, property_index, property, name_prefix): 
     86    def parseProperty(self, property, name_prefix, parser=RawParser): 
    3787        ole2 = self.ole2 
    3888        if not property["size"].value: 
    3989            return 
     
    4393        first = None 
    4494        previous = None 
    4595        size = 0 
    46         start = property["start"].value 
    47         chain = ole2.getChain(start, ole2.ss_fat) 
    48         blocksize = ole2.ss_size 
    49         seek = ole2.seekSBlock 
    50         desc_format = "Small blocks %s..%s (%s)" 
    5196        fragment_group = None 
     97        chain = ole2.getChain(property["start"].value, ole2.ss_fat) 
    5298        while True: 
    5399            try: 
    54100                block = chain.next() 
    55                 contigious = False 
    56                 if not first
     101                contiguous = False 
     102                if first is None
    57103                    first = block 
    58                     contigious = True 
    59                 if previous and block == (previous+1): 
    60                     contigious = True 
    61                 if contigious: 
     104                    contiguous = True 
     105                if previous is not None and block == (previous+1): 
     106                    contiguous = True 
     107                if contiguous: 
    62108                    previous = block 
    63                     size += blocksize 
     109                    size += ole2.ss_size 
    64110                    continue 
    65111            except StopIteration: 
    66112                block = None 
    67             seek(first) 
    68             desc = desc_format % (first, previous, previous-first+1) 
    69             if name_prefix in ("summary", "doc_summary"): 
    70                 yield Summary(self, name, desc, size=size) 
    71             elif property_index == 1: 
    72                 yield CompObj(self, "comp_obj", desc, size=size) 
    73             else: 
    74                 yield RawBytes(self, name, size//8, desc) 
     113            if first is None: 
     114                break 
     115            self.seekSBlock(first) 
     116            desc = "Small blocks %s..%s (%s)" % (first, previous, previous-first+1) 
     117            desc += " of %s bytes" % (ole2.ss_size//8) 
     118            field = CustomFragment(self, name, size, parser, desc, fragment_group) 
     119            yield field 
     120            if not fragment_group: 
     121                fragment_group = field.group 
     122                fragment_group.args["datasize"] = property["size"].value 
    75123            if block is None: 
    76124                break 
    77125            first = block 
    78126            previous = block 
    79127            size = ole2.sector_size 
    80128 
    81 class FragmentGroup: 
    82     def __init__(self, parser): 
    83         self.items = [] 
    84         self.parser = parser 
     129class Pictures(OLE2FragmentParser): 
     130    class Picture(FieldSet): 
     131        def createFields(self): 
     132            yield RawBytes(self, "identifier", 4, "some kind of marker (A0461DF0)") 
     133            yield UInt32(self, "size") 
     134            yield RawBytes(self, "unknown[]", 16) 
     135            yield RawBytes(self, "unknown[]", 1) 
     136            yield SubFile(self, "image", self["size"].value-17, "Image Data") 
     137    ENDIAN_CHECK=False 
     138    OS_CHECK=False 
     139    def createFields(self): 
     140        pos=0 
     141        while pos//8 < self.datasize: 
     142            newpic=Pictures.Picture(self, "picture[]") 
     143            yield newpic 
     144            pos+=newpic.size 
    85145 
    86     def add(self, item): 
    87         self.items.append(item) 
     146class PowerPointDocument(OLE2FragmentParser): 
     147    OBJ_TYPES={ 0:"Unknown", 
     148                1000:"Document", 
     149                1001:"DocumentAtom", 
     150                1002:"EndDocument", 
     151                1006:"Slide", 
     152                1007:"SlideAtom", 
     153                1008:"Notes", 
     154                1009:"NotesAtom", 
     155                1010:"Environment", 
     156                1011:"SlidePersistAtom", 
     157                1015:"SSlideLayoutAtom", 
     158                1016:"MainMaster", 
     159                1017:"SSSlideInfoAtom", 
     160                1018:"SlideViewInfo", 
     161                1019:"GuideAtom", 
     162                1020:"ViewInfo", 
     163                1021:"ViewInfoAtom", 
     164                1022:"SlideViewInfoAtom", 
     165                1023:"VBAInfo", 
     166                1024:"VBAInfoAtom", 
     167                1025:"SSDocInfoAtom", 
     168                1026:"Summary", 
     169                1030:"DocRoutingSlip", 
     170                1031:"OutlineViewInfo", 
     171                1032:"SorterViewInfo", 
     172                1033:"ExObjList", 
     173                1034:"ExObjListAtom", 
     174                1035:"PPDrawingGroup", #FIXME: Office Art File Format Docu 
     175                1036:"PPDrawing", #FIXME: Office Art File Format Docu 
     176                1040:"NamedShows", # don't know if container 
     177                1041:"NamedShow", 
     178                1042:"NamedShowSlides", # don't know if container 
     179                2000:"List", 
     180                2005:"FontCollection", 
     181                2019:"BookmarkCollection", 
     182                2021:"SoundCollAtom", 
     183                2022:"Sound", 
     184                2023:"SoundData", 
     185                2025:"BookmarkSeedAtom", 
     186                2032:"ColorSchemeAtom", 
     187                3009:"ExObjRefAtom", 
     188                3009:"OEShapeAtom", 
     189                3011:"OEPlaceholderAtom", 
     190                3024:"GPointAtom", 
     191                3031:"GRatioAtom", 
     192                3998:"OutlineTextRefAtom", 
     193                3999:"TextHeaderAtom", 
     194                4000:"TextCharsAtom", 
     195                4001:"StyleTextPropAtom", 
     196                4002:"BaseTextPropAtom", 
     197                4003:"TxMasterStyleAtom", 
     198                4004:"TxCFStyleAtom", 
     199                4005:"TxPFStyleAtom", 
     200                4006:"TextRulerAtom", 
     201                4007:"TextBookmarkAtom", 
     202                4008:"TextBytesAtom", 
     203                4009:"TxSIStyleAtom", 
     204                4010:"TextSpecInfoAtom", 
     205                4011:"DefaultRulerAtom", 
     206                4023:"FontEntityAtom", 
     207                4024:"FontEmbeddedData", 
     208                4026:"CString", 
     209                4033:"MetaFile", 
     210                4035:"ExOleObjAtom", 
     211                4040:"SrKinsoku", 
     212                4041:"HandOut", 
     213                4044:"ExEmbed", 
     214                4045:"ExEmbedAtom", 
     215                4046:"ExLink", 
     216                4048:"BookmarkEntityAtom", 
     217                4049:"ExLinkAtom", 
     218                4050:"SrKinsokuAtom", 
     219                4051:"ExHyperlinkAtom", 
     220                4055:"ExHyperlink", 
     221                4056:"SlideNumberMCAtom", 
     222                4057:"HeadersFooters", 
     223                4058:"HeadersFootersAtom", 
     224                4063:"TxInteractiveInfoAtom", 
     225                4066:"CharFormatAtom", 
     226                4067:"ParaFormatAtom", 
     227                4071:"RecolorInfoAtom", 
     228                4074:"ExQuickTimeMovie", 
     229                4075:"ExQuickTimeMovieData", 
     230                4078:"ExControl", 
     231                4080:"SlideListWithText", 
     232                4082:"InteractiveInfo", 
     233                4083:"InteractiveInfoAtom", 
     234                4085:"UserEditAtom", 
     235                4086:"CurrentUserAtom", 
     236                4087:"DateTimeMCAtom", 
     237                4088:"GenericDateMCAtom", 
     238                4090:"FooterMCAtom", 
     239                4091:"ExControlAtom", 
     240                4100:"ExMediaAtom", 
     241                4101:"ExVideo", 
     242                4102:"ExAviMovie", 
     243                4103:"ExMCIMovie", 
     244                4109:"ExMIDIAudio", 
     245                4110:"ExCDAudio", 
     246                4111:"ExWAVAudioEmbedded", 
     247                4112:"ExWAVAudioLink", 
     248                4113:"ExOleObjStg", 
     249                4114:"ExCDAudioAtom", 
     250                4115:"ExWAVAudioEmbeddedAtom", 
     251                4116:"AnimationInfoAtom", 
     252                4117:"RTFDateTimeMCAtom", 
     253                5000:"ProgTags", # don't know if container 
     254                5001:"ProgStringTag", 
     255                5002:"ProgBinaryTag", 
     256                5003:"BinaryTagData", 
     257                6000:"PrintOptions", 
     258                6001:"PersistPtrFullBlock", # don't know if container 
     259                6002:"PersistPtrIncrementalBlock", # don't know if container 
     260                10001:"GScalingAtom", 
     261                10002:"GRColorAtom", 
     262                0xf000:"EscherDggContainer", # Drawing Group Container  
     263                0xf006:"EscherDgg", 
     264                0xf016:"EscherCLSID", 
     265                0xf00b:"EscherOPT", 
     266                0xf001:"EscherBStoreContainer", 
     267                0xf007:"EscherBSE", 
     268                0xf018:"EscherBlip_START", # Blip types are between  
     269                0xf117:"EscherBlip_END", # these two values  
     270                0xf002:"EscherDgContainer", # Drawing Container  
     271                0xf008:"EscherDg", 
     272                0xf118:"EscherRegroupItems", 
     273                0xf120:"EscherColorScheme", # bug in docs  
     274                0xf003:"EscherSpgrContainer", 
     275                0xf004:"EscherSpContainer", 
     276                0xf009:"EscherSpgr", 
     277                0xf00a:"EscherSp", 
     278                0xf00c:"EscherTextbox", 
     279                0xf00d:"EscherClientTextbox", 
     280                0xf00e:"EscherAnchor", 
     281                0xf00f:"EscherChildAnchor", 
     282                0xf010:"EscherClientAnchor", 
     283                0xf011:"EscherClientData", 
     284                0xf005:"EscherSolverContainer", 
     285                0xf012:"EscherConnectorRule", # bug in docs  
     286                0xf013:"EscherAlignRule", 
     287                0xf014:"EscherArcRule", 
     288                0xf015:"EscherClientRule", 
     289                0xf017:"EscherCalloutRule", 
     290                0xf119:"EscherSelection", 
     291                0xf11a:"EscherColorMRU", 
     292                0xf11d:"EscherDeletedPspl", # bug in docs  
     293                0xf11e:"EscherSplitMenuColors", 
     294                0xf11f:"EscherOleObject", 
     295                0xf122:"EscherUserDefined"} 
     296    class PowerPointObject(FieldSet): 
     297        def createFields(self): 
     298            yield Bits(self, "version", 4) 
     299            yield Bits(self, "instance", 12) 
     300            yield Enum(UInt16(self, "type"),PowerPointDocument.OBJ_TYPES) 
     301            yield UInt32(self, "length") 
     302            if self["version"].value==0xF: 
     303                while (self.current_size)//8 < self["length"].value+8: 
     304                    yield PowerPointDocument.PowerPointObject(self, "object[]") 
     305            elif self["length"].value: 
     306                if self["type"].display=="FontEntityAtom": 
     307                    yield String(self, "data", self["length"].value, charset="UTF-16-LE", truncate="\0", strip="\0") 
     308                elif self["type"].display=="TextCharsAtom": 
     309                    yield String(self, "data", self["length"].value, charset="UTF-16-LE") 
     310                elif self["type"].display=="TextBytesAtom": 
     311                    yield String(self, "data", self["length"].value, charset="ASCII") 
     312                else: 
     313                    yield RawBytes(self, "data", self["length"].value) 
     314        def createDescription(self): 
     315            if self["version"].value==0xF: 
     316                return "PowerPoint Object Container; instance %s, type %s"%(self["instance"].value,self["type"].display) 
     317            return "PowerPoint Object; version %s, instance %s, type %s"%(self["version"].value,self["instance"].value,self["type"].display) 
     318    ENDIAN_CHECK=False 
     319    OS_CHECK=False 
     320    def createFields(self): 
     321        pos=0 
     322        while pos//8 < self.datasize: 
     323            newobj=PowerPointDocument.PowerPointObject(self, "object[]") 
     324            yield newobj 
     325            pos+=newobj.size 
    88326 
    89     def createInputStream(self): 
    90         # FIXME: Use lazy stream creation 
    91         data = [] 
    92         for item in self.items: 
    93             data.append( item["rawdata"].value ) 
    94         data = "".join(data) 
     327class ExcelWorkbook(OLE2FragmentParser): 
     328    BIFF_TYPES={0x000:"DIMENSIONS_v0", 
     329                0x200:"DIMENSIONS_v2", 
     330                0x001:"BLANK_v0", 
     331                0x201:"BLANK_v2", 
     332                0x002:"INTEGER", 
     333                0x003:"NUMBER_v0", 
     334                0x203:"NUMBER_v2", 
     335                0x004:"LABEL_v0", 
     336                0x204:"LABEL_v2", 
     337                0x005:"BOOLERR_v0", 
     338                0x205:"BOOLERR_v2", 
     339                0x006:"FORMULA_v0", 
     340                0x206:"FORMULA_v2", 
     341                0x406:"FORMULA_v4", 
     342                0x007:"STRING_v0", 
     343                0x207:"STRING_v2", 
     344                0x008:"ROW_v0", 
     345                0x208:"ROW_v2", 
     346                0x009:"BOF_v0", 
     347                0x209:"BOF_v2", 
     348                0x409:"BOF_v4", 
     349                0x809:"BOF_v8", 
     350                0x00a:"EOF", 
     351                0x00b:"INDEX_v0", 
     352                0x20b:"INDEX_v2", 
     353                0x00c:"CALCCOUNT", 
     354                0x00d:"CALCMODE", 
     355                0x00e:"PRECISION", 
     356                0x00f:"REFMODE", 
     357                0x010:"DELTA", 
     358                0x011:"ITERATION", 
     359                0x012:"PROTECT", 
     360                0x013:"PASSWORD", 
     361                0x014:"HEADER", 
     362                0x015:"FOOTER", 
     363                0x016:"EXTERNCOUNT", 
     364                0x017:"EXTERNSHEET", 
     365                0x018:"NAME_v0", 
     366                0x218:"NAME_v2", 
     367                0x019:"WINDOWPROTECT", 
     368                0x01a:"VERTICALPAGEBREAKS", 
     369                0x01b:"HORIZONTALPAGEBREAKS", 
     370                0x01c:"NOTE", 
     371                0x01d:"SELECTION", 
     372                0x01e:"FORMAT_v0", 
     373                0x41e:"FORMAT_v4", 
     374                0x01f:"FORMATCOUNT",    # Undocumented  
     375                0x020:"COLUMNDEFAULT",  # Undocumented  
     376                0x021:"ARRAY_v0", 
     377                0x221:"ARRAY_v2", 
     378                0x022:"1904", 
     379                0x023:"EXTERNNAME_v0", 
     380                0x223:"EXTERNNAME_v2", 
     381                0x024:"COLWIDTH",       # Undocumented  
     382                0x025:"DEFAULTROWHEIGHT_v0", 
     383                0x225:"DEFAULTROWHEIGHT_v2", 
     384                0x026:"LEFT_MARGIN", 
     385                0x027:"RIGHT_MARGIN", 
     386                0x028:"TOP_MARGIN", 
     387                0x029:"BOTTOM_MARGIN", 
     388                0x02a:"PRINTHEADERS", 
     389                0x02b:"PRINTGRIDLINES", 
     390                0x02f:"FILEPASS", 
     391                0x031:"FONT_v0", 
     392                0x231:"FONT_v2", 
     393                0x032:"FONTCOUNT",      # Undocumented  
     394                0x033:"PRINTSIZE",      # Undocumented  
     395                0x036:"TABLE_v0", 
     396                0x236:"TABLE_v2", 
     397                0x037:"TABLE2", # OOo has docs  
     398                0x038:"WNDESK", # Undocumented  
     399                0x039:"ZOOM",   # Undocumented  
     400                0x03a:"BEGINPREF",      # Undocumented  
     401                0x03b:"ENDPREF",        # Undocumented  
     402                0x03c:"CONTINUE", 
     403                0x03d:"WINDOW1", 
     404                0x03e:"WINDOW2_v0", 
     405                0x23e:"WINDOW2_v2", 
     406                0x03f:"PANE_V2",        # Undocumented  
     407                0x040:"BACKUP", 
     408                0x041:"PANE", 
     409                0x042:"CODEPAGE", 
     410                0x043:"XF_OLD_v0", 
     411                0x243:"XF_OLD_v2", 
     412                0x443:"XF_OLD_v4", 
     413                0x044:"XF_INDEX", 
     414                0x045:"FONT_COLOR", 
     415                0x04d:"PLS", 
     416                0x050:"DCON", 
     417                0x051:"DCONREF", 
     418                0x052:"DCONNAME", 
     419                0x055:"DEFCOLWIDTH", 
     420                0x059:"XCT", 
     421                0x05a:"CRN", 
     422                0x05b:"FILESHARING", 
     423                0x05c:"WRITEACCESS", 
     424                0x05d:"OBJ", 
     425                0x05e:"UNCALCED", 
     426                0x05f:"SAVERECALC", 
     427                0x060:"TEMPLATE", 
     428                0x061:"INTL",   # Undocumented  
     429                0x862:"TAB_COLOR",      # Undocumented, OO calls it SHEETLAYOUT  
     430                0x063:"OBJPROTECT", 
     431                0x07d:"COLINFO", 
     432                0x27e:"RK", # Odd that there is no 0x7e  
     433                0x07f:"IMDATA", 
     434                0x080:"GUTS", 
     435                0x081:"WSBOOL", 
     436                0x082:"GRIDSET", 
     437                0x083:"HCENTER", 
     438                0x084:"VCENTER", 
     439                0x085:"BOUNDSHEET", 
     440                0x086:"WRITEPROT", 
     441                0x087:"ADDIN", 
     442                0x088:"EDG", 
     443                0x089:"PUB", 
     444                0x08c:"COUNTRY", 
     445                0x08d:"HIDEOBJ", 
     446                0x08e:"BUNDLESOFFSET",  # Undocumented  
     447                0x08f:"BUNDLEHEADER",   # Undocumented  
     448                0x090:"SORT", 
     449                0x091:"SUB", 
     450                0x092:"PALETTE", 
     451                0x293:"STYLE", # Odd that there is no 0x93  
     452                0x094:"LHRECORD", 
     453                0x095:"LHNGRAPH", 
     454                0x096:"SOUND", 
     455                0x097:"SYNC",   # Undocumented  
     456                0x098:"LPR", 
     457                0x099:"STANDARDWIDTH", 
     458                0x09a:"FNGROUPNAME", 
     459                0x09b:"FILTERMODE", 
     460                0x09c:"FNGROUPCOUNT", 
     461                0x09d:"AUTOFILTERINFO", 
     462                0x09e:"AUTOFILTER", 
     463                0x0a0:"SCL", 
     464                0x0a1:"SETUP", 
     465                0x0a4:"TOOLBARVER",     # Undocumented  
     466                0x0a9:"COORDLIST", 
     467                0x0ab:"GCW", 
     468                0x0ae:"SCENMAN", 
     469                0x0af:"SCENARIO", 
     470                0x0b0:"SXVIEW", 
     471                0x0b1:"SXVD", 
     472                0x0b2:"SXVI", 
     473                0x0b3:"SXSI",   # Undocumented  
     474                0x0b4:"SXIVD", 
     475                0x0b5:"SXLI", 
     476                0x0b6:"SXPI", 
     477                0x0b7:"FACENUM",        # Undocumented 
     478                0x0b8:"DOCROUTE", 
     479                0x0b9:"RECIPNAME", 
     480                0x0ba:"SSLIST", # Undocumented  
     481                0x0bb:"MASKIMDATA",     # Undocumented  
     482                0x4bc:"SHRFMLA", 
     483                0x0bd:"MULRK", 
     484                0x0be:"MULBLANK", 
     485                0x0bf:"TOOLBARHDR",     # Undocumented  
     486                0x0c0:"TOOLBAREND",     # Undocumented  
     487                0x0c1:"MMS", 
     488                0x0c2:"ADDMENU", 
     489                0x0c3:"DELMENU", 
     490                0x0c4:"TIPHISTORY",     # Undocumented  
     491                0x0c5:"SXDI", 
     492                0x0c6:"SXDB", 
     493                0x0c7:"SXFDB",  # guessed  
     494                0x0c8:"SXDDB",  # guessed  
     495                0x0c9:"SXNUM",  # guessed  
     496                0x0ca:"SXBOOL", # guessed  
     497                0x0cb:"SXERR",  # guessed  
     498                0x0cc:"SXINT",  # guessed  
     499                0x0cd:"SXSTRING", 
     500                0x0ce:"SXDTR",  # guessed  
     501                0x0cf:"SXNIL",  # guessed  
     502                0x0d0:"SXTBL", 
     503                0x0d1:"SXTBRGIITM", 
     504                0x0d2:"SXTBPG", 
     505                0x0d3:"OBPROJ", 
     506                0x0d5:"SXIDSTM", 
     507                0x0d6:"RSTRING", 
     508                0x0d7:"DBCELL", 
     509                0x0d8:"SXNUMGROUP",     # from OO : numerical grouping in pivot cache field  
     510                0x0da:"BOOKBOOL", 
     511                0x0dc:"PARAMQRY",       # DUPLICATE dc  
     512                0x0dc:"SXEXT",  # DUPLICATE dc  
     513                0x0dd:"SCENPROTECT", 
     514                0x0de:"OLESIZE", 
     515                0x0df:"UDDESC", 
     516                0x0e0:"XF", 
     517                0x0e1:"INTERFACEHDR", 
     518                0x0e2:"INTERFACEEND", 
     519                0x0e3:"SXVS", 
     520                0x0e5:"MERGECELLS",     # guessed  
     521                0x0e9:"BG_PIC", # Undocumented  
     522                0x0ea:"TABIDCONF", 
     523                0x0eb:"MS_O_DRAWING_GROUP", 
     524                0x0ec:"MS_O_DRAWING", 
     525                0x0ed:"MS_O_DRAWING_SELECTION", 
     526                0x0ef:"PHONETIC",       # semi-Undocumented  
     527                0x0f0:"SXRULE", 
     528                0x0f1:"SXEX", 
     529                0x0f2:"SXFILT", 
     530                0x0f6:"SXNAME", 
     531                0x0f7:"SXSELECT", 
     532                0x0f8:"SXPAIR", 
     533                0x0f9:"SXFMLA", 
     534                0x0fb:"SXFORMAT", 
     535                0x0fc:"SST", 
     536                0x0fd:"LABELSST", 
     537                0x0ff:"EXTSST", 
     538                0x100:"SXVDEX", 
     539                0x103:"SXFORMULA", 
     540                0x122:"SXDBEX", 
     541                0x137:"CHTRINSERT", 
     542                0x138:"CHTRINFO", 
     543                0x13B:"CHTRCELLCONTENT", 
     544                0x13d:"TABID", 
     545                0x140:"CHTRMOVERANGE", 
     546                0x14D:"CHTRINSERTTAB", 
     547                0x15F:"LABELRANGES", 
     548                0x160:"USESELFS", 
     549                0x161:"DSF", 
     550                0x162:"XL5MODIFY", 
     551                0x196:"CHTRHEADER", 
     552                0x1a5:"FILESHARING2", 
     553                0x1a9:"USERDBVIEW", 
     554                0x1aa:"USERSVIEWBEGIN", 
     555                0x1ab:"USERSVIEWEND", 
     556                0x1ad:"QSI", 
     557                0x1ae:"SUPBOOK", 
     558                0x1af:"PROT4REV", 
     559                0x1b0:"CONDFMT", 
     560                0x1b1:"CF", 
     561                0x1b2:"DVAL", 
     562                0x1b5:"DCONBIN", 
     563                0x1b6:"TXO", 
     564                0x1b7:"REFRESHALL", 
     565                0x1b8:"HLINK", 
     566                0x1ba:"CODENAME",       # TYPO in MS Docs  
     567                0x1bb:"SXFDBTYPE", 
     568                0x1bc:"PROT4REVPASS", 
     569                0x1be:"DV", 
     570                0x1c0:"XL9FILE", 
     571                0x1c1:"RECALCID", 
     572                0x800:"LINK_TIP",       # follows an hlink  
     573                0x802:"UNKNOWN_802",    # OO exports it but has not name or docs  
     574                0x803:"WQSETT", # OO named it and can export it, but does not include it in the docs  
     575                0x804:"WQTABLES",       # OO named it and can export it, but does not include it in the docs  
     576                0x805:"UNKNOWN_805",    # No name or docs, seems related to web query see #153260 for sample  
     577                0x810:"PIVOT_AUTOFORMAT",       # Seems to contain pivot table autoformat indicies, plus ??  
     578                0x864:"UNKNOWN_864",    # seems related to pivot tables  
     579                0x867:"SHEETPROTECTION",        # OO named it, and has docs  
     580                0x868:"RANGEPROTECTION",        # OO named it, no docs yet  
    95581 
    96         # FIXME: Use smarter code to send arguments 
    97         args = {"ole2": self.items[0].root} 
    98         tags = {"class": self.parser, "args": args} 
    99         tags = tags.iteritems() 
    100         return StringInputStream(data, "<fragment group>", tags=tags) 
    101  
    102 class CustomFragment(FieldSet): 
    103     def __init__(self, parent, name, size, parser, description=None, group=None): 
    104         FieldSet.__init__(self, parent, name, description, size=size) 
    105         if not group: 
    106             group = FragmentGroup(parser) 
    107         self.group = group 
    108         self.group.add(self) 
    109  
     582                0x1001:"CHART_units", 
     583                0x1002:"CHART_chart", 
     584                0x1003:"CHART_series", 
     585                0x1006:"CHART_dataformat", 
     586                0x1007:"CHART_lineformat", 
     587                0x1009:"CHART_markerformat", 
     588                0x100a:"CHART_areaformat", 
     589                0x100b:"CHART_pieformat", 
     590                0x100c:"CHART_attachedlabel", 
     591                0x100d:"CHART_seriestext", 
     592                0x1014:"CHART_chartformat", 
     593                0x1015:"CHART_legend", 
     594                0x1016:"CHART_serieslist", 
     595                0x1017:"CHART_bar", 
     596                0x1018:"CHART_line", 
     597                0x1019:"CHART_pie", 
     598                0x101a:"CHART_area", 
     599                0x101b:"CHART_scatter", 
     600                0x101c:"CHART_chartline", 
     601                0x101d:"CHART_axis", 
     602                0x101e:"CHART_tick", 
     603                0x101f:"CHART_valuerange", 
     604                0x1020:"CHART_catserrange", 
     605                0x1021:"CHART_axislineformat", 
     606                0x1022:"CHART_chartformatlink", 
     607                0x1024:"CHART_defaulttext", 
     608                0x1025:"CHART_text", 
     609                0x1026:"CHART_fontx", 
     610                0x1027:"CHART_objectlink", 
     611                0x1032:"CHART_frame", 
     612                0x1033:"CHART_begin", 
     613                0x1034:"CHART_end", 
     614                0x1035:"CHART_plotarea", 
     615                0x103a:"CHART_3d", 
     616                0x103c:"CHART_picf", 
     617                0x103d:"CHART_dropbar", 
     618                0x103e:"CHART_radar", 
     619                0x103f:"CHART_surf", 
     620                0x1040:"CHART_radararea", 
     621                0x1041:"CHART_axisparent", 
     622                0x1043:"CHART_legendxn", 
     623                0x1044:"CHART_shtprops", 
     624                0x1045:"CHART_sertocrt", 
     625                0x1046:"CHART_axesused", 
     626                0x1048:"CHART_sbaseref", 
     627                0x104a:"CHART_serparent", 
     628                0x104b:"CHART_serauxtrend", 
     629                0x104e:"CHART_ifmt", 
     630                0x104f:"CHART_pos", 
     631                0x1050:"CHART_alruns", 
     632                0x1051:"CHART_ai", 
     633                0x105b:"CHART_serauxerrbar", 
     634                0x105c:"CHART_clrtclient",      # Undocumented  
     635                0x105d:"CHART_serfmt", 
     636                0x105f:"CHART_3dbarshape",      # Undocumented  
     637                0x1060:"CHART_fbi", 
     638                0x1061:"CHART_boppop", 
     639                0x1062:"CHART_axcext", 
     640                0x1063:"CHART_dat", 
     641                0x1064:"CHART_plotgrowth", 
     642                0x1065:"CHART_siindex", 
     643                0x1066:"CHART_gelframe", 
     644                0x1067:"CHART_boppopcustom",} 
     645    class BIFF(FieldSet): 
     646        def createFields(self): 
     647            yield Enum(UInt16(self, "type"),ExcelWorkbook.BIFF_TYPES) 
     648            yield UInt16(self, "length") 
     649            if self["length"].value: 
     650                yield RawBytes(self, "data", self["length"].value) 
     651        def createDescription(self): 
     652            return "Excel BIFF; type %s"%self["type"].display 
    110653    def createFields(self): 
    111         yield RawBytes(self, "rawdata", self.size//8) 
    112  
    113     def _createInputStream(self, **args): 
    114         return self.group.createInputStream() 
    115  
     654        pos=0 
     655        while pos//8 < self.datasize: 
     656            newobj=ExcelWorkbook.BIFF(self, "BIFF[]") 
     657            yield newobj 
     658            pos+=newobj.size 
     659PROPERTY_NAME = { 
     660    u"Root Entry": ("root",RootEntry), 
     661    u"\5DocumentSummaryInformation": ("doc_summary",Summary), 
     662    u"\5SummaryInformation": ("summary",Summary), 
     663    u"\1CompObj": ("compobj",CompObj), 
     664    u"Pictures": ("pictures",Pictures), 
     665    u"PowerPoint Document": ("powerpointdoc",PowerPointDocument), 
     666    u"Workbook": ("workbook",ExcelWorkbook), 
     667
  • msoffice_summary.py

    old new  
    1 from hachoir_parser import HachoirParser 
    21from hachoir_core.field import (FieldSet, ParserError, 
    3     RootSeekableFieldSet, SeekableFieldSet, 
     2    SeekableFieldSet, 
    43    Bit, Bits, NullBits, 
    54    UInt16, UInt32, TimestampWin64, Enum, 
    65    Bytes, RawBytes, NullBytes, String, 
    7     Int8, Int16, Int32, Float32, Float64, PascalString32) 
     6    Int32, Float32, Float64, PascalString32) 
    87from hachoir_core.text_handler import textHandler, hexadecimal, filesizeHandler 
    98from hachoir_core.tools import createDict 
    10 from hachoir_core.endian import LITTLE_ENDIAN, BIG_ENDIAN 
    11 from hachoir_parser.common.win32 import GUID, PascalStringWin32 
     9from hachoir_parser.common.win32 import GUID 
    1210from hachoir_parser.image.bmp import BmpHeader, parseImageData 
     11from hachoir_parser.misc.ole2_util import OLE2FragmentParser, Bool 
    1312 
    1413MAX_SECTION_COUNT = 100 
    1514 
    16 class OSConfig: 
    17     def __init__(self, big_endian): 
    18         if big_endian: 
    19             self.charset = "MacRoman" 
    20             self.utf16 = "UTF-16-BE" 
    21         else: 
    22             self.charset = "ISO-8859-1" 
    23             self.utf16 = "UTF-16-LE" 
    24  
    2515class PropertyIndex(FieldSet): 
    2616    COMMON_PROPERTY = { 
    2717        0: "Dictionary", 
     
    8777        yield UInt32(self, "offset") 
    8878 
    8979    def createDescription(self): 
    90         return "Propery: %s" % self["id"].display 
     80        return "Property: %s" % self["id"].display 
    9181 
    92 class Bool(Int8): 
    93     def createValue(self): 
    94         value = Int8.createValue(self) 
    95         return (value == -1) 
    96  
    9782class Thumbnail(FieldSet): 
    9883    """ 
    9984    Thumbnail. 
     
    145130            yield RawBytes(self, "data", size) 
    146131 
    147132class PropertyContent(FieldSet): 
     133    class NullHandler(FieldSet): 
     134        def createFields(self): 
     135            yield UInt32(self, "unknown[]") 
     136            yield PascalString32(self, "data") 
     137        def createValue(self): 
     138            return self["data"].value 
     139    class BlobHandler(FieldSet): 
     140        def createFields(self): 
     141            yield UInt32(self, "size") 
     142            yield UInt32(self, "count") 
     143            for i in range(self["count"].value): 
     144                yield PropertyContent(self, "item[]") 
     145                n=paddingSize(self.current_size,32) 
     146                if n: yield PaddingBits(self, "padding[]", n) 
     147    class WidePascalString32(FieldSet): 
     148        ''' uses number of characters instead of number of bytes ''' 
     149        def __init__(self,parent,name,charset='ASCII'): 
     150            FieldSet.__init__(self,parent,name) 
     151            self.charset=charset 
     152        def createFields(self): 
     153            yield UInt32(self, "length", "Length of this string") 
     154            yield String(self, "data", self["length"].value*2, charset=self.charset) 
     155        def createValue(self): 
     156            return self["data"].value 
     157        def createDisplay(self): 
     158            return 'u'+self["data"].display 
    148159    TYPE_LPSTR = 30 
    149160    TYPE_INFO = { 
    150161        0: ("EMPTY", None), 
    151         1: ("NULL", None), 
    152         2: ("Int16", Int16), 
    153         3: ("Int32", Int32), 
     162        1: ("NULL", NullHandler), 
     163        2: ("UInt16", UInt16), 
     164        3: ("UInt32", UInt32), 
    154165        4: ("Float32", Float32), 
    155166        5: ("Float64", Float64), 
    156167        6: ("CY", None), 
     
    177188        28: ("CARRAY", None), 
    178189        29: ("USERDEFINED", None), 
    179190        30: ("LPSTR", PascalString32), 
    180         31: ("LPWSTR", PascalString32), 
     191        31: ("LPWSTR", WidePascalString32), 
    181192        64: ("FILETIME", TimestampWin64), 
    182         65: ("BLOB", None), 
     193        65: ("BLOB", BlobHandler), 
    183194        66: ("STREAM", None), 
    184195        67: ("STORAGE", None), 
    185196        68: ("STREAMED_OBJECT", None), 
     
    202213        kw = {} 
    203214        try: 
    204215            handler = self.TYPE_INFO[tag][1] 
    205             if handler == PascalString32: 
    206                 osconfig = self["../.."].osconfig 
     216            if handler in (self.WidePascalString32,PascalString32): 
     217                cur = self 
     218                while not hasattr(cur,'osconfig'): 
     219                    cur=cur.parent 
     220                    if cur is None: 
     221                        raise LookupError('Cannot find osconfig') 
     222                osconfig = cur.osconfig 
    207223                if tag == self.TYPE_LPSTR: 
    208224                    kw["charset"] = osconfig.charset 
    209225                else: 
     
    211227        except LookupError: 
    212228            handler = None 
    213229        if not handler: 
    214             raise ParserError("OLE2: Unable to parse property of type %s" \ 
     230            log.warning("OLE2: Unable to parse property of type %s" \ 
    215231                % self["type"].display) 
    216         if self["is_vector"].value: 
     232            # raise ParserError( 
     233        elif self["is_vector"].value: 
    217234            yield UInt32(self, "count") 
    218235            for index in xrange(self["count"].value): 
    219236                yield handler(self, "item[]", **kw) 
     
    243260        yield String(self, "name", 16) 
    244261        yield UInt32(self, "offset") 
    245262 
    246 class Summary(HachoirParser, RootSeekableFieldSet): 
    247     tags = { 
    248         "description": "Microsoft Office document subfragments", 
    249     } 
    250     endian = LITTLE_ENDIAN 
     263class Summary(OLE2FragmentParser): 
     264    ENDIAN_CHECK=True 
     265    OS_CHECK=True 
    251266 
    252     OS_MAC = 1 
    253     OS_NAME = { 
    254         0: "Windows 16-bit", 
    255         1: "Macintosh", 
    256         2: "Windows 32-bit", 
    257     } 
    258  
    259     def __init__(self, stream, **args): 
    260         RootSeekableFieldSet.__init__(self, None, "root", stream, None, stream.askSize(self)) 
    261         HachoirParser.__init__(self, stream, **args) 
    262         if self["endian"].value == "\xFF\xFE": 
    263             self.endian = BIG_ENDIAN 
    264         elif self["endian"].value == "\xFE\xFF": 
    265             self.endian = LITTLE_ENDIAN 
    266         else: 
    267             raise ParserError("OLE2: Invalid endian value") 
    268         self.osconfig = OSConfig(self["os"].value == self.OS_MAC) 
    269  
    270     def validate(self): 
    271         return True 
    272  
    273  
    274267    def createFields(self): 
    275         yield Bytes(self, "endian