
    ,h                    d   d Z ddlmZ dZdZdZg dZddlZddlZddl	Z	ddl
Z
ddlZddlZddlZddlZddlZeeureZ	 eZ e
j                  d      j2                  d	k(  rdZnL e
j                  d
      j2                  d	k(  rd
Zn* e
j                  d      j2                  d	k(  rdZn ed      	 e ej<                  d   dk  rdZndZej@                  dz   fdZ! e!d      Z"d Z#dZ$dZ%dZ&dZ'dZ(dZ)dZ*dZ+dZ,dZ-dZ.dZ/d	Z0dZ1dZ2dZ3dZ4dZ5dZ6d	Z7dZ8dZ9dZ:dZ;dZ<d Z=d!Z>d"Z?d#Z@d$ZAd%ZBd&ZCd'ZDd(ZEd)ZFd*ZGd+ZHd,ZId-ZJd.ZKd/ZLd0ZMd1ZNd2ZOd3ZPd4ZQd5ZRd6ZSd7ZTd8ZUd9ZVd:ZWd;ZXd<ZYd=ZZd>Z[i Z\ e] e^       j                               D ]  \  Z`Zae`dd d?k(  se`e\ea<    d@Zbd Zcd)Zdd3ZedAZfdBZgdZdCZheeu rdD ZindE Zid[dFZjd[dGZkdH ZldI Zm G dJ dKen      Zo G dL dMeo      Zp G dN dO      Zq G dP dQer      Zs G dR dSej                        Zu G dT dU      Zv G dV dW      ZwdX ZxeydYk(  r ex        yy# e$ r eZY w xY w# e$ r eZY }w xY w)\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-01z0.47zPhilippe Lagadec)	isOleFile	OleFileIOOleMetadataenable_loggingMAGICSTGTY_EMPTYSTGTY_STREAMSTGTY_STORAGE
STGTY_ROOTSTGTY_PROPERTYSTGTY_LOCKBYTESMINIMAL_OLEFILE_SIZEDEFECT_UNSUREDEFECT_POTENTIALDEFECT_INCORRECTDEFECT_FATALDEFAULT_PATH_ENCODING
MAXREGSECTDIFSECTFATSECT
ENDOFCHAINFREESECT	MAXREGSIDNOSTREAMUNKNOWN_SIZE
WORD_CLSIDOleFileIONotClosedNL   Iiz>Need to fix a bug with 32 bit arrays, please contact author...   zutf-8   c                 4   | t         j                  j                  j                  v r(t        j                  |       }|j                  |       |S t        j                  |       }|j                  t        j                                |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.
    )loggingLoggermanager
loggerDict	getLoggersetLevel
addHandlerNullHandler)namelevelloggers      Q/var/www/html/Resume-Scraper/venv/lib/python3.12/site-packages/olefile/olefile.py
get_loggerr2      sy     w~~%%000 ""4(t$F g))+,
OOEM    olefilec                  J    t         j                  t        j                         y)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&   NOTSET r3   r1   r   r      s     LL r3   s   ࡱl    l    l    l              i         	   
                                                               @   A   B   C   D   E   F   G   H      VT_z$00020900-0000-0000-C000-000000000046(   i   c                    d}|&t        |      t        k\  r|dt        t               }nyt        | d      r<t        | d      r0| j	                  t        t                    }| j                  d       nht        | t              r%t        |       t        k\  r| dt        t               }n3t        | d      5 }|j	                  t        t                    }ddd       |t        k(  ryy# 1 sw Y   xY w)a  
    Test if a file is an OLE container (according to the magic bytes in its header).

    .. note::
        This function only checks the first 8 bytes of the file, not the
        rest of the OLE structure.
        If data is provided, it also checks if the file size is above
        the minimal size of an OLE file (1536 bytes).
        If filename is provided with the path of the file on disk, the file is
        open only to read the first 8 bytes, then closed.

    .. versionadded:: 0.16

    :param filename: filename, contents or file-like object of the OLE file (string-like or file-like object)

        - if data is provided, filename is ignored.
        - if filename is a unicode string, it is used as path of the file to open on disk.
        - if filename is a bytes string smaller than 1536 bytes, it is used as path
          of the file to open on disk.
        - [deprecated] if filename is a bytes string longer than 1535 bytes, it is parsed
          as the content of an OLE file in memory. (bytes type only)
          Note that this use case is deprecated and should be replaced by the new data parameter
        - if filename is a file-like object (with read and seek methods),
          it is parsed as-is.
    :type filename: bytes, str, unicode or file-like object

    :param data: bytes string with the contents of the file to be checked, when the file is in memory
                 (added in olefile 0.47)
    :type data: bytes

    :returns: True if OLE, False otherwise.
    :rtype: bool
    NFreadseekr   rbT)	lenr   r   hasattrrb   rc   
isinstancebytesopen)filenamedataheaderfps       r1   r   r     s    D Ft9,,+3u:&F 	6	"wx'@s5z*a	He	$X:N)N+3u:& (D! 	)RWWSZ(F	)	) 	)s   4C&&C/c                     t        |       S N)ordcs    r1   i8rs   O  s    1vr3   c                 4    | j                   t        u r| S | d   S )Nr   )	__class__intrq   s    r1   rs   rs   S  s    KK3&q0AaD0r3   c                 @    t        j                  d| ||dz          d   S )z
    Converts a 2-bytes (16 bits) string to an integer.

    :param c: string containing bytes to convert
    :param o: offset of bytes to convert in string
    z<Hr:   r   structunpackrr   os     r1   i16r}   W  $     ==q1Q3x(++r3   c                 @    t        j                  d| ||dz          d   S )z
    Converts a 4-bytes (32 bits) string to an integer.

    :param c: string containing bytes to convert
    :param o: offset of bytes to convert in string
    z<Ir    r   rx   r{   s     r1   i32r   a  r~   r3   c           
          t        |       dk(  sJ | j                  d      sydt        | d      t        | d      t        | d      ft	        t        t        | dd             z   z  S )	z^
    Converts a CLSID to a human-readable string.

    :param clsid: string of length 16.
    rE        z0%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02Xr   r    r<   r>   )re   stripr   r}   tuplemaprs   )clsids    r1   _clsidr   k  sg     u: ;;u4%mS]CqM:#b%"+&'() *r3   c                 n    t        j                   dddddd      }|t        j                  | dz        z   S )zD
    convert FILETIME (64 bits int) to Python datetime.datetime
    A  r$   r   r@   microseconds)datetime	timedelta)filetime_FILETIME_null_dates     r1   filetime2datetimer   |  s9     #++D!Q1a@!3!32!NNNr3   c                       e Zd ZdZy)OleFileErrorz-
    Generic base error for this module.
    N__name__
__module____qualname____doc__r8   r3   r1   r   r          	r3   r   c                       e Zd ZdZy)NotOleFileErrorz?
    Error raised when the opened file is not an OLE file.
    Nr   r8   r3   r1   r   r     r   r3   r   c                   2    e Zd ZdZg dZg dZd Zd Zd Zy)r   aT  
    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
    )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_targetrh   lines
