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); }
//public const UInt32 ExternalAttr = 0x81B40020; // Texmod uses this one but ours won't work if we do... 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 = CRC32.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; }