Ticket #138: ole2.2.diff

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

Patch to hachoir-parser/hachoir_parser/misc/msoffice.py, msoffice_summary.py and ole2.py [updated]

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