HEX
Server: Apache
System: Linux srv1.prosuiteplus.com 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64
User: prosuiteplus (1001)
PHP: 8.3.20
Disabled: NONE
Upload Files
File: //lib/python3/dist-packages/olefile/__pycache__/olefile.cpython-38.pyc
U

6��[_��@s�dZddlmZdZdZdZdddd	d
ddd
ddddddddddddddddddd gZdd!lZdd!lZdd!l	Z	dd!l
Z
dd!lZdd!l
Z
dd!lZeek	r�eZzeZWneZYnXe
�
d"�jd#kr�d"Zn4e
�
d$�jd#kr�d$Zne
�
d%�jd#kr�d%Zned&��zeWnek
�r eZYnXd'Zejdd(k�r<d)Znd!Zejd*fd+d,�Zed-�Z d.d	�Z!d/Z"d0Z#d1Z$d2Z%d3Z&d4Z'd0Z(d4Z)dZ*d*Z+d5Z,d(Z-d#Z.d6Z/d7Z0dZ1d*Z2d5Z3d(Z4d#Z5d6Z6d8Z7d9Z8d:Z9d;Z:d<Z;d=Z<d>Z=d?Z>d@Z?dAZ@dBZAdCZBdDZCdEZDdFZEdGZFdHZGdIZHdJZIdKZJdLZKdMZLdNZMdOZNdPZOdQZPdRZQdSZRdTZSdUZTdVZUdWZVdXZWdYZXdZZYd[ZZd<Z[dEZ\dOZ]d\Z^d]Z_d^d�Z`eek�rvd_d`�Zandad`�Zadsdbdc�Zbdtddde�Zcdfdg�Zddhdi�ZeGdjd�d�ZfGdkdl�dlejg�ZhGdmdn�dn�ZiGdod�d�Zjdpdq�Zkeldrk�r�ek�d!S)ua:
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.4+

Project website: https://www.decalage.info/olefile

olefile is copyright (c) 2005-2018 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
2018-09-09z0.46zPhilippe Lagadec�	isOleFile�	OleFileIO�OleMetadata�enable_logging�MAGIC�STGTY_EMPTY�KEEP_UNICODE_NAMES�STGTY_STREAM�
STGTY_STORAGE�
STGTY_ROOT�STGTY_PROPERTY�STGTY_LOCKBYTES�MINIMAL_OLEFILE_SIZE�
DEFECT_UNSURE�DEFECT_POTENTIAL�DEFECT_INCORRECT�DEFECT_FATAL�DEFAULT_PATH_ENCODING�
MAXREGSECT�DIFSECT�FATSECT�
ENDOFCHAIN�FREESECT�	MAXREGSID�NOSTREAM�UNKNOWN_SIZE�
WORD_CLSIDN�L��I�iz>Need to fix a bug with 32 bit arrays, please contact author...T�zutf-8�cCsL|tjjjkr&t�|�}|�|�|St�|�}|�t���|�|�|S)an
    Create a suitable logger object for this module.
    The goal is not to change settings of the root logger, to avoid getting
    other modules' logs on the screen.
    If a logger exists with same name, reuse it. (Else it would have duplicate
    handlers and messages would be doubled.)
    The level is set to CRITICAL+1 by default, to avoid any logging.
    )�loggingZLogger�managerZ
loggerDictZ	getLogger�setLevelZ
addHandlerZNullHandler)�name�levelZlogger�r)�1/usr/lib/python3/dist-packages/olefile/olefile.py�
get_logger�s



r+�olefilecCst�tj�dS)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$ZNOTSETr)r)r)r*r�ss��ࡱ�l��l��l��l�������i�������	�
���
������������������@�A�B�C�D�E�F�G�H�z$00020900-0000-0000-C000-000000000046�(ic	Cs�t|d�r$|�tt��}|�d�nLt|t�rLt|�tkrL|dtt��}n$t|d��}|�tt��}W5QRX|tkr|dSdSdS)aJ
    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.

    .. versionadded:: 0.16

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

        - 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 and seek methods),
          it is parsed as-is.

    :type filename: bytes or str or unicode or file
    :returns: True if OLE, False otherwise.
    :rtype: bool
    �readrN�rbTF)	�hasattrrU�lenr�seek�
isinstance�bytesr�open)�filename�header�fpr)r)r*rs
cCst|�S�N)�ord��cr)r)r*�i8?srdcCs|jtkr|S|dS�Nr)�	__class__�intrbr)r)r*rdCscCst�d|||d��dS)z�
    Converts a 2-bytes (16 bits) string to an integer.

    :param c: string containing bytes to convert
    :param o: offset of bytes to convert in string
    z<Hr/r��struct�unpack�rc�or)r)r*�i16GsrmcCst�d|||d��dS)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<Irrrhrkr)r)r*�i32QsrncCsTt|�dkst�|�d�sdSdt|d�t|d�t|d�fttt|dd���S)	z^
    Converts a CLSID to a human-readable string.

    :param clsid: string of length 16.
    r:��z0%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02Xrrr1r3)rX�AssertionError�striprnrm�tuple�maprd)�clsidr)r)r*�_clsid[s
��rvcCs(t�dddddd�}|tj|dd�S)zL
        convert FILETIME (64 bits int) to Python datetime.datetime
        �Ar#rr5�Zmicroseconds)�datetime�	timedelta)Zfiletime�_FILETIME_null_dater)r)r*�filetime2datetimelsr|c@s�eZdZdZdddddddd	d
