Sophie

Sophie

distrib > Mageia > 5 > i586 > media > core-release > by-pkgid > b17ed897c34853a0a39ef25ab5d3af32 > files > 31

python3-pillow-doc-2.6.2-2.mga5.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>PIL.OleFileIO &mdash; Pillow v2.6.2 (PIL fork)</title>
    
    <link rel="stylesheet" href="../../_static/default.css" type="text/css" />
    <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
    
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../../',
        VERSION:     '2.6.2',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="../../_static/jquery.js"></script>
    <script type="text/javascript" src="../../_static/underscore.js"></script>
    <script type="text/javascript" src="../../_static/doctools.js"></script>
    <link rel="author" title="About these documents" href="../../about.html" />
    <link rel="top" title="Pillow v2.6.2 (PIL fork)" href="../../index.html" />
    <link rel="up" title="Module code" href="../index.html" /> 
  </head>
  <body>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="../../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li><a href="../../index.html">Home</a> &raquo;</li>
          <li><a href="../index.html" accesskey="U">Module code</a> &raquo;</li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  <h1>Source code for PIL.OleFileIO</h1><div class="highlight"><pre>
<span class="c">#!/usr/bin/python</span>
<span class="c"># -*- coding: latin-1 -*-</span>
<span class="c">## OleFileIO_PL:</span>
<span class="c">## Module to read Microsoft OLE2 files (also called Structured Storage or</span>
<span class="c">## Microsoft Compound Document File Format), such as Microsoft Office</span>
<span class="c">## documents, Image Composer and FlashPix files, Outlook messages, ...</span>
<span class="c">## This version is compatible with Python 2.6+ and 3.x</span>

<span class="c">## version 0.30 2014-02-04 Philippe Lagadec - http://www.decalage.info</span>

<span class="c">## Project website: http://www.decalage.info/python/olefileio</span>

<span class="c">## Improved version of the OleFileIO module from PIL library v1.1.6</span>
<span class="c">## See: http://www.pythonware.com/products/pil/index.htm</span>

<span class="c">## The Python Imaging Library (PIL) is</span>

<span class="c">##     Copyright (c) 1997-2005 by Secret Labs AB</span>
<span class="c">##     Copyright (c) 1995-2005 by Fredrik Lundh</span>

<span class="c">## OleFileIO_PL changes are Copyright (c) 2005-2014 by Philippe Lagadec</span>

<span class="c">## See source code and LICENSE.txt for information on usage and redistribution.</span>

<span class="c">## WARNING: THIS IS (STILL) WORK IN PROGRESS.</span>


<span class="c"># Starting with OleFileIO_PL v0.30, only Python 2.6+ and 3.x is supported</span>
<span class="c"># This import enables print() as a function rather than a keyword</span>
<span class="c"># (main requirement to be compatible with Python 3.x)</span>
<span class="c"># The comment on the line below should be printed on Python 2.5 or older:</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">print_function</span> <span class="c"># This version of OleFileIO_PL requires Python 2.6+ or 3.x.</span>


<span class="n">__author__</span>  <span class="o">=</span> <span class="s">&quot;Philippe Lagadec, Fredrik Lundh (Secret Labs AB)&quot;</span>
<span class="n">__date__</span>    <span class="o">=</span> <span class="s">&quot;2014-02-04&quot;</span>
<span class="n">__version__</span> <span class="o">=</span> <span class="s">&#39;0.30&#39;</span>

<span class="c">#--- LICENSE ------------------------------------------------------------------</span>

<span class="c"># OleFileIO_PL is an improved version of the OleFileIO module from the</span>
<span class="c"># Python Imaging Library (PIL).</span>

<span class="c"># OleFileIO_PL changes are Copyright (c) 2005-2014 by Philippe Lagadec</span>
<span class="c">#</span>
<span class="c"># The Python Imaging Library (PIL) is</span>
<span class="c">#    Copyright (c) 1997-2005 by Secret Labs AB</span>
<span class="c">#    Copyright (c) 1995-2005 by Fredrik Lundh</span>
<span class="c">#</span>
<span class="c"># By obtaining, using, and/or copying this software and/or its associated</span>
<span class="c"># documentation, you agree that you have read, understood, and will comply with</span>
<span class="c"># the following terms and conditions:</span>
<span class="c">#</span>
<span class="c"># Permission to use, copy, modify, and distribute this software and its</span>
<span class="c"># associated documentation for any purpose and without fee is hereby granted,</span>
<span class="c"># provided that the above copyright notice appears in all copies, and that both</span>
<span class="c"># that copyright notice and this permission notice appear in supporting</span>
<span class="c"># documentation, and that the name of Secret Labs AB or the author(s) not be used</span>
<span class="c"># in advertising or publicity pertaining to distribution of the software</span>
<span class="c"># without specific, written prior permission.</span>
<span class="c">#</span>
<span class="c"># SECRET LABS AB AND THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS</span>
<span class="c"># SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.</span>
<span class="c"># IN NO EVENT SHALL SECRET LABS AB OR THE AUTHORS BE LIABLE FOR ANY SPECIAL,</span>
<span class="c"># INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM</span>
<span class="c"># LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR</span>
<span class="c"># OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR</span>
<span class="c"># PERFORMANCE OF THIS SOFTWARE.</span>

<span class="c">#-----------------------------------------------------------------------------</span>
<span class="c"># CHANGELOG: (only OleFileIO_PL changes compared to PIL 1.1.6)</span>
<span class="c"># 2005-05-11 v0.10 PL: - a few fixes for Python 2.4 compatibility</span>
<span class="c">#                        (all changes flagged with [PL])</span>
<span class="c"># 2006-02-22 v0.11 PL: - a few fixes for some Office 2003 documents which raise</span>
<span class="c">#                        exceptions in _OleStream.__init__()</span>
<span class="c"># 2006-06-09 v0.12 PL: - fixes for files above 6.8MB (DIFAT in loadfat)</span>
<span class="c">#                      - added some constants</span>
<span class="c">#                      - added header values checks</span>
<span class="c">#                      - added some docstrings</span>
<span class="c">#                      - getsect: bugfix in case sectors &gt;512 bytes</span>
<span class="c">#                      - getsect: added conformity checks</span>
<span class="c">#                      - DEBUG_MODE constant to activate debug display</span>
<span class="c"># 2007-09-04 v0.13 PL: - improved/translated (lots of) comments</span>
<span class="c">#                      - updated license</span>
<span class="c">#                      - converted tabs to 4 spaces</span>
<span class="c"># 2007-11-19 v0.14 PL: - added OleFileIO._raise_defect() to adapt sensitivity</span>
<span class="c">#                      - improved _unicode() to use Python 2.x unicode support</span>
<span class="c">#                      - fixed bug in _OleDirectoryEntry</span>
<span class="c"># 2007-11-25 v0.15 PL: - added safety checks to detect FAT loops</span>
<span class="c">#                      - fixed _OleStream which didn&#39;t check stream size</span>
<span class="c">#                      - added/improved many docstrings and comments</span>
<span class="c">#                      - moved helper functions _unicode and _clsid out of</span>
<span class="c">#                        OleFileIO class</span>
<span class="c">#                      - improved OleFileIO._find() to add Unix path syntax</span>
<span class="c">#                      - OleFileIO._find() is now case-insensitive</span>
<span class="c">#                      - added get_type() and get_rootentry_name()</span>
<span class="c">#                      - rewritten loaddirectory and _OleDirectoryEntry</span>
<span class="c"># 2007-11-27 v0.16 PL: - added _OleDirectoryEntry.kids_dict</span>
<span class="c">#                      - added detection of duplicate filenames in storages</span>
<span class="c">#                      - added detection of duplicate references to streams</span>
<span class="c">#                      - added get_size() and exists() to _OleDirectoryEntry</span>
<span class="c">#                      - added isOleFile to check header before parsing</span>
<span class="c">#                      - added __all__ list to control public keywords in pydoc</span>
<span class="c"># 2007-12-04 v0.17 PL: - added _load_direntry to fix a bug in loaddirectory</span>
<span class="c">#                      - improved _unicode(), added workarounds for Python &lt;2.3</span>
<span class="c">#                      - added set_debug_mode and -d option to set debug mode</span>
<span class="c">#                      - fixed bugs in OleFileIO.open and _OleDirectoryEntry</span>
<span class="c">#                      - added safety check in main for large or binary</span>
<span class="c">#                        properties</span>
<span class="c">#                      - allow size&gt;0 for storages for some implementations</span>
<span class="c"># 2007-12-05 v0.18 PL: - fixed several bugs in handling of FAT, MiniFAT and</span>
<span class="c">#                        streams</span>
<span class="c">#                      - added option &#39;-c&#39; in main to check all streams</span>
<span class="c"># 2009-12-10 v0.19 PL: - bugfix for 32 bit arrays on 64 bits platforms</span>
<span class="c">#                        (thanks to Ben G. and Martijn for reporting the bug)</span>
<span class="c"># 2009-12-11 v0.20 PL: - bugfix in OleFileIO.open when filename is not plain str</span>
<span class="c"># 2010-01-22 v0.21 PL: - added support for big-endian CPUs such as PowerPC Macs</span>
<span class="c"># 2012-02-16 v0.22 PL: - fixed bug in getproperties, patch by chuckleberryfinn</span>
<span class="c">#                        (https://bitbucket.org/decalage/olefileio_pl/issue/7)</span>
<span class="c">#                      - added close method to OleFileIO (fixed issue #2)</span>
<span class="c"># 2012-07-25 v0.23 PL: - added support for file-like objects (patch by mete0r_kr)</span>
<span class="c"># 2013-05-05 v0.24 PL: - getproperties: added conversion from filetime to python</span>
<span class="c">#                        datetime</span>
<span class="c">#                      - main: displays properties with date format</span>
<span class="c">#                      - new class OleMetadata to parse standard properties</span>
<span class="c">#                      - added get_metadata method</span>
<span class="c"># 2013-05-07 v0.24 PL: - a few improvements in OleMetadata</span>
<span class="c"># 2013-05-24 v0.25 PL: - getproperties: option to not convert some timestamps</span>
<span class="c">#                      - OleMetaData: total_edit_time is now a number of seconds,</span>
<span class="c">#                        not a timestamp</span>
<span class="c">#                      - getproperties: added support for VT_BOOL, VT_INT, V_UINT</span>
<span class="c">#                      - getproperties: filter out null chars from strings</span>
<span class="c">#                      - getproperties: raise non-fatal defects instead of</span>
<span class="c">#                        exceptions when properties cannot be parsed properly</span>
<span class="c"># 2013-05-27       PL: - getproperties: improved exception handling</span>
<span class="c">#                      - _raise_defect: added option to set exception type</span>
<span class="c">#                      - all non-fatal issues are now recorded, and displayed</span>
<span class="c">#                        when run as a script</span>
<span class="c"># 2013-07-11 v0.26 PL: - added methods to get modification and creation times</span>
<span class="c">#                        of a directory entry or a storage/stream</span>
<span class="c">#                      - fixed parsing of direntry timestamps</span>
<span class="c"># 2013-07-24       PL: - new options in listdir to list storages and/or streams</span>
<span class="c"># 2014-02-04 v0.30 PL: - upgraded code to support Python 3.x by Martin Panter</span>
<span class="c">#                      - several fixes for Python 2.6 (xrange, MAGIC)</span>
<span class="c">#                      - reused i32 from Pillow&#39;s _binary</span>

<span class="c">#-----------------------------------------------------------------------------</span>
<span class="c"># TODO (for version 1.0):</span>
<span class="c"># + isOleFile should accept file-like objects like open</span>
<span class="c"># + fix how all the methods handle unicode str and/or bytes as arguments</span>
<span class="c"># + add path attrib to _OleDirEntry, set it once and for all in init or</span>
<span class="c">#   append_kids (then listdir/_list can be simplified)</span>
<span class="c"># - TESTS with Linux, MacOSX, Python 1.5.2, various files, PIL, ...</span>
<span class="c"># - add underscore to each private method, to avoid their display in</span>
<span class="c">#   pydoc/epydoc documentation - Remove it for classes to be documented</span>
<span class="c"># - replace all raised exceptions with _raise_defect (at least in OleFileIO)</span>
<span class="c"># - merge code from _OleStream and OleFileIO.getsect to read sectors</span>
<span class="c">#   (maybe add a class for FAT and MiniFAT ?)</span>
<span class="c"># - add method to check all streams (follow sectors chains without storing all</span>
<span class="c">#   stream in memory, and report anomalies)</span>
<span class="c"># - use _OleDirectoryEntry.kids_dict to improve _find and _list ?</span>
<span class="c"># - fix Unicode names handling (find some way to stay compatible with Py1.5.2)</span>
<span class="c">#   =&gt; if possible avoid converting names to Latin-1</span>
<span class="c"># - review DIFAT code: fix handling of DIFSECT blocks in FAT (not stop)</span>
<span class="c"># - rewrite OleFileIO.getproperties</span>
<span class="c"># - improve docstrings to show more sample uses</span>
<span class="c"># - see also original notes and FIXME below</span>
<span class="c"># - remove all obsolete FIXMEs</span>
<span class="c"># - OleMetadata: fix version attrib according to</span>
<span class="c">#   http://msdn.microsoft.com/en-us/library/dd945671%28v=office.12%29.aspx</span>

<span class="c"># IDEAS:</span>
<span class="c"># - in OleFileIO._open and _OleStream, use size=None instead of 0x7FFFFFFF for</span>
<span class="c">#   streams with unknown size</span>
<span class="c"># - use arrays of int instead of long integers for FAT/MiniFAT, to improve</span>
<span class="c">#   performance and reduce memory usage ? (possible issue with values &gt;2^31)</span>
<span class="c"># - provide tests with unittest (may need write support to create samples)</span>
<span class="c"># - move all debug code (and maybe dump methods) to a separate module, with</span>
<span class="c">#   a class which inherits OleFileIO ?</span>
<span class="c"># - fix docstrings to follow epydoc format</span>
<span class="c"># - add support for 4K sectors ?</span>
<span class="c"># - add support for big endian byte order ?</span>
<span class="c"># - create a simple OLE explorer with wxPython</span>

<span class="c"># FUTURE EVOLUTIONS to add write support:</span>
<span class="c"># 1) add ability to write a stream back on disk from BytesIO (same size, no</span>
<span class="c">#    change in FAT/MiniFAT).</span>
<span class="c"># 2) rename a stream/storage if it doesn&#39;t change the RB tree</span>
<span class="c"># 3) use rbtree module to update the red-black tree + any rename</span>
<span class="c"># 4) remove a stream/storage: free sectors in FAT/MiniFAT</span>
<span class="c"># 5) allocate new sectors in FAT/MiniFAT</span>
<span class="c"># 6) create new storage/stream</span>
<span class="c">#-----------------------------------------------------------------------------</span>

<span class="c">#</span>
<span class="c"># THIS IS WORK IN PROGRESS</span>
<span class="c">#</span>
<span class="c"># The Python Imaging Library</span>
<span class="c"># $Id$</span>
<span class="c">#</span>
<span class="c"># stuff to deal with OLE2 Structured Storage files.  this module is</span>
<span class="c"># used by PIL to read Image Composer and FlashPix files, but can also</span>
<span class="c"># be used to read other files of this type.</span>
<span class="c">#</span>
<span class="c"># History:</span>
<span class="c"># 1997-01-20 fl   Created</span>
<span class="c"># 1997-01-22 fl   Fixed 64-bit portability quirk</span>
<span class="c"># 2003-09-09 fl   Fixed typo in OleFileIO.loadfat (noted by Daniel Haertle)</span>
<span class="c"># 2004-02-29 fl   Changed long hex constants to signed integers</span>
<span class="c">#</span>
<span class="c"># Notes:</span>
<span class="c"># FIXME: sort out sign problem (eliminate long hex constants)</span>
<span class="c"># FIXME: change filename to use &quot;a/b/c&quot; instead of [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;]</span>
<span class="c"># FIXME: provide a glob mechanism function (using fnmatchcase)</span>
<span class="c">#</span>
<span class="c"># Literature:</span>
<span class="c">#</span>
<span class="c"># &quot;FlashPix Format Specification, Appendix A&quot;, Kodak and Microsoft,</span>
<span class="c">#  September 1996.</span>
<span class="c">#</span>
<span class="c"># Quotes:</span>
<span class="c">#</span>
<span class="c"># &quot;If this document and functionality of the Software conflict,</span>
<span class="c">#  the actual functionality of the Software represents the correct</span>
<span class="c">#  functionality&quot; -- Microsoft, in the OLE format specification</span>
<span class="c">#</span>
<span class="c"># Copyright (c) Secret Labs AB 1997.</span>
<span class="c"># Copyright (c) Fredrik Lundh 1997.</span>
<span class="c">#</span>
<span class="c"># See the README file for information on usage and redistribution.</span>
<span class="c">#</span>

<span class="c">#------------------------------------------------------------------------------</span>


<span class="kn">import</span> <span class="nn">io</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">struct</span><span class="o">,</span> <span class="nn">array</span><span class="o">,</span> <span class="nn">os.path</span><span class="o">,</span> <span class="nn">datetime</span>

<span class="c">#[PL] Define explicitly the public API to avoid private objects in pydoc:</span>
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;OleFileIO&#39;</span><span class="p">,</span> <span class="s">&#39;isOleFile&#39;</span><span class="p">,</span> <span class="s">&#39;MAGIC&#39;</span><span class="p">]</span>

<span class="c"># For Python 3.x, need to redefine long as int:</span>
<span class="k">if</span> <span class="nb">str</span> <span class="ow">is</span> <span class="ow">not</span> <span class="nb">bytes</span><span class="p">:</span>
    <span class="nb">long</span> <span class="o">=</span> <span class="nb">int</span>

<span class="c"># Need to make sure we use xrange both on Python 2 and 3.x:</span>
<span class="k">try</span><span class="p">:</span>
    <span class="c"># on Python 2 we need xrange:</span>
    <span class="n">iterrange</span> <span class="o">=</span> <span class="nb">xrange</span>
<span class="k">except</span><span class="p">:</span>
    <span class="c"># no xrange, for Python 3 it was renamed as range:</span>
    <span class="n">iterrange</span> <span class="o">=</span> <span class="nb">range</span>

<span class="c">#[PL] workaround to fix an issue with array item size on 64 bits systems:</span>
<span class="k">if</span> <span class="n">array</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="s">&#39;L&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">itemsize</span> <span class="o">==</span> <span class="mi">4</span><span class="p">:</span>
    <span class="c"># on 32 bits platforms, long integers in an array are 32 bits:</span>
    <span class="n">UINT32</span> <span class="o">=</span> <span class="s">&#39;L&#39;</span>
<span class="k">elif</span> <span class="n">array</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="s">&#39;I&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">itemsize</span> <span class="o">==</span> <span class="mi">4</span><span class="p">:</span>
    <span class="c"># on 64 bits platforms, integers in an array are 32 bits:</span>
    <span class="n">UINT32</span> <span class="o">=</span> <span class="s">&#39;I&#39;</span>
<span class="k">else</span><span class="p">:</span>
    <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&#39;Need to fix a bug with 32 bit arrays, please contact author...&#39;</span><span class="p">)</span>


<span class="c">#[PL] These workarounds were inspired from the Path module</span>
<span class="c"># (see http://www.jorendorff.com/articles/python/path/)</span>
<span class="c">#TODO: test with old Python versions</span>

<span class="c"># Pre-2.3 workaround for basestring.</span>
<span class="k">try</span><span class="p">:</span>
    <span class="nb">basestring</span>
<span class="k">except</span> <span class="ne">NameError</span><span class="p">:</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="c"># is Unicode supported (Python &gt;2.0 or &gt;1.6 ?)</span>
        <span class="nb">basestring</span> <span class="o">=</span> <span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="nb">unicode</span><span class="p">)</span>
    <span class="k">except</span> <span class="ne">NameError</span><span class="p">:</span>
        <span class="nb">basestring</span> <span class="o">=</span> <span class="nb">str</span>

<span class="c">#[PL] Experimental setting: if True, OLE filenames will be kept in Unicode</span>
<span class="c"># if False (default PIL behaviour), all filenames are converted to Latin-1.</span>
<span class="n">KEEP_UNICODE_NAMES</span> <span class="o">=</span> <span class="bp">False</span>

<span class="c">#[PL] DEBUG display mode: False by default, use set_debug_mode() or &quot;-d&quot; on</span>
<span class="c"># command line to change it.</span>
<span class="n">DEBUG_MODE</span> <span class="o">=</span> <span class="bp">False</span>
<span class="k">def</span> <span class="nf">debug_print</span><span class="p">(</span><span class="n">msg</span><span class="p">):</span>
    <span class="k">print</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">debug_pass</span><span class="p">(</span><span class="n">msg</span><span class="p">):</span>
    <span class="k">pass</span>
