Beispiel #1
0
        /// <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();
                }
            }
        }
Beispiel #2
0
 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));
 }
Beispiel #3
0
        /// <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);
        }
Beispiel #4
0
        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);
            }
        }
Beispiel #5
0
 public bool SetString(CMFEntry entry, string data, Encoding encoding)
 {
     return(this.SetEntryData(entry, encoding.GetBytes(data), -1));
 }
Beispiel #6
0
 public bool SetString(CMFEntry entry, string data)
 {
     return(this.SetString(entry, data, Encoding.UTF8));
 }
Beispiel #7
0
 public bool SetData(CMFEntry entry, byte[] data)
 {
     return(this.SetEntryData(entry, data, data.LongLength));
 }
Beispiel #8
0
        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));
        }