📄 unpack.cpp
字号:
#include "rar.hpp"#include "coder.cpp"#include "suballoc.cpp"#include "model.cpp"#ifndef SFX_MODULE#include "unpack15.cpp"// Igor Pavlov
// #include "unpack20.cpp"#endifUnpack::Unpack(ComprDataIO *DataIO){ UnpIO=DataIO; Window=NULL; ExternalWindow=false; Suspended=false; UnpAllBuf=false; UnpSomeRead=false;}Unpack::~Unpack(){ if (Window!=NULL && !ExternalWindow) delete[] Window; InitFilters();}void Unpack::Init(byte *Window){ if (Window==NULL) { Unpack::Window=new byte[MAXWINSIZE];#ifndef ALLOW_EXCEPTIONS if (Unpack::Window==NULL) ErrHandler.MemoryError();#endif } else { Unpack::Window=Window; ExternalWindow=true; } UnpInitData(false);}void Unpack::DoUnpack(int Method,bool Solid){ switch(Method) {#ifndef SFX_MODULE case 15: Unpack15(Solid); break; // Igor Pavlov
/*
case 20: case 26: Unpack20(Solid); break; */
#endif case 29: Unpack29(Solid); break; }}inline void Unpack::InsertOldDist(unsigned int Distance){ OldDist[3]=OldDist[2]; OldDist[2]=OldDist[1]; OldDist[1]=OldDist[0]; OldDist[0]=Distance;}inline void Unpack::InsertLastMatch(unsigned int Length,unsigned int Distance){ LastDist=Distance; LastLength=Length;}void Unpack::CopyString(unsigned int Length,unsigned int Distance){ unsigned int DestPtr=UnpPtr-Distance; if (DestPtr<MAXWINSIZE-260 && UnpPtr<MAXWINSIZE-260) { Window[UnpPtr++]=Window[DestPtr++]; while (--Length>0) Window[UnpPtr++]=Window[DestPtr++]; } else while (Length--) { Window[UnpPtr]=Window[DestPtr++ & MAXWINMASK]; UnpPtr=(UnpPtr+1) & MAXWINMASK; }}int Unpack::DecodeNumber(struct Decode *Dec){ unsigned int Bits; unsigned int BitField=getbits() & 0xfffe; if (BitField<Dec->DecodeLen[8]) if (BitField<Dec->DecodeLen[4]) if (BitField<Dec->DecodeLen[2]) if (BitField<Dec->DecodeLen[1]) Bits=1; else Bits=2; else if (BitField<Dec->DecodeLen[3]) Bits=3; else Bits=4; else if (BitField<Dec->DecodeLen[6]) if (BitField<Dec->DecodeLen[5]) Bits=5; else Bits=6; else if (BitField<Dec->DecodeLen[7]) Bits=7; else Bits=8; else if (BitField<Dec->DecodeLen[12]) if (BitField<Dec->DecodeLen[10]) if (BitField<Dec->DecodeLen[9]) Bits=9; else Bits=10; else if (BitField<Dec->DecodeLen[11]) Bits=11; else Bits=12; else if (BitField<Dec->DecodeLen[14]) if (BitField<Dec->DecodeLen[13]) Bits=13; else Bits=14; else Bits=15; addbits(Bits); unsigned int N=Dec->DecodePos[Bits]+((BitField-Dec->DecodeLen[Bits-1])>>(16-Bits)); if (N>=Dec->MaxNum) N=0; return(Dec->DecodeNum[N]);}void Unpack::Unpack29(bool Solid){ static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224}; static unsigned char LBits[]= {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5}; static int DDecode[DC]; static byte DBits[DC]; static int DBitLengthCounts[]= {4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,14,0,12}; static unsigned char SDDecode[]={0,4,8,16,32,64,128,192}; static unsigned char SDBits[]= {2,2,3, 4, 5, 6, 6, 6}; unsigned int Bits; if (DDecode[1]==0) { int Dist=0,BitLength=0,Slot=0; for (int I=0;I<sizeof(DBitLengthCounts)/sizeof(DBitLengthCounts[0]);I++,BitLength++) for (int J=0;J<DBitLengthCounts[I];J++,Slot++,Dist+=(1<<BitLength)) { DDecode[Slot]=Dist; DBits[Slot]=BitLength; } } FileExtracted=true; if (!Suspended) { UnpInitData(Solid); if (!UnpReadBuf()) return; if ((!Solid || !TablesRead) && !ReadTables()) return; } if (PPMError) return; while (true) { UnpPtr&=MAXWINMASK; if (InAddr>ReadBorder) { if (!UnpReadBuf()) break; } if (((WrPtr-UnpPtr) & MAXWINMASK)<260 && WrPtr!=UnpPtr) { UnpWriteBuf(); if (WrittenFileSize>DestUnpSize) return; if (Suspended) { FileExtracted=false; return; } } if (UnpBlockType==BLOCK_PPM) { int Ch=PPM.DecodeChar(); if (Ch==-1) { PPMError=true; break; } if (Ch==PPMEscChar) { int NextCh=PPM.DecodeChar(); if (NextCh==0) { if (!ReadTables()) break; continue; } if (NextCh==2 || NextCh==-1) break; if (NextCh==3) { if (!ReadVMCodePPM()) break; continue; } if (NextCh==4) { unsigned int Distance=0,Length; bool Failed=false; for (int I=0;I<4 && !Failed;I++) { int Ch=PPM.DecodeChar(); if (Ch==-1) Failed=true; else if (I==3) Length=(byte)Ch; else Distance=(Distance<<8)+(byte)Ch; } if (Failed) break; CopyString(Length+32,Distance+2); continue; } if (NextCh==5) { int Length=PPM.DecodeChar(); if (Length==-1) break; CopyString(Length+4,1); continue; } } Window[UnpPtr++]=Ch; continue; } int Number=DecodeNumber((struct Decode *)&LD); if (Number<256) { Window[UnpPtr++]=(byte)Number; continue; } if (Number>=271) { int Length=LDecode[Number-=271]+3; if ((Bits=LBits[Number])>0) { Length+=getbits()>>(16-Bits); addbits(Bits); } int DistNumber=DecodeNumber((struct Decode *)&DD); unsigned int Distance=DDecode[DistNumber]+1; if ((Bits=DBits[DistNumber])>0) { if (DistNumber>9) { if (Bits>4) { Distance+=((getbits()>>(20-Bits))<<4); addbits(Bits-4); } if (LowDistRepCount>0) { LowDistRepCount--; Distance+=PrevLowDist; } else { int LowDist=DecodeNumber((struct Decode *)&LDD); if (LowDist==16) { LowDistRepCount=LOW_DIST_REP_COUNT-1; Distance+=PrevLowDist; } else { Distance+=LowDist; PrevLowDist=LowDist; } } } else { Distance+=getbits()>>(16-Bits); addbits(Bits); } } if (Distance>=0x2000) { Length++; if (Distance>=0x40000L) Length++; } InsertOldDist(Distance); InsertLastMatch(Length,Distance); CopyString(Length,Distance); continue; } if (Number==256) { if (!ReadEndOfBlock()) break; continue; } if (Number==257) { if (!ReadVMCode()) break; continue; } if (Number==258) { if (LastLength!=0) CopyString(LastLength,LastDist); continue; } if (Number<263) { int DistNum=Number-259; unsigned int Distance=OldDist[DistNum]; for (int I=DistNum;I>0;I--) OldDist[I]=OldDist[I-1]; OldDist[0]=Distance; int LengthNumber=DecodeNumber((struct Decode *)&RD); int Length=LDecode[LengthNumber]+2; if ((Bits=LBits[LengthNumber])>0) { Length+=getbits()>>(16-Bits); addbits(Bits); } InsertLastMatch(Length,Distance); CopyString(Length,Distance); continue; } if (Number<272) { unsigned int Distance=SDDecode[Number-=263]+1; if ((Bits=SDBits[Number])>0) { Distance+=getbits()>>(16-Bits); addbits(Bits); } InsertOldDist(Distance); InsertLastMatch(2,Distance); CopyString(2,Distance); continue; } } UnpWriteBuf();}bool Unpack::ReadEndOfBlock(){ unsigned int BitField=getbits(); bool NewTable,NewFile=false; if (BitField & 0x8000) { NewTable=true; addbits(1); } else { NewFile=true;
// Igor Pavlov
NewTable = ((BitField & 0x4000) != 0);
addbits(2); } TablesRead=!NewTable; return !(NewFile || NewTable && !ReadTables());}bool Unpack::ReadVMCode(){ unsigned int FirstByte=getbits()>>8; addbits(8); int Length=(FirstByte & 7)+1; if (Length==7) { Length=(getbits()>>8)+7; addbits(8); } else if (Length==8) { Length=getbits(); addbits(16); } Array<byte> VMCode(Length); for (int I=0;I<Length;I++) { if (InAddr>=ReadTop-1 && !UnpReadBuf() && I<Length-1) return(false); VMCode[I]=getbits()>>8; addbits(8); } return(AddVMCode(FirstByte,&VMCode[0],Length));}bool Unpack::ReadVMCodePPM(){ unsigned int FirstByte=PPM.DecodeChar(); if ((int)FirstByte==-1) return(false); int Length=(FirstByte & 7)+1; if (Length==7) { int B1=PPM.DecodeChar(); if (B1==-1) return(false); Length=B1+7; } else if (Length==8) { int B1=PPM.DecodeChar(); if (B1==-1) return(false); int B2=PPM.DecodeChar(); if (B2==-1) return(false); Length=B1*256+B2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -