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); } } }
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); }