ddd
dddddddgZdddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0gZd1d2�Zd3d4�Zd5d6�Zd7S)8raT
    class to parse and store metadata from standard properties of OLE files.

    Available attributes:
    codepage, title, subject, author, keywords, comments, template,
    last_saved_by, revision_number, total_edit_time, last_printed, create_time,
    last_saved_time, num_pages, num_words, num_chars, thumbnail,
    creating_application, security, codepage_doc, category, presentation_target,
    bytes, lines, paragraphs, slides, notes, hidden_slides, mm_clips,
    scale_crop, heading_pairs, titles_of_parts, manager, company, links_dirty,
    chars_with_spaces, unused, shared_doc, link_base, hlinks, hlinks_changed,
    version, dig_sig, content_type, content_status, language, doc_version

    Note: an attribute is set to None when not present in the properties of the
    OLE file.

    References for SummaryInformation stream:

    - https://msdn.microsoft.com/en-us/library/dd942545.aspx
    - https://msdn.microsoft.com/en-us/library/dd925819%28v=office.12%29.aspx
    - https://msdn.microsoft.com/en-us/library/windows/desktop/aa380376%28v=vs.85%29.aspx
    - https://msdn.microsoft.com/en-us/library/aa372045.aspx
    - http://sedna-soft.de/articles/summary-information-stream/
    - https://poi.apache.org/apidocs/org/apache/poi/hpsf/SummaryInformation.html

    References for DocumentSummaryInformation stream:

    - https://msdn.microsoft.com/en-us/library/dd945671%28v=office.12%29.aspx
    - https://msdn.microsoft.com/en-us/library/windows/desktop/aa380374%28v=vs.85%29.aspx
    - https://poi.apache.org/apidocs/org/apache/poi/hpsf/DocumentSummaryInformation.html

    new in version 0.25
    �codepage�title�subject�author�keywords�comments�template�
last_saved_by�revision_number�total_edit_time�last_printed�create_time�last_saved_time�	num_pages�	num_words�	num_chars�	thumbnail�creating_application�security�codepage_doc�category�presentation_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_versioncCsd|_d|_d|_d|_d|_d|_d|_d|_d|_d|_	d|_
d|_d|_d|_
d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_ d|_!d|_"d|_#d|_$d|_%d|_&d|_'d|_(d|_)d|_*d|_+d|_,d|_-d|_.dS)z_
        Constructor for OleMetadata
        All attributes are set to None by default
        N)/r}r~rr�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���selfr)r)r*�__init__�s^zOleMetadata.__init__cCs�|j|jD]}t||d�q|�d�rp|jdddgd�}tt|j��D]&}|�|dd�}t||j||�qH|�d�r�|jddd�}tt|j��D]&}|�|dd�}t||j||�q�dS)	a=
        Parse standard properties of an OLE file, from the streams
        ``\x05SummaryInformation`` and ``\x05DocumentSummaryInformation``,
        if present.
        Properties are converted to strings, integers or python datetime objects.
        If a property is not present, its value is set to None.
        NzSummaryInformationTr5)�convert_time�
no_conversionr#zDocumentSummaryInformation�r�)�SUMMARY_ATTRIBS�DOCSUM_ATTRIBS�setattr�exists�
getproperties�rangerX�get)r�r,Zattrib�propsr!�valuer)r)r*�parse_properties�s"	
�
�zOleMetadata.parse_propertiescCshtd�|jD]"}t||�}td|t|�f�qtd�|jD]"}t||�}td|t|�f�q@dS)z<
        Dump all metadata, for debugging purposes.
        z*Properties from SummaryInformation stream:�- %s: %sz2Properties from DocumentSummaryInformation stream:N)�printr��getattr�reprr�)r�Zpropr�r)r)r*�dumps



zOleMetadata.dumpN)	�__name__�
__module__�__qualname__�__doc__r�r�r�r�r�r)r)r)r*rzsV$��8 c@seZdZdZdd�ZdS)�	OleStreama�
    OLE2 Stream

    Returns a read-only file object which can be used to read
    the contents of a OLE stream (instance of the BytesIO class).
    To open a stream, use the openstream method in the OleFile 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	CsDt�d�t�d|||||t|�t|�f�||_|jjjrFtd��d}	|tkrlt|�|}d}	t�d�||d|}
t�d|
�|
t|�kr�|j�	t
d	�g}|d
kr�|tkr�t�d�|j�	t
d�t|
�D�]�}t�d
||f�|tk�r*|	�rt�d��q�nt�d�|j�	t
d�|d
k�sB|t|�k�r�t�d||t|�f�t�d||
f�|j�	t
d��q�z|�
|||�Wn>t�d|||||f�|j�	t
d�Y�q�YnX|�|�}
t|
�|k�rT|t|�dk�rTt�d|t|�||||t|
�f�t�d|||t|
��|j�	t
d�|�|
�z||d@}Wq�tk
�r�|j�	t
d�Y�q�Yq�Xq�d�|�}t|�|k�r�t�dt|�|f�|d|�}||_nR|	�rt�dt|��t|�|_n.t�dt|�|f�t|�|_|j�	t
d�tj�||�dS) a_
        Constructor for OleStream class.

        :param fp: file object, the OLE container or the MiniFAT stream
        :param sect: sector index of first sector in the stream
        :param size: total size of the stream
        :param offset: offset in bytes for the first FAT or MiniFAT sector
        :param sectorsize: size of one sector
        :param fat: array/list of sector indexes (FAT or MiniFAT)
        :param filesize: size of OLE file (for debugging)
        :param olefileio: OleFileIO object containing this stream
        :returns: a BytesIO instance containing the OLE stream
        zOleStream.__init__:zE  sect=%d (%X), size=%d, offset=%d, sectorsize=%d, len(fat)=%d, fp=%sz2Attempting to open a stream from a closed OLE FileFTz  stream with UNKNOWN SIZEr#�nb_sectors = %dz(malformed OLE document, stream too largerz!size == 0 and sect != ENDOFCHAIN:z+incorrect OLE sector index for empty streamzReading stream sector[%d] = %Xhz6Reached ENDOFCHAIN sector for stream with unknown sizez$sect=ENDOFCHAIN before expected sizezincomplete OLE streamzsect=%d (%X) / len(fat)=%dzi=%d / nb_sectors=%d�,incorrect OLE FAT, sector index out of rangezsect=%d, seek=%d, filesize=%d�OLE sector index out of rangez9sect=%d / len(fat)=%d, seek=%d / filesize=%d, len read=%dzseek+len(read)=%d�incomplete OLE sectorr.�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-�debugrXr��oler_�closed�OSErrorr�
