예제 #1
0
        /// <summary>
        /// Gets information about files in a zip archive or archive chain.
        /// </summary>
        /// <param name="streamContext">A context interface to handle opening
        /// and closing of archive and file streams.</param>
        /// <param name="fileFilter">A predicate that can determine
        /// which files to process, optional.</param>
        /// <returns>Information about files in the archive stream.</returns>
        /// <exception cref="ArchiveException">The archive provided
        /// by the stream context is not valid.</exception>
        /// <remarks>
        /// The <paramref name="fileFilter"/> predicate takes an internal file
        /// path and returns true to include the file or false to exclude it.
        /// </remarks>
        public override IList <ArchiveFileInfo> GetFileInfo(
            IUnpackStreamContext streamContext,
            Predicate <string> fileFilter)
        {
            if (streamContext == null)
            {
                throw new ArgumentNullException("streamContext");
            }

            lock (this)
            {
                IList <ZipFileHeader> headers = this.GetCentralDirectory(streamContext);
                if (headers == null)
                {
                    throw new ZipException("Zip central directory not found.");
                }

                List <ArchiveFileInfo> files = new List <ArchiveFileInfo>(headers.Count);
                foreach (ZipFileHeader header in headers)
                {
                    if (!header.IsDirectory &&
                        (fileFilter == null || fileFilter(header.fileName)))
                    {
                        files.Add(header.ToZipFileInfo());
                    }
                }

                return(files.AsReadOnly());
            }
        }
예제 #2
0
파일: CabUnpacker.cs 프로젝트: zooba/wix3
        public IList<ArchiveFileInfo> GetFileInfo(
            IUnpackStreamContext streamContext,
            Predicate<string> fileFilter)
        {
            if (streamContext == null)
            {
                throw new ArgumentNullException("streamContext");
            }

            lock (this)
            {
                this.context = streamContext;
                this.filter = fileFilter;
                this.NextCabinetName = String.Empty;
                this.fileList = new List<ArchiveFileInfo>();
                bool tmpSuppress = this.SuppressProgressEvents;
                this.SuppressProgressEvents = true;
                try
                {
                    for (short cabNumber = 0;
                         this.NextCabinetName != null;
                         cabNumber++)
                    {
                        this.Erf.Clear();
                        this.CabNumbers[this.NextCabinetName] = cabNumber;

                        NativeMethods.FDI.Copy(
                            this.fdiHandle,
                            this.NextCabinetName,
                            String.Empty,
                            0,
                            this.CabListNotify,
                            IntPtr.Zero,
                            IntPtr.Zero);
                        this.CheckError(true);
                    }

                    List<ArchiveFileInfo> tmpFileList = this.fileList;
                    this.fileList = null;
                    return tmpFileList.AsReadOnly();
                }
                finally
                {
                    this.SuppressProgressEvents = tmpSuppress;

                    if (this.CabStream != null)
                    {
                        this.context.CloseArchiveReadStream(
                            this.currentArchiveNumber,
                            this.currentArchiveName,
                            this.CabStream);
                        this.CabStream = null;
                    }

                    this.context = null;
                }
            }
        }
예제 #3
0
        public IList <ArchiveFileInfo> GetFileInfo(
            IUnpackStreamContext streamContext,
            Predicate <string> fileFilter)
        {
            if (streamContext == null)
            {
                throw new ArgumentNullException("streamContext");
            }

            lock (this)
            {
                _context        = streamContext;
                _filter         = fileFilter;
                NextCabinetName = string.Empty;
                _fileList       = new List <ArchiveFileInfo>();
                var tmpSuppress = SuppressProgressEvents;
                SuppressProgressEvents = true;
                try
                {
                    for (short cabNumber = 0;
                         NextCabinetName != null;
                         cabNumber++)
                    {
                        Erf.Clear();
                        CabNumbers[NextCabinetName] = cabNumber;

                        NativeMethods.FDI.Copy(
                            _fdiHandle,
                            NextCabinetName,
                            string.Empty,
                            0,
                            CabListNotify,
                            IntPtr.Zero,
                            IntPtr.Zero);
                        CheckError(true);
                    }

                    var tmpFileList = _fileList;
                    _fileList = null;
                    return(tmpFileList.AsReadOnly());
                }
                finally
                {
                    SuppressProgressEvents = tmpSuppress;

                    if (CabStream != null)
                    {
                        _context.CloseArchiveReadStream(
                            CurrentArchiveNumber,
                            CurrentArchiveName,
                            CabStream);
                        CabStream = null;
                    }

                    _context = null;
                }
            }
        }
예제 #4
0
        public IList <ArchiveFileInfo> GetFileInfo(
            IUnpackStreamContext streamContext,
            Predicate <string> fileFilter)
        {
            if (streamContext == null)
            {
                throw new ArgumentNullException("streamContext");
            }

            lock (this)
            {
                this.context         = streamContext;
                this.filter          = fileFilter;
                this.NextCabinetName = String.Empty;
                this.fileList        = new List <ArchiveFileInfo>();
                bool tmpSuppress = this.SuppressProgressEvents;
                this.SuppressProgressEvents = true;
                try
                {
                    for (short cabNumber = 0;
                         this.NextCabinetName != null;
                         cabNumber++)
                    {
                        this.Erf.Clear();
                        this.CabNumbers[this.NextCabinetName] = cabNumber;

                        NativeMethods.FDI.Copy(
                            this.fdiHandle,
                            this.NextCabinetName,
                            String.Empty,
                            0,
                            this.CabListNotify,
                            IntPtr.Zero,
                            IntPtr.Zero);
                        this.CheckError(true);
                    }

                    List <ArchiveFileInfo> tmpFileList = this.fileList;
                    this.fileList = null;
                    return(tmpFileList.AsReadOnly());
                }
                finally
                {
                    this.SuppressProgressEvents = tmpSuppress;

                    if (this.CabStream != null)
                    {
                        this.context.CloseArchiveReadStream(
                            this.currentArchiveNumber,
                            this.currentArchiveName,
                            this.CabStream);
                        this.CabStream = null;
                    }

                    this.context = null;
                }
            }
        }
 public void Unpack(IUnpackStreamContext streamContext, Predicate <string> fileFilter)
 {
     checked
     {
         lock (this)
         {
             IList <ArchiveFileInfo> fileInfo = GetFileInfo(streamContext, fileFilter);
             ResetProgressData();
             if (fileInfo != null)
             {
                 totalFiles = fileInfo.Count;
                 for (int i = 0; i < fileInfo.Count; i++)
                 {
                     totalFileBytes += fileInfo[i].Length;
                     if (fileInfo[i].ArchiveNumber >= totalArchives)
                     {
                         int num = fileInfo[i].ArchiveNumber + 1;
                         totalArchives = (short)num;
                     }
                 }
             }
             context              = streamContext;
             fileList             = null;
             base.NextCabinetName = string.Empty;
             folderId             = -1;
             currentFileNumber    = -1;
             try
             {
                 short num2 = 0;
                 while (base.NextCabinetName != null)
                 {
                     base.Erf.Clear();
                     base.CabNumbers[base.NextCabinetName] = num2;
                     NativeMethods.FDI.Copy(fdiHandle, base.NextCabinetName, string.Empty, 0, CabExtractNotify, IntPtr.Zero, IntPtr.Zero);
                     CheckError(extracting: true);
                     num2 = (short)(num2 + 1);
                 }
             }
             finally
             {
                 if (base.CabStream != null)
                 {
                     context.CloseArchiveReadStream(currentArchiveNumber, currentArchiveName, base.CabStream);
                     base.CabStream = null;
                 }
                 if (base.FileStream != null)
                 {
                     context.CloseFileWriteStream(currentFileName, base.FileStream, FileAttributes.Normal, DateTime.Now);
                     base.FileStream = null;
                 }
                 context = null;
             }
         }
     }
 }
        public IList <string> GetFiles(IUnpackStreamContext streamContext, Predicate <string> fileFilter)
        {
            if (streamContext == null)
            {
                throw new ArgumentNullException("streamContext");
            }
            IList <ArchiveFileInfo> fileInfo = GetFileInfo(streamContext, fileFilter);
            IList <string>          list     = new List <string>(fileInfo.Count);

            for (int i = 0; i < fileInfo.Count; i = checked (i + 1))
            {
                list.Add(fileInfo[i].Name);
            }
            return(list);
        }
예제 #7
0
        private Stream OpenArchive(IUnpackStreamContext streamContext, int archiveNumber)
        {
            Stream archiveStream = streamContext.OpenArchiveReadStream(
                archiveNumber, String.Empty, this);

            if (archiveStream == null && archiveNumber != 0)
            {
                archiveStream = streamContext.OpenArchiveReadStream(
                    0, String.Empty, this);
            }

            if (archiveStream == null)
            {
                throw new FileNotFoundException("Archive stream not provided.");
            }

            return(archiveStream);
        }
예제 #8
0
        /// <summary>
        /// Gets the list of files in an archive or archive chain.
        /// </summary>
        /// <param name="streamContext">A context interface to handle opening
        /// and closing of archive and file streams.</param>
        /// <param name="fileFilter">A predicate that can determine
        /// which files to process, optional.</param>
        /// <returns>An array containing the names of all files contained in
        /// the archive or archive chain.</returns>
        /// <exception cref="ArchiveException">The archive provided
        /// by the stream context is not valid.</exception>
        /// <remarks>
        /// The <paramref name="fileFilter"/> predicate takes an internal file
        /// path and returns true to include the file or false to exclude it.
        /// </remarks>
        public IList <string> GetFiles(
            IUnpackStreamContext streamContext,
            Predicate <string> fileFilter)
        {
            if (streamContext == null)
            {
                throw new ArgumentNullException("streamContext");
            }

            IList <ArchiveFileInfo> files =
                this.GetFileInfo(streamContext, fileFilter);
            IList <string> fileNames = new List <string>(files.Count);

            for (int i = 0; i < files.Count; i++)
            {
                fileNames.Add(files[i].Name);
            }

            return(fileNames);
        }
 public IList <ArchiveFileInfo> GetFileInfo(IUnpackStreamContext streamContext, Predicate <string> fileFilter)
 {
     if (streamContext == null)
     {
         throw new ArgumentNullException("streamContext");
     }
     lock (this)
     {
         context = streamContext;
         filter  = fileFilter;
         base.NextCabinetName = string.Empty;
         fileList             = new List <ArchiveFileInfo>();
         bool suppressProgressEvents = base.SuppressProgressEvents;
         base.SuppressProgressEvents = true;
         try
         {
             short num = 0;
             while (base.NextCabinetName != null)
             {
                 base.Erf.Clear();
                 base.CabNumbers[base.NextCabinetName] = num;
                 NativeMethods.FDI.Copy(fdiHandle, base.NextCabinetName, string.Empty, 0, CabListNotify, IntPtr.Zero, IntPtr.Zero);
                 CheckError(extracting: true);
                 num = checked ((short)(num + 1));
             }
             List <ArchiveFileInfo> list = fileList;
             fileList = null;
             return(list.AsReadOnly());
         }
         finally
         {
             base.SuppressProgressEvents = suppressProgressEvents;
             if (base.CabStream != null)
             {
                 context.CloseArchiveReadStream(currentArchiveNumber, currentArchiveName, base.CabStream);
                 base.CabStream = null;
             }
             context = null;
         }
     }
 }
예제 #10
0
 /// <summary>
 /// Gets information about files in an archive or archive chain.
 /// </summary>
 /// <param name="streamContext">A context interface to handle opening
 /// and closing of archive and file streams.</param>
 /// <param name="fileFilter">A predicate that can determine
 /// which files to process, optional.</param>
 /// <returns>Information about files in the archive stream.</returns>
 /// <exception cref="ArchiveException">The archive provided
 /// by the stream context is not valid.</exception>
 /// <remarks>
 /// The <paramref name="fileFilter"/> predicate takes an internal file
 /// path and returns true to include the file or false to exclude it.
 /// </remarks>
 public abstract IList<ArchiveFileInfo> GetFileInfo(
     IUnpackStreamContext streamContext,
     Predicate<string> fileFilter);
예제 #11
0
        /// <summary>
        /// Gets the list of files in an archive or archive chain.
        /// </summary>
        /// <param name="streamContext">A context interface to handle opening
        /// and closing of archive and file streams.</param>
        /// <param name="fileFilter">A predicate that can determine
        /// which files to process, optional.</param>
        /// <returns>An array containing the names of all files contained in
        /// the archive or archive chain.</returns>
        /// <exception cref="ArchiveException">The archive provided
        /// by the stream context is not valid.</exception>
        /// <remarks>
        /// The <paramref name="fileFilter"/> predicate takes an internal file
        /// path and returns true to include the file or false to exclude it.
        /// </remarks>
        public IList<string> GetFiles(
            IUnpackStreamContext streamContext,
            Predicate<string> fileFilter)
        {
            if (streamContext == null)
            {
                throw new ArgumentNullException("streamContext");
            }

            IList<ArchiveFileInfo> files =
                this.GetFileInfo(streamContext, fileFilter);
            IList<string> fileNames = new List<string>(files.Count);
            for (int i = 0; i < files.Count; i++)
            {
                fileNames.Add(files[i].Name);
            }

            return fileNames;
        }
예제 #12
0
 /// <summary>
 /// Gets information about files in a cabinet or cabinet chain.
 /// </summary>
 /// <param name="streamContext">A context interface to handle opening
 /// and closing of cabinet and file streams.</param>
 /// <param name="fileFilter">A predicate that can determine
 /// which files to process, optional.</param>
 /// <returns>Information about files in the cabinet stream.</returns>
 /// <exception cref="ArchiveException">The cabinet provided
 /// by the stream context is not valid.</exception>
 /// <remarks>
 /// The <paramref name="fileFilter"/> predicate takes an internal file
 /// path and returns true to include the file or false to exclude it.
 /// </remarks>
 public override IList<ArchiveFileInfo> GetFileInfo(
     IUnpackStreamContext streamContext,
     Predicate<string> fileFilter)
 {
     return this.Unpacker.GetFileInfo(streamContext, fileFilter);
 }
예제 #13
0
 /// <summary>
 /// Extracts files from a cabinet or cabinet chain.
 /// </summary>
 /// <param name="streamContext">A context interface to handle opening
 /// and closing of cabinet and file streams.</param>
 /// <param name="fileFilter">An optional predicate that can determine
 /// which files to process.</param>
 /// <exception cref="ArchiveException">The cabinet provided
 /// by the stream context is not valid.</exception>
 /// <remarks>
 /// The <paramref name="fileFilter"/> predicate takes an internal file
 /// path and returns true to include the file or false to exclude it.
 /// </remarks>
 public override void Unpack(
     IUnpackStreamContext streamContext,
     Predicate<string> fileFilter)
 {
     this.Unpacker.Unpack(streamContext, fileFilter);
 }
예제 #14
0
        /// <summary>
        /// Extracts files from a zip archive or archive chain.
        /// </summary>
        /// <param name="streamContext">A context interface to handle opening
        /// and closing of archive and file streams.</param>
        /// <param name="fileFilter">An optional predicate that can determine
        /// which files to process.</param>
        /// <exception cref="ArchiveException">The archive provided
        /// by the stream context is not valid.</exception>
        /// <remarks>
        /// The <paramref name="fileFilter"/> predicate takes an internal file
        /// path and returns true to include the file or false to exclude it.
        /// </remarks>
        public override void Unpack(
            IUnpackStreamContext streamContext,
            Predicate <string> fileFilter)
        {
            if (streamContext == null)
            {
                throw new ArgumentNullException("streamContext");
            }

            lock (this)
            {
                IList <ZipFileHeader> allHeaders = this.GetCentralDirectory(streamContext);
                if (allHeaders == null)
                {
                    throw new ZipException("Zip central directory not found.");
                }

                IList <ZipFileHeader> headers = new List <ZipFileHeader>(allHeaders.Count);
                foreach (ZipFileHeader header in allHeaders)
                {
                    if (!header.IsDirectory &&
                        (fileFilter == null || fileFilter(header.fileName)))
                    {
                        headers.Add(header);
                    }
                }

                this.ResetProgressData();

                // Count the total number of files and bytes to be compressed.
                this.totalFiles = headers.Count;
                foreach (ZipFileHeader header in headers)
                {
                    long compressedSize;
                    long uncompressedSize;
                    long localHeaderOffset;
                    int  archiveNumber;
                    uint crc;
                    header.GetZip64Fields(
                        out compressedSize,
                        out uncompressedSize,
                        out localHeaderOffset,
                        out archiveNumber,
                        out crc);

                    this.totalFileBytes += uncompressedSize;
                    if (archiveNumber >= this.totalArchives)
                    {
                        this.totalArchives = (short)(archiveNumber + 1);
                    }
                }

                this.currentArchiveNumber = -1;
                this.currentFileNumber    = -1;
                Stream archiveStream = null;
                try
                {
                    foreach (ZipFileHeader header in headers)
                    {
                        this.currentFileNumber++;
                        this.UnpackOneFile(streamContext, header, ref archiveStream);
                    }
                }
                finally
                {
                    if (archiveStream != null)
                    {
                        streamContext.CloseArchiveReadStream(
                            0, String.Empty, archiveStream);
                        this.currentArchiveNumber--;
                        this.OnProgress(ArchiveProgressType.FinishArchive);
                    }
                }
            }
        }
예제 #15
0
        private Stream OpenArchive(IUnpackStreamContext streamContext, int archiveNumber)
        {
            Stream archiveStream = streamContext.OpenArchiveReadStream(
                archiveNumber, String.Empty, this);
            if (archiveStream == null && archiveNumber != 0)
            {
                archiveStream = streamContext.OpenArchiveReadStream(
                    0, String.Empty, this);
            }

            if (archiveStream == null)
            {
                throw new FileNotFoundException("Archive stream not provided.");
            }

            return archiveStream;
        }
예제 #16
0
        public void Unpack(
            IUnpackStreamContext streamContext,
            Predicate <string> fileFilter)
        {
            lock (this)
            {
                IList <ArchiveFileInfo> files =
                    this.GetFileInfo(streamContext, fileFilter);

                this.ResetProgressData();

                if (files != null)
                {
                    this.totalFiles = files.Count;

                    for (int i = 0; i < files.Count; i++)
                    {
                        this.totalFileBytes += files[i].Length;
                        if (files[i].ArchiveNumber >= this.totalArchives)
                        {
                            int totalArchives = files[i].ArchiveNumber + 1;
                            this.totalArchives = (short)totalArchives;
                        }
                    }
                }

                this.context           = streamContext;
                this.fileList          = null;
                this.NextCabinetName   = String.Empty;
                this.folderId          = -1;
                this.currentFileNumber = -1;

                try
                {
                    for (short cabNumber = 0;
                         this.NextCabinetName != null;
                         cabNumber++)
                    {
                        this.Erf.Clear();
                        this.CabNumbers[this.NextCabinetName] = cabNumber;

                        NativeMethods.FDI.Copy(
                            this.fdiHandle,
                            this.NextCabinetName,
                            String.Empty,
                            0,
                            this.CabExtractNotify,
                            IntPtr.Zero,
                            IntPtr.Zero);
                        this.CheckError(true);
                    }
                }
                finally
                {
                    if (this.CabStream != null)
                    {
                        this.context.CloseArchiveReadStream(
                            this.currentArchiveNumber,
                            this.currentArchiveName,
                            this.CabStream);
                        this.CabStream = null;
                    }

                    if (this.FileStream != null)
                    {
                        this.context.CloseFileWriteStream(this.currentFileName, this.FileStream, FileAttributes.Normal, DateTime.Now);
                        this.FileStream = null;
                    }

                    this.context = null;
                }
            }
        }
