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); }
/// <summary> /// Constructor for tree texture object. /// </summary> /// <param name="temppcc">PCC to get info from.</param> /// <param name="ExpID">ExpID of texture.</param> /// <param name="WhichGame">Game target.</param> /// <param name="pathBIOGame">BIOGame path to game targeted.</param> /// <param name="ExecPath">Path to ME3Explorer \exec\ folder.</param> /// <param name="allfiles">List of all PCC's containing texture.</param> /// <param name="Success">OUT: True if sucessfully created.</param> public TreeTexInfo(IPCCObject temppcc, int ExpID, int WhichGame, string pathBIOGame, string ExecPath, out bool Success) { Success = false; CRC32 crcgen = new CRC32(); string ArcPath = pathBIOGame; ITexture2D temptex2D = null; if (temppcc.Exports[ExpID].ValidTextureClass()) { try { temptex2D = temppcc.CreateTexture2D(ExpID, pathBIOGame); } catch (Exception e) { Console.WriteLine(e); return; } // KFreon: If no images, ignore if (temptex2D.imgList.Count == 0) return; string texname = temptex2D.texName; IImageInfo tempImg = temptex2D.GenerateImageInfo(); uint hash = 0; // KFreon: Get texture hash if (tempImg.CompareStorage("pccSto")) { if (temptex2D.texFormat != ImageEngineFormat.DDS_ATI2_3Dc) hash = ~crcgen.BlockChecksum(temptex2D.DumpImg(tempImg.imgSize, ArcPath)); else hash = ~crcgen.BlockChecksum(temptex2D.DumpImg(tempImg.imgSize, pathBIOGame), 0, tempImg.uncSize / 2); } else { byte[] buffer = temptex2D.DumpImg(tempImg.imgSize, ArcPath); if (buffer == null) hash = 0; else { if (temptex2D.texFormat != ImageEngineFormat.DDS_ATI2_3Dc) hash = ~crcgen.BlockChecksum(buffer); else hash = ~crcgen.BlockChecksum(buffer, 0, tempImg.uncSize / 2); } } // KFreon: Get image thumbnail string thumbnailPath = ExecPath + "placeholder.ico"; string tempthumbpath = ExecPath + "ThumbnailCaches\\" + "ME" + WhichGame + "ThumbnailCache\\" + texname + "_" + hash + ".jpg"; bool exists = File.Exists(tempthumbpath); if (!exists) try { using (MemoryStream ms = new MemoryStream(temptex2D.GetImageData())) { var tex = temptex2D.imgList.Where(t => t.offset != -1).First(); int max = (int)(tex.imgSize.height > tex.imgSize.width ? tex.imgSize.height : tex.imgSize.width); double divisor = max > 128 ? max / 128.0 : 1; int newWidth = (int)(tex.imgSize.width / divisor); int newHeight = (int)(tex.imgSize.height / divisor); string temp = KFreonLib.Textures.Creation.GenerateThumbnail(ms, tempthumbpath, newWidth, newHeight); if (temp != null) thumbnailPath = temp; } } catch { } // KFreon: Don't really care about failures // KFreon: Initialise things ValidFirstPCC = WhichGame == 2 && (!String.IsNullOrEmpty(temptex2D.arcName) && temptex2D.arcName != "None"); InfoInitialise(temptex2D, ExpID, hash, WhichGame, temppcc, tempImg.offset, thumbnailPath, pathBIOGame); Success = true; } }
public byte[] Extract(bool Preview, String outname = null) { byte[] databuff; int dataoff = 30; if (Filename != null) dataoff += Filename.Length; if (Extra != null) dataoff += Extra.Length; using (FileStream tpf = new FileStream(_par._filename, FileMode.Open, FileAccess.Read)) { tpf.Seek(FileOffset, SeekOrigin.Begin); databuff = ZipReader.BuffXOR(tpf, dataoff + (int)ComprSize + 16); // XOR the whole data block as well as the footer } // Check for correct header data and such ZipEntry fileentry = new ZipEntry(databuff); if (!fileentry.Compare(this)) throw new InvalidDataException("File header not as expected"); if (BitConverter.ToUInt32(databuff, (int)ComprSize + dataoff) != datadescriptormagic) throw new InvalidDataException("Footer not as expected"); //ZipCrypto.DecryptData(this, databuff, dataoff, (int)ComprSize); KFreonZipCrypto crypto = new KFreonZipCrypto(this, databuff, dataoff, (int)ComprSize); databuff = crypto.GetBlocks(); databuff = Deflate(databuff, 12 + dataoff, (int)ComprSize - 12); if (databuff.Length != UncomprSize) throw new InvalidDataException("Deflation resulted in incorrect file size"); CRC32 crcgen = new CRC32(); if (crcgen.BlockChecksum(databuff, 0, (int)UncomprSize) != CRC) throw new InvalidDataException("Checksums don't match"); if (!Preview) { outname = outname ?? Filename; using (FileStream fs = new FileStream(outname, FileMode.Create, FileAccess.Write)) { fs.Write(databuff, 0, (int)UncomprSize); } return null; } else return databuff; }
public byte[] Extract(bool Preview, String outname = null) { byte[] databuff; int dataoff = 30; if (Filename != null) { dataoff += Filename.Length; } if (Extra != null) { dataoff += Extra.Length; } using (FileStream tpf = new FileStream(_par._filename, FileMode.Open, FileAccess.Read)) { tpf.Seek(FileOffset, SeekOrigin.Begin); databuff = ZipReader.BuffXOR(tpf, dataoff + (int)ComprSize + 16); // XOR the whole data block as well as the footer } // Check for correct header data and such ZipEntry fileentry = new ZipEntry(databuff); if (!fileentry.Compare(this)) { throw new InvalidDataException("File header not as expected"); } if (BitConverter.ToUInt32(databuff, (int)ComprSize + dataoff) != datadescriptormagic) { throw new InvalidDataException("Footer not as expected"); } //ZipCrypto.DecryptData(this, databuff, dataoff, (int)ComprSize); KFreonZipCrypto crypto = new KFreonZipCrypto(this, databuff, dataoff, (int)ComprSize); databuff = crypto.GetBlocks(); databuff = Deflate(databuff, 12 + dataoff, (int)ComprSize - 12); if (databuff.Length != UncomprSize) { throw new InvalidDataException("Deflation resulted in incorrect file size"); } CRC32 crcgen = new CRC32(); if (crcgen.BlockChecksum(databuff, 0, (int)UncomprSize) != CRC) { throw new InvalidDataException("Checksums don't match"); } if (!Preview) { outname = outname ?? Filename; using (FileStream fs = new FileStream(outname, FileMode.Create, FileAccess.Write)) { fs.Write(databuff, 0, (int)UncomprSize); } return(null); } else { return(databuff); } }
/// <summary> /// Constructor for tree texture object. /// </summary> /// <param name="temppcc">PCC to get info from.</param> /// <param name="ExpID">ExpID of texture.</param> /// <param name="WhichGame">Game target.</param> /// <param name="pathBIOGame">BIOGame path to game targeted.</param> /// <param name="ExecPath">Path to ME3Explorer \exec\ folder.</param> /// <param name="allfiles">List of all PCC's containing texture.</param> /// <param name="Success">OUT: True if sucessfully created.</param> public TreeTexInfo(IPCCObject temppcc, int ExpID, int WhichGame, string pathBIOGame, string ExecPath, out bool Success) { Success = false; CRC32 crcgen = new CRC32(); string ArcPath = pathBIOGame; ITexture2D temptex2D = null; if (temppcc.Exports[ExpID].ValidTextureClass()) { try { temptex2D = temppcc.CreateTexture2D(ExpID, pathBIOGame); } catch (Exception e) { Console.WriteLine(e); return; } // KFreon: If no images, ignore if (temptex2D.imgList.Count == 0) return; string texname = temptex2D.texName; IImageInfo tempImg = temptex2D.GenerateImageInfo(); uint hash = 0; /*if (WhichGame != 1 && temptex2D.arcName != "None") ValidFirstPCC = true;*/ // KFreon: Add pcc name to list in tex2D if necessary /*if (temptex2D.allFiles == null || temptex2D.allFiles.Count == 0) { temptex2D.allFiles = new List<string>(); temptex2D.allFiles.Add(temppcc.pccFileName); } else if (!temptex2D.allFiles.Contains(temppcc.pccFileName)) temptex2D.allFiles.Add(temppcc.pccFileName);*/ // KFreon: Get texture hash if (tempImg.CompareStorage("pccSto")) { if (temptex2D.texFormat != "PF_NormalMap_HQ") hash = ~crcgen.BlockChecksum(temptex2D.DumpImg(tempImg.imgSize, ArcPath)); else hash = ~crcgen.BlockChecksum(temptex2D.DumpImg(tempImg.imgSize, pathBIOGame), 0, tempImg.uncSize / 2); } else { byte[] buffer = temptex2D.DumpImg(tempImg.imgSize, ArcPath); if (buffer == null) hash = 0; else { if (temptex2D.texFormat != "PF_NormalMap_HQ") hash = ~crcgen.BlockChecksum(buffer); else hash = ~crcgen.BlockChecksum(buffer, 0, tempImg.uncSize / 2); } } // KFreon: Get image thumbnail string thumbnailPath = ExecPath + "placeholder.ico"; string tempthumbpath = ExecPath + "ThumbnailCaches\\" + "ME" + WhichGame + "ThumbnailCache\\" + texname + "_" + hash + ".jpg"; bool exists = File.Exists(tempthumbpath); if (!exists) try { using (MemoryStream ms = new MemoryStream(temptex2D.GetImageData())) if (ImageEngine.GenerateThumbnailToFile(ms, tempthumbpath, 128)) thumbnailPath = tempthumbpath; } catch { } // KFreon: Don't really care about failures // KFreon: Initialise things ValidFirstPCC = WhichGame == 2 && (!String.IsNullOrEmpty(temptex2D.arcName) && temptex2D.arcName != "None"); InfoInitialise(temptex2D, ExpID, hash, WhichGame, temppcc, tempImg.offset, thumbnailPath, pathBIOGame); Success = true; } }
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); } } }
public byte[] Extract(bool Preview, String outname = null) { byte[] databuff; int dataoff = 30; // For ZipEntry header - not the above one if (Filename != null) { dataoff += Filename.Length; } if (Extra != null) { dataoff += Extra.Length; } // KFreon: Use stored MemoryStream if possible. Stream tpf = null; if (_par.FileData == null) { tpf = new FileStream(_par._filename, FileMode.Open, FileAccess.Read); } else { tpf = new MemoryStream(_par.FileData); } tpf.Seek(FileOffset, SeekOrigin.Begin); databuff = ZipReader.BuffXOR(tpf, dataoff + (int)ComprSize + 16); // XOR the whole data block as well as the footer // KFreon: Dispose of stream IF it was a FileStream if (_par.FileData == null) { tpf.Dispose(); } // Check for correct header data and such ZipEntry fileentry = new ZipEntry(databuff); if (!fileentry.Compare(this)) { throw new InvalidDataException("File header not as expected"); } // KFreon: Apparently not necessary. Some TPF's fail to load with this, but when commented out, they load fine, so... /*if (BitConverter.ToUInt32(databuff, (int)ComprSize + dataoff) != datadescriptormagic) * Console.WriteLine("Footer not as expected");*/ ZipDecrypto crypto = new ZipDecrypto(this, databuff, dataoff, (int)ComprSize); databuff = crypto.GetBlocks(); databuff = Deflate(databuff, 12 + dataoff, (int)ComprSize - 12); if (databuff.Length != UncomprSize) { throw new InvalidDataException("Deflation resulted in incorrect file size"); } CRC32 crcgen = new CRC32(); if (crcgen.BlockChecksum(databuff, 0, (int)UncomprSize) != CRC) { throw new InvalidDataException("Checksums don't match"); } if (!Preview) { outname = outname ?? Filename; using (FileStream fs = new FileStream(outname, FileMode.Create, FileAccess.Write)) { fs.Write(databuff, 0, (int)UncomprSize); } return(null); } else { return(databuff); } }