// ZipEntry.Extract.cs
// ------------------------------------------------------------------
//
// Copyright (c) 2009-2011 Dino Chiesa
// All rights reserved.
//
// This code module is part of DotNetZip, a zipfile class library.
//
// ------------------------------------------------------------------
//
// This code is licensed under the Microsoft Public License.
// See the file License.txt for the license details.
// More info on: http://dotnetzip.codeplex.com
//
// ------------------------------------------------------------------
//
// last saved (in emacs):
// Time-stamp: <2011-August-06 18:08:21>
//
// ------------------------------------------------------------------
//
// This module defines logic for Extract methods on the ZipEntry class.
//
// ------------------------------------------------------------------


using System;
using System.IO;

namespace OfficeOpenXml.Packaging.Ionic.Zip
{

    internal partial class ZipEntry
    {
        /// <summary>
        ///   Extract the entry to the filesystem, starting at the current
        ///   working directory.
        /// </summary>
        ///
        /// <overloads>
        ///   This method has a bunch of overloads! One of them is sure to
        ///   be the right one for you... If you don't like these, check
        ///   out the <c>ExtractWithPassword()</c> methods.
        /// </overloads>
        ///
        /// <seealso cref="ZipEntry.ExtractExistingFile"/>
        /// <seealso cref="ZipEntry.Extract(ExtractExistingFileAction)"/>
        ///
        /// <remarks>
        ///
        /// <para>
        ///   This method extracts an entry from a zip file into the current
        ///   working directory.  The path of the entry as extracted is the full
        ///   path as specified in the zip archive, relative to the current
        ///   working directory.  After the file is extracted successfully, the
        ///   file attributes and timestamps are set.
        /// </para>
        ///
        /// <para>
        ///   The action taken when extraction an entry would overwrite an
        ///   existing file is determined by the <see cref="ExtractExistingFile"
        ///   /> property.
        /// </para>
        ///
        /// <para>
        ///   Within the call to <c>Extract()</c>, the content for the entry is
        ///   written into a filesystem file, and then the last modified time of the
        ///   file is set according to the <see cref="LastModified"/> property on
        ///   the entry. See the remarks the <see cref="LastModified"/> property for
        ///   some details about the last modified time.
        /// </para>
        ///
        /// </remarks>
        internal void Extract()
        {
            InternalExtract(".", null, null);
        }


        /// <summary>
        ///   Extract the entry to a file in the filesystem, using the specified
        ///   behavior when extraction would overwrite an existing file.
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        ///   See the remarks on the <see cref="LastModified"/> property, for some
        ///   details about how the last modified time of the file is set after
        ///   extraction.
        /// </para>
        /// </remarks>
        ///
        /// <param name="extractExistingFile">
        ///   The action to take if extraction would overwrite an existing file.
        /// </param>
        internal void Extract(ExtractExistingFileAction extractExistingFile)
        {
            ExtractExistingFile = extractExistingFile;
            InternalExtract(".", null, null);
        }

        /// <summary>
        ///   Extracts the entry to the specified stream.
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        ///   The caller can specify any write-able stream, for example a <see
        ///   cref="System.IO.FileStream"/>, a <see
        ///   cref="System.IO.MemoryStream"/>, or ASP.NET's
        ///   <c>Response.OutputStream</c>.  The content will be decrypted and
        ///   decompressed as necessary. If the entry is encrypted and no password
        ///   is provided, this method will throw.
        /// </para>
        /// <para>
        ///   The position on the stream is not reset by this method before it extracts.
        ///   You may want to call stream.Seek() before calling ZipEntry.Extract().
        /// </para>
        /// </remarks>
        ///
        /// <param name="stream">
        ///   the stream to which the entry should be extracted.
        /// </param>
        ///
        public void Extract(Stream stream)
        {
            InternalExtract(null, stream, null);
        }

        /// <summary>
        ///   Extract the entry to the filesystem, starting at the specified base
        ///   directory.
        /// </summary>
        ///
        /// <param name="baseDirectory">the pathname of the base directory</param>
        ///
        /// <seealso cref="ZipEntry.ExtractExistingFile"/>
        /// <seealso cref="ZipEntry.Extract(string, ExtractExistingFileAction)"/>
        ///
        /// <example>
        /// This example extracts only the entries in a zip file that are .txt files,
        /// into a directory called "textfiles".
        /// <code lang="C#">
        /// using (ZipFile zip = ZipFile.Read("PackedDocuments.zip"))
        /// {
        ///   foreach (string s1 in zip.EntryFilenames)
        ///   {
        ///     if (s1.EndsWith(".txt"))
        ///     {
        ///       zip[s1].Extract("textfiles");
        ///     }
        ///   }
        /// }
        /// </code>
        /// <code lang="VB">
        ///   Using zip As ZipFile = ZipFile.Read("PackedDocuments.zip")
        ///       Dim s1 As String
        ///       For Each s1 In zip.EntryFilenames
        ///           If s1.EndsWith(".txt") Then
        ///               zip(s1).Extract("textfiles")
        ///           End If
        ///       Next
        ///   End Using
        /// </code>
        /// </example>
        ///
        /// <remarks>
        ///
        /// <para>
        ///   Using this method, existing entries in the filesystem will not be
        ///   overwritten. If you would like to force the overwrite of existing
        ///   files, see the <see cref="ExtractExistingFile"/> property, or call
        ///   <see cref="Extract(string, ExtractExistingFileAction)"/>.
        /// </para>
        ///
        /// <para>
        ///   See the remarks on the <see cref="LastModified"/> property, for some
        ///   details about how the last modified time of the created file is set.
        /// </para>
        /// </remarks>
        public void Extract(string baseDirectory)
        {
            InternalExtract(baseDirectory, null, null);
        }





        /// <summary>
        ///   Extract the entry to the filesystem, starting at the specified base
        ///   directory, and using the specified behavior when extraction would
        ///   overwrite an existing file.
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        ///   See the remarks on the <see cref="LastModified"/> property, for some
        ///   details about how the last modified time of the created file is set.
        /// </para>
        /// </remarks>
        ///
        /// <example>
        /// <code lang="C#">
        /// String sZipPath = "Airborne.zip";
        /// String sFilePath = "Readme.txt";
        /// String sRootFolder = "Digado";
        /// using (ZipFile zip = ZipFile.Read(sZipPath))
        /// {
        ///   if (zip.EntryFileNames.Contains(sFilePath))
        ///   {
        ///     // use the string indexer on the zip file
        ///     zip[sFileName].Extract(sRootFolder,
        ///                            ExtractExistingFileAction.OverwriteSilently);
        ///   }
        /// }
        /// </code>
        ///
        /// <code lang="VB">
        /// Dim sZipPath as String = "Airborne.zip"
        /// Dim sFilePath As String = "Readme.txt"
        /// Dim sRootFolder As String = "Digado"
        /// Using zip As ZipFile = ZipFile.Read(sZipPath)
        ///   If zip.EntryFileNames.Contains(sFilePath)
        ///     ' use the string indexer on the zip file
        ///     zip(sFilePath).Extract(sRootFolder, _
        ///                            ExtractExistingFileAction.OverwriteSilently)
        ///   End If
        /// End Using
        /// </code>
        /// </example>
        ///
        /// <param name="baseDirectory">the pathname of the base directory</param>
        /// <param name="extractExistingFile">
        /// The action to take if extraction would overwrite an existing file.
        /// </param>
        internal void Extract(string baseDirectory, ExtractExistingFileAction extractExistingFile)
        {
            ExtractExistingFile = extractExistingFile;
            InternalExtract(baseDirectory, null, null);
        }


        /// <summary>
        ///   Extract the entry to the filesystem, using the current working directory
        ///   and the specified password.
        /// </summary>
        ///
        /// <overloads>
        ///   This method has a bunch of overloads! One of them is sure to be
        ///   the right one for you...
        /// </overloads>
        ///
        /// <seealso cref="ZipEntry.ExtractExistingFile"/>
        /// <seealso cref="ZipEntry.ExtractWithPassword(ExtractExistingFileAction, string)"/>
        ///
        /// <remarks>
        ///
        /// <para>
        ///   Existing entries in the filesystem will not be overwritten. If you
        ///   would like to force the overwrite of existing files, see the <see
        ///   cref="ZipEntry.ExtractExistingFile"/>property, or call
        ///   <see
        ///   cref="ExtractWithPassword(ExtractExistingFileAction,string)"/>.
        /// </para>
        ///
        /// <para>
        ///   See the remarks on the <see cref="LastModified"/> property for some
        ///   details about how the "last modified" time of the created file is
        ///   set.
        /// </para>
        /// </remarks>
        ///
        /// <example>
        ///   In this example, entries that use encryption are extracted using a
        ///   particular password.
        /// <code>
        /// using (var zip = ZipFile.Read(FilePath))
        /// {
        ///     foreach (ZipEntry e in zip)
        ///     {
        ///         if (e.UsesEncryption)
        ///             e.ExtractWithPassword("Secret!");
        ///         else
        ///             e.Extract();
        ///     }
        /// }
        /// </code>
        /// <code lang="VB">
        /// Using zip As ZipFile = ZipFile.Read(FilePath)
        ///     Dim e As ZipEntry
        ///     For Each e In zip
        ///         If (e.UsesEncryption)
        ///           e.ExtractWithPassword("Secret!")
        ///         Else
        ///           e.Extract
        ///         End If
        ///     Next
        /// End Using
        /// </code>
        /// </example>
        /// <param name="password">The Password to use for decrypting the entry.</param>
        public void ExtractWithPassword(string password)
        {
            InternalExtract(".", null, password);
        }

        /// <summary>
        ///   Extract the entry to the filesystem, starting at the specified base
        ///   directory, and using the specified password.
        /// </summary>
        ///
        /// <seealso cref="ZipEntry.ExtractExistingFile"/>
        /// <seealso cref="ZipEntry.ExtractWithPassword(string, ExtractExistingFileAction, string)"/>
        ///
        /// <remarks>
        /// <para>
        ///   Existing entries in the filesystem will not be overwritten. If you
        ///   would like to force the overwrite of existing files, see the <see
        ///   cref="ZipEntry.ExtractExistingFile"/>property, or call
        ///   <see
        ///   cref="ExtractWithPassword(ExtractExistingFileAction,string)"/>.
        /// </para>
        ///
        /// <para>
        ///   See the remarks on the <see cref="LastModified"/> property, for some
        ///   details about how the last modified time of the created file is set.
        /// </para>
        /// </remarks>
        ///
        /// <param name="baseDirectory">The pathname of the base directory.</param>
        /// <param name="password">The Password to use for decrypting the entry.</param>
        public void ExtractWithPassword(string baseDirectory, string password)
        {
            InternalExtract(baseDirectory, null, password);
        }




        /// <summary>
        ///   Extract the entry to a file in the filesystem, relative to the
        ///   current directory, using the specified behavior when extraction
        ///   would overwrite an existing file.
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        ///   See the remarks on the <see cref="LastModified"/> property, for some
        ///   details about how the last modified time of the created file is set.
        /// </para>
        /// </remarks>
        ///
        /// <param name="password">The Password to use for decrypting the entry.</param>
        ///
        /// <param name="extractExistingFile">
        /// The action to take if extraction would overwrite an existing file.
        /// </param>
        internal void ExtractWithPassword(ExtractExistingFileAction extractExistingFile, string password)
        {
            ExtractExistingFile = extractExistingFile;
            InternalExtract(".", null, password);
        }



        /// <summary>
        ///   Extract the entry to the filesystem, starting at the specified base
        ///   directory, and using the specified behavior when extraction would
        ///   overwrite an existing file.
        /// </summary>
        ///
        /// <remarks>
        ///   See the remarks on the <see cref="LastModified"/> property, for some
        ///   details about how the last modified time of the created file is set.
        /// </remarks>
        ///
        /// <param name="baseDirectory">the pathname of the base directory</param>
        ///
        /// <param name="extractExistingFile">The action to take if extraction would
        /// overwrite an existing file.</param>
        ///
        /// <param name="password">The Password to use for decrypting the entry.</param>
        internal void ExtractWithPassword(string baseDirectory, ExtractExistingFileAction extractExistingFile, string password)
        {
            ExtractExistingFile = extractExistingFile;
            InternalExtract(baseDirectory, null, password);
        }

        /// <summary>
        ///   Extracts the entry to the specified stream, using the specified
        ///   Password.  For example, the caller could extract to Console.Out, or
        ///   to a MemoryStream.
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        ///   The caller can specify any write-able stream, for example a <see
        ///   cref="System.IO.FileStream"/>, a <see
        ///   cref="System.IO.MemoryStream"/>, or ASP.NET's
        ///   <c>Response.OutputStream</c>.  The content will be decrypted and
        ///   decompressed as necessary. If the entry is encrypted and no password
        ///   is provided, this method will throw.
        /// </para>
        /// <para>
        ///   The position on the stream is not reset by this method before it extracts.
        ///   You may want to call stream.Seek() before calling ZipEntry.Extract().
        /// </para>
        /// </remarks>
        ///
        ///
        /// <param name="stream">
        ///   the stream to which the entry should be extracted.
        /// </param>
        /// <param name="password">
        ///   The password to use for decrypting the entry.
        /// </param>
        public void ExtractWithPassword(Stream stream, string password)
        {
            InternalExtract(null, stream, password);
        }


        /// <summary>
        ///   Opens a readable stream corresponding to the zip entry in the
        ///   archive.  The stream decompresses and decrypts as necessary, as it
        ///   is read.
        /// </summary>
        ///
        /// <remarks>
        ///
        /// <para>
        ///   DotNetZip offers a variety of ways to extract entries from a zip
        ///   file.  This method allows an application to extract an entry by
        ///   reading a <see cref="System.IO.Stream"/>.
        /// </para>
        ///
        /// <para>
        ///   The return value is of type <see
        ///   cref="Ionic.Crc.CrcCalculatorStream"/>.  Use it as you would any
        ///   stream for reading.  When an application calls <see
        ///   cref="Stream.Read(byte[], int, int)"/> on that stream, it will
        ///   receive data from the zip entry that is decrypted and decompressed
        ///   as necessary.
        /// </para>
        ///
        /// <para>
        ///   <c>CrcCalculatorStream</c> adds one additional feature: it keeps a
        ///   CRC32 checksum on the bytes of the stream as it is read.  The CRC
        ///   value is available in the <see
        ///   cref="Ionic.Crc.CrcCalculatorStream.Crc"/> property on the
        ///   <c>CrcCalculatorStream</c>.  When the read is complete, your
        ///   application
        ///   <em>should</em> check this CRC against the <see cref="ZipEntry.Crc"/>
        ///   property on the <c>ZipEntry</c> to validate the content of the
        ///   ZipEntry. You don't have to validate the entry using the CRC, but
        ///   you should, to verify integrity. Check the example for how to do
        ///   this.
        /// </para>
        ///
        /// <para>
        ///   If the entry is protected with a password, then you need to provide
        ///   a password prior to calling <see cref="OpenReader()"/>, either by
        ///   setting the <see cref="Password"/> property on the entry, or the
        ///   <see cref="ZipFile.Password"/> property on the <c>ZipFile</c>
        ///   itself. Or, you can use <see cref="OpenReader(String)" />, the
        ///   overload of OpenReader that accepts a password parameter.
        /// </para>
        ///
        /// <para>
        ///   If you want to extract entry data into a write-able stream that is
        ///   already opened, like a <see cref="System.IO.FileStream"/>, do not
        ///   use this method. Instead, use <see cref="Extract(Stream)"/>.
        /// </para>
        ///
        /// <para>
        ///   Your application may use only one stream created by OpenReader() at
        ///   a time, and you should not call other Extract methods before
        ///   completing your reads on a stream obtained from OpenReader().  This
        ///   is because there is really only one source stream for the compressed
        ///   content.  A call to OpenReader() seeks in the source stream, to the
        ///   beginning of the compressed content.  A subsequent call to
        ///   OpenReader() on a different entry will seek to a different position
        ///   in the source stream, as will a call to Extract() or one of its
        ///   overloads.  This will corrupt the state for the decompressing stream
        ///   from the original call to OpenReader().
        /// </para>
        ///
        /// <para>
        ///    The <c>OpenReader()</c> method works only when the ZipEntry is
        ///    obtained from an instance of <c>ZipFile</c>. This method will throw
        ///    an exception if the ZipEntry is obtained from a ZipInputStream.
        /// </para>
        /// </remarks>
        ///
        /// <example>
        ///   This example shows how to open a zip archive, then read in a named
        ///   entry via a stream. After the read loop is complete, the code
        ///   compares the calculated during the read loop with the expected CRC
        ///   on the <c>ZipEntry</c>, to verify the extraction.
        /// <code>
        /// using (ZipFile zip = new ZipFile(ZipFileToRead))
        /// {
        ///   ZipEntry e1= zip["Elevation.mp3"];
        ///   using (Ionic.Zlib.CrcCalculatorStream s = e1.OpenReader())
        ///   {
        ///     byte[] buffer = new byte[4096];
        ///     int n, totalBytesRead= 0;
        ///     do {
        ///       n = s.Read(buffer,0, buffer.Length);
        ///       totalBytesRead+=n;
        ///     } while (n&gt;0);
        ///      if (s.Crc32 != e1.Crc32)
        ///       throw new Exception(string.Format("The Zip Entry failed the CRC Check. (0x{0:X8}!=0x{1:X8})", s.Crc32, e1.Crc32));
        ///      if (totalBytesRead != e1.UncompressedSize)
        ///       throw new Exception(string.Format("We read an unexpected number of bytes. ({0}!={1})", totalBytesRead, e1.UncompressedSize));
        ///   }
        /// }
        /// </code>
        /// <code lang="VB">
        ///   Using zip As New ZipFile(ZipFileToRead)
        ///       Dim e1 As ZipEntry = zip.Item("Elevation.mp3")
        ///       Using s As Ionic.Zlib.CrcCalculatorStream = e1.OpenReader
        ///           Dim n As Integer
        ///           Dim buffer As Byte() = New Byte(4096) {}
        ///           Dim totalBytesRead As Integer = 0
        ///           Do
        ///               n = s.Read(buffer, 0, buffer.Length)
        ///               totalBytesRead = (totalBytesRead + n)
        ///           Loop While (n &gt; 0)
        ///           If (s.Crc32 &lt;&gt; e1.Crc32) Then
        ///               Throw New Exception(String.Format("The Zip Entry failed the CRC Check. (0x{0:X8}!=0x{1:X8})", s.Crc32, e1.Crc32))
        ///           End If
        ///           If (totalBytesRead &lt;&gt; e1.UncompressedSize) Then
        ///               Throw New Exception(String.Format("We read an unexpected number of bytes. ({0}!={1})", totalBytesRead, e1.UncompressedSize))
        ///           End If
        ///       End Using
        ///   End Using
        /// </code>
        /// </example>
        /// <seealso cref="ZipEntry.Extract(System.IO.Stream)"/>
        /// <returns>The Stream for reading.</returns>
        internal Ionic.Crc.CrcCalculatorStream OpenReader()
        {
            // workitem 10923
            if (_container.ZipFile == null)
                throw new InvalidOperationException("Use OpenReader() only with ZipFile.");

            // use the entry password if it is non-null,
            // else use the zipfile password, which is possibly null
            return InternalOpenReader(this._Password ?? this._container.Password);
        }

        /// <summary>
        ///   Opens a readable stream for an encrypted zip entry in the archive.
        ///   The stream decompresses and decrypts as necessary, as it is read.
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        ///   See the documentation on the <see cref="OpenReader()"/> method for
        ///   full details. This overload allows the application to specify a
        ///   password for the <c>ZipEntry</c> to be read.
        /// </para>
        /// </remarks>
        ///
        /// <param name="password">The password to use for decrypting the entry.</param>
        /// <returns>The Stream for reading.</returns>
        internal Ionic.Crc.CrcCalculatorStream OpenReader(string password)
        {
            // workitem 10923
            if (_container.ZipFile == null)
                throw new InvalidOperationException("Use OpenReader() only with ZipFile.");

            return InternalOpenReader(password);
        }



        internal Ionic.Crc.CrcCalculatorStream InternalOpenReader(string password)
        {
            ValidateCompression();
            ValidateEncryption();
            SetupCryptoForExtract(password);

            // workitem 7958
            if (this._Source != ZipEntrySource.ZipFile)
                throw new BadStateException("You must call ZipFile.Save before calling OpenReader");

            // LeftToRead is a count of bytes remaining to be read (out)
            // from the stream AFTER decompression and decryption.
            // It is the uncompressed size, unless ... there is no compression in which
            // case ...?  :< I'm not sure why it's not always UncompressedSize
            Int64 LeftToRead = (_CompressionMethod_FromZipFile == (short)CompressionMethod.None)
                ? this._CompressedFileDataSize
                : this.UncompressedSize;

            Stream input = this.ArchiveStream;

            this.ArchiveStream.Seek(this.FileDataPosition, SeekOrigin.Begin);
            // workitem 10178
            Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream);

            _inputDecryptorStream = GetExtractDecryptor(input);
            Stream input3 = GetExtractDecompressor(_inputDecryptorStream);

            return new Ionic.Crc.CrcCalculatorStream(input3, LeftToRead);
        }



        private void OnExtractProgress(Int64 bytesWritten, Int64 totalBytesToWrite)
        {
            if (_container.ZipFile != null)
            _ioOperationCanceled = _container.ZipFile.OnExtractBlock(this, bytesWritten, totalBytesToWrite);
        }


        private void OnBeforeExtract(string path)
        {
            // When in the context of a ZipFile.ExtractAll, the events are generated from
            // the ZipFile method, not from within the ZipEntry instance. (why?)
            // Therefore we suppress the events originating from the ZipEntry method.
            if (_container.ZipFile != null)
            {
                if (!_container.ZipFile._inExtractAll)
                {
                    _ioOperationCanceled = _container.ZipFile.OnSingleEntryExtract(this, path, true);
                }
            }
        }

        private void OnAfterExtract(string path)
        {
            // When in the context of a ZipFile.ExtractAll, the events are generated from
            // the ZipFile method, not from within the ZipEntry instance. (why?)
            // Therefore we suppress the events originating from the ZipEntry method.
            if (_container.ZipFile != null)
            {
                if (!_container.ZipFile._inExtractAll)
                {
                    _container.ZipFile.OnSingleEntryExtract(this, path, false);
                }
            }
        }

        private void OnExtractExisting(string path)
        {
            if (_container.ZipFile != null)
                _ioOperationCanceled = _container.ZipFile.OnExtractExisting(this, path);
        }

        private static void ReallyDelete(string fileName)
        {
            // workitem 7881
            // reset ReadOnly bit if necessary
#if NETCF
            if ( (NetCfFile.GetAttributes(fileName) & (uint)FileAttributes.ReadOnly) == (uint)FileAttributes.ReadOnly)
                NetCfFile.SetAttributes(fileName, (uint)FileAttributes.Normal);
#elif SILVERLIGHT
#else
            if ((File.GetAttributes(fileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                File.SetAttributes(fileName, FileAttributes.Normal);
#endif
            File.Delete(fileName);
        }


        private void WriteStatus(string format, params Object[] args)
        {
            if (_container.ZipFile != null && _container.ZipFile.Verbose) _container.ZipFile.StatusMessageTextWriter.WriteLine(format, args);
        }


        // Pass in either basedir or s, but not both.
        // In other words, you can extract to a stream or to a directory (filesystem), but not both!
        // The Password param is required for encrypted entries.
        private void InternalExtract(string baseDir, Stream outstream, string password)
        {
            // workitem 7958
            if (_container == null)
                throw new BadStateException("This entry is an orphan");

            // workitem 10355
            if (_container.ZipFile == null)
                throw new InvalidOperationException("Use Extract() only with ZipFile.");

            _container.ZipFile.Reset(false);

            if (this._Source != ZipEntrySource.ZipFile)
                throw new BadStateException("You must call ZipFile.Save before calling any Extract method");

            OnBeforeExtract(baseDir);
            _ioOperationCanceled = false;
            string targetFileName = null;
            Stream output = null;
            bool fileExistsBeforeExtraction = false;
            bool checkLaterForResetDirTimes = false;
            try
            {
                ValidateCompression();
                ValidateEncryption();

                if (ValidateOutput(baseDir, outstream, out targetFileName))
                {
                    WriteStatus("extract dir {0}...", targetFileName);
                    // if true, then the entry was a directory and has been created.
                    // We need to fire the Extract Event.
                    OnAfterExtract(baseDir);
                    return;
                }

                // workitem 10639
                // do we want to extract to a regular filesystem file?
                if (targetFileName != null)
                {
                    // Check for extracting to a previously extant file. The user
                    // can specify bejavior for that case: overwrite, don't
                    // overwrite, and throw.  Also, if the file exists prior to
                    // extraction, it affects exception handling: whether to delete
                    // the target of extraction or not.  This check needs to be done
                    // before the password check is done, because password check may
                    // throw a BadPasswordException, which triggers the catch,
                    // wherein the extant file may be deleted if not flagged as
                    // pre-existing.
                    if (File.Exists(targetFileName))
                    {
                        fileExistsBeforeExtraction = true;
                        int rc = CheckExtractExistingFile(baseDir, targetFileName);
                        if (rc == 2) goto ExitTry; // cancel
                        if (rc == 1) return; // do not overwrite
                    }
                }

                // If no password explicitly specified, use the password on the entry itself,
                // or on the zipfile itself.
                string p = password ?? this._Password ?? this._container.Password;
                if (_Encryption_FromZipFile != EncryptionAlgorithm.None)
                {
                    if (p == null)
                        throw new BadPasswordException();
                    SetupCryptoForExtract(p);
                }


                // set up the output stream
                if (targetFileName != null)
                {
                    WriteStatus("extract file {0}...", targetFileName);
                    targetFileName += ".tmp";
                    var dirName = Path.GetDirectoryName(targetFileName);
                    // ensure the target path exists
                    if (!Directory.Exists(dirName))
                    {
                        // we create the directory here, but we do not set the
                        // create/modified/accessed times on it because it is being
                        // created implicitly, not explcitly. There's no entry in the
                        // zip archive for the directory.
                        Directory.CreateDirectory(dirName);
                    }
                    else
                    {
                        // workitem 8264
                        if (_container.ZipFile != null)
                            checkLaterForResetDirTimes = _container.ZipFile._inExtractAll;
                    }

                    // File.Create(CreateNew) will overwrite any existing file.
                    output = new FileStream(targetFileName, FileMode.CreateNew);
                }
                else
                {
                    WriteStatus("extract entry {0} to stream...", FileName);
                    output = outstream;
                }


                if (_ioOperationCanceled)
                    goto ExitTry;

                Int32 ActualCrc32 = ExtractOne(output);

                if (_ioOperationCanceled)
                    goto ExitTry;

                VerifyCrcAfterExtract(ActualCrc32);

                if (targetFileName != null)
                {
                    output.Close();
                    output = null;

                    // workitem 10639
                    // move file to permanent home
                    string tmpName = targetFileName;
                    string zombie = null;
                    targetFileName = tmpName.Substring(0,tmpName.Length-4);

                    if (fileExistsBeforeExtraction)
                    {
                        // An AV program may hold the target file open, which means
                        // File.Delete() will succeed, though the actual deletion
                        // remains pending. This will prevent a subsequent
                        // File.Move() from succeeding. To avoid this, when the file
                        // already exists, we need to replace it in 3 steps:
                        //
                        //     1. rename the existing file to a zombie name;
                        //     2. rename the extracted file from the temp name to
                        //        the target file name;
                        //     3. delete the zombie.
                        //
                        zombie = targetFileName + ".PendingOverwrite";
                        File.Move(targetFileName, zombie);
                    }

                    File.Move(tmpName, targetFileName);
                    _SetTimes(targetFileName, true);

                    if (zombie != null && File.Exists(zombie))
                        ReallyDelete(zombie);

                    // workitem 8264
                    if (checkLaterForResetDirTimes)
                    {
                        // This is sort of a hack.  What I do here is set the time on
                        // the parent directory, every time a file is extracted into
                        // it.  If there is a directory with 1000 files, then I set
                        // the time on the dir, 1000 times. This allows the directory
                        // to have times that reflect the actual time on the entry in
                        // the zip archive.

                        // String.Contains is not available on .NET CF 2.0
                        if (this.FileName.IndexOf('/') != -1)
                        {
                            string dirname = Path.GetDirectoryName(this.FileName);
                            if (this._container.ZipFile[dirname] == null)
                            {
                                _SetTimes(Path.GetDirectoryName(targetFileName), false);
                            }
                        }
                    }

#if NETCF
                    // workitem 7926 - version made by OS can be zero or 10
                    if ((_VersionMadeBy & 0xFF00) == 0x0a00 || (_VersionMadeBy & 0xFF00) == 0x0000)
                        NetCfFile.SetAttributes(targetFileName, (uint)_ExternalFileAttrs);

#else
                    // workitem 7071
                    //
                    // We can only apply attributes if they are relevant to the NTFS
                    // OS.  Must do this LAST because it may involve a ReadOnly bit,
                    // which would prevent us from setting the time, etc.
                    //
                    // workitem 7926 - version made by OS can be zero (FAT) or 10
                    // (NTFS)
                    if ((_VersionMadeBy & 0xFF00) == 0x0a00 || (_VersionMadeBy & 0xFF00) == 0x0000)
                        File.SetAttributes(targetFileName, (FileAttributes)_ExternalFileAttrs);
#endif
                }

                OnAfterExtract(baseDir);

                ExitTry: ;
            }
            catch (Exception)
            {
                _ioOperationCanceled = true;
                throw;
            }
            finally
            {
                if (_ioOperationCanceled)
                {
                    if (targetFileName != null)
                    {
                        try
                        {
                            if (output != null) output.Close();
                            // An exception has occurred. If the file exists, check
                            // to see if it existed before we tried extracting.  If
                            // it did not, attempt to remove the target file. There
                            // is a small possibility that the existing file has
                            // been extracted successfully, overwriting a previously
                            // existing file, and an exception was thrown after that
                            // but before final completion (setting times, etc). In
                            // that case the file will remain, even though some
                            // error occurred.  Nothing to be done about it.
                            if (File.Exists(targetFileName) && !fileExistsBeforeExtraction)
                                File.Delete(targetFileName);

                        }
                        finally { }
                    }
                }
            }
        }


#if NOT
        internal void CalcWinZipAesMac(Stream input)
        {
            if (Encryption == EncryptionAlgorithm.WinZipAes128 ||
                Encryption == EncryptionAlgorithm.WinZipAes256)
            {
                if (input is WinZipAesCipherStream)
                    wzs = input as WinZipAesCipherStream;

                else if (input is Ionic.Zlib.CrcCalculatorStream)
                {
                    xxx;
                }

            }
        }
#endif


        internal void VerifyCrcAfterExtract(Int32 actualCrc32)
        {

#if AESCRYPTO
                // After extracting, Validate the CRC32
                if (actualCrc32 != _Crc32)
                {
                    // CRC is not meaningful with WinZipAES and AES method 2 (AE-2)
                    if ((Encryption != EncryptionAlgorithm.WinZipAes128 &&
                         Encryption != EncryptionAlgorithm.WinZipAes256)
                        || _WinZipAesMethod != 0x02)
                        throw new BadCrcException("CRC error: the file being extracted appears to be corrupted. " +
                                                  String.Format("Expected 0x{0:X8}, Actual 0x{1:X8}", _Crc32, actualCrc32));
                }

                // ignore MAC if the size of the file is zero
                if (this.UncompressedSize == 0)
                    return;

                // calculate the MAC
                if (Encryption == EncryptionAlgorithm.WinZipAes128 ||
                    Encryption == EncryptionAlgorithm.WinZipAes256)
                {
                    WinZipAesCipherStream wzs = _inputDecryptorStream as WinZipAesCipherStream;
                    _aesCrypto_forExtract.CalculatedMac = wzs.FinalAuthentication;

                    _aesCrypto_forExtract.ReadAndVerifyMac(this.ArchiveStream); // throws if MAC is bad
                    // side effect: advances file position.
                }




#else
            if (actualCrc32 != _Crc32)
                throw new BadCrcException("CRC error: the file being extracted appears to be corrupted. " +
                                          String.Format("Expected 0x{0:X8}, Actual 0x{1:X8}", _Crc32, actualCrc32));
#endif
        }




        private int CheckExtractExistingFile(string baseDir, string targetFileName)
        {
            int loop = 0;
            // returns: 0 == extract, 1 = don't, 2 = cancel
            do
            {
                switch (ExtractExistingFile)
                {
                    case ExtractExistingFileAction.OverwriteSilently:
                        WriteStatus("the file {0} exists; will overwrite it...", targetFileName);
                        return 0;

                    case ExtractExistingFileAction.DoNotOverwrite:
                        WriteStatus("the file {0} exists; not extracting entry...", FileName);
                        OnAfterExtract(baseDir);
                        return 1;

                    case ExtractExistingFileAction.InvokeExtractProgressEvent:
                        if (loop>0)
                            throw new ZipException(String.Format("The file {0} already exists.", targetFileName));
                        OnExtractExisting(baseDir);
                        if (_ioOperationCanceled)
                            return 2;

                        // loop around
                        break;

                    case ExtractExistingFileAction.Throw:
                    default:
                        throw new ZipException(String.Format("The file {0} already exists.", targetFileName));
                }
                loop++;
            }
            while (true);
        }




        private void _CheckRead(int nbytes)
        {
            if (nbytes == 0)
                throw new BadReadException(String.Format("bad read of entry {0} from compressed archive.",
                             this.FileName));
        }


        private Stream _inputDecryptorStream;

        private Int32 ExtractOne(Stream output)
        {
            Int32 CrcResult = 0;
            Stream input = this.ArchiveStream;

            try
            {
                // change for workitem 8098
                input.Seek(this.FileDataPosition, SeekOrigin.Begin);
                // workitem 10178
                Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(input);

                byte[] bytes = new byte[BufferSize];

                // The extraction process varies depending on how the entry was
                // stored.  It could have been encrypted, and it coould have
                // been compressed, or both, or neither. So we need to check
                // both the encryption flag and the compression flag, and take
                // the proper action in all cases.

                Int64 LeftToRead = (_CompressionMethod_FromZipFile != (short)CompressionMethod.None)
                    ? this.UncompressedSize
                    : this._CompressedFileDataSize;

                // Get a stream that either decrypts or not.
                _inputDecryptorStream = GetExtractDecryptor(input);

                Stream input3 = GetExtractDecompressor( _inputDecryptorStream );

                Int64 bytesWritten = 0;
                // As we read, we maybe decrypt, and then we maybe decompress. Then we write.
                using (var s1 = new Ionic.Crc.CrcCalculatorStream(input3))
                {
                    while (LeftToRead > 0)
                    {
                        //Console.WriteLine("ExtractOne: LeftToRead {0}", LeftToRead);

                        // Casting LeftToRead down to an int is ok here in the else clause,
                        // because that only happens when it is less than bytes.Length,
                        // which is much less than MAX_INT.
                        int len = (LeftToRead > bytes.Length) ? bytes.Length : (int)LeftToRead;
                        int n = s1.Read(bytes, 0, len);

                        // must check data read - essential for detecting corrupt zip files
                        _CheckRead(n);

                        output.Write(bytes, 0, n);
                        LeftToRead -= n;
                        bytesWritten += n;

                        // fire the progress event, check for cancels
                        OnExtractProgress(bytesWritten, UncompressedSize);
                        if (_ioOperationCanceled)
                        {
                            break;
                        }
                    }

                    CrcResult = s1.Crc;
                }
            }
            finally
            {
                var zss = input as ZipSegmentedStream;
                if (zss != null)
                {
#if NETCF
                    zss.Close();
#else
                    // need to dispose it
                    zss.Dispose();
#endif
                    _archiveStream = null;
                }
            }

            return CrcResult;
        }



        internal Stream GetExtractDecompressor(Stream input2)
        {
            // get a stream that either decompresses or not.
            switch (_CompressionMethod_FromZipFile)
            {
                case (short)CompressionMethod.None:
                    return input2;
                case (short)CompressionMethod.Deflate:
                    return new Ionic.Zlib.DeflateStream(input2, Ionic.Zlib.CompressionMode.Decompress, true);
#if BZIP
                case (short)CompressionMethod.BZip2:
                    return new Ionic.BZip2.BZip2InputStream(input2, true);
#endif
            }

            return null;
        }



        internal Stream GetExtractDecryptor(Stream input)
        {
            Stream input2 = null;
            if (_Encryption_FromZipFile == EncryptionAlgorithm.PkzipWeak)
                input2 = new ZipCipherStream(input, _zipCrypto_forExtract, CryptoMode.Decrypt);

#if AESCRYPTO
            else if (_Encryption_FromZipFile == EncryptionAlgorithm.WinZipAes128 ||
                 _Encryption_FromZipFile == EncryptionAlgorithm.WinZipAes256)
                input2 = new WinZipAesCipherStream(input, _aesCrypto_forExtract, _CompressedFileDataSize, CryptoMode.Decrypt);
#endif

            else
                input2 = input;

            return input2;
        }




        internal void _SetTimes(string fileOrDirectory, bool isFile)
        {
#if SILVERLIGHT
                    // punt on setting file times
#else
            // workitem 8807:
            // Because setting the time is not considered to be a fatal error,
            // and because other applications can interfere with the setting
            // of a time on a directory, we're going to swallow IO exceptions
            // in this method.

            try
            {
                if (_ntfsTimesAreSet)
                {
#if NETCF
                    // workitem 7944: set time should not be a fatal error on CF
                    int rc = NetCfFile.SetTimes(fileOrDirectory, _Ctime, _Atime, _Mtime);
                    if ( rc != 0)
                    {
                        WriteStatus("Warning: SetTimes failed.  entry({0})  file({1})  rc({2})",
                                    FileName, fileOrDirectory, rc);
                    }
#else
                    if (isFile)
                    {
                        // It's possible that the extract was cancelled, in which case,
                        // the file does not exist.
                        if (File.Exists(fileOrDirectory))
                        {
                            File.SetCreationTimeUtc(fileOrDirectory, _Ctime);
                            File.SetLastAccessTimeUtc(fileOrDirectory, _Atime);
                            File.SetLastWriteTimeUtc(fileOrDirectory, _Mtime);
                        }
                    }
                    else
                    {
                        // It's possible that the extract was cancelled, in which case,
                        // the directory does not exist.
                        if (Directory.Exists(fileOrDirectory))
                        {
                            Directory.SetCreationTimeUtc(fileOrDirectory, _Ctime);
                            Directory.SetLastAccessTimeUtc(fileOrDirectory, _Atime);
                            Directory.SetLastWriteTimeUtc(fileOrDirectory, _Mtime);
                        }
                    }
#endif
                }
                else
                {
                    // workitem 6191
                    DateTime AdjustedLastModified = Ionic.Zip.SharedUtilities.AdjustTime_Reverse(LastModified);

#if NETCF
                    int rc = NetCfFile.SetLastWriteTime(fileOrDirectory, AdjustedLastModified);

                    if ( rc != 0)
                    {
                        WriteStatus("Warning: SetLastWriteTime failed.  entry({0})  file({1})  rc({2})",
                                    FileName, fileOrDirectory, rc);
                    }
#else
                    if (isFile)
                        File.SetLastWriteTime(fileOrDirectory, AdjustedLastModified);
                    else
                        Directory.SetLastWriteTime(fileOrDirectory, AdjustedLastModified);
#endif
                }
            }
            catch (System.IO.IOException ioexc1)
            {
                WriteStatus("failed to set time on {0}: {1}", fileOrDirectory, ioexc1.Message);
            }
#endif
        }


        #region Support methods


        // workitem 7968
        private string UnsupportedAlgorithm
        {
            get
            {
                string alg = String.Empty;
                switch (_UnsupportedAlgorithmId)
                {
                    case 0:
                        alg = "--";
                        break;
                    case 0x6601:
                        alg = "DES";
                        break;
                    case 0x6602: // - RC2 (version needed to extract < 5.2)
                        alg = "RC2";
                        break;
                    case 0x6603: // - 3DES 168
                        alg = "3DES-168";
                        break;
                    case 0x6609: // - 3DES 112
                        alg = "3DES-112";
                        break;
                    case 0x660E: // - AES 128
                        alg = "PKWare AES128";
                        break;
                    case 0x660F: // - AES 192
                        alg = "PKWare AES192";
                        break;
                    case 0x6610: // - AES 256
                        alg = "PKWare AES256";
                        break;
                    case 0x6702: // - RC2 (version needed to extract >= 5.2)
                        alg = "RC2";
                        break;
                    case 0x6720: // - Blowfish
                        alg = "Blowfish";
                        break;
                    case 0x6721: // - Twofish
                        alg = "Twofish";
                        break;
                    case 0x6801: // - RC4
                        alg = "RC4";
                        break;
                    case 0xFFFF: // - Unknown algorithm
                    default:
                        alg = String.Format("Unknown (0x{0:X4})", _UnsupportedAlgorithmId);
                        break;
                }
                return alg;
            }
        }

        // workitem 7968
        private string UnsupportedCompressionMethod
        {
            get
            {
                string meth = String.Empty;
                switch ((int)_CompressionMethod)
                {
                    case 0:
                        meth = "Store";
                        break;
                    case 1:
                        meth = "Shrink";
                        break;
                    case 8:
                        meth = "DEFLATE";
                        break;
                    case 9:
                        meth = "Deflate64";
                        break;
                    case 12:
                        meth = "BZIP2"; // only if BZIP not compiled in
                        break;
                    case 14:
                        meth = "LZMA";
                        break;
                    case 19:
                        meth = "LZ77";
                        break;
                    case 98:
                        meth = "PPMd";
                        break;
                    default:
                        meth = String.Format("Unknown (0x{0:X4})", _CompressionMethod);
                        break;
                }
                return meth;
            }
        }


        internal void ValidateEncryption()
        {
            if (Encryption != EncryptionAlgorithm.PkzipWeak &&
#if AESCRYPTO
 Encryption != EncryptionAlgorithm.WinZipAes128 &&
                Encryption != EncryptionAlgorithm.WinZipAes256 &&
#endif
 Encryption != EncryptionAlgorithm.None)
            {
                // workitem 7968
                if (_UnsupportedAlgorithmId != 0)
                    throw new ZipException(String.Format("Cannot extract: Entry {0} is encrypted with an algorithm not supported by DotNetZip: {1}",
                                                         FileName, UnsupportedAlgorithm));
                else
                    throw new ZipException(String.Format("Cannot extract: Entry {0} uses an unsupported encryption algorithm ({1:X2})",
                                                         FileName, (int)Encryption));
            }
        }


        private void ValidateCompression()
        {
            if ((_CompressionMethod_FromZipFile != (short)CompressionMethod.None) &&
                (_CompressionMethod_FromZipFile != (short)CompressionMethod.Deflate)
#if BZIP
                && (_CompressionMethod_FromZipFile != (short)CompressionMethod.BZip2)
#endif
                )
                throw new ZipException(String.Format("Entry {0} uses an unsupported compression method (0x{1:X2}, {2})",
                                                          FileName, _CompressionMethod_FromZipFile, UnsupportedCompressionMethod));
        }


        private void SetupCryptoForExtract(string password)
        {
            //if (password == null) return;
            if (_Encryption_FromZipFile == EncryptionAlgorithm.None) return;

            if (_Encryption_FromZipFile == EncryptionAlgorithm.PkzipWeak)
            {
                if (password == null)
                    throw new ZipException("Missing password.");

                this.ArchiveStream.Seek(this.FileDataPosition - 12, SeekOrigin.Begin);
                // workitem 10178
                Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream);
                _zipCrypto_forExtract = ZipCrypto.ForRead(password, this);
            }

#if AESCRYPTO
            else if (_Encryption_FromZipFile == EncryptionAlgorithm.WinZipAes128 ||
                 _Encryption_FromZipFile == EncryptionAlgorithm.WinZipAes256)
            {
                if (password == null)
                    throw new ZipException("Missing password.");

                // If we already have a WinZipAesCrypto object in place, use it.
                // It can be set up in the ReadDirEntry(), or during a previous Extract.
                if (_aesCrypto_forExtract != null)
                {
                    _aesCrypto_forExtract.Password = password;
                }
                else
                {
                    int sizeOfSaltAndPv = GetLengthOfCryptoHeaderBytes(_Encryption_FromZipFile);
                    this.ArchiveStream.Seek(this.FileDataPosition - sizeOfSaltAndPv, SeekOrigin.Begin);
                    // workitem 10178
                    Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream);
                    int keystrength = GetKeyStrengthInBits(_Encryption_FromZipFile);
                    _aesCrypto_forExtract = WinZipAesCrypto.ReadFromStream(password, keystrength, this.ArchiveStream);
                }
            }
#endif
        }



        /// <summary>
        /// Validates that the args are consistent.
        /// </summary>
        /// <remarks>
        /// Only one of {baseDir, outStream} can be non-null.
        /// If baseDir is non-null, then the outputFile is created.
        /// </remarks>
        private bool ValidateOutput(string basedir, Stream outstream, out string outFileName)
        {
            if (basedir != null)
            {
                // Sometimes the name on the entry starts with a slash.
                // Rather than unpack to the root of the volume, we're going to
                // drop the slash and unpack to the specified base directory.
                string f = this.FileName.Replace("\\","/");

                // workitem 11772: remove drive letter with separator
                if (f.IndexOf(':') == 1)
                    f= f.Substring(2);

                if (f.StartsWith("/"))
                    f= f.Substring(1);

                // String.Contains is not available on .NET CF 2.0

                if (_container.ZipFile.FlattenFoldersOnExtract)
                    outFileName = Path.Combine(basedir,
                                              (f.IndexOf('/') != -1) ? Path.GetFileName(f) : f);
                else
                    outFileName = Path.Combine(basedir, f);

                // workitem 10639
                outFileName = outFileName.Replace("/","\\");

                // check if it is a directory
                if ((IsDirectory) || (FileName.EndsWith("/")))
                {
                    if (!Directory.Exists(outFileName))
                    {
                        Directory.CreateDirectory(outFileName);
                        _SetTimes(outFileName, false);
                    }
                    else
                    {
                        // the dir exists, maybe we want to overwrite times.
                        if (ExtractExistingFile == ExtractExistingFileAction.OverwriteSilently)
                            _SetTimes(outFileName, false);
                    }
                    return true;  // true == all done, caller will return
                }
                return false;  // false == work to do by caller.
            }

            if (outstream != null)
            {
                outFileName = null;
                if ((IsDirectory) || (FileName.EndsWith("/")))
                {
                    // extract a directory to streamwriter?  nothing to do!
                    return true;  // true == all done!  caller can return
                }
                return false;
            }

            throw new ArgumentNullException("outstream");
        }


        #endregion

    }
}