_raise_defectrrr�rYrU�append�
IndexError�join�size�io�BytesIOr�)r�r_�sectr��offset�
sectorsize�fat�filesize�	olefileioZunknown_size�
nb_sectors�datar!Zsector_datar)r)r*r�*s�
�





�
 �


zOleStream.__init__N)r�r�r�r�r�r)r)r)r*r�sr�c@s�eZdZdZdZdZe�e�eks&t�dd�Z	dd�Z
dd	�Zd
d�Zdd
�Z
dd�Zdd�Zdd�Zddd�Zdd�Zdd�ZdS)�OleDirectoryEntryz
    OLE2 Directory Entry
    z<64sHBBIII16sIQQIII�cCsj||_||_g|_i|_d|_t�tj|�\|_	|_
|_|_|_
|_|_}|_|_|_|_|_|_|jttttfkr�|�td�|jtkr�|dkr�|�td�|dkr�|jtkr�|�td�|j
dkr�|�td�d|_
|j	d|j
d	�|_|�|j�|_t� d
|jt!|j�f�t� d|j�t� d|j�t� d
|j
|j|jf�|j"dk�r�|jdk�r�|jdk�r�t� d|j"|j|j|jf�|�t#d�|j|_$n|jt%|j�d>|_$t� d|j$|j|jf�t&|�|_'|jtk�r|j$dk�r|�t(d�d|_)|jttfk�r`|j$dk�r`|j$|j*k�rJ|jtk�rJd|_)nd|_)|�+|j|j)�d|_,dS)aI
        Constructor for an OleDirectoryEntry object.
        Parses a 128-bytes entry from the OLE Directory stream.

        :param entry  : string (must be 128 bytes long)
        :param sid    : index of this directory entry in the OLE file directory
        :param olefile: OleFileIO containing this directory entry
        Fzunhandled OLE storage typerzduplicate OLE root entryzincorrect OLE root entryrJz(incorrect DirEntry name length >64 bytesNr/zDirEntry SID=%d: %sz - type: %dz - sect: %Xhz% - SID left: %d, right: %d, child: %d�r.z+sectorsize=%d, sizeLow=%d, sizeHigh=%d (%X)zincorrect OLE stream size� z% - size: %d (sizeLow=%d, sizeHigh=%d)zOLE storage with size>0T)-�sidr,�kids�	kids_dict�usedrirjr��STRUCT_DIRENTRYZname_rawZ
namelength�
entry_typeZcolor�sid_left�	sid_right�	sid_childZdwUserFlags�
createTime�
modifyTime�
isectStartZsizeLowZsizeHighrrr
rr�rZ
name_utf16�_decode_utf16_strr'r-r�r�r�rr��longrvrur�
is_minifat�minisectorcutoff�_check_duplicate_stream�
sect_chain)r��entryr�r,rur)r)r*r��sx	�

��

�zOleDirectoryEntry.__init__cCs~|jr
dS|jttfks"|jdkr&dSt�|_|jrB|jsB|��|j	}|t
krz|j�|�|jrn|j|}qH|j|}qHdSre)
r�r�rr
r��listr��minifat�loadminifatr�rr�r�)r�r,Z	next_sectr)r)r*�build_sect_chain-sz"OleDirectoryEntry.build_sect_chaincCsBt�d|jt|j�|jf�|jtkr>|�|j�|j�	�dS)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�r�append_kidsr��sortr�r)r)r*�build_storage_tree@s�
	z$OleDirectoryEntry.build_storage_treecCs�t�d|�|tkrdS|dks2|t|jj�krB|j�td�n�|j�|�}t�d|j	t
|j�|j|j
|jf�|jr�|j�td�dSd|_|�|j�|j��}||jkr�|j�td�|j�|�||j|<|�|j
�|��dS)	a)
        Walk through red-black tree of children of this directory entry to add
        all of them to the kids list. (recursive method)

        :param child_sid: index of child directory entry to use, or None when called
            first time for the root. (only used during recursion)
        zappend_kids: child_sid=%dNrzOLE DirEntry index out of rangezHappend_kids: child_sid=%d - %s - sid_left=%d, sid_right=%d, sid_child=%dz#OLE Entry referenced more than onceTz!Duplicate filename in OLE storage)r-r�rrXr,�
direntriesr�r�_load_direntryr�r�r'r�r�r�r�r��lowerr�r�r�r�)r�Z	child_sidZchildZ
name_lowerr)r)r*r�Xs2��

�
zOleDirectoryEntry.append_kidscCs|j|jkS�zCompare entries by name�r'�r��otherr)r)r*�__eq__�szOleDirectoryEntry.__eq__cCs|j|jkSr�r�r�r)r)r*�__lt__�szOleDirectoryEntry.__lt__cCs|�|�Sr`)rr�r)r)r*�__ne__�szOleDirectoryEntry.__ne__cCs|�|�p|�|�Sr`)rrr�r)r)r*�__le__�szOleDirectoryEntry.__le__rcCs�ddddddg}z||j}Wntk
r6d}YnXtd|t|j�|dd	�|jttfkrrt|jd
dd	�t�|jttfkr�|j	r�td|d|j	�|j
D]}|�|d�q�d
S)zADump this entry, and all its subentries (for debug purposes only)z	(invalid)z	(storage)z(stream)z(lockbytes)z
(property)z(root)z	(UNKNOWN)� ��endr[z{%s}r/N)r�r�r�r�r'r
rr�rrur�r�)r��tabZTYPESZ	type_name�kidr)r)r*r��s �

zOleDirectoryEntry.dumpcCs|jdkrdSt|j�S)z�
        Return modification time of a directory entry.

        :returns: None if modification time is null, a python datetime object
            otherwise (UTC timezone)

        new in version 0.26
        rN)r�r|r�r)r)r*�getmtime�s	
zOleDirectoryEntry.getmtimecCs|jdkrdSt|j�S)z�
        Return creation time of a directory entry.

        :returns: None if modification time is null, a python datetime object
            otherwise (UTC timezone)

        new in version 0.26
        rN)r�r|r�r)r)r*�getctime�s	
zOleDirectoryEntry.getctimeN)r)r�r�r�r�r�Z
DIRENTRY_SIZEri�calcsizerqr�r�r�r�rrrrr�r
rr)r)r)r*r��sb/	
r�c@sZeZdZdZdeddefdd�Zdd�Zdd	�Ze	fd
d�Z
dPd
d�ZdQdd�Zdd�Z
dRdd�ZdSdd�ZdTdd�Zdd�Zdd�Zdd�Zd d!�Zd"d#�ZdUd%d&�ZdVd'd(�Zd)d*�Zd+d,�Zd-d.�Zedfd/d0�ZdWd2d3�ZdXd4d5�Zd6d7�Zd8d9�Z d:d;�Z!d<d=�Z"d>d?�Z#d@dA�Z$dBdC�Z%dDdE�Z&dFdG�Z'dHdI�Z(dJdK�Z)dYdLdM�Z*dNdO�Z+dS)Zra�
    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::

        ole = OleFileIO("fan.mic")

        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).
    NFcCs||_g|_||_||_d|_d|_g|_g|_d|_d|_	d|_
d|_d|_d|_
d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_ d|_!d|_"d|_#d|_$d|_%d|_&|�r|j'||d�dS)a�
        Constructor for the OleFileIO class.

        :param filename: file to open.

            - if filename is a string smaller than 1536 bytes, it is the path
              of the file to open. (bytes or unicode string)
            - if filename is a string longer than 1535 bytes, it is parsed
              as the content of an OLE file in memory. (bytes type only)
            - if filename is a file-like object (with read, seek and tell methods),
              it is parsed as-is.

        :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)
        N)�
write_mode)(�_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_numberr\)r�r]Z
raise_defectsr
r�rr)r)r*r��sTzOleFileIO.__init__cCs|Sr`r)r�r)r)r*�	__enter__6szOleFileIO.__enter__cGs|��dSr`)�close)r��argsr)r)r*�__exit__:szOleFileIO.__exit__cCs<||jkrt�|�||��n|j�||f�t�|�dS)a�
        This method should be called for any defect found during file parsing.
        It may raise an IOError 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, IOError by default
        N)rr-�errorrr��warning)r�Zdefect_level�messageZexception_typer)r)r*r�>s



zOleFileIO._raise_defect�replacecCs(|�d|�}|jr |�|j|�S|SdS)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 utf16_str: bytes string encoded in UTF-16 LE format
        :param errors: str, see python documentation for str.decode()
        :return: str, encoded according to path_encoding
        zUTF-16LEN)�decoder�encode)r�Z	utf16_str�errorsZunicode_strr)r)r*r�Xs
zOleFileIO._decode_utf16_strc	Cs�||_t|d�r||_n@t|t�r<t|�tkr<t�|�|_n|jrHd}nd}t	||�|_d}|j�
dtj�z|j�
�}W5|j�
d�X||_t�d|j|jf�g|_g|_|j�d�}t|�dks�|dd�tk�rt�d	|dd�tf�|�td
�d}t�|�}t�d||d
f�|d|�}t�||�\|_|_|_|_|_|_|_ |_!|_"|_#|_$|_%|_&|_'|_(|_)|_*|_+t�t�||��|jtk�r�|�td�|jt,d�k�r�|�t-d�t�d|j�t�d|j�|jdk�r|�t-d�t�d|j�|jdk�r,|�t-d�d|j|_.t�d|j.�|j.dk�r`|�t-d�|jdk�rx|j.dk�s�|jdk�r�|j.dk�r�|�t-d�d|j |_/t�d |j/�|j/d!k�r�|�t-d"�|j!dk�s�|j"dk�r�|�t-d#�t�d$|j#�|j.dk�r(|j#dk�r(|�t-d%�t�d&|j$�t�d'|j%�t�d(|j&�|j&dk�rp|�t0d)�t�d*|j'�|j'dk�r�|�t-d+�t�1d,|j'�d|_'t�d-|j(�t�d.|j)�t�d/|j*�t�d0|j+�||j.d1|j.d1|_2t�d2|j2|j2f�t3|dd3��|_|j.|_4|j/|_5|j'|_6|�7|j%�|j)�rh|�7|j(�|j+�r||�7|j*�|�8|�|�9|j%�|j(|_:dS)4a�
        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.

        :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)
        rUzr+brVrzFile size: %d bytes (%Xh)r�Nr3zMagic = %r instead of %rz#not an OLE2 structured storage filez<8s16sHHHHHHLLLLLLLLLLzfmt_header size = %d, +FAT = %di�zincorrect OLE signaturer:zincorrect CLSID in OLE headerzMinor Version = %dz%DLL Version   = %d (expected: 3 or 4))r"rz"incorrect DllVersion in OLE headerz#Byte Order    = %X (expected: FFFE)i��z!incorrect ByteOrder in OLE headerr/z0Sector Size   = %d bytes (expected: 512 or 4096))r�rSz#incorrect sector_size in OLE headerr"rrSz3sector_size does not match DllVersion in OLE headerz/MiniFAT Sector Size   = %d bytes (expected: 64))rJz(incorrect mini_sector_size in OLE headerz.incorrect OLE header (non-null reserved bytes)z Number of Directory sectors = %dz3incorrect number of directory sectors in OLE headerzNumber of FAT sectors = %dzFirst Directory sector  = %Xhz$Transaction Signature Number    = %dz5incorrect OLE header (transaction_signature_number>0)z/Mini Stream cutoff size = %Xh (expected: 1000h)z/incorrect mini_stream_cutoff_size in OLE headerzJFixing the mini_stream_cutoff_size to 4096 (mandatory value) instead of %dzFirst MiniFAT sector      = %XhzNumber of MiniFAT sectors = %dzFirst DIFAT sector        = %XhzNumber of DIFAT sectors   = %dr#z/Maximum number of sectors in the file: %d (%Xh)rB);r
