public static void UnpackSng(Stream input, Stream output, Platform platform) { EndianBitConverter conv = platform.GetBitConverter; using (var decrypted = new MemoryStream()) using (var brDec = new EndianBinaryReader(conv, decrypted)) { byte[] key; switch (platform.platform) { case GamePlatform.Mac: key = RijndaelEncryptor.SngKeyMac; break; case GamePlatform.Pc: //PC key = RijndaelEncryptor.SngKeyPC; break; default: key = null; break; } if (key != null) { RijndaelEncryptor.DecryptSngData(input, decrypted, key, conv); } else { input.CopyTo(decrypted); decrypted.Seek(8, SeekOrigin.Begin); } //unZip long plainLen = brDec.ReadUInt32(); ushort xU = brDec.ReadUInt16(); decrypted.Position -= 2; if (xU == 0x78DA || xU == 0xDA78)//LE 55928 //BE 30938 { RijndaelEncryptor.Unzip(decrypted, output, false); } } }
/// <summary> /// Inflates selected entry. /// </summary> /// <param name="entry">Entry to unpack.</param> /// <param name = "destfilepath">Destination file used instead of the temp file.</param> public void InflateEntry(Entry entry, string destfilepath = "") { if (entry.Length == 0) { return; //skip empty files } // Decompress Entry const int zHeader = 0x78DA; uint zChunkID = entry.zIndexBegin; int blockSize = (int)_header.BlockSizeAlloc; //bool isZlib = _header.CompressionMethod == 2053925218; if (destfilepath.Length > 0) { entry.Data = new FileStream(destfilepath, FileMode.Create, FileAccess.Write, FileShare.Read); } else { entry.Data = new TempFileStream(); } _reader.BaseStream.Position = (long)entry.Offset; do { // check for corrupt CDLC content and catch exceptions try { if (_zBlocksSizeList[zChunkID] == 0U) // raw. full cluster used. { entry.Data.Write(_reader.ReadBytes(blockSize), 0, blockSize); } else { var num = _reader.ReadUInt16(); _reader.BaseStream.Position -= 2L; var array = _reader.ReadBytes((int)_zBlocksSizeList[zChunkID]); if (num == zHeader) { // compressed try { RijndaelEncryptor.Unzip(array, entry.Data, false); } catch (Exception ex)//IOException { // corrupt CDLC zlib.net exception ... try to unpack if (String.IsNullOrEmpty(entry.Name)) { ErrMSG = String.Format(@"{1}CDLC contains a zlib exception.{1}Warning: {0}{1}", ex.Message, Environment.NewLine); } else { ErrMSG = String.Format(@"{2}CDLC contains a broken datachunk in file '{0}'.{2}Warning: {1}{2}", entry.Name.Split('/').Last(), ex.Message, Environment.NewLine); } Console.Write(ErrMSG); } } else // raw. used only for data(chunks) smaller than 64 kb { entry.Data.Write(array, 0, array.Length); } } zChunkID += 1; } catch (Exception ex) // index is outside the bounds of the array { // corrupt CDLC data length ... try to unpack ErrMSG = String.Format(@"{2}CDLC contains a broken datachunk in file '{0}'.{2}Warning: {1}{2}", entry.Name.Split('/').Last(), ex.Message, Environment.NewLine); Console.Write(ErrMSG + Environment.NewLine); break; } } while (entry.Data.Length < (long)entry.Length); entry.Data.Seek(0, SeekOrigin.Begin); entry.Data.Flush(); }
/// <summary> /// Inflates selected entry. /// </summary> /// <param name="entry">Enty to unpack.</param> /// <param name = "destfilepath">Destanation file used instead of the temp file.</param> public void InflateEntry(Entry entry, string destfilepath = "") { if (entry.Length > 0) {// Decompress Entry uint zChunkID = entry.zIndexBegin; int blockSize = (int)this.header.blockSizeAlloc; bool isZlib = this.header.CompressionMethod == 2053925218; const int zHeader = 0x78DA; if (destfilepath.Length > 0) { entry.Data = new FileStream(destfilepath, FileMode.Create, FileAccess.Write, FileShare.Read); } else { entry.Data = new TempFileStream(); } var data = entry.Data; _reader.BaseStream.Position = (long)entry.Offset; do { // check for corrupt CDLC content and catch exceptions try { if (this.zBlocksSizeList[zChunkID] == 0) { // raw byte[] array = _reader.ReadBytes(blockSize); data.Write(array, 0, blockSize); } else { var num = _reader.ReadUInt16(); _reader.BaseStream.Position -= 2; byte[] array = _reader.ReadBytes((int)this.zBlocksSizeList[zChunkID]); if (num == zHeader) { // compressed try { RijndaelEncryptor.Unzip(array, data, false); } catch (Exception ex) { // corrupt CDLC zlib.net exception ... try to unpack if (String.IsNullOrEmpty(entry.Name)) { ErrMSG = String.Format(@"{1}CDLC contains a zlib exception.{1}Warning: {0}{1}", ex.Message, Environment.NewLine); } else { ErrMSG = String.Format(@"{2}CDLC contains a broken datachunk in file '{0}'.{2}Warning: {1}{2}", entry.Name.Split('/').Last(), ex.Message, Environment.NewLine); } Console.Write(ErrMSG); // TODO: requires proper presizing of array length // data.Write(new byte[array.Length], 0, array.Length); } } else { // raw. used only after 0? data.Write(array, 0, array.Length); } } zChunkID += 1; } catch (Exception ex) // index is outside the bounds of the array { // corrupt CDLC data length ... try to unpack ErrMSG = String.Format(@"{2}CDLC contains a broken datachunk in file '{0}'.{2}Warning: {1}{2}", entry.Name.Split('/').Last(), ex.Message, Environment.NewLine); Console.Write(ErrMSG + Environment.NewLine); break; } }while (data.Length < (long)entry.Length); data.Seek(0, SeekOrigin.Begin); data.Flush(); } }