paragraphsslidesnoteshidden_slidesmm_clips
scale_cropheading_pairstitles_of_partsr(   companylinks_dirtychars_with_spacesunused
shared_doc	link_basehlinkshlinks_changedversiondig_sigcontent_typecontent_statuslanguagedoc_versionc                    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| _-        d| _.        y)z_
        Constructor for OleMetadata
        All attributes are set to None by default
        N)/r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rh   r   r   r   r   r   r   r   r   r   r(   r   r   r   r   r   r   r   r   r   r   r   r   r   r   selfs    r1   __init__zOleMetadata.__init__  s_    
!## #$(! #' 


!!#!%" "r3   c                 8   | j                   | j                  z   D ]  }t        | |d        |j                  d      rg|j	                  dddg      }t        t        | j                               D ]1  }|j                  |dz   d      }t        | | j                   |   |       3 |j                  d      rf|j	                  dd      }t        t        | j                              D ]1  }|j                  |dz   d      }t        | | j                  |   |       3 yy)	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
        NzSummaryInformationTr@   )convert_timeno_conversionr$   zDocumentSummaryInformationr   )SUMMARY_ATTRIBSDOCSUM_ATTRIBSsetattrexistsgetpropertiesrangere   get)r   ole_fileattribpropsr"   values         r1   parse_propertieszOleMetadata.parse_properties  s&    ++d.A.AA 	(FD&$'	(??34 **+C8<RD + RE 3t3345 >		!A#t,d2215u=> ??;<**+K8< + >E 3t2234 =		!A#t,d11!4e<= =r3   c           	      4   t        d       | j                  D ]2  }t        | |      }t        dj                  |t	        |                   4 t        d       | j
                  D ]2  }t        | |      }t        dj                  |t	        |                   4 y)z<
        Dump all metadata, for debugging purposes.
        z*Properties from SummaryInformation stream:- {}: {}z2Properties from DocumentSummaryInformation stream:N)printr   getattrformatreprr   )r   propr   s      r1   dumpzOleMetadata.dump#  s     	:;(( 	8DD$'E*##D$u+67	8 	BC'' 	8DD$'E*##D$u+67	8r3   N)	r   r   r   r   r   r   r   r   r   r8   r3   r1   r   r     s(     HOEN5 n =D8r3   r   c                   *     e Zd ZdZd fd	Zd Z xZS )r   zR
    Warning type used when OleFileIO is destructed but has open file handle.
    c                 8    t         t        |           || _        y ro   )superr   r   stack_of_open)r   r   ru   s     r1   r   zOleFileIONotClosed.__init__4  s     $02*r3   c                     d}| j                   r/dj                  |ddg| j                   j                         z         S |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   
zStacktrace of open() call:
)r   joinr   )r   msgs     r1   __str__zOleFileIONotClosed.__str__8  sM    3 77C'EF--4467 8 8 Jr3   ro   )r   r   r   r   r   r   __classcell__)ru   s   @r1   r   r   0  s    +	r3   r   c                       e Zd ZdZd Zy)	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	                 "	   t         j                  d       t         j                  d|||||t        |      t        |      fz         || _        | j                  j
                  j                  rt        d      d}	|t        k(  r%t        |      |z  }d}	t         j                  d       ||dz
  z   |z  }
t         j                  d|
z         |
t        |      kD  r | j                  j                  t        d	       g }|d
k(  r>|t        k7  r5t         j                  d       | j                  j                  t        d       t        |
      D ]  }t         j                  d||fz         |t        k(  rO|	rt         j                  d        nt         j                  d       | j                  j                  t        d       |d
k  s|t        |      k\  r`t         j                  d||t        |      fz         t         j                  d||
fz         | j                  j                  t        d        n	 |j                  |||z  z          |j                  |      }t        |      |k7  r|t        |      dz
  k7  rt         j                  d|t        |      |||z  z   |t        |      fz         t         j                  d|||z  z   t        |      z   z         | j                  j                  t        d       |j!                  |       	 ||   dz  } dj%                  |      }t        |      |k\  r0t         j                  dt        |      |fz         |d| }|| _        n|	r2t         j                  dt        |      z         t        |      | _        nSt         j                  dt        |      |fz         t        |      | _        | j                  j                  t        d       t(        j*                  j-                  | |       y# t        $ rF t         j                  d||||z  z   |fz         | j                  j                  t        d       Y  Ew xY w# t"        $ r% | j                  j                  t        d       Y  vw xY w) 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
        zOleStream.__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 larger   z!size == 0 and sect != ENDOFCHAIN:z+incorrect OLE sector index for empty streamzReading stream sector[%d] = %Xhz6Reached ENDOFCHAIN sector for stream with unknown sizez$sect=ENDOFCHAIN before expected sizezincomplete OLE streamzsect=%d (%X) / len(fat)=%dzi=%d / nb_sectors=%d,incorrect OLE FAT, sector index out of rangezsect=%d, seek=%d, filesize=%dOLE sector index out of rangez9sect=%d / len(fat)=%d, seek=%d / filesize=%d, len read=%dzseek+len(read)=%dincomplete OLE sectorr9   r3   z3Read 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)r6   debugre   r   olerm   closedOSErrorr   _raise_defectr   r   r   rc   	Exceptionrb   append
IndexErrorr   sizeioBytesIOr   )r   rm   sectr   offset
sectorsizefatfilesize	olefileiounknown_size
nb_sectorsrk   r"   sector_datas                 r1   r   zOleStream.__init__Z  s    			'(		Y4VJs3xbBC 	D 88;;NOO < s8J&DLII23jl+
:
		#j01 C HH""#35_` 19+II9:HH""#35bc z" 3	AII71d)CDz!IIVW IIDEHH**+;=TUAvs3x		6$c#h9OOP		01j/AB &&'79ghd!223 ''*-K
 ;+s3xz0B		U3s8VJtO%;Xs;GWXY Z		-
41GKHX1XYZ&&'79PQKK$4y:-]3	n xx~t9IIKsSWyZ^N__`;DDI IIKcRViWXD	DI IIQUXY]U^`dTeefD	DIHH""#35\]


D$'_  		96*T/18<= >&&'79XY(  &&'79gh	s%   4PQ A
QQ )RRN)r   r   r   r   r   r8   r3   r1   r   r   F  s    &|(r3   r   c                       e Zd ZdZdZdZ ej                  e      ek(  sJ d Zd Z	d Z
d Zd Zd	 Zd
 Zd ZddZd Zd Zy)OleDirectoryEntryz@
    OLE2 Directory Entry pointing to a stream or a storage
    z<64sHBBIII16sIQQIII   c                 P   || _         || _        g | _        i | _        d| _        t        j                  t        j                  |      \  | _	        | _
        | _        | _        | _        | _        | _        }| _        | _        | _        | _        | _        | _        | j                  t,        t.        t0        t2        fvr|j5                  t6        d       | j                  t,        k(  r|dk7  r|j5                  t6        d       |dk(  r)| j                  t,        k7  r|j5                  t6        d       | j                  dkD  r|j5                  t6        d       d| _
        | j                  d| j                  d	z
   | _        |j;                  | j8                        | _        t>        jA                  d
| j                   tC        | j<                        fz         t>        jA                  d| j                  z         t>        jA                  d| j&                  z         t>        jA                  d| j                  | j                  | j                  fz         |jD                  dk(  r| j*                  dk7  ri| j*                  dk7  rZt>        jA                  d|jD                  | j(                  | j*                  | j*                  fz         |j5                  tF        d       | j(                  | _$        n*| j(                  tK        | j*                        dz  z   | _$        t>        jA                  d| jH                  | j(                  | j*                  fz         tM        |      | _'        | j                  t.        k(  r%| jH                  dk7  r|j5                  tP        d       d| _)        | j                  t,        t0        fv rp| jH                  dkD  ra| jH                  |jT                  k  r| j                  t0        k(  rd| _)        nd| _)        |jW                  | j&                  | jR                         d| _,        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
        Fzunhandled OLE storage typer   zduplicate OLE root entryzincorrect OLE root entryrU   z(incorrect DirEntry name length >64 bytesNr:   zDirEntry SID=%d: %sz - type: %dz - sect: %Xhz% - SID left: %d, right: %d, child: %d   r9   z+sectorsize=%d, sizeLow=%d, sizeHigh=%d (%X)zincorrect OLE stream size    z% - size: %d (sizeLow=%d, sizeHigh=%d)zOLE storage with size>0T)-sidr4   kids	kids_dictusedry   rz   r  STRUCT_DIRENTRYname_raw
namelength
entry_typecolorsid_left	sid_right	sid_childdwUserFlags
createTime
modifyTime
isectStartsizeLowsizeHighr   r   r
   r	   r   r   
name_utf16_decode_utf16_strr.   r6   r   r   r  r   r   longr   r   r   
is_minifatminisectorcutoff_check_duplicate_stream
sect_chain)r   entryr  r   r   s        r1   r   zOleDirectoryEntry.__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$))_*EEF		-$//12		.4??23		9T]]NNDNN=, , 	- #%}}!dmmz&A		G#..dmmT]][\ ]&&}6QRDIT]](;R(?@DI		9TYYVZVcVc<ddeE]
 ??m+		Q""#35NO??z<88TYYq[yy8444-"&"',,T__dooNr3   c                    | j                   ry| j                  t        t        fvs| j                  dk(  ryt               | _         | j                  r|j                  s|j                          | j                  }|t        k7  rQ| j                   j                  |       | j                  r|j                  |   }n|j                  |   }|t        k7  rPyy)z
        Build the sector chain for a stream (from the FAT or the MiniFAT)

        :param OleFileIO ole_file: OleFileIO object containing this directory entry
        :return: nothing
        Nr   )r)  r  r   r
   r   listr&  minifatloadminifatr   r   r   r  )r   r   	next_sects      r1   build_sect_chainz"OleDirectoryEntry.build_sect_chainX  s     ????:|"<<		Q&??8#3#3  "OO	:%OO""9-$,,Y7	$LL3	 :%r3   c                    t         j                  d| j                  t        | j                        | j
                  fz         | j
                  t        k7  r6| j                  | j
                         | j                  j                          yy)z
        Read and build the red-black tree attached to this OleDirectoryEntry
        object, if it is a storage.
        Note that this method builds a tree of all subentries, so it should
        only be called for the root object once.
        z.build_storage_tree: SID=%d - %s - sid_child=%dN)
r6   r   r  r   r.   r  r   append_kidsr  sortr   s    r1   build_storage_treez$OleDirectoryEntry.build_storage_trees  sg     			Bxxdii$..9: 	;>>X% T^^, IINN &r3   c                    t         j                  d|z         |t        k(  ry|dk  s"|t        | j                  j
                        k\  r!| j                  j                  t        d       y| j                  j                  |      }t         j                  d|j                  t        |j                        |j                  |j                  |j                  fz         |j                  r!| j                  j                  t        d       yd|_        | j!                  |j                         |j                  j#                         }|| j$                  v r | j                  j                  t        d       | 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)
        zappend_kids: child_sid=%dNr   zOLE 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)r6   r   r   re   r4   
direntriesr   r   _load_direntryr  r   r.   r  r  r  r  r2  lowerr  r  r   r4  )r   	child_sidchild
name_lowers       r1   r2  zOleDirectoryEntry.append_kids  sa    			-	9:  Q;)S)@)@%AALL&&'79Z[ LL//	:EII`99d5::.QVQ`Q`ab c zz**+;9;EJ U^^,))+JT^^+**+;79 IIU#).DNN:&U__-$$&r3   c                 4    | j                   |j                   k(  S zCompare entries by namer.   r   others     r1   __eq__zOleDirectoryEntry.__eq__  s    yyEJJ&&r3   c                 4    | j                   |j                   k  S r=  r>  r?  s     r1   __lt__zOleDirectoryEntry.__lt__  s    yy5::%%r3   c                 &    | j                  |       S ro   )rA  r?  s     r1   __ne__zOleDirectoryEntry.__ne__  s    ;;u%%%r3   c                 J    | j                  |      xs | j                  |      S ro   )rA  rC  r?  s     r1   __le__zOleDirectoryEntry.__le__  s    {{5!7T[[%77r3   c                    g d}	 || j                      }t        d|z  t        | j                        z   |d       | j                   t
        t        fv rt        | j                  dd       t                | j                   t        t        fv r*| j                  rt        d|z  d| j                  z  z          | j                  D ]  }|j                  |dz           y# t        $ r d}Y w xY w)	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) endrh   z{%s}r:   N)r  r   r   r   r.   r
   r   r   r   r   r  r   )r   tabTYPES	type_namekids        r1   r   zOleDirectoryEntry.dump  s    )	$doo.I 	c#gTYY'<??|Z88$))W#.??}j99djj#c'FTZZ//099 	CHHS1W	  	$#I	$s   C C,+C,c                 L    | j                   dk(  ryt        | j                         S )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
        r   N)r  r   r   s    r1   getmtimezOleDirectoryEntry.getmtime  "     ??a 11r3   c                 L    | j                   dk(  ryt        | j                         S )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
        r   N)r  r   r   s    r1   getctimezOleDirectoryEntry.getctime  rR  r3   Nr   )r   r   r   r   r  DIRENTRY_SIZEry   calcsizer   r0  r4  r2  rA  rC  rE  rG  r   rQ  rT  r8   r3   r1   r  r    sc    * ,OM6???+}<<_B46.,'\'&&8$22r3   r  c                   4   e Zd ZdZdeddefdZd Zd Zd Z	e
fdZd-d	Zd.d
Zd Zd.dZd.dZd/dZd/dZd Zd Zd Zd Zd Zd0dZd0dZd Zd Zd ZedfdZd1dZd1dZ d Z!d Z"d Z#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)3r   a  
    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                  ||       yy# tV        $ r | jY                  d        w xY w)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_modewarn)-_raise_defects_levelparsing_issuesrZ  path_encoding	_filesize
ministream_used_streams_fat_used_streams_minifat
byte_orderdirectory_fpr6  dll_versionr  first_difat_sectorfirst_dir_sectorfirst_mini_fat_sectorrm   header_clsidheader_signaturemetadatamini_sector_shiftmini_sector_sizemini_stream_cutoff_sizer-  minifatsectr'  minisectorsizeminor_versionnb_sectnum_difat_sectorsnum_dir_sectorsnum_fat_sectorsnum_mini_fat_sectors	reserved1	reserved2rootsector_shiftsector_sizetransaction_signature_numberwarn_if_not_closed_we_opened_fp_open_stackri   r   _close)r   rj   raise_defectsrZ  r   r_  s         r1   r   zOleFileIO.__init__  s   : %2! !$*!#%'" "& $%)"  $!% $'+$ $"!!%##$(!	 ,0)"'"		(z	:   's   1E E#c                 (    | j                  d       y)z?Destructor, ensures all file handles are closed that we opened.Tr[  Nr  r   s    r1   __del__zOleFileIO.__del__m  s    r3   c                     | S ro   r8   r   s    r1   	__enter__zOleFileIO.__enter__s  s    r3   c                 (    | j                  d       y )NFr[  r  )r   argss     r1   __exit__zOleFileIO.__exit__w  s    r3   c                     || j                   k\  rt        j                  |        ||      | j                  j	                  ||f       t        j                  |       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]  r6   errorr^  r   warning)r   defect_levelmessageexception_types       r1   r   zOleFileIO._raise_defect{  sP    " 4444IIg )) &&'@AKK r3   c                 z    |j                  d|      }| j                  r|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
        zUTF-16LE)decoder_  encode)r   	utf16_strerrorsunicode_strs       r1   r$  zOleFileIO._decode_utf16_str  s@      &&z6:%%d&8&8&AA r3   c                 8   || _         t        |d      r|| _        nt        |t              r-t        |      t        k\  rt        j                  |      | _        nB| j                   rd}nd}t        ||      | _        d| _
        t        j                         | _        d}| j                  j                  dt        j                          	 | j                  j#                         }| j                  j                  d       || _        t&        j)                  d| j$                  | j$                  fz         g | _        g | _        | j                  j/                  d      }t        |      dk7  s|dd	 t0        k7  rGt&        j)                  d
j3                  |dd	 t0                     | j5                  t6        dt8               d}t;        j<                  |      }t&        j)                  d||dz   fz         |d| }t;        j>                  ||      \  | _         | _!        | _"        | _#        | _$        | _%        | _&        | _'        | _(        | _)        | _*        | _+        | _,        | _-        | _.        | _/        | _0        | _1        t&        j)                  t;        j>                  ||             | j@                  t0        k7  r| j5                  t6        d       | jB                  te        d      k7  r| j5                  tf        d       t&        j)                  d| jD                  z         t&        j)                  d| jF                  z         | jF                  dvr| j5                  tf        d       t&        j)                  d| jH                  z         | jH                  dk7  r| j5                  tf        d       d| jJ                  z  | _4        t&        j)                  d| jh                  z         | jh                  dvr| j5                  tf        d       | jF                  dk(  r| jh                  dk7  s| jF                  dk(  r%| jh                  dk7  r| j5                  tf        d        d| jL                  z  | _5        t&        j)                  d!| jj                  z         | jj                  d"vr| j5                  tf        d#       | jN                  dk7  s| jP                  dk7  r| j5                  tf        d$       t&        j)                  d%| jR                  z         | jh                  dk(  r%| jR                  dk7  r| j5                  tf        d&       t&        j)                  d'| jT                  z         t&        j)                  d(| jV                  z         t&        j)                  d)| jX                  z         | jX                  dk7  r| j5                  tl        d*       t&        j)                  d+| jZ                  z         | jZ                  dk7  r?| j5                  tf        d,       t&        jo                  d-| jZ                  z         d| _-        t&        j)                  d.| j\                  z         t&        j)                  d/| j^                  z         t&        j)                  d0| j`                  z         t&        j)                  d1| jb                  z         || jh                  z   d2z
  | jh                  z  d2z
  | _8        t&        j)                  d3| jp                  | jp                  fz         ts        |d	d4       | _!        | jh                  | _:        | jj                  | _;        | jZ                  | _<        | j{                  | jV                         | j^                  r| j{                  | j\                         | jb                  r| j{                  | j`                         | j}                  |       | j                  | jV                         | j\                  | _@        y# | j                  j                  d       w xY w)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)
        rb   zr+brd   Tr   zFile size: %d bytes (%Xh)r  Nr>   zMagic = {!r} instead of {!r}z#not an OLE2 structured storage filez<8s16sHHHHHHLLLLLLLLLLzfmt_header size = %d, +FAT = %di  zincorrect OLE signaturerE   zincorrect CLSID in OLE headerzMinor Version = %dz%DLL Version   = %d (expected: 3 or 4))r#   r    z"incorrect DllVersion in OLE headerz#Byte Order    = %X (expected: FFFE)i  z!incorrect ByteOrder in OLE headerr:   z0Sector Size   = %d bytes (expected: 512 or 4096))r  r^   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))rU   z(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 headerzNumber of FAT sectors = %dzFirst 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 %dzFirst MiniFAT sector      = %XhzNumber of MiniFAT sectors = %dzFirst DIFAT sector        = %XhzNumber of DIFAT sectors   = %dr$   z/Maximum number of sectors in the file: %d (%Xh)rM   )ArZ  rf   rm   rg   rh   re   r   r   r  ri   r  	tracebackextract_stackr  rc   osSEEK_ENDtellr`  r6   r   rb  rc  rb   r   r   r   r   r   ry   rW  rz   rk  rj  rr  rf  rd  r{  rm  rx  ry  ru  rv  rh  r}  ro  ri  rw  rg  rt  	bytearrayr   r|  rn  r   r  rs  r   r  rq  r'  r(  loadfatloaddirectoryrp  )	r   rj   rZ  moder  rl   
fmt_headerheader_sizeheader1s	            r1   ri   zOleFileIO.open  s   " % 8V$ DG%(S]>R-R jj*DG   8T*DG!%D(668D
 Q$	ww||~HGGLLO!		-0PPQ "$%'"c"v;#u!4II4;;F2AJNO|-RTcdN .
ooj1		4[SXEX7YY[+&( MM*g.'	
!O"NN  !-(&%#"		6==89  E)|-FG	"-/1PQ		'$*<*<<>		:T=M=MMO6) /1UV		84??JL??f$/1TU d///		EHXHXXZ;./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		58L8LLNS T%9%91%</1fg		/$2F2FFH		2T5J5JJL		9D<]<]]_
 ,,1/1hi		DtGcGcce ''61/1bcKKd445 6+1D(		4t7Q7QQS		3d6O6OOQ		4t7N7NNP		3d6L6LLN #T%5%55a7D<L<LLPQQ		DVZVbVbGccd
 #6!B<0 **"33 $ < < 	$$T%:%:;$$(()C)CD!!(()@)@A 	V 	400155[ GGLLOs   _< <`c                 (    | j                  d       y)z
        close the OLE file, release the file object if we created it ourselves.

        Leaves the file handle open if it was provided by the caller.
        Fr[  Nr  r   s    r1   closezOleFileIO.close  s     	r3   c                     | j                   rX|r4| j                  r(t        j                  t	        | j
                               | j                  j                          d| _         yy)z3Implementation of close() with internal arg `warn`.FN)r  r~  warningsr\  r   r  rm   r  )r   r\  s     r1   r  zOleFileIO._close  sJ    // 01A1ABCGGMMO!&D r3   c                 $   |r%t         j                  d|z         | j                  }n=t         j                  d|z         |t        t        t
        t        fv ry| j                  }||v r| j                  t        d       y|j                  |       y)ag  
        Checks if a stream has not been already referenced elsewhere.
        This method should only be called once for each known stream, and only
        if stream size is not null.

        :param first_sect: int, index of first sector of the stream in FAT
        :param minifat: bool, if True, stream is located in the MiniFAT, else in the FAT
        z,_check_duplicate_stream: sect=%Xh in MiniFATz(_check_duplicate_stream: sect=%Xh in FATNzStream referenced twice)r6   r   rc  r   r   r   r   rb  r   r   r   )r   
first_sectr-  used_streamss       r1   r(  z!OleFileIO._check_duplicate_stream  s     IIDzQR55LII@:MNggjBB11L %/1JK
+r3   c                    d}t         dt        dt        dt        di}t	        |      }||z   dz
  |z  }t        dd	       t        |      D ]  }t        d
|z  d	        t                t        |      D ]p  }||z  }	t        d||	z   z  d	       t        |	|	|z         D ]:  }||k\  r n3||   }
|
dz  }||v r||   }n|
|dz   k(  rd}nd
|
z  }t        |d	       < t                r y)zU
        Display a part of FAT in human-readable form for debugging purposes
        r>   z..free..z[ END. ]zFATSECT zDIFSECT r$   indexrI  rJ  %8X%6X:r9   z    --->N)r   r   r   r   re   r   r   )r   r  
firstindexVPLfatnamesnbsectnlinesr"   lr  r  auxr.   s                r1   dumpfatzOleFileIO.dumpfat  s   
 



	 S*Q,$g3s 	&A%!)%	&v 	AcEE&Ju,-375%), %f91vZ'(?#C=Dqs{)$t|d$% G!	r3   c                    d}t        j                   t        |      }t        j                  dk(  r|j	                          t        |      }||z   dz
  |z  }t        dd       t        |      D ]  }t        d|z  d        t                t        |      D ]V  }||z  }	t        d||	z   z  d       t        |	|	|z         D ]   }||k\  r n||   }
d|
z  }t        |d       " t                X y	)
zS
        Display a sector in a human-readable form, for debugging purposes
        r>   bigr$   r  rI  rJ  r  r  N)arrayUINT32sys	byteorderbyteswapre   r   r   )r   sectorr  r  rL  r  r  r"   r  r  r  r.   s               r1   dumpsectzOleFileIO.dumpsect  s     kk&&)==E!LLNS*Q,$g3s 	&A%!)%	&v 		AcEE&Ju,-375%), %f91vt|d$% G		r3   c                     t        j                   t        |      }t        j                  dk(  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  )r  r  r  r  r  )r   r  as      r1   
sect2arrayzOleFileIO.sect2array  s.     KK%==E!JJLr3   c                    t        |t        j                        r|}nE| j                  |      }t        j	                  t
        j                        r| j                  |       d}|D ]  }|dz  }t        j                  d|z         |t        k(  s	|t        k(  rt        j                  d        |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.
        Nr9   z
isect = %Xzfound end of sector chain)rg   r  r  r6   isEnabledForr&   DEBUGr  r   r   r   getsectr  )r   r  fat1isectsnextfats         r1   loadfat_sectzOleFileIO.loadfat_sect  s     dEKK(D ??4(D.d#  	*EJ&EIIlU*+
"ex&7		56  U#A ooa(Gxx')DH	* r3   c                    t         j                  d       |dd }t         j                  dt        |      t        |      dz  fz         t        j                  t              | _        | j                  |       | j                  dk7  rt         j                  d       | j                  dk  r| j                  t        d	       | j                  | j                  k\  r| j                  t        d
       t         j                  d       | j                  dz  dz
  }| j                  dz
  |z   dz
  |z  }t         j                  d|z         | j                  |k7  rt        d      | j                  }t!        |      D ]  }t         j                  d||fz         | j#                  |      }| j%                  |      }t         j'                  t(        j*                        r| j-                  |       | j                  |d|        ||   }t         j                  d|z          |t.        t0        fvr t        d      t         j                  d       t        | j
                        | j                  kD  rUt         j                  dt        | j
                        | j                  fz         | j
                  d| j                   | _        t         j                  dt        | j
                        | j                  fz         t         j'                  t(        j*                        r1t         j                  d       | j3                  | j
                         yy)z%
        Load the FAT table.
        zDLoading the FAT table, starting with the 1st sector after the headerL   r  zlen(sect)=%d, so %d integersr    r   z)DIFAT is used, because file size > 6.8MB.m   z#incorrect DIFAT, not enough sectorsz)incorrect DIFAT, first index out of rangezDIFAT analysis...r$   znb_difat = %dzincorrect DIFATzDIFAT block %d, sector %XNznext DIFAT sector: %Xzincorrect 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:)r6   r   re   r  r  r  r  rt  rv  r   r   rg  rs  r   r  IOError	iterranger  r  r  r&   r  r  r   r   r  )	r   rl   r  nb_difat_sectorsnb_difatisect_difatr"   sector_difatdifats	            r1   r  zOleFileIO.loadfat!  s    			XYb~		1SYD	14MMO
 ;;v&$ !!Q&IIAB ##s* ""#35Z[&&$,,6""<1\]II*, !% 2A5,,S03CCAEHXXHII13%%1/0011Kx( C		6![9IIK#||K85##GMM2MM,/!!%(9)9":;#$45		2[@BC :x"88677 II<= txx=4<<'II9S]DLL<YYZxx.DH		JcRVRZRZm]a]i]iMjjkGMM*IIhLL" +r3   c                 B   | j                   | j                  z  }| j                  j                  | j                  z   dz
  | j                  z  }|dz  }t
        j                  d| j                  | j                   |||fz         ||kD  r| j                  t        d       | j                  | j                  |d      j                         }| j                  |      | _        t
        j                  dt        | j                        |fz         | j                  d| | _        t
        j                  d	t        | j                        z         t
        j                  t         j"                        r1t
        j                  d
       | j%                  | j                         yy)z)
        Load the MiniFAT table.
        r$   r    zaloadminifat(): minifatsect=%d, nb FAT sectors=%d, used_size=%d, stream_size=%d, nb MiniSectors=%dz%OLE MiniStream is larger than MiniFATT	force_FATz$MiniFAT shrunk from %d to %d sectorsNzloadminifat(): len=%dz	
MiniFAT:)rw  r|  rz  r   rn  r6   r   rp  r   r   _openrb   r  r-  re   r  r&   r  r  )r   stream_sizenb_minisectors	used_sizer  s        r1   r.  zOleFileIO.loadminifatt  sN    //$2B2BB ))..4+@+@@BtG\G\\"Q&			ut88)[R`ab 	c{"/1XYJJt''JEJJL q)		8C<M~;^^_||O^4		)C,==>GMM*IIl#LL& +r3   c                    	 | j                   j                  | j                  |dz   z         | j                   j                  | j                        }t        |      | j                  k7  rDt        j                  d|t        |      | j                  fz         | j                  t        d       |S # t        $ rN t        j                  d|| j                  |dz   z  | j                  fz         | j                  t        d       Y w xY w)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=%dr   z*getsect(): sect=%X, read=%d, sectorsize=%dr   )rm   rc   r  r   r6   r   r`  r   r   rb   re   )r   r  r  s      r1   r  zOleFileIO.getsect  s    $	NGGLLDF34
 doo.v;$//)IIBs6{DOO45 6|-DE  	NII@tQ/@A B|-LM	Ns   +B0 0ADDc                    t        |t              st        d      t        |t              rt        |      dk7  rt        d      	 | j                  j                  | j                  |dz   z         t        |      | j                  k  r||| j                  t        |      z
  z  z  }n#t        |      | j                  kD  rt        d      | j                  j                  |       y# t        $ rN t        j                  d|| j                  |dz   z  | j                  fz         | j                  t        d       Y w xY w)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=%dr   Data is larger than sector sizeN)rg   rh   	TypeErrorre   rm   rc   r  r   r6   r   r`  r   r   
ValueErrorwrite)r   r  rk   paddings       r1   
write_sectzOleFileIO.write_sect  s    $&EFF'5)S\1_RSS	NGGLLDF34
 t9t&GtT:;;DY(>??d  	NIICtQ/@A B|-LM	Ns   +C' 'AD>=D>c                    t        |t              st        d      t        |t              rt        |      dk7  rt        d      	 | j                  j                  |       t        |      }|| j                  k  r||| j                  |z
  z  z  }| j                  |k  rt        d      | j                  j                  |       y# t        $ r= t        j                  d|| j                  fz         | j                  t        d       Y w xY w)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=%dr   r  N)rg   rh   r  re   rm   rc   r   r6   r   r`  r   r   rn  r  r  )r   fp_posrk   r  len_datas        r1   _write_mini_sectzOleFileIO._write_mini_sect  s     $&JKK'5)S\Q->WXX	NGGLL 
 t9d+++Gt44x?@@D  8+>??d  	NIIAt~~./ 0|-LM	Ns   C ADDc                    t         j                  d       | j                  |d      | _        | j                  j                  dz  }t         j                  d| j                  j                  |fz         dg|z  | _        | j                  d      }| j
                  d   | _        | j                  j                          y)z]
        Load the directory.

        :param sect: sector index of directory stream.
        zLoading the Directory:Tr  r  z&loaddirectory: size=%d, max_entries=%dNr   )	r6   r   r  re  r   r6  r7  rz  r4  )r   r  max_entries
root_entrys       r1   r  zOleFileIO.loaddirectory  s     			*+ !JJttJ< '',,3		:##[12 	3  &;. ((+
OOA&	 			$$&r3   c                    |dk  s|t        | j                        k\  r| j                  t        d       | j                  |   %| j                  t        d       | j                  |   S | j
                  j                  |dz         | j
                  j                  d      }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.
        r   z OLE directory index out of rangez'double reference for OLE stream/storager  )	re   r6  r   r   r   re  rc   rb   r  )r   r  r*  s      r1   r7  zOleFileIO._load_direntry  s     q5CT__--|-OP??3+/9; ??3''sSy)!!&&s+0TBs##r3   c                 8    | j                   j                          y)z5
        Dump directory (for debugging only)
        N)rz  r   r   s    r1   dumpdirectoryzOleFileIO.dumpdirectory,  s     			r3   c           
         t         j                  d||t        |      fz         || j                  k  r|s| j                  s| j                          | j                  j                  }t         j                  d| j                  j                  |fz         | j                  | j                  j                  |d      | _        t        | j                  ||d| j                  | j                  | j                  j                  |       S t        | 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=%dTr  r   )rm   r  r   r  r  r  r  r  )r6   r   strr'  ra  r.  rz  r   r   r  r   rq  r-  rm   r  r  r`  )r   startr   r  size_ministreams        r1   r  zOleFileIO._open2  s    			ED#i.)* 	+ $'''	??  " #'))..		AYY))?;< ="&**TYY-A-A#t #- #5e$$%$2E2E!%8L8L'+- - e$$(OO(,TXX&*nn'+	- -r3   c                 ~   ||j                   gz   }|j                  D ]  }|j                  t        k(  r:|r"|j	                  |dd |j                   gz          | j                  |||||       P|j                  t        k(  r&|sf|j	                  |dd |j                   gz          | j                  t        d        y)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.   r  r  r   r   _listr
   r   r   )r   filesprefixnodestreamsstoragesr*  s          r1   r  zOleFileIO._listW  s     499+%YY 	BE=0LLuzzl!:;

5&%(C!!\1LLuzzl!:;""#3  6A  B	Br3   c                 H    g }| 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
        )r  rz  )r   r  r  r  s       r1   listdirzOleFileIO.listdirs  s&     

5"dii(;r3   c                    t        |t              r|j                  d      }| j                  }|D ]M  }|j                  D ]/  }|j
                  j                         |j                         k(  s/ n t        d      |}O |j                  S )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
        /zfile not found)	rg   
basestringsplitrz  r  r.   r8  r  r  )r   rj   r  r.   rO  s        r1   _findzOleFileIO._find  s    $ h
+~~c*Hyy 	Dyy 088>>#tzz|30 .//D	 xxr3   c                     | j                  |      }| j                  |   }|j                  t        k7  rt	        d      | j                  |j                  |j                        S )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.
        zthis file is not a stream)r   r6  r  r
   r  r  r   r   r   rj   r  r*  s       r1   
openstreamzOleFileIO.openstream  sU     jj"$|+566zz%**EJJ77r3   c                 Z   |j                   s|j                  |        t        |j                         }| j                  j                   s| j                  j                  |        | j                  | j
                  z  }t        |j                         D ]  \  }}||z  }||z  }| j                  j                   |   dz   | j                  z  || j
                  z  z   }	||dz
  k  r#||| j
                  z  |dz   | j
                  z   }
n||| j
                  z  d  }
| j                  |	|
        y )Nr$   )r)  r0  re   rz  r|  rn  	enumerater  )r   r*  data_to_writer	  
block_sizeidxr  	sect_basesect_offsetr  data_per_sectors              r1   _write_mini_streamzOleFileIO._write_mini_stream  s!   ""4())*
yy##II&&t,%%)>)>>
"5#3#34 	;IC
*I+Kii**9594;K;KKkZ^ZoZoNooFj1n%"/d6K6K0KcTUgY]YnYnMn"o"/d6K6K0K0L"M!!&/:	;r3   c           	      $   t        |t              st        d      | j                  |      }| j                  |   }|j
                  t        k7  rt        d      |j                  }|t        |      k7  rt        d      || j                  k  r&|j
                  t        k7  r| j                  ||      S |j                  }|| j                  dz
  z   | j                  z  }t         j#                  d|z         t%        |      D ]  }||dz
  k  r<||| j                  z  |dz   | j                  z   }	t        |	      | j                  k(  szJ ||| j                  z  d }	t         j#                  d|| j                  t        |	      || j                  z  fz         t        |	      | j                  z  || j                  z  k(  sJ | j'                  ||	       	 | j(                  |   } |t,        k7  rt        d
      y# t*        $ r t        d	      w xY w)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 stringzthis is not a streamz?write_stream: data must be the same size as the existing stream)r*  r  r$   r   NzGwrite_stream: size=%d sectorsize=%d data_sector=%Xh size%%sectorsize=%dr   z)incorrect last sector index in OLE stream)rg   rh   r  r   r6  r  r
   r  r   re   r  r'  r   r  r   r  r6   r   r   r  r  r   r   )
r   stream_namerk   r  r*  r   r  r	  r"   data_sectors
             r1   write_streamzOleFileIO.write_stream  s    $&GHHjj%$|+011zz3t9^__$'''E,<,<
,J**5$*OOdooa/0T__D
		#j01z" 	NA *Q,"Adoo$51doo8MN;'89"Adoo$5$67		cT__c+.>t@VWX Y;'$//94$//;QQROOD+.Nxx~-	N6 :EFF 	  NLMMNs   G::Hc                 z    	 | j                  |      }| j                  |   }|j                  S # t        $ r Y yw xY w)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)r   r6  r  r   r  s       r1   get_typezOleFileIO.get_type  sA    	**X&COOC(E### 		s   +. 	::c                 Z    | j                  |      }| j                  |   }|j                  S )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
        )r   r6  r   r  s       r1   getclsidzOleFileIO.getclsid  s*     jj"${{r3   c                 b    | j                  |      }| j                  |   }|j                         S )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
        )r   r6  rQ  r  s       r1   rQ  zOleFileIO.getmtime$  -     jj"$~~r3   c                 b    | j                  |      }| j                  |   }|j                         S )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
        )r   r6  rT  r  s       r1   rT  zOleFileIO.getctime3  r  r3   c                 F    	 | j                  |      }y# t        $ r Y yw xY w)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)r   r   )r   rj   r  s      r1   r   zOleFileIO.existsB  s*    	**X&C 		s    	  c                     | j                  |      }| j                  |   }|j                  t        k7  r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.
        zobject is not an OLE stream)r   r6  r  r
   r  r   r  s       r1   get_sizezOleFileIO.get_sizeQ  sD     jj"$|+9::zzr3   c                 .    | j                   j                  S )zp
        Return root entry name. Should usually be 'Root Entry' or 'R' in most
        implementations.
        )rz  r.   r   s    r1   get_rootentry_namezOleFileIO.get_rootentry_namea  s    
 yy~~r3   c           	      H   |dk(  rg }|}t        |t              sdj                  |      }| j                  |      }i }	 |j	                  d      }t        |dd       }|j	                  d      }t        |dd       }	|j                  t        |d             d|j	                  t        |j	                  d	            d	z
        z   }t        |d	      }
t        |
t        t!        |      dz              }
t#        |
      D ]  }d}	 t        |d|dz  z         }t        |d|dz  z         }t        ||      }t$        j'                  |d      }t(        j+                  d||||fz         | j-                  ||d	z   ||||      }|||<    |S # t        $ rG}d
j                  t        |      |      }| j                  t        |t        |             |cY d}~S d}~ww xY w# t        $ r<}d|t        |      |fz  }| j                  t        |t        |             Y d}~d}~ww xY w)  
        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)
        Nr  rQ   r>   rM   rI   rE      ****r    z6Error while parsing properties header in stream {}: {}r   rB   UNKNOWN$property id=%d: type=%d/%s offset=%X3Error while parsing property id %d in stream %s: %s)rg   r  r   r  rb   r   rc   r   BaseExceptionr   r   r   r   typeminrv   re   r  VTr   r6   r   _parse_property)r   rj   r   r   
streampathrm   rk   r  r   fmtid	num_propsexcr   r"   property_idr  property_typevt_namer   s                      r1   r   zOleFileIO.getpropertiesh  s!    D M
*c**-J__X&	A1Qr7OEA1Sb6NEGGC2J"''#bggaj/!"344AAq	I 	3s1vz?3	9% 	EAKE!!QqsUmQ1Q3 #Av&&	:		@KQ^`gioCppq,,Qq+}Vbdqr$)[!	E& ;  	 KQQZ #'C/d3i@K	, ! E Lj!13O8 8""#3S$s)DDEs7   BF	 B G		G<GGG	H!%1HH!c           	         d }|t         k  s|t        t        fv r| j                  ||||||      \  }}|S |t        t
        z  k(  rt        j                  d       d}	t        ||      }
g }t        |
      D ]I  }t        |||	z         }| j                  |||	z   dz   ||||      \  }}|j                  |       |	|dz   z  }	K |}|S |t        z  r|t         z  }t        j                  dt        j                  |d      z         d}	t        ||      }
g }t        |
      D ]<  }| j                  |||	z   ||t         z  ||      \  }}|j                  |       |	|z  }	> |}|S t        j                  d||fz         |S )Nz'property_type == VT_VECTOR | VT_VARIANTr    zproperty_type == VT_VECTOR | %sr   5property id=%d: type=%d not implemented in parser yet)VT_BLOBVT_CLSIDVT_CF_parse_property_basic	VT_VECTOR
VT_VARIANTr6   r   r   r   r   r&  r   )r   r  r  r,  r-  r   r   v_offcountvaluesszproperty_type_bases                 r1   r'  zOleFileIO._parse_property  s   G#}58I'I--amUacpqDAq4 3 i*44II?@C6NEF5\  #Av| 433Av|a7GVceq  tA  B2a rAv	
 A  Y&!.)!;II7"&&ASU^:__`C6NEF5\ 221fslKQ^bkakQkmy  |I  J2a r	 A  IIMQ\^kPllmr3   c                 b   d }d}|t         k(  rt        ||      }|dk\  r|dz
  }d}||fS |t        k(  rt        ||      }d}||fS |t        t        t
        fv rt        ||      }d}||fS |t        t        fv rt        ||      }d}||fS |t        t        fv r8t        ||      }	||dz   |dz   |	z   dz
   }|j                  dd      }d|	z   }||fS |t        k(  r#t        ||      }	||dz   |dz   |	z    }d|	z   }||fS |t        k(  r;t        ||dz         }	| j                  ||dz   |dz   |	dz  z          }d|	dz  z   }||fS |t        k(  rt!        t        ||            t!        t        ||dz               d	z  z   }|r}||vryt"        j%                  d
||t'        |      dz  fz         t)        j(                  dddddd      }
t"        j%                  d|dz  z         |
t)        j*                  |dz        z   }n|dz  }d}||fS |t,        k(  rt/        ||         }d}||fS |t0        k(  rt3        |||dz          }d}||fS |t4        k(  r#t        ||      }	||dz   |dz   |	z    }d|	z   }||fS |t6        k(  rt9        t        ||            }d}||fS d }t"        j%                  d||fz         ||fS )Nr         r:   r    r$   r   r3   r  8Converting property #%d to python datetime, value=%d=%fs逖 r   timedelta days=%d    @T$r@   r   r>   rE   r0  )VT_I2r}   VT_UI2VT_I4VT_INTVT_ERRORr   VT_UI4VT_UINTVT_BSTRVT_LPSTRreplacer1  	VT_LPWSTRr$  VT_FILETIMEr%  r6   r   floatr   r   VT_UI1rs   r2  r   r3  VT_BOOLbool)r   r  r  r,  r-  r   r   r   r   r:  r   s              r1   r4  zOleFileIO._parse_property_basic  s   ED %AvE>!EMEb $;a &(Av\ $;[ 5&(";; AvP $;O 67"33AvJ $;I 7H"55
 Av&(6!8E>!#34gs35yv $;u ') Av&(6!8E>25yj $;i )+
 Avax(..q&(57:J/KL519}Z $;Y +-SF^,SF1H5E0F0JK  K}$DIIX)5%,x2GHI J +3*;*;D!Q1a*P'II1U=O5PQR/(2D2DRWY[R[2\\E "X-E8 $;7 &(1V92 $;1 (*qr	23, $;+ %' Av&(6!8E>25y  $; ') SF^, $; 		QU`boTppq $;r3   c                 n    t               | _        | j                  j                  |        | j                  S )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
        )r   rl  r   r   s    r1   get_metadatazOleFileIO.get_metadata%	  s)     $&&t,}}r3   c           
         t        d      }|dk(  rg }|}t        |t              sdj                  |      }| j	                  |      }g }|j                  d      }t        |dd       }	t        |d      }
g }	 t        |
      D ]n  }|j                  d      }t        |dd       }||k(  s)t        |d      }|j                  |       d	|j                  t        |j                  d
            d
z
        z   }t        |d
      }|ddd|z  z    }dd|z  z   }t        |||d
z          }|d
z  }t        |      D ]f  }|||d
z    }t        ||d
z   |dz          }||dz   |dz   |z    j                  d      j                  d      }|j                  |dd       |dz   |z   }h t        |t        t        |      dz              }t        d|      D ]   }d}	 t        |d|dz  z         }t        |d|dz  z         }t        ||      }t         j#                  |d      }t$        j'                  d||||fz         |t(        k(  rt+        ||d
z         }|dk\  r|dz
  }n|dk(  r"t        ||dz         }||dz   |dz   |z   dz
   }na|t,        k(  rt+        ||d
z         }nG|t.        t0        t2        fv rt        ||d
z         }n#|t4        t6        fv rt        ||d
z         }n|t8        t:        fv r4t        ||d
z         }||dz   |dz   |z   dz
   }|j=                  dd      }n|t>        k(  rt        ||d
z         }||dz   |dz   |z    }n|t@        k(  r1t        ||d
z         }| jC                  ||dz   |dz   |dz  z          }n`|tD        k(  rtG        t        ||d
z               tG        t        ||dz               dz  z   }|r}||vryt$        j'                  d||tI        |      dz  fz         tK        jJ                  dddddd      }t$        j'                  d|dz  z         |tK        jL                  |dz        z   }n|dz  }n|tN        k(  rtQ        ||d
z            }n|tR        k(  rt        ||d
z   |dz          }ne|tT        k(  rt        ||d
z         }||dz   |dz   |z    }n>|tV        k(  rtY        t+        ||d
z               }nd}t$        j'                  d ||fz         |||dz
     d!<   # q 	 |S # tZ        $ r<}d"|t]        |      |fz  }| j_                  t`        |tc        |             Y d}~jd}~ww xY w# tZ        $ r=}d#t]        |      d$|}| j_                  t`        |tc        |             |cY d}~S d}~ww xY w)%r  s   ՜. +,Nr  rQ   r>   rM   rI   rE   r  r    utf_8 )property_namer   r:   r   rB   r   r!  r?  r@  r$   r   r3   r  rA  rB  r   rC  rD  r@   r   r0  r   r"  z0Error while parsing properties header in stream z: )2r   rg   r  r   r  rb   r   r   rc   r  r   r   r%  rv   re   r  r&  r   r6   r   rE  r}   rF  rG  rH  rI  rJ  rK  rL  rM  rN  r1  rO  r$  rP  r%  rQ  r   r   rR  rs   r2  r3  rS  rT  r#  r   r   r   r$  )r   rj   r   r   FMTID_USERDEFINED_PROPERTIESr(  rm   rk   r  r   sections_countsection_file_pointersr"   r)  file_pointerr*  PropertyIdentifierAndOffsetr  entry_count
identifierstr_sizestringr,  r  r-  r.  r   r:  r   r+  r   s                                  r1   get_userdefined_propertiesz$OleFileIO.get_userdefined_properties1	  s%     (..q'r$ D M
*c**-J__X& GGBKq2w Q "R	>* HQGGBKq"v88#&q":LGGL)"''#bggaj/A*=">>A #Aq	I23Aq9}2E/ a	kME"%auQw&7"8KQJE";/ 1%&ueQh%7
#&qq%!)'<#=!"57E!GH,<!=!D!DW!M!S!STX!YVT$JK %a 01 !$Is3q6A: ?I 'q)4 iQ&'gQ*-aQU*;K%(BQJ%7F,/6NM&(ff]I&FGII&LP[]jlsu{O|&|}
  -5(+Avz(:#(E>,1EME!.!!3+.q&1*+=()&2+frkH6Lq6P(Q!.&!8(+Avz(:!.5&(2K!K ),Avz(:!.672C!C(+Avz(:!.7H2E!E
 ),Avz(:()&1*VaZ%5G!5K(L(-gs(C!.'!9 ),Avz(:()&1*VaZ%5G(H!.)!;
 ),Avz(:(,(>(>q!FUVJY^abYbLb?c(d!.+!=(,SFQJ-?(@DQPVYZPZI[D\`bDb(c $0K}4T$'II.h1<eU5\T\E\0]/^ %_ ;C:K:KDRSUVXY[\^_:`$7$'II.AUOgEh.i$j,?(BTBTbgkmbmBn,nE -2X,=E!.&!8(*1VaZ=(9!.(!:(.q!FRK/H(I!.%!7 ),Avz(:()&1*VaZ%5G(H!.'!9 )-SFQJ-?(@(, #		$[_jly^z$z!|  05D1Ig.GiQ?HQf !  - Q #X +T*-=s[D #DC ../?d3iPPQ  	
 Z #'C/d3i@K	sP   73T? +D(T? LS7.T? 7	T< 1T71T? 7T<<T? ?	V2V :V V)rN  )FrU  )r   )TF)FN)1r   r   r   r   r   r   r   r  r  r  r   r   r$  ri   r  r  r(  r  r  r  r  r  r.  r  r  r  r  r7  r  r   r  r  r  r   r  r  r  r  r  rQ  rT  r   r  r  r   r'  r4  rV  rd  r8   r3   r1   r   r     s   8 !%L!>SSj  CO !4(_6B ',2"H2
!FQ#f"'H>44&'P$2 #/% #-JB8>8*;$;Gz&   >@>[|
{r3   r   c                     ddl } ddl}d}t        j                  t        j                  t        j
                  t        j                  t        j                  d}d}|j                  |      }|j                  ddd	d
       |j                  dddd       |j                  dddd       |j                  dddd|d       |j                         \  }}t        dj                  t        t                     t        |      dk(  r0t        t                |j#                           | j$                          |j&                  rd|_        t        j*                  ||j(                     d       t-                |D ]  }	 t/        |      }	t        d       t        |       t        d       |	j1                          |	j3                         D ]!  }
|
d   d   dk(  st        d|
z         	 |	j5                  |
d !      }t7        |j9                               }|D ]c  \  }}t;        |t<        t>        f      rt        |      d"kD  r|dd" }t;        |t>              rd#D ]  }|tA        |      v sd$} n t        d%||       e 	 	 |jH                  ra|	jK                  |
d !      }t        |      rCt        d'|
z         tM        |      D ]'  \  }}t        d(j                  ||d)   |d*                ) $ |jN                  rt        d,       |	j3                         D ]  }
t        d-tQ        d.jS                  |
            d-d/0       |	jU                  |
      }|tV        k(  r/t        d1|	jY                  |
      z         |	j[                  |
       st        d2|z          t                t        d3       |	j\                  D ]G  }|t        d4j                  |j^                  |ja                         |jc                                      I t                	 |	je                         }|jg                          t                |	ji                         }t        d6|z         |	jk                  d7      r]t        d8       t        d9|	jU                  d7             t        d:|	jY                  d7             |	jk                  d;      rt        d<       t        d=       |	jl                  r:|	jl                  D ]*  \  }}t        d>j                  |jn                  |             , nt        d?       |	jq                           y# tB        $ r tD        jG                  d&|
z         Y w xY w#  tD        jG                  d+|
z         Y xY w# tB        $ r tD        jG                  d5       Y ow xY w# tB        $ r tD        jG                  d@|z         Y Mw xY w)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
    r   Nr  )r   infor  r  criticalz1usage: %prog [options] <filename> [filename2 ...])usagez-c
store_truecheck_streamsz*check all streams (for debugging purposes))actiondesthelpz-pextract_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
--loglevelloglevelstorezBlogging level debug/info/warning/error/critical (default=%default))rl  rk  defaultrm  z=olefile version {} {} - https://www.decalage.info/en/olefile
r   z%(levelname)-8s %(message)s)r/   r   zD--------------------------------------------------------------------z%r: propertiesTr   2   )r$   r:   r#   r    r;   r<   r=   rA   rB   rD      rE   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   z(binary data)z   z&Error while parsing property stream %rz%r: user-defined propertiesz
	{} {}: {}rZ  r   z3Error while parsing user-defined property stream %rz
Checking streams...-r  rI  rJ  zsize %dzNOT a stream : type=%dz5Modification/Creation times of all directory entries:z- {}: mtime={} ctime={}zError while parsing metadatazRoot entry name: "%s"worddocumentzThis is a Word document.ztype of stream 'WordDocument':zsize :z
macros/vbaz%This document may contain VBA macros.z(
Non-fatal issues raised during parsing:r   NonezError while parsing file %r)9r  optparser&   r  INFOWARNINGERRORCRITICALOptionParser
add_option
parse_argsr   r   __version____date__re   r   
print_helpexitro  rp  basicConfigr   r   r  r  r   sorteditemsrg   r  rh   r  r   r6   	exceptionrn  rd  r  rj  r   r   r  r
   r  r  r6  r.   rQ  rT  rV  r   r  r   r^  r   r  )r  rz  DEFAULT_LOG_LEVEL
LOG_LEVELSrh  parseroptionsr  rj   r   
streamnamer   kr7  rr   	variablesr  variablest_typer*  metarz  exctyper   s                           r1   mainr  	  sM    !MMLLOOMM$$
J @E"""/F
d<o9  ;
d<6JA  C
d<lk  m
dLz'Sd!e  g '')OWd	
J
Q
QR]_g
hi 4yA~g
" j)9)9:C`a  _D^	DH%C(O(O(O!kkm j
b>!$.*Z78] # 1 1*4 1 P &u{{} 5$) /DAq)!j%-@A#&q6B;()#2A)!U3*L !.A'(IaL'8,;(-	!.
 "%A./ 	j"55(+(F(Fz`d(F(eI"9~ %&Cj&P Q7@7K !tOE8$)-*>*>uhF_`hip`q*r$s!t7jD $$-."%++- 	BJ#tCHHZ$89#3G!ll:6G,.i#,,z*BBCz26@A	B  IJ =$3::5::(%..*:< == G>'')		 G))+D)D01zz.)016^8TUh^ <=::l+AB =>!!$'$6$6 DLGS*++G,<,<cBCD fIIK{_D4 % ]&NQ[&[\]j&[^h&hiF  ><=>*  	DMM7(BC	Ds   ?AV#V#*A?T6*T6>V# A-U-CV#AV# U>0DV#6!UV#UV#U;8V#>V V#V  V##!WW__main__)NNrU  )zr   
__future__r   r  r  
__author____all__r   r  ry   r  os.pathr  r   r&   r  r  r  rh   rv   r%  xranger  r   r   itemsizer  r  r  	NameErrorversion_infor   r~  r2   r6   r   r   r   r   r   r   r   r   r   r	   r   r
   r   r   r   r   VT_EMPTYVT_NULLrE  rG  VT_R4VT_R8VT_CYVT_DATErL  VT_DISPATCHrI  rS  r6  
VT_UNKNOWN
VT_DECIMALVT_I1rR  rF  rJ  VT_I8VT_UI8rH  rK  VT_VOID
VT_HRESULTVT_PTRVT_SAFEARRAY	VT_CARRAYVT_USERDEFINEDrM  rO  rP  r1  	VT_STREAM
VT_STORAGEVT_STREAMED_OBJECTVT_STORED_OBJECTVT_BLOB_OBJECTr3  r2  r5  r&  r,  varsr  keywordvarr   r   r   r   r   r   r   rs   r}   r   r   r   r  r   r   r   RuntimeWarningr   r  r   r  r   r  r   r8   r3   r1   <module>r     sQ  8 &x  
	 
 
 E E E E
 eDI 5;;s!FU[[!#FU[[!# F
U
VV A# !
 #++A- 8 ! 	, 

 	 
  
AGQuaq%5	17!kbX"'
"zj2Ubv	"6Ber"6bg
rJ"62lyB8"	"k
bIR*B); B^b2(
	 ( LGSr{e3 4
   
  :z 	C<1,,*"O	7 		l 	X8 X8t ,P(

 P(lZ2 Z2~q qp/ODd zF _P  IB  Js#   H /H$ H! H!$H/.H/