rWr_rZr[rXrr�r�r\rY�os�SEEK_END�tellrr-r�rrrUrr�rrirrjrrr#rrr,rr)r*r&r'rr.r rr(rr%�	bytearrayrr-rrr4r$rvr�r"r�r��loadfat�
loaddirectoryr!)	r�r]r
�moder�r^Z
fmt_header�header_sizeZheader1r)r)r*r\ks�
'

����
zOleFileIO.opencCs|j��dS)z@
        close the OLE file, to release the file object
        N)r_r0r�r)r)r*r0KszOleFileIO.closecCsf|rt�d|�|j}n(t�d|�|ttttfkr<dS|j}||krX|�t	d�n
|�
|�dS)ag
        Checks if a stream has not been already referenced elsewhere.
        This method should only be called once for each known stream, and only
        if stream size is not null.

        :param first_sect: int, index of first sector of the stream in FAT
        :param minifat: bool, if True, stream is located in the MiniFAT, else in the FAT
        z,_check_duplicate_stream: sect=%Xh in MiniFATz(_check_duplicate_stream: sect=%Xh in FATNzStream referenced twice)r-r�rrrrrrr�rr�)r�Z
first_sectr�Zused_streamsr)r)r*r�Rs	z!OleFileIO._check_duplicate_streamrc
Cs�d}tdtdtdtdi}t|�}||d|}tddd	�t|�D]}td
|dd	�qDt�t|�D]�}||}	td||	dd	�t|	|	|�D]X}||kr�q�||}
|
d@}||kr�||}n|
|dkr�d
}nd
|
}t|dd	�q�t�qhdS)zU
        Display a part of FAT in human-readable form for debugging purposes
        r3z..free..z[ END. ]zFATSECT zDIFSECT r#�indexrr�%8X�%6X:r.z    --->N)rrrrrXr�r�)
r�r��
firstindex�VPLZfatnames�nbsect�nlinesr!�lrBr�Zauxr'r)r)r*�dumpfatls>�
zOleFileIO.dumpfatcCs�d}t�t|�}tjdkr"|��t|�}||d|}tddd�t|�D]}td|dd�qNt�t|�D]b}||}	td||	dd�t|	|	|�D],}||kr�q�||}
d|
}t|dd�q�t�qrd	S)
zS
        Display a sector in a human-readable form, for debugging purposes
        r3�bigr#rBrrrCrDN)�array�UINT32�sys�	byteorder�byteswaprXr�r�)r��sectorrErFrrGrHr!rIrBr�r'r)r)r*�dumpsect�s(
zOleFileIO.dumpsectcCs"t�t|�}tjdkr|��|S)z�
        convert a sector to an array of 32 bits unsigned integers,
        swapping bytes on big endian CPUs such as PowerPC (old Macs)
        rK)rLrMrNrOrP)r�r��ar)r)r*�
sect2array�s
zOleFileIO.sect2arraycCs�t|tj�r|}n |�|�}t�tj�r2|�|�d}|D]X}|d@}t�d|�|t	ksd|t
krrt�d�q�|�|�}|�|�}|j||_q:|S)z�
        Adds the indexes of the given sector to the FAT

        :param sect: string containing the first FAT sector, or array of long integers
        :returns: index of last FAT sector.
        Nr.z
isect = %Xzfound end of sector chain)
rZrLrTr-�isEnabledForr$�DEBUGrRr�rr�getsectr�)r�r�Zfat1Zisect�sZnextfatr)r)r*�loadfat_sect�s 




zOleFileIO.loadfat_sectc	Cs�t�d�|dd�}t�dt|�t|�df�t�t�|_|�|�|jdk�rnt�d�|jdkrv|�	t
d	�|j|jkr�|�	t
d
�t�d�|jdd}|jd|d|}t�d
|�|j|kr�td��|j}t|�D]j}t�d||f�|�|�}|�|�}t�tj��r,|�|�|�|d|��||}t�d|�q�|ttfk�rxtd��n
t�d�t|j�|jk�r�t�dt|j�|jf�|jd|j�|_t�dt|j�|jf�t�tj��r�t�d�|�|j�dS)z%
        Load the FAT table.
        zDLoading the FAT table, starting with the 1st sector after the header�Lr�zlen(sect)=%d, so %d integersrrz)DIFAT is used, because file size > 6.8MB.�mz#incorrect DIFAT, not enough sectorsz)incorrect DIFAT, first index out of rangezDIFAT analysis...r#z
nb_difat = %dzincorrect DIFATzDIFAT block %d, sector %XNznext DIFAT sector: %Xzincorrect end of DIFATz$No DIFAT, because file size < 6.8MB.z!len(fat)=%d, shrunk to nb_sect=%dz6FAT references %d sectors / Maximum %d sectors in filez
FAT:)r-r�rXrLrMr�rYr%r'r�rrr$rr��IOError�	iterrangerWrTrUr$rVrRrrrJ)	r�r^r�Znb_difat_sectorsZnb_difatZisect_difatr!Zsector_difatZdifatr)r)r*r>�sJ	












zOleFileIO.loadfatcCs�|j|j}|jj|jd|j}|d}t�d|j|j|||f�||kr\|�t	d�|j
|j|dd���}|�|�|_
t�dt|j
�|f�|j
d|�|_
t�d	t|j
��t�tj�r�t�d
�|�|j
�dS)z)
        Load the MiniFAT table.
        r#rzaloadminifat(): 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 sectorsNzloadminifat(): len=%dz	
MiniFAT:)r(r-r+r�rr-r�r!r�r�_openrUrTr�rXrUr$rVrJ)r�Zstream_sizeZnb_minisectorsZ	used_sizerXr)r)r*r�.s �
zOleFileIO.loadminifatc
Cs�z|j�|j|d�Wn8t�d||j|d|jf�|�td�YnX|j�|j�}t	|�|jkr�t�d|t	|�|jf�|�td�|S)z�
        Read given sector from file on disk.

        :param sect: int, sector index
        :returns: a string containing the sector data.
        r#z(getsect(): sect=%X, seek=%d, filesize=%dr�z*getsect(): sect=%X, read=%d, sectorsize=%dr�)
