ZipArchive.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / MS / Internal / IO / Zip / ZipArchive.cs / 1305600 / ZipArchive.cs

                            //------------------------------------------------------------------------------ 
//-------------   *** WARNING ***
//-------------    This file is part of a legally monitored development project.
//-------------    Do not check in changes to this project.  Do not raid bugs on this
//-------------    code in the main PS database.  Do not contact the owner of this 
//-------------    code directly.  Contact the legal team at �ZSLegal� for assistance.
//-------------   *** WARNING *** 
//----------------------------------------------------------------------------- 

//----------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//  This is an internal class that enables interactions with Zip archives 
//  for OPC scenarios
// 
// History:
//  11/19/2004: IgorBel: Initial creation.
//
//----------------------------------------------------------------------------- 

using System; 
using System.IO; 
using System.Diagnostics;
using System.Collections; 
using System.Globalization;
using System.Runtime.Serialization;
using System.Windows;
using MS.Internal.WindowsBase; 

namespace MS.Internal.IO.Zip 
{ 
    /// 
    ///  This is the main clas of the ZIP IO internal APIs. It has 2 stsatic constructors 
    /// OpenOnFile and OpenOnStream. It provides client app with ability to manipulate
    /// a Zip Archive (create, open, open/add/delete file items).
    /// 
    internal sealed class ZipArchive : IDisposable 
    {
        //------------------------------------------------------ 
        // 
        //  Public Members
        // 
        //-----------------------------------------------------
        // None

        //------------------------------------------------------ 
        //
        //  Internal Constructors 
        // 
        //------------------------------------------------------
        // None 

        //-----------------------------------------------------
        //
        // Internal API Methods (although these methods are marked as 
        // Internal, they are part of the internal ZIP IO API surface
        // 
        //------------------------------------------------------ 
        /// 
        ///  Static constructor File based constructor. all parameteres are obvious. 
        ///  This constructor wil  open the file in requested mode, and it will not do any futher parsing.
        ///
        /// In the case of Create/CreateNew, it will also prebuild in cached in-memory
        /// EndOfCentralDirectoryRecord (which is a minimal zip file requirement), so that if user 
        /// chooses to close right after he will get a file with just EndOfCentralDirectoryRecord.
        ///  
        internal static ZipArchive OpenOnFile(string path, FileMode mode, FileAccess access, FileShare share, bool streaming) 
        {
            if (mode == FileMode.OpenOrCreate || mode == FileMode.Open) 
            {
                // for OpenOrCreate cases we need to check whether it is an exisiting file of size 0.
                // Files of size 0 are onsidered invalid ZipArchives. If we skip this check here, later we wouldn't be able to distinguish
                // between brand new file being created as a result of OpenOrCreate mode, or old 0 length file being open as a result of 
                // OpenOrCreate mode.
                FileInfo fileInfo = new FileInfo(path); 
 
                if (fileInfo.Exists && (fileInfo.Length == 0))
                { 
                    throw new FileFormatException(SR.Get(SRID.ZipZeroSizeFileIsNotValidArchive));
                }
            }
 
            ZipArchive archive = null;
            FileStream archiveStream = null; 
 
            // We would like to run initialization after openning stream in try/catch block
            // so that if anything goes wrong we can close the stream (release file handler) 
            try
            {
                archiveStream = new FileStream(path, mode, access, share, 4096, streaming);
 
                ValidateModeAccessShareStreaming(archiveStream, mode, access, share, streaming);
 
                archive = new ZipArchive(archiveStream, mode, access, streaming, true); 
            }
            catch 
            {
                if (archiveStream != null)
                {
                    archiveStream.Close(); 
                }
 
                throw; 
            }
 
            return archive;
        }

        ///  
        ///  Static constructor Stream based constructor. all parameteres are obvious.
        ///  This constructor wil not do any futher parsing. 
        /// 
        /// In the case of Create/CreateNew, it will also prebuild in cached in-memory
        /// EndOfCentralDirectoryRecord (which is a minimal zip file requirement), so that if user 
        /// chooses to close right after he will get a file with just EndOfCentralDirectoryRecord.
        /// 
        internal static ZipArchive OpenOnStream(Stream stream, FileMode mode, FileAccess access, bool streaming)
        { 
            // we can assume FileShare.None, as there is absolutely nothing we can do
            // about other people working with the underlying storage 
            ValidateModeAccessShareStreaming(stream, mode, access, FileShare.None, streaming); 

            if (stream.CanSeek) 
            {
                bool emptyStream = (stream.Length == 0);

                switch (mode) 
                {
                    // for Open cases we need to check whether it is an existing file of size 0. 
                    // Streams of size 0 are considered invalid ZipArchives. 
                    case FileMode.Open:
                        if (emptyStream) 
                        {
                            throw new FileFormatException(SR.Get(SRID.ZipZeroSizeFileIsNotValidArchive));
                        }
                        break; 

                    // for Create cases, we need to check if the stream is empty or not 
                    case FileMode.CreateNew: 
                        if (!emptyStream)
                        { 
                            throw new IOException(SR.Get(SRID.CreateNewOnNonEmptyStream));
                        }
                        break;
                    case FileMode.Create: 
                        if (!emptyStream)
                        { 
                            // discard existing data 
                            stream.SetLength(0);
                        } 
                        break;
                }
            }
 
            return new ZipArchive(stream, mode, access, streaming, false);
        } 
 

        ///  
        ///  This method will result in a complete parsing of the EndOfCentralDirectory
        /// and CentralDirectory records (if it hasn't been done yet).
        /// After that (assuming no duplicates were found). It will create in appropriate
        /// in memory Local FileHeaders and Central Directory Headers. 
        /// 
        internal ZipFileInfo AddFile(string zipFileName, CompressionMethodEnum compressionMethod, DeflateOptionEnum deflateOption) 
        { 
            CheckDisposed();
 
            if (_openAccess == FileAccess.Read)
            {
                throw new InvalidOperationException(SR.Get(SRID.CanNotWriteInReadOnlyMode));
            } 

            // Validate parameteres 
            zipFileName = ZipIOBlockManager.ValidateNormalizeFileName(zipFileName); 

            if ((compressionMethod != CompressionMethodEnum.Stored) && 
                (compressionMethod != CompressionMethodEnum.Deflated))
            {
                throw new ArgumentOutOfRangeException("compressionMethod");
            } 

            // non-contiguous range requires more complex test 
            if (deflateOption < DeflateOptionEnum.Normal || ( 
                deflateOption > DeflateOptionEnum.SuperFast && deflateOption != DeflateOptionEnum.None))
            { 
                throw new ArgumentOutOfRangeException("deflateOption");
            }

            // Check for duplicates , 
            if (FileExists(zipFileName))
            { 
                throw new System.InvalidOperationException(SR.Get(SRID.AttemptedToCreateDuplicateFileName)); 
            }
 
            // Create Local File Block through Block Manager
            ZipIOLocalFileBlock fileBlock = _blockManager.CreateLocalFileBlock(zipFileName, compressionMethod, deflateOption);

            //build new ZipFileInfo and add reference to the collection, so we can keep track of the instances of the ZipFileInfo, 
            // that were given out  and invalidate any collection that was returned on GetFiles calls
            ZipFileInfo zipFileInfo = new ZipFileInfo(this, fileBlock); 
            ZipFileInfoDictionary.Add(zipFileInfo.Name, zipFileInfo); 

            return zipFileInfo; 
        }

        /// 
        ///  This method will result in a complete parsing of the EndOfCentralDirectory 
        /// and CentralDirectory records (if it hasn't been done yet).
        /// After that (assuming the file was found). It will parse the apropriate local file block 
        /// header and data descriptor (if present). 
        /// 
        internal ZipFileInfo GetFile(string zipFileName) 
        {
            CheckDisposed();

            if (_openAccess == FileAccess.Write) 
            {
                throw new InvalidOperationException(SR.Get(SRID.CanNotReadInWriteOnlyMode)); 
            } 

            // Validate parameteres 
            zipFileName = ZipIOBlockManager.ValidateNormalizeFileName(zipFileName);

            // try to get it from the ZipFileInfo dictionary
            if (ZipFileInfoDictionary.Contains(zipFileName)) 
            {
                // this ZipFileInfo was already built through AddFile or GetFile(s) 
                // we have this cached 
                return (ZipFileInfo)(ZipFileInfoDictionary[zipFileName]);
            } 
            else
            {
                // we need to check whether it is present in the central directory
                if (!FileExists(zipFileName)) 
                {
                    throw new InvalidOperationException(SR.Get(SRID.FileDoesNotExists)); 
                } 

                // Load Local File Block through Block Manager 
                ZipIOLocalFileBlock fileBlock = _blockManager.LoadLocalFileBlock(zipFileName);

                // build new ZipFileInfo and add reference to the collection, so we can keep track of the instances of the ZipFileInfo,
                // that were given out  and invalidate any collection that was returned on GetFiles calls 
                ZipFileInfo zipFileInfo = new ZipFileInfo(this, fileBlock);
 
                //this should invalidate any outstanding collections 
                ZipFileInfoDictionary.Add(zipFileInfo.Name, zipFileInfo);
 
                return zipFileInfo;
            }
        }
 
        /// 
        ///  This method will result in a complete parsing of the EndOfCentralDirectory 
        /// and CentralDirectory records (if it hasn't been done yet). 
        /// After that it will check whether central directory contains the file.
        /// It will not attempt the parsing of the local file headers / descriptors. 
        /// 
        internal bool FileExists (string zipFileName)
        {
            CheckDisposed(); 

            // Validate parameteres 
            zipFileName = ZipIOBlockManager.ValidateNormalizeFileName(zipFileName); 

            return _blockManager.CentralDirectoryBlock.FileExists(zipFileName); 
        }


        ///  
        ///  This method will result in a complete parsing of the EndOfCentralDirectory
        /// and CentralDirectory records (if it hasn't been done yet). 
        /// After that it will check whether central directory contains the file. 
        /// If it is present it will parse local fileheader, and remove their in memory
        /// representation 
        /// 
        internal void DeleteFile (string zipFileName)
        {
            CheckDisposed(); 

            if (_openAccess == FileAccess.Read) 
            { 
                throw new InvalidOperationException(SR.Get(SRID.CanNotWriteInReadOnlyMode));
            } 

            // Validate parameteres
            zipFileName = ZipIOBlockManager.ValidateNormalizeFileName(zipFileName);
 
            if (FileExists(zipFileName)) // is it in central Directory ?
            { 
                ZipFileInfo fileInfoToBeDeleted  = GetFile(zipFileName); 

                //this should invalidate any outstanding collections 
                // and update central directory status as appropriate
                ZipFileInfoDictionary.Remove(zipFileName);

                //this should remove the local file block 
                // from the blockManager's collection
                _blockManager.RemoveLocalFileBlock(fileInfoToBeDeleted.LocalFileBlock); 
            } 
        }
 
        /// 
        ///  This method will result in a complete parsing of the EndOfCentralDirectory
        /// and CentralDirectory records (if it hasn't been done yet).
        /// After that it will go through allfiles in the central directory and parse their 
        /// local headers and desciptors one by one.
        ///  
        internal ZipFileInfoCollection GetFiles() 
        {
            CheckDisposed(); 

            if (_openAccess == FileAccess.Write)
            {
                throw new InvalidOperationException(SR.Get(SRID.CanNotReadInWriteOnlyMode)); 
            }
 
            // We need to scan through the central Directory, and for each file 
            // call GetFile(fileName), which will result in adding missing (not loaded)
            // information to the ZipFileInfoDictionary. 
            foreach(string fileName in _blockManager.CentralDirectoryBlock.GetFileNamesCollection())
            {
                GetFile(fileName);  // fileName must be validated and normalized at this
                                            // point by the central directory parsing routine 
            }
            return new ZipFileInfoCollection(ZipFileInfoDictionary.Values); 
        } 

        ///  
        ///  This method will result in a complete Flushing of any outstanding data in buffers and
        /// any streams ever returned by the GetStream calls.This call results in Archive file that
        /// has a completely valid state. If application were to crash right afte the Flush is complete,
        /// the resulting files would be a "valid" Zip archive 
        /// 
        internal void Flush() 
        { 
            CheckDisposed();
            _blockManager.Save(false); 
        }

        /// 
        /// Results in a complete Flush of all the outstanding buffers and closing/disposing all of the objects 
        /// ZipFileInfo, Streams ZipArchive.
        ///  
        internal void Close() 
        {
            Dispose(); 
        }

