#ifndef _RAR_UNPACK_ #define _RAR_UNPACK_ // Maximum allowed number of compressed bits processed in quick mode. #define 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. #define 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. #define 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. #define 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. #define 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. #define UNPACK_MAX_WRITE 0x400000 // Decode compressed bit fields to alphabet numbers. struct DecodeTable:PackDef { // Real size of DecodeNum table. 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. uint DecodeLen[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. uint DecodePos[16]; // Number of compressed bits processed in quick mode. // Must not exceed MAX_QUICK_DECODE_BITS. uint QuickBits; // Translates compressed bits (up to QuickBits length) // to bit length in quick mode. byte QuickLen[1< FilterSrcMemory; Array FilterDstMemory; // Filters code, one entry per filter. Array Filters; uint OldDist[4],OldDistPtr; uint LastLength; // LastDist is necessary only for RAR2 and older with circular OldDist // array. In RAR3 last distance is always stored in OldDist[0]. uint LastDist; size_t UnpPtr,WrPtr; // Top border of read packed data. 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. int ReadBorder; UnpackBlockHeader BlockHeader; UnpackBlockTables BlockTables; size_t WriteBorder; byte *Window; FragmentedWindow FragWindow; bool Fragmented; int64 DestUnpSize; bool Suspended; bool UnpAllBuf; bool UnpSomeRead; int64 WrittenFileSize; 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); ushort ChSet[256],ChSetA[256],ChSetB[256],ChSetC[256]; byte NToPl[256],NToPlB[256],NToPlC[256]; uint FlagBuf,AvrPlc,AvrPlcB,AvrLn1,AvrLn2,AvrLn3; int Buf60,NumHuf,StMode,LCount,FlagsCnt; uint Nhfb,Nlzb,MaxDist3; /***************************** Unpack v 1.5 *********************************/ /***************************** Unpack v 2.0 *********************************/ void Unpack20(bool Solid); DecodeTable MD[4]; // Decode multimedia data, up to 4 channels. unsigned char UnpOldTable20[MC20*4]; bool UnpAudioBlock; uint UnpChannels,UnpCurChannel; int UnpChannelDelta; void CopyString20(uint Length,uint Distance); bool ReadTables20(); void UnpWriteBuf20(); void UnpInitData20(int Solid); void ReadLastTables(); byte DecodeAudio(int Delta); struct AudioVariables AudV[4]; /***************************** Unpack v 2.0 *********************************/ /***************************** Unpack v 3.0 *********************************/ enum BLOCK_TYPES {BLOCK_LZ,BLOCK_PPM}; void UnpInitData30(bool Solid); void Unpack29(bool Solid); void InitFilters30(bool Solid); bool ReadEndOfBlock(); bool ReadVMCode(); bool ReadVMCodePPM(); bool AddVMCode(uint FirstByte,byte *Code,uint CodeSize); int SafePPMDecodeChar(); bool ReadTables30(); bool UnpReadBuf30(); void UnpWriteBuf30(); void ExecuteCode(VM_PreparedProgram *Prg); int PrevLowDist,LowDistRepCount; ModelPPM PPM; int PPMEscChar; byte UnpOldTable[HUFF_TABLE_SIZE30]; 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. bool TablesRead2,TablesRead3,TablesRead5; // Virtual machine to execute filters code. RarVM VM; // Buffer to read VM filters code. We moved it here from AddVMCode // function to reduce time spent in BitInput constructor. BitInput VMCodeInp; // Filters code, one entry per filter. Array Filters30; // Filters stack, several entrances of same filter are possible. Array PrgStack; // 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. Array OldFilterLengths; int LastFilter; /***************************** Unpack v 3.0 *********************************/ public: Unpack(ComprDataIO *DataIO); ~Unpack(); void Init(size_t WinSize,bool Solid); void DoUnpack(uint Method,bool Solid); bool IsFileExtracted() {return(FileExtracted);} void SetDestSize(int64 DestSize) {DestUnpSize=DestSize;FileExtracted=false;} void SetSuspended(bool Suspended) {Unpack::Suspended=Suspended;} #ifdef 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 size_t MaxWinSize; size_t MaxWinMask; uint GetChar() { if (Inp.InAddr>BitInput::MAX_SIZE-30) { UnpReadBuf(); if (Inp.InAddr>=BitInput::MAX_SIZE) // If nothing was read. return 0; } return Inp.InBuf[Inp.InAddr++]; } }; #endif