Exemple #1
0
        /// <summary>
        /// Computes a table that speeds up calculation of the CRC.
        /// </summary>
        private static uint[] MakeCrcTable()
        {
            uint[] crcTable = new uint[256];
            for (uint n = 0; n < 256; n++)
            {
                uint c = ZipCrc.Reflect(n, 8);
                c = c << 24;
                for (uint k = 0; k < 8; k++)
                {
                    c = (c << 1) ^ ((c & 0x80000000u) != 0 ? ZipCrc.Poly : 0);
                }

                crcTable[n] = ZipCrc.Reflect(c, 32);
            }

            return(crcTable);
        }
Exemple #2
0
        public void AddFile(Stream stream, string packageUri, string mimeType, CompressionLevel level)
        {
            string      partName    = this.DeterminePartName(packageUri);
            ContentType contentType = this.DetermineContentType(partName, mimeType);

            ZipFileHeader localFileHeader = new ZipFileHeader(false);

            localFileHeader.localHeaderOffset = (uint)this.BaseStream.Position;
            localFileHeader.zip64             = stream.Length > 0xFFFFFFFF;
            localFileHeader.versionMadeBy     = 0;
            localFileHeader.versionNeeded     = localFileHeader.zip64 ? (ushort)45 : (ushort)20;
            localFileHeader.fileName          = partName;
            localFileHeader.compressionMethod = (level == CompressionLevel.NoCompression) ? ZipCompressionMethod.Store : ZipCompressionMethod.Deflate;
            localFileHeader.flags             = this.BaseStream.CanSeek ? ZipFileFlags.None : ZipFileFlags.DataDescriptor;

            localFileHeader.Write(this.BaseStream);

            BlockMapFile blockMapFile = new BlockMapFile(partName)
            {
                Size = stream.Length, ZipLocalFileHeaderSize = localFileHeader.GetSize()
            };

            this.blockMapFiles.Add(blockMapFile);

            ZipCrc             crc     = new ZipCrc();
            BlockDeflateStream deflate = (level == CompressionLevel.NoCompression) ? null : new BlockDeflateStream(this.BaseStream, (BlockDeflateCompressionLevel)level);

            long outputStart = this.BaseStream.Position;

            int read = 0;

            byte[] buffer = new byte[64 * 1024];
            while (0 < (read = stream.Read(buffer, 0, buffer.Length)))
            {
                crc.UpdateCrc(buffer, 0, read);

                string hash;
                using (SHA256 sha256 = SHA256.Create())
                {
                    byte[] hashedBytes = sha256.ComputeHash(buffer, 0, read);
                    hash = Convert.ToBase64String(hashedBytes);
                }

                long compressedBlockSize = 0;
                if (deflate != null)
                {
                    compressedBlockSize = deflate.Deflate(buffer, 0, read);
                }
                else
                {
                    this.BaseStream.Write(buffer, 0, read);
                    compressedBlockSize = -1;
                }

                BlockMapFileBlock block = new BlockMapFileBlock()
                {
                    Hash = hash, CompressedSize = compressedBlockSize
                };
                blockMapFile.Blocks.Add(block);
            }

            if (deflate != null)
            {
                deflate.Flush();
            }
            else
            {
                this.BaseStream.Flush();
            }

            // Update the local file header with data discovered while processing file data.
            localFileHeader.crc32            = crc.Crc;
            localFileHeader.compressedSize   = (uint)(this.BaseStream.Position - outputStart); // (uint)compressedSize;
            localFileHeader.uncompressedSize = (uint)stream.Length;

            // If we're using the data descriptor (because we can't see), append the updated information to the file data.
            if ((localFileHeader.flags & ZipFileFlags.DataDescriptor) == ZipFileFlags.DataDescriptor)
            {
                localFileHeader.WriteDataDescriptor(this.BaseStream);
            }
            else // go back to re-write the updated local file header in place, then seek back to our current location.
            {
                long position = this.BaseStream.Position;

                this.BaseStream.Seek(localFileHeader.localHeaderOffset, SeekOrigin.Begin);
                localFileHeader.Write(this.BaseStream);

                this.BaseStream.Seek(position, SeekOrigin.Begin);
            }

            // If we have a 64-bit local header then the central directory must be
            // ZIP64 as well.
            if (localFileHeader.zip64)
            {
                this.eocd.zip64         = true;
                this.eocd.versionMadeBy = 45;
                this.eocd.versionNeeded = 45;
            }

            ZipFileHeader centralFileHeader = new ZipFileHeader(localFileHeader);

            this.eocd.CentralDirectory.Add(centralFileHeader);
        }