<span class="n">debug</span> <span class="o">=</span> <span class="n">debug_pass</span>

<span class="k">def</span> <span class="nf">set_debug_mode</span><span class="p">(</span><span class="n">debug_mode</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Set debug mode on or off, to control display of debugging messages.</span>
<span class="sd">    mode: True or False</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">global</span> <span class="n">DEBUG_MODE</span><span class="p">,</span> <span class="n">debug</span>
    <span class="n">DEBUG_MODE</span> <span class="o">=</span> <span class="n">debug_mode</span>
    <span class="k">if</span> <span class="n">debug_mode</span><span class="p">:</span>
        <span class="n">debug</span> <span class="o">=</span> <span class="n">debug_print</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">debug</span> <span class="o">=</span> <span class="n">debug_pass</span>

<span class="n">MAGIC</span> <span class="o">=</span> <span class="n">b</span><span class="s">&#39;</span><span class="se">\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1</span><span class="s">&#39;</span>

<span class="c">#[PL]: added constants for Sector IDs (from AAF specifications)</span>
<span class="n">MAXREGSECT</span> <span class="o">=</span> <span class="mh">0xFFFFFFFA</span><span class="p">;</span> <span class="c"># maximum SECT</span>
<span class="n">DIFSECT</span>    <span class="o">=</span> <span class="mh">0xFFFFFFFC</span><span class="p">;</span> <span class="c"># (-4) denotes a DIFAT sector in a FAT</span>
<span class="n">FATSECT</span>    <span class="o">=</span> <span class="mh">0xFFFFFFFD</span><span class="p">;</span> <span class="c"># (-3) denotes a FAT sector in a FAT</span>
<span class="n">ENDOFCHAIN</span> <span class="o">=</span> <span class="mh">0xFFFFFFFE</span><span class="p">;</span> <span class="c"># (-2) end of a virtual stream chain</span>
<span class="n">FREESECT</span>   <span class="o">=</span> <span class="mh">0xFFFFFFFF</span><span class="p">;</span> <span class="c"># (-1) unallocated sector</span>

<span class="c">#[PL]: added constants for Directory Entry IDs (from AAF specifications)</span>
<span class="n">MAXREGSID</span>  <span class="o">=</span> <span class="mh">0xFFFFFFFA</span><span class="p">;</span> <span class="c"># maximum directory entry ID</span>
<span class="n">NOSTREAM</span>   <span class="o">=</span> <span class="mh">0xFFFFFFFF</span><span class="p">;</span> <span class="c"># (-1) unallocated directory entry</span>

<span class="c">#[PL] object types in storage (from AAF specifications)</span>
<span class="n">STGTY_EMPTY</span>     <span class="o">=</span> <span class="mi">0</span> <span class="c"># empty directory entry (according to OpenOffice.org doc)</span>
<span class="n">STGTY_STORAGE</span>   <span class="o">=</span> <span class="mi">1</span> <span class="c"># element is a storage object</span>
<span class="n">STGTY_STREAM</span>    <span class="o">=</span> <span class="mi">2</span> <span class="c"># element is a stream object</span>
<span class="n">STGTY_LOCKBYTES</span> <span class="o">=</span> <span class="mi">3</span> <span class="c"># element is an ILockBytes object</span>
<span class="n">STGTY_PROPERTY</span>  <span class="o">=</span> <span class="mi">4</span> <span class="c"># element is an IPropertyStorage object</span>
<span class="n">STGTY_ROOT</span>      <span class="o">=</span> <span class="mi">5</span> <span class="c"># element is a root storage</span>


<span class="c">#</span>
<span class="c"># --------------------------------------------------------------------</span>
<span class="c"># property types</span>

<span class="n">VT_EMPTY</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">VT_NULL</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span> <span class="n">VT_I2</span><span class="o">=</span><span class="mi">2</span><span class="p">;</span> <span class="n">VT_I4</span><span class="o">=</span><span class="mi">3</span><span class="p">;</span> <span class="n">VT_R4</span><span class="o">=</span><span class="mi">4</span><span class="p">;</span> <span class="n">VT_R8</span><span class="o">=</span><span class="mi">5</span><span class="p">;</span> <span class="n">VT_CY</span><span class="o">=</span><span class="mi">6</span><span class="p">;</span>
<span class="n">VT_DATE</span><span class="o">=</span><span class="mi">7</span><span class="p">;</span> <span class="n">VT_BSTR</span><span class="o">=</span><span class="mi">8</span><span class="p">;</span> <span class="n">VT_DISPATCH</span><span class="o">=</span><span class="mi">9</span><span class="p">;</span> <span class="n">VT_ERROR</span><span class="o">=</span><span class="mi">10</span><span class="p">;</span> <span class="n">VT_BOOL</span><span class="o">=</span><span class="mi">11</span><span class="p">;</span>
<span class="n">VT_VARIANT</span><span class="o">=</span><span class="mi">12</span><span class="p">;</span> <span class="n">VT_UNKNOWN</span><span class="o">=</span><span class="mi">13</span><span class="p">;</span> <span class="n">VT_DECIMAL</span><span class="o">=</span><span class="mi">14</span><span class="p">;</span> <span class="n">VT_I1</span><span class="o">=</span><span class="mi">16</span><span class="p">;</span> <span class="n">VT_UI1</span><span class="o">=</span><span class="mi">17</span><span class="p">;</span>
<span class="n">VT_UI2</span><span class="o">=</span><span class="mi">18</span><span class="p">;</span> <span class="n">VT_UI4</span><span class="o">=</span><span class="mi">19</span><span class="p">;</span> <span class="n">VT_I8</span><span class="o">=</span><span class="mi">20</span><span class="p">;</span> <span class="n">VT_UI8</span><span class="o">=</span><span class="mi">21</span><span class="p">;</span> <span class="n">VT_INT</span><span class="o">=</span><span class="mi">22</span><span class="p">;</span> <span class="n">VT_UINT</span><span class="o">=</span><span class="mi">23</span><span class="p">;</span>
<span class="n">VT_VOID</span><span class="o">=</span><span class="mi">24</span><span class="p">;</span> <span class="n">VT_HRESULT</span><span class="o">=</span><span class="mi">25</span><span class="p">;</span> <span class="n">VT_PTR</span><span class="o">=</span><span class="mi">26</span><span class="p">;</span> <span class="n">VT_SAFEARRAY</span><span class="o">=</span><span class="mi">27</span><span class="p">;</span> <span class="n">VT_CARRAY</span><span class="o">=</span><span class="mi">28</span><span class="p">;</span>
<span class="n">VT_USERDEFINED</span><span class="o">=</span><span class="mi">29</span><span class="p">;</span> <span class="n">VT_LPSTR</span><span class="o">=</span><span class="mi">30</span><span class="p">;</span> <span class="n">VT_LPWSTR</span><span class="o">=</span><span class="mi">31</span><span class="p">;</span> <span class="n">VT_FILETIME</span><span class="o">=</span><span class="mi">64</span><span class="p">;</span>
<span class="n">VT_BLOB</span><span class="o">=</span><span class="mi">65</span><span class="p">;</span> <span class="n">VT_STREAM</span><span class="o">=</span><span class="mi">66</span><span class="p">;</span> <span class="n">VT_STORAGE</span><span class="o">=</span><span class="mi">67</span><span class="p">;</span> <span class="n">VT_STREAMED_OBJECT</span><span class="o">=</span><span class="mi">68</span><span class="p">;</span>
<span class="n">VT_STORED_OBJECT</span><span class="o">=</span><span class="mi">69</span><span class="p">;</span> <span class="n">VT_BLOB_OBJECT</span><span class="o">=</span><span class="mi">70</span><span class="p">;</span> <span class="n">VT_CF</span><span class="o">=</span><span class="mi">71</span><span class="p">;</span> <span class="n">VT_CLSID</span><span class="o">=</span><span class="mi">72</span><span class="p">;</span>
<span class="n">VT_VECTOR</span><span class="o">=</span><span class="mh">0x1000</span><span class="p">;</span>

<span class="c"># map property id to name (for debugging purposes)</span>

<span class="n">VT</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">keyword</span><span class="p">,</span> <span class="n">var</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="nb">vars</span><span class="p">()</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span>
    <span class="k">if</span> <span class="n">keyword</span><span class="p">[:</span><span class="mi">3</span><span class="p">]</span> <span class="o">==</span> <span class="s">&quot;VT_&quot;</span><span class="p">:</span>
        <span class="n">VT</span><span class="p">[</span><span class="n">var</span><span class="p">]</span> <span class="o">=</span> <span class="n">keyword</span>

<span class="c">#</span>
<span class="c"># --------------------------------------------------------------------</span>
<span class="c"># Some common document types (root.clsid fields)</span>

<span class="n">WORD_CLSID</span> <span class="o">=</span> <span class="s">&quot;00020900-0000-0000-C000-000000000046&quot;</span>
<span class="c">#TODO: check Excel, PPT, ...</span>

<span class="c">#[PL]: Defect levels to classify parsing errors - see OleFileIO._raise_defect()</span>
<span class="n">DEFECT_UNSURE</span> <span class="o">=</span>    <span class="mi">10</span>    <span class="c"># a case which looks weird, but not sure it&#39;s a defect</span>
<span class="n">DEFECT_POTENTIAL</span> <span class="o">=</span> <span class="mi">20</span>    <span class="c"># a potential defect</span>
<span class="n">DEFECT_INCORRECT</span> <span class="o">=</span> <span class="mi">30</span>    <span class="c"># an error according to specifications, but parsing</span>
                         <span class="c"># can go on</span>
<span class="n">DEFECT_FATAL</span> <span class="o">=</span>     <span class="mi">40</span>    <span class="c"># an error which cannot be ignored, parsing is</span>
                         <span class="c"># impossible</span>

<span class="c">#[PL] add useful constants to __all__:</span>
<span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="nb">vars</span><span class="p">()</span><span class="o">.</span><span class="n">keys</span><span class="p">()):</span>
    <span class="k">if</span> <span class="n">key</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;STGTY_&#39;</span><span class="p">)</span> <span class="ow">or</span> <span class="n">key</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;DEFECT_&#39;</span><span class="p">):</span>
        <span class="n">__all__</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>


<span class="c">#--- FUNCTIONS ----------------------------------------------------------------</span>

<div class="viewcode-block" id="isOleFile"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.isOleFile">[docs]</a><span class="k">def</span> <span class="nf">isOleFile</span> <span class="p">(</span><span class="n">filename</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Test if file is an OLE container (according to its header).</span>
<span class="sd">    </span>
<span class="sd">    :param filename: file name or path (str, unicode)</span>
<span class="sd">    :returns: True if OLE, False otherwise.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="s">&#39;rb&#39;</span><span class="p">)</span>
    <span class="n">header</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">MAGIC</span><span class="p">))</span>
    <span class="k">if</span> <span class="n">header</span> <span class="o">==</span> <span class="n">MAGIC</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">True</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">False</span>

</div>
<span class="k">if</span> <span class="nb">bytes</span> <span class="ow">is</span> <span class="nb">str</span><span class="p">:</span>
    <span class="c"># version for Python 2.x</span>
    <span class="k">def</span> <span class="nf">i8</span><span class="p">(</span><span class="n">c</span><span class="p">):</span>
        <span class="k">return</span> <span class="nb">ord</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
    <span class="c"># version for Python 3.x</span>
    <span class="k">def</span> <span class="nf">i8</span><span class="p">(</span><span class="n">c</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">c</span> <span class="k">if</span> <span class="n">c</span><span class="o">.</span><span class="n">__class__</span> <span class="ow">is</span> <span class="nb">int</span> <span class="k">else</span> <span class="n">c</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>


<span class="c">#TODO: replace i16 and i32 with more readable struct.unpack equivalent?</span>

<span class="k">def</span> <span class="nf">i16</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">o</span> <span class="o">=</span> <span class="mi">0</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Converts a 2-bytes (16 bits) string to an integer.</span>

<span class="sd">    :param c: string containing bytes to convert</span>
<span class="sd">    :param o: offset of bytes to convert in string</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">return</span> <span class="n">i8</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="n">o</span><span class="p">])</span> <span class="o">|</span> <span class="p">(</span><span class="n">i8</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="n">o</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span><span class="o">&lt;&lt;</span><span class="mi">8</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">i32</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">o</span> <span class="o">=</span> <span class="mi">0</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Converts a 4-bytes (32 bits) string to an integer.</span>

<span class="sd">    :param c: string containing bytes to convert</span>
<span class="sd">    :param o: offset of bytes to convert in string</span>
<span class="sd">    &quot;&quot;&quot;</span>
<span class="c">##    return int(ord(c[o])+(ord(c[o+1])&lt;&lt;8)+(ord(c[o+2])&lt;&lt;16)+(ord(c[o+3])&lt;&lt;24))</span>
<span class="c">##    # [PL]: added int() because &quot;&lt;&lt;&quot; gives long int since Python 2.4</span>
    <span class="c"># copied from Pillow&#39;s _binary:</span>
    <span class="k">return</span> <span class="n">i8</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="n">o</span><span class="p">])</span> <span class="o">|</span> <span class="p">(</span><span class="n">i8</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="n">o</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span><span class="o">&lt;&lt;</span><span class="mi">8</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">i8</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="n">o</span><span class="o">+</span><span class="mi">2</span><span class="p">])</span><span class="o">&lt;&lt;</span><span class="mi">16</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">i8</span><span class="p">(</span><span class="n">c</span><span class="p">[</span><span class="n">o</span><span class="o">+</span><span class="mi">3</span><span class="p">])</span><span class="o">&lt;&lt;</span><span class="mi">24</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">_clsid</span><span class="p">(</span><span class="n">clsid</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Converts a CLSID to a human-readable string.</span>

<span class="sd">    :param clsid: string of length 16.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">clsid</span><span class="p">)</span> <span class="o">==</span> <span class="mi">16</span>
    <span class="c"># if clsid is only made of null bytes, return an empty string:</span>
    <span class="c"># (PL: why not simply return the string with zeroes?)</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">clsid</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="n">b</span><span class="s">&quot;</span><span class="se">\0</span><span class="s">&quot;</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">&quot;&quot;</span>
    <span class="k">return</span> <span class="p">((</span><span class="s">&quot;</span><span class="si">%08X</span><span class="s">-</span><span class="si">%04X</span><span class="s">-</span><span class="si">%04X</span><span class="s">-</span><span class="si">%02X%02X</span><span class="s">-&quot;</span> <span class="o">+</span> <span class="s">&quot;</span><span class="si">%02X</span><span class="s">&quot;</span> <span class="o">*</span> <span class="mi">6</span><span class="p">)</span> <span class="o">%</span>
            <span class="p">((</span><span class="n">i32</span><span class="p">(</span><span class="n">clsid</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">i16</span><span class="p">(</span><span class="n">clsid</span><span class="p">,</span> <span class="mi">4</span><span class="p">),</span> <span class="n">i16</span><span class="p">(</span><span class="n">clsid</span><span class="p">,</span> <span class="mi">6</span><span class="p">))</span> <span class="o">+</span>
            <span class="nb">tuple</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="n">i8</span><span class="p">,</span> <span class="n">clsid</span><span class="p">[</span><span class="mi">8</span><span class="p">:</span><span class="mi">16</span><span class="p">]))))</span>



<span class="c"># UNICODE support:</span>
<span class="c"># (necessary to handle storages/streams names which use Unicode)</span>

<span class="k">def</span> <span class="nf">_unicode</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="s">&#39;replace&#39;</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Map unicode string to Latin 1. (Python with Unicode support)</span>

<span class="sd">    :param s: UTF-16LE unicode string to convert to Latin-1</span>
<span class="sd">    :param errors: &#39;replace&#39;, &#39;ignore&#39; or &#39;strict&#39;.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="c">#TODO: test if it OleFileIO works with Unicode strings, instead of</span>
    <span class="c">#      converting to Latin-1.</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="c"># First the string is converted to plain Unicode:</span>
        <span class="c"># (assuming it is encoded as UTF-16 little-endian)</span>
        <span class="n">u</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s">&#39;UTF-16LE&#39;</span><span class="p">,</span> <span class="n">errors</span><span class="p">)</span>
        <span class="k">if</span> <span class="nb">bytes</span> <span class="ow">is</span> <span class="ow">not</span> <span class="nb">str</span> <span class="ow">or</span> <span class="n">KEEP_UNICODE_NAMES</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">u</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="c"># Second the unicode string is converted to Latin-1</span>
            <span class="k">return</span> <span class="n">u</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s">&#39;latin_1&#39;</span><span class="p">,</span> <span class="n">errors</span><span class="p">)</span>
    <span class="k">except</span><span class="p">:</span>
        <span class="c"># there was an error during Unicode to Latin-1 conversion:</span>
        <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">&#39;incorrect Unicode name&#39;</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">filetime2datetime</span><span class="p">(</span><span class="n">filetime</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        convert FILETIME (64 bits int) to Python datetime.datetime</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c"># TODO: manage exception when microseconds is too large</span>
        <span class="c"># inspired from http://code.activestate.com/recipes/511425-filetime-to-datetime/</span>
        <span class="n">_FILETIME_null_date</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="p">(</span><span class="mi">1601</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
        <span class="c">#debug(&#39;timedelta days=%d&#39; % (filetime//(10*1000000*3600*24)))</span>
        <span class="k">return</span> <span class="n">_FILETIME_null_date</span> <span class="o">+</span> <span class="n">datetime</span><span class="o">.</span><span class="n">timedelta</span><span class="p">(</span><span class="n">microseconds</span><span class="o">=</span><span class="n">filetime</span><span class="o">//</span><span class="mi">10</span><span class="p">)</span>



<span class="c">#=== CLASSES ==================================================================</span>

<span class="k">class</span> <span class="nc">OleMetadata</span><span class="p">:</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    class to parse and store metadata from standard properties of OLE files.</span>

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

<span class="sd">    Note: an attribute is set to None when not present in the properties of the</span>
<span class="sd">    OLE file.</span>

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

<span class="sd">    References for DocumentSummaryInformation stream:</span>
<span class="sd">    - http://msdn.microsoft.com/en-us/library/dd945671%28v=office.12%29.aspx</span>
<span class="sd">    - http://msdn.microsoft.com/en-us/library/windows/desktop/aa380374%28v=vs.85%29.aspx</span>
<span class="sd">    - http://poi.apache.org/apidocs/org/apache/poi/hpsf/DocumentSummaryInformation.html</span>

<span class="sd">    new in version 0.25</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="c"># attribute names for SummaryInformation stream properties:</span>
    <span class="c"># (ordered by property id, starting at 1)</span>
    <span class="n">SUMMARY_ATTRIBS</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;codepage&#39;</span><span class="p">,</span> <span class="s">&#39;title&#39;</span><span class="p">,</span> <span class="s">&#39;subject&#39;</span><span class="p">,</span> <span class="s">&#39;author&#39;</span><span class="p">,</span> <span class="s">&#39;keywords&#39;</span><span class="p">,</span> <span class="s">&#39;comments&#39;</span><span class="p">,</span>
        <span class="s">&#39;template&#39;</span><span class="p">,</span> <span class="s">&#39;last_saved_by&#39;</span><span class="p">,</span> <span class="s">&#39;revision_number&#39;</span><span class="p">,</span> <span class="s">&#39;total_edit_time&#39;</span><span class="p">,</span>
        <span class="s">&#39;last_printed&#39;</span><span class="p">,</span> <span class="s">&#39;create_time&#39;</span><span class="p">,</span> <span class="s">&#39;last_saved_time&#39;</span><span class="p">,</span> <span class="s">&#39;num_pages&#39;</span><span class="p">,</span>
        <span class="s">&#39;num_words&#39;</span><span class="p">,</span> <span class="s">&#39;num_chars&#39;</span><span class="p">,</span> <span class="s">&#39;thumbnail&#39;</span><span class="p">,</span> <span class="s">&#39;creating_application&#39;</span><span class="p">,</span>
        <span class="s">&#39;security&#39;</span><span class="p">]</span>

    <span class="c"># attribute names for DocumentSummaryInformation stream properties:</span>
    <span class="c"># (ordered by property id, starting at 1)</span>
    <span class="n">DOCSUM_ATTRIBS</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;codepage_doc&#39;</span><span class="p">,</span> <span class="s">&#39;category&#39;</span><span class="p">,</span> <span class="s">&#39;presentation_target&#39;</span><span class="p">,</span> <span class="s">&#39;bytes&#39;</span><span class="p">,</span> <span class="s">&#39;lines&#39;</span><span class="p">,</span> <span class="s">&#39;paragraphs&#39;</span><span class="p">,</span>
        <span class="s">&#39;slides&#39;</span><span class="p">,</span> <span class="s">&#39;notes&#39;</span><span class="p">,</span> <span class="s">&#39;hidden_slides&#39;</span><span class="p">,</span> <span class="s">&#39;mm_clips&#39;</span><span class="p">,</span>
        <span class="s">&#39;scale_crop&#39;</span><span class="p">,</span> <span class="s">&#39;heading_pairs&#39;</span><span class="p">,</span> <span class="s">&#39;titles_of_parts&#39;</span><span class="p">,</span> <span class="s">&#39;manager&#39;</span><span class="p">,</span>
        <span class="s">&#39;company&#39;</span><span class="p">,</span> <span class="s">&#39;links_dirty&#39;</span><span class="p">,</span> <span class="s">&#39;chars_with_spaces&#39;</span><span class="p">,</span> <span class="s">&#39;unused&#39;</span><span class="p">,</span> <span class="s">&#39;shared_doc&#39;</span><span class="p">,</span>
        <span class="s">&#39;link_base&#39;</span><span class="p">,</span> <span class="s">&#39;hlinks&#39;</span><span class="p">,</span> <span class="s">&#39;hlinks_changed&#39;</span><span class="p">,</span> <span class="s">&#39;version&#39;</span><span class="p">,</span> <span class="s">&#39;dig_sig&#39;</span><span class="p">,</span>
        <span class="s">&#39;content_type&#39;</span><span class="p">,</span> <span class="s">&#39;content_status&#39;</span><span class="p">,</span> <span class="s">&#39;language&#39;</span><span class="p">,</span> <span class="s">&#39;doc_version&#39;</span><span class="p">]</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Constructor for OleMetadata</span>
<span class="sd">        All attributes are set to None by default</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c"># properties from SummaryInformation stream</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">codepage</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">subject</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">author</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">keywords</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">comments</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">template</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">last_saved_by</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">revision_number</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">total_edit_time</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">last_printed</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">create_time</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">last_saved_time</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">num_pages</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">num_words</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">num_chars</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">thumbnail</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">creating_application</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">security</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="c"># properties from DocumentSummaryInformation stream</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">codepage_doc</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">category</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">presentation_target</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">bytes</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">lines</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">paragraphs</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">slides</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">notes</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">hidden_slides</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">mm_clips</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">scale_crop</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">heading_pairs</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">titles_of_parts</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">manager</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">company</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">links_dirty</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">chars_with_spaces</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">unused</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">shared_doc</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">link_base</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">hlinks</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">hlinks_changed</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">version</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">dig_sig</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">content_type</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">content_status</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">language</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">doc_version</span> <span class="o">=</span> <span class="bp">None</span>


    <span class="k">def</span> <span class="nf">parse_properties</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">olefile</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Parse standard properties of an OLE file, from the streams</span>
<span class="sd">        &quot;\x05SummaryInformation&quot; and &quot;\x05DocumentSummaryInformation&quot;,</span>
<span class="sd">        if present.</span>
<span class="sd">        Properties are converted to strings, integers or python datetime objects.</span>
<span class="sd">        If a property is not present, its value is set to None.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c"># first set all attributes to None:</span>
        <span class="k">for</span> <span class="n">attrib</span> <span class="ow">in</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">SUMMARY_ATTRIBS</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">DOCSUM_ATTRIBS</span><span class="p">):</span>
            <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">attrib</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">olefile</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="s">&quot;</span><span class="se">\x05</span><span class="s">SummaryInformation&quot;</span><span class="p">):</span>
            <span class="c"># get properties from the stream:</span>
            <span class="c"># (converting timestamps to python datetime, except total_edit_time,</span>
            <span class="c"># which is property #10)</span>
            <span class="n">props</span> <span class="o">=</span> <span class="n">olefile</span><span class="o">.</span><span class="n">getproperties</span><span class="p">(</span><span class="s">&quot;</span><span class="se">\x05</span><span class="s">SummaryInformation&quot;</span><span class="p">,</span>
                <span class="n">convert_time</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">no_conversion</span><span class="o">=</span><span class="p">[</span><span class="mi">10</span><span class="p">])</span>
            <span class="c"># store them into this object&#39;s attributes:</span>
            <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">SUMMARY_ATTRIBS</span><span class="p">)):</span>
                <span class="c"># ids for standards properties start at 0x01, until 0x13</span>
                <span class="n">value</span> <span class="o">=</span> <span class="n">props</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
                <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">SUMMARY_ATTRIBS</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">value</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">olefile</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="s">&quot;</span><span class="se">\x05</span><span class="s">DocumentSummaryInformation&quot;</span><span class="p">):</span>
            <span class="c"># get properties from the stream:</span>
            <span class="n">props</span> <span class="o">=</span> <span class="n">olefile</span><span class="o">.</span><span class="n">getproperties</span><span class="p">(</span><span class="s">&quot;</span><span class="se">\x05</span><span class="s">DocumentSummaryInformation&quot;</span><span class="p">,</span>
                <span class="n">convert_time</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
            <span class="c"># store them into this object&#39;s attributes:</span>
            <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">DOCSUM_ATTRIBS</span><span class="p">)):</span>
                <span class="c"># ids for standards properties start at 0x01, until 0x13</span>
                <span class="n">value</span> <span class="o">=</span> <span class="n">props</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
                <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">DOCSUM_ATTRIBS</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">value</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">dump</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Dump all metadata, for debugging purposes.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">print</span><span class="p">(</span><span class="s">&#39;Properties from SummaryInformation stream:&#39;</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">prop</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">SUMMARY_ATTRIBS</span><span class="p">:</span>
            <span class="n">value</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">prop</span><span class="p">)</span>
            <span class="k">print</span><span class="p">(</span><span class="s">&#39;- </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">prop</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">value</span><span class="p">)))</span>
        <span class="k">print</span><span class="p">(</span><span class="s">&#39;Properties from DocumentSummaryInformation stream:&#39;</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">prop</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">DOCSUM_ATTRIBS</span><span class="p">:</span>
            <span class="n">value</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">prop</span><span class="p">)</span>
            <span class="k">print</span><span class="p">(</span><span class="s">&#39;- </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">prop</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">value</span><span class="p">)))</span>


<span class="c">#--- _OleStream ---------------------------------------------------------------</span>

<span class="k">class</span> <span class="nc">_OleStream</span><span class="p">(</span><span class="n">io</span><span class="o">.</span><span class="n">BytesIO</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    OLE2 Stream</span>

<span class="sd">    Returns a read-only file object which can be used to read</span>
<span class="sd">    the contents of a OLE stream (instance of the BytesIO class).</span>
<span class="sd">    To open a stream, use the openstream method in the OleFile class.</span>

<span class="sd">    This function can be used with either ordinary streams,</span>
<span class="sd">    or ministreams, depending on the offset, sectorsize, and</span>
<span class="sd">    fat table arguments.</span>

<span class="sd">    Attributes:</span>
<span class="sd">        - size: actual size of data stream, after it was opened.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="c"># FIXME: should store the list of sects obtained by following</span>
    <span class="c"># the fat chain, and load new sectors on demand instead of</span>
    <span class="c"># loading it all in one go.</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fp</span><span class="p">,</span> <span class="n">sect</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">offset</span><span class="p">,</span> <span class="n">sectorsize</span><span class="p">,</span> <span class="n">fat</span><span class="p">,</span> <span class="n">filesize</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Constructor for _OleStream class.</span>

<span class="sd">        :param fp        : file object, the OLE container or the MiniFAT stream</span>
<span class="sd">        :param sect      : sector index of first sector in the stream</span>
<span class="sd">        :param size      : total size of the stream</span>
<span class="sd">        :param offset    : offset in bytes for the first FAT or MiniFAT sector</span>
<span class="sd">        :param sectorsize: size of one sector</span>
<span class="sd">        :param fat       : array/list of sector indexes (FAT or MiniFAT)</span>
<span class="sd">        :param filesize  : size of OLE file (for debugging)</span>
<span class="sd">        :returns    : a BytesIO instance containing the OLE stream</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">debug</span><span class="p">(</span><span class="s">&#39;_OleStream.__init__:&#39;</span><span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span><span class="s">&#39;  sect=</span><span class="si">%d</span><span class="s"> (</span><span class="si">%X</span><span class="s">), size=</span><span class="si">%d</span><span class="s">, offset=</span><span class="si">%d</span><span class="s">, sectorsize=</span><span class="si">%d</span><span class="s">, len(fat)=</span><span class="si">%d</span><span class="s">, fp=</span><span class="si">%s</span><span class="s">&#39;</span>
            <span class="o">%</span><span class="p">(</span><span class="n">sect</span><span class="p">,</span><span class="n">sect</span><span class="p">,</span><span class="n">size</span><span class="p">,</span><span class="n">offset</span><span class="p">,</span><span class="n">sectorsize</span><span class="p">,</span><span class="nb">len</span><span class="p">(</span><span class="n">fat</span><span class="p">),</span> <span class="nb">repr</span><span class="p">(</span><span class="n">fp</span><span class="p">)))</span>
        <span class="c">#[PL] To detect malformed documents with FAT loops, we compute the</span>
        <span class="c"># expected number of sectors in the stream:</span>
        <span class="n">unknown_size</span> <span class="o">=</span> <span class="bp">False</span>
        <span class="k">if</span> <span class="n">size</span><span class="o">==</span><span class="mh">0x7FFFFFFF</span><span class="p">:</span>
            <span class="c"># this is the case when called from OleFileIO._open(), and stream</span>
            <span class="c"># size is not known in advance (for example when reading the</span>
            <span class="c"># Directory stream). Then we can only guess maximum size:</span>
            <span class="n">size</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">fat</span><span class="p">)</span><span class="o">*</span><span class="n">sectorsize</span>
            <span class="c"># and we keep a record that size was unknown:</span>
            <span class="n">unknown_size</span> <span class="o">=</span> <span class="bp">True</span>
            <span class="n">debug</span><span class="p">(</span><span class="s">&#39;  stream with UNKNOWN SIZE&#39;</span><span class="p">)</span>
        <span class="n">nb_sectors</span> <span class="o">=</span> <span class="p">(</span><span class="n">size</span> <span class="o">+</span> <span class="p">(</span><span class="n">sectorsize</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span> <span class="o">//</span> <span class="n">sectorsize</span>
        <span class="n">debug</span><span class="p">(</span><span class="s">&#39;nb_sectors = </span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">nb_sectors</span><span class="p">)</span>
        <span class="c"># This number should (at least) be less than the total number of</span>
        <span class="c"># sectors in the given FAT:</span>
        <span class="k">if</span> <span class="n">nb_sectors</span> <span class="o">&gt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">fat</span><span class="p">):</span>
            <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">&#39;malformed OLE document, stream too large&#39;</span><span class="p">)</span>
        <span class="c"># optimization(?): data is first a list of strings, and join() is called</span>
        <span class="c"># at the end to concatenate all in one string.</span>
        <span class="c"># (this may not be really useful with recent Python versions)</span>
        <span class="n">data</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="c"># if size is zero, then first sector index should be ENDOFCHAIN:</span>
        <span class="k">if</span> <span class="n">size</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">sect</span> <span class="o">!=</span> <span class="n">ENDOFCHAIN</span><span class="p">:</span>
            <span class="n">debug</span><span class="p">(</span><span class="s">&#39;size == 0 and sect != ENDOFCHAIN:&#39;</span><span class="p">)</span>
            <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">&#39;incorrect OLE sector index for empty stream&#39;</span><span class="p">)</span>
        <span class="c">#[PL] A fixed-length for loop is used instead of an undefined while</span>
        <span class="c"># loop to avoid DoS attacks:</span>
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">nb_sectors</span><span class="p">):</span>
            <span class="c"># Sector index may be ENDOFCHAIN, but only if size was unknown</span>
            <span class="k">if</span> <span class="n">sect</span> <span class="o">==</span> <span class="n">ENDOFCHAIN</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">unknown_size</span><span class="p">:</span>
                    <span class="k">break</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="c"># else this means that the stream is smaller than declared:</span>
                    <span class="n">debug</span><span class="p">(</span><span class="s">&#39;sect=ENDOFCHAIN before expected size&#39;</span><span class="p">)</span>
                    <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">&#39;incomplete OLE stream&#39;</span><span class="p">)</span>
            <span class="c"># sector index should be within FAT:</span>
            <span class="k">if</span> <span class="n">sect</span><span class="o">&lt;</span><span class="mi">0</span> <span class="ow">or</span> <span class="n">sect</span><span class="o">&gt;=</span><span class="nb">len</span><span class="p">(</span><span class="n">fat</span><span class="p">):</span>
                <span class="n">debug</span><span class="p">(</span><span class="s">&#39;sect=</span><span class="si">%d</span><span class="s"> (</span><span class="si">%X</span><span class="s">) / len(fat)=</span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">sect</span><span class="p">,</span> <span class="n">sect</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">fat</span><span class="p">)))</span>
                <span class="n">debug</span><span class="p">(</span><span class="s">&#39;i=</span><span class="si">%d</span><span class="s"> / nb_sectors=</span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">nb_sectors</span><span class="p">))</span>
<span class="c">##                tmp_data = b&quot;&quot;.join(data)</span>
<span class="c">##                f = open(&#39;test_debug.bin&#39;, &#39;wb&#39;)</span>
<span class="c">##                f.write(tmp_data)</span>
<span class="c">##                f.close()</span>
<span class="c">##                debug(&#39;data read so far: %d bytes&#39; % len(tmp_data))</span>
                <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">&#39;incorrect OLE FAT, sector index out of range&#39;</span><span class="p">)</span>
            <span class="c">#TODO: merge this code with OleFileIO.getsect() ?</span>
            <span class="c">#TODO: check if this works with 4K sectors:</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="n">fp</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="n">offset</span> <span class="o">+</span> <span class="n">sectorsize</span> <span class="o">*</span> <span class="n">sect</span><span class="p">)</span>
            <span class="k">except</span><span class="p">:</span>
                <span class="n">debug</span><span class="p">(</span><span class="s">&#39;sect=</span><span class="si">%d</span><span class="s">, seek=</span><span class="si">%d</span><span class="s">, filesize=</span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span>
                    <span class="p">(</span><span class="n">sect</span><span class="p">,</span> <span class="n">offset</span><span class="o">+</span><span class="n">sectorsize</span><span class="o">*</span><span class="n">sect</span><span class="p">,</span> <span class="n">filesize</span><span class="p">))</span>
                <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">&#39;OLE sector index out of range&#39;</span><span class="p">)</span>
            <span class="n">sector_data</span> <span class="o">=</span> <span class="n">fp</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">sectorsize</span><span class="p">)</span>
            <span class="c"># [PL] check if there was enough data:</span>
            <span class="c"># Note: if sector is the last of the file, sometimes it is not a</span>
            <span class="c"># complete sector (of 512 or 4K), so we may read less than</span>
            <span class="c"># sectorsize.</span>
            <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sector_data</span><span class="p">)</span><span class="o">!=</span><span class="n">sectorsize</span> <span class="ow">and</span> <span class="n">sect</span><span class="o">!=</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">fat</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">):</span>
                <span class="n">debug</span><span class="p">(</span><span class="s">&#39;sect=</span><span class="si">%d</span><span class="s"> / len(fat)=</span><span class="si">%d</span><span class="s">, seek=</span><span class="si">%d</span><span class="s"> / filesize=</span><span class="si">%d</span><span class="s">, len read=</span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span>
                    <span class="p">(</span><span class="n">sect</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">fat</span><span class="p">),</span> <span class="n">offset</span><span class="o">+</span><span class="n">sectorsize</span><span class="o">*</span><span class="n">sect</span><span class="p">,</span> <span class="n">filesize</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">sector_data</span><span class="p">)))</span>
                <span class="n">debug</span><span class="p">(</span><span class="s">&#39;seek+len(read)=</span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">offset</span><span class="o">+</span><span class="n">sectorsize</span><span class="o">*</span><span class="n">sect</span><span class="o">+</span><span class="nb">len</span><span class="p">(</span><span class="n">sector_data</span><span class="p">)))</span>
                <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">&#39;incomplete OLE sector&#39;</span><span class="p">)</span>
            <span class="n">data</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">sector_data</span><span class="p">)</span>
            <span class="c"># jump to next sector in the FAT:</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="n">sect</span> <span class="o">=</span> <span class="n">fat</span><span class="p">[</span><span class="n">sect</span><span class="p">]</span>
            <span class="k">except</span> <span class="ne">IndexError</span><span class="p">:</span>
                <span class="c"># [PL] if pointer is out of the FAT an exception is raised</span>
                <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">&#39;incorrect OLE FAT, sector index out of range&#39;</span><span class="p">)</span>
        <span class="c">#[PL] Last sector should be a &quot;end of chain&quot; marker:</span>
        <span class="k">if</span> <span class="n">sect</span> <span class="o">!=</span> <span class="n">ENDOFCHAIN</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">&#39;incorrect last sector index in OLE stream&#39;</span><span class="p">)</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">b</span><span class="s">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
        <span class="c"># Data is truncated to the actual stream size:</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="n">size</span><span class="p">:</span>
            <span class="n">data</span> <span class="o">=</span> <span class="n">data</span><span class="p">[:</span><span class="n">size</span><span class="p">]</span>
            <span class="c"># actual stream size is stored for future use:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="o">=</span> <span class="n">size</span>
        <span class="k">elif</span> <span class="n">unknown_size</span><span class="p">:</span>
            <span class="c"># actual stream size was not known, now we know the size of read</span>
            <span class="c"># data:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="c"># read data is less than expected:</span>
            <span class="n">debug</span><span class="p">(</span><span class="s">&#39;len(data)=</span><span class="si">%d</span><span class="s">, size=</span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">),</span> <span class="n">size</span><span class="p">))</span>
            <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">&#39;OLE stream size is less than declared&#39;</span><span class="p">)</span>
        <span class="c"># when all data is read in memory, BytesIO constructor is called</span>
        <span class="n">io</span><span class="o">.</span><span class="n">BytesIO</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span>
        <span class="c"># Then the _OleStream object can be used as a read-only file object.</span>


<span class="c">#--- _OleDirectoryEntry -------------------------------------------------------</span>

<span class="k">class</span> <span class="nc">_OleDirectoryEntry</span><span class="p">:</span>

    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    OLE2 Directory Entry</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="c">#[PL] parsing code moved from OleFileIO.loaddirectory</span>

    <span class="c"># struct to parse directory entries:</span>
    <span class="c"># &lt;: little-endian byte order, standard sizes</span>
    <span class="c">#    (note: this should guarantee that Q returns a 64 bits int)</span>
    <span class="c"># 64s: string containing entry name in unicode (max 31 chars) + null char</span>
    <span class="c"># H: uint16, number of bytes used in name buffer, including null = (len+1)*2</span>
    <span class="c"># B: uint8, dir entry type (between 0 and 5)</span>
    <span class="c"># B: uint8, color: 0=black, 1=red</span>
    <span class="c"># I: uint32, index of left child node in the red-black tree, NOSTREAM if none</span>
    <span class="c"># I: uint32, index of right child node in the red-black tree, NOSTREAM if none</span>
    <span class="c"># I: uint32, index of child root node if it is a storage, else NOSTREAM</span>
    <span class="c"># 16s: CLSID, unique identifier (only used if it is a storage)</span>
    <span class="c"># I: uint32, user flags</span>
    <span class="c"># Q (was 8s): uint64, creation timestamp or zero</span>
    <span class="c"># Q (was 8s): uint64, modification timestamp or zero</span>
    <span class="c"># I: uint32, SID of first sector if stream or ministream, SID of 1st sector</span>
    <span class="c">#    of stream containing ministreams if root entry, 0 otherwise</span>
    <span class="c"># I: uint32, total stream size in bytes if stream (low 32 bits), 0 otherwise</span>
    <span class="c"># I: uint32, total stream size in bytes if stream (high 32 bits), 0 otherwise</span>
    <span class="n">STRUCT_DIRENTRY</span> <span class="o">=</span> <span class="s">&#39;&lt;64sHBBIII16sIQQIII&#39;</span>
    <span class="c"># size of a directory entry: 128 bytes</span>
    <span class="n">DIRENTRY_SIZE</span> <span class="o">=</span> <span class="mi">128</span>
    <span class="k">assert</span> <span class="n">struct</span><span class="o">.</span><span class="n">calcsize</span><span class="p">(</span><span class="n">STRUCT_DIRENTRY</span><span class="p">)</span> <span class="o">==</span> <span class="n">DIRENTRY_SIZE</span>


    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entry</span><span class="p">,</span> <span class="n">sid</span><span class="p">,</span> <span class="n">olefile</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Constructor for an _OleDirectoryEntry object.</span>
<span class="sd">        Parses a 128-bytes entry from the OLE Directory stream.</span>

<span class="sd">        :param entry  : string (must be 128 bytes long)</span>
<span class="sd">        :param sid    : index of this directory entry in the OLE file directory</span>
<span class="sd">        :param olefile: OleFileIO containing this directory entry</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">sid</span> <span class="o">=</span> <span class="n">sid</span>
        <span class="c"># ref to olefile is stored for future use</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">olefile</span> <span class="o">=</span> <span class="n">olefile</span>
        <span class="c"># kids is a list of children entries, if this entry is a storage:</span>
        <span class="c"># (list of _OleDirectoryEntry objects)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">kids</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="c"># kids_dict is a dictionary of children entries, indexed by their</span>
        <span class="c"># name in lowercase: used to quickly find an entry, and to detect</span>
        <span class="c"># duplicates</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">kids_dict</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="c"># flag used to detect if the entry is referenced more than once in</span>
        <span class="c"># directory:</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">used</span> <span class="o">=</span> <span class="bp">False</span>
        <span class="c"># decode DirEntry</span>
        <span class="p">(</span>
            <span class="n">name</span><span class="p">,</span>
            <span class="n">namelength</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">color</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">sid_left</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">sid_right</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">sid_child</span><span class="p">,</span>
            <span class="n">clsid</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">dwUserFlags</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">createTime</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">modifyTime</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">isectStart</span><span class="p">,</span>
            <span class="n">sizeLow</span><span class="p">,</span>
            <span class="n">sizeHigh</span>
        <span class="p">)</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">unpack</span><span class="p">(</span><span class="n">_OleDirectoryEntry</span><span class="o">.</span><span class="n">STRUCT_DIRENTRY</span><span class="p">,</span> <span class="n">entry</span><span class="p">)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="n">STGTY_ROOT</span><span class="p">,</span> <span class="n">STGTY_STORAGE</span><span class="p">,</span> <span class="n">STGTY_STREAM</span><span class="p">,</span> <span class="n">STGTY_EMPTY</span><span class="p">]:</span>
            <span class="n">olefile</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span> <span class="s">&#39;unhandled OLE storage type&#39;</span><span class="p">)</span>
        <span class="c"># only first directory entry can (and should) be root:</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span> <span class="o">==</span> <span class="n">STGTY_ROOT</span> <span class="ow">and</span> <span class="n">sid</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">olefile</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span> <span class="s">&#39;duplicate OLE root entry&#39;</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">sid</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span> <span class="o">!=</span> <span class="n">STGTY_ROOT</span><span class="p">:</span>
            <span class="n">olefile</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span> <span class="s">&#39;incorrect OLE root entry&#39;</span><span class="p">)</span>
        <span class="c">#debug (struct.unpack(fmt_entry, entry[:len_entry]))</span>
        <span class="c"># name should be at most 31 unicode characters + null character,</span>
        <span class="c"># so 64 bytes in total (31*2 + 2):</span>
        <span class="k">if</span> <span class="n">namelength</span><span class="o">&gt;</span><span class="mi">64</span><span class="p">:</span>
            <span class="n">olefile</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span> <span class="s">&#39;incorrect DirEntry name length&#39;</span><span class="p">)</span>
            <span class="c"># if exception not raised, namelength is set to the maximum value:</span>
            <span class="n">namelength</span> <span class="o">=</span> <span class="mi">64</span>
        <span class="c"># only characters without ending null char are kept:</span>
        <span class="n">name</span> <span class="o">=</span> <span class="n">name</span><span class="p">[:(</span><span class="n">namelength</span><span class="o">-</span><span class="mi">2</span><span class="p">)]</span>
        <span class="c"># name is converted from unicode to Latin-1:</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">_unicode</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>

        <span class="n">debug</span><span class="p">(</span><span class="s">&#39;DirEntry SID=</span><span class="si">%d</span><span class="s">: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sid</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)))</span>
        <span class="n">debug</span><span class="p">(</span><span class="s">&#39; - type: </span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span><span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span><span class="s">&#39; - sect: </span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">isectStart</span><span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span><span class="s">&#39; - SID left: </span><span class="si">%d</span><span class="s">, right: </span><span class="si">%d</span><span class="s">, child: </span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sid_left</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">sid_right</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">sid_child</span><span class="p">))</span>

        <span class="c"># sizeHigh is only used for 4K sectors, it should be zero for 512 bytes</span>
        <span class="c"># sectors, BUT apparently some implementations set it as 0xFFFFFFFF, 1</span>
        <span class="c"># or some other value so it cannot be raised as a defect in general:</span>
        <span class="k">if</span> <span class="n">olefile</span><span class="o">.</span><span class="n">sectorsize</span> <span class="o">==</span> <span class="mi">512</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">sizeHigh</span> <span class="o">!=</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">sizeHigh</span> <span class="o">!=</span> <span class="mh">0xFFFFFFFF</span><span class="p">:</span>
                <span class="n">debug</span><span class="p">(</span><span class="s">&#39;sectorsize=</span><span class="si">%d</span><span class="s">, sizeLow=</span><span class="si">%d</span><span class="s">, sizeHigh=</span><span class="si">%d</span><span class="s"> (</span><span class="si">%X</span><span class="s">)&#39;</span> <span class="o">%</span>
                    <span class="p">(</span><span class="n">olefile</span><span class="o">.</span><span class="n">sectorsize</span><span class="p">,</span> <span class="n">sizeLow</span><span class="p">,</span> <span class="n">sizeHigh</span><span class="p">,</span> <span class="n">sizeHigh</span><span class="p">))</span>
                <span class="n">olefile</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_UNSURE</span><span class="p">,</span> <span class="s">&#39;incorrect OLE stream size&#39;</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="o">=</span> <span class="n">sizeLow</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="o">=</span> <span class="n">sizeLow</span> <span class="o">+</span> <span class="p">(</span><span class="nb">long</span><span class="p">(</span><span class="n">sizeHigh</span><span class="p">)</span><span class="o">&lt;&lt;</span><span class="mi">32</span><span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span><span class="s">&#39; - size: </span><span class="si">%d</span><span class="s"> (sizeLow=</span><span class="si">%d</span><span class="s">, sizeHigh=</span><span class="si">%d</span><span class="s">)&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">,</span> <span class="n">sizeLow</span><span class="p">,</span> <span class="n">sizeHigh</span><span class="p">))</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">clsid</span> <span class="o">=</span> <span class="n">_clsid</span><span class="p">(</span><span class="n">clsid</span><span class="p">)</span>
        <span class="c"># a storage should have a null size, BUT some implementations such as</span>
        <span class="c"># Word 8 for Mac seem to allow non-null values =&gt; Potential defect:</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span> <span class="o">==</span> <span class="n">STGTY_STORAGE</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">olefile</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_POTENTIAL</span><span class="p">,</span> <span class="s">&#39;OLE storage with size&gt;0&#39;</span><span class="p">)</span>
        <span class="c"># check if stream is not already referenced elsewhere:</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span> <span class="ow">in</span> <span class="p">(</span><span class="n">STGTY_ROOT</span><span class="p">,</span> <span class="n">STGTY_STREAM</span><span class="p">)</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="o">&gt;</span><span class="mi">0</span><span class="p">:</span>
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="o">&lt;</span> <span class="n">olefile</span><span class="o">.</span><span class="n">minisectorcutoff</span> \
            <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span><span class="o">==</span><span class="n">STGTY_STREAM</span><span class="p">:</span> <span class="c"># only streams can be in MiniFAT</span>
                <span class="c"># ministream object</span>
                <span class="n">minifat</span> <span class="o">=</span> <span class="bp">True</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">minifat</span> <span class="o">=</span> <span class="bp">False</span>
            <span class="n">olefile</span><span class="o">.</span><span class="n">_check_duplicate_stream</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">isectStart</span><span class="p">,</span> <span class="n">minifat</span><span class="p">)</span>



    <span class="k">def</span> <span class="nf">build_storage_tree</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Read and build the red-black tree attached to this _OleDirectoryEntry</span>
<span class="sd">        object, if it is a storage.</span>
<span class="sd">        Note that this method builds a tree of all subentries, so it should</span>
<span class="sd">        only be called for the root object once.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">debug</span><span class="p">(</span><span class="s">&#39;build_storage_tree: SID=</span><span class="si">%d</span><span class="s"> - </span><span class="si">%s</span><span class="s"> - sid_child=</span><span class="si">%d</span><span class="s">&#39;</span>
            <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sid</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">sid_child</span><span class="p">))</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">sid_child</span> <span class="o">!=</span> <span class="n">NOSTREAM</span><span class="p">:</span>
            <span class="c"># if child SID is not NOSTREAM, then this entry is a storage.</span>
            <span class="c"># Let&#39;s walk through the tree of children to fill the kids list:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">append_kids</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sid_child</span><span class="p">)</span>

            <span class="c"># Note from OpenOffice documentation: the safest way is to</span>
            <span class="c"># recreate the tree because some implementations may store broken</span>
            <span class="c"># red-black trees...</span>

            <span class="c"># in the OLE file, entries are sorted on (length, name).</span>
            <span class="c"># for convenience, we sort them on name instead:</span>
            <span class="c"># (see rich comparison methods in this class)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">kids</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span>


    <span class="k">def</span> <span class="nf">append_kids</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">child_sid</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Walk through red-black tree of children of this directory entry to add</span>
<span class="sd">        all of them to the kids list. (recursive method)</span>

<span class="sd">        child_sid : index of child directory entry to use, or None when called</span>
<span class="sd">                    first time for the root. (only used during recursion)</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c">#[PL] this method was added to use simple recursion instead of a complex</span>
        <span class="c"># algorithm.</span>
        <span class="c"># if this is not a storage or a leaf of the tree, nothing to do:</span>
        <span class="k">if</span> <span class="n">child_sid</span> <span class="o">==</span> <span class="n">NOSTREAM</span><span class="p">:</span>
            <span class="k">return</span>
        <span class="c"># check if child SID is in the proper range:</span>
        <span class="k">if</span> <span class="n">child_sid</span><span class="o">&lt;</span><span class="mi">0</span> <span class="ow">or</span> <span class="n">child_sid</span><span class="o">&gt;=</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">olefile</span><span class="o">.</span><span class="n">direntries</span><span class="p">):</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">olefile</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_FATAL</span><span class="p">,</span> <span class="s">&#39;OLE DirEntry index out of range&#39;</span><span class="p">)</span>
        <span class="c"># get child direntry:</span>
        <span class="n">child</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">olefile</span><span class="o">.</span><span class="n">_load_direntry</span><span class="p">(</span><span class="n">child_sid</span><span class="p">)</span> <span class="c">#direntries[child_sid]</span>
        <span class="n">debug</span><span class="p">(</span><span class="s">&#39;append_kids: child_sid=</span><span class="si">%d</span><span class="s"> - </span><span class="si">%s</span><span class="s"> - sid_left=</span><span class="si">%d</span><span class="s">, sid_right=</span><span class="si">%d</span><span class="s">, sid_child=</span><span class="si">%d</span><span class="s">&#39;</span>
            <span class="o">%</span> <span class="p">(</span><span class="n">child</span><span class="o">.</span><span class="n">sid</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">child</span><span class="o">.</span><span class="n">name</span><span class="p">),</span> <span class="n">child</span><span class="o">.</span><span class="n">sid_left</span><span class="p">,</span> <span class="n">child</span><span class="o">.</span><span class="n">sid_right</span><span class="p">,</span> <span class="n">child</span><span class="o">.</span><span class="n">sid_child</span><span class="p">))</span>
        <span class="c"># the directory entries are organized as a red-black tree.</span>
        <span class="c"># (cf. Wikipedia for details)</span>
        <span class="c"># First walk through left side of the tree:</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">append_kids</span><span class="p">(</span><span class="n">child</span><span class="o">.</span><span class="n">sid_left</span><span class="p">)</span>
        <span class="c"># Check if its name is not already used (case-insensitive):</span>
        <span class="n">name_lower</span> <span class="o">=</span> <span class="n">child</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
        <span class="k">if</span> <span class="n">name_lower</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">kids_dict</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">olefile</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span>
                <span class="s">&quot;Duplicate filename in OLE storage&quot;</span><span class="p">)</span>
        <span class="c"># Then the child_sid _OleDirectoryEntry object is appended to the</span>
        <span class="c"># kids list and dictionary:</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">kids</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">child</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">kids_dict</span><span class="p">[</span><span class="n">name_lower</span><span class="p">]</span> <span class="o">=</span> <span class="n">child</span>
        <span class="c"># Check if kid was not already referenced in a storage:</span>
        <span class="k">if</span> <span class="n">child</span><span class="o">.</span><span class="n">used</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">olefile</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span>
                <span class="s">&#39;OLE Entry referenced more than once&#39;</span><span class="p">)</span>
        <span class="n">child</span><span class="o">.</span><span class="n">used</span> <span class="o">=</span> <span class="bp">True</span>
        <span class="c"># Finally walk through right side of the tree:</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">append_kids</span><span class="p">(</span><span class="n">child</span><span class="o">.</span><span class="n">sid_right</span><span class="p">)</span>
        <span class="c"># Afterwards build kid&#39;s own tree if it&#39;s also a storage:</span>
        <span class="n">child</span><span class="o">.</span><span class="n">build_storage_tree</span><span class="p">()</span>


    <span class="k">def</span> <span class="nf">__eq__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
        <span class="s">&quot;Compare entries by name&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="n">other</span><span class="o">.</span><span class="n">name</span>

    <span class="k">def</span> <span class="nf">__lt__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
        <span class="s">&quot;Compare entries by name&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">&lt;</span> <span class="n">other</span><span class="o">.</span><span class="n">name</span>

    <span class="k">def</span> <span class="nf">__ne__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
        <span class="k">return</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">__eq__</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">__le__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__eq__</span><span class="p">(</span><span class="n">other</span><span class="p">)</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">__lt__</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>

    <span class="c"># Reflected __lt__() and __le__() will be used for __gt__() and __ge__()</span>

    <span class="c">#TODO: replace by the same function as MS implementation ?</span>
    <span class="c"># (order by name length first, then case-insensitive order)</span>


    <span class="k">def</span> <span class="nf">dump</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tab</span> <span class="o">=</span> <span class="mi">0</span><span class="p">):</span>
        <span class="s">&quot;Dump this entry, and all its subentries (for debug purposes only)&quot;</span>
        <span class="n">TYPES</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;(invalid)&quot;</span><span class="p">,</span> <span class="s">&quot;(storage)&quot;</span><span class="p">,</span> <span class="s">&quot;(stream)&quot;</span><span class="p">,</span> <span class="s">&quot;(lockbytes)&quot;</span><span class="p">,</span>
                 <span class="s">&quot;(property)&quot;</span><span class="p">,</span> <span class="s">&quot;(root)&quot;</span><span class="p">]</span>
        <span class="k">print</span><span class="p">(</span><span class="s">&quot; &quot;</span><span class="o">*</span><span class="n">tab</span> <span class="o">+</span> <span class="nb">repr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">),</span> <span class="n">TYPES</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span><span class="p">],</span> <span class="n">end</span><span class="o">=</span><span class="s">&#39; &#39;</span><span class="p">)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span> <span class="ow">in</span> <span class="p">(</span><span class="n">STGTY_STREAM</span><span class="p">,</span> <span class="n">STGTY_ROOT</span><span class="p">):</span>
            <span class="k">print</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">,</span> <span class="s">&quot;bytes&quot;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s">&#39; &#39;</span><span class="p">)</span>
        <span class="k">print</span><span class="p">()</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span> <span class="ow">in</span> <span class="p">(</span><span class="n">STGTY_STORAGE</span><span class="p">,</span> <span class="n">STGTY_ROOT</span><span class="p">)</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">clsid</span><span class="p">:</span>
            <span class="k">print</span><span class="p">(</span><span class="s">&quot; &quot;</span><span class="o">*</span><span class="n">tab</span> <span class="o">+</span> <span class="s">&quot;{</span><span class="si">%s</span><span class="s">}&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">clsid</span><span class="p">)</span>

        <span class="k">for</span> <span class="n">kid</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">kids</span><span class="p">:</span>
            <span class="n">kid</span><span class="o">.</span><span class="n">dump</span><span class="p">(</span><span class="n">tab</span> <span class="o">+</span> <span class="mi">2</span><span class="p">)</span>


    <span class="k">def</span> <span class="nf">getmtime</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return modification time of a directory entry.</span>

<span class="sd">        :returns: None if modification time is null, a python datetime object</span>
<span class="sd">        otherwise (UTC timezone)</span>

<span class="sd">        new in version 0.26</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">modifyTime</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">None</span>
        <span class="k">return</span> <span class="n">filetime2datetime</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">modifyTime</span><span class="p">)</span>


    <span class="k">def</span> <span class="nf">getctime</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return creation time of a directory entry.</span>

<span class="sd">        :returns: None if modification time is null, a python datetime object</span>
<span class="sd">        otherwise (UTC timezone)</span>

<span class="sd">        new in version 0.26</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">createTime</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">None</span>
        <span class="k">return</span> <span class="n">filetime2datetime</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">createTime</span><span class="p">)</span>


<span class="c">#--- OleFileIO ----------------------------------------------------------------</span>

<div class="viewcode-block" id="OleFileIO"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO">[docs]</a><span class="k">class</span> <span class="nc">OleFileIO</span><span class="p">:</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    OLE container object</span>

<span class="sd">    This class encapsulates the interface to an OLE 2 structured</span>
<span class="sd">    storage file.  Use the :py:meth:`~PIL.OleFileIO.OleFileIO.listdir` and</span>
<span class="sd">    :py:meth:`~PIL.OleFileIO.OleFileIO.openstream` methods to</span>
<span class="sd">    access the contents of this file.</span>

<span class="sd">    Object names are given as a list of strings, one for each subentry</span>
<span class="sd">    level.  The root entry should be omitted.  For example, the following</span>
<span class="sd">    code extracts all image streams from a Microsoft Image Composer file::</span>

<span class="sd">        ole = OleFileIO(&quot;fan.mic&quot;)</span>

<span class="sd">        for entry in ole.listdir():</span>
<span class="sd">            if entry[1:2] == &quot;Image&quot;:</span>
<span class="sd">                fin = ole.openstream(entry)</span>
<span class="sd">                fout = open(entry[0:1], &quot;wb&quot;)</span>
<span class="sd">                while True:</span>
<span class="sd">                    s = fin.read(8192)</span>
<span class="sd">                    if not s:</span>
<span class="sd">                        break</span>
<span class="sd">                    fout.write(s)</span>

<span class="sd">    You can use the viewer application provided with the Python Imaging</span>
<span class="sd">    Library to view the resulting files (which happens to be standard</span>
<span class="sd">    TIFF files).</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">raise_defects</span><span class="o">=</span><span class="n">DEFECT_FATAL</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Constructor for OleFileIO class.</span>

<span class="sd">        :param filename: file to open.</span>
<span class="sd">        :param raise_defects: minimal level for defects to be raised as exceptions.</span>
<span class="sd">        (use DEFECT_FATAL for a typical application, DEFECT_INCORRECT for a</span>
<span class="sd">        security-oriented application, see source code for details)</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c"># minimal level for defects to be raised as exceptions:</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defects_level</span> <span class="o">=</span> <span class="n">raise_defects</span>
        <span class="c"># list of defects/issues not raised as exceptions:</span>
        <span class="c"># tuples of (exception type, message)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">parsing_issues</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">if</span> <span class="n">filename</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>


    <span class="k">def</span> <span class="nf">_raise_defect</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">defect_level</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">exception_type</span><span class="o">=</span><span class="ne">IOError</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        This method should be called for any defect found during file parsing.</span>
<span class="sd">        It may raise an IOError exception according to the minimal level chosen</span>
<span class="sd">        for the OleFileIO object.</span>

<span class="sd">        :param defect_level: defect level, possible values are:</span>
<span class="sd">            DEFECT_UNSURE    : a case which looks weird, but not sure it&#39;s a defect</span>
<span class="sd">            DEFECT_POTENTIAL : a potential defect</span>
<span class="sd">            DEFECT_INCORRECT : an error according to specifications, but parsing can go on</span>
<span class="sd">            DEFECT_FATAL     : an error which cannot be ignored, parsing is impossible</span>
<span class="sd">        :param message: string describing the defect, used with raised exception.</span>
<span class="sd">        :param exception_type: exception class to be raised, IOError by default</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c"># added by [PL]</span>
        <span class="k">if</span> <span class="n">defect_level</span> <span class="o">&gt;=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defects_level</span><span class="p">:</span>
            <span class="k">raise</span> <span class="n">exception_type</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="c"># just record the issue, no exception raised:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">parsing_issues</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">exception_type</span><span class="p">,</span> <span class="n">message</span><span class="p">))</span>


<div class="viewcode-block" id="OleFileIO.open"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.open">[docs]</a>    <span class="k">def</span> <span class="nf">open</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Open an OLE2 file.</span>
<span class="sd">        Reads the header, FAT and directory.</span>

<span class="sd">        :param filename: string-like or file-like object</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c">#[PL] check if filename is a string-like or file-like object:</span>
        <span class="c"># (it is better to check for a read() method)</span>
        <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="s">&#39;read&#39;</span><span class="p">):</span>
            <span class="c"># file-like object</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">fp</span> <span class="o">=</span> <span class="n">filename</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="c"># string-like object: filename of file on disk</span>
            <span class="c">#TODO: if larger than 1024 bytes, this could be the actual data =&gt; BytesIO</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">fp</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="s">&quot;rb&quot;</span><span class="p">)</span>
        <span class="c"># old code fails if filename is not a plain string:</span>
        <span class="c">#if isinstance(filename, (bytes, basestring)):</span>
        <span class="c">#    self.fp = open(filename, &quot;rb&quot;)</span>
        <span class="c">#else:</span>
        <span class="c">#    self.fp = filename</span>
        <span class="c"># obtain the filesize by using seek and tell, which should work on most</span>
        <span class="c"># file-like objects:</span>
        <span class="c">#TODO: do it above, using getsize with filename when possible?</span>
        <span class="c">#TODO: fix code to fail with clear exception when filesize cannot be obtained</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">fp</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">SEEK_END</span><span class="p">)</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">filesize</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">fp</span><span class="o">.</span><span class="n">tell</span><span class="p">()</span>
        <span class="k">finally</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">fp</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_filesize</span> <span class="o">=</span> <span class="n">filesize</span>

        <span class="c"># lists of streams in FAT and MiniFAT, to detect duplicate references</span>
        <span class="c"># (list of indexes of first sectors of each stream)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_used_streams_fat</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_used_streams_minifat</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="n">header</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">fp</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="mi">512</span><span class="p">)</span>

        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">header</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">512</span> <span class="ow">or</span> <span class="n">header</span><span class="p">[:</span><span class="mi">8</span><span class="p">]</span> <span class="o">!=</span> <span class="n">MAGIC</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_FATAL</span><span class="p">,</span> <span class="s">&quot;not an OLE2 structured storage file&quot;</span><span class="p">)</span>

        <span class="c"># [PL] header structure according to AAF specifications:</span>
        <span class="c">##Header</span>
        <span class="c">##struct StructuredStorageHeader { // [offset from start (bytes), length (bytes)]</span>
        <span class="c">##BYTE _abSig[8]; // [00H,08] {0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1,</span>
        <span class="c">##                // 0x1a, 0xe1} for current version</span>
        <span class="c">##CLSID _clsid;   // [08H,16] reserved must be zero (WriteClassStg/</span>
        <span class="c">##                // GetClassFile uses root directory class id)</span>
        <span class="c">##USHORT _uMinorVersion; // [18H,02] minor version of the format: 33 is</span>
        <span class="c">##                       // written by reference implementation</span>
        <span class="c">##USHORT _uDllVersion;   // [1AH,02] major version of the dll/format: 3 for</span>
        <span class="c">##                       // 512-byte sectors, 4 for 4 KB sectors</span>
        <span class="c">##USHORT _uByteOrder;    // [1CH,02] 0xFFFE: indicates Intel byte-ordering</span>
        <span class="c">##USHORT _uSectorShift;  // [1EH,02] size of sectors in power-of-two;</span>
        <span class="c">##                       // typically 9 indicating 512-byte sectors</span>
        <span class="c">##USHORT _uMiniSectorShift; // [20H,02] size of mini-sectors in power-of-two;</span>
        <span class="c">##                          // typically 6 indicating 64-byte mini-sectors</span>
        <span class="c">##USHORT _usReserved; // [22H,02] reserved, must be zero</span>
        <span class="c">##ULONG _ulReserved1; // [24H,04] reserved, must be zero</span>
        <span class="c">##FSINDEX _csectDir; // [28H,04] must be zero for 512-byte sectors,</span>
        <span class="c">##                   // number of SECTs in directory chain for 4 KB</span>
        <span class="c">##                   // sectors</span>
        <span class="c">##FSINDEX _csectFat; // [2CH,04] number of SECTs in the FAT chain</span>
        <span class="c">##SECT _sectDirStart; // [30H,04] first SECT in the directory chain</span>
        <span class="c">##DFSIGNATURE _signature; // [34H,04] signature used for transactions; must</span>
        <span class="c">##                        // be zero. The reference implementation</span>
        <span class="c">##                        // does not support transactions</span>
        <span class="c">##ULONG _ulMiniSectorCutoff; // [38H,04] maximum size for a mini stream;</span>
        <span class="c">##                           // typically 4096 bytes</span>
        <span class="c">##SECT _sectMiniFatStart; // [3CH,04] first SECT in the MiniFAT chain</span>
        <span class="c">##FSINDEX _csectMiniFat; // [40H,04] number of SECTs in the MiniFAT chain</span>
        <span class="c">##SECT _sectDifStart; // [44H,04] first SECT in the DIFAT chain</span>
        <span class="c">##FSINDEX _csectDif; // [48H,04] number of SECTs in the DIFAT chain</span>
        <span class="c">##SECT _sectFat[109]; // [4CH,436] the SECTs of first 109 FAT sectors</span>
        <span class="c">##};</span>

        <span class="c"># [PL] header decoding:</span>
        <span class="c"># &#39;&lt;&#39; indicates little-endian byte ordering for Intel (cf. struct module help)</span>
        <span class="n">fmt_header</span> <span class="o">=</span> <span class="s">&#39;&lt;8s16sHHHHHHLLLLLLLLLL&#39;</span>
        <span class="n">header_size</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">calcsize</span><span class="p">(</span><span class="n">fmt_header</span><span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;fmt_header size = </span><span class="si">%d</span><span class="s">, +FAT = </span><span class="si">%d</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">header_size</span><span class="p">,</span> <span class="n">header_size</span> <span class="o">+</span> <span class="mi">109</span><span class="o">*</span><span class="mi">4</span><span class="p">)</span> <span class="p">)</span>
        <span class="n">header1</span> <span class="o">=</span> <span class="n">header</span><span class="p">[:</span><span class="n">header_size</span><span class="p">]</span>
        <span class="p">(</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">Sig</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">clsid</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">MinorVersion</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">DllVersion</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">ByteOrder</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">SectorShift</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">MiniSectorShift</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">Reserved</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">Reserved1</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">csectDir</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">csectFat</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">sectDirStart</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">signature</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">MiniSectorCutoff</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">MiniFatStart</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">csectMiniFat</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">sectDifStart</span><span class="p">,</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">csectDif</span>
        <span class="p">)</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">unpack</span><span class="p">(</span><span class="n">fmt_header</span><span class="p">,</span> <span class="n">header1</span><span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span> <span class="n">struct</span><span class="o">.</span><span class="n">unpack</span><span class="p">(</span><span class="n">fmt_header</span><span class="p">,</span>    <span class="n">header1</span><span class="p">))</span>

        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">Sig</span> <span class="o">!=</span> <span class="n">MAGIC</span><span class="p">:</span>
            <span class="c"># OLE signature should always be present</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_FATAL</span><span class="p">,</span> <span class="s">&quot;incorrect OLE signature&quot;</span><span class="p">)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">clsid</span> <span class="o">!=</span> <span class="nb">bytearray</span><span class="p">(</span><span class="mi">16</span><span class="p">):</span>
            <span class="c"># according to AAF specs, CLSID should always be zero</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span> <span class="s">&quot;incorrect CLSID in OLE header&quot;</span><span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;MinorVersion = </span><span class="si">%d</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">MinorVersion</span> <span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;DllVersion   = </span><span class="si">%d</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">DllVersion</span> <span class="p">)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">DllVersion</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">]:</span>
            <span class="c"># version 3: usual format, 512 bytes per sector</span>
            <span class="c"># version 4: large format, 4K per sector</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span> <span class="s">&quot;incorrect DllVersion in OLE header&quot;</span><span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;ByteOrder    = </span><span class="si">%X</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">ByteOrder</span> <span class="p">)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">ByteOrder</span> <span class="o">!=</span> <span class="mh">0xFFFE</span><span class="p">:</span>
            <span class="c"># For now only common little-endian documents are handled correctly</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_FATAL</span><span class="p">,</span> <span class="s">&quot;incorrect ByteOrder in OLE header&quot;</span><span class="p">)</span>
            <span class="c"># TODO: add big-endian support for documents created on Mac ?</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">SectorSize</span> <span class="o">=</span> <span class="mi">2</span><span class="o">**</span><span class="bp">self</span><span class="o">.</span><span class="n">SectorShift</span>
        <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;SectorSize   = </span><span class="si">%d</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">SectorSize</span> <span class="p">)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">SectorSize</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">512</span><span class="p">,</span> <span class="mi">4096</span><span class="p">]:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span> <span class="s">&quot;incorrect SectorSize in OLE header&quot;</span><span class="p">)</span>
        <span class="k">if</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">DllVersion</span><span class="o">==</span><span class="mi">3</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">SectorSize</span><span class="o">!=</span><span class="mi">512</span><span class="p">)</span> \
        <span class="ow">or</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">DllVersion</span><span class="o">==</span><span class="mi">4</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">SectorSize</span><span class="o">!=</span><span class="mi">4096</span><span class="p">):</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span> <span class="s">&quot;SectorSize does not match DllVersion in OLE header&quot;</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">MiniSectorSize</span> <span class="o">=</span> <span class="mi">2</span><span class="o">**</span><span class="bp">self</span><span class="o">.</span><span class="n">MiniSectorShift</span>
        <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;MiniSectorSize   = </span><span class="si">%d</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">MiniSectorSize</span> <span class="p">)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">MiniSectorSize</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">64</span><span class="p">]:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span> <span class="s">&quot;incorrect MiniSectorSize in OLE header&quot;</span><span class="p">)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">Reserved</span> <span class="o">!=</span> <span class="mi">0</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">Reserved1</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span> <span class="s">&quot;incorrect OLE header (non-null reserved bytes)&quot;</span><span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;csectDir     = </span><span class="si">%d</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">csectDir</span> <span class="p">)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">SectorSize</span><span class="o">==</span><span class="mi">512</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">csectDir</span><span class="o">!=</span><span class="mi">0</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span> <span class="s">&quot;incorrect csectDir in OLE header&quot;</span><span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;csectFat     = </span><span class="si">%d</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">csectFat</span> <span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;sectDirStart = </span><span class="si">%X</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">sectDirStart</span> <span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;signature    = </span><span class="si">%d</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">signature</span> <span class="p">)</span>
        <span class="c"># Signature should be zero, BUT some implementations do not follow this</span>
        <span class="c"># rule =&gt; only a potential defect:</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">signature</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_POTENTIAL</span><span class="p">,</span> <span class="s">&quot;incorrect OLE header (signature&gt;0)&quot;</span><span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;MiniSectorCutoff = </span><span class="si">%d</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">MiniSectorCutoff</span> <span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;MiniFatStart     = </span><span class="si">%X</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">MiniFatStart</span> <span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;csectMiniFat     = </span><span class="si">%d</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">csectMiniFat</span> <span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;sectDifStart     = </span><span class="si">%X</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">sectDifStart</span> <span class="p">)</span>
        <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;csectDif         = </span><span class="si">%d</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">csectDif</span> <span class="p">)</span>

        <span class="c"># calculate the number of sectors in the file</span>
        <span class="c"># (-1 because header doesn&#39;t count)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">nb_sect</span> <span class="o">=</span> <span class="p">(</span> <span class="p">(</span><span class="n">filesize</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">SectorSize</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">//</span> <span class="bp">self</span><span class="o">.</span><span class="n">SectorSize</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>
        <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;Number of sectors in the file: </span><span class="si">%d</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">nb_sect</span> <span class="p">)</span>

        <span class="c"># file clsid (probably never used, so we don&#39;t store it)</span>
        <span class="n">clsid</span> <span class="o">=</span> <span class="n">_clsid</span><span class="p">(</span><span class="n">header</span><span class="p">[</span><span class="mi">8</span><span class="p">:</span><span class="mi">24</span><span class="p">])</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">sectorsize</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">SectorSize</span> <span class="c">#1 &lt;&lt; i16(header, 30)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">minisectorsize</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">MiniSectorSize</span>  <span class="c">#1 &lt;&lt; i16(header, 32)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">minisectorcutoff</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">MiniSectorCutoff</span> <span class="c"># i32(header, 56)</span>

        <span class="c"># check known streams for duplicate references (these are always in FAT,</span>
        <span class="c"># never in MiniFAT):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_check_duplicate_stream</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sectDirStart</span><span class="p">)</span>
        <span class="c"># check MiniFAT only if it is not empty:</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">csectMiniFat</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_check_duplicate_stream</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">MiniFatStart</span><span class="p">)</span>
        <span class="c"># check DIFAT only if it is not empty:</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">csectDif</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_check_duplicate_stream</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sectDifStart</span><span class="p">)</span>

        <span class="c"># Load file allocation tables</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">loadfat</span><span class="p">(</span><span class="n">header</span><span class="p">)</span>
        <span class="c"># Load direcory.  This sets both the direntries list (ordered by sid)</span>
        <span class="c"># and the root (ordered by hierarchy) members.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">loaddirectory</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sectDirStart</span><span class="p">)</span><span class="c">#i32(header, 48))</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">ministream</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">minifatsect</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">MiniFatStart</span> <span class="c">#i32(header, 60)</span>

</div>
<div class="viewcode-block" id="OleFileIO.close"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.close">[docs]</a>    <span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        close the OLE file, to release the file object</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">fp</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>

</div>
    <span class="k">def</span> <span class="nf">_check_duplicate_stream</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">first_sect</span><span class="p">,</span> <span class="n">minifat</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Checks if a stream has not been already referenced elsewhere.</span>
<span class="sd">        This method should only be called once for each known stream, and only</span>
<span class="sd">        if stream size is not null.</span>
<span class="sd">        :param first_sect: index of first sector of the stream in FAT</span>
<span class="sd">        :param minifat: if True, stream is located in the MiniFAT, else in the FAT</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="n">minifat</span><span class="p">:</span>
            <span class="n">debug</span><span class="p">(</span><span class="s">&#39;_check_duplicate_stream: sect=</span><span class="si">%d</span><span class="s"> in MiniFAT&#39;</span> <span class="o">%</span> <span class="n">first_sect</span><span class="p">)</span>
            <span class="n">used_streams</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_used_streams_minifat</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">debug</span><span class="p">(</span><span class="s">&#39;_check_duplicate_stream: sect=</span><span class="si">%d</span><span class="s"> in FAT&#39;</span> <span class="o">%</span> <span class="n">first_sect</span><span class="p">)</span>
            <span class="c"># some values can be safely ignored (not a real stream):</span>
            <span class="k">if</span> <span class="n">first_sect</span> <span class="ow">in</span> <span class="p">(</span><span class="n">DIFSECT</span><span class="p">,</span><span class="n">FATSECT</span><span class="p">,</span><span class="n">ENDOFCHAIN</span><span class="p">,</span><span class="n">FREESECT</span><span class="p">):</span>
                <span class="k">return</span>
            <span class="n">used_streams</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_used_streams_fat</span>
        <span class="c">#TODO: would it be more efficient using a dict or hash values, instead</span>
        <span class="c">#      of a list of long ?</span>
        <span class="k">if</span> <span class="n">first_sect</span> <span class="ow">in</span> <span class="n">used_streams</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span> <span class="s">&#39;Stream referenced twice&#39;</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">used_streams</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">first_sect</span><span class="p">)</span>


<div class="viewcode-block" id="OleFileIO.dumpfat"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.dumpfat">[docs]</a>    <span class="k">def</span> <span class="nf">dumpfat</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fat</span><span class="p">,</span> <span class="n">firstindex</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
        <span class="s">&quot;Displays a part of FAT in human-readable form for debugging purpose&quot;</span>
        <span class="c"># [PL] added only for debug</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">DEBUG_MODE</span><span class="p">:</span>
            <span class="k">return</span>
        <span class="c"># dictionary to convert special FAT values in human-readable strings</span>
        <span class="n">VPL</span><span class="o">=</span><span class="mi">8</span> <span class="c"># valeurs par ligne (8+1 * 8+1 = 81)</span>
        <span class="n">fatnames</span> <span class="o">=</span> <span class="p">{</span>
            <span class="n">FREESECT</span><span class="p">:</span>   <span class="s">&quot;..free..&quot;</span><span class="p">,</span>
            <span class="n">ENDOFCHAIN</span><span class="p">:</span> <span class="s">&quot;[ END. ]&quot;</span><span class="p">,</span>
            <span class="n">FATSECT</span><span class="p">:</span>    <span class="s">&quot;FATSECT &quot;</span><span class="p">,</span>
            <span class="n">DIFSECT</span><span class="p">:</span>    <span class="s">&quot;DIFSECT &quot;</span>
            <span class="p">}</span>
        <span class="n">nbsect</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">fat</span><span class="p">)</span>
        <span class="n">nlines</span> <span class="o">=</span> <span class="p">(</span><span class="n">nbsect</span><span class="o">+</span><span class="n">VPL</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="n">VPL</span>
        <span class="k">print</span><span class="p">(</span><span class="s">&quot;index&quot;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s">&quot; &quot;</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">VPL</span><span class="p">):</span>
            <span class="k">print</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%8X</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">i</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s">&quot; &quot;</span><span class="p">)</span>
        <span class="k">print</span><span class="p">()</span>
        <span class="k">for</span> <span class="n">l</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">nlines</span><span class="p">):</span>
            <span class="n">index</span> <span class="o">=</span> <span class="n">l</span><span class="o">*</span><span class="n">VPL</span>
            <span class="k">print</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%8X</span><span class="s">:&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">firstindex</span><span class="o">+</span><span class="n">index</span><span class="p">),</span> <span class="n">end</span><span class="o">=</span><span class="s">&quot; &quot;</span><span class="p">)</span>
            <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="n">index</span><span class="o">+</span><span class="n">VPL</span><span class="p">):</span>
                <span class="k">if</span> <span class="n">i</span><span class="o">&gt;=</span><span class="n">nbsect</span><span class="p">:</span>
                    <span class="k">break</span>
                <span class="n">sect</span> <span class="o">=</span> <span class="n">fat</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
                <span class="k">if</span> <span class="n">sect</span> <span class="ow">in</span> <span class="n">fatnames</span><span class="p">:</span>
                    <span class="n">nom</span> <span class="o">=</span> <span class="n">fatnames</span><span class="p">[</span><span class="n">sect</span><span class="p">]</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="k">if</span> <span class="n">sect</span> <span class="o">==</span> <span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">:</span>
                        <span class="n">nom</span> <span class="o">=</span> <span class="s">&quot;    ---&gt;&quot;</span>
                    <span class="k">else</span><span class="p">:</span>
                        <span class="n">nom</span> <span class="o">=</span> <span class="s">&quot;</span><span class="si">%8X</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">sect</span>
                <span class="k">print</span><span class="p">(</span><span class="n">nom</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s">&quot; &quot;</span><span class="p">)</span>
            <span class="k">print</span><span class="p">()</span>

</div>
<div class="viewcode-block" id="OleFileIO.dumpsect"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.dumpsect">[docs]</a>    <span class="k">def</span> <span class="nf">dumpsect</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sector</span><span class="p">,</span> <span class="n">firstindex</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
        <span class="s">&quot;Displays a sector in a human-readable form, for debugging purpose.&quot;</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">DEBUG_MODE</span><span class="p">:</span>
            <span class="k">return</span>
        <span class="n">VPL</span><span class="o">=</span><span class="mi">8</span> <span class="c"># number of values per line (8+1 * 8+1 = 81)</span>
        <span class="n">tab</span> <span class="o">=</span> <span class="n">array</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">UINT32</span><span class="p">,</span> <span class="n">sector</span><span class="p">)</span>
        <span class="n">nbsect</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">tab</span><span class="p">)</span>
        <span class="n">nlines</span> <span class="o">=</span> <span class="p">(</span><span class="n">nbsect</span><span class="o">+</span><span class="n">VPL</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">//</span><span class="n">VPL</span>
        <span class="k">print</span><span class="p">(</span><span class="s">&quot;index&quot;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s">&quot; &quot;</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">VPL</span><span class="p">):</span>
            <span class="k">print</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%8X</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">i</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s">&quot; &quot;</span><span class="p">)</span>
        <span class="k">print</span><span class="p">()</span>
        <span class="k">for</span> <span class="n">l</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">nlines</span><span class="p">):</span>
            <span class="n">index</span> <span class="o">=</span> <span class="n">l</span><span class="o">*</span><span class="n">VPL</span>
            <span class="k">print</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%8X</span><span class="s">:&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">firstindex</span><span class="o">+</span><span class="n">index</span><span class="p">),</span> <span class="n">end</span><span class="o">=</span><span class="s">&quot; &quot;</span><span class="p">)</span>
            <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="n">index</span><span class="o">+</span><span class="n">VPL</span><span class="p">):</span>
                <span class="k">if</span> <span class="n">i</span><span class="o">&gt;=</span><span class="n">nbsect</span><span class="p">:</span>
                    <span class="k">break</span>
                <span class="n">sect</span> <span class="o">=</span> <span class="n">tab</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
                <span class="n">nom</span> <span class="o">=</span> <span class="s">&quot;</span><span class="si">%8X</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">sect</span>
                <span class="k">print</span><span class="p">(</span><span class="n">nom</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s">&quot; &quot;</span><span class="p">)</span>
            <span class="k">print</span><span class="p">()</span>
</div>
<div class="viewcode-block" id="OleFileIO.sect2array"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.sect2array">[docs]</a>    <span class="k">def</span> <span class="nf">sect2array</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sect</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        convert a sector to an array of 32 bits unsigned integers,</span>
<span class="sd">        swapping bytes on big endian CPUs such as PowerPC (old Macs)</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">a</span> <span class="o">=</span> <span class="n">array</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">UINT32</span><span class="p">,</span> <span class="n">sect</span><span class="p">)</span>
        <span class="c"># if CPU is big endian, swap bytes:</span>
        <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">byteorder</span> <span class="o">==</span> <span class="s">&#39;big&#39;</span><span class="p">:</span>
            <span class="n">a</span><span class="o">.</span><span class="n">byteswap</span><span class="p">()</span>
        <span class="k">return</span> <span class="n">a</span>

</div>
<div class="viewcode-block" id="OleFileIO.loadfat_sect"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.loadfat_sect">[docs]</a>    <span class="k">def</span> <span class="nf">loadfat_sect</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sect</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Adds the indexes of the given sector to the FAT</span>
<span class="sd">        </span>
<span class="sd">        :param sect: string containing the first FAT sector, or array of long integers</span>
<span class="sd">        :returns: index of last FAT sector.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c"># a FAT sector is an array of ulong integers.</span>
        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">sect</span><span class="p">,</span> <span class="n">array</span><span class="o">.</span><span class="n">array</span><span class="p">):</span>
            <span class="c"># if sect is already an array it is directly used</span>
            <span class="n">fat1</span> <span class="o">=</span> <span class="n">sect</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="c"># if it&#39;s a raw sector, it is parsed in an array</span>
            <span class="n">fat1</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">sect2array</span><span class="p">(</span><span class="n">sect</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">dumpsect</span><span class="p">(</span><span class="n">sect</span><span class="p">)</span>
        <span class="c"># The FAT is a sector chain starting at the first index of itself.</span>
        <span class="k">for</span> <span class="n">isect</span> <span class="ow">in</span> <span class="n">fat1</span><span class="p">:</span>
            <span class="c">#print(&quot;isect = %X&quot; % isect)</span>
            <span class="k">if</span> <span class="n">isect</span> <span class="o">==</span> <span class="n">ENDOFCHAIN</span> <span class="ow">or</span> <span class="n">isect</span> <span class="o">==</span> <span class="n">FREESECT</span><span class="p">:</span>
                <span class="c"># the end of the sector chain has been reached</span>
                <span class="k">break</span>
            <span class="c"># read the FAT sector</span>
            <span class="n">s</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">getsect</span><span class="p">(</span><span class="n">isect</span><span class="p">)</span>
            <span class="c"># parse it as an array of 32 bits integers, and add it to the</span>
            <span class="c"># global FAT array</span>
            <span class="n">nextfat</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">sect2array</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">fat</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">fat</span> <span class="o">+</span> <span class="n">nextfat</span>
        <span class="k">return</span> <span class="n">isect</span>

</div>
<div class="viewcode-block" id="OleFileIO.loadfat"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.loadfat">[docs]</a>    <span class="k">def</span> <span class="nf">loadfat</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">header</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Load the FAT table.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c"># The header contains a sector  numbers</span>
        <span class="c"># for the first 109 FAT sectors.  Additional sectors are</span>
        <span class="c"># described by DIF blocks</span>

        <span class="n">sect</span> <span class="o">=</span> <span class="n">header</span><span class="p">[</span><span class="mi">76</span><span class="p">:</span><span class="mi">512</span><span class="p">]</span>
        <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;len(sect)=</span><span class="si">%d</span><span class="s">, so </span><span class="si">%d</span><span class="s"> integers&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">sect</span><span class="p">),</span> <span class="nb">len</span><span class="p">(</span><span class="n">sect</span><span class="p">)</span><span class="o">//</span><span class="mi">4</span><span class="p">)</span> <span class="p">)</span>
        <span class="c">#fat    = []</span>
        <span class="c"># [PL] FAT is an array of 32 bits unsigned ints, it&#39;s more effective</span>
        <span class="c"># to use an array than a list in Python.</span>
        <span class="c"># It&#39;s initialized as empty first:</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">fat</span> <span class="o">=</span> <span class="n">array</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">UINT32</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">loadfat_sect</span><span class="p">(</span><span class="n">sect</span><span class="p">)</span>
        <span class="c">#self.dumpfat(self.fat)</span>
<span class="c">##      for i in range(0, len(sect), 4):</span>
<span class="c">##          ix = i32(sect, i)</span>
<span class="c">##          #[PL] if ix == -2 or ix == -1: # ix == 0xFFFFFFFE or ix == 0xFFFFFFFF:</span>
<span class="c">##          if ix == 0xFFFFFFFE or ix == 0xFFFFFFFF:</span>
<span class="c">##              break</span>
<span class="c">##          s = self.getsect(ix)</span>
<span class="c">##          #fat    = fat + [i32(s, i) for i in range(0, len(s), 4)]</span>
<span class="c">##          fat = fat + array.array(UINT32, s)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">csectDif</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
            <span class="c"># [PL] There&#39;s a DIFAT because file is larger than 6.8MB</span>
            <span class="c"># some checks just in case:</span>
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">csectFat</span> <span class="o">&lt;=</span> <span class="mi">109</span><span class="p">:</span>
                <span class="c"># there must be at least 109 blocks in header and the rest in</span>
                <span class="c"># DIFAT, so number of sectors must be &gt;109.</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span> <span class="s">&#39;incorrect DIFAT, not enough sectors&#39;</span><span class="p">)</span>
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">sectDifStart</span> <span class="o">&gt;=</span> <span class="bp">self</span><span class="o">.</span><span class="n">nb_sect</span><span class="p">:</span>
                <span class="c"># initial DIFAT block index must be valid</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_FATAL</span><span class="p">,</span> <span class="s">&#39;incorrect DIFAT, first index out of range&#39;</span><span class="p">)</span>
            <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;DIFAT analysis...&quot;</span> <span class="p">)</span>
            <span class="c"># We compute the necessary number of DIFAT sectors :</span>
            <span class="c"># (each DIFAT sector = 127 pointers + 1 towards next DIFAT sector)</span>
            <span class="n">nb_difat</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">csectFat</span><span class="o">-</span><span class="mi">109</span> <span class="o">+</span> <span class="mi">126</span><span class="p">)</span><span class="o">//</span><span class="mi">127</span>
            <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;nb_difat = </span><span class="si">%d</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">nb_difat</span> <span class="p">)</span>
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">csectDif</span> <span class="o">!=</span> <span class="n">nb_difat</span><span class="p">:</span>
                <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">&#39;incorrect DIFAT&#39;</span><span class="p">)</span>
            <span class="n">isect_difat</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">sectDifStart</span>
            <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">iterrange</span><span class="p">(</span><span class="n">nb_difat</span><span class="p">):</span>
                <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;DIFAT block </span><span class="si">%d</span><span class="s">, sector </span><span class="si">%X</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">isect_difat</span><span class="p">)</span> <span class="p">)</span>
                <span class="c">#TODO: check if corresponding FAT SID = DIFSECT</span>
                <span class="n">sector_difat</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">getsect</span><span class="p">(</span><span class="n">isect_difat</span><span class="p">)</span>
                <span class="n">difat</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">sect2array</span><span class="p">(</span><span class="n">sector_difat</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">dumpsect</span><span class="p">(</span><span class="n">sector_difat</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">loadfat_sect</span><span class="p">(</span><span class="n">difat</span><span class="p">[:</span><span class="mi">127</span><span class="p">])</span>
                <span class="c"># last DIFAT pointer is next DIFAT sector:</span>
                <span class="n">isect_difat</span> <span class="o">=</span> <span class="n">difat</span><span class="p">[</span><span class="mi">127</span><span class="p">]</span>
                <span class="n">debug</span><span class="p">(</span> <span class="s">&quot;next DIFAT sector: </span><span class="si">%X</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">isect_difat</span> <span class="p">)</span>
            <span class="c"># checks:</span>
            <span class="k">if</span> <span class="n">isect_difat</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="n">ENDOFCHAIN</span><span class="p">,</span> <span class="n">FREESECT</span><span class="p">]:</span>
                <span class="c"># last DIFAT pointer value must be ENDOFCHAIN or FREESECT</span>
                <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">&#39;incorrect end of DIFAT&#39;</span><span class="p">)</span>
<span class="c">##          if len(self.fat) != self.csectFat:</span>
<span class="c">##              # FAT should contain csectFat blocks</span>
<span class="c">##              print(&quot;FAT length: %d instead of %d&quot; % (len(self.fat), self.csectFat))</span>
<span class="c">##              raise IOError(&#39;incorrect DIFAT&#39;)</span>
        <span class="c"># since FAT is read from fixed-size sectors, it may contain more values</span>
        <span class="c"># than the actual number of sectors in the file.</span>
        <span class="c"># Keep only the relevant sector indexes:</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">fat</span><span class="p">)</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">nb_sect</span><span class="p">:</span>
            <span class="n">debug</span><span class="p">(</span><span class="s">&#39;len(fat)=</span><span class="si">%d</span><span class="s">, shrunk to nb_sect=</span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">fat</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">nb_sect</span><span class="p">))</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">fat</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">fat</span><span class="p">[:</span><span class="bp">self</span><span class="o">.</span><span class="n">nb_sect</span><span class="p">]</span>
        <span class="n">debug</span><span class="p">(</span><span class="s">&#39;</span><span class="se">\n</span><span class="s">FAT:&#39;</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">dumpfat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">fat</span><span class="p">)</span>

</div>
<div class="viewcode-block" id="OleFileIO.loadminifat"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.loadminifat">[docs]</a>    <span class="k">def</span> <span class="nf">loadminifat</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Load the MiniFAT table.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c"># MiniFAT is stored in a standard  sub-stream, pointed to by a header</span>
        <span class="c"># field.</span>
        <span class="c"># NOTE: there are two sizes to take into account for this stream:</span>
        <span class="c"># 1) Stream size is calculated according to the number of sectors</span>
        <span class="c">#    declared in the OLE header. This allocated stream may be more than</span>
        <span class="c">#    needed to store the actual sector indexes.</span>
        <span class="c"># (self.csectMiniFat is the number of sectors of size self.SectorSize)</span>
        <span class="n">stream_size</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">csectMiniFat</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">SectorSize</span>
        <span class="c"># 2) Actually used size is calculated by dividing the MiniStream size</span>
        <span class="c">#    (given by root entry size) by the size of mini sectors, *4 for</span>
        <span class="c">#    32 bits indexes:</span>
        <span class="n">nb_minisectors</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">root</span><span class="o">.</span><span class="n">size</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">MiniSectorSize</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">//</span> <span class="bp">self</span><span class="o">.</span><span class="n">MiniSectorSize</span>
        <span class="n">used_size</span> <span class="o">=</span> <span class="n">nb_minisectors</span> <span class="o">*</span> <span class="mi">4</span>
        <span class="n">debug</span><span class="p">(</span><span class="s">&#39;loadminifat(): minifatsect=</span><span class="si">%d</span><span class="s">, nb FAT sectors=</span><span class="si">%d</span><span class="s">, used_size=</span><span class="si">%d</span><span class="s">, stream_size=</span><span class="si">%d</span><span class="s">, nb MiniSectors=</span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span>
            <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">minifatsect</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">csectMiniFat</span><span class="p">,</span> <span class="n">used_size</span><span class="p">,</span> <span class="n">stream_size</span><span class="p">,</span> <span class="n">nb_minisectors</span><span class="p">))</span>
        <span class="k">if</span> <span class="n">used_size</span> <span class="o">&gt;</span> <span class="n">stream_size</span><span class="p">:</span>
            <span class="c"># This is not really a problem, but may indicate a wrong implementation:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span> <span class="s">&#39;OLE MiniStream is larger than MiniFAT&#39;</span><span class="p">)</span>
        <span class="c"># In any case, first read stream_size:</span>
        <span class="n">s</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">minifatsect</span><span class="p">,</span> <span class="n">stream_size</span><span class="p">,</span> <span class="n">force_FAT</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
        <span class="c">#[PL] Old code replaced by an array:</span>
        <span class="c">#self.minifat = [i32(s, i) for i in range(0, len(s), 4)]</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">minifat</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">sect2array</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
        <span class="c"># Then shrink the array to used size, to avoid indexes out of MiniStream:</span>
        <span class="n">debug</span><span class="p">(</span><span class="s">&#39;MiniFAT shrunk from </span><span class="si">%d</span><span class="s"> to </span><span class="si">%d</span><span class="s"> sectors&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">minifat</span><span class="p">),</span> <span class="n">nb_minisectors</span><span class="p">))</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">minifat</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">minifat</span><span class="p">[:</span><span class="n">nb_minisectors</span><span class="p">]</span>
        <span class="n">debug</span><span class="p">(</span><span class="s">&#39;loadminifat(): len=</span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">minifat</span><span class="p">))</span>
        <span class="n">debug</span><span class="p">(</span><span class="s">&#39;</span><span class="se">\n</span><span class="s">MiniFAT:&#39;</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">dumpfat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">minifat</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="OleFileIO.getsect"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.getsect">[docs]</a>    <span class="k">def</span> <span class="nf">getsect</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sect</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Read given sector from file on disk.</span>
<span class="sd">        </span>
<span class="sd">        :param sect: sector index</span>
<span class="sd">        :returns: a string containing the sector data.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c"># [PL] this original code was wrong when sectors are 4KB instead of</span>
        <span class="c"># 512 bytes:</span>
        <span class="c">#self.fp.seek(512 + self.sectorsize * sect)</span>
        <span class="c">#[PL]: added safety checks:</span>
        <span class="c">#print(&quot;getsect(%X)&quot; % sect)</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">fp</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sectorsize</span> <span class="o">*</span> <span class="p">(</span><span class="n">sect</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span>
        <span class="k">except</span><span class="p">:</span>
            <span class="n">debug</span><span class="p">(</span><span class="s">&#39;getsect(): sect=</span><span class="si">%X</span><span class="s">, seek=</span><span class="si">%d</span><span class="s">, filesize=</span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span>
                <span class="p">(</span><span class="n">sect</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">sectorsize</span><span class="o">*</span><span class="p">(</span><span class="n">sect</span><span class="o">+</span><span class="mi">1</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">_filesize</span><span class="p">))</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_FATAL</span><span class="p">,</span> <span class="s">&#39;OLE sector index out of range&#39;</span><span class="p">)</span>
        <span class="n">sector</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">fp</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sectorsize</span><span class="p">)</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sector</span><span class="p">)</span> <span class="o">!=</span> <span class="bp">self</span><span class="o">.</span><span class="n">sectorsize</span><span class="p">:</span>
            <span class="n">debug</span><span class="p">(</span><span class="s">&#39;getsect(): sect=</span><span class="si">%X</span><span class="s">, read=</span><span class="si">%d</span><span class="s">, sectorsize=</span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span>
                <span class="p">(</span><span class="n">sect</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">sector</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">sectorsize</span><span class="p">))</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_FATAL</span><span class="p">,</span> <span class="s">&#39;incomplete OLE sector&#39;</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">sector</span>

</div>
<div class="viewcode-block" id="OleFileIO.loaddirectory"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.loaddirectory">[docs]</a>    <span class="k">def</span> <span class="nf">loaddirectory</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sect</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Load the directory.</span>
<span class="sd">        </span>
<span class="sd">        :param sect: sector index of directory stream.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c"># The directory is  stored in a standard</span>
        <span class="c"># substream, independent of its size.</span>

        <span class="c"># open directory stream as a read-only file:</span>
        <span class="c"># (stream size is not known in advance)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">directory_fp</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_open</span><span class="p">(</span><span class="n">sect</span><span class="p">)</span>

        <span class="c">#[PL] to detect malformed documents and avoid DoS attacks, the maximum</span>
        <span class="c"># number of directory entries can be calculated:</span>
        <span class="n">max_entries</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">directory_fp</span><span class="o">.</span><span class="n">size</span> <span class="o">//</span> <span class="mi">128</span>
        <span class="n">debug</span><span class="p">(</span><span class="s">&#39;loaddirectory: size=</span><span class="si">%d</span><span class="s">, max_entries=</span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span>
            <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">directory_fp</span><span class="o">.</span><span class="n">size</span><span class="p">,</span> <span class="n">max_entries</span><span class="p">))</span>

        <span class="c"># Create list of directory entries</span>
        <span class="c">#self.direntries = []</span>
        <span class="c"># We start with a list of &quot;None&quot; object</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">direntries</span> <span class="o">=</span> <span class="p">[</span><span class="bp">None</span><span class="p">]</span> <span class="o">*</span> <span class="n">max_entries</span>
<span class="c">##        for sid in iterrange(max_entries):</span>
<span class="c">##            entry = fp.read(128)</span>
<span class="c">##            if not entry:</span>
<span class="c">##                break</span>
<span class="c">##            self.direntries.append(_OleDirectoryEntry(entry, sid, self))</span>
        <span class="c"># load root entry:</span>
        <span class="n">root_entry</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_load_direntry</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
        <span class="c"># Root entry is the first entry:</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">root</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">direntries</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
        <span class="c"># read and build all storage trees, starting from the root:</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">root</span><span class="o">.</span><span class="n">build_storage_tree</span><span class="p">()</span>

</div>
    <span class="k">def</span> <span class="nf">_load_direntry</span> <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sid</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Load a directory entry from the directory.</span>
<span class="sd">        This method should only be called once for each storage/stream when</span>
<span class="sd">        loading the directory.</span>

<span class="sd">        :param sid: index of storage/stream in the directory.</span>
<span class="sd">        :returns: a _OleDirectoryEntry object</span>
<span class="sd">        :exception IOError: if the entry has always been referenced.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c"># check if SID is OK:</span>
        <span class="k">if</span> <span class="n">sid</span><span class="o">&lt;</span><span class="mi">0</span> <span class="ow">or</span> <span class="n">sid</span><span class="o">&gt;=</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">direntries</span><span class="p">):</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_FATAL</span><span class="p">,</span> <span class="s">&quot;OLE directory index out of range&quot;</span><span class="p">)</span>
        <span class="c"># check if entry was already referenced:</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">direntries</span><span class="p">[</span><span class="n">sid</span><span class="p">]</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span>
                <span class="s">&quot;double reference for OLE stream/storage&quot;</span><span class="p">)</span>
            <span class="c"># if exception not raised, return the object</span>
            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">direntries</span><span class="p">[</span><span class="n">sid</span><span class="p">]</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">directory_fp</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="n">sid</span> <span class="o">*</span> <span class="mi">128</span><span class="p">)</span>
        <span class="n">entry</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">directory_fp</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="mi">128</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">direntries</span><span class="p">[</span><span class="n">sid</span><span class="p">]</span> <span class="o">=</span> <span class="n">_OleDirectoryEntry</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="n">sid</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">direntries</span><span class="p">[</span><span class="n">sid</span><span class="p">]</span>


<div class="viewcode-block" id="OleFileIO.dumpdirectory"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.dumpdirectory">[docs]</a>    <span class="k">def</span> <span class="nf">dumpdirectory</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Dump directory (for debugging only)</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">root</span><span class="o">.</span><span class="n">dump</span><span class="p">()</span>

</div>
    <span class="k">def</span> <span class="nf">_open</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">size</span> <span class="o">=</span> <span class="mh">0x7FFFFFFF</span><span class="p">,</span> <span class="n">force_FAT</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Open a stream, either in FAT or MiniFAT according to its size.</span>
<span class="sd">        (openstream helper)</span>

<span class="sd">        :param start: index of first sector</span>
<span class="sd">        :param size: size of stream (or nothing if size is unknown)</span>
<span class="sd">        :param force_FAT: if False (default), stream will be opened in FAT or MiniFAT</span>
<span class="sd">                   according to size. If True, it will always be opened in FAT.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">debug</span><span class="p">(</span><span class="s">&#39;OleFileIO.open(): sect=</span><span class="si">%d</span><span class="s">, size=</span><span class="si">%d</span><span class="s">, force_FAT=</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span>
            <span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">force_FAT</span><span class="p">)))</span>
        <span class="c"># stream size is compared to the MiniSectorCutoff threshold:</span>
        <span class="k">if</span> <span class="n">size</span> <span class="o">&lt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">minisectorcutoff</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">force_FAT</span><span class="p">:</span>
            <span class="c"># ministream object</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">ministream</span><span class="p">:</span>
                <span class="c"># load MiniFAT if it wasn&#39;t already done:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">loadminifat</span><span class="p">()</span>
                <span class="c"># The first sector index of the miniFAT stream is stored in the</span>
                <span class="c"># root directory entry:</span>
                <span class="n">size_ministream</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">root</span><span class="o">.</span><span class="n">size</span>
                <span class="n">debug</span><span class="p">(</span><span class="s">&#39;Opening MiniStream: sect=</span><span class="si">%d</span><span class="s">, size=</span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span>
                    <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">root</span><span class="o">.</span><span class="n">isectStart</span><span class="p">,</span> <span class="n">size_ministream</span><span class="p">))</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">ministream</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">root</span><span class="o">.</span><span class="n">isectStart</span><span class="p">,</span>
                    <span class="n">size_ministream</span><span class="p">,</span> <span class="n">force_FAT</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
            <span class="k">return</span> <span class="n">_OleStream</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ministream</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span>
                              <span class="bp">self</span><span class="o">.</span><span class="n">minisectorsize</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">minifat</span><span class="p">,</span>
                              <span class="bp">self</span><span class="o">.</span><span class="n">ministream</span><span class="o">.</span><span class="n">size</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="c"># standard stream</span>
            <span class="k">return</span> <span class="n">_OleStream</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">fp</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="mi">512</span><span class="p">,</span>
                              <span class="bp">self</span><span class="o">.</span><span class="n">sectorsize</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">fat</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_filesize</span><span class="p">)</span>


    <span class="k">def</span> <span class="nf">_list</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">files</span><span class="p">,</span> <span class="n">prefix</span><span class="p">,</span> <span class="n">node</span><span class="p">,</span> <span class="n">streams</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">storages</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        (listdir helper)</span>
<span class="sd">        :param files: list of files to fill in</span>
<span class="sd">        :param prefix: current location in storage tree (list of names)</span>
<span class="sd">        :param node: current node (_OleDirectoryEntry object)</span>
<span class="sd">        :param streams: bool, include streams if True (True by default) - new in v0.26</span>
<span class="sd">        :param storages: bool, include storages if True (False by default) - new in v0.26</span>
<span class="sd">        (note: the root storage is never included)</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">prefix</span> <span class="o">=</span> <span class="n">prefix</span> <span class="o">+</span> <span class="p">[</span><span class="n">node</span><span class="o">.</span><span class="n">name</span><span class="p">]</span>
        <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">node</span><span class="o">.</span><span class="n">kids</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">entry</span><span class="o">.</span><span class="n">kids</span><span class="p">:</span>
                <span class="c"># this is a storage</span>
                <span class="k">if</span> <span class="n">storages</span><span class="p">:</span>
                    <span class="c"># add it to the list</span>
                    <span class="n">files</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">prefix</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span> <span class="o">+</span> <span class="p">[</span><span class="n">entry</span><span class="o">.</span><span class="n">name</span><span class="p">])</span>
                <span class="c"># check its kids</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">_list</span><span class="p">(</span><span class="n">files</span><span class="p">,</span> <span class="n">prefix</span><span class="p">,</span> <span class="n">entry</span><span class="p">,</span> <span class="n">streams</span><span class="p">,</span> <span class="n">storages</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="c"># this is a stream</span>
                <span class="k">if</span> <span class="n">streams</span><span class="p">:</span>
                    <span class="c"># add it to the list</span>
                    <span class="n">files</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">prefix</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span> <span class="o">+</span> <span class="p">[</span><span class="n">entry</span><span class="o">.</span><span class="n">name</span><span class="p">])</span>


<div class="viewcode-block" id="OleFileIO.listdir"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.listdir">[docs]</a>    <span class="k">def</span> <span class="nf">listdir</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">streams</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">storages</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return a list of streams stored in this file</span>

<span class="sd">        :param streams: bool, include streams if True (True by default) - new in v0.26</span>
<span class="sd">        :param storages: bool, include storages if True (False by default) - new in v0.26</span>
<span class="sd">            (note: the root storage is never included)</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">files</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_list</span><span class="p">(</span><span class="n">files</span><span class="p">,</span> <span class="p">[],</span> <span class="bp">self</span><span class="o">.</span><span class="n">root</span><span class="p">,</span> <span class="n">streams</span><span class="p">,</span> <span class="n">storages</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">files</span>

</div>
    <span class="k">def</span> <span class="nf">_find</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Returns directory entry of given filename. (openstream helper)</span>
<span class="sd">        Note: this method is case-insensitive.</span>

<span class="sd">        :param filename: path of stream in storage tree (except root entry), either:</span>
<span class="sd">        </span>
<span class="sd">            - a string using Unix path syntax, for example:</span>
<span class="sd">              &#39;storage_1/storage_1.2/stream&#39;</span>
<span class="sd">            - a list of storage filenames, path to the desired stream/storage.</span>
<span class="sd">              Example: [&#39;storage_1&#39;, &#39;storage_1.2&#39;, &#39;stream&#39;]</span>
<span class="sd">        :returns: sid of requested filename</span>
<span class="sd">        raise IOError if file not found</span>
<span class="sd">        &quot;&quot;&quot;</span>

        <span class="c"># if filename is a string instead of a list, split it on slashes to</span>
        <span class="c"># convert to a list:</span>
        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="nb">basestring</span><span class="p">):</span>
            <span class="n">filename</span> <span class="o">=</span> <span class="n">filename</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
        <span class="c"># walk across storage tree, following given path:</span>
        <span class="n">node</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">root</span>
        <span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">filename</span><span class="p">:</span>
            <span class="k">for</span> <span class="n">kid</span> <span class="ow">in</span> <span class="n">node</span><span class="o">.</span><span class="n">kids</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">kid</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="n">name</span><span class="o">.</span><span class="n">lower</span><span class="p">():</span>
                    <span class="k">break</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">&quot;file not found&quot;</span><span class="p">)</span>
            <span class="n">node</span> <span class="o">=</span> <span class="n">kid</span>
        <span class="k">return</span> <span class="n">node</span><span class="o">.</span><span class="n">sid</span>


<div class="viewcode-block" id="OleFileIO.openstream"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.openstream">[docs]</a>    <span class="k">def</span> <span class="nf">openstream</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Open a stream as a read-only file object (BytesIO).</span>

<span class="sd">        :param filename: path of stream in storage tree (except root entry), either:</span>
<span class="sd">        </span>
<span class="sd">            - a string using Unix path syntax, for example:</span>
<span class="sd">              &#39;storage_1/storage_1.2/stream&#39;</span>
<span class="sd">            - a list of storage filenames, path to the desired stream/storage.</span>
<span class="sd">              Example: [&#39;storage_1&#39;, &#39;storage_1.2&#39;, &#39;stream&#39;]</span>
<span class="sd">              </span>
<span class="sd">        :returns: file object (read-only)</span>
<span class="sd">        :exception IOError: if filename not found, or if this is not a stream.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">sid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_find</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
        <span class="n">entry</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">direntries</span><span class="p">[</span><span class="n">sid</span><span class="p">]</span>
        <span class="k">if</span> <span class="n">entry</span><span class="o">.</span><span class="n">entry_type</span> <span class="o">!=</span> <span class="n">STGTY_STREAM</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">&quot;this file is not a stream&quot;</span><span class="p">)</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_open</span><span class="p">(</span><span class="n">entry</span><span class="o">.</span><span class="n">isectStart</span><span class="p">,</span> <span class="n">entry</span><span class="o">.</span><span class="n">size</span><span class="p">)</span>

</div>
<div class="viewcode-block" id="OleFileIO.get_type"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.get_type">[docs]</a>    <span class="k">def</span> <span class="nf">get_type</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Test if given filename exists as a stream or a storage in the OLE</span>
<span class="sd">        container, and return its type.</span>

<span class="sd">        :param filename: path of stream in storage tree. (see openstream for syntax)</span>
<span class="sd">        :returns: False if object does not exist, its entry type (&gt;0) otherwise:</span>
<span class="sd">        </span>
<span class="sd">            - STGTY_STREAM: a stream</span>
<span class="sd">            - STGTY_STORAGE: a storage</span>
<span class="sd">            - STGTY_ROOT: the root entry</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">sid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_find</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
            <span class="n">entry</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">direntries</span><span class="p">[</span><span class="n">sid</span><span class="p">]</span>
            <span class="k">return</span> <span class="n">entry</span><span class="o">.</span><span class="n">entry_type</span>
        <span class="k">except</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">False</span>

</div>
<div class="viewcode-block" id="OleFileIO.getmtime"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.getmtime">[docs]</a>    <span class="k">def</span> <span class="nf">getmtime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return modification time of a stream/storage.</span>

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

<span class="sd">        new in version 0.26</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">sid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_find</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
        <span class="n">entry</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">direntries</span><span class="p">[</span><span class="n">sid</span><span class="p">]</span>
        <span class="k">return</span> <span class="n">entry</span><span class="o">.</span><span class="n">getmtime</span><span class="p">()</span>

</div>
<div class="viewcode-block" id="OleFileIO.getctime"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.getctime">[docs]</a>    <span class="k">def</span> <span class="nf">getctime</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return creation time of a stream/storage.</span>

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

<span class="sd">        new in version 0.26</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">sid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_find</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
        <span class="n">entry</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">direntries</span><span class="p">[</span><span class="n">sid</span><span class="p">]</span>
        <span class="k">return</span> <span class="n">entry</span><span class="o">.</span><span class="n">getctime</span><span class="p">()</span>

</div>
<div class="viewcode-block" id="OleFileIO.exists"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.exists">[docs]</a>    <span class="k">def</span> <span class="nf">exists</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Test if given filename exists as a stream or a storage in the OLE</span>
<span class="sd">        container.</span>

<span class="sd">        :param filename: path of stream in storage tree. (see openstream for syntax)</span>
<span class="sd">        :returns: True if object exist, else False.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">sid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_find</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
            <span class="k">return</span> <span class="bp">True</span>
        <span class="k">except</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">False</span>

</div>
<div class="viewcode-block" id="OleFileIO.get_size"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.get_size">[docs]</a>    <span class="k">def</span> <span class="nf">get_size</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return size of a stream in the OLE container, in bytes.</span>

<span class="sd">        :param filename: path of stream in storage tree (see openstream for syntax)</span>
<span class="sd">        :returns: size in bytes (long integer)</span>
<span class="sd">        :exception IOError: if file not found</span>
<span class="sd">        :exception TypeError: if this is not a stream</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">sid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_find</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
        <span class="n">entry</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">direntries</span><span class="p">[</span><span class="n">sid</span><span class="p">]</span>
        <span class="k">if</span> <span class="n">entry</span><span class="o">.</span><span class="n">entry_type</span> <span class="o">!=</span> <span class="n">STGTY_STREAM</span><span class="p">:</span>
            <span class="c">#TODO: Should it return zero instead of raising an exception ?</span>
            <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s">&#39;object is not an OLE stream&#39;</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">entry</span><span class="o">.</span><span class="n">size</span>

</div>
<div class="viewcode-block" id="OleFileIO.get_rootentry_name"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.get_rootentry_name">[docs]</a>    <span class="k">def</span> <span class="nf">get_rootentry_name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return root entry name. Should usually be &#39;Root Entry&#39; or &#39;R&#39; in most</span>
<span class="sd">        implementations.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">root</span><span class="o">.</span><span class="n">name</span>

</div>
<div class="viewcode-block" id="OleFileIO.getproperties"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.getproperties">[docs]</a>    <span class="k">def</span> <span class="nf">getproperties</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">,</span> <span class="n">convert_time</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">no_conversion</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Return properties described in substream.</span>

<span class="sd">        :param filename: path of stream in storage tree (see openstream for syntax)</span>
<span class="sd">        :param convert_time: bool, if True timestamps will be converted to Python datetime</span>
<span class="sd">        :param no_conversion: None or list of int, timestamps not to be converted</span>
<span class="sd">            (for example total editing time is not a real timestamp)</span>
<span class="sd">        :returns: a dictionary of values indexed by id (integer)</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c"># make sure no_conversion is a list, just to simplify code below:</span>
        <span class="k">if</span> <span class="n">no_conversion</span> <span class="o">==</span> <span class="bp">None</span><span class="p">:</span>
            <span class="n">no_conversion</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="c"># stream path as a string to report exceptions:</span>
        <span class="n">streampath</span> <span class="o">=</span> <span class="n">filename</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">streampath</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
            <span class="n">streampath</span> <span class="o">=</span> <span class="s">&#39;/&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">streampath</span><span class="p">)</span>

        <span class="n">fp</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">openstream</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>

        <span class="n">data</span> <span class="o">=</span> <span class="p">{}</span>

        <span class="k">try</span><span class="p">:</span>
            <span class="c"># header</span>
            <span class="n">s</span> <span class="o">=</span> <span class="n">fp</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="mi">28</span><span class="p">)</span>
            <span class="n">clsid</span> <span class="o">=</span> <span class="n">_clsid</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="mi">8</span><span class="p">:</span><span class="mi">24</span><span class="p">])</span>

            <span class="c"># format id</span>
            <span class="n">s</span> <span class="o">=</span> <span class="n">fp</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="mi">20</span><span class="p">)</span>
            <span class="n">fmtid</span> <span class="o">=</span> <span class="n">_clsid</span><span class="p">(</span><span class="n">s</span><span class="p">[:</span><span class="mi">16</span><span class="p">])</span>
            <span class="n">fp</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="n">i32</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="mi">16</span><span class="p">))</span>

            <span class="c"># get section</span>
            <span class="n">s</span> <span class="o">=</span> <span class="n">b</span><span class="s">&quot;****&quot;</span> <span class="o">+</span> <span class="n">fp</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">i32</span><span class="p">(</span><span class="n">fp</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="mi">4</span><span class="p">))</span><span class="o">-</span><span class="mi">4</span><span class="p">)</span>
            <span class="c"># number of properties:</span>
            <span class="n">num_props</span> <span class="o">=</span> <span class="n">i32</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
        <span class="k">except</span> <span class="ne">BaseException</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
            <span class="c"># catch exception while parsing property header, and only raise</span>
            <span class="c"># a DEFECT_INCORRECT then return an empty dict, because this is not</span>
            <span class="c"># a fatal error when parsing the whole file</span>
            <span class="n">msg</span> <span class="o">=</span> <span class="s">&#39;Error while parsing properties header in stream </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span>
                <span class="nb">repr</span><span class="p">(</span><span class="n">streampath</span><span class="p">),</span> <span class="n">exc</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span> <span class="n">msg</span><span class="p">,</span> <span class="nb">type</span><span class="p">(</span><span class="n">exc</span><span class="p">))</span>
            <span class="k">return</span> <span class="n">data</span>

        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">num_props</span><span class="p">):</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="nb">id</span> <span class="o">=</span> <span class="mi">0</span> <span class="c"># just in case of an exception</span>
                <span class="nb">id</span> <span class="o">=</span> <span class="n">i32</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="mi">8</span><span class="o">+</span><span class="n">i</span><span class="o">*</span><span class="mi">8</span><span class="p">)</span>
                <span class="n">offset</span> <span class="o">=</span> <span class="n">i32</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="mi">12</span><span class="o">+</span><span class="n">i</span><span class="o">*</span><span class="mi">8</span><span class="p">)</span>
                <span class="nb">type</span> <span class="o">=</span> <span class="n">i32</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">offset</span><span class="p">)</span>

                <span class="n">debug</span> <span class="p">(</span><span class="s">&#39;property id=</span><span class="si">%d</span><span class="s">: type=</span><span class="si">%d</span><span class="s"> offset=</span><span class="si">%X</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="nb">id</span><span class="p">,</span> <span class="nb">type</span><span class="p">,</span> <span class="n">offset</span><span class="p">))</span>

                <span class="c"># test for common types first (should perhaps use</span>
                <span class="c"># a dictionary instead?)</span>

                <span class="k">if</span> <span class="nb">type</span> <span class="o">==</span> <span class="n">VT_I2</span><span class="p">:</span> <span class="c"># 16-bit signed integer</span>
                    <span class="n">value</span> <span class="o">=</span> <span class="n">i16</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">offset</span><span class="o">+</span><span class="mi">4</span><span class="p">)</span>
                    <span class="k">if</span> <span class="n">value</span> <span class="o">&gt;=</span> <span class="mi">32768</span><span class="p">:</span>
                        <span class="n">value</span> <span class="o">=</span> <span class="n">value</span> <span class="o">-</span> <span class="mi">65536</span>
                <span class="k">elif</span> <span class="nb">type</span> <span class="o">==</span> <span class="n">VT_UI2</span><span class="p">:</span> <span class="c"># 2-byte unsigned integer</span>
                    <span class="n">value</span> <span class="o">=</span> <span class="n">i16</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">offset</span><span class="o">+</span><span class="mi">4</span><span class="p">)</span>
                <span class="k">elif</span> <span class="nb">type</span> <span class="ow">in</span> <span class="p">(</span><span class="n">VT_I4</span><span class="p">,</span> <span class="n">VT_INT</span><span class="p">,</span> <span class="n">VT_ERROR</span><span class="p">):</span>
                    <span class="c"># VT_I4: 32-bit signed integer</span>
                    <span class="c"># VT_ERROR: HRESULT, similar to 32-bit signed integer,</span>
                    <span class="c"># see http://msdn.microsoft.com/en-us/library/cc230330.aspx</span>
                    <span class="n">value</span> <span class="o">=</span> <span class="n">i32</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">offset</span><span class="o">+</span><span class="mi">4</span><span class="p">)</span>
                <span class="k">elif</span> <span class="nb">type</span> <span class="ow">in</span> <span class="p">(</span><span class="n">VT_UI4</span><span class="p">,</span> <span class="n">VT_UINT</span><span class="p">):</span> <span class="c"># 4-byte unsigned integer</span>
                    <span class="n">value</span> <span class="o">=</span> <span class="n">i32</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">offset</span><span class="o">+</span><span class="mi">4</span><span class="p">)</span> <span class="c"># FIXME</span>
                <span class="k">elif</span> <span class="nb">type</span> <span class="ow">in</span> <span class="p">(</span><span class="n">VT_BSTR</span><span class="p">,</span> <span class="n">VT_LPSTR</span><span class="p">):</span>
                    <span class="c"># CodePageString, see http://msdn.microsoft.com/en-us/library/dd942354.aspx</span>
                    <span class="c"># size is a 32 bits integer, including the null terminator, and</span>
                    <span class="c"># possibly trailing or embedded null chars</span>
                    <span class="c">#TODO: if codepage is unicode, the string should be converted as such</span>
                    <span class="n">count</span> <span class="o">=</span> <span class="n">i32</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">offset</span><span class="o">+</span><span class="mi">4</span><span class="p">)</span>
                    <span class="n">value</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">offset</span><span class="o">+</span><span class="mi">8</span><span class="p">:</span><span class="n">offset</span><span class="o">+</span><span class="mi">8</span><span class="o">+</span><span class="n">count</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
                    <span class="c"># remove all null chars:</span>
                    <span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">b</span><span class="s">&#39;</span><span class="se">\x00</span><span class="s">&#39;</span><span class="p">,</span> <span class="n">b</span><span class="s">&#39;&#39;</span><span class="p">)</span>
                <span class="k">elif</span> <span class="nb">type</span> <span class="o">==</span> <span class="n">VT_BLOB</span><span class="p">:</span>
                    <span class="c"># binary large object (BLOB)</span>
                    <span class="c"># see http://msdn.microsoft.com/en-us/library/dd942282.aspx</span>
                    <span class="n">count</span> <span class="o">=</span> <span class="n">i32</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">offset</span><span class="o">+</span><span class="mi">4</span><span class="p">)</span>
                    <span class="n">value</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">offset</span><span class="o">+</span><span class="mi">8</span><span class="p">:</span><span class="n">offset</span><span class="o">+</span><span class="mi">8</span><span class="o">+</span><span class="n">count</span><span class="p">]</span>
                <span class="k">elif</span> <span class="nb">type</span> <span class="o">==</span> <span class="n">VT_LPWSTR</span><span class="p">:</span>
                    <span class="c"># UnicodeString</span>
                    <span class="c"># see http://msdn.microsoft.com/en-us/library/dd942313.aspx</span>
                    <span class="c"># &quot;the string should NOT contain embedded or additional trailing</span>
                    <span class="c"># null characters.&quot;</span>
                    <span class="n">count</span> <span class="o">=</span> <span class="n">i32</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">offset</span><span class="o">+</span><span class="mi">4</span><span class="p">)</span>
                    <span class="n">value</span> <span class="o">=</span> <span class="n">_unicode</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">offset</span><span class="o">+</span><span class="mi">8</span><span class="p">:</span><span class="n">offset</span><span class="o">+</span><span class="mi">8</span><span class="o">+</span><span class="n">count</span><span class="o">*</span><span class="mi">2</span><span class="p">])</span>
                <span class="k">elif</span> <span class="nb">type</span> <span class="o">==</span> <span class="n">VT_FILETIME</span><span class="p">:</span>
                    <span class="n">value</span> <span class="o">=</span> <span class="nb">long</span><span class="p">(</span><span class="n">i32</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">offset</span><span class="o">+</span><span class="mi">4</span><span class="p">))</span> <span class="o">+</span> <span class="p">(</span><span class="nb">long</span><span class="p">(</span><span class="n">i32</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">offset</span><span class="o">+</span><span class="mi">8</span><span class="p">))</span><span class="o">&lt;&lt;</span><span class="mi">32</span><span class="p">)</span>
                    <span class="c"># FILETIME is a 64-bit int: &quot;number of 100ns periods</span>
                    <span class="c"># since Jan 1,1601&quot;.</span>
                    <span class="k">if</span> <span class="n">convert_time</span> <span class="ow">and</span> <span class="nb">id</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">no_conversion</span><span class="p">:</span>
                        <span class="n">debug</span><span class="p">(</span><span class="s">&#39;Converting property #</span><span class="si">%d</span><span class="s"> to python datetime, value=</span><span class="si">%d</span><span class="s">=</span><span class="si">%f</span><span class="s">s&#39;</span>
                                <span class="o">%</span><span class="p">(</span><span class="nb">id</span><span class="p">,</span> <span class="n">value</span><span class="p">,</span> <span class="nb">float</span><span class="p">(</span><span class="n">value</span><span class="p">)</span><span class="o">/</span><span class="mi">10000000</span><span class="p">))</span>
                        <span class="c"># convert FILETIME to Python datetime.datetime</span>
                        <span class="c"># inspired from http://code.activestate.com/recipes/511425-filetime-to-datetime/</span>
                        <span class="n">_FILETIME_null_date</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="p">(</span><span class="mi">1601</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
                        <span class="n">debug</span><span class="p">(</span><span class="s">&#39;timedelta days=</span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">value</span><span class="o">//</span><span class="p">(</span><span class="mi">10</span><span class="o">*</span><span class="mi">1000000</span><span class="o">*</span><span class="mi">3600</span><span class="o">*</span><span class="mi">24</span><span class="p">)))</span>
                        <span class="n">value</span> <span class="o">=</span> <span class="n">_FILETIME_null_date</span> <span class="o">+</span> <span class="n">datetime</span><span class="o">.</span><span class="n">timedelta</span><span class="p">(</span><span class="n">microseconds</span><span class="o">=</span><span class="n">value</span><span class="o">//</span><span class="mi">10</span><span class="p">)</span>
                    <span class="k">else</span><span class="p">:</span>
                        <span class="c"># legacy code kept for backward compatibility: returns a</span>
                        <span class="c"># number of seconds since Jan 1,1601</span>
                        <span class="n">value</span> <span class="o">=</span> <span class="n">value</span> <span class="o">//</span> <span class="mi">10000000</span> <span class="c"># seconds</span>
                <span class="k">elif</span> <span class="nb">type</span> <span class="o">==</span> <span class="n">VT_UI1</span><span class="p">:</span> <span class="c"># 1-byte unsigned integer</span>
                    <span class="n">value</span> <span class="o">=</span> <span class="n">i8</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">offset</span><span class="o">+</span><span class="mi">4</span><span class="p">])</span>
                <span class="k">elif</span> <span class="nb">type</span> <span class="o">==</span> <span class="n">VT_CLSID</span><span class="p">:</span>
                    <span class="n">value</span> <span class="o">=</span> <span class="n">_clsid</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">offset</span><span class="o">+</span><span class="mi">4</span><span class="p">:</span><span class="n">offset</span><span class="o">+</span><span class="mi">20</span><span class="p">])</span>
                <span class="k">elif</span> <span class="nb">type</span> <span class="o">==</span> <span class="n">VT_CF</span><span class="p">:</span>
                    <span class="c"># PropertyIdentifier or ClipboardData??</span>
                    <span class="c"># see http://msdn.microsoft.com/en-us/library/dd941945.aspx</span>
                    <span class="n">count</span> <span class="o">=</span> <span class="n">i32</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">offset</span><span class="o">+</span><span class="mi">4</span><span class="p">)</span>
                    <span class="n">value</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="n">offset</span><span class="o">+</span><span class="mi">8</span><span class="p">:</span><span class="n">offset</span><span class="o">+</span><span class="mi">8</span><span class="o">+</span><span class="n">count</span><span class="p">]</span>
                <span class="k">elif</span> <span class="nb">type</span> <span class="o">==</span> <span class="n">VT_BOOL</span><span class="p">:</span>
                    <span class="c"># VARIANT_BOOL, 16 bits bool, 0x0000=Fals, 0xFFFF=True</span>
                    <span class="c"># see http://msdn.microsoft.com/en-us/library/cc237864.aspx</span>
                    <span class="n">value</span> <span class="o">=</span> <span class="nb">bool</span><span class="p">(</span><span class="n">i16</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">offset</span><span class="o">+</span><span class="mi">4</span><span class="p">))</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">value</span> <span class="o">=</span> <span class="bp">None</span> <span class="c"># everything else yields &quot;None&quot;</span>
                    <span class="n">debug</span> <span class="p">(</span><span class="s">&#39;property id=</span><span class="si">%d</span><span class="s">: type=</span><span class="si">%d</span><span class="s"> not implemented in parser yet&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="nb">id</span><span class="p">,</span> <span class="nb">type</span><span class="p">))</span>

                <span class="c"># missing: VT_EMPTY, VT_NULL, VT_R4, VT_R8, VT_CY, VT_DATE,</span>
                <span class="c"># VT_DECIMAL, VT_I1, VT_I8, VT_UI8,</span>
                <span class="c"># see http://msdn.microsoft.com/en-us/library/dd942033.aspx</span>

                <span class="c"># FIXME: add support for VT_VECTOR</span>
                <span class="c"># VT_VECTOR is a 32 uint giving the number of items, followed by</span>
                <span class="c"># the items in sequence. The VT_VECTOR value is combined with the</span>
                <span class="c"># type of items, e.g. VT_VECTOR|VT_BSTR</span>
                <span class="c"># see http://msdn.microsoft.com/en-us/library/dd942011.aspx</span>

                <span class="c">#print(&quot;%08x&quot; % id, repr(value), end=&quot; &quot;)</span>
                <span class="c">#print(&quot;(%s)&quot; % VT[i32(s, offset) &amp; 0xFFF])</span>

                <span class="n">data</span><span class="p">[</span><span class="nb">id</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
            <span class="k">except</span> <span class="ne">BaseException</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
                <span class="c"># catch exception while parsing each property, and only raise</span>
                <span class="c"># a DEFECT_INCORRECT, because parsing can go on</span>
                <span class="n">msg</span> <span class="o">=</span> <span class="s">&#39;Error while parsing property id </span><span class="si">%d</span><span class="s"> in stream </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span>
                    <span class="nb">id</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">streampath</span><span class="p">),</span> <span class="n">exc</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">_raise_defect</span><span class="p">(</span><span class="n">DEFECT_INCORRECT</span><span class="p">,</span> <span class="n">msg</span><span class="p">,</span> <span class="nb">type</span><span class="p">(</span><span class="n">exc</span><span class="p">))</span>

        <span class="k">return</span> <span class="n">data</span>
</div>
<div class="viewcode-block" id="OleFileIO.get_metadata"><a class="viewcode-back" href="../../reference/OleFileIO.html#PIL.OleFileIO.OleFileIO.get_metadata">[docs]</a>    <span class="k">def</span> <span class="nf">get_metadata</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Parse standard properties streams, return an OleMetadata object</span>
<span class="sd">        containing all the available metadata.</span>
<span class="sd">        (also stored in the metadata attribute of the OleFileIO object)</span>

<span class="sd">        new in version 0.25</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">metadata</span> <span class="o">=</span> <span class="n">OleMetadata</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">metadata</span><span class="o">.</span><span class="n">parse_properties</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">metadata</span>

<span class="c">#</span>
<span class="c"># --------------------------------------------------------------------</span>
<span class="c"># This script can be used to dump the directory of any OLE2 structured</span>
<span class="c"># storage file.</span>
</div></div>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span>

    <span class="kn">import</span> <span class="nn">sys</span>

    <span class="c"># [PL] display quick usage info if launched from command-line</span>
    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="mi">1</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="n">__doc__</span><span class="p">)</span>
        <span class="k">print</span><span class="p">(</span><span class="s">&quot;&quot;&quot;</span>
<span class="s">Launched from command line, this script parses OLE files and prints info.</span>

<span class="s">Usage: OleFileIO_PL.py [-d] [-c] &lt;file&gt; [file2 ...]</span>

<span class="s">Options:</span>
<span class="s">-d : debug mode (display a lot of debug information, for developers only)</span>
<span class="s">-c : check all streams (for debugging purposes)</span>
<span class="s">&quot;&quot;&quot;</span><span class="p">)</span>
        <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>

    <span class="n">check_streams</span> <span class="o">=</span> <span class="bp">False</span>
    <span class="k">for</span> <span class="n">filename</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span>
<span class="c">##      try:</span>
            <span class="c"># OPTIONS:</span>
            <span class="k">if</span> <span class="n">filename</span> <span class="o">==</span> <span class="s">&#39;-d&#39;</span><span class="p">:</span>
                <span class="c"># option to switch debug mode on:</span>
                <span class="n">set_debug_mode</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
                <span class="k">continue</span>
            <span class="k">if</span> <span class="n">filename</span> <span class="o">==</span> <span class="s">&#39;-c&#39;</span><span class="p">:</span>
                <span class="c"># option to switch check streams mode on:</span>
                <span class="n">check_streams</span> <span class="o">=</span> <span class="bp">True</span>
                <span class="k">continue</span>

            <span class="n">ole</span> <span class="o">=</span> <span class="n">OleFileIO</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span><span class="c">#, raise_defects=DEFECT_INCORRECT)</span>
            <span class="k">print</span><span class="p">(</span><span class="s">&quot;-&quot;</span> <span class="o">*</span> <span class="mi">68</span><span class="p">)</span>
            <span class="k">print</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
            <span class="k">print</span><span class="p">(</span><span class="s">&quot;-&quot;</span> <span class="o">*</span> <span class="mi">68</span><span class="p">)</span>
            <span class="n">ole</span><span class="o">.</span><span class="n">dumpdirectory</span><span class="p">()</span>
            <span class="k">for</span> <span class="n">streamname</span> <span class="ow">in</span> <span class="n">ole</span><span class="o">.</span><span class="n">listdir</span><span class="p">():</span>
                <span class="k">if</span> <span class="n">streamname</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s">&quot;</span><span class="se">\005</span><span class="s">&quot;</span><span class="p">:</span>
                    <span class="k">print</span><span class="p">(</span><span class="n">streamname</span><span class="p">,</span> <span class="s">&quot;: properties&quot;</span><span class="p">)</span>
                    <span class="n">props</span> <span class="o">=</span> <span class="n">ole</span><span class="o">.</span><span class="n">getproperties</span><span class="p">(</span><span class="n">streamname</span><span class="p">,</span> <span class="n">convert_time</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
                    <span class="n">props</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">props</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>
                    <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">props</span><span class="p">:</span>
                        <span class="c">#[PL]: avoid to display too large or binary values:</span>
                        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="p">(</span><span class="nb">basestring</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">)):</span>
                            <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">50</span><span class="p">:</span>
                                <span class="n">v</span> <span class="o">=</span> <span class="n">v</span><span class="p">[:</span><span class="mi">50</span><span class="p">]</span>
                        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">):</span>
                            <span class="c"># quick and dirty binary check:</span>
                            <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">11</span><span class="p">,</span><span class="mi">12</span><span class="p">,</span><span class="mi">14</span><span class="p">,</span><span class="mi">15</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">17</span><span class="p">,</span><span class="mi">18</span><span class="p">,</span><span class="mi">19</span><span class="p">,</span><span class="mi">20</span><span class="p">,</span>
                                <span class="mi">21</span><span class="p">,</span><span class="mi">22</span><span class="p">,</span><span class="mi">23</span><span class="p">,</span><span class="mi">24</span><span class="p">,</span><span class="mi">25</span><span class="p">,</span><span class="mi">26</span><span class="p">,</span><span class="mi">27</span><span class="p">,</span><span class="mi">28</span><span class="p">,</span><span class="mi">29</span><span class="p">,</span><span class="mi">30</span><span class="p">,</span><span class="mi">31</span><span class="p">):</span>
                                <span class="k">if</span> <span class="n">c</span> <span class="ow">in</span> <span class="nb">bytearray</span><span class="p">(</span><span class="n">v</span><span class="p">):</span>
                                    <span class="n">v</span> <span class="o">=</span> <span class="s">&#39;(binary data)&#39;</span>
                                    <span class="k">break</span>
                        <span class="k">print</span><span class="p">(</span><span class="s">&quot;   &quot;</span><span class="p">,</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span>

            <span class="k">if</span> <span class="n">check_streams</span><span class="p">:</span>
                <span class="c"># Read all streams to check if there are errors:</span>
                <span class="k">print</span><span class="p">(</span><span class="s">&#39;</span><span class="se">\n</span><span class="s">Checking streams...&#39;</span><span class="p">)</span>
                <span class="k">for</span> <span class="n">streamname</span> <span class="ow">in</span> <span class="n">ole</span><span class="o">.</span><span class="n">listdir</span><span class="p">():</span>
                    <span class="c"># print name using repr() to convert binary chars to \xNN:</span>
                    <span class="k">print</span><span class="p">(</span><span class="s">&#39;-&#39;</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">streamname</span><span class="p">)),</span><span class="s">&#39;-&#39;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s">&#39; &#39;</span><span class="p">)</span>
                    <span class="n">st_type</span> <span class="o">=</span> <span class="n">ole</span><span class="o">.</span><span class="n">get_type</span><span class="p">(</span><span class="n">streamname</span><span class="p">)</span>
                    <span class="k">if</span> <span class="n">st_type</span> <span class="o">==</span> <span class="n">STGTY_STREAM</span><span class="p">:</span>
                        <span class="k">print</span><span class="p">(</span><span class="s">&#39;size </span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">ole</span><span class="o">.</span><span class="n">get_size</span><span class="p">(</span><span class="n">streamname</span><span class="p">))</span>
                        <span class="c"># just try to read stream in memory:</span>
                        <span class="n">ole</span><span class="o">.</span><span class="n">openstream</span><span class="p">(</span><span class="n">streamname</span><span class="p">)</span>
                    <span class="k">else</span><span class="p">:</span>
                        <span class="k">print</span><span class="p">(</span><span class="s">&#39;NOT a stream : type=</span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">st_type</span><span class="p">)</span>
                <span class="k">print</span><span class="p">()</span>

<span class="c">##            for streamname in ole.listdir():</span>
<span class="c">##                # print name using repr() to convert binary chars to \xNN:</span>
<span class="c">##                print(&#39;-&#39;, repr(&#39;/&#39;.join(streamname)),&#39;-&#39;, end=&#39; &#39;)</span>
<span class="c">##                print(ole.getmtime(streamname))</span>
<span class="c">##            print()</span>

            <span class="k">print</span><span class="p">(</span><span class="s">&#39;Modification/Creation times of all directory entries:&#39;</span><span class="p">)</span>
            <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">ole</span><span class="o">.</span><span class="n">direntries</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">entry</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
                    <span class="k">print</span><span class="p">(</span><span class="s">&#39;- </span><span class="si">%s</span><span class="s">: mtime=</span><span class="si">%s</span><span class="s"> ctime=</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">entry</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
                        <span class="n">entry</span><span class="o">.</span><span class="n">getmtime</span><span class="p">(),</span> <span class="n">entry</span><span class="o">.</span><span class="n">getctime</span><span class="p">()))</span>
            <span class="k">print</span><span class="p">()</span>

            <span class="c"># parse and display metadata:</span>
            <span class="n">meta</span> <span class="o">=</span> <span class="n">ole</span><span class="o">.</span><span class="n">get_metadata</span><span class="p">()</span>
            <span class="n">meta</span><span class="o">.</span><span class="n">dump</span><span class="p">()</span>
            <span class="k">print</span><span class="p">()</span>
            <span class="c">#[PL] Test a few new methods:</span>
            <span class="n">root</span> <span class="o">=</span> <span class="n">ole</span><span class="o">.</span><span class="n">get_rootentry_name</span><span class="p">()</span>
            <span class="k">print</span><span class="p">(</span><span class="s">&#39;Root entry name: &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span> <span class="o">%</span> <span class="n">root</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">ole</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="s">&#39;worddocument&#39;</span><span class="p">):</span>
                <span class="k">print</span><span class="p">(</span><span class="s">&quot;This is a Word document.&quot;</span><span class="p">)</span>
                <span class="k">print</span><span class="p">(</span><span class="s">&quot;type of stream &#39;WordDocument&#39;:&quot;</span><span class="p">,</span> <span class="n">ole</span><span class="o">.</span><span class="n">get_type</span><span class="p">(</span><span class="s">&#39;worddocument&#39;</span><span class="p">))</span>
                <span class="k">print</span><span class="p">(</span><span class="s">&quot;size :&quot;</span><span class="p">,</span> <span class="n">ole</span><span class="o">.</span><span class="n">get_size</span><span class="p">(</span><span class="s">&#39;worddocument&#39;</span><span class="p">))</span>
                <span class="k">if</span> <span class="n">ole</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="s">&#39;macros/vba&#39;</span><span class="p">):</span>
                    <span class="k">print</span><span class="p">(</span><span class="s">&quot;This document may contain VBA macros.&quot;</span><span class="p">)</span>

            <span class="c"># print parsing issues:</span>
            <span class="k">print</span><span class="p">(</span><span class="s">&#39;</span><span class="se">\n</span><span class="s">Non-fatal issues raised during parsing:&#39;</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">ole</span><span class="o">.</span><span class="n">parsing_issues</span><span class="p">:</span>
                <span class="k">for</span> <span class="n">exctype</span><span class="p">,</span> <span class="n">msg</span> <span class="ow">in</span> <span class="n">ole</span><span class="o">.</span><span class="n">parsing_issues</span><span class="p">:</span>
                    <span class="k">print</span><span class="p">(</span><span class="s">&#39;- </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">exctype</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span> <span class="n">msg</span><span class="p">))</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">print</span><span class="p">(</span><span class="s">&#39;None&#39;</span><span class="p">)</span>
<span class="c">##      except IOError as v:</span>
<span class="c">##          print(&quot;***&quot;, &quot;cannot read&quot;, file, &quot;-&quot;, v)</span>
</pre></div>

          </div>
        </div>
      </div>
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper"><h3>Need help?</h3>
<p>
    You can get help via IRC at <a href="irc://irc.freenode.net#pil">irc://irc.freenode.net#pil</a> or Stack Overflow <a href="http://stackoverflow.com/questions/tagged/pillow">here</a> and <a href="http://stackoverflow.com/questions/tagged/pil">here</a>. Please <a href="https://github.com/python-pillow/Pillow/issues/new">report issues on GitHub</a>.
</p>
<div id="searchbox" style="display: none">
  <h3>Quick search</h3>
    <form class="search" action="../../search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    <p class="searchtip" style="font-size: 90%">
    Enter search terms or a module, class or function name.
    </p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../../genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="../../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li><a href="../../index.html">Home</a> &raquo;</li>
          <li><a href="../index.html" >Module code</a> &raquo;</li> 
      </ul>
    </div>
    <div class="footer">
        &copy; Copyright 1997-2011 by Secret Labs AB, 1995-2011 by Fredrik Lundh, 2010-2013 Alex Clark.
      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.3.
    </div>
  </body>
</html>