MpjddZddlmZdZdZdZgdZddlZddlZddl Z ddl Z ddl Z ddl Z ddlZddlZddlZeeureZ eZe jdj2d k(rdZnLe jd j2d k(rd Zn*e jd j2d k(rd Zned  eej<dd krdZndZej@dzfdZ!e!dZ"dZ#dZ$dZ%dZ&dZ'dZ(dZ)dZ*dZ+dZ,dZ-dZ.d Z/d Z0dZ1dZ2dZ3dZ4dZ5d Z6d Z7dZ8dZ9dZ:dZ;dZd"Z?d#Z@d$ZAd%ZBd&ZCd'ZDd(ZEd)ZFd*ZGd+ZHd,ZId-ZJd.ZKd/ZLd0ZMd1ZNd2ZOd3ZPd4ZQd5ZRd6ZSd7ZTd8ZUd9ZVd:ZWd;ZXdZ[iZ\e]e^jD]\Z`Zae`dd d?k(se`e\ea<d@Zbd Zcd)Zdd3ZedAZfdBZgdZdCZheeurdDZindEZid[dFZjd[dGZkdHZldIZmGdJdKenZoGdLdMeoZpGdNdOZqGdPdQerZsGdRdSejZuGdTdUZvGdVdWZwdXZxeydYk(rexyy#e$reZYwxYw#e$reZY}wxYw)\a: olefile (formerly OleFileIO_PL) Module to read/write Microsoft OLE2 files (also called Structured Storage or Microsoft Compound Document File Format), such as Microsoft Office 97-2003 documents, Image Composer and FlashPix files, Outlook messages, ... This version is compatible with Python 2.7 and 3.5+ Project website: https://www.decalage.info/olefile olefile is copyright (c) 2005-2023 Philippe Lagadec (https://www.decalage.info) olefile is based on the OleFileIO module from the PIL library v1.1.7 See: http://www.pythonware.com/products/pil/index.htm and http://svn.effbot.org/public/tags/pil-1.1.7/PIL/OleFileIO.py The Python Imaging Library (PIL) is Copyright (c) 1997-2009 by Secret Labs AB Copyright (c) 1995-2009 by Fredrik Lundh See source code and LICENSE.txt for information on usage and redistribution. )print_functionz 2023-12-01z0.47zPhilippe Lagadec) isOleFile OleFileIO OleMetadataenable_loggingMAGIC STGTY_EMPTY STGTY_STREAM STGTY_STORAGE STGTY_ROOTSTGTY_PROPERTYSTGTY_LOCKBYTESMINIMAL_OLEFILE_SIZE DEFECT_UNSUREDEFECT_POTENTIALDEFECT_INCORRECT DEFECT_FATALDEFAULT_PATH_ENCODING MAXREGSECTDIFSECTFATSECT ENDOFCHAINFREESECT MAXREGSIDNOSTREAM UNKNOWN_SIZE WORD_CLSIDOleFileIONotClosedNLIiz>Need to fix a bug with 32 bit arrays, please contact author...zutf-8c4|tjjjvr(tj|}|j ||Stj|}|j tj|j ||S)an Create a suitable logger object for this module. The goal is not to change settings of the root logger, to avoid getting other modules' logs on the screen. If a logger exists with same name, reuse it. (Else it would have duplicate handlers and messages would be doubled.) The level is set to CRITICAL+1 by default, to avoid any logging. )loggingLoggermanager loggerDict getLoggersetLevel addHandler NullHandler)namelevelloggers ]/mnt/ssd/data/Dropbox/adrian/scripts/msg_venv/lib/python3.12/site-packages/olefile/olefile.py get_loggerr2sy w~~%%000""4(   t $F g))+, OOE MolefilecJtjtjy)z Enable logging for this module (disabled by default). This will set the module-specific logger level to NOTSET, which means the main application controls the actual logging level. N)logr+r&NOTSETr3r1rrs LL r3sࡱlllli @ABCDEFGHVT_z$00020900-0000-0000-C000-000000000046(icd}|&t|tk\r|dtt}nyt|dr)restriprr}tuplemaprs)clsids r1_clsidrksj u:   ;;u  4%mS]CqM : #b%"+& '( )*r3cntjdddddd}|tj|dzzS)zD convert FILETIME (64 bits int) to Python datetime.datetime Ar$rr@ microseconds)datetime timedelta)filetime_FILETIME_null_dates r1filetime2datetimer|s9 #++D!Q1a@ !3!32!N NNr3ceZdZdZy) OleFileErrorz- Generic base error for this module. N__name__ __module__ __qualname____doc__r8r3r1rr  r3rceZdZdZy)NotOleFileErrorz? Error raised when the opened file is not an OLE file. Nrr8r3r1rrrr3rc2eZdZdZgdZgdZdZdZdZy)raT Class to parse and store metadata from standard properties of OLE files. Available attributes: codepage, title, subject, author, keywords, comments, template, last_saved_by, revision_number, total_edit_time, last_printed, create_time, last_saved_time, num_pages, num_words, num_chars, thumbnail, creating_application, security, codepage_doc, category, presentation_target, bytes, lines, paragraphs, slides, notes, hidden_slides, mm_clips, scale_crop, heading_pairs, titles_of_parts, manager, company, links_dirty, chars_with_spaces, unused, shared_doc, link_base, hlinks, hlinks_changed, version, dig_sig, content_type, content_status, language, doc_version Note: an attribute is set to None when not present in the properties of the OLE file. References for SummaryInformation stream: - https://msdn.microsoft.com/en-us/library/dd942545.aspx - https://msdn.microsoft.com/en-us/library/dd925819%28v=office.12%29.aspx - https://msdn.microsoft.com/en-us/library/windows/desktop/aa380376%28v=vs.85%29.aspx - https://msdn.microsoft.com/en-us/library/aa372045.aspx - http://sedna-soft.de/articles/summary-information-stream/ - https://poi.apache.org/apidocs/org/apache/poi/hpsf/SummaryInformation.html References for DocumentSummaryInformation stream: - https://msdn.microsoft.com/en-us/library/dd945671%28v=office.12%29.aspx - https://msdn.microsoft.com/en-us/library/windows/desktop/aa380374%28v=vs.85%29.aspx - https://poi.apache.org/apidocs/org/apache/poi/hpsf/DocumentSummaryInformation.html New in version 0.25 )codepagetitlesubjectauthorkeywordscommentstemplate last_saved_byrevision_numbertotal_edit_time last_printed create_timelast_saved_time num_pages num_words num_chars thumbnailcreating_applicationsecurity) codepage_doccategorypresentation_targetrhlines paragraphsslidesnotes hidden_slidesmm_clips scale_crop heading_pairstitles_of_partsr(company links_dirtychars_with_spacesunused shared_doc link_basehlinkshlinks_changedversiondig_sig content_typecontent_statuslanguage doc_versioncd|_d|_d|_d|_d|_d|_d|_d|_d|_d|_ d|_ d|_ d|_ d|_ d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_ d|_!d|_"d|_#d|_$d|_%d|_&d|_'d|_(d|_)d|_*d|_+d|_,d|_-d|_.y)z_ Constructor for OleMetadata All attributes are set to None by default N)/rrrrrrrrrrrrrrrrrrrrrrrhrrrrrrrrrr(rrrrrrrrrrrrrrselfs r1__init__zOleMetadata.__init__s_        !## #$(!   #'     ! !#  !%  "   " r3c8|j|jzD]}t||d|jdrg|j dddg}t t |jD]1}|j|dzd}t||j||3|jdrf|j dd}t t |jD]1}|j|dzd}t||j||3yy) a Parse standard properties of an OLE file, from the streams ``\x05SummaryInformation`` and ``\x05DocumentSummaryInformation``, if present. Properties are converted to strings, integers or python datetime objects. If a property is not present, its value is set to None. :param ole_file: OleFileIO object from which to parse properties NzSummaryInformationTr@) convert_time no_conversionr$zDocumentSummaryInformationr)SUMMARY_ATTRIBSDOCSUM_ATTRIBSsetattrexists getpropertiesrangereget)role_fileattribpropsr"values r1parse_propertieszOleMetadata.parse_propertiess&++d.A.AA (F D&$ ' ( ??3 4**+C8 !A#t,d2215u= > ??; <**+K8<+>E3t2234 = !A#t,d11!4e< = =r3c 4td|jD]2}t||}tdj|t |4td|j D]2}t||}tdj|t |4y)z< Dump all metadata, for debugging purposes. z*Properties from SummaryInformation stream:- {}: {}z2Properties from DocumentSummaryInformation stream:N)printrgetattrformatreprr)rproprs r1dumpzOleMetadata.dump#s :;(( 8DD$'E *##D$u+6 7 8 BC'' 8DD$'E *##D$u+6 7 8r3N) rrrrrrrrrr8r3r1rrs( HOEN5 n =D 8r3rc*eZdZdZdfd ZdZxZS)rzR Warning type used when OleFileIO is destructed but has open file handle. c8tt| ||_yro)superrr stack_of_open)rrrus r1rzOleFileIONotClosed.__init__4s  $02*r3cd}|jr/dj|ddg|jjzS|S)NzDeleting OleFileIO instance with open file handle. You should ensure that OleFileIO is never deleted without calling close() first. Consider using "with OleFileIO(...) as ole: ...".r zStacktrace of open() call: )rjoinr)rmsgs r1__str__zOleFileIONotClosed.__str__8sM3   77C'EF--44678 8Jr3ro)rrrrrr __classcell__)rus@r1rr0s+ r3rceZdZdZdZy) OleStreama OLE2 Stream Returns a read-only file object which can be used to read the contents of a OLE stream (instance of the BytesIO class). To open a stream, use the openstream method in the OleFileIO class. This function can be used with either ordinary streams, or ministreams, depending on the offset, sectorsize, and fat table arguments. Attributes: - size: actual size of data stream, after it was opened. c " tjdtjd|||||t|t|fz||_|jj j r tdd} |tk(r%t||z}d} tjd||dz z|z} tjd| z| t|kDr |jjtd g} |d k(r>|tk7r5tjd |jjtd t| D]} tjd | |fz|tk(rO| rtjdntjd|jjtd|d ks|t|k\r`tjd||t|fztjd| | fz|jjtdn |j|||zz|j|} t| |k7r|t|dz k7rtjd|t||||zz|t| fztjd|||zzt| zz|jjtd| j!|  ||dz}dj%| } t| |k\r0tjdt| |fz| d|} ||_n| r2tjdt| zt| |_nStjdt| |fzt| |_|jjtdt(j*j-|| y#t$rFtjd||||zz|fz|jjtdYEwxYw#t"$r%|jjtdYvwxYw) a_ Constructor for OleStream class. :param fp: file object, the OLE container or the MiniFAT stream :param sect: sector index of first sector in the stream :param size: total size of the stream :param offset: offset in bytes for the first FAT or MiniFAT sector :param sectorsize: size of one sector :param fat: array/list of sector indexes (FAT or MiniFAT) :param filesize: size of OLE file (for debugging) :param olefileio: OleFileIO object containing this stream :returns: a BytesIO instance containing the OLE stream zOleStream.__init__:zE sect=%d (%X), size=%d, offset=%d, sectorsize=%d, len(fat)=%d, fp=%sz2Attempting to open a stream from a closed OLE FileFTz stream with UNKNOWN SIZEr$nb_sectors = %dz(malformed OLE document, stream too largerz!size == 0 and sect != ENDOFCHAIN:z+incorrect OLE sector index for empty streamzReading stream sector[%d] = %Xhz6Reached ENDOFCHAIN sector for stream with unknown sizez$sect=ENDOFCHAIN before expected sizezincomplete OLE streamzsect=%d (%X) / len(fat)=%dzi=%d / nb_sectors=%d,incorrect OLE FAT, sector index out of rangezsect=%d, seek=%d, filesize=%dOLE sector index out of rangez9sect=%d / len(fat)=%d, seek=%d / filesize=%d, len read=%dzseek+len(read)=%dincomplete OLE sectorr9r3z3Read data of length %d, truncated to stream size %dNz3Read data of length %d, the stream size was unknownz9Read data of length %d, less than expected stream size %dz%OLE stream size is less than declared)r6debugrerolermclosedOSErrorr _raise_defectrrrrc Exceptionrbappend IndexErrorrsizeioBytesIOr)rrmsectroffset sectorsizefatfilesize olefileio unknown_size nb_sectorsrkr" sector_datas r1rzOleStream.__init__Zs '( Y4VJs3xb BC D 88;;  NO O < s8J&DL II2 3jl+ :  #j01 C HH " "#35_ ` 19+ II9 : HH " "#35b cz"3 A II71d)C Dz!IIVWIIDEHH**+;=TUAvs3x 6$c#h9OOP 01j/AB &&'79gh d!223''*-K ;+s3xz0B U3s8VJtO%;Xs;GWXYZ - 41GKHX1XYZ&&'79PQ KK $ 4y:-]3 nxx~ t9  IIKsSWyZ^N__ `;DDI  IIKcRViW XD DI IIQUXY]U^`dTee fD DI HH " "#35\ ] D$'_  96*T/18<=>&&'79XY  ( &&'79gh  s%4P Q A QQ )R RN)rrrrrr8r3r1rrFs &|(r3rceZdZdZdZdZejeek(sJdZdZ dZ dZ dZ d Z d Zd Zdd Zd ZdZy)OleDirectoryEntryz@ OLE2 Directory Entry pointing to a stream or a storage z<64sHBBIII16sIQQIIIcP||_||_g|_i|_d|_t j tj|\|_ |_ |_ |_ |_ |_|_}|_|_|_|_|_|_|jt,t.t0t2fvr|j5t6d|jt,k(r|dk7r|j5t6d|dk(r)|jt,k7r|j5t6d|jdkDr|j5t6dd|_ |jd|jd z |_|j;|j8|_t>jAd |jtC|j<fzt>jAd |jzt>jAd |j&zt>jAd |j|j|jfz|jDdk(r|j*dk7ri|j*dk7rZt>jAd|jD|j(|j*|j*fz|j5tFd|j(|_$n*|j(tK|j*dzz|_$t>jAd|jH|j(|j*fztM||_'|jt.k(r%|jHdk7r|j5tPdd|_)|jt,t0fvrp|jHdkDra|jH|jTkr|jt0k(rd|_)nd|_)|jW|j&|jRd|_,y)ae Constructor for an OleDirectoryEntry object. Parses a 128-bytes entry from the OLE Directory stream. :param bytes entry: bytes string (must be 128 bytes long) :param int sid: index of this directory entry in the OLE file directory :param OleFileIO ole_file: OleFileIO object containing this directory entry Fzunhandled OLE storage typerzduplicate OLE root entryzincorrect OLE root entryrUz(incorrect DirEntry name length >64 bytesNr:zDirEntry SID=%d: %sz - type: %dz - sect: %Xhz% - SID left: %d, right: %d, child: %dr9z+sectorsize=%d, sizeLow=%d, sizeHigh=%d (%X)zincorrect OLE stream size z% - size: %d (sizeLow=%d, sizeHigh=%d)zOLE storage with size>0T)-sidr4kids kids_dictusedryrzr STRUCT_DIRENTRYname_raw namelength entry_typecolorsid_left sid_right sid_child dwUserFlags createTime modifyTime isectStartsizeLowsizeHighr r r r rr name_utf16_decode_utf16_strr.r6rrrrrlongrrr is_minifatminisectorcutoff_check_duplicate_stream sect_chain)rentryrrrs r1rzOleDirectoryEntry.__init__s0   " MM+;;U C M O O J M N N    O O O L M ??:}lK"X X  " "#35Q R ??j (SAX  " "#35O P !8:5  " "#35O P ??R   " "#35_ ` DO--(<$//!*;= ..t?  '488T$))_*EEF -$//12 .4??23 9T]] NNDNN=,, -   # %}}!dmmz&A G#.. dmmT]][\]&&}6QR DI T]](;R(?@DI 9TYY VZVcVc>X %   T^^ , IINN  &r3ctjd|z|tk(ry|dks"|t|jj k\r!|jj tdy|jj|}tjd|jt|j|j|j|jfz|jr!|jj tdyd|_|j!|j|jj#}||j$vr |jj td|j&j)|||j$|<|j!|j|j+y) a) Walk through red-black tree of children of this directory entry to add all of them to the kids list. (recursive method) :param child_sid: index of child directory entry to use, or None when called first time for the root. (only used during recursion) zappend_kids: child_sid=%dNrzOLE DirEntry index out of rangezHappend_kids: child_sid=%d - %s - sid_left=%d, sid_right=%d, sid_child=%dz#OLE Entry referenced more than onceTz!Duplicate filename in OLE storage)r6rrrer4 direntriesrr_load_direntryrrr.rrrrr2lowerrrrr4)r child_sidchild name_lowers r1r2zOleDirectoryEntry.append_kidssa - 9:   Q;)S)@)@%AA LL & &'79Z [LL// :E II`99d5::.QVQ`Q`ab czz **+;9;EJ   U^^ ,))+JT^^+ **+;79 II  U #).DNN: &   U__ -  $ $ &r3c4|j|jk(SzCompare entries by namer.rothers r1__eq__zOleDirectoryEntry.__eq__syyEJJ&&r3c4|j|jkSr=r>r?s r1__lt__zOleDirectoryEntry.__lt__syy5::%%r3c&|j| Sro)rAr?s r1__ne__zOleDirectoryEntry.__ne__s;;u%%%r3cJ|j|xs|j|Sro)rArCr?s r1__le__zOleDirectoryEntry.__le__s{{5!7T[[%77r3cgd} ||j}td|zt|jz|d|jt t fvrt|jddt|jtt fvr*|jrtd|zd|jzz|jD]}|j|dzy#t$rd}YwxYw) zADump this entry, and all its subentries (for debug purposes only))z (invalid)z (storage)z(stream)z (lockbytes)z (property)z(root)z (UNKNOWN) endrhz{%s}r:N) rrrrr.r r rr rrr)rtabTYPES type_namekids r1rzOleDirectoryEntry.dumps) $doo.I c#gTYY'< ??|Z8 8 $))W# .  ??}j9 9djj #c'FTZZ// 099 C HHS1W   $#I $sC C,+C,cL|jdk(ryt|jS)z Return modification time of a directory entry. :returns: None if modification time is null, a python datetime object otherwise (UTC timezone) new in version 0.26 rN)rrrs r1getmtimezOleDirectoryEntry.getmtime" ??a  11r3cL|jdk(ryt|jS)z Return creation time of a directory entry. :returns: None if modification time is null, a python datetime object otherwise (UTC timezone) new in version 0.26 rN)rrrs r1getctimezOleDirectoryEntry.getctimerRr3Nr)rrrrr DIRENTRY_SIZErycalcsizerr0r4r2rArCrErGrrQrTr8r3r1r r sf*,OM 6??? +} << <_B46.,'\'&&8$ 2 2r3r c4eZdZdZdeddefdZdZdZdZ e fdZ d-d Z d.d Z d Zd.d Zd.d Zd/dZd/dZdZdZdZdZdZd0dZd0dZdZdZdZedfdZd1dZd1dZ dZ!dZ"dZ#d Z$d!Z%d"Z&d#Z'd$Z(d%Z)d&Z*d'Z+d2d(Z,d)Z-d*Z.d+Z/d2d,Z0y)3ra OLE container object This class encapsulates the interface to an OLE 2 structured storage file. Use the listdir and openstream methods to access the contents of this file. Object names are given as a list of strings, one for each subentry level. The root entry should be omitted. For example, the following code extracts all image streams from a Microsoft Image Composer file:: with OleFileIO("fan.mic") as ole: for entry in ole.listdir(): if entry[1:2] == "Image": fin = ole.openstream(entry) fout = open(entry[0:1], "wb") while True: s = fin.read(8192) if not s: break fout.write(s) You can use the viewer application provided with the Python Imaging Library to view the resulting files (which happens to be standard TIFF files). NFc||_g|_||_||_d|_d|_g|_g|_d|_d|_ d|_ d|_ d|_ d|_ d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_ d|_!d|_"d|_#d|_$d|_%d|_&d|_'d|_(d|_)|r |jU||yy#tV$r|jYdwxYw)a Constructor for the OleFileIO class. :param filename: file to open. - if filename is a string smaller than 1536 bytes, it is the path of the file to open. (bytes or unicode string) - if filename is a string longer than 1535 bytes, it is parsed as the content of an OLE file in memory. (bytes type only) - if filename is a file-like object (with read, seek and tell methods), it is parsed as-is. The caller is responsible for closing it when done. :param raise_defects: minimal level for defects to be raised as exceptions. (use DEFECT_FATAL for a typical application, DEFECT_INCORRECT for a security-oriented application, see source code for details) :param write_mode: bool, if True the file is opened in read/write mode instead of read-only by default. :param debug: bool, set debug mode (deprecated, not used anymore) :param path_encoding: None or str, name of the codec to use for path names (streams and storages), or None for Unicode. Unicode by default on Python 3+, UTF-8 on Python 2.x. (new in olefile 0.42, was hardcoded to Latin-1 until olefile v0.41) NF) write_modewarn)-_raise_defects_levelparsing_issuesrZ path_encoding _filesize ministream_used_streams_fat_used_streams_minifat byte_order directory_fpr6 dll_versionrfirst_difat_sectorfirst_dir_sectorfirst_mini_fat_sectorrm header_clsidheader_signaturemetadatamini_sector_shiftmini_sector_sizemini_stream_cutoff_sizer- minifatsectr'minisectorsize minor_versionnb_sectnum_difat_sectorsnum_dir_sectorsnum_fat_sectorsnum_mini_fat_sectors reserved1 reserved2root sector_shift sector_sizetransaction_signature_numberwarn_if_not_closed _we_opened_fp _open_stackrir_close)rrj raise_defectsrZrr_s r1rzOleFileIO.__init__s:%2!!$*!#%'" "& $%)"  $ !% $'+$  $"! !%##$(!  ,0)"'"   (z :    ' s 1EE#c(|jdy)z?Destructor, ensures all file handles are closed that we opened.Tr[Nrrs r1__del__zOleFileIO.__del__ms  r3c|Sror8rs r1 __enter__zOleFileIO.__enter__ss r3c(|jdy)NFr[r)rargss r1__exit__zOleFileIO.__exit__ws  r3c||jk\rtj||||jj ||ftj |y)a This method should be called for any defect found during file parsing. It may raise an OleFileError exception according to the minimal level chosen for the OleFileIO object. :param defect_level: defect level, possible values are: - DEFECT_UNSURE : a case which looks weird, but not sure it's a defect - DEFECT_POTENTIAL : a potential defect - DEFECT_INCORRECT : an error according to specifications, but parsing can go on - DEFECT_FATAL : an error which cannot be ignored, parsing is impossible :param message: string describing the defect, used with raised exception. :param exception_type: exception class to be raised, OleFileError by default N)r]r6errorr^rwarning)r defect_levelmessageexception_types r1rzOleFileIO._raise_defect{sP" 444 4 IIg  ) )    & &'@ A KK r3cz|jd|}|jr|j|j|S|S)a Decode a string encoded in UTF-16 LE format, as found in the OLE directory or in property streams. Return a string encoded according to the path_encoding specified for the OleFileIO object. :param bytes utf16_str: bytes string encoded in UTF-16 LE format :param str errors: str, see python documentation for str.decode() :return: str, encoded according to path_encoding :rtype: str zUTF-16LE)decoder_encode)r utf16_strerrors unicode_strs r1r$zOleFileIO._decode_utf16_strs@ &&z6:   %%d&8&8&A A r3c8||_t|dr||_nt|tr-t |t k\rtj||_nB|jrd}nd}t|||_d|_ tj|_ d}|jjdtj  |jj#}|jjd||_t&j)d|j$|j$fzg|_g|_|jj/d}t |dk7s |dd t0k7rGt&j)d j3|dd t0|j5t6d t8d }t;j<|}t&j)d ||dzfz|d|}t;j>||\|_ |_!|_"|_#|_$|_%|_&|_'|_(|_)|_*|_+|_,|_-|_.|_/|_0|_1t&j)t;j>|||j@t0k7r|j5t6d|jBtedk7r|j5tfdt&j)d|jDzt&j)d|jFz|jFdvr|j5tfdt&j)d|jHz|jHdk7r|j5tfdd|jJz|_4t&j)d|jhz|jhdvr|j5tfd|jFdk(r|jhdk7s|jFdk(r%|jhdk7r|j5tfd d|jLz|_5t&j)d!|jjz|jjd"vr|j5tfd#|jNdk7s|jPdk7r|j5tfd$t&j)d%|jRz|jhdk(r%|jRdk7r|j5tfd&t&j)d'|jTzt&j)d(|jVzt&j)d)|jXz|jXdk7r|j5tld*t&j)d+|jZz|jZdk7r?|j5tfd,t&jod-|jZzd|_-t&j)d.|j\zt&j)d/|j^zt&j)d0|j`zt&j)d1|jbz||jhzd2z |jhzd2z |_8t&j)d3|jp|jpfzts|d d4|_!|jh|_:|jj|_;|jZ|_<|j{|jV|j^r|j{|j\|jbr|j{|j`|j}||j|jV|j\|_@y#|jjdwxYw)5a1 Open an OLE2 file in read-only or read/write mode. Read and parse the header, FAT and directory. :param filename: string-like or file-like object, OLE file to parse - if filename is a string smaller than 1536 bytes, it is the path of the file to open. (bytes or unicode string) - if filename is a string longer than 1535 bytes, it is parsed as the content of an OLE file in memory. (bytes type only) - if filename is a file-like object (with read, seek and tell methods), it is parsed as-is. The caller is responsible for closing it when done :param write_mode: bool, if True the file is opened in read/write mode instead of read-only by default. (ignored if filename is not a path) rbzr+brdTrzFile size: %d bytes (%Xh)rNr>zMagic = {!r} instead of {!r}z#not an OLE2 structured storage filez<8s16sHHHHHHLLLLLLLLLLzfmt_header size = %d, +FAT = %dizincorrect OLE signaturerEzincorrect CLSID in OLE headerzMinor Version = %dz%DLL Version = %d (expected: 3 or 4))r#r z"incorrect DllVersion in OLE headerz#Byte Order = %X (expected: FFFE)iz!incorrect ByteOrder in OLE headerr:z0Sector Size = %d bytes (expected: 512 or 4096))rr^z#incorrect sector_size in OLE headerr#r r^z3sector_size does not match DllVersion in OLE headerz/MiniFAT Sector Size = %d bytes (expected: 64))rUz(incorrect mini_sector_size in OLE headerz.incorrect OLE header (non-null reserved bytes)z Number of Directory sectors = %dz3incorrect number of directory sectors in OLE headerzNumber of FAT sectors = %dzFirst Directory sector = %Xhz$Transaction Signature Number = %dz5incorrect OLE header (transaction_signature_number>0)z/Mini Stream cutoff size = %Xh (expected: 1000h)z/incorrect mini_stream_cutoff_size in OLE headerzJFixing the mini_stream_cutoff_size to 4096 (mandatory value) instead of %dzFirst MiniFAT sector = %XhzNumber of MiniFAT sectors = %dzFirst DIFAT sector = %XhzNumber of DIFAT sectors = %dr$z/Maximum number of sectors in the file: %d (%Xh)rM)ArZrfrmrgrhrerrrrir traceback extract_stackrrcosSEEK_ENDtellr`r6rrbrcrbrrrrrryrWrzrkrjrrrfrdr{rmrxryrurvrhr}rorirwrgrt bytearrayrr|rnrrrsrrrqr'r(loadfat loaddirectoryrp) rrjrZmoderrl fmt_header header_sizeheader1s r1rizOleFileIO.opens"% 8V $DG % (S]>R-Rjj*DG8T*DG!%D (668D    Q $ ww||~H GGLLO! -0PPQ"$%'"c" v;# u!4 II4;;F2AJN O   |-RTc dN. ooj1  4 [SXEX7YY[+&( MM*g .'  !       O    " N N    !  -  (  &  %  #  " 6==89  E )   |-F G    " -   /1P Q '$*<*<<> :T=M=MMO   6 )   /1U V 84??JL ??f $   /1T Ud/// EHXHXXZ   ; .   /1V W   a D$4$4c$9   a D$4$4d$:   /1f g !4#9#9 9 DtG\G\\^   ,   /1[ \ >>Q $..A"5   /1a b 58L8LLN   S T%9%91%<   /1f g /$2F2FFH 2T5J5JJL 9D<]<]]_  , , 1   /1h i DtGcGcce  ' '6 1   /1b c KKd445 6+1D ( 4t7Q7QQS 3d6O6OOQ 4t7N7NNP 3d6L6LLN#T%5%55a7Dz..free..z[ END. ]zFATSECT zDIFSECT r$indexrIrJ%8X%6X:r9z --->N)rrrrrerr) rr firstindexVPLfatnamesnbsectnlinesr"lrrauxr.s r1dumpfatzOleFileIO.dumpfats       S*Q,$ g3s &A %!) % & v AcEE &Ju,-3 75%), %f91vZ'(?#C=Dqs{)$t|d$ % G! r3cd}tjt|}tjdk(r|j t |}||zdz |z}t ddt|D]}t d|zdt t|D]V}||z} t d|| zzdt| | |zD] }||k\rn||} d| z} t | d"t Xy ) zS Display a sector in a human-readable form, for debugging purposes r>bigr$rrIrJrrN)arrayUINT32sys byteorderbyteswaprerr) rsectorrrrLrrr"rrrr.s r1dumpsectzOleFileIO.dumpsects kk&&) ==E ! LLNS*Q,$ g3s &A %!) % & v AcEE &Ju,-3 75%), %f91vt|d$  % G r3ctjt|}tjdk(r|j |S)z convert a sector to an array of 32 bits unsigned integers, swapping bytes on big endian CPUs such as PowerPC (old Macs) r)rrrrr)rras r1 sect2arrayzOleFileIO.sect2arrays. KK % ==E ! JJLr3ct|tjr|}nE|j|}tj t j r|j|d}|D]}|dz}tjd|z|tk(s |tk(rtjd|S|j|}|j|}|j|z|_ |S)z Adds the indexes of the given sector to the FAT :param sect: string containing the first FAT sector, or array of long integers :returns: index of last FAT sector. Nr9z isect = %Xzfound end of sector chain) rgrrr6 isEnabledForr&DEBUGrrrrgetsectr)rrfat1isectsnextfats r1 loadfat_sectzOleFileIO.loadfat_sects dEKK (D??4(D . d# *EJ&E IIlU* + "ex&7 56  U#Aooa(Gxx')DH * r3ctjd|dd}tjdt|t|dzfztjt|_|j ||jdk7rtjd|jdkr|jtd |j|jk\r|jtd tjd |jdzd z }|jdz |zd z |z}tjd |z|j|k7r td|j}t!|D]}tjd||fz|j#|}|j%|}tj't(j*r|j-||j |d|||}tjd|z|t.t0fvr tdtjdt|j |jkDrUtjdt|j |jfz|j d|j|_tjdt|j |jfztj't(j*r1tjd|j3|j yy)z% Load the FAT table. zDLoading the FAT table, starting with the 1st sector after the headerLrzlen(sect)=%d, so %d integersr rz)DIFAT is used, because file size > 6.8MB.mz#incorrect DIFAT, not enough sectorsz)incorrect DIFAT, first index out of rangezDIFAT analysis...r$z nb_difat = %dzincorrect DIFATzDIFAT block %d, sector %XNznext DIFAT sector: %Xzincorrect end of DIFATz$No DIFAT, because file size < 6.8MB.z!len(fat)=%d, shrunk to nb_sect=%dz6FAT references %d sectors / Maximum %d sectors in filez FAT:)r6rrerrrrrtrvrrrgrsrrIOError iterrangerrrr&rrrrr) rrlrnb_difat_sectorsnb_difat isect_difatr" sector_difatdifats r1rzOleFileIO.loadfat!s XYb~ 1SYD 1 4MMO ;;v& $  ! !Q & IIA B##s*""#35Z[&&$,,6""<1\] II* ,!% 2A5 ,,S03CCAEHXXH II1 3%%1/0011Kx( C 6![9IIK#||K8  5##GMM2MM,/!!%(9)9":;#$45  2[@B C:x"88677 II< = txx=4<< ' II9S]DLL   GMM * IIl # LL & +r3c |jj|j|dzz|jj|j}t||jk7rDtj d|t||jfz|jtd|S#t$rNtj d||j|dzz|j fz|jtdYwxYw)z Read given sector from file on disk. :param sect: int, sector index :returns: a string containing the sector data. r$z(getsect(): sect=%X, seek=%d, filesize=%drz*getsect(): sect=%X, read=%d, sectorsize=%dr) rmrcrrr6rr`rrrbre)rrrs r1rzOleFileIO.getsects$ N GGLLDF3 4 doo. v;$// ) IIBs6{DOO45 6   |-D E  N II@tQ/@A B   |-L M Ns+B00ADDct|ts tdt|trt|dk7r td |jj |j |dzzt||j kr|||j t|z zz }n#t||j kDr td|jj|y#t$rNtjd||j |dzz|jfz|jtdYwxYw)z Write given sector to file on disk. :param sect: int, sector index :param data: bytes, sector data :param padding: single byte, padding character if data < sector size z'write_sect: data must be a bytes stringr$z4write_sect: padding must be a bytes string of 1 charz+write_sect(): sect=%X, seek=%d, filesize=%drData is larger than sector sizeN)rgrh TypeErrorrermrcrrr6rr`rr ValueErrorwrite)rrrkpaddings r1 write_sectzOleFileIO.write_sects $&EF F'5)S\1_RS S N GGLLDF3 4 t9t & GtT:; ;D Y (>? ?  d N IICtQ/@A B   |-L M Ns+C''AD>=D>ct|ts tdt|trt|dk7r td |jj |t|}||jkr|||j|z zz }|j|kr td|jj|y#t $r=tjd||jfz|jtdYwxYw)z Write given sector to file on disk. :param fp_pos: int, file position :param data: bytes, sector data :param padding: single byte, padding character if data < sector size z,write_mini_sect: data must be a bytes stringr$z9write_mini_sect: padding must be a bytes string of 1 charz)write_mini_sect(): fp_pos=%d, filesize=%drrN)rgrhrrermrcrr6rr`rrrnrr)rfp_posrkrlen_datas r1_write_mini_sectzOleFileIO._write_mini_sects$&JK K'5)S\Q->WX X N GGLL t9 d++ + Gt44x?@ @D  8 +>? ?  d N IIAt~~./ 0   |-L M NsCAD  D ctjd|j|d|_|jjdz}tjd|jj|fzdg|z|_|j d}|j d|_|jjy)z] Load the directory. :param sect: sector index of directory stream. zLoading the Directory:Trr z&loaddirectory: size=%d, max_entries=%dNr) r6rrrerr6r7rzr4)rr max_entries root_entrys r1rzOleFileIO.loaddirectorys *+ !JJttJ<'',,3  :    # #[ 12 3  &;.((+ OOA& $$&r3c|dks|t|jk\r|jtd|j|%|jtd|j|S|j j |dz|j jd}t||||j|<|j|S)a^ Load a directory entry from the directory. This method should only be called once for each storage/stream when loading the directory. :param sid: index of storage/stream in the directory. :returns: a OleDirectoryEntry object :exception OleFileError: if the entry has always been referenced. rz OLE directory index out of rangez'double reference for OLE stream/storager ) rer6rrrrercrbr )rrr*s r1r7zOleFileIO._load_direntrys q5CT__--   |-O P ??3  +   /9 ;??3' ' sSy)!!&&s+0TBs##r3c8|jjy)z5 Dump directory (for debugging only) N)rzrrs r1 dumpdirectoryzOleFileIO.dumpdirectory,s r3c tjd||t|fz||jkr|s|js|j |j j}tjd|j j|fz|j|j j|d|_t|j||d|j|j|jj|St|j|||j|j|j|j |S)a| Open a stream, either in FAT or MiniFAT according to its size. (openstream helper) :param start: index of first sector :param size: size of stream (or nothing if size is unknown) :param force_FAT: if False (default), stream will be opened in FAT or MiniFAT according to size. If True, it will always be opened in FAT. z1OleFileIO.open(): sect=%Xh, size=%d, force_FAT=%sz%Opening MiniStream: sect=%Xh, size=%dTrr)rmrrrrrrr)r6rstrr'rar.rzrr rrrqr-rmrrr`)rstartrrsize_ministreams r1rzOleFileIO._open2s E D#i. )* + $'' ' ??  "#')).. AYY))?;<="&**TYY-A-A#t#-#5e$$%$2E2E!%8L8L'+- - e$$(OO(,TXX&*nn'+ - -r3c~||jgz}|jD]}|jtk(r:|r"|j |dd|jgz|j |||||P|jt k(r&|sf|j |dd|jgz|jtdy)a listdir helper :param files: list of files to fill in :param prefix: current location in storage tree (list of names) :param node: current node (OleDirectoryEntry object) :param streams: bool, include streams if True (True by default) - new in v0.26 :param storages: bool, include storages if True (False by default) - new in v0.26 (note: the root storage is never included) r$NzIThe directory tree contains an entry which is not a stream nor a storage.) r.rrr r_listr rr)rfilesprefixnodestreamsstoragesr*s r1rzOleFileIO._listWs499+%YY BE=0LLuzzl!:; 5&%(C!!\1LLuzzl!:;""#36AB Br3cHg}|j|g|j|||S)am Return a list of streams and/or storages stored in this file :param streams: bool, include streams if True (True by default) - new in v0.26 :param storages: bool, include storages if True (False by default) - new in v0.26 (note: the root storage is never included) :returns: list of stream and/or storage paths )rrz)rrrrs r1listdirzOleFileIO.listdirss& 5"dii(; r3ct|tr|jd}|j}|D]M}|jD]/}|j j |j k(s/n td|}O|jS)a* Returns directory entry of given filename. (openstream helper) Note: this method is case-insensitive. :param filename: path of stream in storage tree (except root entry), either: - a string using Unix path syntax, for example: 'storage_1/storage_1.2/stream' - or a list of storage filenames, path to the desired stream/storage. Example: ['storage_1', 'storage_1.2', 'stream'] :returns: sid of requested filename :exception IOError: if file not found /zfile not found) rg basestringsplitrzrr.r8rr)rrjrr.rOs r1_findzOleFileIO._finds$ h +~~c*Hyy Dyy 088>>#tzz|3 0.//D  xxr3c|j|}|j|}|jtk7r t d|j |j |jS)a; Open a stream as a read-only file object (BytesIO). Note: filename is case-insensitive. :param filename: path of stream in storage tree (except root entry), either: - a string using Unix path syntax, for example: 'storage_1/storage_1.2/stream' - or a list of storage filenames, path to the desired stream/storage. Example: ['storage_1', 'storage_1.2', 'stream'] :returns: file object (read-only) :exception IOError: if filename not found, or if this is not a stream. zthis file is not a stream)rr6rr rrr rrrjrr*s r1 openstreamzOleFileIO.openstreamsUjj"$   | +56 6zz%**EJJ77r3cZ|js|j|t|j}|jjs|jj||j|j z}t |jD]\}}||z}||z}|jj|dz|jz||j zz} ||dz kr#|||j z|dz|j z} n|||j zd} |j| | y)Nr$)r)r0rerzr|rn enumerater) rr* data_to_writer  block_sizeidxr sect_base sect_offsetrdata_per_sectors r1_write_mini_streamzOleFileIO._write_mini_streams!  " "4 ())* yy## II & &t ,%%)>)>> "5#3#34 ;IC *I+Kii**9594;K;KKkZ^ZoZoNooFj1n%"/d6K6K0KcTUgY]YnYnMn"o"/d6K6K0K0L"M  ! !&/ : ;r3c $t|ts td|j|}|j|}|j t k7r td|j}|t|k7r td||jkr&|j tk7r|j||S|j}||jdz z|jz}t j#d|zt%|D]}||dz kr<|||jz|dz|jz} t| |jk(szJ|||jzd} t j#d||jt| ||jzfzt| |jz||jzk(sJ|j'||  |j(|}|t,k7r td y#t*$r td wxYw) aD Write a stream to disk. For now, it is only possible to replace an existing stream by data of the same size. :param stream_name: path of stream in storage tree (except root entry), either: - a string using Unix path syntax, for example: 'storage_1/storage_1.2/stream' - or a list of storage filenames, path to the desired stream/storage. Example: ['storage_1', 'storage_1.2', 'stream'] :param data: bytes, data to be written, must be the same size as the original stream. z)write_stream: data must be a bytes stringzthis is not a streamz?write_stream: data must be the same size as the existing stream)r*rr$rNzGwrite_stream: size=%d sectorsize=%d data_sector=%Xh size%%sectorsize=%drz)incorrect last sector index in OLE stream)rgrhrrr6rr rrrerr'r r r rr6rrrrrr) r stream_namerkrr*rrr r" data_sectors r1 write_streamzOleFileIO.write_streams$&GH Hjj%$   | +01 1zz 3t9 ^_ _ $'' 'E,<,< ,J**5$*O Odooa/0T__D  #j01z" NA*Q,"Adoo$51doo8MN ;'898"Adoo$5$67  cT__c+.>t@VWXY;'$//94$//;QQRQ OOD+ . Nxx~- N6 : EF F   NLMM Ns G::Hcz |j|}|j|}|jS#t$rYywxYw)a Test if given filename exists as a stream or a storage in the OLE container, and return its type. :param filename: path of stream in storage tree. (see openstream for syntax) :returns: False if object does not exist, its entry type (>0) otherwise: - STGTY_STREAM: a stream - STGTY_STORAGE: a storage - STGTY_ROOT: the root entry F)rr6rrrs r1get_typezOleFileIO.get_typesA **X&COOC(E## #  s +. ::cZ|j|}|j|}|jS)a Return clsid of a stream/storage. :param filename: path of stream/storage in storage tree. (see openstream for syntax) :returns: Empty string if clsid is null, a printable representation of the clsid otherwise new in version 0.44 )rr6rrs r1getclsidzOleFileIO.getclsids*jj"${{r3cb|j|}|j|}|jS)a9 Return modification time of a stream/storage. :param filename: path of stream/storage in storage tree. (see openstream for syntax) :returns: None if modification time is null, a python datetime object otherwise (UTC timezone) new in version 0.26 )rr6rQrs r1rQzOleFileIO.getmtime$-jj"$~~r3cb|j|}|j|}|jS)a1 Return creation time of a stream/storage. :param filename: path of stream/storage in storage tree. (see openstream for syntax) :returns: None if creation time is null, a python datetime object otherwise (UTC timezone) new in version 0.26 )rr6rTrs r1rTzOleFileIO.getctime3rr3cF |j|}y#t$rYywxYw)a Test if given filename exists as a stream or a storage in the OLE container. Note: filename is case-insensitive. :param filename: path of stream in storage tree. (see openstream for syntax) :returns: True if object exist, else False. TF)rr)rrjrs r1rzOleFileIO.existsBs* **X&C  s   c|j|}|j|}|jtk7r t d|j S)a2 Return size of a stream in the OLE container, in bytes. :param filename: path of stream in storage tree (see openstream for syntax) :returns: size in bytes (long integer) :exception IOError: if file not found :exception TypeError: if this is not a stream. zobject is not an OLE stream)rr6rr rrrs r1get_sizezOleFileIO.get_sizeQsDjj"$   | +9: :zzr3c.|jjS)zp Return root entry name. Should usually be 'Root Entry' or 'R' in most implementations. )rzr.rs r1get_rootentry_namezOleFileIO.get_rootentry_nameas yy~~r3c H|dk(rg}|}t|tsdj|}|j|}i} |j d}t |dd}|j d}t |dd} |j t|dd|j t|j d d z z}t|d } t| tt!|dz } t#| D]} d } t|d| dzz}t|d | dzz}t||}t$j'|d }t(j+d||||fz|j-||d z||||}|||<|S#t$rG} d jt|| } |jt| t| |cYd} ~ Sd} ~ wwxYw#t$r<} d|t|| fz} |jt| t| Yd} ~ d} ~ wwxYw) Return properties described in substream. :param filename: path of stream in storage tree (see openstream for syntax) :param convert_time: bool, if True timestamps will be converted to Python datetime :param no_conversion: None or list of int, timestamps not to be converted (for example total editing time is not a real timestamp) :returns: a dictionary of values indexed by id (integer) NrrQr>rMrIrE****r z6Error while parsing properties header in stream {}: {}rrBUNKNOWN$property id=%d: type=%d/%s offset=%X3Error while parsing property id %d in stream %s: %s)rgrrrrbrrcr BaseExceptionrrrrtypeminrvrerVTrr6r_parse_property)rrjrr streampathrmrkrrfmtid num_propsexcrr" property_idr property_typevt_namers r1rzOleFileIO.getpropertieshs! D M *c**-J __X &  A1Qr7OE A1Sb6NE GGC2J "''#bggaj/!"344AAq I 3s1vz?3 9% EAK E!!QqsUm Q1Q3 #Av && : @KQ^`gioCppq,,Qq+}Vbdqr$)[! E& ; KQQZ #'C   /d3i @K ,! ELj!13O88""#3S$s)DD  Es7BF BG G| }|St jd||fz|S)Nz'property_type == VT_VECTOR | VT_VARIANTr zproperty_type == VT_VECTOR | %sr 5property id=%d: type=%d not implemented in parser yet) VT_BLOBVT_CLSIDVT_CF_parse_property_basic VT_VECTOR VT_VARIANTr6rrrrr&r)rrrr,r-rrv_offcountvaluesszproperty_type_bases r1r'zOleFileIO._parse_propertys  G #}58I'I--amUacpqDAq43i*4 4 II? @C6NEF5\  #Av| 4 33Av|a7GVceqtAB2 a rAv    AY &!.)!;  II7"&&ASU^:__ `C6NEF5\ 221fslKQ^bkakQkmy|IJ2 a r  A IIMQ\^kPll mr3cbd}d}|tk(rt||}|dk\r|dz }d}||fS|tk(rt||}d}||fS|ttt fvrt ||}d}||fS|ttfvrt ||}d}||fS|ttfvr8t ||} ||dz|dz| zdz }|jdd}d| z}||fS|tk(r#t ||} ||dz|dz| z}d| z}||fS|tk(r;t ||dz} |j||dz|dz| dzz}d| dzz}||fS|tk(rt!t ||t!t ||dzd zz}|r}||vryt"j%d ||t'|d z fzt)j(d ddddd} t"j%d |dzz| t)j*|dzz}n|d z}d}||fS|t,k(rt/||}d}||fS|t0k(rt3|||dz}d}||fS|t4k(r#t ||} ||dz|dz| z}d| z}||fS|t6k(rt9t||}d}||fSd}t"j%d||fz||fS)Nrr:r r$rr3r8Converting property #%d to python datetime, value=%d=%fs逖rtimedelta days=%d@T$r@rr>rEr0)VT_I2r}VT_UI2VT_I4VT_INTVT_ERRORrVT_UI4VT_UINTVT_BSTRVT_LPSTRreplacer1 VT_LPWSTRr$ VT_FILETIMEr%r6rfloatrrVT_UI1rsr2rr3VT_BOOLbool) rrrr,r-rrrrr:rs r1r4zOleFileIO._parse_property_basicsED%AvE>!EMEb$; a&(Av\$; [5&(";;AvP$; O67"33AvJ$; I7H"55 Av&(6!8E>!#34 gs35yv$; u')Av&(6!8E>25yj$; i)+ Avax(..q&(57:J/KL519}Z$; Y+-SF^,SF1H5E0F0JK K}$DIIX)5%,x2GHIJ+3*;*;D!Q1a*P'II1U=O5PQR/(2D2DRWY[R[2\\E"X-E8$; 7&(1V9 2$; 1(*qr 23,$; +%'Av&(6!8E>25y $; ')SF^,$;  QU`boTppq$; r3cnt|_|jj||jS)z Parse standard properties streams, return an OleMetadata object containing all the available metadata. (also stored in the metadata attribute of the OleFileIO object) new in version 0.25 )rrlrrs r1 get_metadatazOleFileIO.get_metadata% s)$   &&t,}}r3c  td}|dk(rg}|}t|tsdj|}|j |}g}|j d}t|dd} t |d} g} t| D]n} |j d}t|dd} | |k(s)t |d}|j|d |j t |j d d z z}t |d }|ddd|zz}dd|zz}t |||d z}|d z }t|D]f} |||d z}t ||d z|dz}||dz|dz|zjd jd }|j|dd |dz|z}ht|tt|dz }td|D] } d} t |d| dzz}t |d| dzz}t ||}t j#|d}t$j'd||||fz|t(k(rt+||d z}|dk\r|dz }n|dk(r"t ||dz}||dz|dz|zdz }na|t,k(rt+||d z}nG|t.t0t2fvrt ||d z}n#|t4t6fvrt ||d z}n|t8t:fvr4t ||d z}||dz|dz|zdz }|j=dd}n|t>k(rt ||d z}||dz|dz|z}n|t@k(r1t ||d z}|jC||dz|dz|dzz}n`|tDk(rtGt ||d ztGt ||dzdzz}|r}||vryt$j'd||tI|dz fztKjJdddddd}t$j'd|dzz|tKjL|dzz}n|dz}n|tNk(rtQ||d z}n|tRk(rt||d z|dz}ne|tTk(rt ||d z}||dz|dz|z}n>|tVk(rtYt+||d z}nd}t$j'd ||fz||| dz d!<#q |S#tZ$r<}d"|t]||fz}|j_t`|tc|Yd}~jd}~wwxYw#tZ$r=}d#t]|d$|}|j_t`|tc||cYd}~Sd}~wwxYw)%rs՜.+,NrrQr>rMrIrErr utf_8) property_namerr:rrBr r!r?r@r$rr3rrArBrrCrDr@rr0rr"z0Error while parsing properties header in stream z: )2rrgrrrrbrrrcrrrr%rvrerr&rr6rrEr}rFrGrHrIrJrKrLrMrNr1rOr$rPr%rQrrrRrsr2r3rSrTr#rrrr$)rrjrrFMTID_USERDEFINED_PROPERTIESr(rmrkrrsections_countsection_file_pointersr"r) file_pointerr*PropertyIdentifierAndOffsetr entry_count identifierstr_sizestringr,rr-r.rr:rr+rs r1get_userdefined_propertiesz$OleFileIO.get_userdefined_properties1 s% (..q'r$ D M *c**-J __X & GGBKq2wQ "R >*H QGGBKq"v88#&q":LGGL)"''#bggaj/A*=">>A #Aq I23Aq9}2E/a kME"%auQw&7"8KQJE";/1%&ueQh%7 #&qq%!)'<#=!"57E!GH,,1EME!.!!3+.q&1*+=()&2+frkH6Lq6P(Q!.&!8(+Avz(:!.5&(2K!K),Avz(:!.672C!C(+Avz(:!.7H2E!E ),Avz(:()&1*VaZ%5G!5K(L(- gs(C!.'!9),Avz(:()&1*VaZ%5G(H!.)!; ),Avz(:(,(>(>q!FUVJY^abYbLb?c(d!.+!=(,SFQJ-?(@DQPVYZPZI[D\`bDb(c$0K}4T$'II.h1SSj  CO!4(_6B ',2"H2 !FQ#f"'H>44&'P$2 #/%#-JB8 >8*;$;Gz&       >@>[| {r3rc  ddl}ddl}d}tjtjtj tj tjd}d}|j|}|jddd d |jd dd d |jdddd |jdddd|d|j\}}tdjttt|dk(r0tt |j#|j$|j&rd|_tj*||j(dt-|D]} t/|} tdt|td| j1| j3D]!} | dddk(std| z | j5| d !} t7| j9} | D]c\} } t;| t<t>frt| d"kDr| dd"} t;| t>rd#D]}|tA| vsd$} ntd%| | e |jHra| jK| d !}t|rCtd'| ztM|D]'\}}td(j||d)|d*)$|jNrtd,| j3D]} td-tQd.jS| d-d/0| jU| }|tVk(r/td1| jY| z| j[| std2|zttd3| j\D]G}|td4j|j^|ja|jcIt | je}|jgt| ji}td6|z| jkd7r]td8td9| jUd7td:| jYd7| jkd;r td<td=| jlr:| jlD]*\}}td>j|jn|,n td?| jqy#tB$rtDjGd&| zYwxYw#tDjGd+| zYxYw#tB$rtDjGd5YowxYw#tB$rtDjGd@|zYMwxYw)Az Main function when olefile is runs as a script from the command line. This will open an OLE2 file and display its structure and properties :return: nothing rNr)rinforrcriticalz1usage: %prog [options] [filename2 ...])usagez-c store_true check_streamsz*check all streams (for debugging purposes))actiondesthelpz-pextract_custompropz$extract all user-defined propertiresz-d debug_modez\debug mode, shortcut for -l debug (displays a lot of debug information, for developers only)z-lz --loglevelloglevelstorezBlogging level debug/info/warning/error/critical (default=%default))rlrkdefaultrmz=olefile version {} {} - https://www.decalage.info/en/olefile rz%(levelname)-8s %(message)s)r/rzD--------------------------------------------------------------------z%r: propertiesTr2)r$r:r#r r;r<r=rArBrDrErFrGrHrIrJrKrLrMrNrOrPrQrRrSrTz (binary data)z z&Error while parsing property stream %rz%r: user-defined propertiesz {} {}: {}rZrz3Error while parsing user-defined property stream %rz Checking streams...-rrIrJzsize %dzNOT a stream : type=%dz5Modification/Creation times of all directory entries:z- {}: mtime={} ctime={}zError while parsing metadatazRoot entry name: "%s" worddocumentzThis is a Word document.ztype of stream 'WordDocument':zsize :z macros/vbaz%This document may contain VBA macros.z( Non-fatal issues raised during parsing:rNonezError while parsing file %r)9roptparser&rINFOWARNINGERRORCRITICAL OptionParser add_option parse_argsrr __version____date__rer print_helpexitrorp basicConfigrrrrrsorteditemsrgrrhrrr6 exceptionrnrdrrjrrrr rrr6r.rQrTrVrrrr^rr)rrzDEFAULT_LOG_LEVEL LOG_LEVELSrhparseroptionsrrjr streamnamerkr7rr variablesrvariablest_typer*metarzexctypers r1mainr sM !MMLLOOMM$$  J @E  " " " /F d!$.*Z78] # 1 1*4 1 P &u{{} 5$) /DAq)!j%-@A#&q6B;()#2A)!U3*L!.A'(IaL'8,;(- !. "%A. / j"55(+(F(Fz`d(F(eI"9~ %&Cj&P Q7@7K!tOE8$)-*>*>uhF_`hip`q*r$s!t7 jD$$-."%++- BJ#tCHHZ$89#3G!ll:6G,.i#,,z*BBCz26@A B I J =$3::5::(%..*:<= = G >'')  G))+D )D0 1zz.)016 ^8TUh ^ <=::l+AB = >!!$'$6$6DLGS*++G,<, <= >* D MM7(B C Ds?AV#V#*A?T6*T6>V#A-U-CV#AV# U>0DV#6!UV#UV#U;8V#>V V#V  V##!WW__main__)NNrU)zr __future__rrr __author____all__rrryros.pathrrr&rrrrhrvr%xrangerrritemsizerrr NameError version_inforr~r2r6rrrrrrrrrr r r rr r rVT_EMPTYVT_NULLrErGVT_R4VT_R8VT_CYVT_DATErL VT_DISPATCHrIrSr6 VT_UNKNOWN VT_DECIMALVT_I1rRrFrJVT_I8VT_UI8rHrKVT_VOID VT_HRESULTVT_PTR VT_SAFEARRAY VT_CARRAYVT_USERDEFINEDrMrOrPr1 VT_STREAM VT_STORAGEVT_STREAMED_OBJECTVT_STORED_OBJECTVT_BLOB_OBJECTr3r2r5r&r,varsrkeywordvarrrrrrrrrsr}rrrrrrrRuntimeWarningrrrr rrrr8r3r1rsQ8&x    EEEE e DI 5;;s! FU[[!# FU[[!#F U VV A#! #++A-8! ,          AGQuaq%5 17!kbX"' "zj2Ubv "6Ber"6bg rJ"62lyB8" "k bIR*B);B^b2(  (LGSr{e34   :z C<1,, *"O 7  l X8X8t,P( P(lZ2Z2~qqp/ODd zF_PIBJs#H/H$H! H!$H/.H/