r_rYr�r-r�rr�rrUrX)r�r�rQr)r)r*rWRs��zOleFileIO.getsectroc
Cs�t|t�std��t|t�r(t|�dkr0td��z|j�|j|d�Wn8t�d||j|d|j	f�|�
td�YnXt|�|jkr�|||jt|�7}nt|�|jkr�td��|j�
|�dS)z�
        Write given sector to file on disk.

        :param sect: int, sector index
        :param data: bytes, sector data
        :param padding: single byte, padding character if data < sector size
        z'write_sect: data must be a bytes stringr#z4write_sect: padding must be a bytes string of 1 charz+write_sect(): sect=%X, seek=%d, filesize=%dr��Data is larger than sector sizeN)rZr[�	TypeErrorrXr_rYr�r-r�rr�r�
ValueError�write)r�r�r��paddingr)r)r*�
write_sectrs 
�zOleFileIO.write_sectcCs�t|t�std��t|t�r(t|�dkr0td��z|j�|�Wn,t�d||jf�|�	t
d�YnXt|�}||jkr�|||j|7}|j|kr�td��|j�
|�dS)z�
        Write given sector to file on disk.

        :param fp_pos: int, file position
        :param data: bytes, sector data
        :param padding: single byte, padding character if data < sector size
        z,write_mini_sect: data must be a bytes stringr#z9write_mini_sect: padding must be a bytes string of 1 charz)write_mini_sect(): fp_pos=%d, filesize=%dr�raN)rZr[rbrXr_rYr-r�rr�rrrcrd)r��fp_posr�reZlen_datar)r)r*�_write_mini_sect�s"
�

zOleFileIO._write_mini_sectcCslt�d�|j|dd�|_|jjd}t�d|jj|f�dg||_|�d�}|jd|_|j��dS)z]
        Load the directory.

        :param sect: sector index of directory stream.
        zLoading the Directory:Tr^r�z&loaddirectory: size=%d, max_entries=%dNr)	r-r�r`rr�r�r�r+r�)r�r�Zmax_entriesZ
root_entryr)r)r*r?�s

�
zOleFileIO.loaddirectorycCs~|dks|t|j�kr"|�td�|j|dk	rF|�td�|j|S|j�|d�|j�d�}t|||�|j|<|j|S)aY
        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 IOError: if the entry has always been referenced.
        rz OLE directory index out of rangeNz'double reference for OLE stream/storager�)	rXr�r�rrrrYrUr�)r�r�r�r)r)r*r��s�
zOleFileIO._load_direntrycCs|j��dS)z5
        Dump directory (for debugging only)
        N)r+r�r�r)r)r*�
dumpdirectory�szOleFileIO.dumpdirectoryc
Cs�t�d||t|�f�||jkr�|s�|jsh|��|jj}t�d|jj|f�|j	|jj|dd�|_t
|j||d|j|j|jj|d�St
|j
|||j|j|j|j|d�SdS)a|
        Open a stream, either in FAT or MiniFAT according to its size.
        (openstream helper)

        :param start: index of first sector
        :param size: size of stream (or nothing if size is unknown)
        :param force_FAT: if False (default), stream will be opened in FAT or MiniFAT
            according to size. If True, it will always be opened in FAT.
        z1OleFileIO.open(): sect=%Xh, size=%d, force_FAT=%sz%Opening MiniStream: sect=%Xh, size=%dTr^r)r_r�r�r�r�r�r�r�N)r-r��strr�rr�r+r�r�r`r�r"r�r_r�r�r)r��startr�r_Zsize_ministreamr)r)r*r`�s8
�
�
�
�
�zOleFileIO._openTcCs�||jg}|jD]v}|jtkrR|r>|�|dd�|jg�|�|||||�q|jtkr||r�|�|dd�|jg�q|�td�qdS)a�
        listdir helper

        :param files: list of files to fill in
        :param prefix: current location in storage tree (list of names)
        :param node: current node (OleDirectoryEntry object)
        :param streams: bool, include streams if True (True by default) - new in v0.26
        :param storages: bool, include storages if True (False by default) - new in v0.26
            (note: the root storage is never included)
        r#NzIThe directory tree contains an entry which is not a stream nor a storage.)	r'r�r�rr��_listr
r�r)r��files�prefix�node�streams�storagesr�r)r)r*rls


zOleFileIO._listcCsg}|�|g|j||�|S)am
        Return a list of streams and/or storages stored in this file

        :param streams: bool, include streams if True (True by default) - new in v0.26
        :param storages: bool, include storages if True (False by default) - new in v0.26
            (note: the root storage is never included)
        :returns: list of stream and/or storage paths
        )rlr+)r�rprqrmr)r)r*�listdir3s	zOleFileIO.listdircCsXt|t�r|�d�}|j}|D]2}|jD]}|j��|��kr(qLq(td��|}q|jS)a*
        Returns directory entry of given filename. (openstream helper)
        Note: this method is case-insensitive.

        :param filename: path of stream in storage tree (except root entry), either:

            - a string using Unix path syntax, for example:
              'storage_1/storage_1.2/stream'
            - or a list of storage filenames, path to the desired stream/storage.
              Example: ['storage_1', 'storage_1.2', 'stream']

        :returns: sid of requested filename
        :exception IOError: if file not found
        �/zfile not found)	rZ�
basestring�splitr+r�r'r�r\r�)r�r]ror'r	r)r)r*�_findAs


zOleFileIO._findcCs6|�|�}|j|}|jtkr&td��|�|j|j�S)a;
        Open a stream as a read-only file object (BytesIO).
        Note: filename is case-insensitive.

        :param filename: path of stream in storage tree (except root entry), either:

            - a string using Unix path syntax, for example:
              'storage_1/storage_1.2/stream'
            - or a list of storage filenames, path to the desired stream/storage.
              Example: ['storage_1', 'storage_1.2', 'stream']

        :returns: file object (read-only)
        :exception IOError: if filename not found, or if this is not a stream.
        zthis file is not a stream)rvr�r�r
