예제 #1
0
        /*
         * end of central dir signature     4 bytes (0x06054b50)
         * number of this disk  2 bytes
         * number of the disk with the start of the central directory   2 bytes
         * total number of entries in the central directory on this disk    2 bytes
         * total number of entries in the central directory     2 bytes
         * size of the central directory    4 bytes
         * offset of start of central directory
         * with respect to the starting disk number     4 bytes
         * .ZIP file comment length     2 bytes
         * .ZIP file comment    (variable size)
         */

        /// <summary>
        /// TODO: case when the whole file is smaller than 64K
        /// TODO: handle non HTTP case
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public bool Load()
        {
            int CentralOffset, CentralSize;
            int TotalEntries;

            if (!FindCentralDirectory(out CentralOffset, out CentralSize, out TotalEntries))
            {
                return(false);
            }

            MaxFileOffset = CentralOffset;

            // now retrieve the Central Directory
            entries = new ZipEntry[TotalEntries];

            //HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            //req.AddRange(CentralOffset, CentralOffset+CentralSize);
            //HttpWebResponse res = (HttpWebResponse)req.GetResponse();

            using (Stream s = protocolProvider.CreateStream(this.url,
                                                            CentralOffset, CentralOffset + CentralSize))
            {
                // code taken from SharpZipLib with modification for not seekable stream
                // and adjustement for Central Directory entry
                for (int i = 0; i < TotalEntries; i++)
                {
                    if (ReadLeInt(s) != ZipConstants.CentralHeaderSignature)
                    {
                        throw new ZipException("Wrong Central Directory signature");
                    }

                    // skip 6 bytes: version made (W), version ext (W), flags (W)
                    ReadLeInt(s);
                    ReadLeShort(s);
                    int method     = ReadLeShort(s);
                    int dostime    = ReadLeInt(s);
                    int crc        = ReadLeInt(s);
                    int csize      = ReadLeInt(s);
                    int size       = ReadLeInt(s);
                    int nameLen    = ReadLeShort(s);
                    int extraLen   = ReadLeShort(s);
                    int commentLen = ReadLeShort(s);
                    // skip 8 bytes: disk number start, internal file attribs, external file attribs (DW)
                    ReadLeInt(s);
                    ReadLeInt(s);
                    int offset = ReadLeInt(s);

                    byte[] buffer = new byte[Math.Max(nameLen, commentLen)];

                    StreamHelper.ReadAll(buffer, 0, nameLen, s);
                    string name = ZipConstants.ConvertToString(buffer);

                    ZipEntry entry = new ZipEntry(name);
                    entry.CompressionMethod = (CompressionMethod)method;
                    entry.Crc            = crc & 0xffffffffL;
                    entry.Size           = size & 0xffffffffL;
                    entry.CompressedSize = csize & 0xffffffffL;
                    entry.DosTime        = (uint)dostime;
                    if (extraLen > 0)
                    {
                        byte[] extra = new byte[extraLen];
                        StreamHelper.ReadAll(extra, 0, extraLen, s);
                        entry.ExtraData = extra;
                    }
                    if (commentLen > 0)
                    {
                        StreamHelper.ReadAll(buffer, 0, commentLen, s);
                        entry.Comment = ZipConstants.ConvertToString(buffer);
                    }
                    entry.ZipFileIndex = i;
                    entry.Offset       = offset;
                    entries[i]         = entry;
                    OnProgress((i * 100) / TotalEntries);
                }
            }

            OnProgress(100);

            return(true);
        }