예제 #17
0
파일: ZipEngine.cs 프로젝트: Jeremiahf/wix3
        /// <summary>
        /// Reads all the file headers from the central directory in the main archive.
        /// </summary>
        private IList<ZipFileHeader> GetCentralDirectory(IUnpackStreamContext streamContext)
        {
            Stream archiveStream = null;
            this.currentArchiveNumber = 0;
            try
            {
                List<ZipFileHeader> headers = new List<ZipFileHeader>();
                archiveStream = this.OpenArchive(streamContext, 0);

                ZipEndOfCentralDirectory eocd = this.GetEOCD(streamContext, archiveStream);
                if (eocd == null)
                {
                    return null;
                }
                else if (eocd.totalEntries == 0)
                {
                    return headers;
                }

                headers.Capacity = (int) eocd.totalEntries;

                if (eocd.dirOffset > archiveStream.Length - ZipFileHeader.CFH_FIXEDSIZE)
                {
                    streamContext.CloseArchiveReadStream(
                        this.currentArchiveNumber, String.Empty, archiveStream);
                    archiveStream = null;
                }
                else
                {
                    archiveStream.Seek(eocd.dirOffset, SeekOrigin.Begin);
                    uint sig = new BinaryReader(archiveStream).ReadUInt32();
                    if (sig != ZipFileHeader.CFHSIG)
                    {
                        streamContext.CloseArchiveReadStream(
                            this.currentArchiveNumber, String.Empty, archiveStream);
                        archiveStream = null;
                    }
                }

                if (archiveStream == null)
                {
                    this.currentArchiveNumber = (short) (eocd.dirStartDiskNumber + 1);
                    archiveStream = streamContext.OpenArchiveReadStream(
                        this.currentArchiveNumber, String.Empty, this);

                    if (archiveStream == null)
                    {
                        return null;
                    }
                }

                archiveStream.Seek(eocd.dirOffset, SeekOrigin.Begin);

                while (headers.Count < eocd.totalEntries)
                {
                    ZipFileHeader header = new ZipFileHeader();
                    if (!header.Read(archiveStream, true))
                    {
                        throw new ZipException(
                            "Missing or invalid central directory file header");
                    }

                    headers.Add(header);

                    if (headers.Count < eocd.totalEntries &&
                        archiveStream.Position == archiveStream.Length)
                    {
                        streamContext.CloseArchiveReadStream(
                            this.currentArchiveNumber, String.Empty, archiveStream);
                        this.currentArchiveNumber++;
                        archiveStream = streamContext.OpenArchiveReadStream(
                            this.currentArchiveNumber, String.Empty, this);
                        if (archiveStream == null)
                        {
                            this.currentArchiveNumber = 0;
                            archiveStream = streamContext.OpenArchiveReadStream(
                                this.currentArchiveNumber, String.Empty, this);
                        }
                    }
                }

                return headers;
            }
            finally
            {
                if (archiveStream != null)
                {
                    streamContext.CloseArchiveReadStream(
                        this.currentArchiveNumber, String.Empty, archiveStream);
                }
            }
        }
예제 #18
0
        internal void Unpack(
            IUnpackStreamContext streamContext,
            Predicate<string> fileFilter)
        {
            lock (this)
            {
                IList<ArchiveFileInfo> files =
                    this.GetFileInfo(streamContext, fileFilter);

                this.ResetProgressData();

                if (files != null)
                {
                    this.totalFiles = files.Count;

                    for (int i = 0; i < files.Count; i++)
                    {
                        this.totalFileBytes += files[i].Length;
                        if (files[i].ArchiveNumber >= this.totalArchives)
                        {
                            int totalArchives = files[i].ArchiveNumber + 1;
                            this.totalArchives = (short) totalArchives;
                        }
                    }
                }

                this.context = streamContext;
                this.fileList = null;
                this.NextCabinetName = String.Empty;
                this.folderId = -1;
                this.currentFileNumber = -1;

                try
                {
                    for (short cabNumber = 0;
                         this.NextCabinetName != null;
                         cabNumber++)
                    {
                        this.Erf.Clear();
                        this.CabNumbers[this.NextCabinetName] = cabNumber;

                        NativeMethods.FDI.Copy(
                            this.fdiHandle,
                            this.NextCabinetName,
                            String.Empty,
                            0,
                            this.CabExtractNotify,
                            IntPtr.Zero,
                            IntPtr.Zero);
                        this.CheckError(true);
                    }
                }
                finally
                {
                    if (this.CabStream != null)
                    {
                        this.context.CloseArchiveReadStream(
                            this.currentArchiveNumber,
                            this.currentArchiveName,
                            this.CabStream);
                        this.CabStream = null;
                    }

                    if (this.FileStream != null)
                    {
                        this.context.CloseFileWriteStream(this.currentFileName, this.FileStream, FileAttributes.Normal, DateTime.Now);
                        this.FileStream = null;
                    }

                    this.context = null;
                }
            }
        }
예제 #19
0
 /// <summary>
 /// Gets information about files in a cabinet or cabinet chain.
 /// </summary>
 /// <param name="streamContext">A context interface to handle opening
 /// and closing of cabinet and file streams.</param>
 /// <param name="fileFilter">A predicate that can determine
 /// which files to process, optional.</param>
 /// <returns>Information about files in the cabinet stream.</returns>
 /// <exception cref="ArchiveException">The cabinet provided
 /// by the stream context is not valid.</exception>
 /// <remarks>
 /// The <paramref name="fileFilter"/> predicate takes an internal file
 /// path and returns true to include the file or false to exclude it.
 /// </remarks>
 public override IList <ArchiveFileInfo> GetFileInfo(
     IUnpackStreamContext streamContext,
     Predicate <string> fileFilter)
 {
     return(Unpacker.GetFileInfo(streamContext, fileFilter));
 }
예제 #20
0
        /// <summary>
        /// Extracts files from a zip archive or archive chain.
        /// </summary>
        /// <param name="streamContext">A context interface to handle opening
        /// and closing of archive and file streams.</param>
        /// <param name="fileFilter">An optional predicate that can determine
        /// which files to process.</param>
        /// <exception cref="ArchiveException">The archive provided
        /// by the stream context is not valid.</exception>
        /// <remarks>
        /// The <paramref name="fileFilter"/> predicate takes an internal file
        /// path and returns true to include the file or false to exclude it.
        /// </remarks>
        public override void Unpack(
            IUnpackStreamContext streamContext,
            Predicate<string> fileFilter)
        {
            if (streamContext == null)
            {
                throw new ArgumentNullException("streamContext");
            }

            lock (this)
            {
                IList<ZipFileHeader> allHeaders = this.GetCentralDirectory(streamContext);
                if (allHeaders == null)
                {
                    throw new ZipException("Zip central directory not found.");
                }

                IList<ZipFileHeader> headers = new List<ZipFileHeader>(allHeaders.Count);
                foreach (ZipFileHeader header in allHeaders)
                {
                    if (!header.IsDirectory &&
                        (fileFilter == null || fileFilter(header.fileName)))
                    {
                        headers.Add(header);
                    }
                }

                this.ResetProgressData();

                // Count the total number of files and bytes to be compressed.
                this.totalFiles = headers.Count;
                foreach (ZipFileHeader header in headers)
                {
                    long compressedSize;
                    long uncompressedSize;
                    long localHeaderOffset;
                    int archiveNumber;
                    uint crc;
                    header.GetZip64Fields(
                        out compressedSize,
                        out uncompressedSize,
                        out localHeaderOffset,
                        out archiveNumber,
                        out crc);

                    this.totalFileBytes += uncompressedSize;
                    if (archiveNumber >= this.totalArchives)
                    {
                        this.totalArchives = (short) (archiveNumber + 1);
                    }
                }

                this.currentArchiveNumber = -1;
                this.currentFileNumber = -1;
                Stream archiveStream = null;
                try
                {
                    foreach (ZipFileHeader header in headers)
                    {
                        this.currentFileNumber++;
                        this.UnpackOneFile(streamContext, header, ref archiveStream);
                    }
                }
                finally
                {
                    if (archiveStream != null)
                    {
                        streamContext.CloseArchiveReadStream(
                            0, String.Empty, archiveStream);
                        this.currentArchiveNumber--;
                        this.OnProgress(ArchiveProgressType.FinishArchive);
                    }
                }
            }
        }
예제 #21
0
        /// <summary>
        /// Unpacks a single file from an archive or archive chain.
        /// </summary>
        private void UnpackOneFile(
            IUnpackStreamContext streamContext,
            ZipFileHeader header,
            ref Stream archiveStream)
        {
            ZipFileInfo fileInfo = null;
            Stream fileStream = null;
            try
            {
                Converter<Stream, Stream> compressionStreamCreator;
                if (!ZipEngine.decompressionStreamCreators.TryGetValue(
                    header.compressionMethod, out compressionStreamCreator))
                {
                    // Silently skip files of an unsupported compression method.
                    return;
                }

                long compressedSize;
                long uncompressedSize;
                long localHeaderOffset;
                int archiveNumber;
                uint crc;
                header.GetZip64Fields(
                    out compressedSize,
                    out uncompressedSize,
                    out localHeaderOffset,
                    out archiveNumber,
                    out crc);

                if (this.currentArchiveNumber != archiveNumber + 1)
                {
                    if (archiveStream != null)
                    {
                        streamContext.CloseArchiveReadStream(
                            this.currentArchiveNumber,
                            String.Empty,
                            archiveStream);
                        archiveStream = null;

                        this.OnProgress(ArchiveProgressType.FinishArchive);
                        this.currentArchiveName = null;
                    }

                    this.currentArchiveNumber = (short) (archiveNumber + 1);
                    this.currentArchiveBytesProcessed = 0;
                    this.currentArchiveTotalBytes = 0;

                    archiveStream = this.OpenArchive(
                        streamContext, this.currentArchiveNumber);

                    FileStream archiveFileStream = archiveStream as FileStream;
                    this.currentArchiveName = (archiveFileStream != null ?
                        Path.GetFileName(archiveFileStream.Name) : null);

                    this.currentArchiveTotalBytes = archiveStream.Length;
                    this.currentArchiveNumber--;
                    this.OnProgress(ArchiveProgressType.StartArchive);
                    this.currentArchiveNumber++;
                }

                archiveStream.Seek(localHeaderOffset, SeekOrigin.Begin);

                ZipFileHeader localHeader = new ZipFileHeader();
                if (!localHeader.Read(archiveStream, false) ||
                    !ZipEngine.AreFilePathsEqual(localHeader.fileName, header.fileName))
                {
                    string msg = "Could not read file: " + header.fileName;
                    throw new ZipException(msg);
                }

                fileInfo = header.ToZipFileInfo();

                fileStream = streamContext.OpenFileWriteStream(
                    fileInfo.FullName,
                    fileInfo.Length,
                    fileInfo.LastWriteTime);

                if (fileStream != null)
                {
                    this.currentFileName = header.fileName;
                    this.currentFileBytesProcessed = 0;
                    this.currentFileTotalBytes = fileInfo.Length;
                    this.currentArchiveNumber--;
                    this.OnProgress(ArchiveProgressType.StartFile);
                    this.currentArchiveNumber++;

                    this.UnpackFileBytes(
                        streamContext,
                        fileInfo.FullName,
                        fileInfo.CompressedLength,
                        fileInfo.Length,
                        header.crc32,
                        fileStream,
                        compressionStreamCreator,
                        ref archiveStream);
                }
            }
            finally
            {
                if (fileStream != null)
                {
                    streamContext.CloseFileWriteStream(
                        fileInfo.FullName,
                        fileStream,
                        fileInfo.Attributes,
                        fileInfo.LastWriteTime);

                    this.currentArchiveNumber--;
                    this.OnProgress(ArchiveProgressType.FinishFile);
                    this.currentArchiveNumber++;
                }
            }
        }
예제 #22
0
        /// <summary>
        /// Decompresses bytes for one file from an archive or archive chain,
        /// checking the crc at the end.
        /// </summary>
        private void UnpackFileBytes(
            IUnpackStreamContext streamContext,
            string fileName,
            long compressedSize,
            long uncompressedSize,
            uint crc,
            Stream fileStream,
            Converter<Stream, Stream> compressionStreamCreator,
            ref Stream archiveStream)
        {
            CrcStream crcStream = new CrcStream(fileStream);

            ConcatStream concatStream = new ConcatStream(
                delegate(ConcatStream s)
                {
                    this.currentArchiveBytesProcessed = s.Source.Position;
                    streamContext.CloseArchiveReadStream(
                        this.currentArchiveNumber,
                        String.Empty,
                        s.Source);

                    this.currentArchiveNumber--;
                    this.OnProgress(ArchiveProgressType.FinishArchive);
                    this.currentArchiveNumber += 2;
                    this.currentArchiveName = null;
                    this.currentArchiveBytesProcessed = 0;
                    this.currentArchiveTotalBytes = 0;

                    s.Source = this.OpenArchive(streamContext, this.currentArchiveNumber);

                    FileStream archiveFileStream = s.Source as FileStream;
                    this.currentArchiveName = (archiveFileStream != null ?
                        Path.GetFileName(archiveFileStream.Name) : null);

                    this.currentArchiveTotalBytes = s.Source.Length;
                    this.currentArchiveNumber--;
                    this.OnProgress(ArchiveProgressType.StartArchive);
                    this.currentArchiveNumber++;
                });

            concatStream.Source = archiveStream;
            concatStream.SetLength(compressedSize);

            Stream decompressionStream = compressionStreamCreator(concatStream);

            try
            {
                byte[] buf = new byte[4096];
                long bytesRemaining = uncompressedSize;
                int counter = 0;
                while (bytesRemaining > 0)
                {
                    int count = (int) Math.Min(buf.Length, bytesRemaining);
                    count = decompressionStream.Read(buf, 0, count);
                    crcStream.Write(buf, 0, count);
                    bytesRemaining -= count;

                    this.fileBytesProcessed += count;
                    this.currentFileBytesProcessed += count;
                    this.currentArchiveBytesProcessed = concatStream.Source.Position;

                    if (++counter % 16 == 0) // Report every 64K
                    {
                        this.currentArchiveNumber--;
                        this.OnProgress(ArchiveProgressType.PartialFile);
                        this.currentArchiveNumber++;
                    }
                }
            }
            finally
            {
                archiveStream = concatStream.Source;
            }

            crcStream.Flush();

            if (crcStream.Crc != crc)
            {
                throw new ZipException("CRC check failed for file: " + fileName);
            }
        }
예제 #23
0
 /// <summary>
 /// Extracts files from an archive or archive chain.
 /// </summary>
 /// <param name="streamContext">A context interface to handle opening
 /// and closing of archive and file streams.</param>
 /// <param name="fileFilter">An optional predicate that can determine
 /// which files to process.</param>
 /// <exception cref="ArchiveException">The archive provided
 /// by the stream context is not valid.</exception>
 /// <remarks>
 /// The <paramref name="fileFilter"/> predicate takes an internal file
 /// path and returns true to include the file or false to exclude it.
 /// </remarks>
 public abstract void Unpack(
     IUnpackStreamContext streamContext,
     Predicate<string> fileFilter);
예제 #24
0
        public void Unpack(
            IUnpackStreamContext streamContext,
            Predicate <string> fileFilter)
        {
            lock (this)
            {
                var files =
                    GetFileInfo(streamContext, fileFilter);

                ResetProgressData();

                if (files != null)
                {
                    TotalFiles = files.Count;

                    for (var i = 0; i < files.Count; i++)
                    {
                        TotalFileBytes += files[i].Length;
                        if (files[i].ArchiveNumber >= TotalArchives)
                        {
                            var totalArchives = files[i].ArchiveNumber + 1;
                            TotalArchives = (short)totalArchives;
                        }
                    }
                }

                _context          = streamContext;
                _fileList         = null;
                NextCabinetName   = string.Empty;
                _folderID         = -1;
                CurrentFileNumber = -1;

                try
                {
                    for (short cabNumber = 0;
                         NextCabinetName != null;
                         cabNumber++)
                    {
                        Erf.Clear();
                        CabNumbers[NextCabinetName] = cabNumber;

                        NativeMethods.FDI.Copy(
                            _fdiHandle,
                            NextCabinetName,
                            string.Empty,
                            0,
                            CabExtractNotify,
                            IntPtr.Zero,
                            IntPtr.Zero);
                        CheckError(true);
                    }
                }
                finally
                {
                    if (CabStream != null)
                    {
                        _context.CloseArchiveReadStream(
                            CurrentArchiveNumber,
                            CurrentArchiveName,
                            CabStream);
                        CabStream = null;
                    }

                    if (FileStream != null)
                    {
                        _context.CloseFileWriteStream(CurrentFileName, FileStream, FileAttributes.Normal, DateTime.Now);
                        FileStream = null;
                    }

                    _context = null;
                }
            }
        }
예제 #25
0
        /// <summary>
        /// Unpacks a single file from an archive or archive chain.
        /// </summary>
        private void UnpackOneFile(
            IUnpackStreamContext streamContext,
            ZipFileHeader header,
            ref Stream archiveStream)
        {
            ZipFileInfo fileInfo   = null;
            Stream      fileStream = null;

            try
            {
                Func <Stream, Stream> compressionStreamCreator;
                if (!ZipEngine.decompressionStreamCreators.TryGetValue(
                        header.compressionMethod, out compressionStreamCreator))
                {
                    // Silently skip files of an unsupported compression method.
                    return;
                }

                long compressedSize;
                long uncompressedSize;
                long localHeaderOffset;
                int  archiveNumber;
                uint crc;
                header.GetZip64Fields(
                    out compressedSize,
                    out uncompressedSize,
                    out localHeaderOffset,
                    out archiveNumber,
                    out crc);

                if (this.currentArchiveNumber != archiveNumber + 1)
                {
                    if (archiveStream != null)
                    {
                        streamContext.CloseArchiveReadStream(
                            this.currentArchiveNumber,
                            String.Empty,
                            archiveStream);
                        archiveStream = null;

                        this.OnProgress(ArchiveProgressType.FinishArchive);
                        this.currentArchiveName = null;
                    }

                    this.currentArchiveNumber         = (short)(archiveNumber + 1);
                    this.currentArchiveBytesProcessed = 0;
                    this.currentArchiveTotalBytes     = 0;

                    archiveStream = this.OpenArchive(
                        streamContext, this.currentArchiveNumber);

                    FileStream archiveFileStream = archiveStream as FileStream;
                    this.currentArchiveName = (archiveFileStream != null ?
                                               Path.GetFileName(archiveFileStream.Name) : null);

                    this.currentArchiveTotalBytes = archiveStream.Length;
                    this.currentArchiveNumber--;
                    this.OnProgress(ArchiveProgressType.StartArchive);
                    this.currentArchiveNumber++;
                }

                archiveStream.Seek(localHeaderOffset, SeekOrigin.Begin);

                ZipFileHeader localHeader = new ZipFileHeader();
                if (!localHeader.Read(archiveStream, false) ||
                    !ZipEngine.AreFilePathsEqual(localHeader.fileName, header.fileName))
                {
                    string msg = "Could not read file: " + header.fileName;
                    throw new ZipException(msg);
                }

                fileInfo = header.ToZipFileInfo();

                fileStream = streamContext.OpenFileWriteStream(
                    fileInfo.FullName,
                    fileInfo.Length,
                    fileInfo.LastWriteTime);

                if (fileStream != null)
                {
                    this.currentFileName           = header.fileName;
                    this.currentFileBytesProcessed = 0;
                    this.currentFileTotalBytes     = fileInfo.Length;
                    this.currentArchiveNumber--;
                    this.OnProgress(ArchiveProgressType.StartFile);
                    this.currentArchiveNumber++;

                    this.UnpackFileBytes(
                        streamContext,
                        fileInfo.FullName,
                        fileInfo.CompressedLength,
                        fileInfo.Length,
                        header.crc32,
                        fileStream,
                        compressionStreamCreator,
                        ref archiveStream);
                }
            }
            finally
            {
                if (fileStream != null)
                {
                    streamContext.CloseFileWriteStream(
                        fileInfo.FullName,
                        fileStream,
                        fileInfo.Attributes,
                        fileInfo.LastWriteTime);

                    this.currentArchiveNumber--;
                    this.OnProgress(ArchiveProgressType.FinishFile);
                    this.currentArchiveNumber++;
                }
            }
        }
예제 #26
0
파일: ZipEngine.cs 프로젝트: Jeremiahf/wix3
        /// <summary>
        /// Gets information about files in a zip archive or archive chain.
        /// </summary>
        /// <param name="streamContext">A context interface to handle opening
        /// and closing of archive and file streams.</param>
        /// <param name="fileFilter">A predicate that can determine
        /// which files to process, optional.</param>
        /// <returns>Information about files in the archive stream.</returns>
        /// <exception cref="ArchiveException">The archive provided
        /// by the stream context is not valid.</exception>
        /// <remarks>
        /// The <paramref name="fileFilter"/> predicate takes an internal file
        /// path and returns true to include the file or false to exclude it.
        /// </remarks>
        public override IList<ArchiveFileInfo> GetFileInfo(
            IUnpackStreamContext streamContext,
            Predicate<string> fileFilter)
        {
            if (streamContext == null)
            {
                throw new ArgumentNullException("streamContext");
            }

            lock (this)
            {
                IList<ZipFileHeader> headers = this.GetCentralDirectory(streamContext);
                if (headers == null)
                {
                    throw new ZipException("Zip central directory not found.");
                }

                List<ArchiveFileInfo> files = new List<ArchiveFileInfo>(headers.Count);
                foreach (ZipFileHeader header in headers)
                {
                    if (!header.IsDirectory &&
                        (fileFilter == null || fileFilter(header.fileName)))
                    {
                        files.Add(header.ToZipFileInfo());
                    }
                }

                return files.AsReadOnly();
            }
        }
예제 #27
0
        /// <summary>
        /// Decompresses bytes for one file from an archive or archive chain,
        /// checking the crc at the end.
        /// </summary>
        private void UnpackFileBytes(
            IUnpackStreamContext streamContext,
            string fileName,
            long compressedSize,
            long uncompressedSize,
            uint crc,
            Stream fileStream,
            Func <Stream, Stream> compressionStreamCreator,
            ref Stream archiveStream)
        {
            CrcStream crcStream = new CrcStream(fileStream);

            ConcatStream concatStream = new ConcatStream(
                delegate(ConcatStream s)
            {
                this.currentArchiveBytesProcessed = s.Source.Position;
                streamContext.CloseArchiveReadStream(
                    this.currentArchiveNumber,
                    String.Empty,
                    s.Source);

                this.currentArchiveNumber--;
                this.OnProgress(ArchiveProgressType.FinishArchive);
                this.currentArchiveNumber        += 2;
                this.currentArchiveName           = null;
                this.currentArchiveBytesProcessed = 0;
                this.currentArchiveTotalBytes     = 0;

                s.Source = this.OpenArchive(streamContext, this.currentArchiveNumber);

                FileStream archiveFileStream = s.Source as FileStream;
                this.currentArchiveName      = (archiveFileStream != null ?
                                                Path.GetFileName(archiveFileStream.Name) : null);

                this.currentArchiveTotalBytes = s.Source.Length;
                this.currentArchiveNumber--;
                this.OnProgress(ArchiveProgressType.StartArchive);
                this.currentArchiveNumber++;
            });

            concatStream.Source = archiveStream;
            concatStream.SetLength(compressedSize);

            Stream decompressionStream = compressionStreamCreator(concatStream);

            try
            {
                byte[] buf            = new byte[4096];
                long   bytesRemaining = uncompressedSize;
                int    counter        = 0;
                while (bytesRemaining > 0)
                {
                    int count = (int)Math.Min(buf.Length, bytesRemaining);
                    count = decompressionStream.Read(buf, 0, count);
                    crcStream.Write(buf, 0, count);
                    bytesRemaining -= count;

                    this.fileBytesProcessed          += count;
                    this.currentFileBytesProcessed   += count;
                    this.currentArchiveBytesProcessed = concatStream.Source.Position;

                    if (++counter % 16 == 0) // Report every 64K
                    {
                        this.currentArchiveNumber--;
                        this.OnProgress(ArchiveProgressType.PartialFile);
                        this.currentArchiveNumber++;
                    }
                }
            }
            finally
            {
                archiveStream = concatStream.Source;
            }

            crcStream.Flush();

            if (crcStream.Crc != crc)
            {
                throw new ZipException("CRC check failed for file: " + fileName);
            }
        }
예제 #28
0
 /// <summary>
 /// Extracts files from an archive or archive chain.
 /// </summary>
 /// <param name="streamContext">A context interface to handle opening
 /// and closing of archive and file streams.</param>
 /// <param name="fileFilter">An optional predicate that can determine
 /// which files to process.</param>
 /// <exception cref="ArchiveException">The archive provided
 /// by the stream context is not valid.</exception>
 /// <remarks>
 /// The <paramref name="fileFilter"/> predicate takes an internal file
 /// path and returns true to include the file or false to exclude it.
 /// </remarks>
 public abstract void Unpack(
     IUnpackStreamContext streamContext,
     Predicate <string> fileFilter);
예제 #29
0
        /// <summary>
        /// Reads all the file headers from the central directory in the main archive.
        /// </summary>
        private IList <ZipFileHeader> GetCentralDirectory(IUnpackStreamContext streamContext)
        {
            Stream archiveStream = null;

            this.currentArchiveNumber = 0;
            try
            {
                List <ZipFileHeader> headers = new List <ZipFileHeader>();
                archiveStream = this.OpenArchive(streamContext, 0);

                ZipEndOfCentralDirectory eocd = this.GetEOCD(streamContext, archiveStream);
                if (eocd == null)
                {
                    return(null);
                }
                else if (eocd.totalEntries == 0)
                {
                    return(headers);
                }

                headers.Capacity = (int)eocd.totalEntries;

                if (eocd.dirOffset > archiveStream.Length - ZipFileHeader.CFH_FIXEDSIZE)
                {
                    streamContext.CloseArchiveReadStream(
                        this.currentArchiveNumber, String.Empty, archiveStream);
                    archiveStream = null;
                }
                else
                {
                    archiveStream.Seek(eocd.dirOffset, SeekOrigin.Begin);
                    uint sig = new BinaryReader(archiveStream).ReadUInt32();
                    if (sig != ZipFileHeader.CFHSIG)
                    {
                        streamContext.CloseArchiveReadStream(
                            this.currentArchiveNumber, String.Empty, archiveStream);
                        archiveStream = null;
                    }
                }

                if (archiveStream == null)
                {
                    this.currentArchiveNumber = (short)(eocd.dirStartDiskNumber + 1);
                    archiveStream             = streamContext.OpenArchiveReadStream(
                        this.currentArchiveNumber, String.Empty, this);

                    if (archiveStream == null)
                    {
                        return(null);
                    }
                }

                archiveStream.Seek(eocd.dirOffset, SeekOrigin.Begin);

                while (headers.Count < eocd.totalEntries)
                {
                    ZipFileHeader header = new ZipFileHeader();
                    if (!header.Read(archiveStream, true))
                    {
                        throw new ZipException(
                                  "Missing or invalid central directory file header");
                    }

                    headers.Add(header);

                    if (headers.Count < eocd.totalEntries &&
                        archiveStream.Position == archiveStream.Length)
                    {
                        streamContext.CloseArchiveReadStream(
                            this.currentArchiveNumber, String.Empty, archiveStream);
                        this.currentArchiveNumber++;
                        archiveStream = streamContext.OpenArchiveReadStream(
                            this.currentArchiveNumber, String.Empty, this);
                        if (archiveStream == null)
                        {
                            this.currentArchiveNumber = 0;
                            archiveStream             = streamContext.OpenArchiveReadStream(
                                this.currentArchiveNumber, String.Empty, this);
                        }
                    }
                }

                return(headers);
            }
            finally
            {
                if (archiveStream != null)
                {
                    streamContext.CloseArchiveReadStream(
                        this.currentArchiveNumber, String.Empty, archiveStream);
                }
            }
        }
예제 #30
0
파일: ZipEngine.cs 프로젝트: Jeremiahf/wix3
        private ZipEndOfCentralDirectory GetEOCD(
            IUnpackStreamContext streamContext, Stream archiveStream)
        {
            BinaryReader reader = new BinaryReader(archiveStream);
            long offset = archiveStream.Length
                - ZipEndOfCentralDirectory.EOCD_RECORD_FIXEDSIZE;
            while (offset >= 0)
            {
                archiveStream.Seek(offset, SeekOrigin.Begin);

                uint sig = reader.ReadUInt32();
                if (sig == ZipEndOfCentralDirectory.EOCDSIG)
                {
                    break;
                }

                offset--;
            }

            if (offset < 0)
            {
                return null;
            }

            ZipEndOfCentralDirectory eocd = new ZipEndOfCentralDirectory();
            archiveStream.Seek(offset, SeekOrigin.Begin);
            if (!eocd.Read(archiveStream))
            {
                throw new ZipException("Invalid end of central directory record");
            }

            if (eocd.dirOffset == (long) UInt32.MaxValue)
            {
                string saveComment = eocd.comment;

                archiveStream.Seek(
                    offset - Zip64EndOfCentralDirectoryLocator.EOCDL64_SIZE,
                    SeekOrigin.Begin);

                Zip64EndOfCentralDirectoryLocator eocdl =
                    new Zip64EndOfCentralDirectoryLocator();
                if (!eocdl.Read(archiveStream))
                {
                    throw new ZipException("Missing or invalid end of " +
                        "central directory record locator");
                }

                if (eocdl.dirStartDiskNumber == eocdl.totalDisks - 1)
                {
                    // ZIP64 eocd is entirely in current stream.
                    archiveStream.Seek(eocdl.dirOffset, SeekOrigin.Begin);
                    if (!eocd.Read(archiveStream))
                    {
                        throw new ZipException("Missing or invalid ZIP64 end of " +
                            "central directory record");
                    }
                }
                else if (streamContext == null)
                {
                    return null;
                }
                else
                {
                    // TODO: handle EOCD64 spanning archives!
                    throw new NotImplementedException("Zip implementation does not " +
                        "handle end of central directory record that spans archives.");
                }

                eocd.comment = saveComment;
            }

            return eocd;
        }
예제 #31
0
 /// <summary>
 /// Extracts files from a cabinet or cabinet chain.
 /// </summary>
 /// <param name="streamContext">A context interface to handle opening
 /// and closing of cabinet and file streams.</param>
 /// <param name="fileFilter">An optional predicate that can determine
 /// which files to process.</param>
 /// <exception cref="ArchiveException">The cabinet provided
 /// by the stream context is not valid.</exception>
 /// <remarks>
 /// The <paramref name="fileFilter"/> predicate takes an internal file
 /// path and returns true to include the file or false to exclude it.
 /// </remarks>
 public override void Unpack(
     IUnpackStreamContext streamContext,
     Predicate <string> fileFilter)
 {
     Unpacker.Unpack(streamContext, fileFilter);
 }
예제 #32
0
파일: CabEngine.cs 프로젝트: caoxk/coapp
 /// <summary>
 /// Extracts files from a cabinet or cabinet chain.
 /// </summary>
 /// <param name="streamContext">A context interface to handle opening
 /// and closing of cabinet and file streams.</param>
 /// <param name="fileFilter">An optional predicate that can determine
 /// which files to process.</param>
 /// <exception cref="ArchiveException">The cabinet provided
 /// by the stream context is not valid.</exception>
 /// <remarks>
 /// The <paramref name="fileFilter"/> predicate takes an internal file
 /// path and returns true to include the file or false to exclude it.
 /// </remarks>
 internal override void Unpack(
     IUnpackStreamContext streamContext,
     Predicate <string> fileFilter)
 {
     this.Unpacker.Unpack(streamContext, fileFilter);
 }
예제 #33
0
        private ZipEndOfCentralDirectory GetEOCD(
            IUnpackStreamContext streamContext, Stream archiveStream)
        {
            BinaryReader reader = new BinaryReader(archiveStream);
            long         offset = archiveStream.Length
                                  - ZipEndOfCentralDirectory.EOCD_RECORD_FIXEDSIZE;

            while (offset >= 0)
            {
                archiveStream.Seek(offset, SeekOrigin.Begin);

                uint sig = reader.ReadUInt32();
                if (sig == ZipEndOfCentralDirectory.EOCDSIG)
                {
                    break;
                }

                offset--;
            }

            if (offset < 0)
            {
                return(null);
            }

            ZipEndOfCentralDirectory eocd = new ZipEndOfCentralDirectory();

            archiveStream.Seek(offset, SeekOrigin.Begin);
            if (!eocd.Read(archiveStream))
            {
                throw new ZipException("Invalid end of central directory record");
            }

            if (eocd.dirOffset == (long)UInt32.MaxValue)
            {
                string saveComment = eocd.comment;

                archiveStream.Seek(
                    offset - Zip64EndOfCentralDirectoryLocator.EOCDL64_SIZE,
                    SeekOrigin.Begin);

                Zip64EndOfCentralDirectoryLocator eocdl =
                    new Zip64EndOfCentralDirectoryLocator();
                if (!eocdl.Read(archiveStream))
                {
                    throw new ZipException("Missing or invalid end of " +
                                           "central directory record locator");
                }

                if (eocdl.dirStartDiskNumber == eocdl.totalDisks - 1)
                {
                    // ZIP64 eocd is entirely in current stream.
                    archiveStream.Seek(eocdl.dirOffset, SeekOrigin.Begin);
                    if (!eocd.Read(archiveStream))
                    {
                        throw new ZipException("Missing or invalid ZIP64 end of " +
                                               "central directory record");
                    }
                }
                else if (streamContext == null)
                {
                    return(null);
                }
                else
                {
                    // TODO: handle EOCD64 spanning archives!
                    throw new NotImplementedException("Zip implementation does not " +
                                                      "handle end of central directory record that spans archives.");
                }

                eocd.comment = saveComment;
            }

            return(eocd);
        }
예제 #34
0
 /// <summary>
 /// Gets information about files in an archive or archive chain.
 /// </summary>
 /// <param name="streamContext">A context interface to handle opening
 /// and closing of archive and file streams.</param>
 /// <param name="fileFilter">A predicate that can determine
 /// which files to process, optional.</param>
 /// <returns>Information about files in the archive stream.</returns>
 /// <exception cref="ArchiveException">The archive provided
 /// by the stream context is not valid.</exception>
 /// <remarks>
 /// The <paramref name="fileFilter"/> predicate takes an internal file
 /// path and returns true to include the file or false to exclude it.
 /// </remarks>
 public abstract IList <ArchiveFileInfo> GetFileInfo(
     IUnpackStreamContext streamContext,
     Predicate <string> fileFilter);