r\r`r�r��r�r]r�r�r)r)r*�
openstreamas



zOleFileIO.openstreamcCs�|js|�|�t|j�}|jjs.|j�|�|j|j}t|j�D]�\}}||}||}|jj|d|j||j}	||dkr�|||j|d|j�}
n|||jd�}
|�|	|
�qDdS)Nr#)r�r�rXr+r-r�	enumeraterh)r�r��
data_to_writer�Z
block_size�idxr�Z	sect_baseZsect_offsetrgZdata_per_sectorr)r)r*�_write_mini_streamvs

 zOleFileIO._write_mini_streamc
	Cs�t|t�std��|�|�}|j|}|jtkr8td��|j}|t	|�krRt
d��||jkrt|jtkrt|j
||d�S|j}||jd|j}t�d|�t|�D]�}||dkr�|||j|d|j�}	t	|	�|jks�t�nR|||jd�}	t�d||jt	|	�||jf�t	|	�|j||jk�s6t�|�||	�z|j|}Wq�tk
�rntd	��Yq�Xq�|tk�r�td
��dS)aD
        Write a stream to disk. For now, it is only possible to replace an
        existing stream by data of the same size.

        :param stream_name: path of stream in storage tree (except root entry), either:

            - a string using Unix path syntax, for example:
              'storage_1/storage_1.2/stream'
            - or a list of storage filenames, path to the desired stream/storage.
              Example: ['storage_1', 'storage_1.2', 'stream']

        :param data: bytes, data to be written, must be the same size as the original
            stream.
        z)write_stream: data must be a bytes stringzthis is not a streamz?write_stream: data must be the same size as the existing stream)r�rzr#r�NzGwrite_stream: size=%d sectorsize=%d data_sector=%Xh size%%sectorsize=%dr�z)incorrect last sector index in OLE stream)rZr[rbrvr�r�r
r\r�rXrcr�rr|r�r�r-r�r�rqrfr�r�r)
r�Zstream_namer�r�r�r�r�r�r!Zdata_sectorr)r)r*�write_stream�s<



�
zOleFileIO.write_streamcCs0z|�|�}|j|}|jWSYdSXdS)a�
        Test if given filename exists as a stream or a storage in the OLE
        container, and return its type.

        :param filename: path of stream in storage tree. (see openstream for syntax)
        :returns: False if object does not exist, its entry type (>0) otherwise:

            - STGTY_STREAM: a stream
            - STGTY_STORAGE: a storage
            - STGTY_ROOT: the root entry
        FN)rvr�r�rwr)r)r*�get_type�s

zOleFileIO.get_typecCs|�|�}|j|}|jS)a
        Return clsid of a stream/storage.

        :param filename: path of stream/storage in storage tree. (see openstream for
            syntax)
        :returns: Empty string if clsid is null, a printable representation of the clsid otherwise

        new in version 0.44
        )rvr�rurwr)r)r*�getclsid�s


zOleFileIO.getclsidcCs|�|�}|j|}|��S)a9
        Return modification time of a stream/storage.

        :param filename: path of stream/storage in storage tree. (see openstream for
            syntax)
        :returns: None if modification time is null, a python datetime object
            otherwise (UTC timezone)

        new in version 0.26
        )rvr�r
rwr)r)r*r
�s

zOleFileIO.getmtimecCs|�|�}|j|}|��S)a1
        Return creation time of a stream/storage.

        :param filename: path of stream/storage in storage tree. (see openstream for
            syntax)
        :returns: None if creation time is null, a python datetime object
            otherwise (UTC timezone)

        new in version 0.26
        )rvr�rrwr)r)r*r�s

zOleFileIO.getctimecCs$z|�|�}WdSYdSXdS)a
        Test if given filename exists as a stream or a storage in the OLE
        container.
        Note: filename is case-insensitive.

        :param filename: path of stream in storage tree. (see openstream for syntax)
        :returns: True if object exist, else False.
        TFN)rv)r�r]r�r)r)r*r�	s
	
zOleFileIO.existscCs,|�|�}|j|}|jtkr&td��|jS)a2
        Return size of a stream in the OLE container, in bytes.

        :param filename: path of stream in storage tree (see openstream for syntax)
        :returns: size in bytes (long integer)
        :exception IOError: if file not found
        :exception TypeError: if this is not a stream.
        zobject is not an OLE stream)rvr�r�r
rbr�rwr)r)r*�get_sizes
	


zOleFileIO.get_sizecCs|jjS)zp
        Return root entry name. Should usually be 'Root Entry' or 'R' in most
        implementations.
        )r+r'r�r)r)r*�get_rootentry_name*szOleFileIO.get_rootentry_namecCsH|dkrg}|}t|t�s$d�|�}|�|�}i}zn|�d�}t|dd��}|�d�}t|dd��}	|�t|d��d|�t|�d	��d	�}t|d	�}
WnLtk
r�}z.d
t	|�|f}|�
t|t|��|WY�Sd}~XYnXt
|
tt|�d��}
t|
�D�]4}
d}�z�t|d|
d�}t|d|
d�}t||�}t�d
|||f�|tk�r�t||d	�}|dk�r�|d}�nb|tk�r�t||d	�}�nF|tttfk�r�t||d	�}�n$|ttfk�r�t||d	�}�n|ttfk�r0t||d	�}||d|d|d�}|�dd�}�n�|tk�rdt||d	�}||d|d|�}�n�|tk�r�t||d	�}|� ||d|d|d��}�nJ|t!k�rFt"t||d	��t"t||d��d>}|�r<||k�r<t�d||t#|�df�t$�$dddddd�}t�d|d�|t$j%|dd�}n|d}n�|t&k�rbt'||d	�}n�|t(k�r�t||d	|d��}nf|t)k�r�t||d	�}||d|d|�}n4|t*k�r�t+t||d	��}nd}t�d||f�|||<WnHtk
�r>}z(d|t	|�|f}|�
t|t|��W5d}~XYnX�q|S)a�
        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)
        NrsrFr3rBr>r:s****rz6Error while parsing properties header in stream %s: %srr7z!property id=%d: type=%d offset=%Xi�ir#ror�r/r�z8Converting property #%d to python datetime, value=%d=%fsi���rwztimedelta days=%dl@�T$r5rxz5property id=%d: type=%d not implemented in parser yetz3Error while parsing property id %d in stream %s: %s),rZrjr�rxrUrvrYrn�
BaseExceptionr�r�r�type�minrgrXr]r-r��VT_I2rm�VT_UI2�VT_I4�VT_INT�VT_ERROR�VT_UI4�VT_UINT�VT_BSTR�VT_LPSTRr6�VT_BLOB�	VT_LPWSTRr��VT_FILETIMEr��floatryrz�VT_UI1rd�VT_CLSID�VT_CF�VT_BOOL�bool)r�r]r�r�Z
streampathr_r�rXruZfmtidZ	num_props�exc�msgr!Zproperty_idr�Z
property_typer��countr{r)r)r*r�2s�





�





&
(�




�(zOleFileIO.getpropertiescCst�|_|j�|�|jS)z�
        Parse standard properties streams, return an OleMetadata object
        containing all the available metadata.
        (also stored in the metadata attribute of the OleFileIO object)

        new in version 0.25
        )rrr�r�r)r)r*�get_metadata�szOleFileIO.get_metadata)r6)F)F)r)r)ro)ro)TF)TF)FN),r�r�r�r�rrr�r/r2r\r�r�r\r0r�rJrRrTrYr>r�rWrfrhr?r�rirr`rlrrrvrxr|r}r~rr
rr�r�r�r�r�r)r)r)r*r�sV�
M

a

%
$T$ 

)&

 >
c	Cs�ddl}ddl}d}tjtjtjtjtjd�}d}|j|d�}|j	ddd	d
d�|j	ddd
dd�|j	dddd|dd�|�
�\}}tdtt
f�t|�dkr�tt�|��|��|jr�d|_tj||jdd�t�|D�]�}�z�t|�}	td�t|�td�|	��|	��D]�}
|
dddk�rtd|
�z�|	j|
dd�}t|���}|D]p\}}
t|
ttf��r�t|
�dk�r�|
dd�}
t|
t��r�d D]}|t|
�k�r�d!}
�q��q�td"||
��q^Wnt �!d#|
�YnX�q|j"�rptd$�|	��D]^}
td%t#d&�$|
��d%d'd(�|	�%|
�}|t&k�rZtd)|	�'|
��|	�(|
�ntd*|��q
t�td+�|	j)D],}|dk	�r~td,|j*|�+�|�,�f��q~t�z|	�-�}|�.�Wnt �!d-�YnXt�|	�/�}td.|�|	�0d/��r@td0�td1|	�%d/��td2|	�'d/��|	�0d3��r@td4�td5�|	j1�rv|	j1D]\}}td6|j2|f��qVntd7�Wq�t �!d8|�Yq�Xq�dS)9z�
    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
    rNr4)r��infor4r3Zcriticalz1usage: %prog [options] <filename> [filename2 ...])�usagez-c�
store_true�
check_streamsz*check all streams (for debugging purposes))�action�dest�helpz-d�
debug_modez\debug mode, shortcut for -l debug (displays a lot of debug information, for developers only)z-lz
--loglevel�loglevelZstorezBlogging level debug/info/warning/error/critical (default=%default))r�r��defaultr�z=olefile version %s %s - https://www.decalage.info/en/olefile
r�z%(levelname)-8s %(message)s)r(�formatzD--------------------------------------------------------------------����z%r: propertiesTr��2)r#r/r"rr0r1r2r6r7r9�r:r;r<r=r>r?r@rArBrCrDrErFrGrHrIz
(binary data)z   z&Error while parsing property stream %rz
Checking streams...�-rsrrzsize %dzNOT a stream : type=%dz5Modification/Creation times of all directory entries:z- %s: mtime=%s ctime=%szError while parsing metadatazRoot entry name: "%s"ZworddocumentzThis is a Word document.ztype of stream 'WordDocument':zsize :z
macros/vbaz%This document may contain VBA macros.z(
Non-fatal issues raised during parsing:r��NonezError while parsing file %r)3rN�optparser$rV�INFOZWARNINGZERROR�CRITICALZOptionParserZ
add_option�
parse_argsr��__version__�__date__rXr�Z
print_help�exitr�r�ZbasicConfigrrrirrr��sorted�itemsrZrtr[r=r-Z	exceptionr�r�r�r~r
r�rxr�r'r
rr�r�r�r�rr�)rNr�ZDEFAULT_LOG_LEVELZ
LOG_LEVELSr��parserZoptionsr1r]r�Z
streamnamer��k�vrcZst_typer��metar+�exctyper�r)r)r*�main�s��
�
��





�r��__main__)r)r)mr�Z
__future__rr�r��
__author__�__all__r�rNrirL�os.pathr:ryr$rjr[rgr�Zxranger]r��itemsizerMrcrt�	NameErrorr	�version_inforr�r+r-rrrrrrrrrrrr
rr
rrZVT_EMPTYZVT_NULLr�r�ZVT_R4ZVT_R8ZVT_CYZVT_DATEr�ZVT_DISPATCHr�r�Z
VT_VARIANTZ
VT_UNKNOWNZ
VT_DECIMALZVT_I1r�r�r�ZVT_I8ZVT_UI8r�r�ZVT_VOIDZ
VT_HRESULTZVT_PTRZVT_SAFEARRAYZ	VT_CARRAYZVT_USERDEFINEDr�r�r�r�Z	VT_STREAMZ
VT_STORAGEZVT_STREAMED_OBJECTZVT_STORED_OBJECTZVT_BLOB_OBJECTr�r�Z	VT_VECTORrrrrrrrrdrmrnrvr|rr�r�r�rr�r�r)r)r)r*�<module>s(<�
(

*





"