public static void Repack(String filename, List <String> files)
        {
            List <ZipEntry> Entries = new List <ZipEntry>();

            foreach (String file in files)
            {
                if (!File.Exists(file))
                {
                    throw new FileNotFoundException(Path.GetFileName(file) + " was not found");
                }
            }

            using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite))
            {
                CRC32 crcgen = new CRC32();
                foreach (String file in files)
                {
                    ZipEntry entry = new ZipEntry();
                    entry.MainOffset = fs.Position;
                    entry.Filename   = Path.GetFileName(file);

                    //Header
                    fs.Write(BitConverter.GetBytes(ZipReader.filemagic), 0, 4);
                    fs.Write(BitConverter.GetBytes(MinVers), 0, 2);

                    // TEST build version?
                    //fs.Write(BitConverter.GetBytes(20), 0, 2);

                    fs.Write(BitConverter.GetBytes(BitFlag), 0, 2);
                    fs.Write(BitConverter.GetBytes(ComprMethod), 0, 2);

                    //Date/time
                    FileInfo finfo    = new FileInfo(file);
                    ushort   secs     = (ushort)finfo.LastWriteTime.Second;
                    ushort   mins     = (ushort)finfo.LastWriteTime.Minute;
                    ushort   hours    = (ushort)finfo.LastWriteTime.Hour;
                    ushort   datetime = (ushort)(secs / 2);
                    datetime |= (ushort)(mins >> 5);
                    datetime |= (ushort)(hours >> 11);
                    fs.Write(BitConverter.GetBytes(datetime), 0, 2);
                    entry.Time = datetime;

                    ushort day   = (ushort)finfo.LastWriteTime.Day;
                    ushort month = (ushort)finfo.LastWriteTime.Month;
                    ushort year  = (ushort)finfo.LastWriteTime.Year;
                    datetime  = day;
                    datetime &= (ushort)(month >> 5);
                    datetime &= (ushort)(year >> 9);
                    fs.Write(BitConverter.GetBytes(datetime), 0, 2);
                    entry.Date = datetime;

                    byte[] comprData;
                    long   temppos;
                    using (FileStream fs2 = new FileStream(file, FileMode.Open, FileAccess.Read))
                    {
                        byte[] buff = new byte[fs2.Length];
                        fs2.Read(buff, 0, buff.Length);

                        entry.CRC32  = crcgen.BlockChecksum(buff);
                        entry.UncLen = (UInt32)fs2.Length;

                        fs.Write(BitConverter.GetBytes(entry.CRC32), 0, 4);

                        fs.Seek(4, SeekOrigin.Current); // Skip compressed size
                        fs.Write(BitConverter.GetBytes(entry.UncLen), 0, 4);

                        if (entry.Filename.ToLower().Contains("meresults"))
                        {
                            entry.Filename = "texmod.log";
                        }

                        fs.Write(BitConverter.GetBytes((ushort)entry.Filename.Length), 0, 2);
                        fs.Write(BitConverter.GetBytes((ushort)0), 0, 2);

                        foreach (char c in entry.Filename)
                        {
                            fs.WriteByte((byte)c);
                        }
                        temppos = fs.Position;

                        fs2.Seek(0, SeekOrigin.Begin); // Rewind
                        using (MemoryStream ms = new MemoryStream())
                        {
                            using (DeflateStream deflator = new DeflateStream(ms, CompressionMode.Compress))
                                fs2.CopyTo(deflator);

                            comprData = ms.ToArray();
                        }
                        entry.ComprLen = (uint)comprData.Length + 12;
                    }

                    fs.Seek(entry.MainOffset + 18, SeekOrigin.Begin);
                    fs.Write(BitConverter.GetBytes(entry.ComprLen), 0, 4);
                    fs.Seek(temppos, SeekOrigin.Begin);
                    ZipCrypto.EncryptData(fs, comprData); // Encrypt and write data

                    fs.Write(BitConverter.GetBytes(ZipReader.datadescriptormagic), 0, 4);
                    fs.Write(BitConverter.GetBytes(entry.CRC32), 0, 4);
                    fs.Write(BitConverter.GetBytes(entry.ComprLen), 0, 4);
                    fs.Write(BitConverter.GetBytes(entry.UncLen), 0, 4);
                    Entries.Add(entry);
                }

                uint cdlen = 0;
                uint cdpos = (uint)fs.Position;
                for (int i = 0; i < Entries.Count; i++)
                {
                    long start = fs.Position;
                    fs.Write(BitConverter.GetBytes(ZipReader.dirfileheadermagic), 0, 4);
                    fs.Write(BitConverter.GetBytes(ZipWriter.MinVers), 0, 2);
                    fs.Write(BitConverter.GetBytes(ZipWriter.MinVers), 0, 2);
                    fs.Write(BitConverter.GetBytes(ZipWriter.BitFlag), 0, 2);
                    fs.Write(BitConverter.GetBytes(ZipWriter.ComprMethod), 0, 2);

                    ZipWriter.ZipEntry entry = Entries[i];
                    fs.Write(BitConverter.GetBytes(entry.Time), 0, 2);
                    fs.Write(BitConverter.GetBytes(entry.Date), 0, 2);
                    fs.Write(BitConverter.GetBytes(entry.CRC32), 0, 4);
                    fs.Write(BitConverter.GetBytes(entry.ComprLen), 0, 4);
                    fs.Write(BitConverter.GetBytes(entry.UncLen), 0, 4);
                    fs.Write(BitConverter.GetBytes((ushort)entry.Filename.Length), 0, 2);

                    fs.Write(BitConverter.GetBytes(0), 0, 4); // 0 for extra field

                    fs.Write(BitConverter.GetBytes(0), 0, 4); // 0 for disk no, 0 for internal attributes
                    fs.Write(BitConverter.GetBytes(0x81B40020), 0, 4);
                    fs.Write(BitConverter.GetBytes((int)entry.MainOffset), 0, 4);
                    foreach (char c in entry.Filename)
                    {
                        fs.WriteByte((byte)c);
                    }
                    long end = fs.Position;
                    cdlen += (uint)(end - start);
                }

                fs.Write(BitConverter.GetBytes(ZipReader.endofdirmagic), 0, 4);
                fs.Write(BitConverter.GetBytes(0), 0, 4);
                fs.Write(BitConverter.GetBytes((ushort)Entries.Count), 0, 2);
                fs.Write(BitConverter.GetBytes((ushort)Entries.Count), 0, 2);
                fs.Write(BitConverter.GetBytes(cdlen), 0, 4);
                fs.Write(BitConverter.GetBytes(cdpos), 0, 4);

                string createdBy = " ";
                string comment   = " ";

                string fullString = createdBy + "\n" + comment;

                fs.Write(BitConverter.GetBytes(fullString.Length), 0, 2);
                byte[] bytes = Encoding.Default.GetBytes(fullString);
                fs.Write(bytes, 0, bytes.Length);


                long streamlen = fs.Length;
                fs.Seek(0, SeekOrigin.Begin); // XOR the file

                while (fs.Position < fs.Length)
                {
                    int count = (fs.Position + 10000 <= fs.Length) ? 10000 : (int)(fs.Length - fs.Position);

                    byte[] buff2 = BuffXOR(fs, count);
                    fs.Seek(-count, SeekOrigin.Current);
                    fs.Write(buff2, 0, count);
                }
            }
        }
