#if !Rar2017_64bit using nint = System.Int32; using nuint = System.UInt32; using size_t = System.UInt32; #else using nint = System.Int64; using nuint = System.UInt64; using size_t = System.UInt64; #endif using int64 = System.Int64; using System.Collections.Generic; using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal; // TODO: REMOVE THIS... WIP #pragma warning disable 169 #pragma warning disable 414 namespace SharpCompress.Compressors.Rar.UnpackV2017 { internal static class UnpackGlobal { // Maximum allowed number of compressed bits processed in quick mode. public const int MAX_QUICK_DECODE_BITS =10; // Maximum number of filters per entire data block. Must be at least // twice more than MAX_PACK_FILTERS to store filters from two data blocks. public const int MAX_UNPACK_FILTERS =8192; // Maximum number of filters per entire data block for RAR3 unpack. // Must be at least twice more than v3_MAX_PACK_FILTERS to store filters // from two data blocks. public const int MAX3_UNPACK_FILTERS =8192; // Limit maximum number of channels in RAR3 delta filter to some reasonable // value to prevent too slow processing of corrupt archives with invalid // channels number. Must be equal or larger than v3_MAX_FILTER_CHANNELS. // No need to provide it for RAR5, which uses only 5 bits to store channels. private const int MAX3_UNPACK_CHANNELS =1024; // Maximum size of single filter block. We restrict it to limit memory // allocation. Must be equal or larger than MAX_ANALYZE_SIZE. public const int MAX_FILTER_BLOCK_SIZE =0x400000; // Write data in 4 MB or smaller blocks. Must not exceed PACK_MAX_WRITE, // so we keep number of buffered filter in unpacker reasonable. public const int UNPACK_MAX_WRITE =0x400000; } // Decode compressed bit fields to alphabet numbers. internal sealed class DecodeTable { // Real size of DecodeNum table. public uint MaxNum; // Left aligned start and upper limit codes defining code space // ranges for bit lengths. DecodeLen[BitLength-1] defines the start of // range for bit length and DecodeLen[BitLength] defines next code // after the end of range or in other words the upper limit code // for specified bit length. public readonly uint[] DecodeLen = new uint[16]; // Every item of this array contains the sum of all preceding items. // So it contains the start position in code list for every bit length. public readonly uint[] DecodePos = new uint[16]; // Number of compressed bits processed in quick mode. // Must not exceed MAX_QUICK_DECODE_BITS. public uint QuickBits; // Translates compressed bits (up to QuickBits length) // to bit length in quick mode. public readonly byte[] QuickLen = new byte[1< Filters = new List(); private readonly uint[] OldDist = new uint[4]; private uint OldDistPtr; private uint LastLength; // LastDist is necessary only for RAR2 and older with circular OldDist // array. In RAR3 last distance is always stored in OldDist[0]. private uint LastDist; private size_t UnpPtr,WrPtr; // Top border of read packed data. private int ReadTop; // Border to call UnpReadBuf. We use it instead of (ReadTop-C) // for optimization reasons. Ensures that we have C bytes in buffer // unless we are at the end of file. private int ReadBorder; private UnpackBlockHeader BlockHeader; private UnpackBlockTables BlockTables; private size_t WriteBorder; private byte[] Window; private readonly FragmentedWindow FragWindow = new FragmentedWindow(); private bool Fragmented; private int64 DestUnpSize; //bool Suspended; private bool UnpAllBuf; private bool UnpSomeRead; private int64 WrittenFileSize; private bool FileExtracted; /***************************** Unpack v 1.5 *********************************/ //void Unpack15(bool Solid); //void ShortLZ(); //void LongLZ(); //void HuffDecode(); //void GetFlagsBuf(); //void UnpInitData15(int Solid); //void InitHuff(); //void CorrHuff(ushort *CharSet,byte *NumToPlace); //void CopyString15(uint Distance,uint Length); //uint DecodeNum(uint Num,uint StartPos,uint *DecTab,uint *PosTab); private readonly ushort[] ChSet = new ushort[256],ChSetA = new ushort[256],ChSetB = new ushort[256],ChSetC = new ushort[256]; private readonly byte[] NToPl = new byte[256],NToPlB = new byte[256],NToPlC = new byte[256]; private uint FlagBuf,AvrPlc,AvrPlcB,AvrLn1,AvrLn2,AvrLn3; private int Buf60,NumHuf,StMode,LCount,FlagsCnt; private uint Nhfb,Nlzb,MaxDist3; /***************************** Unpack v 1.5 *********************************/ /***************************** Unpack v 2.0 *********************************/ //void Unpack20(bool Solid); private DecodeTable[] MD = new DecodeTable[4]; // Decode multimedia data, up to 4 channels. private readonly byte[] UnpOldTable20 = new byte[MC20*4]; private bool UnpAudioBlock; private uint UnpChannels,UnpCurChannel; private int UnpChannelDelta; //void CopyString20(uint Length,uint Distance); //bool ReadTables20(); //void UnpWriteBuf20(); //void UnpInitData20(int Solid); //void ReadLastTables(); //byte DecodeAudio(int Delta); private AudioVariables[] AudV = new AudioVariables[4]; /***************************** Unpack v 2.0 *********************************/ /***************************** Unpack v 3.0 *********************************/ public const int BLOCK_LZ = 0; public const int BLOCK_PPM = 1; //void UnpInitData30(bool Solid); //void Unpack29(bool Solid); //void InitFilters30(bool Solid); //bool ReadEndOfBlock(); //bool ReadVMCode(); //bool ReadVMCodePPM(); //bool AddVMCode(uint FirstByte,byte *Code,int CodeSize); //int SafePPMDecodeChar(); //bool ReadTables30(); //bool UnpReadBuf30(); //void UnpWriteBuf30(); //void ExecuteCode(VM_PreparedProgram *Prg); private int PrevLowDist,LowDistRepCount; /*#if !RarV2017_RAR5ONLY ModelPPM PPM; #endif*/ private int PPMEscChar; private readonly byte [] UnpOldTable = new byte[HUFF_TABLE_SIZE30]; private int UnpBlockType; // If we already read decoding tables for Unpack v2,v3,v5. // We should not use a single variable for all algorithm versions, // because we can have a corrupt archive with one algorithm file // followed by another algorithm file with "solid" flag and we do not // want to reuse tables from one algorithm in another. private bool TablesRead2,TablesRead3,TablesRead5; // Virtual machine to execute filters code. /*#if !RarV2017_RAR5ONLY RarVM VM; #endif*/ // Buffer to read VM filters code. We moved it here from AddVMCode // function to reduce time spent in BitInput constructor. private readonly BitInput VMCodeInp = new BitInput(true); // Filters code, one entry per filter. private readonly List Filters30 = new List(); // Filters stack, several entrances of same filter are possible. private readonly List PrgStack = new List(); // Lengths of preceding data blocks, one length of one last block // for every filter. Used to reduce the size required to write // the data block length if lengths are repeating. private readonly List OldFilterLengths = new List(); private int LastFilter; /***************************** Unpack v 3.0 *********************************/ //Unpack(ComprDataIO *DataIO); //~Unpack(); //void Init(size_t WinSize,bool Solid); //void DoUnpack(uint Method,bool Solid); private bool IsFileExtracted() {return(FileExtracted);} private void SetDestSize(int64 DestSize) {DestUnpSize=DestSize;FileExtracted=false;} private void SetSuspended(bool Suspended) {this.Suspended=Suspended;} #if RarV2017_RAR_SMP // More than 8 threads are unlikely to provide a noticeable gain // for unpacking, but would use the additional memory. void SetThreads(uint Threads) {MaxUserThreads=Min(Threads,8);} void UnpackDecode(UnpackThreadData &D); #endif private size_t MaxWinSize; private size_t MaxWinMask; private uint GetChar() { if (Inp.InAddr>MAX_SIZE-30) UnpReadBuf(); return(Inp.InBuf[Inp.InAddr++]); } } }