
 Xd             ,   @   s2  d  d l  m Z d Z d Z d Z d  d l Z d  d l Z d  d l Z d  d l Z d  d l	 Z
 d  d l Z e e k	 r e Z n  y
 e Z Wn e Z Yn Xe j d  j d k r d Z nN e j d  j d k r d Z n- e j d	  j d k r d	 Z n e d
   y e Wn e k
 r+e Z Yn Xd Z e j d  d k  rNd Z n d Z d a d d   Z d d   Z e a d d   Z d Z  d Z! d Z" d Z# d Z$ d Z% d Z& d Z' d  Z( d Z) d Z* d Z+ d Z, d Z- d  Z. d Z/ d Z0 d Z1 d Z2 d Z3 d Z4 d Z5 d  Z6 d! Z7 d" Z8 d# Z9 d$ Z: d% Z; d& Z< d' Z= d( Z> d) Z? d* Z@ d+ ZA d, ZB d- ZC d. ZD d/ ZE d0 ZF d1 ZG d2 ZH d3 ZI d4 ZJ d5 ZK d6 ZL d7 ZM d8 ZN d9 ZO d: ZP d; ZQ d< ZR d= ZS d> ZT d? ZU d@ ZV i  ZW xF eX eY   jZ    D]/ \ Z[ Z\ e[ d d  dA k re[ eW e\ <n  qWdB Z] d" Z^ d+ Z_ d5 Z` dC Za dD Zb dE dF   Zc e e k rhdG dH   Zd n dI dH   Zd d  dJ dK  Ze d  dL dM  Zf dN dO   Zg dP dQ   Zh GdR dS   dS ei  Zj GdT dU   dU e jk  Zl GdV dW   dW ei  Zm GdX dY   dY ei  Zn eo dZ k r.ep e jq  d k rTer d[ e e e f  er d\  e js   n  d Zt xe jq d d  D]Zu eu d] k re d  qnn  eu d^ k rd Zt qnn  en eu  Zv er d_ d;  er eu  er d_ d;  ev jw   xTev jx   D]FZy ey d d  d` k r7er ey da  ev jz ey db d Z{ e| e{ jZ    Z{ x e{ D] \ Z} Z~ e e~ e e f  rep e~  dc k re~ d dc  Z~ n  n  e e~ e  r x{ d d d d d d d d# d$ d& dd d' d( d) d* d+ d, d- d. d/ d0 d1 d2 d3 d4 d5 d6 f D]" Z e e e~  k rde Z~ Pn  qWn  er df e} e~  qGWn  qWet rer dg  x ev jx   D]{ Zy er d_ e dh j ey   d_ di dj ev j ey  Z e e* k rer dk ev j ey   ev j ey  n er dl e  qXWer   n  er dm  xF ev j D]; Z e d k	 r0er dn e j e j   e j   f  n  qWer   ev j   Z e j   er   ev j   Z er do e  ev j dp  rer dq  er dr ev j dp   er ds ev j dp   ev j dt  rer du  n  n  er dv  ev j rx. ev j D]# \ Z Z er dw e jo e f  qWn
 er dx  qnWn  d S)y    )print_functionzPhilippe Lagadecz
2015-01-25z0.42bNL   Iiz>Need to fix a bug with 32 bit arrays, please contact author...T   zutf-8Fc             C   s   t  |   d  S)N)print)msg r
   J/home/ubuntu/projects/ifolica/lib/python3.4/site-packages/PIL/OleFileIO.pydebug_printN  s    r   c             C   s   d  S)Nr
   )r	   r
   r
   r   
debug_passR  s    r   c             C   s   |  a  |  r t a n t a d S)zl
    Set debug mode on or off, to control display of debugging messages.
    :param mode: True or False
    N)
DEBUG_MODEr   debugr   )Z
debug_moder
   r
   r   set_debug_modeY  s    	r   s   ࡱl    l    l    l    l                      	   
                                                               @   A   B   C   D   E   F   G   H   i   ZVT_z$00020900-0000-0000-C000-000000000046(   i   c             C   s   t  |  d  r4 |  j t t   } |  j d  nX t |  t  rn t |   t k rn |  d t t   } n t |  d  j t t   } | t k r d Sd Sd S)aH  
    Test if a file is an OLE container (according to the magic bytes in its header).

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

    :returns: True if OLE, False otherwise.
    readr   NrbTF)	hasattrr7   lenMAGICseek
isinstancebytesMINIMAL_OLEFILE_SIZEopen)filenameheaderr
   r
   r   	isOleFile  s    !rC   c             C   s
   t  |   S)N)ord)cr
   r
   r   i8  s    rF   c             C   s   |  j  t k r |  S|  d S)Nr   )	__class__int)rE   r
   r
   r   rF     s    c             C   s"   t  j d |  | | d   d S)z
    Converts a 2-bytes (16 bits) string to an integer.

    c: string containing bytes to convert
    o: offset of bytes to convert in string
    z<Hr   r   )structunpack)rE   or
   r
   r   i16  s    rL   c             C   s"   t  j d |  | | d   d S)z
    Converts a 4-bytes (32 bits) string to an integer.

    c: string containing bytes to convert
    o: offset of bytes to convert in string
    z<Ir   r   )rI   rJ   )rE   rK   r
   r
   r   i32  s    rM   c             C   s|   t  |   d k s t  |  j d  s+ d Sd d d t |  d  t |  d  t |  d  f t t t |  d	 d    S)
z^
    Converts a CLSID to a human-readable string.

    :param clsid: string of length 16.
    r   s     z%08X-%04X-%04X-%02X%02X-z%02Xr   r   r   r   )r:   AssertionErrorstriprM   rL   tuplemaprF   )clsidr
   r
   r   _clsid  s    'rT   c             C   s6   t  j  d d d d d d  } | t  j d |  d  S)zD
    convert FILETIME (64 bits int) to Python datetime.datetime
    iA  r   r   microsecondsr   )datetime	timedelta)Zfiletime_FILETIME_null_dater
   r
   r   filetime2datetime   s    rY   c               @   s   e  Z d  Z d Z d d d d d d d d	 d
 d d d d d d d d d d g Z 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/ d0 g Z d1 d2   Z d3 d4   Z d5 d6   Z d7 S)8OleMetadataaP  
    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/
    - http://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
    - http://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_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_versionc             C   s  d |  _  d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _	 d |  _
 d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _ d |  _  d |  _! d |  _" d |  _# d |  _$ d |  _% d |  _& d |  _' d |  _( d |  _) d |  _* d |  _+ d |  _, d |  _- d |  _. d S)z_
        Constructor for OleMetadata
        All attributes are set to None by default
        N)/r[   r\   r]   r^   r_   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   rn   ro   rp   r>   rq   rr   rs   rt   ru   rv   rw   rx   ry   rz   r{   r|   r}   r~   r   r   r   r   r   r   r   r   r   r   )selfr
   r
   r   __init__?  s^    																																														zOleMetadata.__init__c             C   s   x( |  j  |  j D] } t |  | d  q W| j d  r | j d d d d d g } xM t t |  j    D]3 } | j | d d  } t |  |  j  | |  qn Wn  | j d  r| j d d d } xM t t |  j   D]3 } | j | d d  } t |  |  j | |  q Wn  d S)	a3  
        Parse standard properties of an OLE file, from the streams
        "SummaryInformation" and "DocumentSummaryInformation",
        if present.
        Properties are converted to strings, integers or python datetime objects.
        If a property is not present, its value is set to None.
        NzSummaryInformationconvert_timeTno_conversionr   r   zDocumentSummaryInformation)SUMMARY_ATTRIBSDOCSUM_ATTRIBSsetattrexistsgetpropertiesranger:   get)r   olefileZattribpropsr   valuer
   r
   r   parse_propertiesv  s    		zOleMetadata.parse_propertiesc             C   s   t  d  x: |  j D]/ } t |  |  } t  d | t |  f  q Wt  d  x: |  j D]/ } t |  |  } t  d | t |  f  q[ Wd S)z<
        Dump all metadata, for debugging purposes.
        z*Properties from SummaryInformation stream:z- %s: %sz2Properties from DocumentSummaryInformation stream:N)r   r   getattrreprr   )r   propr   r
   r
   r   dump  s    

zOleMetadata.dumpN)	__name__
__module____qualname____doc__r   r   r   r   r   r
   r
   r
   r   rZ     s   	7 rZ   c               @   s"   e  Z d  Z d Z d d   Z d S)
_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             C   s]  t  d  t  d | | | | | t |  t |  f  d } | d k rn t |  | } d } t  d  n  | | d | }	 t  d |	  |	 t |  k r t d	   n  g  }
 | d
 k r | t k r t  d  t d   n  xt |	  D]} | t k r(| rPq(t  d  t d   n  | d
 k  sF| t |  k rt  d | | t |  f  t  d | |	 f  t d   n  y | j | | |  Wn3 t  d | | | | | f  t d   Yn X| j |  } t |  | k rl| t |  d k rlt  d | t |  | | | | t |  f  t  d | | | t |   t d   n  |
 j |  y | | d @} Wq t	 k
 rt d   Yq Xq W| t k rt d   n  d j
 |
  }
 t |
  | k r|
 d |  }
 | |  _ n> | r t |
  |  _ n& t  d t |
  | f  t d   t j j |  |
  d S)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)
        :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=%sFiTz  stream with UNKNOWN SIZEr   znb_sectors = %dz(malformed OLE document, stream too larger   z!size == 0 and sect != ENDOFCHAIN:z+incorrect OLE sector index for empty streamz$sect=ENDOFCHAIN before expected sizezincomplete OLE streamzsect=%d (%X) / len(fat)=%dzi=%d / nb_sectors=%dz,incorrect OLE FAT, sector index out of rangezsect=%d, seek=%d, filesize=%dzOLE sector index out of rangez9sect=%d / len(fat)=%d, seek=%d / filesize=%d, len read=%dzseek+len(read)=%dzincomplete OLE sectorl    z)incorrect last sector index in OLE stream    Nzlen(data)=%d, size=%dz%OLE stream size is less than declared)r   r:   r   IOError
ENDOFCHAINr   r<   r7   append
IndexErrorjoinsizeioBytesIOr   )r   fpsectr   offset
sectorsizefatfilesizeZunknown_size
nb_sectorsdatar   Zsector_datar
   r
   r   r     sl    
)

(+ z_OleStream.__init__N)r   r   r   r   r   r
   r
   r
   r   r     s   r   c               @   s   e  Z d  Z d Z d Z d Z e j e  e k s9 t  d d   Z	 d d   Z
 d d	   Z d
 d   Z d d   Z d d   Z d d   Z d d d  Z d d   Z d d   Z d S)_OleDirectoryEntryz
    OLE2 Directory Entry
    z<64sHBBIII16sIQQIII   c       
      C   s   | |  _  | |  _ g  |  _ i  |  _ d |  _ t j t j |  \ } } |  _	 |  _
 |  _ |  _ |  _ } |  _ |  _ |  _ |  _ } } |  j	 t t t t g k r | j t d  n  |  j	 t k r | d k r | j t d  n  | d k r|  j	 t k r| j t d  n  | d k r6| j t d  d } n  | d | d	  } | j |  |  _ t d
 |  j  t |  j  f  t d |  j	  t d |  j  t d |  j |  j |  j f  | j d k r!| d k r| d k rt d | j | | | f  | j t d  n  | |  _ n | t |  d >|  _ t d |  j | | f  t  |  |  _! |  j	 t k r|  j d k r| j t" d  n  |  j	 t t f k r|  j d k r|  j | j# k  r|  j	 t k rd }	 n d }	 | j$ |  j |	  n  d S)aJ  
        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
        Fzunhandled OLE storage typer   zduplicate OLE root entryzincorrect OLE root entryr-   zincorrect DirEntry name lengthNr   zDirEntry SID=%d: %sz - type: %dz - sect: %dz% - SID left: %d, right: %d, child: %di   l    z+sectorsize=%d, sizeLow=%d, sizeHigh=%d (%X)zincorrect OLE stream size    z% - size: %d (sizeLow=%d, sizeHigh=%d)zOLE storage with size>0T)%sidr   kids	kids_dictusedrI   rJ   r   STRUCT_DIRENTRY
entry_typeZcolorsid_left	sid_right	sid_childZdwUserFlags
createTime
modifyTime
isectStart
STGTY_ROOTSTGTY_STORAGESTGTY_STREAMSTGTY_EMPTYraise_defectDEFECT_INCORRECT_decode_utf16_strnamer   r   r   DEFECT_UNSUREr   longrT   rS   DEFECT_POTENTIALminisectorcutoff_check_duplicate_stream)
r   entryr   r   r   Z
namelengthrS   ZsizeLowZsizeHighminifatr
   r
   r   r   H  sN    						Z	 $	z_OleDirectoryEntry.__init__c             C   sY   t  d |  j t |  j  |  j f  |  j t k rU |  j |  j  |  j j   n  d S)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   NOSTREAMappend_kidsr   sort)r   r
   r
   r   build_storage_tree  s
     	z%_OleDirectoryEntry.build_storage_treec             C   s5  | t  k r d S| d k  s4 | t |  j j  k rJ |  j j t d  n  |  j j |  } t d | j t	 | j
  | j | j | j f  |  j | j  | j
 j   } | |  j k r |  j j t d  n  |  j j |  | |  j | <| j r|  j j t d  n  d | _ |  j | j  | j   d S)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)
        Nr   zOLE DirEntry index out of rangezHappend_kids: child_sid=%d - %s - sid_left=%d, sid_right=%d, sid_child=%dz!Duplicate filename in OLE storagez#OLE Entry referenced more than onceT)r   r:   r   
direntriesr   DEFECT_FATAL_load_direntryr   r   r   r   r   r   r   r   lowerr   r   r   r   r   r   )r   Z	child_sidchildZ
name_lowerr
   r
   r   r     s(    $,
	
	z_OleDirectoryEntry.append_kidsc             C   s   |  j  | j  k S)zCompare entries by name)r   )r   otherr
   r
   r   __eq__  s    z_OleDirectoryEntry.__eq__c             C   s   |  j  | j  k  S)zCompare entries by name)r   )r   r   r
   r
   r   __lt__  s    z_OleDirectoryEntry.__lt__c             C   s   |  j  |  S)N)r   )r   r   r
   r
   r   __ne__  s    z_OleDirectoryEntry.__ne__c             C   s   |  j  |  p |  j |  S)N)r   r   )r   r   r
   r
   r   __le__  s    z_OleDirectoryEntry.__le__r   c             C   s   d d d d d d g } t  d | t |  j  | |  j d d |  j t t f k rq t  |  j d	 d d n  t    |  j t t f k r |  j r t  d | d
 |  j  n  x" |  j	 D] } | j
 | d  q Wd S)zADump this entry, and all its subentries (for debug purposes only)z	(invalid)z	(storage)z(stream)z(lockbytes)z
(property)z(root) endr>   z{%s}r   N)r   r   r   r   r   r   r   r   rS   r   r   )r   tabZTYPESkidr
   r
   r   r     s    +z_OleDirectoryEntry.dumpc             C   s    |  j  d k r d St |  j   S)z
        Return modification time of a directory entry.

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

        new in version 0.26
        r   N)r   rY   )r   r
   r
   r   getmtime
  s    	z_OleDirectoryEntry.getmtimec             C   s    |  j  d k r d St |  j   S)z
        Return creation time of a directory entry.

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

        new in version 0.26
        r   N)r   rY   )r   r
   r
   r   getctime  s    	z_OleDirectoryEntry.getctimeN)r   r   r   r   r   ZDIRENTRY_SIZErI   calcsizerO   r   r   r   r   r   r   r   r   r   r   r
   r
   r
   r   r   *  s   _+r   c               @   s  e  Z d  Z d Z d e d d e d d  Z e d d  Z d d	 d
  Z	 d d d  Z
 d d   Z d d d  Z d d d  Z d d d  Z d d   Z d d   Z d d   Z d d   Z d d   Z d  d! d"  Z d# d$   Z d% d&   Z d' d(   Z d) d d* d+  Z d, d d- d.  Z d, d d/ d0  Z d1 d2   Z d3 d4   Z d5 d6   Z d7 d8   Z d9 d:   Z d; d<   Z  d= d>   Z! d? d@   Z" dA dB   Z# d d dC dD  Z$ dE dF   Z% d S)G	OleFileIOa  
    OLE container object

    This class encapsulates the interface to an OLE 2 structured
    storage file.  Use the :py:meth:`~PIL.OleFileIO.OleFileIO.listdir` and
    :py:meth:`~PIL.OleFileIO.OleFileIO.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).
    NFc             C   s`   t  |  | |  _ g  |  _ | |  _ | |  _ d |  _ d |  _ | r\ |  j | d | n  d S)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

        :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)r   _raise_defects_levelparsing_issuesr   path_encoding	_filesizer   r@   )r   rA   Zraise_defectsr   r   r   r
   r
   r   r   E  s    
						zOleFileIO.__init__c             C   s8   | |  j  k r | |   n |  j j | | f  d S)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)r   r   r   )r   Zdefect_levelmessageZexception_typer
   r
   r   r   n  s    zOleFileIO.raise_defectreplacec             C   s6   | j  d |  } |  j r. | j |  j |  S| Sd S)a  
        Decode a string encoded in UTF-16 LE format, as found in the OLE
        directory or in property streams. Return a string encoded
        according to the path_encoding specified for the OleFileIO object.

        :param 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
        zUTF-16LEN)decoder   encode)r   Z	utf16_strerrorsZunicode_strr
   r
   r   r     s    
	zOleFileIO._decode_utf16_strc       	      C   s  | |  _  t | d  r$ | |  _ n` t | t  rZ t |  t k rZ t j |  |  _ n* |  j  rl d } n d } t	 | |  |  _ d } |  j j
 d t j  z |  j j   } Wd |  j j
 d  X| |  _ g  |  _ g  |  _ |  j j d  } t |  d k s| d d  t k r/|  j t d  n  d	 } t j |  } t d
 | | d/ f  | d |  } t j | |  \ |  _ |  _ |  _ |  _ |  _ |  _ |  _ |  _  |  _! |  _" |  _# |  _$ |  _% |  _& |  _' |  _( |  _) |  _* t t j | |   |  j t k r"|  j t d  n  |  j t+ d  k rJ|  j t, d  n  t d |  j  t d |  j  |  j d0 k r|  j t, d  n  t d |  j  |  j d k r|  j t d  n  d |  j |  _- t d |  j-  |  j- d1 k r|  j t, d  n  |  j d k r"|  j- d k s@|  j d k rS|  j- d k rS|  j t, d  n  d |  j |  _. t d |  j.  |  j. d2 k r|  j t, d  n  |  j  d k s|  j! d k r|  j t, d  n  t d  |  j"  |  j- d k r	|  j" d k r	|  j t, d!  n  t d" |  j#  t d# |  j$  t d$ |  j%  |  j% d k r^|  j t/ d%  n  t d& |  j&  |  j& d k r|  j t, d'  n  t d( |  j'  t d) |  j(  t d* |  j)  t d+ |  j*  | |  j- d, |  j- d, |  _0 t d- |  j0  t1 | d d.   |  _ |  j- |  _2 |  j. |  _3 |  j& |  _4 |  j5 |  j$  |  j( rn|  j5 |  j'  n  |  j* r|  j5 |  j)  n  |  j6 |  |  j7 |  j$  d |  _8 |  j' |  _9 d S)3a  
        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)
        r7   zr+br8   r   N   r   z#not an OLE2 structured storage filez<8s16sHHHHHHLLLLLLLLLLzfmt_header size = %d, +FAT = %dm   r   zincorrect OLE signaturer   zincorrect CLSID in OLE headerzMinorVersion = %dzDllVersion   = %dr   z"incorrect DllVersion in OLE headerzByteOrder    = %Xi  z!incorrect ByteOrder in OLE headerr   zSectorSize   = %d   z"incorrect SectorSize in OLE headerz2SectorSize does not match DllVersion in OLE headerzMiniSectorSize   = %dr-   z&incorrect MiniSectorSize in OLE headerz.incorrect OLE header (non-null reserved bytes)zcsectDir     = %dz incorrect csectDir in OLE headerzcsectFat     = %dzsectDirStart = %Xzsignature    = %dz"incorrect OLE header (signature>0)zMiniSectorCutoff = %dz(incorrect MiniSectorCutoff in OLE headerzMiniFatStart     = %XzcsectMiniFat     = %dzsectDifStart     = %XzcsectDif         = %dr   z!Number of sectors in the file: %dr%   i  )r   r   )r   r   )r-   ):r   r9   r   r=   r>   r:   r?   r   r   r@   r<   osSEEK_ENDtellr   _used_streams_fat_used_streams_minifatr7   r;   r   r   rI   r   r   rJ   ZSigrS   ZMinorVersionZ
DllVersionZ	ByteOrderZSectorShiftZMiniSectorShiftZReservedZ	Reserved1ZcsectDircsectFatZsectDirStartZ	signatureZMiniSectorCutoffZMiniFatStartcsectMiniFatsectDifStartcsectDif	bytearrayr   
SectorSizeMiniSectorSizer   nb_sectrT   r   minisectorsizer   r   loadfatloaddirectory
ministreamminifatsect)	r   rA   r   moder   rB   Z
fmt_headerZheader_sizeZheader1r
   r
   r   r@     s    	!					('~			zOleFileIO.openc             C   s   |  j  j   d S)z@
        close the OLE file, to release the file object
        N)r   close)r   r
   r
   r   r  n  s    zOleFileIO.closec             C   s   | r  t  d |  |  j } n3 t  d |  | t t t t f k rJ d S|  j } | | k rr |  j t d  n | j	 |  d S)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=%d in MiniFATz'_check_duplicate_stream: sect=%d in FATNzStream referenced twice)
r   r   DIFSECTFATSECTr   FREESECTr   r   r   r   )r   Z
first_sectr   Zused_streamsr
   r
   r   r   t  s    		z!OleFileIO._check_duplicate_streamr   c             C   sd  t  s
 d Sd } i d t 6d t 6d t 6d t 6} t |  } | | d | } t d d	 d
 x( t |  D] } t d | d	 d
 qm Wt   x t |  D] } | | }	 t d | |	 d	 d
 x t |	 |	 |  D]v } | | k r Pn  | | }
 |
 d @} | | k r| | } n# |
 | d k r7d } n
 d |
 } t | d	 d
 q Wt   q Wd S)zCDisplays a part of FAT in human-readable form for debugging purposeNr   z..free..z[ END. ]zFATSECT zDIFSECT r   indexr   r   z%8Xz%8X:l    z    --->)r   r	  r   r  r  r:   r   r   )r   r   
firstindexVPLZfatnamesnbsectnlinesr   lr
  r   Zauxr   r
   r
   r   dumpfat  s:    



	
zOleFileIO.dumpfatc             C   s4  t  s
 d Sd } t j t |  } t j d k r> | j   n  t |  } | | d | } t d d d x( t |  D] } t d | d d qy Wt   x t |  D] } | | }	 t d	 | |	 d d xO t |	 |	 |  D]: } | | k r Pn  | | }
 d |
 } t | d d q Wt   q Wd S)
zBDisplays a sector in a human-readable form, for debugging purpose.Nr   bigr   r
  r   r   z%8Xz%8X:)	r   arrayUINT32sys	byteorderbyteswapr:   r   r   )r   sectorr  r  r   r  r  r   r  r
  r   r   r
   r
   r   dumpsect  s,    


zOleFileIO.dumpsectc             C   s2   t  j  t |  } t j d k r. | j   n  | S)z
        convert a sector to an array of 32 bits unsigned integers,
        swapping bytes on big endian CPUs such as PowerPC (old Macs)
        r  )r  r  r  r  r  )r   r   ar
   r
   r   
sect2array  s    zOleFileIO.sect2arrayc             C   s   t  | t j  r | } n |  j |  } |  j |  xz | D]r } | d @} t d |  | t k st | t k r t d  Pn  |  j |  } |  j |  } |  j | |  _ q> W| 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.
        l    z
isect = %Xzfound end of sector chain)	r=   r  r  r  r   r   r	  getsectr   )r   r   Zfat1ZisectsZnextfatr
   r
   r   loadfat_sect  s    	

zOleFileIO.loadfat_sectc       	      C   s-  | d d  } t  d t |  t |  d f  t j t  |  _ |  j |  |  j d k r|  j d k r |  j t	 d  n  |  j
 |  j k r |  j t d  n  t  d	  |  j d d
 } |  j d | d
 | } t  d |  |  j | k r	t d   n  |  j
 } x t |  D]t } t  d | | f  |  j |  } |  j |  } |  j |  |  j | d |   | | } t  d |  qW| t t g k rt d   qn  t |  j  |  j k rt  d t |  j  |  j f  |  j d |  j  |  _ n  t  d  |  j |  j  d S)z%
        Load the FAT table.
        L   i   zlen(sect)=%d, so %d integersr   r   r   z#incorrect DIFAT, not enough sectorsz)incorrect DIFAT, first index out of rangezDIFAT analysis...r   znb_difat = %dzincorrect DIFATzDIFAT block %d, sector %XNznext DIFAT sector: %Xzincorrect end of DIFATz!len(fat)=%d, shrunk to nb_sect=%dz
FAT:)r   r:   r  r  r   r  r   r   r   r   r   r   r   r   r   	iterranger  r  r  r   r	  r  )	r   rB   r   Znb_difat_sectorsZnb_difatZisect_difatr   Zsector_difatZdifatr
   r
   r   r    s>    	$

	
 
zOleFileIO.loadfatc             C   s  |  j  |  j } |  j j |  j d |  j } | d } t d |  j |  j  | | | f  | | k rz |  j t d  n  |  j	 |  j | d d j
   } |  j |  |  _ t d t |  j  | f  |  j d |  |  _ t d	 t |  j   t d
  |  j |  j  d S)z)
        Load the MiniFAT table.
        r   r   zaloadminifat(): minifatsect=%d, nb FAT sectors=%d, used_size=%d, stream_size=%d, nb MiniSectors=%dz%OLE MiniStream is larger than MiniFAT	force_FATTz$MiniFAT shrunk from %d to %d sectorsNzloadminifat(): len=%dz	
MiniFAT:)r   r   rootr   r   r   r  r   r   _openr7   r  r   r:   r  )r   Zstream_sizeZnb_minisectorsZ	used_sizer  r
   r
   r   loadminifat?  s    
!
zOleFileIO.loadminifatc             C   s   y |  j  j |  j | d  Wn= t d | |  j | d |  j f  |  j t d  Yn X|  j  j |  j  } t |  |  j k r t d | t |  |  j f  |  j t d  n  | 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=%dzOLE sector index out of rangez*getsect(): sect=%X, read=%d, sectorsize=%dzincomplete OLE sector)	r   r<   r   r   r   r   r   r7   r:   )r   r   r  r
   r
   r   r  a  s    zOleFileIO.getsects    c             C   s  t  | t  s t d   n  t  | t  s@ t |  d k rO t d   n  y |  j j |  j | d  Wn= t d | |  j | d |  j f  |  j	 t
 d  Yn Xt |  |  j k  r | | |  j t |  7} n$ t |  |  j k  rt d   n  |  j j |  d S)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=%dzOLE sector index out of rangezData is larger than sector sizeN)r=   r>   	TypeErrorr:   r   r<   r   r   r   r   r   
ValueErrorwrite)r   r   r   paddingr
   r
   r   
write_sect  s    "zOleFileIO.write_sectc             C   s|   |  j  |  |  _ |  j j d } t d |  j j | f  d g | |  _ |  j d  } |  j d |  _ |  j j   d S)z]
        Load the directory.

        :param sect: sector index of directory stream.
        r   z&loaddirectory: size=%d, max_entries=%dNr   )r"  directory_fpr   r   r   r   r!  r   )r   r   Zmax_entriesZ
root_entryr
   r
   r   r    s    zOleFileIO.loaddirectoryc             C   s   | d k  s! | t  |  j  k r4 |  j t d  n  |  j | d k	 rb |  j t d  |  j | S|  j j | d  |  j j d  } t | | |   |  j | <|  j | S)aZ  
        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.
        r   z OLE directory index out of rangeNz'double reference for OLE stream/storager   )	r:   r   r   r   r   r)  r<   r7   r   )r   r   r   r
   r
   r   r     s    !	zOleFileIO._load_direntryc             C   s   |  j  j   d S)z5
        Dump directory (for debugging only)
        N)r!  r   )r   r
   r
   r   dumpdirectory  s    zOleFileIO.dumpdirectoryic             C   s  t  d | | t |  f  | |  j k  r | r |  j s |  j   |  j j } t  d |  j j | f  |  j |  j j | d d |  _ n  t	 d |  j d | d | d d	 d
 |  j
 d |  j d |  j j  St	 d |  j d | d | d |  j d
 |  j d |  j d |  j  Sd S)a|  
        Open a stream, either in FAT or MiniFAT according to its size.
        (openstream helper)

        :param start: index of first sector
        :param size: size of stream (or nothing if size is unknown)
        :param force_FAT: if False (default), stream will be opened in FAT or MiniFAT
            according to size. If True, it will always be opened in FAT.
        z0OleFileIO.open(): sect=%d, size=%d, force_FAT=%sz$Opening MiniStream: sect=%d, size=%dr   Tr   r   r   r   r   r   r   r   N)r   strr   r  r#  r!  r   r   r"  r   r   r   r   r   r   r   )r   startr   r   Zsize_ministreamr
   r
   r   r"    s"    
	
	zOleFileIO._openTc             C   s   | | j  g } x | j D] } | j t k ru | rY | j | d d  | j  g  n  |  j | | | | |  q | j t k r | r | j | d d  | j  g  q q |  j t d  q Wd S)a  
        listdir helper

        :param files: list of files to fill in
        :param prefix: current location in storage tree (list of names)
        :param node: current node (_OleDirectoryEntry object)
        :param streams: bool, include streams if True (True by default) - new in v0.26
        :param storages: bool, include storages if True (False by default) - new in v0.26
            (note: the root storage is never included)
        r   NzIThe directory tree contains an entry which is not a stream nor a storage.)	r   r   r   r   r   _listr   r   r   )r   filesprefixnodestreamsstoragesr   r
   r
   r   r-    s    $'zOleFileIO._listc             C   s&   g  } |  j  | g  |  j | |  | S)am  
        Return a list of streams and/or storages stored in this file

        :param streams: bool, include streams if True (True by default) - new in v0.26
        :param storages: bool, include storages if True (False by default) - new in v0.26
            (note: the root storage is never included)
        :returns: list of stream and/or storage paths
        )r-  r!  )r   r1  r2  r.  r
   r
   r   listdir  s    	zOleFileIO.listdirc             C   s   t  | t  r! | j d  } n  |  j } xS | D]K } x< | j D]% } | j j   | j   k rA PqA qA Wt d   | } q1 W| j S)a*  
        Returns directory entry of given filename. (openstream helper)
        Note: this method is case-insensitive.

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

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

        :returns: sid of requested filename
        :exception IOError: if file not found
        /zfile not found)	r=   
basestringsplitr!  r   r   r   r   r   )r   rA   r0  r   r   r
   r
   r   _find(  s    	
zOleFileIO._findc             C   sP   |  j  |  } |  j | } | j t k r: t d   n  |  j | j | j  S)a;  
        Open a stream as a read-only file object (BytesIO).
        Note: filename is case-insensitive.

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

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

        :returns: file object (read-only)
        :exception IOError: if filename not found, or if this is not a stream.
        zthis file is not a stream)r7  r   r   r   r   r"  r   r   )r   rA   r   r   r
   r
   r   
openstreamG  s
    zOleFileIO.openstreamc       
      C   s  t  | t  s t d   n  |  j |  } |  j | } | j t k rX t d   n  | j } | t	 |  k r t
 d   n  | |  j k  r t d   n  | j } | |  j d |  j } t d |  xt |  D] } | | d k  r2| | |  j | d |  j  }	 t	 |	  |  j k st  ng | | |  j d  }	 t d | |  j t	 |	  | |  j f  t	 |	  |  j | |  j k st  |  j | |	  y |  j | } Wq t k
 rt d	   Yq Xq W| t k rt d
   n  d S)aD  
        Write a stream to disk. For now, it is only possible to replace an
        existing stream by data of the same size.

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

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

        :param data: bytes, data to be written, must be the same size as the original
            stream.
        z)write_stream: data must be a bytes stringzthis is not a streamz?write_stream: data must be the same size as the existing streamz2Writing a stream in MiniFAT is not implemented yetr   znb_sectors = %dNzFwrite_stream: size=%d sectorsize=%d data_sector=%d size%%sectorsize=%dz,incorrect OLE FAT, sector index out of rangez)incorrect last sector index in OLE stream)r=   r>   r$  r7  r   r   r   r   r   r:   r%  r   NotImplementedErrorr   r   r   r   rO   r(  r   r   r   )
r   Zstream_namer   r   r   r   r   r   r   Zdata_sectorr
   r
   r   write_stream\  s:    		"$&zOleFileIO.write_streamc          	   C   s:   y' |  j  |  } |  j | } | j SWn d SYn Xd S)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)r7  r   r   )r   rA   r   r   r
   r
   r   get_type  s    zOleFileIO.get_typec             C   s&   |  j  |  } |  j | } | j   S)a9  
        Return modification time of a stream/storage.

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

        new in version 0.26
        )r7  r   r   )r   rA   r   r   r
   r
   r   r     s    zOleFileIO.getmtimec             C   s&   |  j  |  } |  j | } | j   S)a1  
        Return creation time of a stream/storage.

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

        new in version 0.26
        )r7  r   r   )r   rA   r   r   r
   r
   r   r     s    zOleFileIO.getctimec          	   C   s*   y |  j  |  } d SWn d SYn Xd S)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)r7  )r   rA   r   r
   r
   r   r     s
    	zOleFileIO.existsc             C   sA   |  j  |  } |  j | } | j t k r: t d   n  | j S)a2  
        Return size of a stream in the OLE container, in bytes.

        :param filename: path of stream in storage tree (see openstream for syntax)
        :returns: size in bytes (long integer)
        :exception IOError: if file not found
        :exception TypeError: if this is not a stream.
        zobject is not an OLE stream)r7  r   r   r   r$  r   )r   rA   r   r   r
   r
   r   get_size  s
    	zOleFileIO.get_sizec             C   s
   |  j  j S)zp
        Return root entry name. Should usually be 'Root Entry' or 'R' in most
        implementations.
        )r!  r   )r   r
   r
   r   get_rootentry_name  s    zOleFileIO.get_rootentry_namec              C   sR  | d k r g  } n  | } t  | t  s< d j |  } n  |  j |  } i  } y | j d  } t | d d   } | j d  } t | d d   }	 | j t | d   d | j t | j d	   d	  } t | d	  }
 WnX t k
 rD} z8 d
 t	 |  | f } |  j
 t | | |   | SWYd d } ~ Xn Xxt |
  D]} yd } t | d | d  } t | d | d  } t | |  } t d | | | f  | t k rt | | d	  } | d k r| d } qn| t k rt | | d	  } n| t t t f k r=t | | d	  } n| t t f k ret | | d	  } n| t t f k rt | | d	  } | | d | d | d  } | j d d  } n&| t k rt | | d	  } | | d | d |  } n| t k rHt | | d	  } |  j | | d | d | d   } n| t k rt t | | d	   t t | | d   d >} | r| | k rt d | | t |  d f  t j d d d d d d  } t d | d!  | t j  d | d  } q| d } n | t! k r8t" | | d	  } n | t# k ret | | d	 | d   } n | t$ k rt | | d	  } | | d | d |  } nB | t% k rt& t | | d	   } n d } t d | | f  | | | <WqRt k
 rI} z7 d | t	 |  | f } |  j
 t | | |   WYd d } ~ XqRXqRW| 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)
        Nr4  r)   r   r%   r!   r   s   ****r   z6Error while parsing properties header in stream %s: %sr   r   z!property id=%d: type=%d offset=%Xi   i   r   s    r   r   r   z8Converting property #%d to python datetime, value=%d=%fsi iA  ztimedelta days=%dr   i@B i  rU   z5property id=%d: type=%d not implemented in parser yetz3Error while parsing property id %d in stream %s: %si l    hC! l    @T$)'r=   r+  r   r8  r7   rT   r<   rM   BaseExceptionr   r   r   r   r   VT_I2rL   VT_UI2VT_I4VT_INTVT_ERRORVT_UI4VT_UINTVT_BSTRVT_LPSTRr   VT_BLOB	VT_LPWSTRr   VT_FILETIMEr   floatrV   rW   VT_UI1rF   VT_CLSIDVT_CFVT_BOOLbool)r   rA   r   r   Z
streampathr   r   r  rS   ZfmtidZ	num_propsexcr	   typer   idr   r   countrX   r
   r
   r   r     s    	& ,4!0zOleFileIO.getpropertiesc             C   s#   t    |  _ |  j j |   |  j S)z
        Parse standard properties streams, return an OleMetadata object
        containing all the available metadata.
        (also stored in the metadata attribute of the OleFileIO object)

        new in version 0.25
        )rZ   metadatar   )r   r
   r
   r   get_metadata  s    zOleFileIO.get_metadata)&r   r   r   r   r   DEFAULT_PATH_ENCODINGr   r   r   r   r@   r  r   r  r  r  r  r  r#  r  r(  r  r   r*  r"  r-  r3  r7  r8  r:  r;  r   r   r   r<  r=  r   rV  r
   r
   r
   r   r   '  sB   (%J"##<r   __main__zolefile version %s %s - %sa@  
Launched from the command line, this script parses OLE files and prints info.

Usage: olefile.py [-d] [-c] <file> [file2 ...]

Options:
-d : debug mode (displays a lot of debug information, for developers only)
-c : check all streams (for debugging purposes)

For more information, see http://www.decalage.info/olefile
z-dz-c-z: propertiesr   2      z(binary data)z   z
Checking streams...r4  r   r   zsize %dzNOT a stream : type=%dz5Modification/Creation times of all directory entries:z- %s: mtime=%s ctime=%sz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:z- %s: %sNone)
__future__r   
__author____date____version__r   r  rI   r  os.pathr   rV   r+  r>   rH   r   xranger  r   itemsizer  r%  r5  	NameErrorZKEEP_UNICODE_NAMESversion_inforW  r   r   r   r   r   r;   Z
MAXREGSECTr  r  r   r	  Z	MAXREGSIDr   r   r   r   ZSTGTY_LOCKBYTESZSTGTY_PROPERTYr   ZVT_EMPTYZVT_NULLr?  rA  ZVT_R4ZVT_R8ZVT_CYZVT_DATErF  ZVT_DISPATCHrC  rO  Z
VT_VARIANTZ
VT_UNKNOWNZ
VT_DECIMALZVT_I1rL  r@  rD  ZVT_I8ZVT_UI8rB  rE  ZVT_VOIDZ
VT_HRESULTZVT_PTRZVT_SAFEARRAYZ	VT_CARRAYZVT_USERDEFINEDrG  rI  rJ  rH  Z	VT_STREAMZ
VT_STORAGEZVT_STREAMED_OBJECTZVT_STORED_OBJECTZVT_BLOB_OBJECTrN  rM  Z	VT_VECTORZVTlistvarsitemskeywordvarZ
WORD_CLSIDr   r   r   r   r?   rC   rF   rL   rM   rT   rY   objectrZ   r   r   r   r   r   r:   argvr   exitZcheck_streamsrA   Zoler*  r3  Z
streamnamer   r   sortedkvr=   rE   r   r   r   r;  Zst_typer<  r8  r   r   r   r   r   rV  metar   r=  r!  r   r   exctyper	   r
   r
   r
   r   <module>   sn  		
					                                "
!

    r


3+
%

!


	