        /// 
        /// Results in a complete Flush of all the outstanding buffers and closing/disposing all of the objects 
        /// ZipFileInfo, Streams ZipArchive.
        ///  
        public void Dispose() 
        {
            Dispose(true); 
            // GC.SuppressFinalize(this);  // Because this class is sealed and there is no Finalizer,
                                                        // there is no need for this call. Leaving it in case we decide to unseal it
        }
 
        /// 
        /// Throw if version needed to extract is not supported 
        ///  
        /// version to inspect
        static internal void VerifyVersionNeededToExtract(UInt16 version) 
        {
            // strictly enforce this list
            switch (version)
            { 
                case (UInt16)ZipIOVersionNeededToExtract.StoredData: break;
                case (UInt16)ZipIOVersionNeededToExtract.VolumeLabel: break; 
                case (UInt16)ZipIOVersionNeededToExtract.DeflatedData: break; 
                case (UInt16)ZipIOVersionNeededToExtract.Zip64FileFormat: break;
                default: 
                    throw new NotSupportedException(SR.Get(SRID.NotSupportedVersionNeededToExtract));
            }
        }
 
        //-----------------------------------------------------
        // 
        //  Internal Properties 
        //
        //----------------------------------------------------- 
        /// 
        /// Read only property, that returns the value of FileAccess that
        /// was passed into the OpenOnFile or OpenOnStream call
        ///  
        internal FileAccess OpenAccess
        { 
            get 
            {
                CheckDisposed(); 
                return _openAccess;
            }
        }
 
//  This functionality commented out in order to comply with FX Cop rule
//  AvoidUncalledPrivateCode. However, because of a chance that this functionality 
//  might eventually get public exposure we would like to keep this code around 
#if ZIP_IO_PUBLIC
 
        /// 
        /// Returns Comment field from the End Of Central Directory Record.
        /// Therefore, call to this property might result in some parsing.
        /// If the End Of Central Directory isn't parsed yet, it will be as a 
        /// result of querying this property.
        ///  
        internal string Comment 
        {
            get 
            {
                CheckDisposed();
                return _blockManager.EndOfCentralDirectoryBlock.Comment;
            } 
        }
#endif 
 

        //----------------------------------------------------- 
        //
        // Internal NON API Methods (these methods are marked as
        // Internal, and they are trully internal and not the part of the
        // internal ZIP IO API surface 
        //
        //------------------------------------------------------ 
 
        //-----------------------------------------------------
        // 
        //  Private Constructors
        //
        //------------------------------------------------------
        ///  
        /// This private constructor isonly supposed to be called by the
        /// OpenOnFile and OpenOnStream static members. 
        ///  
        /// 
        ///  
        /// 
        /// 
        /// true if this class is responsible for closing the archiveStream
        private ZipArchive(Stream archiveStream, FileMode mode, FileAccess access, bool streaming, bool ownStream) 
        {
            // as this contructor is only called from the static member 
            // all checks should have been done before 

            _blockManager = new ZipIOBlockManager(archiveStream, streaming, ownStream); 

            _openMode = mode;
            _openAccess = access;
 
            // In case of "create" we also need to create at least an end of Central Directory Record.
            // For FileMode OpenOrCreate we use stream Length to distinguish open and create scenarios. 
            // Implications of this decision is that existing file of size 0 opened in OpenOrCreate Mode 
            // will be treated as a newly/created file.
            if ((_openMode == FileMode.CreateNew) || 
               (_openMode == FileMode.Create) ||
               ((_openMode == FileMode.OpenOrCreate) && archiveStream.Length == 0))
            {
                _blockManager.CreateEndOfCentralDirectoryBlock(); 
            }
            else 
            { 
                _blockManager.LoadEndOfCentralDirectoryBlock();
            } 
        }

        //------------------------------------------------------
        // 
        //  Private Methods
        // 
        //----------------------------------------------------- 

        ///  
        /// Dispose(bool)
        /// 
        /// 
        private void Dispose(bool disposing) 
        {
            if (disposing) 
            { 
                if (!_disposedFlag)
                { 
                    try
                    {
                        // allow this in Debug mode to catch any place where we accidentally
                        // make something dirty when we are read-only 
#if !DEBUG
                        if (_openAccess == FileAccess.ReadWrite || _openAccess == FileAccess.Write) 
#endif 
                        {
                            _blockManager.Save(true); 
                        }

                        ((IDisposable)_blockManager).Dispose();
                    } 
                    finally
                    { 
                        _disposedFlag = true; 
                    }
                } 
            }
        }

        ///  
        /// This is function is called by the OpenOnFile and OpenOnStream in order
        /// to validate parameteresgiven to those functions. The combinations of valid 
        /// parameters is quite complex and not obvious, so after basic range checks, 
        /// it is actually using a lookup table to answer the question whether the given
        /// parameter  combination is valid or not. 
        /// 
        static private void ValidateModeAccessShareStreaming(Stream stream, FileMode mode, FileAccess access, FileShare share, bool streaming)
        {
            if (stream == null) 
            {
                throw new ArgumentNullException("stream"); 
            } 

            //////////// 
            // filter out values that are out of enum ranges first
            ////////////
            ValidateModeAccessShareValidEnums(mode, access, share);
 
            ////////////
            // filter out values that are not supported regardless of other parameters 
            // but still validate enum members 
            ////////////
            ValidateModeAccessShareSupportedEnums(mode, share); 

            ////////////
            // let's makes sure that given stream is capable of supporting required functionality
            //////////// 
            ValidateModeAccessStreamStreamingCombinations(stream, access, streaming);
 
            //////////// 
            //let's make sure that comnbintaion of mode, access,share,,streaming
            // parameters is supported 
            ////////////
            int intMode =  Convert.ToInt32(mode, CultureInfo.InvariantCulture);
            int intAccess = Convert.ToInt32(access, CultureInfo.InvariantCulture);
            int intShare = Convert.ToInt32(share, CultureInfo.InvariantCulture); 
            int intStreaming = Convert.ToInt32(streaming, CultureInfo.InvariantCulture);
            for(int i=0; i<_validOpenParameters.GetLength(0); i++) 
            { 
                if ((_validOpenParameters [i,0] == intMode) &&
                    (_validOpenParameters [i,1] == intAccess) && 
                    (_validOpenParameters [i,2] == intShare) &&
                    (_validOpenParameters [i,3] == intStreaming))
                {
                    return; 
                }
            } 
 
            throw new ArgumentException(SR.Get(SRID.UnsupportedCombinationOfModeAccessShareStreaming));
        } 

