///<summary> /// 重启报文 ///</summary> ///<returns></returns> public override string Serialize() { // 包头 F3 // 功能码 03 // 子功能码 00 // CRC校验 2bytes var data = new List <string> { Header, Convert.ToString(FunctionCode, 16), Convert.ToString(SubFunctionCode, 16), }; var crc = CrcHelper.GetCrc16(data); data.AddRange(crc); return(data.Join(",")); }
///<summary> /// 报文 ///</summary> ///<returns></returns> public override string Serialize() { //0xF1 10 00 00 01,41,00,00,脚本长度4字节小端,密码长度4字节小端 CRC // 包头 F1 // 功能码 10 // 子功能码 00 // 操作码 00 // 脚本长度4字节小端 01,41 // 密码长度4字节小端 00,00 // CRC校验 2bytes var data = new List <string> { Header, FunctionCode.ToString(), Convert.ToString(SubFunctionCode, 16), Convert.ToString(OperateCode, 16), "01", "41", "00", "00" }; var cData = new List <string>(); for (var i = 0; i < 4; i++) { cData.Add(Convert.ToString((byte)(DataLength >> i * 8 & 0xff), 16)); } data.AddRange(cData); cData.Clear(); for (var i = 0; i < 4; i++) { cData.Add(Convert.ToString((byte)(PwdLength >> i * 8 & 0xff), 16)); } data.AddRange(cData); var crc = CrcHelper.GetCrc16(data); data.AddRange(crc); return(data.Join(",")); }
public byte[] BuildBytes() { var list = new List <byte>(); list.AddRange(Header); list.AddRange(EncodingHelper.HexToBytes(Length.ToHex(4))); list.AddRange(EncodingHelper.HexToBytes(SessionId)); list.AddRange(Device.Bytes); list.AddRange(Command.GetBytes()); Crc16 = CrcHelper.GetCrc16(list.ToArray()).ToHex(4); list.AddRange(EncodingHelper.HexToBytes(Crc16)); Body = list.CloneRange(Header.Length + 2, Length).ToArray(); BodyHex = Body.ToHex(); EncryptedBody = filter.Crypto.Encrypt(Body); list.RemoveRange(Header.Length + 2, Length); list.AddRange(EncryptedBody); return(list.ToArray()); }
public IdatChunk ToIdatChunk() { uint newCrc; using (var msCrc = new MemoryStream()) { msCrc.WriteBytes(new[] { (byte)'I', (byte)'D', (byte)'A', (byte)'T' }); msCrc.WriteBytes(FrameData); newCrc = CrcHelper.Calculate(msCrc.ToArray()); } using (var ms = new MemoryStream()) { ms.WriteUInt32(Helper.ConvertEndian(Length - 4)); ms.WriteBytes(new[] { (byte)'I', (byte)'D', (byte)'A', (byte)'T' }); ms.WriteBytes(FrameData); ms.WriteUInt32(Helper.ConvertEndian(newCrc)); ms.Position = 0; return(new IdatChunk(ms)); } }
public static byte GetExtraCrc(string xMessageName, IEnumerable <MessageField> xMessageFields) { UInt16 crc = CrcHelper.GetCrc(xMessageName + ' '); IList <MessageFieldCrcData> fieldCrcDatas = ToMessageFieldCrcDatas(xMessageFields); foreach (MessageFieldCrcData fieldCrcData in fieldCrcDatas.OrderByDescending(t => t.TypeLength).ThenBy(t => t.DefinitionIndex).ToList()) { String translatedRawType = TypeHelper.TranslatePrimitiveRawType(fieldCrcData.Field.Type); string rawDataType = TypeHelper.ToRawDataType(translatedRawType); crc = CrcHelper.GetCrc(rawDataType + ' ', crc); crc = CrcHelper.GetCrc(fieldCrcData.Field.Name + ' ', crc); if (fieldCrcData.ArrayLength > 1) { crc = CrcHelper.GetCrc((byte)fieldCrcData.ArrayLength, crc); } } byte result = (byte)((crc & 0xFF) ^ (crc >> 8)); return(result); }
internal ApngFrame GetFrame(int index) { //Build each frame using: //Starting blocks: IHDR, tIME, zTXt, tEXt, iTXt, pHYs, sPLT, (iCCP | sRGB), sBIT, gAMA, cHRM, PLTE, tRNS, hIST, bKGD. //Image data: IDAT. //End block: IEND. var chunks = Chunks.Where(w => w.FrameGroupId == index).ToList(); var otherChunks = Chunks.Where(w => w.FrameGroupId == -1 && w.ChunkType != "IDAT").ToList(); if (!chunks.Any()) { return(null); } var frame = new ApngFrame(); //First frame • Second frame //Default image is part of the animation: fcTL + IDAT • fcTL + fdAT //Default image isn't part of the animation: IDAT • fcTL + fdAT if (chunks[0].ChunkType == "fcTL") { var fctl = FctlChunk.Read(chunks[0].Length, chunks[0].ChunkData); frame.Delay = fctl.DelayNum == 0 ? 10 : (int)(fctl.DelayNum / (fctl.DelayDen == 0 ? 100d : fctl.DelayDen) * 1000d); frame.Width = fctl.Width; frame.Height = fctl.Height; frame.Left = fctl.XOffset; frame.Top = fctl.YOffset; frame.ColorType = Ihdr.ColorType; frame.BitDepth = Ihdr.BitDepth; frame.DisposeOp = fctl.DisposeOp; frame.BlendOp = fctl.BlendOp; using (var stream = new MemoryStream()) { //Png signature, 8 bytes. stream.WriteBytes(new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 }); //Image header chunk. 25 bytes. Ihdr.Write(stream, fctl.Width, fctl.Height); //Any other auxiliar chunks. foreach (var other in otherChunks) { other.Write(stream); } //Frame has multiple chunks. if (chunks.Count > 2) { var datas = new List <byte[]>(); //Data chunks. for (var i = 1; i < chunks.Count; i++) { switch (chunks[i].ChunkType) { case "fdAT": { var fdat = FdatChunk.Read(chunks[i].Length, chunks[i].ChunkData); datas.Add(fdat.FrameData); break; } case "IDAT": { var idat = IdatChunk.Read(chunks[i].Length, chunks[i].ChunkData); datas.Add(idat.FrameData); break; } } } //Write combined frame data. var length = datas.Sum(s => s.Length); stream.WriteUInt32(BitHelper.ConvertEndian((uint)length)); //4 bytes. stream.WriteBytes(Encoding.ASCII.GetBytes("IDAT")); //4 bytes. stream.WriteBytes(datas.SelectMany(s => s).ToArray()); //XX bytes. stream.WriteUInt32(BitHelper.ConvertEndian(CrcHelper.Calculate(stream.PeekBytes(stream.Position - (length + 4), length + 4)))); //CRC, 4 bytes. } else { switch (chunks[1].ChunkType) { case "fdAT": { var fdat = FdatChunk.Read(chunks[1].Length, chunks[1].ChunkData); fdat.Write(stream); break; } case "IDAT": { var idat = IdatChunk.Read(chunks[1].Length, chunks[1].ChunkData); idat.Write(stream); break; } } } //End chunk. stream.WriteUInt32(BitHelper.ConvertEndian(0u)); //Chunk length, 4 bytes. stream.WriteBytes(Encoding.ASCII.GetBytes("IEND")); //Chunk type, 4 bytes. stream.WriteUInt32(BitHelper.ConvertEndian(CrcHelper.Calculate(stream.PeekBytes(stream.Position - 4, 4)))); //CRC, 4 bytes. //Gets the whole Png. frame.ImageData = stream.ToArray(); } } else { //This is not supposed to happen. //All chunks with an FrameGroupId are grouped with a starting fcTL, ending with a IDAT or fdAT chunk. LogWriter.Log(new Exception("Missing fcTL on frame number " + index), $"It was not possible to read frame number {index}"); return(null); } return(frame); }
internal void AddFrame(string path, Int32Rect rect, int delay = 66) { using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { if (IsFirstFrame) { //Png Header: 8 bytes. InternalStream.WriteBytes(stream.ReadBytes(8)); //IHDR chunk. 13 bytes (Length + Type + CRC, 4 bytes each) = 25 bytes. InternalStream.WriteBytes(stream.ReadBytes(25)); //acTL: Animation control chunk. 8 bytes (Length + Type + CRC, 4 bytes each) = 20 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian(8u)); //Length, 4 bytes. InternalStream.WriteBytes(Encoding.ASCII.GetBytes("acTL")); //Chunk type, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)FrameCount)); //NumFrames, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)RepeatCount)); //NumPlays, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian(CrcHelper.Calculate(InternalStream.PeekBytes(InternalStream.Position - 12, 12)))); //CRC, 4 bytes. } //fcTL: Frame control chunk. 26 bytes (Length + Type + CRC, 4 bytes each) = 38 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian(26u)); //Length, 4 bytes. InternalStream.WriteBytes(Encoding.ASCII.GetBytes("fcTL")); //Chunk type, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)SequenceNumber++)); //SequenceNumber, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)rect.Width)); //Width, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)rect.Height)); //Height, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)rect.X)); //OffsetX, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)rect.Y)); //OffsetY, 4 bytes. InternalStream.WriteUInt16(BitHelper.ConvertEndian((ushort)delay)); //Delay numerator, 2 bytes. InternalStream.WriteUInt16(BitHelper.ConvertEndian((ushort)1000)); //Delay denominator, 2 bytes. if (IsFirstFrame) { InternalStream.WriteByte((byte)DisposeOps.None); //DisposeOp, 1 byte. InternalStream.WriteByte((byte)BlendOps.Source); //BlendOp, 1 byte. } else { InternalStream.WriteByte((byte)DisposeOps.None); //DisposeOp, 1 byte. InternalStream.WriteByte((byte)BlendOps.Over); //BlendOp, 1 byte. } InternalStream.WriteUInt32(BitHelper.ConvertEndian(CrcHelper.Calculate(InternalStream.PeekBytes(InternalStream.Position - 30, 30)))); //CRC, 4 bytes. //fdAT: Frame data chunk. 4 + n bytes (Length + Type + CRC, 4 bytes each) = 16 + n bytes, where n is the frame data. var dataList = GetData(stream); foreach (var data in dataList) { if (IsFirstFrame) { InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)data.Length)); //Length, 4 bytes. InternalStream.WriteBytes(Encoding.ASCII.GetBytes("IDAT")); //Chunk type, 4 bytes. InternalStream.WriteBytes(data); //Frame data, n bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian(CrcHelper.Calculate(InternalStream.PeekBytes(InternalStream.Position - (data.Length + 4), data.Length + 4)))); //CRC, 4 bytes. } else { InternalStream.WriteUInt32(BitHelper.ConvertEndian(4 + (uint)data.Length)); //Length, 4 bytes. InternalStream.WriteBytes(Encoding.ASCII.GetBytes("fdAT")); //Chunk type, 4 bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian((uint)SequenceNumber++)); //SequenceNumber, 4 bytes. InternalStream.WriteBytes(data); //Frame data, n bytes. InternalStream.WriteUInt32(BitHelper.ConvertEndian(CrcHelper.Calculate(InternalStream.PeekBytes(InternalStream.Position - (data.Length + 8), data.Length + 8)))); //CRC, 4 bytes. } } IsFirstFrame = false; } }
/// <summary> /// Determines whether [is update package available]. /// </summary> /// <returns></returns> public bool IsUpdatePackageAvailable() { return(LatestVersion != null && File.Exists(ConstantsBase.UpdatePath) && String.Equals(CrcHelper.GetCrc32HashToString(ConstantsBase.UpdatePath), LatestVersion.CrcHash, StringComparison.CurrentCultureIgnoreCase)); }
/// <summary> /// Simple method to compare checksums /// </summary> /// <param name="toComputeData">Actual hash</param> /// <param name="expectedHash">To be expetected hash</param> /// <returns></returns> private static bool CompareCrcHashes(byte[] toComputeData, string expectedHash) { return (int.Parse(CrcHelper.GetCrc32HashFromMemoryToString(toComputeData).ToLower(), System.Globalization.NumberStyles.HexNumber) == int.Parse(expectedHash.ToLower(), System.Globalization.NumberStyles.HexNumber)); }
/// <summary> /// Reads index file and creates deserialized data /// </summary> /// <param name="filePath">Path to index file</param> /// <param name="indexKey">Index XTEA key</param> /// <param name="parentFile">Parent file</param> /// <returns></returns> public static List<IndexItem> ReadIndexFile(string filePath, byte[] indexKey, string parentFile) { byte[] plainData = NormalizeIndexFile(filePath, indexKey); if (plainData == null) return null; var rtnList = new List<IndexItem>(); rtnList.Clear(); //Remove header var dataBuffer = new byte[plainData.Length - 12]; Array.Copy(plainData, 12, dataBuffer, 0, plainData.Length - 12); //Convert byte[] to int int fileCount = IOHelper.ReadIntFromArray(plainData, 8, 4); int indexVersion = IOHelper.ReadIntFromArray(plainData, 4, 4); if (indexVersion != 2) { //WindowLog.LogOutputMessage(Log.LogId.ETER_INDEX_WRONG_IDX_VERSION_LOG, args: fileCount); TODO return null; } //Holding variables var Index = new byte[4]; var FileName = new byte[161]; var FilenameCRC = new byte[4]; var DiskSize = new byte[4]; var DataSize = new byte[4]; var CRC = new byte[4]; var FileOffset = new byte[4]; var PackedType = new byte[1]; //Loop through files for (int i = 0; i < fileCount; i++) { Array.Copy(dataBuffer, 0 + (192 * i), Index, 0, 4); Array.Copy(dataBuffer, 4 + (192 * i), FileName, 0, 161); Array.Copy(dataBuffer, 168 + (192 * i), FilenameCRC, 0, 4); Array.Copy(dataBuffer, 172 + (192 * i), DiskSize, 0, 4); Array.Copy(dataBuffer, 176 + (192 * i), DataSize, 0, 4); Array.Copy(dataBuffer, 180 + (192 * i), CRC, 0, 4); Array.Copy(dataBuffer, 184 + (192 * i), FileOffset, 0, 4); Array.Copy(dataBuffer, 188 + (192 * i), PackedType, 0, 1); string tempFileName = Encoding.Default.GetString(FileName).Replace("\0", ""); string fileName = tempFileName.Contains("type\"") ? tempFileName.Substring(0, tempFileName.IndexOf("type\"", StringComparison.Ordinal) - 1) : tempFileName; // Fail-safe to make sure the path is valid if (!CrcHelper.GetCrc32HashFromMemoryToByteArray(Encoding.Default.GetBytes(fileName)).SequenceEqual(FilenameCRC)) { for (int j = 1; j < fileName.Length; j++) { var newFileName = fileName.Substring(0, j); if ( CrcHelper.GetCrc32HashFromMemoryToByteArray(Encoding.Default.GetBytes(newFileName)).Reverse().ToArray() .SequenceEqual(FilenameCRC)) { fileName = newFileName; break; } } } // New drive point? //DPHelper.CheckIfContainsDrivePoint(fileName); TODO rtnList.Add(new IndexItem(BitConverter.ToInt32(Index, 0), fileName, System.Text.RegularExpressions.Regex.Replace(BitConverter.ToString(FilenameCRC), "-", ""), BitConverter.ToInt32(DiskSize, 0), BitConverter.ToInt32(DataSize, 0), BitConverter.ToInt32(CRC, 0).ToString("X"), BitConverter.ToInt32(FileOffset, 0), Convert.ToInt32(PackedType[0]), parentFile)); } return rtnList; }
/// <summary> /// Buils EIX and EPK files /// </summary> /// <param name="list">Deserialized list</param> /// <param name="packFilePath">Path to EPK file, including the name</param> /// <param name="unpackedFilesPath">Path to unpacked files</param> /// <param name="indexKey">Index XTEA key</param> /// <param name="packKey">Pack XTEA key</param> /// <param name="errorLogCallBack"></param> /// <param name="progressCallback">Callback if progress updates are needed</param> /// <returns></returns> public static bool BuildIndexAndPackFiles( List<IndexItem> list, string packFilePath, string unpackedFilesPath, byte[] indexKey, byte[] packKey, Action<ErrorItem> errorLogCallBack, Action<int, int> progressCallback, Action fatalErrorCallback) { using (var fStream = new MemoryStream()) { packFilePath = packFilePath.Replace("\\", "/"); // Check if directory exists string directoryPath = packFilePath.Substring(0, packFilePath.LastIndexOf("/")); Directory.CreateDirectory(directoryPath); // Create stream to EPK file var epkStream = new FileStream(EterHelper.ReplaceWithEpkExt(packFilePath), FileMode.Create); // Size from header for each file int decompressedSize = 0; int compressedSize = 0; uint encryptedSize = 0; // File counter to index files int indexCount = 0; // Progress variables double actionProgress = 0; // FileOffset holder (EPK stream's length) int fileOffset = 0; // Write first header to EIX file fStream.Write(ConstantsBase.EterFourCc, 0, ConstantsBase.EterFourCc.Length); fStream.Write(BitConverter.GetBytes(2), 0, 4); fStream.Write(BitConverter.GetBytes(list.Count), 0, 4); try { foreach (IndexItem item in list) { // Loop through items var fileName = new byte[161]; var fileNameCrc = new byte[4]; //Index item's structure (totalizing 192 bytes) #region Byte Holders var fileIndex = new byte[4]; var realDataSize = new byte[4]; var dataSize = new byte[4]; var dataCrc = new byte[4]; var dataOffset = new byte[4]; var padding3B = new byte[3]; #endregion // Set all backslashs to forwards slashes item.Filename = item.Filename.Replace('\\', '/'); // Get raw data byte[] rawData = IOHelper.ReadFile(unpackedFilesPath + item.Filename); // Header sizees int encryptedFileSize = 0; int compressedFileSize = 0; int decompressedFileSize = 0; // Set real data & decompressed size to raw data's lenth realDataSize = BitConverter.GetBytes(rawData.Length); decompressedFileSize = rawData.Length; // Set fileoffset to actual stream's length fileOffset = (int)epkStream.Length; #region File Type Processing // Switch through the 3 possible cases switch (item.PackType) { case 0: // Write data to EPK stream epkStream.Write(rawData, 0, rawData.Length); // Set data size equal to raw data since no compression nor encrypted occured dataSize = BitConverter.GetBytes(rawData.Length); break; case 1: case 2: // Compress data byte[] compressedDataBuffer = LzoHelper.CompressData(rawData.Length, rawData); // Create buffer to hold header + compressedData byte[] compressedDataWithHeaderBuffer = new byte[compressedDataBuffer.Length + 4]; // Copy header and compressedData to previously created buffer Array.Copy(ConstantsBase.LzoFourCc, 0, compressedDataWithHeaderBuffer, 0, 4); Array.Copy(compressedDataBuffer, 0, compressedDataWithHeaderBuffer, 4, compressedDataBuffer.Length); // Set dataSize to compressedSize (since it assumes it's type 1) dataSize = BitConverter.GetBytes(compressedDataWithHeaderBuffer.Length + 16); // Set compressedSize compressedFileSize = compressedDataBuffer.Length; // If type 2 if (item.PackType == 2) { // Get encrypted size (ALWAYS the upper multiple) encryptedFileSize = GetUpperMultiple(compressedDataWithHeaderBuffer.Length); // Resize data to fit encryptedSize Array.Resize(ref compressedDataWithHeaderBuffer, encryptedFileSize); // Encrypt Data Xtea.Encrypt2(ref compressedDataWithHeaderBuffer, packKey); // Set dataSize to encryptedData + header dataSize = BitConverter.GetBytes(compressedDataWithHeaderBuffer.Length + 16); } // Write header of file to EPK stream epkStream.Write(ConstantsBase.LzoFourCc, 0, 4); epkStream.Write(BitConverter.GetBytes(encryptedFileSize), 0, 4); epkStream.Write(BitConverter.GetBytes(compressedFileSize), 0, 4); epkStream.Write(BitConverter.GetBytes(decompressedFileSize), 0, 4); // Write actual data epkStream.Write(compressedDataWithHeaderBuffer, 0, compressedDataWithHeaderBuffer.Length); break; } #endregion #region Building index file // Check if string replacment is needed string virtualPathFile = DrivePointManager.InsertDrivePoints(item.Filename); // Populate byte[] with data fileIndex = BitConverter.GetBytes(item.Index); byte[] fileNameTemp = Encoding.Default.GetBytes(virtualPathFile); fileNameCrc = CrcHelper.GetCrc32HashFromMemoryToByteArray(Encoding.Default.GetBytes(virtualPathFile)); realDataSize = (realDataSize == null) ? BitConverter.GetBytes(item.DiskSize) : realDataSize; dataSize = (dataSize == null) ? BitConverter.GetBytes(item.Size) : dataSize; dataCrc = CrcHelper.GetCrc32HashToByteArray(unpackedFilesPath + item.Filename); dataOffset = BitConverter.GetBytes(fileOffset); var compressedType = (byte)item.PackType; // Check if filename buffer is expectedSize if (fileNameTemp.Length != 161) { Array.Copy(fileNameTemp, 0, fileName, 0, fileNameTemp.Length); } // Write data to EIX's stream fStream.Write(fileIndex, 0, fileIndex.Length); fStream.Write(fileName, 0, 161); fStream.Write(padding3B, 0, padding3B.Length); fStream.Write(fileNameCrc.Reverse().ToArray(), 0, fileNameCrc.Length); fStream.Write(realDataSize, 0, realDataSize.Length); fStream.Write(dataSize, 0, dataSize.Length); fStream.Write(dataCrc.Reverse().ToArray(), 0, dataCrc.Length); fStream.Write(dataOffset, 0, dataOffset.Length); fStream.WriteByte(compressedType); fStream.Write(padding3B, 0, padding3B.Length); indexCount++; #endregion // Update progress actionProgress = (indexCount / (double)list.Count * 100.0); progressCallback(0, (int)actionProgress); } } catch (Exception ex) { //WindowLog.LogExceptioToFile(ex.ToString()); TODO fatalErrorCallback(); throw; } // Assign current stream's lenght to decmopressedSize decompressedSize = (int)fStream.Length; // Buffer to hold compressedData byte[] compressedData = LzoHelper.CompressData(decompressedSize, fStream.ToArray()); // Buffer with compressedData + MCOZ header byte[] compressedDataWithHeader = new byte[compressedData.Length + 4]; // Copy Header to buffer Array.Copy(ConstantsBase.LzoFourCc, 0, compressedDataWithHeader, 0, 4); // Copy data to buffer Array.Copy(compressedData, 0, compressedDataWithHeader, 4, compressedData.Length); // Save compressedSize compressedSize = compressedData.Length; // Save encryptedSize (round to upper multiple) encryptedSize = (uint)GetUpperMultiple(compressedSize + 4); // Resize array to fit new size Array.Resize(ref compressedDataWithHeader, (int)encryptedSize); // Encrypt data Xtea.Encrypt2(ref compressedDataWithHeader, indexKey); // Create buffer to hold final data + header var outputFileBuffer = new byte[compressedDataWithHeader.Length + 16]; // Copy header to buffer Array.Copy(ConstantsBase.LzoFourCc, 0, outputFileBuffer, 0, 4); Array.Copy(BitConverter.GetBytes(encryptedSize), 0, outputFileBuffer, 4, 4); Array.Copy(BitConverter.GetBytes(compressedSize), 0, outputFileBuffer, 8, 4); Array.Copy(BitConverter.GetBytes(decompressedSize), 0, outputFileBuffer, 12, 4); // Copy data to buffer Array.Copy(compressedDataWithHeader, 0, outputFileBuffer, 16, compressedDataWithHeader.Length); // Close stream epkStream.Close(); epkStream.Dispose(); // Save file File.WriteAllBytes(EterHelper.ReplaceWithEixExt(packFilePath), outputFileBuffer); return true; } }