/// <summary> /// Decompress the entry to a stream. /// </summary> /// <param name="entry">The entry which will be decompressed</param> /// <param name="outStream">The output stream</param> public void ExtractEntry(CMFEntry entry, Stream outStream) { if (this._disposed) { throw new System.ObjectDisposedException("Archive"); } if (!outStream.CanWrite) { throw new InvalidOperationException("The stream should be writable."); } long entrydataoffset = entry.dataoffset + this.dataoffsetStart; this.BaseStream.Seek(entrydataoffset, SeekOrigin.Begin); if (!CmfFormat.IsEncryptedFile(entry.FileName) && entry.IsCompressed) { using (Stream srcStream = new ZlibStream(new EntryStream(this.BaseStream, entrydataoffset, entry.CompressedSize, true), System.IO.Compression.CompressionMode.Decompress, false)) { srcStream.CopyTo(outStream); outStream.Flush(); } } else { // Let's extract encrypted content as raw data, too. // Because I don't know how to decrypt. using (Stream srcStream = new EntryStream(this.BaseStream, entrydataoffset, entry.UnpackedSize, true)) { srcStream.CopyTo(outStream); outStream.Flush(); } } }
public bool SetDataSource(CMFEntry entry, Stream data, long length) { if (!data.CanRead) { throw new InvalidOperationException("The data's stream should be readable."); } return(this.SetEntryData(entry, data, length)); }
/// <summary> /// Decompress the entry to a destination path. /// </summary> /// <param name="entry">The entry which will be decompressed</param> /// <param name="filepath">Destination of the file</param> public void ExtractEntry(CMFEntry entry, string filepath) { if (this._disposed) { throw new System.ObjectDisposedException("Archive"); } using (FileStream fs = File.Create(filepath)) this.ExtractEntry(entry, fs); }
private bool SetEntryData(CMFEntry entry, object data, long length) { if (this._disposed) { throw new System.ObjectDisposedException("Editor"); } if (this._issaving) { throw new InvalidOperationException("The Editor is writing data. Adding more data is not possible."); // Although it is possible. But I'm lazy. } if (entry == null || this.myArchive.Entries.IndexOf(entry) == -1) { return(false); } else { if (length == -1) { if (data is Stream stream) { FileStream fs = SpawnTempFile(); if (!CmfFormat.IsEncryptedFile(entry.FileName) && entry.IsCompressed) { using (ZlibStream zlibstream = new ZlibStream(fs, System.IO.Compression.CompressionMode.Compress, this.CompressionLevel, true, Encoding.UTF8)) CopyStream(stream, zlibstream, ref this.myultimatebuffer); } else { CopyStream(stream, fs, ref this.myultimatebuffer); } if (fs.Length > entry.CompressedSize) { fs.Dispose(); throw new InvalidDataException($"The new data of '{entry.FileName}' size is bigger than the original one."); } else { if (this.datadictionary.ContainsKey(entry)) { this.datadictionary[entry].Dispose(); } this.datadictionary[entry] = fs; fs.Flush(); } } else if (data is byte[] dataArray) { if (!CmfFormat.IsEncryptedFile(entry.FileName) && entry.IsCompressed) { FileStream fs = SpawnTempFile(); using (ZlibStream zlibstream = new ZlibStream(fs, System.IO.Compression.CompressionMode.Compress, this.CompressionLevel, true, Encoding.UTF8)) zlibstream.Write(dataArray, 0, dataArray.Length); if (fs.Length > entry.CompressedSize) { fs.Dispose(); throw new InvalidDataException($"The new data of '{entry.FileName}' size is bigger than the original one."); } else { if (this.datadictionary.ContainsKey(entry)) { this.datadictionary[entry].Dispose(); } this.datadictionary[entry] = fs; fs.Flush(); } } else { if (dataArray.Length > entry.CompressedSize) { throw new InvalidDataException($"The new data of '{entry.FileName}' size is bigger than the original one."); } else { FileStream fs = SpawnTempFile(); fs.Write(dataArray, 0, dataArray.Length); if (this.datadictionary.ContainsKey(entry)) { this.datadictionary[entry].Dispose(); } this.datadictionary[entry] = fs; fs.Flush(); } } } } else { if (data is Stream stream) { FileStream fs = SpawnTempFile(); if (length > 0) { if (!CmfFormat.IsEncryptedFile(entry.FileName) && entry.IsCompressed) { using (ZlibStream zlibstream = new ZlibStream(fs, System.IO.Compression.CompressionMode.Compress, this.CompressionLevel, true, Encoding.UTF8)) CopyStream(stream, zlibstream, ref this.myultimatebuffer, length); } else { CopyStream(stream, fs, ref this.myultimatebuffer, length); } } if (fs.Length > entry.CompressedSize) { fs.Dispose(); throw new InvalidDataException($"The new data of '{entry.FileName}' size is bigger than the original one."); } else { if (this.datadictionary.ContainsKey(entry)) { this.datadictionary[entry].Dispose(); } this.datadictionary[entry] = fs; fs.Flush(); } } else if (data is byte[] dataArray) { if (!CmfFormat.IsEncryptedFile(entry.FileName) && entry.IsCompressed) { FileStream fs = SpawnTempFile(); using (ZlibStream zlibstream = new ZlibStream(fs, System.IO.Compression.CompressionMode.Compress, this.CompressionLevel, true, Encoding.UTF8)) zlibstream.Write(dataArray, 0, dataArray.Length); if (fs.Length > entry.CompressedSize) { fs.Dispose(); throw new InvalidDataException($"The new data of '{entry.FileName}' size is bigger than the original one."); } else { if (this.datadictionary.ContainsKey(entry)) { this.datadictionary[entry].Dispose(); } this.datadictionary[entry] = fs; fs.Flush(); } } else { if (dataArray.Length > entry.CompressedSize) { throw new InvalidDataException($"The new data of '{entry.FileName}' size is bigger than the original one."); } else { FileStream fs = SpawnTempFile(); fs.Write(dataArray, 0, dataArray.Length); if (this.datadictionary.ContainsKey(entry)) { this.datadictionary[entry].Dispose(); } this.datadictionary[entry] = fs; fs.Flush(); } } } } return(true); } }
public bool SetString(CMFEntry entry, string data, Encoding encoding) { return(this.SetEntryData(entry, encoding.GetBytes(data), -1)); }
public bool SetString(CMFEntry entry, string data) { return(this.SetString(entry, data, Encoding.UTF8)); }
public bool SetData(CMFEntry entry, byte[] data) { return(this.SetEntryData(entry, data, data.LongLength)); }
private ReadOnlyCollection <CMFEntry> ReadEntryList() { this.BaseStream.Seek(this.headeroffsetStart, SeekOrigin.Begin); /* * File table has fixed row size 528 bytes. * string(512):Filename - int(4):FileSize - int(4):CompressedFileSize - int(4):FileOffset - int(4):Flag */ // CmfFormat.FileHeaderSize CMFEntry[] entryList = new CMFEntry[this.filecount]; string tmp_filename; byte[] bytebuffer = new byte[CmfFormat.FileHeaderSize]; int readcount, indexofNull; int offset = (int)this.BaseStream.Position; CMFEntry currentCMFEntry; for (int i = 0; i < entryList.Length; i++) { tmp_filename = null; currentCMFEntry = new CMFEntry(); readcount = this.binaryReader.Read(bytebuffer, 0, bytebuffer.Length); if (readcount == bytebuffer.Length) { currentCMFEntry.headeroffset = offset; // Decode the buffer. CmfHelper.Decode(ref bytebuffer); // First 512 bytes is the filename tmp_filename = Encoding.ASCII.GetString(bytebuffer, 0, CmfFormat.FileHeaderNameSize); // This doesn't look good. indexofNull = tmp_filename.IndexOf("\0\0"); if (tmp_filename.IndexOf("\0\0") == -1) { indexofNull = tmp_filename.LastIndexOf('\0'); tmp_filename = Encoding.ASCII.GetString(bytebuffer, 0, indexofNull); } else { currentCMFEntry._filename = Encoding.Unicode.GetString(bytebuffer, 0, indexofNull + 1); } currentCMFEntry._filename = currentCMFEntry._filename.RemoveNullChar(); // Next is 4 bytes for the unpacked size (aka original file) currentCMFEntry._unpackedsize = BitConverter.ToInt32(bytebuffer, 512); // Next is another 4 bytes for compressedsize currentCMFEntry._compressedsize = BitConverter.ToInt32(bytebuffer, 516); // Next is another 4 bytes for "DataOffset" currentCMFEntry.dataoffset = BitConverter.ToInt32(bytebuffer, 520); // if (str == "FX" || str == "LUA" || str == "TET" || str == "XET") // Last is the flag, determine if the file is compressed (with Zlib) or encrypted or nothing special. switch (BitConverter.ToInt32(bytebuffer, 524)) { case 1: currentCMFEntry._iscompressed = true; break; case 2: currentCMFEntry._isencrypted = true; break; } entryList[i] = currentCMFEntry; } offset += readcount; } return(new ReadOnlyCollection <CMFEntry>(entryList)); }