Beispiel #2
0
        static WriterZipEntry BuildEntry(Stream ms, string file, Func <byte[]> dataGetter)
        {
            bool FileOnDisk = dataGetter == null;

            WriterZipEntry entry = new WriterZipEntry();

            entry.MainOffset = ms.Position;
            entry.Filename   = FileOnDisk ? Path.GetFileName(file) : file;

            //Header
            ms.Write(BitConverter.GetBytes(ZipReader.filemagic), 0, 4);
            ms.Write(BitConverter.GetBytes(MinVers), 0, 2);
            ms.Write(BitConverter.GetBytes(BitFlag), 0, 2);
            ms.Write(BitConverter.GetBytes(ComprMethod), 0, 2);

            //Date/time
            DateTime date  = FileOnDisk ? new FileInfo(file).LastWriteTime : DateTime.Now;
            ushort   secs  = 0;
            ushort   mins  = 0;
            ushort   hours = 0;

            ushort day   = 0;
            ushort month = 0;
            ushort year  = 0;

            secs  = (ushort)date.Second;
            mins  = (ushort)date.Minute;
            hours = (ushort)date.Hour;

            ushort datetime = (ushort)(secs / 2);

            datetime |= (ushort)(mins >> 5);
            datetime |= (ushort)(hours >> 11);
            ms.Write(BitConverter.GetBytes(datetime), 0, 2);
            entry.Time = datetime;

            day   = (ushort)date.Day;
            month = (ushort)date.Month;
            year  = (ushort)date.Year;

            datetime  = day;
            datetime &= (ushort)(month >> 5);
            datetime &= (ushort)(year >> 9);
            ms.Write(BitConverter.GetBytes(datetime), 0, 2);
            entry.Date = datetime;

            byte[] comprData;
            Stream dataStream = null;

            if (FileOnDisk)
            {
                dataStream = new FileStream(file, FileMode.Open, FileAccess.Read);
            }
            else
            {
                dataStream = new MemoryStream(dataGetter());
            }

            using (dataStream)
            {
                byte[] buff = new byte[dataStream.Length];
                dataStream.Read(buff, 0, buff.Length);

                // create and write local header
                entry.CRC32  = crc.BlockChecksum(buff);
                entry.UncLen = (UInt32)dataStream.Length;

                ms.Write(BitConverter.GetBytes(entry.CRC32), 0, 4);

                ms.Seek(4, SeekOrigin.Current); // Skip compressed size
                ms.Write(BitConverter.GetBytes(entry.UncLen), 0, 4);

                if (entry.Filename.ToLower().Contains("meresults"))
                {
                    entry.Filename = "texmod.def";
                }

                ms.Write(BitConverter.GetBytes((ushort)entry.Filename.Length), 0, 2);
                ms.Write(BitConverter.GetBytes((ushort)0), 0, 2);  // extra

                // Filename
                foreach (char c in entry.Filename)
                {
                    ms.WriteByte((byte)c);
                }

                dataStream.Seek(0, SeekOrigin.Begin); // Rewind to compress entry
                using (MemoryStream ms2 = new MemoryStream())
                {
                    using (DeflateStream deflator = new DeflateStream(ms2, CompressionMode.Compress))
                        dataStream.CopyTo(deflator);

                    comprData = ms2.ToArray();
                }
                entry.ComprLen = (uint)comprData.Length + 12;      // 12 is crypt header
                ZipCrypto.EncryptData(ms, comprData, entry.CRC32); // Encrypt and write data
            }

            // Footer
            ms.Write(BitConverter.GetBytes(ZipReader.datadescriptormagic), 0, 4);
            ms.Write(BitConverter.GetBytes(entry.CRC32), 0, 4);
            ms.Write(BitConverter.GetBytes(entry.ComprLen), 0, 4);
            ms.Write(BitConverter.GetBytes(entry.UncLen), 0, 4);

            // Go back and write compressed length
            ms.Seek(entry.MainOffset + 18, SeekOrigin.Begin);
            ms.Write(BitConverter.GetBytes(entry.ComprLen), 0, 4);

            // Go to end for next entry
            ms.Seek(0, SeekOrigin.End);
            return(entry);
        }