        static private void ValidateModeAccessStreamStreamingCombinations(Stream stream, FileAccess access, bool streaming)
        {
            //////////// 
            // let's makes sure that given stream is capable of supporting required functionality
            //////////// 
            if ((access== FileAccess.Read || access == FileAccess.ReadWrite) && !stream.CanRead) 
            {
                throw new ArgumentException(SR.Get(SRID.CanNotReadDataFromStreamWhichDoesNotSupportReading)); 
            }

            // if user want to be able to write stream needs to support it
            if ((access == FileAccess.Write || access == FileAccess.ReadWrite) && !stream.CanWrite) 
            {
                throw new ArgumentException(SR.Get(SRID.CanNotWriteDataToStreamWhichDoesNotSupportWriting)); 
            } 

            // if user works in non-streaming mode we need to Seek on underlying stream 
            if (! streaming && !stream.CanSeek)
            {
                throw new ArgumentException(SR.Get(SRID.CanNotOperateOnStreamWhichDoesNotSupportSeeking));
            } 
        }
 
        static private void ValidateModeAccessShareSupportedEnums(FileMode mode, FileShare share) 
        {
            //////////// 
            // filter out values that are not supported regardless of other parameters
            // but still validate enum members
            ////////////
             if (mode == FileMode.Append || mode == FileMode.Truncate) 
            {
                throw new NotSupportedException(SR.Get(SRID.TruncateAppendModesNotSupported)); 
            } 
            else if (share != FileShare.Read && share != FileShare.None)
            { 
                // later as we get to streaming other FileShare values will be supported too
                throw new NotSupportedException (SR.Get(SRID.OnlyFileShareReadAndFileShareNoneSupported));
            }
        } 

        static private void ValidateModeAccessShareValidEnums(FileMode mode, FileAccess access, FileShare share) 
        { 
            ////////////
            // filter out values that are out of enum ranges first 
            ////////////
            if ((mode != FileMode.Append) && (mode != FileMode.Create) && (mode != FileMode.CreateNew) && (mode != FileMode.Open)
                && (mode != FileMode.OpenOrCreate) && (mode != FileMode.Truncate))
            { 
                throw new ArgumentOutOfRangeException("mode");
            } 
            else if ((access != FileAccess.Read) && (access != FileAccess.ReadWrite) && (access != FileAccess.Write)) 
            {
                throw new ArgumentOutOfRangeException("access"); 
            }
            else if ((share != FileShare.Delete) && (share != FileShare.Inheritable) && (share != FileShare.None) &&
                (share != FileShare.Read) && (share != FileShare.ReadWrite) && (share != FileShare.Write))
            { 
                throw new ArgumentOutOfRangeException("share");
            } 
        } 

        ///  
        /// Throws exception if object already Disposed/Closed.
        /// 
        private void CheckDisposed()
        { 
            if (_disposedFlag)
            { 
                throw new ObjectDisposedException(null, SR.Get(SRID.ZipArchiveDisposed)); 
            }
        } 

        //------------------------------------------------------
        //
        //  Private Properties 
        //
        //----------------------------------------------------- 
        ///  
        /// This private property is used as a mean to achieve lazy memory allocation for the
        /// hashtable that maintains a cahce of the returned instrances of ZipFileInfo(s). 
        /// This hashtable uses file names as keys in the case insensitive and culture invariant fashion
        /// 
        private IDictionary ZipFileInfoDictionary
        { 
            get
            { 
                if (_zipFileInfoDictionary == null) 
                {
                                // ordinal case sensitive comparison 
                    _zipFileInfoDictionary = new Hashtable(_zipFileInfoDictionaryInitialSize, StringComparer.Ordinal);
                }
                return _zipFileInfoDictionary;
            } 
        }
 
        //----------------------------------------------------- 
        //
        //  Private Fields 
        //
        //-----------------------------------------------------

        // This 2 dimensional table is used by the ValidateModeAccessShareStreaming 
        // function as a set of valid parameter combinations
        static private int[,] _validOpenParameters = new int[,] 
        {   // FileMode                             // FileAccess                     / FileShare                     // streaming 
            {(int)FileMode.Create,             (int)FileAccess.Write,        (int)FileShare.None,        1},
            {(int)FileMode.Create,             (int)FileAccess.Write,        (int)FileShare.Read,        1}, 
            {(int)FileMode.Create,             (int)FileAccess.ReadWrite, (int)FileShare.None,        0},
            {(int)FileMode.CreateNew,       (int)FileAccess.Write,        (int)FileShare.None,        1},
            {(int)FileMode.CreateNew,       (int)FileAccess.Write,        (int)FileShare.Read,        1},
            {(int)FileMode.CreateNew,       (int)FileAccess.ReadWrite, (int)FileShare.None,        0}, 
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.None,        1},
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.None,        0}, 
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.Read,        1}, 
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.Read,        0},
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.Write,        1}, 
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.ReadWrite, 1},
            {(int)FileMode.Open,               (int)FileAccess.ReadWrite,  (int)FileShare.None,        0},
            {(int)FileMode.OpenOrCreate,  (int)FileAccess.ReadWrite,  (int)FileShare.None,        0}
        }; 

        // modes that were used for openning (OpenOnStream or OpenOnFile), 
        // there is no way to change these values after class is constructed 
        private FileMode _openMode;
        private FileAccess  _openAccess; 

        private bool _disposedFlag;

        // reference to the ZipIOBlockManager, this reference is instantiated as 
        // a part of the OpenOnFile/OpenOnStream contruction
        private ZipIOBlockManager _blockManager; 
 
        // this is a Dictionary of all the ZipFileInfos that were given out.
        // It uses file name as key in case insensitive and culture invariant fashion. 
        // all members of the class are supposed to use this field indirectly through
        // ZipFileInfoDictionary property, as ZipFileInfoDictionary is respnsible
        // for lazy allocation of the hashtable.
        private IDictionary _zipFileInfoDictionary; 
        private const int _zipFileInfoDictionaryInitialSize = 50;
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------ 
//-------------   *** WARNING ***
//-------------    This file is part of a legally monitored development project.
//-------------    Do not check in changes to this project.  Do not raid bugs on this
//-------------    code in the main PS database.  Do not contact the owner of this 
//-------------    code directly.  Contact the legal team at �ZSLegal� for assistance.
//-------------   *** WARNING *** 
//----------------------------------------------------------------------------- 

//----------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//  This is an internal class that enables interactions with Zip archives 
//  for OPC scenarios
// 
// History:
//  11/19/2004: IgorBel: Initial creation.
//
//----------------------------------------------------------------------------- 

using System; 
using System.IO; 
using System.Diagnostics;
using System.Collections; 
using System.Globalization;
using System.Runtime.Serialization;
using System.Windows;
using MS.Internal.WindowsBase; 

namespace MS.Internal.IO.Zip 
{ 
    /// 
    ///  This is the main clas of the ZIP IO internal APIs. It has 2 stsatic constructors 
    /// OpenOnFile and OpenOnStream. It provides client app with ability to manipulate
    /// a Zip Archive (create, open, open/add/delete file items).
    /// 
    internal sealed class ZipArchive : IDisposable 
    {
        //------------------------------------------------------ 
        // 
        //  Public Members
        // 
        //-----------------------------------------------------
        // None

        //------------------------------------------------------ 
        //
        //  Internal Constructors 
        // 
        //------------------------------------------------------
        // None 

        //-----------------------------------------------------
        //
        // Internal API Methods (although these methods are marked as 
        // Internal, they are part of the internal ZIP IO API surface
        // 
        //------------------------------------------------------ 
        /// 
        ///  Static constructor File based constructor. all parameteres are obvious. 
        ///  This constructor wil  open the file in requested mode, and it will not do any futher parsing.
        ///
        /// In the case of Create/CreateNew, it will also prebuild in cached in-memory
        /// EndOfCentralDirectoryRecord (which is a minimal zip file requirement), so that if user 
        /// chooses to close right after he will get a file with just EndOfCentralDirectoryRecord.
        ///  
        internal static ZipArchive OpenOnFile(string path, FileMode mode, FileAccess access, FileShare share, bool streaming) 
        {
            if (mode == FileMode.OpenOrCreate || mode == FileMode.Open) 
            {
                // for OpenOrCreate cases we need to check whether it is an exisiting file of size 0.
                // Files of size 0 are onsidered invalid ZipArchives. If we skip this check here, later we wouldn't be able to distinguish
                // between brand new file being created as a result of OpenOrCreate mode, or old 0 length file being open as a result of 
                // OpenOrCreate mode.
                FileInfo fileInfo = new FileInfo(path); 
 
                if (fileInfo.Exists && (fileInfo.Length == 0))
                { 
                    throw new FileFormatException(SR.Get(SRID.ZipZeroSizeFileIsNotValidArchive));
                }
            }
 
            ZipArchive archive = null;
            FileStream archiveStream = null; 
 
            // We would like to run initialization after openning stream in try/catch block
            // so that if anything goes wrong we can close the stream (release file handler) 
            try
            {
                archiveStream = new FileStream(path, mode, access, share, 4096, streaming);
 
                ValidateModeAccessShareStreaming(archiveStream, mode, access, share, streaming);
 
                archive = new ZipArchive(archiveStream, mode, access, streaming, true); 
            }
            catch 
            {
                if (archiveStream != null)
                {
                    archiveStream.Close(); 
                }
 
                throw; 
            }
 
            return archive;
        }

        ///  
        ///  Static constructor Stream based constructor. all parameteres are obvious.
        ///  This constructor wil not do any futher parsing. 
        /// 
        /// In the case of Create/CreateNew, it will also prebuild in cached in-memory
        /// EndOfCentralDirectoryRecord (which is a minimal zip file requirement), so that if user 
        /// chooses to close right after he will get a file with just EndOfCentralDirectoryRecord.
        /// 
        internal static ZipArchive OpenOnStream(Stream stream, FileMode mode, FileAccess access, bool streaming)
        { 
            // we can assume FileShare.None, as there is absolutely nothing we can do
            // about other people working with the underlying storage 
            ValidateModeAccessShareStreaming(stream, mode, access, FileShare.None, streaming); 

            if (stream.CanSeek) 
            {
                bool emptyStream = (stream.Length == 0);

                switch (mode) 
                {
                    // for Open cases we need to check whether it is an existing file of size 0. 
                    // Streams of size 0 are considered invalid ZipArchives. 
                    case FileMode.Open:
                        if (emptyStream) 
                        {
                            throw new FileFormatException(SR.Get(SRID.ZipZeroSizeFileIsNotValidArchive));
                        }
                        break; 

                    // for Create cases, we need to check if the stream is empty or not 
                    case FileMode.CreateNew: 
                        if (!emptyStream)
                        { 
                            throw new IOException(SR.Get(SRID.CreateNewOnNonEmptyStream));
                        }
                        break;
                    case FileMode.Create: 
                        if (!emptyStream)
                        { 
                            // discard existing data 
                            stream.SetLength(0);
                        } 
                        break;
                }
            }
 
            return new ZipArchive(stream, mode, access, streaming, false);
        } 
 

