📄 rartool.cpp
字号:
#include "stdafx.h"
#include "RarTool.h"
bool CRarTool::Check( const char* fname, unsigned long fsize )
{
if( (arc=fopen(fname,"rb"))==NULL )
return false;
bool ans=IsArchive(true);
fclose(arc);
return ans;
}
bool CRarTool::Extract( const char* fname,const char* ddir )
{
// 曄悢弶婜壔
bool bFirstVol=true,bFirstFile=true;
char *DestName;
bNeedNextVol=false;
char PassWord[128]={0};
TCHAR t_DestName[MAX_PATH]; // by uema2.
strcpy(ArcName,fname);
// 奐偔
arc=fopen(fname,"rb");
if( arc==NULL )return false;
if( !IsArchive(false) ){fclose(arc);return false;}
fseek(arc,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
while( true )
{
int Size=ReadBlock(FILE_HEAD|READSUBBLOCK);
if( Size<=0 && !bNeedNextVol ) break;
if( BlockHead.HeadType==SUB_HEAD )
{fseek(arc,NextBlockPos,SEEK_SET);continue;}
// 儅儖僠儃儕儏乕儉張棟
if( (NewLhd.Flags&LHD_SPLIT_BEFORE) && bSolid && bFirstVol )break;
bFirstVol=false;
if( bNeedNextVol && Size==0 && !GetNextVolume() )break;
bNeedNextVol=(0!=(NewLhd.Flags&LHD_SPLIT_AFTER));
// 埑弅僨乕僞埵抲傊旘傇
fseek(arc,NextBlockPos-NewLhd.PackSize,SEEK_SET);
if( !(NewLhd.Flags&LHD_SPLIT_BEFORE) )
{
// 僷僗儚乕僪擖椡
if( NewLhd.Flags&LHD_PASSWORD )
if( *PassWord==0 )
strncpy(PassWord,GetPassword(),sizeof(PassWord));
// 奿擺偝傟偰傞偺偑僼傽僀儖偩偭偨傜側傫偐張棟丅
if( NewLhd.FileAttr&0x08 ) continue;
if( NewLhd.HostOS==UNIX ){NewLhd.FileAttr=(NewLhd.FileAttr&0x40)?0x10:0x20;}
//by uema2.
DestName = (char*)LocalAlloc(LPTR, MAX_PATH*sizeof(char)); // by uema2.
sprintf(DestName, "%s\\%s", ueutil::GetExtractPath(), kiutil::pathMake( ExtrName ));
// DestName = kiutil::pathMake( ExtrName );
if( NewLhd.FileAttr&0x10 ) continue;
// 揥奐
out=fopen( DestName,"wb" );
if( out!=NULL )
{
CurUnpRead=CurUnpWrite=0;
UnpFileCRC=(ArcFormat==OLD)?0:0xFFFFFFFFL;
PackedCRC=0xFFFFFFFFL;
if( 0!=(Encryption=((*PassWord!=0)&&(NewLhd.Flags&LHD_PASSWORD))?NewLhd.UnpVer:0) )
SetCryptKeys(PassWord);
UnpPackedSize=NewLhd.PackSize;
DestUnpSize=NewLhd.UnpSize;
if( NewLhd.Method==0x30 )
Unstore();
else if( NewLhd.UnpVer<13 || NewLhd.UnpVer>UNP_VER );
else if( NewLhd.UnpVer<=15 )
OldUnpack(!bFirstFile&&bSolid);
else
Unpack(0!=(NewLhd.Flags&LHD_SOLID));
fclose(out);
//DestName傪TCHAR偵 by uema2.
_MultiByteToWideChar(CP_ACP, 0, DestName, strlen(DestName)+1,
t_DestName, strlen(DestName)+1);
if( !(ArcFormat==OLD && UnpFileCRC==NewLhd.FileCRC) && !(ArcFormat==NEW && UnpFileCRC==~NewLhd.FileCRC) )
{
if( NewLhd.Flags&LHD_PASSWORD ) // Bad CRC
// DeleteFile(DestName);
DeleteFile(t_DestName); //by uema2.
}
else
{
kiutil::timeSet(DestName,(WORD)(NewLhd.FileTime>>16),(WORD)NewLhd.FileTime);
// SetFileAttributes(DestName,NewLhd.FileAttr);
SetFileAttributes(t_DestName,NewLhd.FileAttr); //fixed by uema2.
}
}
LocalFree(DestName); // by uema2.
}
if(arc==NULL)break;
bFirstFile=false;
fseek(arc,NextBlockPos,SEEK_SET);
}
fclose(arc);
return true;
}
/**** Unpackers(Old) *****************************************************/
#define GetBits() \
BitField = ( ( ( (DWORD)InBuf[InAddr] << 16 ) | \
( (WORD) InBuf[InAddr+1] << 8 ) | \
( InBuf[InAddr+2] ) ) \
>> (8-InBit) ) & 0xffff;
#define AddBits(Bits) \
InAddr += ( InBit + (Bits) ) >> 3; \
InBit = ( InBit + (Bits) ) & 7;
static unsigned int ShortLen1[]={1,3,4,4,5,6,7,8,8,4,4,5,6,6,4,0};
static unsigned int ShortXor1[]={0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,
0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0};
static unsigned int ShortLen2[]={2,3,3,3,4,4,5,6,6,4,4,5,6,6,4,0};
static unsigned int ShortXor2[]={0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,
0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0};
#define STARTL1 2
static unsigned int DecL1[]={0x8000,0xa000,0xc000,0xd000,0xe000,0xea00,
0xee00,0xf000,0xf200,0xf200,0xffff};
static unsigned int PosL1[]={0,0,0,2,3,5,7,11,16,20,24,32,32};
#define STARTL2 3
static unsigned int DecL2[]={0xa000,0xc000,0xd000,0xe000,0xea00,0xee00,
0xf000,0xf200,0xf240,0xffff};
static unsigned int PosL2[]={0,0,0,0,5,7,9,13,18,22,26,34,36};
#define STARTHF0 4
static unsigned int DecHf0[]={0x8000,0xc000,0xe000,0xf200,0xf200,0xf200,
0xf200,0xf200,0xffff};
static unsigned int PosHf0[]={0,0,0,0,0,8,16,24,33,33,33,33,33};
#define STARTHF1 5
static unsigned int DecHf1[]={0x2000,0xc000,0xe000,0xf000,0xf200,0xf200,
0xf7e0,0xffff};
static unsigned int PosHf1[]={0,0,0,0,0,0,4,44,60,76,80,80,127};
#define STARTHF2 5
static unsigned int DecHf2[]={0x1000,0x2400,0x8000,0xc000,0xfa00,0xffff,
0xffff,0xffff};
static unsigned int PosHf2[]={0,0,0,0,0,0,2,7,53,117,233,0,0};
#define STARTHF3 6
static unsigned int DecHf3[]={0x800,0x2400,0xee00,0xfe80,0xffff,0xffff,
0xffff};
static unsigned int PosHf3[]={0,0,0,0,0,0,0,2,16,218,251,0,0};
#define STARTHF4 8
static unsigned int DecHf4[]={0xff00,0xffff,0xffff,0xffff,0xffff,0xffff};
static unsigned int PosHf4[]={0,0,0,0,0,0,0,0,0,255,0,0,0};
void CRarTool::OldUnpack(bool bSolid)
{
int SetStMode=0;
UnpInitData(bSolid);
OldUnpInitData(bSolid);
UnpReadBuf(1);
if (!bSolid)
{
InitHuff();
UnpPtr=0;
}
else
UnpPtr=WrPtr;
DestUnpSize--;
if (SetStMode)
StMode=1;
else
if (DestUnpSize>=0)
{
GetFlagsBuf();
FlagsCnt=8;
}
while (DestUnpSize>=0)
{
UnpPtr&=MAXWINMASK;
if (InAddr>sizeof(InBuf)-30)
UnpReadBuf(0);
if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
{
UnpWriteBuf();
}
if (StMode)
{
HuffDecode();
continue;
}
if (--FlagsCnt < 0)
{
GetFlagsBuf();
FlagsCnt=7;
}
if (FlagBuf & 0x80)
{
FlagBuf<<=1;
if (Nlzb > Nhfb)
LongLZ();
else
HuffDecode();
}
else
{
FlagBuf<<=1;
if (--FlagsCnt < 0)
{
GetFlagsBuf();
FlagsCnt=7;
}
if (FlagBuf & 0x80)
{
FlagBuf<<=1;
if (Nlzb > Nhfb)
HuffDecode();
else
LongLZ();
}
else
{
FlagBuf<<=1;
ShortLZ();
}
}
}
UnpWriteBuf();
}
void CRarTool::ShortLZ()
{
unsigned int Length,SaveLength;
unsigned int LastDistance;
unsigned int Distance;
int DistancePlace;
NumHuf=0;
GetBits();
if (LCount==2)
{
AddBits(1);
if (BitField >= 0x8000)
{
OldCopyString((unsigned int)LastDist,LastLength);
return;
}
BitField <<= 1;
LCount=0;
}
BitField>>=8;
ShortLen1[1]=ShortLen2[3]=Buf60+3;
if (AvrLn1<37)
{
for (Length=0;;Length++)
if (((BitField^ShortXor1[Length]) & (~(0xff>>ShortLen1[Length])))==0)
break;
AddBits(ShortLen1[Length]);
}
else
{
for (Length=0;;Length++)
if (((BitField^ShortXor2[Length]) & (~(0xff>>ShortLen2[Length])))==0)
break;
AddBits(ShortLen2[Length]);
}
if (Length >= 9)
{
if (Length == 9)
{
LCount++;
OldCopyString((unsigned int)LastDist,LastLength);
return;
}
if (Length == 14)
{
LCount=0;
GetBits();
Length=DecodeNum(BitField,STARTL2,DecL2,PosL2)+5;
GetBits();
Distance=(BitField>>1) | 0x8000;
AddBits(15);
LastLength=Length;
LastDist=Distance;
OldCopyString(Distance,Length);
return;
}
LCount=0;
SaveLength=Length;
Distance=OldDist[(OldDistPtr-(Length-9)) & 3];
GetBits();
Length=DecodeNum(BitField,STARTL1,DecL1,PosL1)+2;
if (Length==0x101 && SaveLength==10)
{
Buf60 ^= 1;
return;
}
if (Distance > 256)
Length++;
if (Distance >= MaxDist3)
Length++;
OldDist[OldDistPtr++]=Distance;
OldDistPtr = OldDistPtr & 3;
LastLength=Length;
LastDist=Distance;
OldCopyString(Distance,Length);
return;
}
LCount=0;
AvrLn1 += Length;
AvrLn1 -= AvrLn1 >> 4;
GetBits();
DistancePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
Distance=ChSetA[DistancePlace];
if (--DistancePlace != -1)
{
PlaceA[Distance]--;
LastDistance=ChSetA[DistancePlace];
PlaceA[LastDistance]++;
ChSetA[DistancePlace+1]=LastDistance;
ChSetA[DistancePlace]=Distance;
}
Length+=2;
OldDist[OldDistPtr++] = ++Distance;
OldDistPtr = OldDistPtr & 3;
LastLength=Length;
LastDist=Distance;
OldCopyString(Distance,Length);
return;
}
void CRarTool::LongLZ()
{
unsigned int Length;
unsigned int Distance;
unsigned int DistancePlace,NewDistancePlace;
unsigned int OldAvr2,OldAvr3;
NumHuf=0;
Nlzb+=16;
if (Nlzb > 0xff)
{
Nlzb=0x90;
Nhfb >>= 1;
}
OldAvr2=AvrLn2;
GetBits();
if (AvrLn2 >= 122)
Length=DecodeNum(BitField,STARTL2,DecL2,PosL2);
else
if (AvrLn2 >= 64)
Length=DecodeNum(BitField,STARTL1,DecL1,PosL1);
else
if (BitField < 0x100)
{
Length=BitField;
AddBits(16);
}
else
{
for (Length=0;((BitField<<Length)&0x8000)==0;Length++)
;
AddBits(Length+1);
}
AvrLn2 += Length;
AvrLn2 -= AvrLn2 >> 5;
GetBits();
if (AvrPlcB > 0x28ff)
DistancePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
else
if (AvrPlcB > 0x6ff)
DistancePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1);
else
DistancePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0);
AvrPlcB += DistancePlace;
AvrPlcB -= AvrPlcB >> 8;
while (1)
{
Distance = ChSetB[DistancePlace];
NewDistancePlace = NToPlB[Distance++ & 0xff]++;
if (!(Distance & 0xff))
CorrHuff(ChSetB,NToPlB);
else
break;
}
ChSetB[DistancePlace]=ChSetB[NewDistancePlace];
ChSetB[NewDistancePlace]=Distance;
GetBits();
Distance=((WORD)((Distance & 0xff00) | (BitField >> 8))) >> 1;
AddBits(7);
OldAvr3=AvrLn3;
if (Length!=1 && Length!=4)
if (Length==0 && Distance <= MaxDist3)
{
AvrLn3++;
AvrLn3 -= AvrLn3 >> 8;
}
else
if (AvrLn3 > 0)
AvrLn3--;
Length+=3;
if (Distance >= MaxDist3)
Length++;
if (Distance <= 256)
Length+=8;
if (OldAvr3 > 0xb0 || AvrPlc >= 0x2a00 && OldAvr2 < 0x40)
MaxDist3=0x7f00;
else
MaxDist3=0x2001;
OldDist[OldDistPtr++]=Distance;
OldDistPtr = OldDistPtr & 3;
LastLength=Length;
LastDist=Distance;
OldCopyString(Distance,Length);
}
void CRarTool::HuffDecode()
{
unsigned int CurByte,NewBytePlace;
unsigned int Length;
unsigned int Distance;
int BytePlace;
GetBits();
if (AvrPlc > 0x75ff)
BytePlace=DecodeNum(BitField,STARTHF4,DecHf4,PosHf4);
else
if (AvrPlc > 0x5dff)
BytePlace=DecodeNum(BitField,STARTHF3,DecHf3,PosHf3);
else
if (AvrPlc > 0x35ff)
BytePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
else
if (AvrPlc > 0x0dff)
BytePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1);
else
BytePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0);
if (StMode)
{
if (BytePlace==0 && BitField > 0xfff)
BytePlace=0x100;
if (--BytePlace==-1)
{
GetBits();
AddBits(1);
if (BitField & 0x8000)
{
NumHuf=StMode=0;
return;
}
else
{
Length = (BitField & 0x4000) ? 4 : 3;
AddBits(1);
GetBits();
Distance=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
GetBits();
Distance = (Distance << 5) | (BitField >> 11);
AddBits(5);
OldCopyString(Distance,Length);
return;
}
}
}
else
if (NumHuf++ >= 16 && FlagsCnt==0)
StMode=1;
AvrPlc += BytePlace;
AvrPlc -= AvrPlc >> 8;
Nhfb+=16;
if (Nhfb > 0xff)
{
Nhfb=0x90;
Nlzb >>= 1;
}
CTool::common_buf[UnpPtr++]=(BYTE)(ChSet[BytePlace]>>8);
DestUnpSize--;
while (1)
{
CurByte=ChSet[BytePlace];
NewBytePlace=NToPl[CurByte++ & 0xff]++;
if ((CurByte & 0xff) > 0xa1)
CorrHuff(ChSet,NToPl);
else
break;
}
ChSet[BytePlace]=ChSet[NewBytePlace];
ChSet[NewBytePlace]=CurByte;
}
void CRarTool::GetFlagsBuf()
{
unsigned int Flags,FlagsPlace,NewFlagsPlace;
GetBits();
FlagsPlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
while (1)
{
Flags=ChSetC[FlagsPlace];
FlagBuf=Flags>>8;
NewFlagsPlace=NToPlC[Flags++ & 0xff]++;
if ((Flags & 0xff) == 0)
CorrHuff(ChSetC,NToPlC);
else
break;
}
ChSetC[FlagsPlace]=ChSetC[NewFlagsPlace];
ChSetC[NewFlagsPlace]=Flags;
}
void CRarTool::OldUnpInitData(bool bSolid)
{
if(!bSolid)
{
AvrPlcB=AvrLn1=AvrLn2=AvrLn3=NumHuf=Buf60=0;
AvrPlc=0x3500;
MaxDist3=0x2001;
Nhfb=Nlzb=0x80;
}
FlagsCnt=0;
FlagBuf=0;
StMode=0;
LCount=0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -