+
    !Oi c                   s   R t ^ RIHt RtRtRt. R1Ot^ RIt^ RIt^ RI	t	^ RI
t
^ RIt^ RIt^ RIt^ RIt^ RIt]]Jd   ]t ]t]
P                  ! R	4      P2                  ^8X  d   R	tMP]
P                  ! R
4      P2                  ^8X  d   R
tM,]
P                  ! R4      P2                  ^8X  d   RtM]! R4      h ] ]P<                  ^ ,          ^8  d   RtMRt]P@                  ^,           3R lt!]!! R4      t"R t#Rt$Rt%Rt&Rt'Rt(Rt)Rt*Rt+^ t,^t-^t.^t/^t0^t1Rt2^ t3^t4^t5^t6^t7^t8^t9^t:^t;^	t<^
t=^t>^t?^t@^tA^tB^tC^tD^tE^tF^tG^tH^tI^tJ^tK^tL^tM^tN^tO^tP^tQ^@tR^AtS^BtT^CtU^DtV^EtW^FtX^GtY^HtZRt[/ t\]]! ]^! 4       P                  4       4       F  w  t`ta]`R,          R8X  g   K  ]`]\]a&   K  	  Rtb^
tc^td^te^(tfRtgR2R lth]]J d   R tiMR tiR3R  ltjR3R! ltkR" tlR# tm ! R$ R%]n4      to ! R& R']o4      tp ! R( R4      tq ! R) R]r4      ts ! R* R+]P                  4      tu ! R, R-4      tv ! R. R4      twR/ tx]yR08X  d
   ]x! 4        R# R#   ] d    ]t ELi ; i  ] d    ]t ELi ; i)4a:  
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	OleFileIOOleMetadataOleFileIONotClosedNZLZIiz>Need to fix a bug with 32 bit arrays, please contact author...zutf-8c                s@   V \         P                  P                  P                  9   d*   \         P                  ! V 4      pVP                  V4       V# \         P                  ! V 4      pVP                  \         P                  ! 4       4       VP                  V4       V# )aR  
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.
)loggingZLoggermanagerZ
loggerDictZ	getLoggersetLevelZ
addHandlerZNullHandler)namelevelZlogger   && 4/usr/lib/python3.14/site-packages/olefile/olefile.py
get_loggerr      sy     w~~%%000 ""4(t$F g))+,
OOEM    olefilec                 sL    \         P                  \        P                  4       R# )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   ZNOTSET r   r   enable_loggingr      s     LL r   s   ࡱl    l    l    l        i   :N   NZVT_z$00020900-0000-0000-C000-000000000046i   c                s<   RpVe*   \        V4      \        8  d   VR\        \        4       pMR# \        V R4      '       dC   \        V R4      '       d1   V P	                  \        \        4      4      pV P                  ^ 4       Mx\        V \        4      '       d(   \        V 4      \        8  d   V R\        \        4       pM;\        V R4      ;_uu_ 4       pVP	                  \        \        4      4      pRRR4       V\        8X  d   R# R#   + '       g   i     L; i)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seekrbT)	lenMINIMAL_OLEFILE_SIZEMAGIChasattrr   r   
isinstancebytesopen)filenamedataheaderfp   &&  r   	isOleFiler$     s    D Ft9,,+3u:&F 	6	"	"wx'@'@s5z*a	He	$	$X:N)N+3u:& (D!!RWWSZ(F " "!s   DD	c                 s    \        V 4      # N)Zordc   &r   i8r)   O  s    1vr   c                 s@    V P                   \        J d   V # V ^ ,          # i    )	__class__intr&   r(   r   r)   r)   S  s    KK3&q0AaD0r   c                sP    \         P                  ! RWV^,            4      ^ ,          # )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<Hstructunpackr'   Zo   &&r   i16r2   W  "     ==q1Q3x(++r   c                sP    \         P                  ! RWV^,            4      ^ ,          # )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-   r0   r1   r   i32r4   a  r3   r   c           	     s    V P                  R4      '       g   R# R\        V ^ 4      \        V ^4      \        V ^4      3\        \	        \
        V R,          4      4      ,           ,          # )zR
Converts a CLSID to a human-readable string.

:param clsid: string of length 16.
     :      Nz0%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X)stripr4   r2   ZtupleZmapr)   )clsidr(   r   _clsidr;   k  sW     ;;u4%mS]CqM:#b%+&'() *r   c                s    \         P                   ! R^^^ ^ ^ 4      pV\         P                  ! V ^
,          R7      ,           # )z<
convert FILETIME (64 bits int) to Python datetime.datetime
A  Zmicroseconds)datetime	timedelta)Zfiletime_FILETIME_null_date   & r   filetime2datetimerB   |  s9     #++D!Q1a@!3!32!NNNr   c                       ] tR tRtRtRtR# )OleFileErrori  z%
Generic base error for this module.
r   N__name__
__module____qualname____firstlineno____doc____static_attributes__r   r   r   rD   rD          	r   rD   c                   rC   )NotOleFileErrori  z7
Error raised when the opened file is not an OLE file.
r   NrE   r   r   r   rM   rM     rL   r   rM   c                   sF   a  ] tR tRt o Rt. ROt. R	OtR tR tR t	Rt
V tR# )
r   i  a  
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
c                s   RV n         RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n	        RV n
        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n         RV n!        RV n"        RV n#        RV n$        RV n%        RV n&        RV n'        RV n(        RV n)        RV n*        RV n+        RV n,        RV n-        RV n.        R# )zG
Constructor for OleMetadata
All attributes are set to None by default
N)/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_targetr   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_versionselfr(   r   __init__ZOleMetadata.__init__  s_    
!## #$(! #' 


!!#!%" "r   c                s   V P                   V P                  ,            F  p\        WR4       K  	  VP                  R4      '       dq   VP	                  RR^
.R7      p\        \        V P                   4      4       F9  pVP                  V^,           R4      p\        W P                   V,          V4       K;  	  VP                  R4      '       dq   VP	                  RRR7      p\        \        V P                  4      4       F9  pVP                  V^,           R4      p\        W P                  V,          V4       K;  	  R# R# )aO  
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SummaryInformationT)convert_timeno_conversionzDocumentSummaryInformationr~   )SUMMARY_ATTRIBSDOCSUM_ATTRIBSZsetattrexistsgetpropertiesranger   get)r|   ole_fileZattribpropsr   value   &&    r   parse_propertiesZOleMetadata.parse_properties  s    ++d.A.AAAFD$' B??344 **+C8<RD + RE 3t3345		!A#t,2215u= 6 ??;<<**+K8< + >E 3t2234		!A#t,11!4e< 5 =r   c           	     s:   \        R4       V P                   F2  p\        W4      p\        RP                  V\	        V4      4      4       K4  	  \        R4       V P
                   F2  p\        W4      p\        RP                  V\	        V4      4      4       K4  	  R# )z,
Dump all metadata, for debugging purposes.
z*Properties from SummaryInformation stream:- {}: {}z2Properties from DocumentSummaryInformation stream:N)printr   Zgetattrformatreprr   )r|   Zpropr   s   &  r   dumpZOleMetadata.dump#  s~     	:;((DD'E*##D$u+67 ) 	BC''DD'E*##D$u+67 (r   )/rQ   r   rb   ro   rN   ra   rS   rm   rx   rw   rY   r_   rv   rz   rk   rh   rs   rt   rR   ry   rX   rU   rZ   rd   rr   rn   r   ri   rg   r]   r[   r\   re   rc   rV   rj   r`   rq   rf   rP   rT   r^   rO   rl   rW   rp   ru   N)rN   rO   rP   rQ   rR   rS   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r]   r^   r_   r`   )ra   rb   rc   r   rd   re   rf   rg   rh   ri   rj   rk   rl   r   rm   rn   ro   rp   rq   rr   rs   rt   ru   rv   rw   rx   ry   rz   )rF   rG   rH   rI   rJ   r   r   r}   r   r   rK   __classdictcell____classdict__   @r   r   r     s0      HOEN5 n =D8 8r   c                   s@   a a ] tR tRt oRtRV 3R lltR tRtVtV ;t	# )r   i0  zJ
Warning type used when OleFileIO is destructed but has open file handle.
c                s8   < \         \        V `  4        Wn        R # r%   )Zsuperr   r}   stack_of_open)r|   r   r+   s   &&r   r}   ZOleFileIONotClosed.__init__4  s     $02*r   c                s    R pV P                   '       d4   RP                  VRR.V P                   P                  4       ,           4      # V# )zDeleting OleFileIO instance with open file handle. You should ensure that OleFileIO is never deleted without calling close() first. Consider using "with OleFileIO(...) as ole: ...".r6   Z
zStacktrace of open() call:
)r   joinr   )r|   msgrA   r   __str__ZOleFileIONotClosed.__str__8  sP    3 77C'EF--4467 8 8 Jr   )r   r%   )
rF   rG   rH   rI   rJ   r}   r   rK   r   Z__classcell__)r+   r   s   @@r   r   r   0  s     +	 	r   c                   s*   a  ] tR tRt o RtR tRtV tR# )	OleStreamiF  a  
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	                s<
   \         P                  R4       \         P                  RW"W4V\        V4      \        V4      3,          4       Wn        V P                  P
                  P                  '       d   \        R4      hRp	V\        8X  d*   \        V4      V,          pRp	\         P                  R4       W5^,
          ,           V,          p
\         P                  RV
,          4       V
\        V4      8  d!   V P                  P                  \        R4       . pV^ 8X  dA   V\        8w  d6   \         P                  R	4       V P                  P                  \        R
4       \        V
4       EF  p\         P                  RW3,          4       V\        8X  dV   V	'       d   \         P                  R4        EM\         P                  R4       V P                  P                  \        R4       V^ 8  g   V\        V4      8  dh   \         P                  RW"\        V4      3,          4       \         P                  RW3,          4       V P                  P                  \        R4        EM VP                  WEV,          ,           4       TP                  T4      p\        T4      T8w  d   T\        T4      ^,
          8w  d   \         P                  RT\        T4      YET,          ,           T\        T4      3,          4       \         P                  RYET,          ,           \        T4      ,           ,          4       T P                  P                  \        R4       TP!                  T4        Yb,          R,          pEK  	  RP%                  V4      p\        V4      V8  d4   \         P                  R\        V4      V3,          4       VRV pW0n        MV	'       d7   \         P                  R\        V4      ,          4       \        V4      V n        MW\         P                  R\        V4      V3,          4       \        V4      V n        V P                  P                  \        R4       \(        P*                  P-                  W4       R#   \         dR    \         P                  RY$YR,          ,           T3,          4       T P                  P                  \        R4         EKe  i ; i  \"         d'    T P                  P                  \        R4         EK  i ; i)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 SIZEnb_sectors = %dz(malformed OLE document, stream too largez!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 sectorr   r   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)r   debugr   r   oler"   ZclosedZOSErrorUNKNOWN_SIZE_raise_defectDEFECT_INCORRECT
ENDOFCHAINr   r   	Exceptionr   append
IndexErrorr   sizeioBytesIOr}   )r|   r"   sectr   offset
sectorsizefatfilesize	olefileioZunknown_size
nb_sectorsr    r   Zsector_datas   &&&&&&&&&     r   r}   ZOleStream.__init__Z  s    			'(		YJs3xbBC 	D 88;;NOO < s8J&DLII23l+
:
		#j01 C HH""#35_` 19+II9:HH""#35bc z"AII71)CDz!IIVW IIDEHH**+;=TUAvs3x		6$c#h9OOP		01/AB &&'79ghd!223 ''*-K
 ;+s3xz0B		U3s8VtO%;Xs;GWXY Z		-41GKHX1XYZ&&'79PQKK$y:-] #n xx~t9IIKsSWyZ^N__`;DI IIKcRViWXD	DI IIQUXY]U^`dTeefD	DIHH""#35\]


D'_  		9*/18<= >&&'79XY(  &&'79gh	s%   ,R-S*AS'&S'*+TT)r   r   N)rF   rG   rH   rI   rJ   r}   rK   r   r   r   r   r   r   F  s     &|( |(r   r   c                   sr   a  ] tR tRt o RtRt^tR tR tR t	R t
R tR	 tR
 tR tRR ltR tR tRtV tR# )OleDirectoryEntryi  z8
OLE2 Directory Entry pointing to a stream or a storage
z<64sHBBIII16sIQQIIIc                s   W n         W0n        . V n        / V n        RV n        \
        P                  ! \        P                  V4      w  V n	        V n
        V n        V n        V n        V n        V n        pV n        V n        V n        V n        V n        V n        V P                  \,        \.        \0        \2        39  d   VP5                  \6        R4       V P                  \,        8X  d   V^ 8w  d   VP5                  \6        R4       V^ 8X  d,   V P                  \,        8w  d   VP5                  \6        R4       V P                  ^@8  d   VP5                  \6        R4       ^@V n
        V P                  RV P                  ^,
           V n        VP;                  V P8                  4      V n        \>        PA                  RV P                   \C        V P<                  4      3,          4       \>        PA                  RV P                  ,          4       \>        PA                  R	V P&                  ,          4       \>        PA                  R
V P                  V P                  V P                  3,          4       VPD                  R8X  d   V P*                  ^ 8w  dp   V P*                  R8w  d_   \>        PA                  RVPD                  V P(                  V P*                  V P*                  3,          4       VP5                  \F        R4       V P(                  V n$        M2V P(                  \K        V P*                  4      ^ ,          ,           V n$        \>        PA                  RV PH                  V P(                  V P*                  3,          4       \M        V4      V n'        V P                  \.        8X  d(   V PH                  ^ 8w  d   VP5                  \P        R4       RV n)        V P                  \,        \0        39   dw   V PH                  ^ 8  df   V PH                  VPT                  8  d   V P                  \0        8X  d	   RV n)        MRV n)        VPW                  V P&                  V PR                  4       RV n,        R# )a5  
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 typezduplicate OLE root entryzincorrect OLE root entryz(incorrect DirEntry name length >64 bytesNzDirEntry SID=%d: %sz - type: %dz - sect: %Xhz% - SID left: %d, right: %d, child: %d   r   z+sectorsize=%d, sizeLow=%d, sizeHigh=%d (%X)zincorrect OLE stream sizez% - size: %d (sizeLow=%d, sizeHigh=%d)zOLE storage with size>0T)-sidr   kids	kids_dictusedr.   r/   r   STRUCT_DIRENTRYname_raw
namelength
entry_typecolorsid_left	sid_right	sid_childdwUserFlags
createTime
modifyTime
isectStartsizeLowsizeHigh
STGTY_ROOTSTGTY_STORAGESTGTY_STREAMSTGTY_EMPTYr   r   
name_utf16_decode_utf16_strr   r   r   r   r   DEFECT_UNSUREr   longr;   r:   DEFECT_POTENTIAL
is_minifatminisectorcutoff_check_duplicate_stream
sect_chain)r|   entryr   r   r:      &&&& r   r}   ZOleDirectoryEntry.__init__  s,     	  	" 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r   c                s   V P                   '       d   R# V P                  \        \        39  g   V P                  ^ 8X  d   R# \        4       V n         V P                  '       d#   VP                  '       g   VP                  4        V P                  pV\        8w  dX   V P                   P                  V4       V P                  '       d   VP                  V,          pKM  VP                  V,          pKb  R# )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
N)r   r   r   r   r   listr   minifatloadminifatr   r   r   r   )r|   r   Z	next_sectr
   r   build_sect_chainZ"OleDirectoryEntry.build_sect_chainX  s     ?????:|"<<		Q&???8#3#3#3  "OO	:%OO""9-$,,Y7	$LL3	 &r   c                s*   \         P                  RV P                  \        V P                  4      V P
                  3,          4       V P
                  \        8w  d8   V P                  V P
                  4       V P                  P                  4        R# R# )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)
r   r   r   r   r   r   NOSTREAMappend_kidsr   Zsortr{   r(   r   build_storage_treeZ$OleDirectoryEntry.build_storage_trees  sg     			Bxxdii$..9: 	;>>X% T^^, IINN &r   c                s   \         P                  RV,          4       V\        8X  d   R# V^ 8  g%   V\        V P                  P
                  4      8  d#   V P                  P                  \        R4       R# V P                  P                  V4      p\         P                  RVP                  \        VP                  4      VP                  VP                  VP                  3,          4       VP                  '       d#   V P                  P                  \        R4       R# RVn        V P!                  VP                  4       VP                  P#                  4       pW0P$                  9   d!   V P                  P                  \        R4       V P&                  P)                  V4       W P$                  V&   V P!                  VP                  4       VP+                  4        R# )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=%dNz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)r   r   r   r   r   
direntriesr   r   _load_direntryr   r   r   r   r   r   r   r   lowerr   r   r   r   )r|   Z	child_sidZchildZ
name_lowerr#   r   r   ZOleDirectoryEntry.append_kids  s_    			-	9:  Q;)S)@)@%AALL&&'79Z[ LL//	:EII`99d5::.QVQ`Q`ab c zzz**+;9;EJ U^^,))+J^^+**+;79 IIU#).NN:&U__-$$&r   c                s4    V P                   VP                   8H  # zCompare entries by namer   r|   Zotherr1   r   __eq__ZOleDirectoryEntry.__eq__  s    yyEJJ&&r   c                s4    V P                   VP                   8  # r   r   r   r1   r   __lt__ZOleDirectoryEntry.__lt__  s    yy5::%%r   c                s.    V P                  V4      '       * # r%   )r   r   r1   r   __ne__ZOleDirectoryEntry.__ne__  s    ;;u%%%r   c                sV    V P                  V4      ;'       g    V P                  V4      # r%   )r   r   r   r1   r   __le__ZOleDirectoryEntry.__le__  s"    {{5!77T[[%77r   c                s6   . ROp W P                   ,          p\        RV,          \        V P                  4      ,           VRR7       V P                   \
        \        39   d   \        V P                  RRR7       \        4        V P                   \        \        39   d=   V P                  '       d+   \        RV,          RV P                  ,          ,           4       V P                   F  pVP                  V^,           4       K  	  R#   \         d    Rp Li ; i)zADump this entry, and all its subentries (for debug purposes only)z	(UNKNOWN) Zendr   z{%s}N)z	(invalid)z	(storage)z(stream)z(lockbytes)z
(property)z(root))r   r   r   r   r   r   r   r   r   r:   r   r   )r|   tabZTYPESZ	type_namekid   &&   r   r   ZOleDirectoryEntry.dump  s    )	$oo.I 	c#gTYY'<??|Z88$))W#.??}j99djjj#c'FTZZ//099CHHS1W   	$#I	$s   D DDc                R    V P                   ^ 8X  d   R# \        V P                   4      # )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
N)r   rB   r{   r(   r   getmtimeZOleDirectoryEntry.getmtime  "     ??a 11r   c                r   )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
N)r   rB   r{   r(   r   getctimeZOleDirectoryEntry.getctime  r   r   )r:   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   Nr*   )rF   rG   rH   rI   rJ   r   ZDIRENTRY_SIZEr}   r   r   r   r   r   r   r   r   r   r   rK   r   r   r   r   r   r     sU     * ,OM_B46.,'\'&&8$22 2r   r   c                   sf  a  ] tR tRt o RtR]RR]3R ltR tR t	R t
]3R	 ltR/R
 ltR0R ltR tR0R ltR0R ltR1R ltR1R ltR tR tR tR tR tR2R ltR2R ltR tR tR t]R3R ltR3R lt R3R lt!R t"R t#R  t$R! t%R" t&R# t'R$ t(R% t)R& t*R' t+R( t,R4R) lt-R* t.R+ t/R, t0R4R- lt1R.t2V t3R# )5r   i  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                s   W n         . V n        W0n        WPn        RV n        RV n        . V n        . V n        RV n        RV n	        RV n
        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n        RV n         RV n!        RV n"        RV n#        RV n$        RV n%        RV n&        RV n'        RV n(        RV n)        V'       d    V PU                  WR7       R# R#   \V         d    T PY                  RR7       h i ; i)ad  
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_issuesr   path_encoding	_filesize
ministream_used_streams_fat_used_streams_minifat
byte_orderdirectory_fpr   dll_versionr   first_difat_sectorfirst_dir_sectorfirst_mini_fat_sectorr"   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_stackr   r   _close)r|   r   Zraise_defectsr   r   r   s   &&&&&&r   r}   ZOleFileIO.__init__  s   : %2! !$*!#%'" "& $%)"  $!% $'+$ $"!!%##$(!	 ,0)"'"		(	:   's   4E
 
E)c                *    V P                  RR7       R# )z?Destructor, ensures all file handles are closed that we opened.Tr   Nr  r{   r(   r   __del__ZOleFileIO.__del__m  s    r   c                s    V # r%   r   r{   r(   r   	__enter__ZOleFileIO.__enter__s  s    r   c                s*    V P                  R R7       R# )Fr   Nr  )r|   argss   &*r   __exit__ZOleFileIO.__exit__w  s    r   c                s    WP                   8  d   \        P                  V4       V! V4      hV P                  P	                  W234       \        P                  V4       R# )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   r   errorr   r   warning)r|   Zdefect_levelZmessageZexception_type   &&&&r   r   ZOleFileIO._raise_defect{  sL    " 444IIg )) &&'@AKK r   c                s    VP                  RV4      pV P                  '       d   VP                  V P                  V4      # V# )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   Zencode)r|   Z	utf16_strZerrorsZunicode_str   &&& r   r   ZOleFileIO._decode_utf16_str  sC      &&z6:%%d&8&8&AA r   c                s   W n         \        VR4      '       d   Wn        M\        V\        4      '       d1   \        V4      \        8  d   \        P                  ! V4      V n        MHV P                   '       d   RpMRp\        W4      V n        RV n
        \        P                  ! 4       V n        ^ pV P                  P                  ^ \        P                   4        V P                  P#                  4       pV P                  P                  ^ 4       W@n        \&        P)                  RV P$                  V P$                  3,          4       . V n        . V n        V P                  P/                  R4      p\        V4      R8w  g   VR,          \0        8w  dL   \&        P)                  RP3                  VR,          \0        4      4       V P5                  \6        R	\8        4       R
p\:        P<                  ! V4      p\&        P)                  RWwR+,           3,          4       VRV p\:        P>                  ! Wh4      w  V n         V n!        V n"        V n#        V n$        V n%        V n&        V n'        V n(        V n)        V n*        V n+        V n,        V n-        V n.        V n/        V n0        V n1        \&        P)                  \:        P>                  ! Wh4      4       V P@                  \0        8w  d   V P5                  \6        R4       V PB                  \e        ^4      8w  d   V P5                  \f        R4       \&        P)                  RV PD                  ,          4       \&        P)                  RV PF                  ,          4       V PF                  R,9  d   V P5                  \f        R4       \&        P)                  RV PH                  ,          4       V PH                  R8w  d   V P5                  \f        R4       ^V PJ                  ,          V n4        \&        P)                  RV Ph                  ,          4       V Ph                  R-9  d   V P5                  \f        R4       V PF                  ^8X  d   V Ph                  R8w  g#   V PF                  ^8X  d(   V Ph                  R8w  d   V P5                  \f        R4       ^V PL                  ,          V n5        \&        P)                  RV Pj                  ,          4       V Pj                  R.9  d   V P5                  \f        R4       V PN                  ^ 8w  g   V PP                  ^ 8w  d   V P5                  \f        R4       \&        P)                  RV PR                  ,          4       V Ph                  R8X  d(   V PR                  ^ 8w  d   V P5                  \f        R4       \&        P)                  RV PT                  ,          4       \&        P)                  RV PV                  ,          4       \&        P)                  R V PX                  ,          4       V PX                  ^ 8w  d   V P5                  \l        R!4       \&        P)                  R"V PZ                  ,          4       V PZ                  R8w  dD   V P5                  \f        R#4       \&        Po                  R$V PZ                  ,          4       RV n-        \&        P)                  R%V P\                  ,          4       \&        P)                  R&V P^                  ,          4       \&        P)                  R'V P`                  ,          4       \&        P)                  R(V Pb                  ,          4       W@Ph                  ,           ^,
          V Ph                  ,          ^,
          V n8        \&        P)                  R)V Pp                  V Pp                  3,          4       \s        VR*,          4      V n!        V Ph                  V n:        V Pj                  V n;        V PZ                  V n<        V P{                  V PV                  4       V P^                  '       d   V P{                  V P\                  4       V Pb                  '       d   V P{                  V P`                  4       V P}                  V4       V P                  V PV                  4       V P\                  V n@        R#   T P                  P                  ^ 4       i ; i)/a  
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)
r   zr+br   TzFile size: %d bytes (%Xh)r   :Nr7   NzMagic = {!r} instead of {!r}z#not an OLE2 structured storage filez<8s16sHHHHHHLLLLLLLLLLzfmt_header size = %d, +FAT = %dNzincorrect OLE signaturezincorrect CLSID in OLE headerzMinor Version = %dz%DLL Version   = %d (expected: 3 or 4)z"incorrect DllVersion in OLE headerz#Byte Order    = %X (expected: FFFE)i  z!incorrect ByteOrder in OLE headerz0Sector Size   = %d bytes (expected: 512 or 4096)r   z#incorrect sector_size in OLE headerz3sector_size does not match DllVersion in OLE headerz/MiniFAT Sector Size   = %d bytes (expected: 64)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   = %dz/Maximum number of sectors in the file: %d (%Xh)r7      Ni  )r      )r   r   )i@   )Ar   r   r"   r   r   r   r   r   r   r   r  	tracebackZextract_stackr  r   osZSEEK_ENDZtellr   r   r   r   r   r   r   r   r   DEFECT_FATALrM   r.   Zcalcsizer/   r   r   r  r   r   r  r  r  r  r	  r
  r   r  r  r   r  r   r  	bytearrayr   r  r  r   r  r  r;   r   r  r   r   loadfatloaddirectoryr  )	r|   r   r   Zmoder   r!   Z
fmt_headerZheader_sizeZheader1s	   &&&      r   r   ZOleFileIO.open  s   " % 8V$$ G%((S]>R-R jj*DG   8*DG!%D(668D
 Q$	ww||~HGGLLO!		-0PPQ "$%'"c"v;#u!4II4;;F2JNO|-RTcdN .
ooj1		4SXEX7YY[+&( MM*.'	
!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 #%5%55a7D<L<LLPQQ		DVZVbVbGccd
 #6$<0 **"33 $ < < 	$$T%:%:;$$$(()C)CD!!!(()@)@A 	V 	400155[ GGLLOs   b1 1cc                r  )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{   r(   r   closeZOleFileIO.close  s     	r   c                s    V P                   '       dg   V'       d<   V P                  '       d*   \        P                  ! \	        V P
                  4      4       V P                  P                  4        RV n         R# R# )z3Implementation of close() with internal arg `warn`.FN)r  r  warningsr   r   r  r"   r*  )r|   r   r1   r   r  ZOleFileIO._close  sP    /// 01A1ABCGGMMO!&D r   c                sP   V'       d*   \         P                  RV,          4       V P                  pME\         P                  RV,          4       V\        \        \
        \        39   d   R# V P                  pW9   d   V P                  \        R4       R# VP                  V4       R# )a7  
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)r   r   r   DIFSECTFATSECTr   FREESECTr   r   r   r   )r|   Z
first_sectr   Zused_streamsr   r   r   Z!OleFileIO._check_duplicate_stream  s}     IIDzQR55LII@:MNggjBB11L %/1JK
+r   c                sD   ^p\         R\        R\        R\        R/p\	        V4      pWS,           ^,
          V,          p\        RRR7       \        V4       F  p\        RV,          RR7       K  	  \        4        \        V4       F  pW,          p	\        R	W),           ,          RR7       \        WV,           4       FQ  pWu8  d    MJW,          p
V
R
,          pW9   d
   WK,          pMW^,           8X  d   RpM	RV
,          p\        VRR7       KS  	  \        4        K  	  R# )zE
Display a part of FAT in human-readable form for debugging purposes
z..free..z[ END. ]zFATSECT zDIFSECT indexr   r   %8X%6X:r   z    --->N)r.  r   r-  r,  r   r   r   )r|   r   
firstindexVPLZfatnamesnbsectnlinesr   lr/  r   Zauxr   s   &&&          r   dumpfatZOleFileIO.dumpfat  s    
 



	 S*Q,$g3sA%!)% vAEE&J,-375),9vZ'?#=Ds{)$t|d$ - G! r   c                s@   ^p\         P                   ! \        V4      p\        P                  R8X  d   VP	                  4        \        V4      pWS,           ^,
          V,          p\        RRR7       \        V4       F  p\        RV,          RR7       K  	  \        4        \        V4       Fn  pW,          p	\        RW),           ,          RR7       \        WV,           4       F)  pWu8  d    M"WG,          p
RV
,          p\        VRR7       K+  	  \        4        Kp  	  R# )zC
Display a sector in a human-readable form, for debugging purposes
bigr/  r   r   r0  r1  N)arrayUINT32sys	byteorderbyteswapr   r   r   )r|   sectorr2  r3  r   r4  r5  r   r6  r/  r   r   s   &&&         r   dumpsectZOleFileIO.dumpsect  s     kk&&)==E!LLNS*Q,$g3sA%!)% vAEE&J,-375),9vt|d$ - G r   c                s    \         P                   ! \        V4      p\        P                  R8X  d   VP	                  4        V# )zy
convert a sector to an array of 32 bits unsigned integers,
swapping bytes on big endian CPUs such as PowerPC (old Macs)
r8  )r9  r:  r;  r<  r=  )r|   r   Zar
   r   
sect2arrayZOleFileIO.sect2array  s.     KK%==E!JJLr   c                s   \        V\        P                  4      '       d   TpMKV P                  V4      p\        P	                  \
        P                  4      '       d   V P                  V4       RpV F  pVR,          p\        P                  RV,          4       V\        8X  g   V\        8X  d   \        P                  R4        V# V P                  V4      pV P                  V4      pV P                  V,           V n        K  	  V# )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.
Nr   z
isect = %Xzfound end of sector chain)r   r9  r@  r   isEnabledForr   DEBUGr?  r   r   r.  getsectr   )r|   r   Zfat1ZisectsZnextfatr   r   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  r   c                sT   \         P                  R4       VR,          p\         P                  R\        V4      \        V4      ^,          3,          4       \        P                  ! \        4      V n        V P                  V4       V P                  ^ 8w  Ed   \         P                  R4       V P                  ^m8:  d   V P                  \        R4       V P                  V P                  8  d   V P                  \        R4       \         P                  R4       V P                  ^,          ^,
          pV P                  ^m,
          V,           ^,
          V,          p\         P                  RV,          4       V P                  V8w  d   \        R	4      hV P                  p\!        V4       F  p\         P                  R
We3,          4       V P#                  V4      pV P%                  V4      p\         P'                  \(        P*                  4      '       d   V P-                  V4       V P                  VRV 4       W,          p\         P                  RV,          4       K  	  V\.        \0        39  d   \        R4      hM\         P                  R4       \        V P
                  4      V P                  8  dZ   \         P                  R\        V P
                  4      V P                  3,          4       V P
                  RV P                   V n        \         P                  R\        V P
                  4      V P                  3,          4       \         P'                  \(        P*                  4      '       d3   \         P                  R4       V P3                  V P
                  4       R# R# )z
Load the FAT table.
zDLoading the FAT table, starting with the 1st sector after the header:iL   r   Nzlen(sect)=%d, so %d integersz)DIFAT is used, because file size > 6.8MB.z#incorrect DIFAT, not enough sectorsz)incorrect DIFAT, first index out of rangezDIFAT analysis...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:)r   r   r   r9  r:  r   rE  r  r
  r   r   r   r  r&  r   IOError	iterrangerC  r@  rA  r   rB  r?  r   r.  r7  )	r|   r!   r   Znb_difat_sectorsZnb_difatZisect_difatr   Zsector_difatZdifats	   &&       r   r(  ZOleFileIO.loadfat!  s    			XYf~		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(		6!9IIK#||K85##GMM22MM,/!!%(9)9":;#5		2[@B ) :x"88677 9 II<= txx=4<<'II9S]DLL<YYZxx.DH		JcRVRZRZm]a]i]iMjjkGMM**IIhLL" +r   c                s   V P                   V P                  ,          pV P                  P                  V P                  ,           ^,
          V P                  ,          pV^,          p\
        P                  RV P                  V P                   W1V3,          4       W18  d   V P                  \        R4       V P                  V P                  VRR7      P                  4       pV P                  V4      V n        \
        P                  R\        V P                  4      V3,          4       V P                  RV V n        \
        P                  R\        V P                  4      ,          4       \
        P                  \         P"                  4      '       d3   \
        P                  R4       V P%                  V P                  4       R# R# )	z
Load the MiniFAT table.
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:)r  r  r  r   r  r   r   r  r   r   _openr   r@  r   r   rA  r   rB  r7  )r|   Zstream_sizeZnb_minisectorsZ	used_sizerD  s   &    r   r   ZOleFileIO.loadminifatt  sM    //$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& +r   c                sJ    V P                   P                  V P                  V^,           ,          4       V P                   P                  V P                  4      p\        V4      V P                  8w  dI   \        P                  RV\        V4      V P                  3,          4       V P                  \        R4       V#   \         dZ    \        P                  RYP                  T^,           ,          T P                  3,          4       T P                  \        R4        Li ; i)zu
Read given sector from file on disk.

:param sect: int, sector index
:returns: a string containing the sector data.
z(getsect(): sect=%X, seek=%d, filesize=%dr   z*getsect(): sect=%X, read=%d, sectorsize=%dr   )r"   r   r   r   r   r   r   r   r&  r   r   )r|   r   r>  r
   r   rC  ZOleFileIO.getsect  s    $	NGGLLDF34
 doo.v;$//)IIBs6{DOO45 6|-DE  	NII@Q/@A B|-LM	Ns   3B> >A!D"!D"c                s   \        V\        4      '       g   \        R4      h\        V\        4      '       d   \        V4      ^8w  d   \        R4      h V P                  P                  V P                  V^,           ,          4       \        V4      V P                  8  d+   W#V P                  \        V4      ,
          ,          ,          pM%\        V4      V P                  8  d   \        R4      hV P                  P                  V4       R#   \         dZ    \        P                  RYP                  T^,           ,          T P                  3,          4       T P                  \        R4        Li ; i)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 stringz4write_sect: padding must be a bytes string of 1 charz+write_sect(): sect=%X, seek=%d, filesize=%dr   Data is larger than sector sizeN)r   r   	TypeErrorr   r"   r   r   r   r   r   r   r   r&  
ValueErrorwrite)r|   r   r    paddingr  r   
write_sectZOleFileIO.write_sect  s    $&&EFF'5))S\1_RSS	NGGLLDF34
 t9t&tT:;;DY(>??d  	NIICQ/@A B|-LM	Ns   3D A!E10E1c                sb   \        V\        4      '       g   \        R4      h\        V\        4      '       d   \        V4      ^8w  d   \        R4      h V P                  P                  V4       \        V4      pW@P                  8  d!   W#V P                  V,
          ,          ,          pV P                  V8  d   \        R4      hV P                  P                  V4       R#   \         dA    \        P                  RYP                  3,          4       T P                  \        R4        Li ; i)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 stringz9write_mini_sect: padding must be a bytes string of 1 charz)write_mini_sect(): fp_pos=%d, filesize=%dr   rK  N)r   r   rL  r   r"   r   r   r   r   r   r   r&  r  rM  rN  )r|   fp_posr    rO  Zlen_datar   r   _write_mini_sectZOleFileIO._write_mini_sect  s     $&&JKK'5))S\Q->WXX	NGGLL 
 t9+++t44x?@@D  8+>??d  	NIIA~~./ 0|-LM	Ns   C# #AD.-D.c                s   \         P                  R4       V P                  VRR7      V n        V P                  P                  ^,          p\         P                  RV P                  P                  V3,          4       R.V,          V n        V P                  ^ 4      pV P
                  ^ ,          V n        V P                  P                  4        R# )zE
Load the directory.

:param sect: sector index of directory stream.
zLoading the Directory:TrH  z&loaddirectory: size=%d, max_entries=%dN)	r   r   rJ  r   r   r   r   r  r   )r|   r   Zmax_entriesZ
root_entryr#   r   r)  ZOleFileIO.loaddirectory  s     			*+ !JJttJ< '',,3		:##[12 	3  &;. ((+
OOA&	 			$$&r   c                s   V^ 8  g   V\        V P                  4      8  d   V P                  \        R4       V P                  V,          e*   V P                  \        R4       V P                  V,          # V P
                  P                  V^,          4       V P
                  P                  ^4      p\        W!V 4      V P                  V&   V P                  V,          # )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.
z OLE directory index out of rangez'double reference for OLE stream/storage)	r   r   r   r&  r   r   r   r   r   )r|   r   r   r
   r   r   ZOleFileIO._load_direntry  s     q5CT__--|-OP??3+/9; ??3''sSy)!!&&s+0TBs##r   c                s:    V P                   P                  4        R# )z%
Dump directory (for debugging only)
N)r  r   r{   r(   r   dumpdirectoryZOleFileIO.dumpdirectory,  s     			r   c                s   \         P                  RW\        V4      3,          4       W P                  8  d   V'       g   V P                  '       g   V P                  4        V P                  P                  p\         P                  RV P                  P                  V3,          4       V P                  V P                  P                  VRR7      V n        \        V P                  W^ V P                  V P                  V P                  P                  V R7      # \        V P                  WV P                  V P                  V P                  V P                   V R7      # )aD  
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=%dTrH  )r"   r   r   r   r   r   r   r   )r   r   strr   r   r   r  r   r   rJ  r   r  r   r"   r   r   r   )r|   Zstartr   rI  Zsize_ministreamr   r   rJ  ZOleFileIO._open2  s    			E#i.)* 	+ '''	???  " #'))..		AYY))?;< ="&**TYY-A-A#t #- #5e$%$2E2E!%8L8L'+- - e$(OO(,TXX&*nn'+	- -r   c                s   W#P                   .,           pVP                   F  pVP                  \        8X  dH   V'       d+   VP	                  VR,          VP                   .,           4       V P                  WWdV4       K_  VP                  \        8X  d7   V'       d-   VP	                  VR,          VP                   .,           4       K  K  V P                  \        R4       K  	  R# )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)
:   NNzIThe directory tree contains an entry which is not a stream nor a storage.N)	r   r   r   r   r   _listr   r   r   )r|   filesZprefixnodestreamsstoragesr   s   &&&&&& r   rV  ZOleFileIO._listW  s     99+%YYE=0LLuzzl!:;

5%(C!!\1LLuzzl!:;  ""#3  6A  B r   c                sF    . pV P                  V. V P                  W4       V# )a=  
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
)rV  r  )r|   rY  rZ  rW  r   r   listdirZOleFileIO.listdirs  s$     

5"dii;r   c                s0   \        V\        4      '       d   VP                  R4      pV P                  pV FR  pVP                   F2  pVP
                  P                  4       VP                  4       8X  g   K2   M	  \        R4      hTpKT  	  VP                  # )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)	r   
basestringZsplitr  r   r   r   rF  r   )r|   r   rX  r   r   r   r   _findZOleFileIO._find  sz    $ h
++~~c*HyyDyy88>>#tzz|3 ! .//D  xxr   c                s    V P                  V4      pV P                  V,          pVP                  \        8w  d   \	        R4      hV P                  VP                  VP                  4      # )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^  r   r   r   rF  rJ  r   r   r|   r   r   r   r#   r   
openstreamZOleFileIO.openstream  sU     jj"$|+566zz%**EJJ77r   c                s   VP                   '       g   VP                  V 4       \        VP                   4      pV P                  P                   '       g   V P                  P                  V 4       V P                  V P
                  ,          p\        VP                   4       F  w  rVWd,          pWd,          pV P                  P                   V,          ^,           V P                  ,          WP
                  ,          ,           p	WS^,
          8  d/   W%V P
                  ,          V^,           V P
                  ,           p
MW%V P
                  ,          R p
V P                  W4       K  	  R# )rU  N)r   r   r   r  r  r  	enumeraterR  )r|   r   data_to_writer   Z
block_sizeZidxr   Z	sect_baseZsect_offsetrQ  Zdata_per_sectors   &&&        r   _write_mini_streamZOleFileIO._write_mini_stream  s   ""4())*
yy###II&&t,%%)>)>>
"5#3#34IC*I+Kii**9594;K;KKkZoZoNooF1n%"/d6K6K0KcTUgY]YnYnMn"o"/d6K6K0K0L"M!!&: 5r   c           	     s"   \        V\        4      '       g   \        R4      hV P                  V4      pV P                  V,          pVP
                  \        8w  d   \        R4      hVP                  pV\        V4      8w  d   \        R4      hWPP                  8  d(   VP
                  \        8w  d   V P                  WBR7      # VP                  pWPP                  ^,
          ,           V P                  ,          p\         P#                  RV,          4       \%        V4       F  pW^,
          8  d/   W(V P                  ,          V^,           V P                  ,           p	MWW(V P                  ,          R p	\         P#                  RWPP                  \        V	4      WPP                  ,          3,          4       V P'                  Wi4        V P(                  V,          pK  	  V\,        8w  d   \        R	4      hR#   \*         d    \        R4      hi ; i)
a  
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   rb  r   NzGwrite_stream: size=%d sectorsize=%d data_sector=%Xh size%%sectorsize=%dr   z)incorrect last sector index in OLE stream)r   r   rL  r^  r   r   r   rF  r   r   rM  r   r   rc  r   r   r   r   r   rP  r   r   r   )
r|   Zstream_namer    r   r   r   r   r   r   Zdata_sectors
   &&&       r   write_streamZOleFileIO.write_stream  s    $&&GHHjj%$|+011zz3t9^__'''E,<,<
,J**5*OOooa/0T__D
		#j01z"A Q,"doo$51doo8MN #doo$5$67		c__c+.>@VWX Y OOD.Nxx~- #6 :EFF 	  NLMMNs   G77Hc                s     V P                  V4      pV P                  V,          pVP                  #   \         d     R# i ; i)aX  
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^  r   r   r   r_  r#   r   get_typeZOleFileIO.get_type  sA    	**X&COOC(E### 		s   /2 A Ac                sb    V P                  V4      pV P                  V,          pVP                  # )z
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^  r   r:   r_  r#   r   getclsidZOleFileIO.getclsid  s*     jj"${{r   c                j    V P                  V4      pV P                  V,          pVP                  4       # )a  
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^  r   r   r_  r#   r   r   ZOleFileIO.getmtime$  -     jj"$~~r   c                rg  )z
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^  r   r   r_  r#   r   r   ZOleFileIO.getctime3  rh  r   c                sN     V P                  V4      pR#   \         d     R# i ; i)z
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|   r   r   r
   r   r   ZOleFileIO.existsB  s*    	**X&C 		s    $$c                s    V P                  V4      pV P                  V,          pVP                  \        8w  d   \	        R4      hVP
                  # )a  
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^  r   r   r   rL  r   r_  r#   r   get_sizeZOleFileIO.get_sizeQ  sD     jj"$|+9::zzr   c                s.    V P                   P                  # )zX
Return root entry name. Should usually be 'Root Entry' or 'R' in most
implementations.
)r  r   r{   r(   r   get_rootentry_nameZOleFileIO.get_rootentry_namea  s    
 yy~~r   c           	     s   VR8X  d   . pTp\        V\        4      '       g   RP                  V4      pV P                  V4      p/ p VP	                  ^4      p\        VR,          4      pVP	                  ^4      p\        VR,          4      p	VP                  \        V^4      4       RVP	                  \        VP	                  ^4      4      ^,
          4      ,           p\        V^4      p
\        T
\        \!        T4      ^,          4      4      p
\#        T
4       F  p^ p \        T^T^,          ,           4      p\        T^T^,          ,           4      p\        Y4      p\$        P'                  TR4      p\(        P+                  RTTTT3,          4       T P-                  Y^,           TTY#4      pTYn&   K  	  T#   \         dH   pRP                  \        T4      T4      pT P                  \        T\        T4      4       Tu Rp?# Rp?ii ; i  \         dB   pR	T\        T4      T3,          pT P                  \        T\        T4      4        Rp?EK<  Rp?ii ; i)
  
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\  r!  Nr8   N   ****z6Error while parsing properties header in stream {}: {}UNKNOWN$property id=%d: type=%d/%s offset=%X3Error while parsing property id %d in stream %s: %s)r   rT  r   r`  r   r;   r   r4   BaseExceptionr   r   r   r   typeminr,   r   rG  VTr   r   r   _parse_property)r|   r   r~   r   
streampathr"   r    rD  r:   fmtid	num_propsexcr   r   property_idr   property_typevt_namer   s   &&&&               r   r   ZOleFileIO.getpropertiesh  s    D M
*c***-J__X&	A1T7OEA1S6NEGGC2J"''#bggaj/!"344AAq	I 	3s1vz?3	9%AKE!!QqsUmQ1Q3 #A&&	:		@KQ^`gioCppq,,Qq+}Vbr$)! && ;  	 KQQZ #'C/d3i@K	, ! E Lj!13O8 8""#3S$s)DDEs8   B$F; !BH;H<HHHI5IIc           	     sb   R pV\         8:  g   V\        \        39   d   V P                  WW4WV4      w  rxV# V\        \
        ,          8X  d   \        P                  R4       ^p	\        W4      p
. p\        V
4       FX  p\        WV	,           4      pV P                  WV	,           ^,           W4WV4      w  r|VP                  V4       W^,           ,          p	KZ  	  TpV# V\        ,          '       d   V\        ( ,          p\        P                  R\        P                  VR4      ,          4       ^p	\        W4      p
. p\        V
4       FD  pV P                  WV	,           W4\        ( ,          WV4      w  r|VP                  V4       W,          p	KF  	  TpV# \        P                  RW43,          4       V# )Nz'property_type == VT_VECTOR | VT_VARIANTzproperty_type == VT_VECTOR | %srn  5property id=%d: type=%d not implemented in parser yet)VT_BLOBVT_CLSIDVT_CF_parse_property_basic	VT_VECTOR
VT_VARIANTr   r   r4   r   r   rt  r   )r|   rD  r   rz  r{  r~   r   vZ_ZoffcountZvaluesZszZproperty_type_bases   &&&&&&&       r   ru  ZOleFileIO._parse_property  s   G#}58I'I--aUaqDA4 3 i*44II?@CNEF5\ #A| 433A|a7Geq  Ba Av	 "
 A  Y&&!.)!;II7"&&ASU^:__`CNEF5\221slKbkakQkmy  Ja 	 " A  IIMQ\Pllmr   c                s   R p^ pV\         8X  d!   \        W4      pVR8  d
   VR,
          p^pWx3# V\        8X  d   \        W4      p^pWx3# V\        \        \
        39   d   \        W4      p^pWx3# V\        \        39   d   \        W4      p^pWx3# V\        \        39   dJ   \        W4      p	W^,           V^,           V	,           ^,
           pVP                  RR4      p^V	,           pWx3# V\        8X  d1   \        W4      p	W^,           V^,           V	,            p^V	,           pWx3# V\        8X  dU   \        W^,           4      p	V P                  W^,           V^,           V	^,          ,            4      p^V	^,          ,           pWx3# V\        8X  d   \!        \        W4      4      \!        \        W^,           4      4      ^ ,          ,           pV'       d   W69  d   \"        P%                  RW7\'        V4      R,          3,          4       \(        P(                  ! R^^^ ^ ^ 4      p
\"        P%                  RVR,          ,          4       V
\(        P*                  ! V^
,          R	7      ,           pM	VR,          p^pWx3# V\,        8X  d   \/        W,          4      p^pWx3# V\0        8X  d   \3        WV^,            4      p^pWx3# V\4        8X  d1   \        W4      p	W^,           V^,           V	,            p^V	,           pWx3# V\6        8X  d   \9        \        W4      4      p^pWx3# R p\"        P%                  R
W43,          4       Wx3# )N      r5   r   8Converting property #%d to python datetime, value=%d=%fs逖 r<   timedelta days=%dr=   r}      @T$)VT_I2r2   VT_UI2VT_I4VT_INTVT_ERRORr4   VT_UI4VT_UINTVT_BSTRVT_LPSTRreplacer~  	VT_LPWSTRr   VT_FILETIMEr   r   r   floatr>   r?   VT_UI1r)   r  r;   r  VT_BOOLbool)r|   rD  r   rz  r{  r~   r   r   r   r  r@   s   &&&&&&&    r   r  ZOleFileIO._parse_property_basic  sX   ED %AE>!EMEb ;a &(A\ ;[ 5&(";; AP ;O 67"33AJ ;I 7H"55
 A(6!8E>!#34gs35yv ;u ') A(6!8E>25yj ;i )+
 Aax(..q&(57:J/KL519}Z ;Y +-S^,S1H5E0F0JK  K$DIIX)%,x2GHI J +3*;*;D!Q1a*P'II1U=O5PQR/(2D2DRWY[R[2\\E "X-E8 ;7 &(192 ;1 (*qr	23, ;+ %' A(6!8E>25y  ; ') S^, ; 		QU`Tppq ;r   c                sn    \        4       V n        V P                  P                  V 4       V P                  # )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   r   r   r{   r(   r   get_metadataZOleFileIO.get_metadata%	  s)     $&&t,}}r   c           
     s   \        R4      pVR8X  d   . pTp\        V\        4      '       g   RP                  V4      pV P	                  V4      p. pVP                  ^4      p\        VR,          4      p	\        V^4      p
. p \        V
4       EF  pVP                  ^4      p\        VR,          4      pW8X  g   K/  \        V^4      pVP                  V4       RVP                  \        VP                  ^4      4      ^,
          4      ,           p\        V^4      pV^^^V,          ,            p^^V,          ,           p\        VVV^,            4      pV^,          p\        V4       F  pVVV^,            p\        VV^,           V^,            4      pVV^,           V^,           V,            P                  R4      P                  R4      pVP                  R	VR
R/4       V^,           V,           pK  	  \        V\        \        V4      ^,          4      4      p\        ^V4       EF  p^ p \        V^V^,          ,           4      p\        V^V^,          ,           4      p\        VV4      p\         P#                  VR4      p\$        P'                  RVVVV3,          4       V\(        8X  d&   \+        VV^,           4      pVR8  d
   VR,
          pEMZV^8X  d7   \        VV^,           4      pVV^,           V^,           V,           ^,
           pEMV\,        8X  d   \+        VV^,           4      pEMV\.        \0        \2        39   d   \        VV^,           4      pEMV\4        \6        39   d   \        VV^,           4      pEMV\8        \:        39   dI   \        VV^,           4      pVV^,           V^,           V,           ^,
           pVP=                  RR4      pEMSV\>        8X  d0   \        VV^,           4      pVV^,           V^,           V,            pEMV\@        8X  dF   \        VV^,           4      pV PC                  VV^,           V^,           V^,          ,            4      pEMV\D        8X  d   \G        \        VV^,           4      4      \G        \        VV^,           4      4      ^ ,          ,           pV'       d   VV9  d   \$        P'                  RVV\I        V4      R,          3,          4       \J        PJ                  ! R^^^ ^ ^ 4      p\$        P'                  RVR,          ,          4       V\J        PL                  ! V^
,          R7      ,           pMVR,          pMV\N        8X  d   \Q        VV^,           ,          4      pMV\R        8X  d   \        VV^,           V^,            4      pMV\T        8X  d/   \        VV^,           4      pVV^,           V^,           V,            pMHV\V        8X  d   \Y        \+        VV^,           4      4      pM Rp\$        P'                  RVV3,          4       VW|^,
          ,          R
&   EK  	  EK  	  V#   \Z         dB   pRT\]        T4      T3,          pT P_                  \`        T\c        T4      4        Rp?EKl  Rp?ii ; i  \Z         d@   pR\]        T4      : RT: 2pT P_                  \`        T\c        T4      4       Tu Rp?# Rp?ii ; i)rk  s   ՜. +,Nr\  r!  rl  rm  Zutf_8Z property_namer   rn  ro  r  r  r5   r   r  r  r<   r  r=   r}  rp  z0Error while parsing properties header in stream z: r  )2r;   r   rT  r   r`  r   r4   r   r   r  r9   r   rs  r,   r   rG  rt  r   r   r   r  r2   r  r  r  r  r  r  r  r  r  r~  r  r   r  r   r  r>   r?   r  r)   r  r  r  r  rq  r   r   r   rr  )r|   r   r~   r   ZFMTID_USERDEFINED_PROPERTIESrv  r"   r    rD  r:   Zsections_countZsection_file_pointersr   rw  Zfile_pointerrx  ZPropertyIdentifierAndOffsetr/  Zentry_countZ
identifierZstr_sizeZstringrz  r   r{  r|  r   r  r@   ry  r   s   &&&&                           r   get_userdefined_propertiesZ$OleFileIO.get_userdefined_properties1	  s     (..q'r$ D M
*c***-J__X& GGBKqw Q "R	>*GGBKqv8#&q":LGGL)"''#bggaj/A*=">>A #Aq	I23Aq9}2E/ a	kME"%auQw&7"8KQJE";/%&ueQh%7
#&qq%!)'<#=!"57E!GH,<!=!D!DW!M!S!STX!Y_VWT$JK %a 0 0 !$Is3q6A: ?I 'q)4&'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!|  05D1Ig.G 5? +f !  - Q #X +T*-=s[D #DC ../?d3iPPQ  	
 Z #'C/d3i@K	sP   5Z =E/Z -PY?
Z Z5ZZ ZZ [$%4[[$[$)+r   r  r   r   r   r  r   r   r   r   r   r   r   r   r"   r   r   r   r  r  r  r   r  r   r  r   r  r  r  r	  r
  r  r   r   r  r  r  r  r  r   r  r  r   )r  )Fr*   )r5   )TF)FN)4rF   rG   rH   rI   rJ   r&  DEFAULT_PATH_ENCODINGr}   r  r  r  rD   r   r   r   r*  r  r   r7  r?  r@  rE  r(  r   rC  rP  rR  r)  r   rS  r   rJ  rV  r[  r^  r`  rc  rd  re  rf  r   r   r   ri  rj  r   ru  r  r  r  rK   r   r   r   r   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&   >@>[|
{ {r   c                 s   ^ RI p ^ RIpRpR\        P                  R\        P                  R\        P
                  R\        P                  R\        P                  /pRpVP                  VR7      pVP                  R	R
RRR7       VP                  RR
RRR7       VP                  RR
RRR7       VP                  RRRRVRR7       VP                  4       w  rg\        RP                  \        \        4      4       \        V4      ^ 8X  d1   \        \         4       VP#                  4        V P$                  ! 4        VP&                  '       d   RVn        \        P*                  ! W6P(                  ,          RR7       \-        4        V EF/  p \/        V4      p	\        R?4       \        V4       \        R?4       V	P1                  4        V	P3                  4        EFg  p
V
R@,          ^ ,          R8X  g   K  \        RV
,          4        V	P5                  V
R R!7      p\7        VP9                  4       4      pV Fy  w  r\;        V\<        \>        34      '       d   \        V4      ^28  d
   VR",          p\;        V\>        4      '       d   RA F  pV\A        V4      9   g   K  R#p M	  \        R$W4       K{  	   VPH                  '       d|   V	PK                  V
R R!7      p\        V4      '       dU   \        R&V
,          4       \M        V4       F0  w  pp\        R'P                  VVR(,          VR),          4      4       K2  	  EKd  EKg  EKj  	  VPN                  '       d   \        R+4       V	P3                  4        F  p
\        R\Q        R,PS                  V
4      4      RR-R.7       V	PU                  V
4      pV\V        8X  d5   \        R/V	PY                  V
4      ,          4       V	P[                  V
4       Kz  \        R0V,          4       K  	  \        4        \        R14       V	P\                   FK  pVf   K	  \        R2P                  VP^                  VPa                  4       VPc                  4       4      4       KM  	  \        4         V	Pe                  4       pVPg                  4        \        4        V	Pi                  4       p\        R4V,          4       V	Pk                  R54      '       dd   \        R64       \        R7V	PU                  R54      4       \        R8V	PY                  R54      4       V	Pk                  R94      '       d   \        R:4       \        R;4       V	Pl                  '       d=   V	Pl                   F+  w  pp\        R<P                  VPn                  V4      4       K-  	  M\        R=4       V	Pq                  4        EK2  	  R#   \B         d!    \D        PG                  R%T
,          4        EL6i ; i   \D        PG                  R*T
,          4        EK5  ; i  \B         d    \D        PG                  R34        ELi ; i  \B         d"    \D        PG                  R>T,          4        EK  i ; i)Bz
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
Nr  r   Zinfor  Zcriticalz1usage: %prog [options] <filename> [filename2 ...])usagez-cZ
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loglevelZstorezBlogging level debug/info/warning/error/critical (default=%default))r  r  Zdefaultr  z=olefile version {} {} - https://www.decalage.info/en/olefile
z%(levelname)-8s %(message)s)r	   r   Z-Zz%r: propertiesTr   :Ni2   Nz(binary data)z   z&Error while parsing property stream %rz%r: user-defined propertiesz
	{} {}: {}r  r   z3Error while parsing user-defined property stream %rz
Checking streams...r\  r   r   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"Z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   ZNonezError while parsing file %rzD--------------------------------------------------------------------i)rU  i   r   r#  i   i   i   i   i   i   i   r8   i   i   i   i   i   i   i   r"  i   i   i   i   i   i   i   )9r;  optparser   rB  ZINFOZWARNINGZERRORCRITICALZOptionParserZ
add_optionZ
parse_argsr   r   __version____date__r   rJ   Z
print_helpZexitr  r  ZbasicConfigr   r   rS  r[  r   Zsorteditemsr   r]  r   r'  r   r   Z	exceptionr  r  ra  r  r   r   re  r   ri  r`  r   r   r   r   r  r   rj  r   r   rF   r*  )r;  r  ZDEFAULT_LOG_LEVELZ
LOG_LEVELSr  ZparserZoptionsr  r   r   Z
streamnamer   Zkr  r'   Z	variablesr/  ZvariableZst_typer   Zmetar  Zexctyper   s                           r   mainr  	  sB    !GMMGLLGOOGMMG$$
J @E"""/F
d<o9  ;
d<6JA  C
d<lk  m
dLz'Sd!e  g '')OW	
J
Q
QR]_g
hi 4yA~g
" j)9)9:C`a ^	DH%C(O(O(O!kkm
b>!$.*Z78] # 1 1*4 1 P &u{{} 5$)DA)!j%-@AA#&q6B;()#A)!U33*LA'(IaL'8,;(-	*L
 "%. %* 	j"555(+(F(Fz`d(F(eI"9~~ %&Cj&P Q7@7KOE8$)-*>*>uhF_`hip`q*r$s 8L  . 6/ ,D $$$-."%++-J#tCHHZ$89#3G!ll:6G,.i#,,z*BBCz26@A #0  IJ$3::5::(%..*:< = ( G>'')		 G))+D)D01zz.))016^8TUh^ <=::l++AB =>!!!$'$6$6LGS*++G,<,<cBC %7 fIIK{ 4 % ]&NQ[&[\]j&[^h&hiiF  ><=>*  	DMM7(BCC	Ds   A"X95X9BV?V?4W-A5W-;X9CX9-AX9> XDX9?'W*&X9)W**X9-XX9 X62X95X66X99'Y%$Y%Z__main__)r$   r   r   r   r   r   r   r   r   STGTY_PROPERTYSTGTY_LOCKBYTESr   r   r   r   r&  r  
MAXREGSECTr,  r-  r   r.  	MAXREGSIDr   r   
WORD_CLSIDr   )NNr*   )zrJ   Z
__future__r    r  r  Z
__author__Z__all__r   r;  r.   r9  Zos.pathr%  r>   r   r+  r$  rT  r   r,   r   ZxrangerG  r   r   Zitemsizer:  rM  r]  Z	NameErrorZversion_infor  r  r   r   r   r   r  r,  r-  r   r.  r  r   r   r   r   r  r  r   r   ZVT_EMPTYZVT_NULLr  r  ZVT_R4ZVT_R8ZVT_CYZVT_DATEr  ZVT_DISPATCHr  r  r  Z
VT_UNKNOWNZ
VT_DECIMALZVT_I1r  r  r  ZVT_I8ZVT_UI8r  r  ZVT_VOIDZ
VT_HRESULTZVT_PTRZVT_SAFEARRAYZ	VT_CARRAYZVT_USERDEFINEDr  r  r  r~  Z	VT_STREAMZ
VT_STORAGEZVT_STREAMED_OBJECTZVT_STORED_OBJECTZVT_BLOB_OBJECTr  r  r  rt  r   Zvarsr  ZkeywordZvarr  r   r   r   r&  r   r$   r)   r2   r4   r;   rB   rF  rD   rM   r   ZRuntimeWarningr   r   r   r   r   r  rF   r   r   r   <module>r     sD  8 &x  
	 
 
 E E E E
 eDI 	;;s!F
[[!#F
[[!# 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; 7I ;	II	II