        ///  
        ///  This method will result in a complete parsing of the EndOfCentralDirectory
        /// and CentralDirectory records (if it hasn't been done yet).
        /// After that (assuming no duplicates were found). It will create in appropriate
        /// in memory Local FileHeaders and Central Directory Headers. 
        /// 
        internal ZipFileInfo AddFile(string zipFileName, CompressionMethodEnum compressionMethod, DeflateOptionEnum deflateOption) 
        { 
            CheckDisposed();
 
            if (_openAccess == FileAccess.Read)
            {
                throw new InvalidOperationException(SR.Get(SRID.CanNotWriteInReadOnlyMode));
            } 

            // Validate parameteres 
            zipFileName = ZipIOBlockManager.ValidateNormalizeFileName(zipFileName); 

            if ((compressionMethod != CompressionMethodEnum.Stored) && 
                (compressionMethod != CompressionMethodEnum.Deflated))
            {
                throw new ArgumentOutOfRangeException("compressionMethod");
            } 

            // non-contiguous range requires more complex test 
            if (deflateOption < DeflateOptionEnum.Normal || ( 
                deflateOption > DeflateOptionEnum.SuperFast && deflateOption != DeflateOptionEnum.None))
            { 
                throw new ArgumentOutOfRangeException("deflateOption");
            }

            // Check for duplicates , 
            if (FileExists(zipFileName))
            { 
                throw new System.InvalidOperationException(SR.Get(SRID.AttemptedToCreateDuplicateFileName)); 
            }
 
            // Create Local File Block through Block Manager
            ZipIOLocalFileBlock fileBlock = _blockManager.CreateLocalFileBlock(zipFileName, compressionMethod, deflateOption);

            //build new ZipFileInfo and add reference to the collection, so we can keep track of the instances of the ZipFileInfo, 
            // that were given out  and invalidate any collection that was returned on GetFiles calls
            ZipFileInfo zipFileInfo = new ZipFileInfo(this, fileBlock); 
            ZipFileInfoDictionary.Add(zipFileInfo.Name, zipFileInfo); 

            return zipFileInfo; 
        }

        /// 
        ///  This method will result in a complete parsing of the EndOfCentralDirectory 
        /// and CentralDirectory records (if it hasn't been done yet).
        /// After that (assuming the file was found). It will parse the apropriate local file block 
        /// header and data descriptor (if present). 
        /// 
        internal ZipFileInfo GetFile(string zipFileName) 
        {
            CheckDisposed();

            if (_openAccess == FileAccess.Write) 
            {
                throw new InvalidOperationException(SR.Get(SRID.CanNotReadInWriteOnlyMode)); 
            } 

            // Validate parameteres 
            zipFileName = ZipIOBlockManager.ValidateNormalizeFileName(zipFileName);

            // try to get it from the ZipFileInfo dictionary
            if (ZipFileInfoDictionary.Contains(zipFileName)) 
            {
                // this ZipFileInfo was already built through AddFile or GetFile(s) 
                // we have this cached 
                return (ZipFileInfo)(ZipFileInfoDictionary[zipFileName]);
            } 
            else
            {
                // we need to check whether it is present in the central directory
                if (!FileExists(zipFileName)) 
                {
                    throw new InvalidOperationException(SR.Get(SRID.FileDoesNotExists)); 
                } 

                // Load Local File Block through Block Manager 
                ZipIOLocalFileBlock fileBlock = _blockManager.LoadLocalFileBlock(zipFileName);

                // build new ZipFileInfo and add reference to the collection, so we can keep track of the instances of the ZipFileInfo,
                // that were given out  and invalidate any collection that was returned on GetFiles calls 
                ZipFileInfo zipFileInfo = new ZipFileInfo(this, fileBlock);
 
                //this should invalidate any outstanding collections 
                ZipFileInfoDictionary.Add(zipFileInfo.Name, zipFileInfo);
 
                return zipFileInfo;
            }
        }
 
        /// 
        ///  This method will result in a complete parsing of the EndOfCentralDirectory 
        /// and CentralDirectory records (if it hasn't been done yet). 
        /// After that it will check whether central directory contains the file.
        /// It will not attempt the parsing of the local file headers / descriptors. 
        /// 
        internal bool FileExists (string zipFileName)
        {
            CheckDisposed(); 

            // Validate parameteres 
            zipFileName = ZipIOBlockManager.ValidateNormalizeFileName(zipFileName); 

            return _blockManager.CentralDirectoryBlock.FileExists(zipFileName); 
        }


        ///  
        ///  This method will result in a complete parsing of the EndOfCentralDirectory
        /// and CentralDirectory records (if it hasn't been done yet). 
        /// After that it will check whether central directory contains the file. 
        /// If it is present it will parse local fileheader, and remove their in memory
        /// representation 
        /// 
        internal void DeleteFile (string zipFileName)
        {
            CheckDisposed(); 

            if (_openAccess == FileAccess.Read) 
            { 
                throw new InvalidOperationException(SR.Get(SRID.CanNotWriteInReadOnlyMode));
            } 

            // Validate parameteres
            zipFileName = ZipIOBlockManager.ValidateNormalizeFileName(zipFileName);
 
            if (FileExists(zipFileName)) // is it in central Directory ?
            { 
                ZipFileInfo fileInfoToBeDeleted  = GetFile(zipFileName); 

                //this should invalidate any outstanding collections 
                // and update central directory status as appropriate
                ZipFileInfoDictionary.Remove(zipFileName);

                //this should remove the local file block 
                // from the blockManager's collection
                _blockManager.RemoveLocalFileBlock(fileInfoToBeDeleted.LocalFileBlock); 
            } 
        }
 
        /// 
        ///  This method will result in a complete parsing of the EndOfCentralDirectory
        /// and CentralDirectory records (if it hasn't been done yet).
        /// After that it will go through allfiles in the central directory and parse their 
        /// local headers and desciptors one by one.
        ///  
        internal ZipFileInfoCollection GetFiles() 
        {
            CheckDisposed(); 

            if (_openAccess == FileAccess.Write)
            {
                throw new InvalidOperationException(SR.Get(SRID.CanNotReadInWriteOnlyMode)); 
            }
 
            // We need to scan through the central Directory, and for each file 
            // call GetFile(fileName), which will result in adding missing (not loaded)
            // information to the ZipFileInfoDictionary. 
            foreach(string fileName in _blockManager.CentralDirectoryBlock.GetFileNamesCollection())
            {
                GetFile(fileName);  // fileName must be validated and normalized at this
                                            // point by the central directory parsing routine 
            }
            return new ZipFileInfoCollection(ZipFileInfoDictionary.Values); 
        } 

        ///  
        ///  This method will result in a complete Flushing of any outstanding data in buffers and
        /// any streams ever returned by the GetStream calls.This call results in Archive file that
        /// has a completely valid state. If application were to crash right afte the Flush is complete,
        /// the resulting files would be a "valid" Zip archive 
        /// 
        internal void Flush() 
        { 
            CheckDisposed();
            _blockManager.Save(false); 
        }

        /// 
        /// Results in a complete Flush of all the outstanding buffers and closing/disposing all of the objects 
        /// ZipFileInfo, Streams ZipArchive.
        ///  
        internal void Close() 
        {
            Dispose(); 
        }

        /// 
        /// Results in a complete Flush of all the outstanding buffers and closing/disposing all of the objects 
        /// ZipFileInfo, Streams ZipArchive.
        ///  
        public void Dispose() 
        {
            Dispose(true); 
            // GC.SuppressFinalize(this);  // Because this class is sealed and there is no Finalizer,
                                                        // there is no need for this call. Leaving it in case we decide to unseal it
        }
 
        /// 
        /// Throw if version needed to extract is not supported 
        ///  
        /// version to inspect
        static internal void VerifyVersionNeededToExtract(UInt16 version) 
        {
            // strictly enforce this list
            switch (version)
            { 
                case (UInt16)ZipIOVersionNeededToExtract.StoredData: break;
                case (UInt16)ZipIOVersionNeededToExtract.VolumeLabel: break; 
                case (UInt16)ZipIOVersionNeededToExtract.DeflatedData: break; 
                case (UInt16)ZipIOVersionNeededToExtract.Zip64FileFormat: break;
                default: 
                    throw new NotSupportedException(SR.Get(SRID.NotSupportedVersionNeededToExtract));
            }
        }
 
        //-----------------------------------------------------
        // 
        //  Internal Properties 
        //
        //----------------------------------------------------- 
        /// 
        /// Read only property, that returns the value of FileAccess that
        /// was passed into the OpenOnFile or OpenOnStream call
        ///  
        internal FileAccess OpenAccess
        { 
            get 
            {
                CheckDisposed(); 
                return _openAccess;
            }
        }
 
//  This functionality commented out in order to comply with FX Cop rule
//  AvoidUncalledPrivateCode. However, because of a chance that this functionality 
//  might eventually get public exposure we would like to keep this code around 
#if ZIP_IO_PUBLIC
 
        /// 
        /// Returns Comment field from the End Of Central Directory Record.
        /// Therefore, call to this property might result in some parsing.
        /// If the End Of Central Directory isn't parsed yet, it will be as a 
        /// result of querying this property.
        ///  
        internal string Comment 
        {
            get 
            {
                CheckDisposed();
                return _blockManager.EndOfCentralDirectoryBlock.Comment;
            } 
        }
#endif 
 

        //----------------------------------------------------- 
        //
        // Internal NON API Methods (these methods are marked as
        // Internal, and they are trully internal and not the part of the
        // internal ZIP IO API surface 
        //
        //------------------------------------------------------ 
 
        //-----------------------------------------------------
        // 
        //  Private Constructors
        //
        //------------------------------------------------------
        ///  
        /// This private constructor isonly supposed to be called by the
        /// OpenOnFile and OpenOnStream static members. 
        ///  
        /// 
        ///  
        /// 
        /// 
        /// true if this class is responsible for closing the archiveStream
        private ZipArchive(Stream archiveStream, FileMode mode, FileAccess access, bool streaming, bool ownStream) 
        {
            // as this contructor is only called from the static member 
            // all checks should have been done before 

            _blockManager = new ZipIOBlockManager(archiveStream, streaming, ownStream); 

            _openMode = mode;
            _openAccess = access;
 
            // In case of "create" we also need to create at least an end of Central Directory Record.
            // For FileMode OpenOrCreate we use stream Length to distinguish open and create scenarios. 
            // Implications of this decision is that existing file of size 0 opened in OpenOrCreate Mode 
            // will be treated as a newly/created file.
            if ((_openMode == FileMode.CreateNew) || 
               (_openMode == FileMode.Create) ||
               ((_openMode == FileMode.OpenOrCreate) && archiveStream.Length == 0))
            {
                _blockManager.CreateEndOfCentralDirectoryBlock(); 
            }
            else 
            { 
                _blockManager.LoadEndOfCentralDirectoryBlock();
            } 
        }

        //------------------------------------------------------
        // 
        //  Private Methods
        // 
        //----------------------------------------------------- 

        ///  
        /// Dispose(bool)
        /// 
        /// 
        private void Dispose(bool disposing) 
        {
            if (disposing) 
            { 
                if (!_disposedFlag)
                { 
                    try
                    {
                        // allow this in Debug mode to catch any place where we accidentally
                        // make something dirty when we are read-only 
#if !DEBUG
                        if (_openAccess == FileAccess.ReadWrite || _openAccess == FileAccess.Write) 
#endif 
                        {
                            _blockManager.Save(true); 
                        }

                        ((IDisposable)_blockManager).Dispose();
                    } 
                    finally
                    { 
                        _disposedFlag = true; 
                    }
                } 
            }
        }

        ///  
        /// This is function is called by the OpenOnFile and OpenOnStream in order
        /// to validate parameteresgiven to those functions. The combinations of valid 
        /// parameters is quite complex and not obvious, so after basic range checks, 
        /// it is actually using a lookup table to answer the question whether the given
        /// parameter  combination is valid or not. 
        /// 
        static private void ValidateModeAccessShareStreaming(Stream stream, FileMode mode, FileAccess access, FileShare share, bool streaming)
        {
            if (stream == null) 
            {
                throw new ArgumentNullException("stream"); 
            } 

            //////////// 
            // filter out values that are out of enum ranges first
            ////////////
            ValidateModeAccessShareValidEnums(mode, access, share);
 
            ////////////
            // filter out values that are not supported regardless of other parameters 
            // but still validate enum members 
            ////////////
            ValidateModeAccessShareSupportedEnums(mode, share); 

            ////////////
            // let's makes sure that given stream is capable of supporting required functionality
            //////////// 
            ValidateModeAccessStreamStreamingCombinations(stream, access, streaming);
 
            //////////// 
            //let's make sure that comnbintaion of mode, access,share,,streaming
            // parameters is supported 
            ////////////
            int intMode =  Convert.ToInt32(mode, CultureInfo.InvariantCulture);
            int intAccess = Convert.ToInt32(access, CultureInfo.InvariantCulture);
            int intShare = Convert.ToInt32(share, CultureInfo.InvariantCulture); 
            int intStreaming = Convert.ToInt32(streaming, CultureInfo.InvariantCulture);
            for(int i=0; i<_validOpenParameters.GetLength(0); i++) 
            { 
                if ((_validOpenParameters [i,0] == intMode) &&
                    (_validOpenParameters [i,1] == intAccess) && 
                    (_validOpenParameters [i,2] == intShare) &&
                    (_validOpenParameters [i,3] == intStreaming))
                {
                    return; 
                }
            } 
 
            throw new ArgumentException(SR.Get(SRID.UnsupportedCombinationOfModeAccessShareStreaming));
        } 

        static private void ValidateModeAccessStreamStreamingCombinations(Stream stream, FileAccess access, bool streaming)
        {
            //////////// 
            // let's makes sure that given stream is capable of supporting required functionality
            //////////// 
            if ((access== FileAccess.Read || access == FileAccess.ReadWrite) && !stream.CanRead) 
            {
                throw new ArgumentException(SR.Get(SRID.CanNotReadDataFromStreamWhichDoesNotSupportReading)); 
            }

            // if user want to be able to write stream needs to support it
            if ((access == FileAccess.Write || access == FileAccess.ReadWrite) && !stream.CanWrite) 
            {
                throw new ArgumentException(SR.Get(SRID.CanNotWriteDataToStreamWhichDoesNotSupportWriting)); 
            } 

            // if user works in non-streaming mode we need to Seek on underlying stream 
            if (! streaming && !stream.CanSeek)
            {
                throw new ArgumentException(SR.Get(SRID.CanNotOperateOnStreamWhichDoesNotSupportSeeking));
            } 
        }
 
        static private void ValidateModeAccessShareSupportedEnums(FileMode mode, FileShare share) 
        {
            //////////// 
            // filter out values that are not supported regardless of other parameters
            // but still validate enum members
            ////////////
             if (mode == FileMode.Append || mode == FileMode.Truncate) 
            {
                throw new NotSupportedException(SR.Get(SRID.TruncateAppendModesNotSupported)); 
            } 
            else if (share != FileShare.Read && share != FileShare.None)
            { 
                // later as we get to streaming other FileShare values will be supported too
                throw new NotSupportedException (SR.Get(SRID.OnlyFileShareReadAndFileShareNoneSupported));
            }
        } 

        static private void ValidateModeAccessShareValidEnums(FileMode mode, FileAccess access, FileShare share) 
        { 
            ////////////
            // filter out values that are out of enum ranges first 
            ////////////
            if ((mode != FileMode.Append) && (mode != FileMode.Create) && (mode != FileMode.CreateNew) && (mode != FileMode.Open)
                && (mode != FileMode.OpenOrCreate) && (mode != FileMode.Truncate))
            { 
                throw new ArgumentOutOfRangeException("mode");
            } 
            else if ((access != FileAccess.Read) && (access != FileAccess.ReadWrite) && (access != FileAccess.Write)) 
            {
                throw new ArgumentOutOfRangeException("access"); 
            }
            else if ((share != FileShare.Delete) && (share != FileShare.Inheritable) && (share != FileShare.None) &&
                (share != FileShare.Read) && (share != FileShare.ReadWrite) && (share != FileShare.Write))
            { 
                throw new ArgumentOutOfRangeException("share");
            } 
        } 

        ///  
        /// Throws exception if object already Disposed/Closed.
        /// 
        private void CheckDisposed()
        { 
            if (_disposedFlag)
            { 
                throw new ObjectDisposedException(null, SR.Get(SRID.ZipArchiveDisposed)); 
            }
        } 

        //------------------------------------------------------
        //
        //  Private Properties 
        //
        //----------------------------------------------------- 
        ///  
        /// This private property is used as a mean to achieve lazy memory allocation for the
        /// hashtable that maintains a cahce of the returned instrances of ZipFileInfo(s). 
        /// This hashtable uses file names as keys in the case insensitive and culture invariant fashion
        /// 
        private IDictionary ZipFileInfoDictionary
        { 
            get
            { 
                if (_zipFileInfoDictionary == null) 
                {
                                // ordinal case sensitive comparison 
                    _zipFileInfoDictionary = new Hashtable(_zipFileInfoDictionaryInitialSize, StringComparer.Ordinal);
                }
                return _zipFileInfoDictionary;
            } 
        }
 
        //----------------------------------------------------- 
        //
        //  Private Fields 
        //
        //-----------------------------------------------------

        // This 2 dimensional table is used by the ValidateModeAccessShareStreaming 
        // function as a set of valid parameter combinations
        static private int[,] _validOpenParameters = new int[,] 
        {   // FileMode                             // FileAccess                     / FileShare                     // streaming 
            {(int)FileMode.Create,             (int)FileAccess.Write,        (int)FileShare.None,        1},
            {(int)FileMode.Create,             (int)FileAccess.Write,        (int)FileShare.Read,        1}, 
            {(int)FileMode.Create,             (int)FileAccess.ReadWrite, (int)FileShare.None,        0},
            {(int)FileMode.CreateNew,       (int)FileAccess.Write,        (int)FileShare.None,        1},
            {(int)FileMode.CreateNew,       (int)FileAccess.Write,        (int)FileShare.Read,        1},
            {(int)FileMode.CreateNew,       (int)FileAccess.ReadWrite, (int)FileShare.None,        0}, 
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.None,        1},
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.None,        0}, 
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.Read,        1}, 
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.Read,        0},
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.Write,        1}, 
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.ReadWrite, 1},
            {(int)FileMode.Open,               (int)FileAccess.ReadWrite,  (int)FileShare.None,        0},
            {(int)FileMode.OpenOrCreate,  (int)FileAccess.ReadWrite,  (int)FileShare.None,        0}
        }; 

        // modes that were used for openning (OpenOnStream or OpenOnFile), 
        // there is no way to change these values after class is constructed 
        private FileMode _openMode;
        private FileAccess  _openAccess; 

        private bool _disposedFlag;

        // reference to the ZipIOBlockManager, this reference is instantiated as 
        // a part of the OpenOnFile/OpenOnStream contruction
        private ZipIOBlockManager _blockManager; 
 
        // this is a Dictionary of all the ZipFileInfos that were given out.
        // It uses file name as key in case insensitive and culture invariant fashion. 
        // all members of the class are supposed to use this field indirectly through
        // ZipFileInfoDictionary property, as ZipFileInfoDictionary is respnsible
        // for lazy allocation of the hashtable.
        private IDictionary _zipFileInfoDictionary; 
        private const int _zipFileInfoDictionaryInitialSize = 50;
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK