Patch by Ioan Molnar: update unrar from version 3.67 to 3.76 - thanks!

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21952 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2007-08-14 22:45:34 +00:00
parent c1b3e74df2
commit 36c5ff54b6
52 changed files with 844 additions and 325 deletions

View File

@ -197,6 +197,10 @@ bool Archive::IsArchive(bool EnableBroken)
#ifdef RARDLL
SilentOpen=true;
#endif
//if not encrypted, we'll check it below
NotFirstVolume=Encrypted && (NewMhd.Flags & MHD_FIRSTVOLUME)==0;
if (!SilentOpen || !Encrypted)
{
SaveFilePos SavePos(*this);
@ -226,6 +230,12 @@ bool Archive::IsArchive(bool EnableBroken)
CurBlockPos=SaveCurBlockPos;
NextBlockPos=SaveNextBlockPos;
}
if (!Volume || !NotFirstVolume)
{
strcpy(FirstVolumeName,FileName);
strcpyw(FirstVolumeNameW,FileNameW);
}
return(true);
}

View File

@ -10,11 +10,9 @@ class Archive:public File
private:
bool IsSignature(byte *D);
void UpdateLatestTime(FileHeader *CurBlock);
void Protect(int RecSectors);
void ConvertNameCase(char *Name);
void ConvertNameCase(wchar *Name);
void ConvertUnknownHeader();
bool AddArcComment(char *NameToShow);
int ReadOldHeader();
void PrepareExtraTime(FileHeader *hd,EXTTIME_MODE etm,EXTTIME_MODE etc,EXTTIME_MODE eta,EXTTIME_MODE etarc,Array<byte> &TimeData);

View File

@ -162,8 +162,7 @@ int Archive::ReadHeader()
Raw.Get((byte *)FileName,NameSize);
FileName[NameSize]=0;
strncpy(hd->FileName,FileName,sizeof(hd->FileName));
hd->FileName[sizeof(hd->FileName)-1]=0;
strncpyz(hd->FileName,FileName,ASIZE(hd->FileName));
if (hd->HeadType==NEWSUB_HEAD)
{

View File

@ -55,10 +55,10 @@ void CommandData::ParseArg(char *Arg,wchar *ArgW)
else
if (*Command==0)
{
strncpy(Command,Arg,sizeof(Command));
strncpyz(Command,Arg,ASIZE(Command));
if (ArgW!=NULL)
strncpyw(CommandW,ArgW,sizeof(CommandW)/sizeof(CommandW[0]));
if (toupper(*Command)=='S')
if (etoupper(*Command)=='S')
{
const char *SFXName=Command[1] ? Command+1:DefSFXName;
if (PointToName(SFXName)!=SFXName || FileExist(SFXName))
@ -67,7 +67,7 @@ void CommandData::ParseArg(char *Arg,wchar *ArgW)
GetConfigName(SFXName,SFXModule,true);
}
#ifndef GUI
*Command=toupper(*Command);
*Command=etoupper(*Command);
if (*Command!='I' && *Command!='S')
strupper(Command);
#endif
@ -75,19 +75,23 @@ void CommandData::ParseArg(char *Arg,wchar *ArgW)
else
if (*ArcName==0)
{
strncpy(ArcName,Arg,sizeof(ArcName));
strncpyz(ArcName,Arg,ASIZE(ArcName));
if (ArgW!=NULL)
strncpyw(ArcNameW,ArgW,sizeof(ArcNameW)/sizeof(ArcNameW[0]));
strncpyzw(ArcNameW,ArgW,ASIZE(ArcNameW));
}
else
{
int Length=strlen(Arg);
char EndChar=Arg[Length-1];
char CmdChar=toupper(*Command);
char CmdChar=etoupper(*Command);
bool Add=strchr("AFUM",CmdChar)!=NULL;
bool Extract=CmdChar=='X' || CmdChar=='E';
if ((IsDriveDiv(EndChar) || IsPathDiv(EndChar)) && !Add)
strcpy(ExtrPath,Arg);
{
strncpyz(ExtrPath,Arg,ASIZE(ExtrPath));
if (ArgW!=NULL)
strncpyzw(ExtrPathW,ArgW,ASIZE(ExtrPathW));
}
else
if ((Add || CmdChar=='T') && *Arg!='@')
FileArgs->AddString(Arg);
@ -98,7 +102,18 @@ void CommandData::ParseArg(char *Arg,wchar *ArgW)
if (!Found && *Arg=='@' && !IsWildcard(Arg))
{
FileLists=true;
ReadTextFile(Arg+1,FileArgs,false,true,true,true,true);
RAR_CHARSET Charset=FilelistCharset;
#if defined(_WIN_32) && !defined(GUI)
// for compatibility reasons we use OEM encoding
// in Win32 console version by default
if (Charset==RCH_DEFAULT)
Charset=RCH_OEM;
#endif
ReadTextFile(Arg+1,FileArgs,false,true,Charset,true,true);
}
else
if (Found && FileData.IsDir && Extract && *ExtrPath==0)
@ -118,7 +133,7 @@ void CommandData::ParseDone()
{
if (FileArgs->ItemsCount()==0 && !FileLists)
FileArgs->AddString(MASKALL);
char CmdChar=toupper(*Command);
char CmdChar=etoupper(*Command);
bool Extract=CmdChar=='X' || CmdChar=='E';
if (Test && Extract)
Test=false;
@ -136,7 +151,11 @@ void CommandData::ParseEnvVar()
#endif
#if !defined(GUI) && !defined(SFX_MODULE)
// return 'false' if -cfg- is present and preprocess switches
// which must be processed before the rest of command line
#ifndef SFX_MODULE
bool CommandData::IsConfigEnabled(int argc,char *argv[])
{
bool ConfigEnabled=true;
@ -145,11 +164,20 @@ bool CommandData::IsConfigEnabled(int argc,char *argv[])
{
if (stricomp(&argv[I][1],"cfg-")==0)
ConfigEnabled=false;
#ifndef GUI
if (strnicomp(&argv[I][1],"ilog",4)==0)
{
// ensure that correct log file name is already set
// if we need to report an error when processing the command line
ProcessSwitch(&argv[I][1]);
InitLogOptions(LogName);
}
#endif
if (strnicomp(&argv[I][1],"sc",2)==0)
{
// process -cs before reading any file lists
ProcessSwitch(&argv[I][1]);
}
}
return(ConfigEnabled);
}
@ -201,12 +229,12 @@ void CommandData::ProcessSwitchesString(char *Str)
void CommandData::ProcessSwitch(char *Switch)
{
switch(toupper(Switch[0]))
switch(etoupper(Switch[0]))
{
case 'I':
if (strnicomp(&Switch[1],"LOG",3)==0)
{
strncpy(LogName,Switch[4] ? Switch+4:DefLogName,sizeof(LogName));
strncpyz(LogName,Switch[4] ? Switch+4:DefLogName,ASIZE(LogName));
break;
}
if (stricomp(&Switch[1],"SND")==0)
@ -221,7 +249,7 @@ void CommandData::ProcessSwitch(char *Switch)
}
if (strnicomp(&Switch[1],"EML",3)==0)
{
strncpy(EmailTo,Switch[4] ? Switch+4:"@",sizeof(EmailTo));
strncpyz(EmailTo,Switch[4] ? Switch+4:"@",ASIZE(EmailTo));
EmailTo[sizeof(EmailTo)-1]=0;
break;
}
@ -230,10 +258,10 @@ void CommandData::ProcessSwitch(char *Switch)
MsgStream=MSG_NULL;
break;
}
if (toupper(Switch[1])=='D')
if (etoupper(Switch[1])=='D')
{
for (int I=2;Switch[I]!=0;I++)
switch(toupper(Switch[I]))
switch(etoupper(Switch[I]))
{
case 'Q':
MsgStream=MSG_ERRONLY;
@ -257,7 +285,7 @@ void CommandData::ProcessSwitch(char *Switch)
}
break;
case 'T':
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case 'K':
ArcTime=ARCTIME_KEEP;
@ -293,7 +321,7 @@ void CommandData::ProcessSwitch(char *Switch)
Mode=(EXTTIME_MODE)(Switch[3]-'0');
if (Switch[3]=='-')
Mode=EXTTIME_NONE;
switch(toupper(Switch[2]))
switch(etoupper(Switch[2]))
{
case 'M':
xmtime=Mode;
@ -323,7 +351,7 @@ void CommandData::ProcessSwitch(char *Switch)
}
break;
case 'A':
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case 'C':
ClearArc=true;
@ -337,7 +365,7 @@ void CommandData::ProcessSwitch(char *Switch)
else
{
GenerateArcName=true;
strncpy(GenerateMask,Switch+2,sizeof(GenerateMask));
strncpyz(GenerateMask,Switch+2,ASIZE(GenerateMask));
}
break;
case 'N': //reserved for archive name
@ -351,11 +379,14 @@ void CommandData::ProcessSwitch(char *Switch)
case 'S':
SyncFiles=true;
break;
default:
BadSwitch(Switch);
break;
}
break;
case 'D':
if (Switch[2]==0)
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case 'S':
DisableSortSolid=true;
@ -369,7 +400,7 @@ void CommandData::ProcessSwitch(char *Switch)
}
break;
case 'O':
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case '+':
Overwrite=OVERWRITE_ALL;
@ -402,7 +433,7 @@ void CommandData::ProcessSwitch(char *Switch)
}
break;
case 'R':
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case 0:
Recurse=RECURSE_ALWAYS;
@ -435,16 +466,28 @@ void CommandData::ProcessSwitch(char *Switch)
case 'N':
case 'X':
if (Switch[1]!=0)
{
StringList *Args=toupper(Switch[0])=='N' ? InclArgs:ExclArgs;
{
StringList *Args=etoupper(Switch[0])=='N' ? InclArgs:ExclArgs;
if (Switch[1]=='@' && !IsWildcard(Switch))
ReadTextFile(Switch+2,Args,false,true,true,true,true);
{
RAR_CHARSET Charset=FilelistCharset;
#if defined(_WIN_32) && !defined(GUI)
// for compatibility reasons we use OEM encoding
// in Win32 console version by default
if (Charset==RCH_DEFAULT)
Charset=RCH_OEM;
#endif
ReadTextFile(Switch+2,Args,false,true,Charset,true,true);
}
else
Args->AddString(Switch+1);
}
break;
case 'E':
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case 'P':
switch(Switch[2])
@ -490,14 +533,14 @@ void CommandData::ProcessSwitch(char *Switch)
eprintf("\n");
}
else
strncpy(Password,Switch+1,sizeof(Password));
strncpyz(Password,Switch+1,ASIZE(Password));
break;
case 'H':
if (toupper(Switch[1])=='P')
if (etoupper(Switch[1])=='P')
{
EncryptHeaders=true;
if (Switch[2]!=0)
strncpy(Password,Switch+2,sizeof(Password));
strncpyz(Password,Switch+2,ASIZE(Password));
else
if (*Password==0)
{
@ -507,11 +550,10 @@ void CommandData::ProcessSwitch(char *Switch)
}
break;
case 'Z':
strncpy(CommentFile,Switch[1]!=0 ? Switch+1:"stdin",sizeof(CommentFile)-1);
CommentFile[sizeof(CommentFile)-1]=0;
strncpyz(CommentFile,Switch[1]!=0 ? Switch+1:"stdin",ASIZE(CommentFile));
break;
case 'M':
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case 'C':
{
@ -537,7 +579,7 @@ void CommandData::ProcessSwitch(char *Switch)
while (isdigit(*Str))
Str++;
}
switch(toupper(*(Str++)))
switch(etoupper(*(Str++)))
{
case 'T': Type=FILTER_PPM; break;
case 'E': Type=FILTER_E8; break;
@ -560,7 +602,7 @@ void CommandData::ProcessSwitch(char *Switch)
case 'D':
{
if ((WinSize=atoi(&Switch[2]))==0)
WinSize=0x10000<<(toupper(Switch[2])-'A');
WinSize=0x10000<<(etoupper(Switch[2])-'A');
else
WinSize*=1024;
if (!CheckWinSize())
@ -612,7 +654,7 @@ void CommandData::ProcessSwitch(char *Switch)
}
break;
case 'V':
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
#ifdef _WIN_32
case 'D':
@ -626,7 +668,7 @@ void CommandData::ProcessSwitch(char *Switch)
VolumePause=true;
break;
case 'E':
if (toupper(Switch[2])=='R')
if (etoupper(Switch[2])=='R')
VersionControl=atoi(Switch+3)+1;
break;
case '-':
@ -695,30 +737,19 @@ void CommandData::ProcessSwitch(char *Switch)
}
break;
case 'F':
switch(toupper(Switch[1]))
{
case 0:
FreshFiles=true;
break;
case 'C':
if (toupper(Switch[2])=='U')
{
UnicodeComment=true;
if (*CommentFile==0 || Switch[3]!=0)
{
strncpy(CommentFile,Switch[3]!=0 ? Switch+3:"stdin",sizeof(CommentFile)-1);
CommentFile[sizeof(CommentFile)-1]=0;
}
}
break;
}
if (Switch[1]==0)
FreshFiles=true;
else
BadSwitch(Switch);
break;
case 'U':
if (Switch[1]==0)
UpdateFiles=true;
else
BadSwitch(Switch);
break;
case 'W':
strncpy(TempPath,&Switch[1],sizeof(TempPath)-1);
strncpyz(TempPath,&Switch[1],ASIZE(TempPath));
AddEndSlash(TempPath);
break;
case 'S':
@ -736,7 +767,7 @@ void CommandData::ProcessSwitch(char *Switch)
SolidCount=atoi(&Switch[1]);
}
else
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case 0:
Solid|=SOLID_NORMAL;
@ -761,11 +792,48 @@ void CommandData::ProcessSwitch(char *Switch)
if (isdigit(Switch[2]))
FileSizeMore=atoil(Switch+2);
break;
case 'C':
{
RAR_CHARSET rch;
switch(etoupper(Switch[2]))
{
case 'A':
rch=RCH_ANSI;
break;
case 'O':
rch=RCH_OEM;
break;
case 'U':
rch=RCH_UNICODE;
break;
default :
BadSwitch(Switch);
break;
};
if (Switch[3]==0)
CommentCharset=FilelistCharset=rch;
else
for (int I=3;Switch[I]!=0;I++)
switch(etoupper(Switch[I]))
{
case 'C':
CommentCharset=rch;
break;
case 'L':
FilelistCharset=rch;
break;
default:
BadSwitch(Switch);
break;
}
}
break;
}
break;
case 'C':
if (Switch[2]==0)
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case '-':
DisableComment=true;
@ -779,7 +847,7 @@ void CommandData::ProcessSwitch(char *Switch)
}
break;
case 'K':
switch(toupper(Switch[1]))
switch(etoupper(Switch[1]))
{
case 'B':
KeepBroken=true;
@ -866,17 +934,17 @@ void CommandData::OutHelp()
MCHelpSwAO,MCHelpSwAP,MCHelpSwAS,MCHelpSwAV,MCHelpSwAVm,MCHelpSwCm,
MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU,MCHelpSwDF,MCHelpSwDH,MCHelpSwDS,
MCHelpSwEa,MCHelpSwED,MCHelpSwEE,MCHelpSwEN,MCHelpSwEP,MCHelpSwEP1,
MCHelpSwEP2,MCHelpSwEP3,MCHelpSwF,MCHelpSwFCU,MCHelpSwHP,MCHelpSwIDP,
MCHelpSwEP2,MCHelpSwEP3,MCHelpSwF,MCHelpSwHP,MCHelpSwIDP,
MCHelpSwIEML,MCHelpSwIERR,MCHelpSwILOG,MCHelpSwINUL,MCHelpSwIOFF,
MCHelpSwISND,MCHelpSwK,MCHelpSwKB,MCHelpSwMn,MCHelpSwMC,MCHelpSwMD,
MCHelpSwMS,MCHelpSwMT,MCHelpSwN,MCHelpSwNa,MCHelpSwNal,MCHelpSwOp,
MCHelpSwOm,MCHelpSwOC,MCHelpSwOL,MCHelpSwOR,MCHelpSwOS,MCHelpSwOW,
MCHelpSwP,MCHelpSwPm,MCHelpSwR,MCHelpSwR0,MCHelpSwRI,MCHelpSwRR,
MCHelpSwRV,MCHelpSwS,MCHelpSwSm,MCHelpSwSFX,MCHelpSwSI,MCHelpSwSL,
MCHelpSwSM,MCHelpSwT,MCHelpSwTA,MCHelpSwTB,MCHelpSwTK,MCHelpSwTL,
MCHelpSwTN,MCHelpSwTO,MCHelpSwTS,MCHelpSwU,MCHelpSwV,MCHelpSwVn,
MCHelpSwVD,MCHelpSwVER,MCHelpSwVN,MCHelpSwVP,MCHelpSwW,MCHelpSwX,
MCHelpSwXa,MCHelpSwXal,MCHelpSwY,MCHelpSwZ
MCHelpSwRV,MCHelpSwS,MCHelpSwSm,MCHelpSwSC,MCHelpSwSFX,MCHelpSwSI,
MCHelpSwSL,MCHelpSwSM,MCHelpSwT,MCHelpSwTA,MCHelpSwTB,MCHelpSwTK,
MCHelpSwTL,MCHelpSwTN,MCHelpSwTO,MCHelpSwTS,MCHelpSwU,MCHelpSwV,
MCHelpSwVn,MCHelpSwVD,MCHelpSwVER,MCHelpSwVN,MCHelpSwVP,MCHelpSwW,
MCHelpSwX,MCHelpSwXa,MCHelpSwXal,MCHelpSwY,MCHelpSwZ
#endif
};
@ -1079,7 +1147,9 @@ int CommandData::IsProcessFile(FileHeader &NewLhd,bool *ExactMatch,int MatchType
void CommandData::ProcessCommand()
{
#ifndef SFX_MODULE
if (Command[1] && strchr("FUADPXETK",*Command)!=NULL || *ArcName==0)
const char *SingleCharCommands="FUADPXETK";
if (Command[1] && strchr(SingleCharCommands,*Command)!=NULL || *ArcName==0)
OutHelp();
#ifdef _UNIX
@ -1163,7 +1233,7 @@ uint CommandData::GetExclAttr(char *Str)
{
uint Attr;
for (Attr=0;*Str;Str++)
switch(toupper(*Str))
switch(etoupper(*Str))
{
#ifdef _UNIX
case 'D':

View File

@ -29,7 +29,7 @@ enum {CODE_HUFFMAN,CODE_LZ,CODE_LZ2,CODE_REPEATLZ,CODE_CACHELZ,
enum FilterType {
FILTER_NONE, FILTER_PPM /*dummy*/, FILTER_E8, FILTER_E8E9,
FILTER_UPCASETOLOW, FILTER_AUDIO, FILTER_RGB, FILTER_DELTA,
FILTER_UPCASETOLOW, FILTER_AUDIO, FILTER_RGB, FILTER_DELTA,
FILTER_ITANIUM, FILTER_E8E9V2
};

View File

@ -124,8 +124,9 @@ void GetPasswordText(char *Str,int MaxLength)
#elif defined(_EMX) || defined(_BEOS) || defined(__sparc) || defined(sparc) || defined (__VMS)
fgets(Str,MaxLength-1,stdin);
#else
strncpy(Str,getpass(""),MaxLength-1);
strncpyz(Str,getpass(""),MaxLength);
#endif
Str[MaxLength-1]=0;
RemoveLF(Str);
}
#endif
@ -159,7 +160,7 @@ bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxL
Alarm();
while (true)
{
char PromptStr[256];
char PromptStr[NM+256];
#if defined(_EMX) || defined(_BEOS)
strcpy(PromptStr,St(MAskPswEcho));
#else
@ -168,7 +169,9 @@ bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxL
if (Type!=PASSWORD_GLOBAL)
{
strcat(PromptStr,St(MFor));
strcat(PromptStr,PointToName(FileName));
char *NameOnly=PointToName(FileName);
if (strlen(PromptStr)+strlen(NameOnly)<ASIZE(PromptStr))
strcat(PromptStr,NameOnly);
}
eprintf("\n%s: ",PromptStr);
GetPasswordText(Password,MaxLength);
@ -176,19 +179,12 @@ bool GetPassword(PASSWORD_TYPE Type,const char *FileName,char *Password,int MaxL
return(false);
if (Type==PASSWORD_GLOBAL)
{
strcpy(PromptStr,St(MReAskPsw));
eprintf(PromptStr);
char CmpStr[256];
GetPasswordText(CmpStr,sizeof(CmpStr));
eprintf(St(MReAskPsw));
char CmpStr[MAXPASSWORD];
GetPasswordText(CmpStr,ASIZE(CmpStr));
if (*CmpStr==0 || strcmp(Password,CmpStr)!=0)
{
strcpy(PromptStr,St(MNotMatchPsw));
/*
#ifdef _WIN_32
CharToOem(PromptStr,PromptStr);
#endif
*/
eprintf(PromptStr);
eprintf(St(MNotMatchPsw));
memset(Password,0,MaxLength);
memset(CmpStr,0,sizeof(CmpStr));
continue;
@ -212,7 +208,7 @@ int Ask(const char *AskStr)
for (const char *NextItem=AskStr;NextItem!=NULL;NextItem=strchr(NextItem+1,'_'))
{
char *CurItem=Item[NumItems];
strncpy(CurItem,NextItem+1,sizeof(Item[0]));
strncpyz(CurItem,NextItem+1,ASIZE(Item[0]));
char *EndItem=strchr(CurItem,'_');
if (EndItem!=NULL)
*EndItem=0;

View File

@ -42,7 +42,7 @@ uint CRC(uint StartCRC,const void *Addr,uint Size)
Size-=8;
}
#endif
for (uint I=0;I<Size;I++)
for (int I=0;I<Size;I++)
StartCRC=CRCTab[(byte)(StartCRC^Data[I])]^(StartCRC>>8);
return(StartCRC);
}
@ -51,7 +51,7 @@ uint CRC(uint StartCRC,const void *Addr,uint Size)
ushort OldCRC(ushort StartCRC,const void *Addr,uint Size)
{
byte *Data=(byte *)Addr;
for (uint I=0;I<Size;I++)
for (int I=0;I<Size;I++)
{
StartCRC=(StartCRC+Data[I])&0xffff;
StartCRC=((StartCRC<<1)|(StartCRC>>15))&0xffff;

View File

@ -204,7 +204,7 @@ void CryptData::SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly
#if defined(_WIN_32) && !defined(GUI)
CharToOemBuff(Password,(char*)Psw,strlen(Password));
#else
strncpy((char *)Psw,Password,MAXPASSWORD-1);
strncpyz((char *)Psw,Password,ASIZE(Psw));
#endif
int PswLength=strlen(Password);
memcpy(SubstTable,InitSubstTable,sizeof(SubstTable));
@ -223,7 +223,7 @@ void CryptData::SetCryptKeys(char *Password,byte *Salt,bool Encrypt,bool OldOnly
}
bool Cached=false;
for (uint I=0;I<sizeof(Cache)/sizeof(Cache[0]);I++)
for (int I=0;I<sizeof(Cache)/sizeof(Cache[0]);I++)
if (strcmp(Cache[I].Password,Password)==0 &&
(Salt==NULL && !Cache[I].SaltPresent || Salt!=NULL &&
Cache[I].SaltPresent && memcmp(Cache[I].Salt,Salt,SALT_SIZE)==0) &&

View File

@ -110,6 +110,7 @@ int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *D)
(Data->Arc.EndArcHead.Flags & EARC_NEXT_VOLUME))
if (MergeArchive(Data->Arc,NULL,false,'L'))
{
Data->Extract.SignatureFound=false;
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
return(RARReadHeader(hArcData,D));
}
@ -125,8 +126,8 @@ int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *D)
else
return(Code);
}
strncpy(D->ArcName,Data->Arc.FileName,sizeof(D->ArcName));
strncpy(D->FileName,Data->Arc.NewLhd.FileName,sizeof(D->FileName));
strncpyz(D->ArcName,Data->Arc.FileName,ASIZE(D->ArcName));
strncpyz(D->FileName,Data->Arc.NewLhd.FileName,ASIZE(D->FileName));
D->Flags=Data->Arc.NewLhd.Flags;
D->PackSize=Data->Arc.NewLhd.PackSize;
D->UnpSize=Data->Arc.NewLhd.UnpSize;
@ -158,6 +159,7 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
(Data->Arc.EndArcHead.Flags & EARC_NEXT_VOLUME))
if (MergeArchive(Data->Arc,NULL,false,'L'))
{
Data->Extract.SignatureFound=false;
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
return(RARReadHeaderEx(hArcData,D));
}
@ -173,12 +175,12 @@ int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
else
return(Code);
}
strncpy(D->ArcName,Data->Arc.FileName,sizeof(D->ArcName));
strncpyz(D->ArcName,Data->Arc.FileName,ASIZE(D->ArcName));
if (*Data->Arc.FileNameW)
strncpyw(D->ArcNameW,Data->Arc.FileNameW,sizeof(D->ArcNameW));
else
CharToWide(Data->Arc.FileName,D->ArcNameW);
strncpy(D->FileName,Data->Arc.NewLhd.FileName,sizeof(D->FileName));
strncpyz(D->FileName,Data->Arc.NewLhd.FileName,ASIZE(D->FileName));
if (*Data->Arc.NewLhd.FileNameW)
strncpyw(D->FileNameW,Data->Arc.NewLhd.FileNameW,sizeof(D->FileNameW));
else
@ -226,6 +228,7 @@ int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestNa
(Data->Arc.NewLhd.Flags & LHD_SPLIT_AFTER)!=0)
if (MergeArchive(Data->Arc,NULL,false,'L'))
{
Data->Extract.SignatureFound=false;
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
return(0);
}
@ -327,7 +330,7 @@ void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataPro
void PASCAL RARSetPassword(HANDLE hArcData,char *Password)
{
DataSet *Data=(DataSet *)hArcData;
strncpy(Data->Cmd.Password,Password,sizeof(Data->Cmd.Password));
strncpyz(Data->Cmd.Password,Password,ASIZE(Data->Cmd.Password));
}

View File

@ -1,18 +1,19 @@
#ifndef _UNRAR_DLL_
#define _UNRAR_DLL_
#define ERAR_END_ARCHIVE 10
#define ERAR_NO_MEMORY 11
#define ERAR_BAD_DATA 12
#define ERAR_BAD_ARCHIVE 13
#define ERAR_UNKNOWN_FORMAT 14
#define ERAR_EOPEN 15
#define ERAR_ECREATE 16
#define ERAR_ECLOSE 17
#define ERAR_EREAD 18
#define ERAR_EWRITE 19
#define ERAR_SMALL_BUF 20
#define ERAR_UNKNOWN 21
#define ERAR_END_ARCHIVE 10
#define ERAR_NO_MEMORY 11
#define ERAR_BAD_DATA 12
#define ERAR_BAD_ARCHIVE 13
#define ERAR_UNKNOWN_FORMAT 14
#define ERAR_EOPEN 15
#define ERAR_ECREATE 16
#define ERAR_ECLOSE 17
#define ERAR_EREAD 18
#define ERAR_EWRITE 19
#define ERAR_SMALL_BUF 20
#define ERAR_UNKNOWN 21
#define ERAR_MISSING_PASSWORD 22
#define RAR_OM_LIST 0
#define RAR_OM_EXTRACT 1

View File

@ -357,7 +357,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
if (ExactMatch || (SkipSolid=Arc.Solid)!=0)
{
if (Arc.NewLhd.Flags & LHD_PASSWORD)
if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0)
#ifndef RARDLL
if (*Password==0)
#endif
@ -410,7 +410,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
#ifndef SFX_MODULE
if (Cmd->AppendArcNameToPath)
{
strcat(DestFileName,PointToName(Arc.FileName));
strcat(DestFileName,PointToName(Arc.FirstVolumeName));
SetExt(DestFileName,NULL);
AddEndSlash(DestFileName);
}
@ -443,7 +443,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
else
strcat(DestFileName,ExtrName);
char DiskLetter=toupper(DestFileName[0]);
char DiskLetter=etoupper(DestFileName[0]);
if (AbsPaths && DestFileName[1]=='_' && IsPathDiv(DestFileName[2]) &&
DiskLetter>='A' && DiskLetter<='Z')
@ -469,10 +469,10 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
if (Cmd->AppendArcNameToPath)
{
wchar FileNameW[NM];
if (*Arc.FileNameW!=0)
strcpyw(FileNameW,Arc.FileNameW);
if (*Arc.FirstVolumeNameW!=0)
strcpyw(FileNameW,Arc.FirstVolumeNameW);
else
CharToWide(Arc.FileName,FileNameW);
CharToWide(Arc.FirstVolumeName,FileNameW);
strcatw(DestFileNameW,PointToName(FileNameW));
SetExt(DestFileNameW,NULL);
AddEndSlash(DestFileNameW);
@ -505,7 +505,8 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
else
*DestFileNameW=0;
ExtrFile=!SkipSolid && !EmptyName && (Arc.NewLhd.Flags & LHD_SPLIT_BEFORE)==0/* && *ExtrName*/;
ExtrFile=!SkipSolid && !EmptyName && (Arc.NewLhd.Flags & LHD_SPLIT_BEFORE)==0;
if ((Cmd->FreshFiles || Cmd->UpdateFiles) && (Command=='E' || Command=='X'))
{
struct FindData FD;
@ -519,17 +520,27 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
ExtrFile=false;
}
// skip encrypted file if no password is specified
if ((Arc.NewLhd.Flags & LHD_PASSWORD)!=0 && *Password==0)
{
ErrHandler.SetErrorCode(WARNING);
#ifdef RARDLL
Cmd->DllError=ERAR_MISSING_PASSWORD;
#endif
ExtrFile=false;
}
#ifdef RARDLL
if (*Cmd->DllDestName)
{
strncpy(DestFileName,Cmd->DllDestName,sizeof(DestFileName));
strncpyz(DestFileName,Cmd->DllDestName,ASIZE(DestFileName));
*DestFileNameW=0;
if (Cmd->DllOpMode!=RAR_EXTRACT)
ExtrFile=false;
}
if (*Cmd->DllDestNameW)
{
strncpyw(DestFileNameW,Cmd->DllDestNameW,sizeof(DestFileNameW)/sizeof(DestFileNameW[0]));
strncpyzw(DestFileNameW,Cmd->DllDestNameW,ASIZE(DestFileNameW));
DestNameW=DestFileNameW;
if (Cmd->DllOpMode!=RAR_EXTRACT)
ExtrFile=false;
@ -655,8 +666,7 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
{
Log(Arc.FileName,St(MCorrectingName));
char OrigName[sizeof(DestFileName)];
strncpy(OrigName,DestFileName,sizeof(OrigName)-1);
OrigName[sizeof(OrigName)-1]=0;
strncpyz(OrigName,DestFileName,ASIZE(OrigName));
MakeNameUsable(DestFileName,true);
CreatePath(DestFileName,NULL,true);
@ -799,6 +809,10 @@ bool CmdExtract::ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize
#if defined(_WIN_32) || defined(_EMX)
if (Cmd->ClearArc)
Arc.NewLhd.FileAttr&=~FA_ARCH;
/*
else
Arc.NewLhd.FileAttr|=FA_ARCH; //set archive bit for unpacked files (file is not backed up)
*/
#endif
if (!BrokenFile || Cmd->KeepBroken)
{

View File

@ -24,7 +24,6 @@ class CmdExtract
char Password[MAXPASSWORD];
bool PasswordAll;
bool PrevExtracted;
bool SignatureFound;
char DestFileName[NM];
wchar DestFileNameW[NM];
bool PasswordCancelled;
@ -36,6 +35,8 @@ class CmdExtract
bool ExtractCurrentFile(CommandData *Cmd,Archive &Arc,int HeaderSize,
bool &Repeat);
static void UnstoreFile(ComprDataIO &DataIO,Int64 DestUnpSize);
bool SignatureFound;
};
#endif

View File

@ -139,7 +139,7 @@ bool UpdateExistingShortName(char *Name,wchar *NameW)
char NewName[NM];
for (int I=0;I<10000;I+=123)
{
strncpy(NewName,Name,sizeof(NewName));
strncpyz(NewName,Name,ASIZE(NewName));
sprintf(PointToName(NewName),"rtmp%d",I);
if (!FileExist(NewName))
break;
@ -147,7 +147,7 @@ bool UpdateExistingShortName(char *Name,wchar *NameW)
if (FileExist(NewName))
return(false);
char FullName[NM];
strncpy(FullName,Name,sizeof(FullName));
strncpyz(FullName,Name,ASIZE(FullName));
strcpy(PointToName(FullName),PointToName(fd.Name));
if (!MoveFile(FullName,NewName))
return(false);

View File

@ -41,7 +41,7 @@ MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr)
}
void CreatePath(const char *Path,const wchar *PathW,bool SkipLastName)
bool CreatePath(const char *Path,const wchar *PathW,bool SkipLastName)
{
#ifdef _WIN_32
uint DirAttr=0;
@ -54,6 +54,7 @@ void CreatePath(const char *Path,const wchar *PathW,bool SkipLastName)
bool Wide=false;
#endif
bool IgnoreAscii=false;
bool Success=true;
const char *s=Path;
for (int PosW=0;;PosW++)
@ -95,12 +96,16 @@ void CreatePath(const char *Path,const wchar *PathW,bool SkipLastName)
mprintf(" %s",St(MOk));
#endif
}
else
Success=false;
}
if (!IgnoreAscii)
s=charnext(s);
}
if (!SkipLastName && !IsPathDiv(*PointToLastChar(Path)))
MakeDir(Path,PathW,DirAttr);
if (MakeDir(Path,PathW,DirAttr)!=MKDIR_SUCCESS)
Success=false;
return(Success);
}
@ -148,7 +153,7 @@ bool IsRemovable(const char *Name)
int Type=GetDriveType(*Root ? Root:NULL);
return(Type==DRIVE_REMOVABLE || Type==DRIVE_CDROM);
#elif defined(_EMX)
char Drive=toupper(Name[0]);
char Drive=etoupper(Name[0]);
return((Drive=='A' || Drive=='B') && Name[1]==':');
#else
return(false);
@ -176,7 +181,7 @@ Int64 GetFreeDisk(const char *Name)
}
if (pGetDiskFreeSpaceEx!=NULL)
{
GetFilePath(Name,Root);
GetFilePath(Name,Root,ASIZE(Root));
ULARGE_INTEGER uiTotalSize,uiTotalFree,uiUserFree;
uiUserFree.u.LowPart=uiUserFree.u.HighPart=0;
if (pGetDiskFreeSpaceEx(*Root ? Root:NULL,&uiUserFree,&uiTotalSize,&uiTotalFree) &&
@ -192,7 +197,7 @@ Int64 GetFreeDisk(const char *Name)
return(FreeSize);
#elif defined(_BEOS)
char Root[NM];
GetFilePath(Name,Root);
GetFilePath(Name,Root,ASIZE(Root));
dev_t Dev=dev_for_path(*Root ? Root:".");
if (Dev<0)
return(1457664);
@ -205,7 +210,7 @@ Int64 GetFreeDisk(const char *Name)
#elif defined(_UNIX)
return(1457664);
#elif defined(_EMX)
int Drive=(!isalpha(Name[0]) || Name[1]!=':') ? 0:toupper(Name[0])-'A'+1;
int Drive=(!isalpha(Name[0]) || Name[1]!=':') ? 0:etoupper(Name[0])-'A'+1;
if (_osmode == OS2_MODE)
{
FSALLOCATE fsa;
@ -465,7 +470,7 @@ char *MkTemp(char *Name)
#ifndef SFX_MODULE
uint CalcFileCRC(File *SrcFile,Int64 Size)
uint CalcFileCRC(File *SrcFile,Int64 Size,CALCCRC_SHOWMODE ShowMode)
{
SaveFilePos SavePos(*SrcFile);
const int BufSize=0x10000;
@ -474,6 +479,15 @@ uint CalcFileCRC(File *SrcFile,Int64 Size)
uint DataCRC=0xffffffff;
int ReadSize;
#if !defined(SILENT) && !defined(_WIN_CE)
Int64 FileLength=SrcFile->FileLength();
if (ShowMode!=CALCCRC_SHOWNONE)
{
mprintf(St(MCalcCRC));
mprintf(" ");
}
#endif
SrcFile->Seek(0,SEEK_SET);
while ((ReadSize=SrcFile->Read(&Data[0],int64to32(Size==INT64ERR ? Int64(BufSize):Min(Int64(BufSize),Size))))!=0)
@ -481,12 +495,20 @@ uint CalcFileCRC(File *SrcFile,Int64 Size)
++BlockCount;
if ((BlockCount & 15)==0)
{
#if !defined(SILENT) && !defined(_WIN_CE)
if (ShowMode==CALCCRC_SHOWALL)
mprintf("\b\b\b\b%3d%%",ToPercent(BlockCount*Int64(BufSize),FileLength));
#endif
Wait();
}
DataCRC=CRC(DataCRC,&Data[0],ReadSize);
if (Size!=INT64ERR)
Size-=ReadSize;
}
#if !defined(SILENT) && !defined(_WIN_CE)
if (ShowMode==CALCCRC_SHOWALL)
mprintf("\b\b\b\b ");
#endif
return(DataCRC^0xffffffff);
}
#endif

View File

@ -4,7 +4,7 @@
enum MKDIR_CODE {MKDIR_SUCCESS,MKDIR_ERROR,MKDIR_BADPATH};
MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,uint Attr);
void CreatePath(const char *Path,const wchar *PathW,bool SkipLastName);
bool CreatePath(const char *Path,const wchar *PathW,bool SkipLastName);
void SetDirTime(const char *Name,RarTime *ftm,RarTime *ftc,RarTime *fta);
bool IsRemovable(const char *Name);
Int64 GetFreeDisk(const char *Name);
@ -25,7 +25,9 @@ void ConvertNameToFull(const wchar *Src,wchar *Dest);
char* MkTemp(char *Name);
uint CalcFileCRC(File *SrcFile,Int64 Size=INT64ERR);
enum CALCCRC_SHOWMODE {CALCCRC_SHOWNONE,CALCCRC_SHOWTEXT,CALCCRC_SHOWALL};
uint CalcFileCRC(File *SrcFile,Int64 Size=INT64ERR,CALCCRC_SHOWMODE ShowMode=CALCCRC_SHOWNONE);
bool RenameFile(const char *SrcName,const wchar *SrcNameW,const char *DestName,const wchar *DestNameW);
bool DelFile(const char *Name);
bool DelFile(const char *Name,const wchar *NameW);

View File

@ -3,7 +3,7 @@
static bool IsUnicode(byte *Data,int Size);
bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
bool ConvertToAnsi,bool Unquote,bool SkipComments)
RAR_CHARSET SrcCharset,bool Unquote,bool SkipComments)
{
char FileName[NM];
if (Config)
@ -37,9 +37,15 @@ bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
memset(&Data[DataSize],0,5);
if (IsUnicode((byte *)&Data[0],DataSize))
if (SrcCharset==RCH_UNICODE ||
SrcCharset==RCH_DEFAULT && IsUnicode((byte *)&Data[0],DataSize))
{
wchar *CurStr=(wchar *)&Data[2];
// Unicode in native system format, can be more than 2 bytes per character
Array<wchar> DataW(Data.Size()/2+1);
for (int I=2;I<Data.Size()-1;I+=2)
DataW[(I-2)/2]=(wchar)Data[I]+(wchar)Data[I+1]*256;
wchar *CurStr=&DataW[0];
Array<char> AnsiName;
while (*CurStr!=0)
@ -114,7 +120,7 @@ bool ReadTextFile(char *Name,StringList *List,bool Config,bool AbortOnError,
}
}
#if defined(_WIN_32)
if (ConvertToAnsi)
if (SrcCharset==RCH_OEM)
OemToChar(CurStr,CurStr);
#endif
List->AddString(CurStr);
@ -133,7 +139,7 @@ bool IsUnicode(byte *Data,int Size)
if (Size<4 || Data[0]!=0xff || Data[1]!=0xfe)
return(false);
for (int I=2;I<Size;I++)
if (Data[I]<32)
if (Data[I]<32 && Data[I]!='\r' && Data[I]!='\n')
return(true);
return(false);
}

View File

@ -2,7 +2,7 @@
#define _RAR_FILESTR_
bool ReadTextFile(char *Name,StringList *List,bool Config,
bool AbortOnError=false,bool ConvertToAnsi=false,
bool AbortOnError=false,RAR_CHARSET SrcCharset=RCH_DEFAULT,
bool Unquote=false,bool SkipComments=false);
#endif

View File

@ -92,7 +92,16 @@ bool FindFile::Next(struct FindData *fd,bool GetSymLink)
{
char FullName[NM];
strcpy(FullName,FindMask);
strcpy(PointToName(FullName),ent->d_name);
*PointToName(FullName)=0;
if (strlen(FullName)+strlen(ent->d_name)>=ASIZE(FullName)-1)
{
#ifndef SILENT
Log(NULL,"\n%s%s",FullName,ent->d_name);
Log(NULL,St(MPathTooLong));
#endif
return(false);
}
strcat(FullName,ent->d_name);
if (!FastFind(FullName,NULL,fd,GetSymLink))
{
ErrHandler.OpenErrorMsg(FullName);

View File

@ -33,5 +33,6 @@ class BitInput
}
void faddbits(int Bits);
unsigned int fgetbits();
bool Overflow(int IncPtr) {return(InAddr+IncPtr>=MAX_SIZE);}
};
#endif

View File

@ -64,7 +64,7 @@
#define SKIP_IF_UNKNOWN 0x4000
#define LONG_BLOCK 0x8000
#define EARC_NEXT_VOLUME 0x0001
#define EARC_NEXT_VOLUME 0x0001 // not last volume
#define EARC_DATACRC 0x0002
#define EARC_REVSPACE 0x0004
#define EARC_VOLNUMBER 0x0008

View File

@ -118,7 +118,7 @@ void ListArchive(CommandData *Cmd)
itoa(TotalPackSize,PackSizeText);
mprintf("\n%5lu %16s %8s %3d%%",FileCount,UnpSizeText,
PackSizeText,ToPercent(TotalPackSize,TotalUnpSize));
PackSizeText,ToPercentUnlim(TotalPackSize,TotalUnpSize));
SumFileCount+=FileCount;
SumUnpSize+=TotalUnpSize;
SumPackSize+=TotalPackSize;
@ -162,7 +162,7 @@ void ListArchive(CommandData *Cmd)
itoa(SumUnpSize,UnpSizeText);
itoa(SumPackSize,PackSizeText);
mprintf("\n%5lu %16s %8s %3d%%\n",SumFileCount,UnpSizeText,
PackSizeText,ToPercent(SumPackSize,SumUnpSize));
PackSizeText,ToPercentUnlim(SumPackSize,SumUnpSize));
}
}
@ -231,7 +231,7 @@ void ListFileHeader(FileHeader &hd,bool Verbose,bool Technical,bool &TitleShown,
if (hd.Flags & LHD_SPLIT_AFTER)
mprintf(" -->");
else
mprintf("%3d%%",ToPercent(hd.FullPackSize,hd.FullUnpSize));
mprintf("%3d%%",ToPercentUnlim(hd.FullPackSize,hd.FullUnpSize));
char DateStr[50];
hd.mtime.GetText(DateStr,false);
@ -355,7 +355,7 @@ void ListOldSubHeader(Archive &Arc)
void ListNewSubHeader(CommandData *Cmd,Archive &Arc,bool Technical)
{
if (Technical && Arc.SubHead.CmpName(SUBHEAD_TYPE_CMT) &&
if (Arc.SubHead.CmpName(SUBHEAD_TYPE_CMT) &&
(Arc.SubHead.Flags & LHD_SPLIT_BEFORE)==0 && !Cmd->DisableComment)
{
Array<byte> CmtData;

View File

@ -73,7 +73,6 @@
#define MCHelpSwEP2 "\n ep2 Expand paths to full"
#define MCHelpSwEP3 "\n ep3 Expand paths to full including the drive letter"
#define MCHelpSwF "\n f Freshen files"
#define MCHelpSwFCU "\n fcu[file] Read archive comment from Unicode file"
#define MCHelpSwHP "\n hp[password] Encrypt both file data and headers"
#define MCHelpSwIDP "\n id[c,d,p,q] Disable messages"
#define MCHelpSwIEML "\n ieml[addr] Send archive by email"
@ -108,6 +107,7 @@
#define MCHelpSwRV "\n rv[N] Create recovery volumes"
#define MCHelpSwS "\n s[<N>,v[-],e] Create solid archive"
#define MCHelpSwSm "\n s- Disable solid archiving"
#define MCHelpSwSC "\n sc<chr>[obj] Specify the character set"
#define MCHelpSwSFX "\n sfx[name] Create SFX archive"
#define MCHelpSwSI "\n si[name] Read data from standard input (stdin)"
#define MCHelpSwSL "\n sl<size> Process files with size less than specified"
@ -345,3 +345,5 @@
#define MRecVolLimit "\nTotal number of usual and recovery volumes must not exceed 255"
#define MVolumeNumber "volume %d"
#define MCannotDelete "\nCannot delete %s"
#define MCalcCRC "\nCalculating the control sum"
#define MTooLargeSFXArc "\nWARNING: Too large SFX archive. Windows cannot run the executable file exceeding 4 GB."

View File

@ -50,8 +50,8 @@ bool CmpName(char *Wildcard,char *Name,int CmpPath)
return(true);
}
char Path1[NM],Path2[NM];
GetFilePath(Wildcard,Path1);
GetFilePath(Name,Path2);
GetFilePath(Wildcard,Path1,ASIZE(Path1));
GetFilePath(Name,Path2,ASIZE(Path1));
if (mstricompc(Wildcard,Path2,ForceCase)==0)
return(true);
if ((CmpPath==MATCH_PATH || CmpPath==MATCH_EXACTPATH) && mstricompc(Path1,Path2,ForceCase)!=0)
@ -94,8 +94,8 @@ bool CmpName(wchar *Wildcard,wchar *Name,int CmpPath)
return(true);
}
wchar Path1[NM],Path2[NM];
GetFilePath(Wildcard,Path1);
GetFilePath(Name,Path2);
GetFilePath(Wildcard,Path1,ASIZE(Path1));
GetFilePath(Name,Path2,ASIZE(Path2));
if ((CmpPath==MATCH_PATH || CmpPath==MATCH_EXACTPATH) && mstricompcw(Path1,Path2,ForceCase)!=0)
return(false);
if (CmpPath==MATCH_SUBPATH || CmpPath==MATCH_WILDSUBPATH)

View File

@ -21,6 +21,8 @@ enum OVERWRITE_MODE {
OVERWRITE_ASK,OVERWRITE_ALL,OVERWRITE_NONE,OVERWRITE_AUTORENAME
};
enum RAR_CHARSET { RCH_DEFAULT=0,RCH_ANSI,RCH_OEM,RCH_UNICODE };
#define MAX_FILTERS 16
enum FilterState {FILTER_DEFAULT=0,FILTER_AUTO,FILTER_FORCE,FILTER_DISABLE};
@ -49,7 +51,8 @@ class RAROptions
char ExtrPath[NM];
wchar ExtrPathW[NM];
char CommentFile[NM];
bool UnicodeComment;
RAR_CHARSET CommentCharset;
RAR_CHARSET FilelistCharset;
char ArcPath[NM];
char Password[MAXPASSWORD];
bool EncryptHeaders;

View File

@ -33,6 +33,7 @@
#include <prsht.h>
#ifndef _WIN_CE
#include <shlobj.h>
#include <winioctl.h>
#endif

View File

@ -44,12 +44,13 @@ char* ConvertPath(const char *SrcPath,char *DestPath)
const char *s=DestPtr;
if (s[0] && IsDriveDiv(s[1]))
s+=2;
if (s[0]=='\\' && s[1]=='\\')
{
const char *Slash=strchr(s+2,'\\');
if (Slash!=NULL && (Slash=strchr(Slash+1,'\\'))!=NULL)
s=Slash+1;
}
else
if (s[0]=='\\' && s[1]=='\\')
{
const char *Slash=strchr(s+2,'\\');
if (Slash!=NULL && (Slash=strchr(Slash+1,'\\'))!=NULL)
s=Slash+1;
}
for (const char *t=s;*t!=0;t++)
if (IsPathDiv(*t))
s=t+1;
@ -68,7 +69,7 @@ char* ConvertPath(const char *SrcPath,char *DestPath)
if (DestPath!=NULL)
{
char TmpStr[NM];
strncpy(TmpStr,DestPtr,sizeof(TmpStr)-1);
strncpyz(TmpStr,DestPtr,ASIZE(TmpStr));
strcpy(DestPath,TmpStr);
}
return((char *)DestPtr);
@ -235,7 +236,7 @@ bool IsDriveDiv(int Ch)
int GetPathDisk(const char *Path)
{
if (IsDiskLetter(Path))
return(toupper(*Path)-'A');
return(etoupper(*Path)-'A');
else
return(-1);
}
@ -257,23 +258,26 @@ void AddEndSlash(wchar *Path)
}
void GetFilePath(const char *FullName,char *Path)
// returns file path including the trailing path separator symbol
void GetFilePath(const char *FullName,char *Path,int MaxLength)
{
int PathLength=PointToName(FullName)-FullName;
int PathLength=Min(MaxLength-1,PointToName(FullName)-FullName);
strncpy(Path,FullName,PathLength);
Path[PathLength]=0;
}
void GetFilePath(const wchar *FullName,wchar *Path)
// returns file path including the trailing path separator symbol
void GetFilePath(const wchar *FullName,wchar *Path,int MaxLength)
{
const wchar *PathPtr=/*(*FullName && IsDriveDiv(FullName[1])) ? FullName+2:*/FullName;
int PathLength=PointToName(FullName)-FullName;
strncpyw(Path,PathPtr,PathLength);
int PathLength=Min(MaxLength-1,PointToName(FullName)-FullName);
strncpyw(Path,FullName,PathLength);
Path[PathLength]=0;
}
// removes name and returns file path without the trailing
// path separator symbol
void RemoveNameFromPath(char *Path)
{
char *Name=PointToName(Path);
@ -284,6 +288,8 @@ void RemoveNameFromPath(char *Path)
#ifndef SFX_MODULE
// removes name and returns file path without the trailing
// path separator symbol
void RemoveNameFromPath(wchar *Path)
{
wchar *Name=PointToName(Path);
@ -294,6 +300,31 @@ void RemoveNameFromPath(wchar *Path)
#endif
#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE)
void GetAppDataPath(char *Path)
{
LPMALLOC g_pMalloc;
SHGetMalloc(&g_pMalloc);
LPITEMIDLIST ppidl;
*Path=0;
bool Success=false;
if (SHGetSpecialFolderLocation(NULL,CSIDL_APPDATA,&ppidl)==NOERROR &&
SHGetPathFromIDList(ppidl,Path) && *Path!=0)
{
AddEndSlash(Path);
strcat(Path,"WinRAR");
Success=FileExist(Path) || MakeDir(Path,NULL,0)==MKDIR_SUCCESS;
}
if (!Success)
{
GetModuleFileName(NULL,Path,NM);
RemoveNameFromPath(Path);
}
g_pMalloc->Free(ppidl);
}
#endif
#ifndef SFX_MODULE
bool EnumConfigPaths(char *Path,int Number)
{
@ -320,7 +351,7 @@ bool EnumConfigPaths(char *Path,int Number)
char *EnvStr=getenv("HOME");
if (EnvStr==NULL)
return(false);
strncpy(Path,EnvStr,NM);
strncpy(Path,EnvStr,NM-1);
Path[NM-1]=0;
return(true);
}
@ -333,11 +364,18 @@ bool EnumConfigPaths(char *Path,int Number)
strcpy(Path,AltPath[Number]);
return(true);
#elif defined(_WIN_32)
if (Number!=0)
if (Number<0 || Number>1)
return(false);
GetModuleFileName(NULL,Path,NM);
RemoveNameFromPath(Path);
if (Number==0)
GetAppDataPath(Path);
else
{
GetModuleFileName(NULL,Path,NM);
RemoveNameFromPath(Path);
}
return(true);
#else
return(false);
#endif
@ -359,6 +397,7 @@ void GetConfigName(const char *Name,char *FullName,bool CheckExist)
#endif
// returns a pointer to rightmost digit of volume number
char* GetVolNumPart(char *ArcName)
{
char *ChPtr=ArcName+strlen(ArcName)-1;
@ -506,10 +545,32 @@ char* DosSlashToUnix(char *SrcName,char *DestName,uint MaxLength)
}
wchar* UnixSlashToDos(wchar *SrcName,wchar *DestName,uint MaxLength)
{
if (DestName!=NULL && DestName!=SrcName)
if (strlenw(SrcName)>=MaxLength)
{
*DestName=0;
return(DestName);
}
else
strcpyw(DestName,SrcName);
for (wchar *s=SrcName;*s!=0;s++)
{
if (*s=='/')
if (DestName==NULL)
*s='\\';
else
DestName[s-SrcName]='\\';
}
return(DestName==NULL ? SrcName:DestName);
}
bool IsFullPath(const char *Path)
{
char PathOnly[NM];
GetFilePath(Path,PathOnly);
GetFilePath(Path,PathOnly,ASIZE(PathOnly));
if (IsWildcard(PathOnly))
return(true);
#if defined(_WIN_32) || defined(_EMX)
@ -523,7 +584,7 @@ bool IsFullPath(const char *Path)
bool IsDiskLetter(const char *Path)
{
char Letter=toupper(Path[0]);
char Letter=etoupper(Path[0]);
return(Letter>='A' && Letter<='Z' && IsDriveDiv(Path[1]));
}

View File

@ -19,10 +19,11 @@ bool IsDriveDiv(int Ch);
int GetPathDisk(const char *Path);
void AddEndSlash(char *Path);
void AddEndSlash(wchar *Path);
void GetFilePath(const char *FullName,char *Path);
void GetFilePath(const wchar *FullName,wchar *Path);
void GetFilePath(const char *FullName,char *Path,int MaxLength);
void GetFilePath(const wchar *FullName,wchar *Path,int MaxLength);
void RemoveNameFromPath(char *Path);
void RemoveNameFromPath(wchar *Path);
void GetAppDataPath(char *Path);
bool EnumConfigPaths(char *Path,int Number);
void GetConfigName(const char *Name,char *FullName,bool CheckExist);
char* GetVolNumPart(char *ArcName);
@ -31,6 +32,7 @@ bool IsNameUsable(const char *Name);
void MakeNameUsable(char *Name,bool Extended);
char* UnixSlashToDos(char *SrcName,char *DestName=NULL,uint MaxLength=NM);
char* DosSlashToUnix(char *SrcName,char *DestName=NULL,uint MaxLength=NM);
wchar* UnixSlashToDos(wchar *SrcName,wchar *DestName=NULL,uint MaxLength=NM);
bool IsFullPath(const char *Path);
bool IsDiskLetter(const char *Path);
void GetPathRoot(const char *Path,char *Root);

View File

@ -46,6 +46,9 @@ int main(int argc, char *argv[])
#endif
#if defined(_WIN_32) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
bool ShutdownOnClose;
#endif
#ifdef ALLOW_EXCEPTIONS
try
@ -71,7 +74,7 @@ int main(int argc, char *argv[])
#endif
if (Switch!=NULL && Cmd.IsSwitch(Switch[0]))
{
int UpperCmd=toupper(Switch[1]);
int UpperCmd=etoupper(Switch[1]);
switch(UpperCmd)
{
case 'T':
@ -95,6 +98,9 @@ int main(int argc, char *argv[])
#endif
Cmd.ParseDone();
#if defined(_WIN_32) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
ShutdownOnClose=Cmd.Shutdown;
#endif
InitConsoleOptions(Cmd.MsgStream,Cmd.Sound);
InitLogOptions(Cmd.LogName);
@ -126,6 +132,10 @@ int main(int argc, char *argv[])
#endif
#if defined(_EMX) && !defined(_DJGPP)
uni_done();
#endif
#if defined(_WIN_32) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
if (ShutdownOnClose)
Shutdown();
#endif
return(ErrHandler.GetErrorCode());
}

View File

@ -20,6 +20,7 @@
#include "errhnd.hpp"
#include "array.hpp"
#include "timefn.hpp"
#include "options.hpp"
#include "headers.hpp"
#include "rarfn.hpp"
#include "pathfn.hpp"
@ -37,7 +38,6 @@
#include "savepos.hpp"
#include "getbits.hpp"
#include "rdwrfn.hpp"
#include "options.hpp"
#include "archive.hpp"
#include "match.hpp"
#include "cmddata.hpp"

View File

@ -20,16 +20,37 @@ void RarVM::Init()
Mem=new byte[VM_MEMSIZE+4];
}
/*********************************************************************
IS_VM_MEM macro checks if address belongs to VM memory pool (Mem).
Only Mem data are always low endian regardless of machine architecture,
so we need to convert them to native format when reading or writing.
VM registers have endianness of host machine.
**********************************************************************/
#define IS_VM_MEM(a) (((byte*)a)>=Mem && ((byte*)a)<Mem+VM_MEMSIZE)
inline uint RarVM::GetValue(bool ByteMode,uint *Addr)
{
if (ByteMode)
{
#ifdef BIG_ENDIAN
if (IS_VM_MEM(Addr))
return(*(byte *)Addr);
else
return(*Addr & 0xff);
#else
return(*(byte *)Addr);
#endif
}
else
{
#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT)
byte *B=(byte *)Addr;
return UINT32((uint)B[0]|((uint)B[1]<<8)|((uint)B[2]<<16)|((uint)B[3]<<24));
if (IS_VM_MEM(Addr))
{
byte *B=(byte *)Addr;
return UINT32((uint)B[0]|((uint)B[1]<<8)|((uint)B[2]<<16)|((uint)B[3]<<24));
}
else
return UINT32(*Addr);
#else
return UINT32(*Addr);
#endif
@ -46,14 +67,28 @@ inline uint RarVM::GetValue(bool ByteMode,uint *Addr)
inline void RarVM::SetValue(bool ByteMode,uint *Addr,uint Value)
{
if (ByteMode)
{
#ifdef BIG_ENDIAN
if (IS_VM_MEM(Addr))
*(byte *)Addr=Value;
else
*Addr=(*Addr & ~0xff)|(Value & 0xff);
#else
*(byte *)Addr=Value;
#endif
}
else
{
#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32)
((byte *)Addr)[0]=(byte)Value;
((byte *)Addr)[1]=(byte)(Value>>8);
((byte *)Addr)[2]=(byte)(Value>>16);
((byte *)Addr)[3]=(byte)(Value>>24);
if (IS_VM_MEM(Addr))
{
((byte *)Addr)[0]=(byte)Value;
((byte *)Addr)[1]=(byte)(Value>>8);
((byte *)Addr)[2]=(byte)(Value>>16);
((byte *)Addr)[3]=(byte)(Value>>24);
}
else
*(uint *)Addr=Value;
#else
*(uint32 *)Addr=Value;
#endif
@ -67,9 +102,16 @@ inline void RarVM::SetValue(bool ByteMode,uint *Addr,uint Value)
#endif
void RarVM::SetValue(uint *Addr,uint Value)
void RarVM::SetLowEndianValue(uint *Addr,uint Value)
{
SetValue(false,Addr,Value);
#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32)
((byte *)Addr)[0]=(byte)Value;
((byte *)Addr)[1]=(byte)(Value>>8);
((byte *)Addr)[2]=(byte)(Value>>16);
((byte *)Addr)[3]=(byte)(Value>>24);
#else
*(uint32 *)Addr=Value;
#endif
}
@ -88,7 +130,7 @@ void RarVM::Execute(VM_PreparedProgram *Prg)
unsigned int GlobalSize=Min(Prg->GlobalData.Size(),VM_GLOBALMEMSIZE);
if (GlobalSize)
memcpy(Mem+VM_GLOBALMEMADDR,&Prg->GlobalData[0],GlobalSize);
uint StaticSize=Min((uint)Prg->StaticData.Size(),VM_GLOBALMEMSIZE-GlobalSize);
unsigned int StaticSize=Min(Prg->StaticData.Size(),VM_GLOBALMEMSIZE-GlobalSize);
if (StaticSize)
memcpy(Mem+VM_GLOBALMEMADDR+GlobalSize,&Prg->StaticData[0],StaticSize);
@ -106,7 +148,8 @@ void RarVM::Execute(VM_PreparedProgram *Prg)
Prg->FilteredDataSize=NewBlockSize;
Prg->GlobalData.Reset();
uint DataSize=Min(GET_VALUE(false,(uint*)&Mem[VM_GLOBALMEMADDR+0x30]),VM_GLOBALMEMSIZE);
uint DataSize=Min(GET_VALUE(false,(uint*)&Mem[VM_GLOBALMEMADDR+0x30]),VM_GLOBALMEMSIZE-VM_FIXEDGLOBALSIZE);
if (DataSize!=0)
{
Prg->GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE);
@ -115,6 +158,14 @@ void RarVM::Execute(VM_PreparedProgram *Prg)
}
/*
Note:
Due to performance considerations RAR VM may set VM_FS, VM_FC, VM_FZ
incorrectly for byte operands. These flags are always valid only
for 32-bit operands. Check implementation of concrete VM command
to see if it sets flags right.
*/
#define SET_IP(IP) \
if ((IP)>=CodeSize) \
return(true); \
@ -171,7 +222,13 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
{
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
uint Result=UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2));
Flags=Result==0 ? VM_FZ:(Result<Value1)|(Result&VM_FS);
if (Cmd->ByteMode)
{
Result&=0xff;
Flags=(Result<Value1)|(Result==0 ? VM_FZ:((Result&0x80) ? VM_FS:0));
}
else
Flags=(Result<Value1)|(Result==0 ? VM_FZ:(Result&VM_FS));
SET_VALUE(Cmd->ByteMode,Op1,Result);
}
break;
@ -209,13 +266,15 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
case VM_JNZ:
if ((Flags & VM_FZ)==0)
{
SET_IP(GET_VALUE(false,(uint)Op1));
SET_IP(GET_VALUE(false,Op1));
continue;
}
break;
case VM_INC:
{
uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)+1);
if (Cmd->ByteMode)
Result&=0xff;
SET_VALUE(Cmd->ByteMode,Op1,Result);
Flags=Result==0 ? VM_FZ:Result&VM_FS;
}
@ -244,7 +303,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
break;
#endif
case VM_JMP:
SET_IP(GET_VALUE((uint)false,Op1));
SET_IP(GET_VALUE(false,Op1));
continue;
case VM_XOR:
{
@ -276,42 +335,42 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
case VM_JS:
if ((Flags & VM_FS)!=0)
{
SET_IP(GET_VALUE((uint)false,Op1));
SET_IP(GET_VALUE(false,Op1));
continue;
}
break;
case VM_JNS:
if ((Flags & VM_FS)==0)
{
SET_IP(GET_VALUE((uint)false,Op1));
SET_IP(GET_VALUE(false,Op1));
continue;
}
break;
case VM_JB:
if ((Flags & VM_FC)!=0)
{
SET_IP(GET_VALUE((uint)false,Op1));
SET_IP(GET_VALUE(false,Op1));
continue;
}
break;
case VM_JBE:
if ((Flags & (VM_FC|VM_FZ))!=0)
{
SET_IP(GET_VALUE((uint)false,Op1));
SET_IP(GET_VALUE(false,Op1));
continue;
}
break;
case VM_JA:
if ((Flags & (VM_FC|VM_FZ))==0)
{
SET_IP(GET_VALUE((uint)false,Op1));
SET_IP(GET_VALUE(false,Op1));
continue;
}
break;
case VM_JAE:
if ((Flags & VM_FC)==0)
{
SET_IP(GET_VALUE((uint)false,Op1));
SET_IP(GET_VALUE(false,Op1));
continue;
}
break;
@ -430,7 +489,9 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
uint FC=(Flags&VM_FC);
uint Result=UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2)+FC);
Flags=Result==0 ? VM_FZ:(Result<Value1 || Result==Value1 && FC)|(Result&VM_FS);
if (Cmd->ByteMode)
Result&=0xff;
Flags=(Result<Value1 || Result==Value1 && FC)|(Result==0 ? VM_FZ:(Result&VM_FS));
SET_VALUE(Cmd->ByteMode,Op1,Result);
}
break;
@ -439,7 +500,9 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
uint FC=(Flags&VM_FC);
uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)-FC);
Flags=Result==0 ? VM_FZ:(Result>Value1 || Result==Value1 && FC)|(Result&VM_FS);
if (Cmd->ByteMode)
Result&=0xff;
Flags=(Result>Value1 || Result==Value1 && FC)|(Result==0 ? VM_FZ:(Result&VM_FS));
SET_VALUE(Cmd->ByteMode,Op1,Result);
}
break;
@ -496,6 +559,10 @@ void RarVM::Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg)
#endif
uint DataFlag=fgetbits();
faddbits(1);
/* Read static data contained in DB operators. This data cannot be changed,
it is a part of VM code, not a filter parameter.
*/
if (DataFlag&0x8000)
{
int DataSize=ReadData(*this)+1;
@ -506,6 +573,7 @@ void RarVM::Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg)
faddbits(8);
}
}
while (InAddr<CodeSize)
{
Prg->Cmd.Add(1);
@ -699,8 +767,6 @@ void RarVM::Optimize(VM_PreparedProgram *Prg)
case VM_CMP:
Cmd->OpCode=Cmd->ByteMode ? VM_CMPB:VM_CMPD;
continue;
default:
break;
}
if ((VM_CmdFlags[Cmd->OpCode] & VMCF_CHFLAGS)==0)
continue;
@ -735,8 +801,6 @@ void RarVM::Optimize(VM_PreparedProgram *Prg)
case VM_NEG:
Cmd->OpCode=Cmd->ByteMode ? VM_NEGB:VM_NEGD;
continue;
default:
break;
}
}
}
@ -864,6 +928,10 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);
if (DataSize>=VM_GLOBALMEMADDR/2)
break;
// bytes from same channels are grouped to continual data blocks,
// so we need to place them back to their interleaving positions
for (int CurChannel=0;CurChannel<Channels;CurChannel++)
{
byte PrevByte=0;
@ -878,7 +946,7 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
byte *SrcData=Mem,*DestData=SrcData+DataSize;
const int Channels=3;
SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);
if (DataSize>=VM_GLOBALMEMADDR/2)
if (DataSize>=VM_GLOBALMEMADDR/2 || PosR<0)
break;
for (int CurChannel=0;CurChannel<Channels;CurChannel++)
{

View File

@ -66,7 +66,7 @@ struct VM_PreparedProgram
int CmdCount;
Array<byte> GlobalData;
Array<byte> StaticData;
Array<byte> StaticData; // static data contained in DB operators
uint InitR[7];
byte *FilteredData;
@ -101,7 +101,7 @@ class RarVM:private BitInput
void Init();
void Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg);
void Execute(VM_PreparedProgram *Prg);
void SetValue(uint *Addr,uint Value);
void SetLowEndianValue(uint *Addr,uint Value);
void SetMemory(unsigned int Pos,byte *Data,unsigned int DataSize);
static uint ReadData(BitInput &Inp);
};

View File

@ -52,23 +52,38 @@ void RawRead::Read(byte *SrcData,int Size)
void RawRead::Get(byte &Field)
{
Field=Data[ReadPos];
ReadPos++;
if (ReadPos<DataSize)
{
Field=Data[ReadPos];
ReadPos++;
}
else
Field=0;
}
void RawRead::Get(ushort &Field)
{
Field=Data[ReadPos]+(Data[ReadPos+1]<<8);
ReadPos+=2;
if (ReadPos+1<DataSize)
{
Field=Data[ReadPos]+(Data[ReadPos+1]<<8);
ReadPos+=2;
}
else
Field=0;
}
void RawRead::Get(uint &Field)
{
Field=Data[ReadPos]+(Data[ReadPos+1]<<8)+(Data[ReadPos+2]<<16)+
(Data[ReadPos+3]<<24);
ReadPos+=4;
if (ReadPos+3<DataSize)
{
Field=Data[ReadPos]+(Data[ReadPos+1]<<8)+(Data[ReadPos+2]<<16)+
(Data[ReadPos+3]<<24);
ReadPos+=4;
}
else
Field=0;
}
@ -83,15 +98,25 @@ void RawRead::Get8(Int64 &Field)
void RawRead::Get(byte *Field,int Size)
{
memcpy(Field,&Data[ReadPos],Size);
ReadPos+=Size;
if (ReadPos+Size-1<DataSize)
{
memcpy(Field,&Data[ReadPos],Size);
ReadPos+=Size;
}
else
memset(Field,0,Size);
}
void RawRead::Get(wchar *Field,int Size)
{
RawToWide(&Data[ReadPos],Field,Size);
ReadPos+=2*Size;
if (ReadPos+2*Size-1<DataSize)
{
RawToWide(&Data[ReadPos],Field,Size);
ReadPos+=2*Size;
}
else
memset(Field,0,2*Size);
}

View File

@ -92,7 +92,7 @@ int ComprDataIO::UnpRead(byte *Addr,uint Count)
Decrypt.Crypt(Addr,RetCode,(Decryption==15) ? NEW_CRYPT : OLD_DECODE);
else
if (Decryption==20)
for (int I=0;I<RetCode;I+=16)
for (uint I=0;I<RetCode;I+=16)
Decrypt.DecryptBlock20(&Addr[I]);
else
#endif

View File

@ -1,62 +1,62 @@
Portable UnRAR version
1. General
This package includes freeware Unrar C++ source and a few makefiles
(makefile.bcc, makefile.msc+msc.dep, makefile.unix). Unrar source
is subset of RAR and generated from RAR source automatically,
by a small program removing blocks like '#ifndef UNRAR ... #endif'.
Such method is not perfect and you may find some RAR related
stuff unnecessary in Unrar, especially in header files.
If you wish to port Unrar to a new platform, you may need to edit
'#define LITTLE_ENDIAN' in os.hpp and data type definitions
in rartypes.hpp.
if computer architecture does not allow not aligned data access,
you need to undefine ALLOW_NOT_ALIGNED_INT and define
STRICT_ALIGNMENT_REQUIRED in os.h. Note that it will increase memory
requirements.
If you use Borland C++ makefile (makefile.bcc), you need to define
BASEPATHCC environment (or makefile) variable containing
the path to Borland C++ installation.
Makefile.unix contains numerous compiler option sets.
GCC Linux is selected by default. If you need to compile Unrar
for other platforms, uncomment corresponding lines.
2. Unrar binaries
If you compiled Unrar for OS, which is not present in "Downloads"
and "RAR extras" on www.rarlab.com, we will appreciate if you send
us the compiled executable to place it to our site.
3. Acknowledgements
This source includes parts of code written by the following authors:
Dmitry Shkarin PPMII text compression
Dmitry Subbotin Carryless rangecoder
Szymon Stefanek AES encryption
Brian Gladman AES encryption
Steve Reid SHA-1 hash function
Marcus Herbert makefile.unix file
Tomasz Klim fixes for libunrar.so
4. Legal stuff
Unrar source may be used in any software to handle RAR archives
without limitations free of charge, but cannot be used to re-create
the RAR compression algorithm, which is proprietary. Distribution
of modified Unrar source in separate form or as a part of other
software is permitted, provided that it is clearly stated in
the documentation and source comments that the code may not be used
to develop a RAR (WinRAR) compatible archiver.
More detailed license text is available in license.txt.
Portable UnRAR version
1. General
This package includes freeware Unrar C++ source and a few makefiles
(makefile.bcc, makefile.msc+msc.dep, makefile.unix). Unrar source
is subset of RAR and generated from RAR source automatically,
by a small program removing blocks like '#ifndef UNRAR ... #endif'.
Such method is not perfect and you may find some RAR related
stuff unnecessary in Unrar, especially in header files.
If you wish to port Unrar to a new platform, you may need to edit
'#define LITTLE_ENDIAN' in os.hpp and data type definitions
in rartypes.hpp.
if computer architecture does not allow not aligned data access,
you need to undefine ALLOW_NOT_ALIGNED_INT and define
STRICT_ALIGNMENT_REQUIRED in os.h. Note that it will increase memory
requirements.
If you use Borland C++ makefile (makefile.bcc), you need to define
BASEPATHCC environment (or makefile) variable containing
the path to Borland C++ installation.
Makefile.unix contains numerous compiler option sets.
GCC Linux is selected by default. If you need to compile Unrar
for other platforms, uncomment corresponding lines.
2. Unrar binaries
If you compiled Unrar for OS, which is not present in "Downloads"
and "RAR extras" on www.rarlab.com, we will appreciate if you send
us the compiled executable to place it to our site.
3. Acknowledgements
This source includes parts of code written by the following authors:
Dmitry Shkarin PPMII v.H text compression
Dmitry Subbotin Carryless rangecoder
Szymon Stefanek AES encryption
Brian Gladman AES encryption
Steve Reid SHA-1 hash function
Marcus Herbert makefile.unix file
Tomasz Klim fixes for libunrar.so
4. Legal stuff
Unrar source may be used in any software to handle RAR archives
without limitations free of charge, but cannot be used to re-create
the RAR compression algorithm, which is proprietary. Distribution
of modified Unrar source in separate form or as a part of other
software is permitted, provided that it is clearly stated in
the documentation and source comments that the code may not be used
to develop a RAR (WinRAR) compatible archiver.
More detailed license text is available in license.txt.

View File

@ -11,7 +11,7 @@ RecVolumes::RecVolumes()
RecVolumes::~RecVolumes()
{
for (uint I=0;I<sizeof(SrcFile)/sizeof(SrcFile[0]);I++)
for (int I=0;I<sizeof(SrcFile)/sizeof(SrcFile[0]);I++)
delete SrcFile[I];
}
@ -132,7 +132,7 @@ bool RecVolumes::Restore(RAROptions *Cmd,const char *Name,
if (Dot==NULL)
continue;
bool WrongParam=false;
for (uint I=0;I<sizeof(P)/sizeof(P[0]);I++)
for (int I=0;I<sizeof(P)/sizeof(P[0]);I++)
{
do
{

View File

@ -59,6 +59,8 @@ bool ScanTree::PrepareMasks()
{
if (!FileMasks->GetString(CurMask,CurMaskW,sizeof(CurMask)))
return(false);
CurMask[ASIZE(CurMask)-1]=0;
CurMaskW[ASIZE(CurMaskW)-1]=0;
#ifdef _WIN_32
UnixSlashToDos(CurMask);
#endif

View File

@ -2,10 +2,16 @@
int ToPercent(Int64 N1,Int64 N2)
{
if (N2==0)
return(0);
if (N2<N1)
return(100);
return(ToPercentUnlim(N1,N2));
}
/* allows percent larger than 100 */
int ToPercentUnlim(Int64 N1,Int64 N2)
{
if (N2==0)
return(0);
return(int64to32(N1*100/N2));
}

View File

@ -2,6 +2,7 @@
#define _RAR_SMALLFN_
int ToPercent(Int64 N1,Int64 N2);
int ToPercentUnlim(Int64 N1,Int64 N2);
void RARInitData();
#endif

View File

@ -69,17 +69,17 @@ char* strupper(char *Str)
int stricomp(const char *Str1,const char *Str2)
{
char S1[NM*2],S2[NM*2];
strncpy(S1,Str1,sizeof(S1));
strncpy(S2,Str2,sizeof(S2));
strncpyz(S1,Str1,ASIZE(S1));
strncpyz(S2,Str2,ASIZE(S2));
return(strcmp(strupper(S1),strupper(S2)));
}
int strnicomp(const char *Str1,const char *Str2,int N)
{
char S1[512],S2[512];
strncpy(S1,Str1,sizeof(S1));
strncpy(S2,Str2,sizeof(S2));
char S1[NM*2],S2[NM*2];
strncpyz(S1,Str1,ASIZE(S1));
strncpyz(S2,Str2,ASIZE(S2));
return(strncmp(strupper(S1),strupper(S2),N));
}
@ -120,6 +120,17 @@ unsigned int loctoupper(byte ch)
}
// toupper with English only results. Avoiding Turkish i -> I conversion
// problem
int etoupper(int ch)
{
if (ch=='i')
return('I');
return(toupper(ch));
}
@ -163,3 +174,26 @@ int stricompcw(const wchar *Str1,const wchar *Str2)
#endif
}
#endif
// safe strncpy: copies maxlen-1 max and always returns zero terminated dest
char* strncpyz(char *dest, const char *src, size_t maxlen)
{
if (maxlen>0)
{
strncpy(dest,src,maxlen-1);
dest[maxlen-1]=0;
}
return(dest);
}
// safe strncpyw: copies maxlen-1 max and always returns zero terminated dest
wchar* strncpyzw(wchar *dest, const wchar *src, size_t maxlen)
{
if (maxlen>0)
{
strncpyw(dest,src,maxlen-1);
dest[maxlen-1]=0;
}
return(dest);
}

View File

@ -15,6 +15,11 @@ char* RemoveLF(char *Str);
unsigned int loctolower(byte ch);
unsigned int loctoupper(byte ch);
char* strncpyz(char *dest, const char *src, size_t maxlen);
wchar* strncpyzw(wchar *dest, const wchar *src, size_t maxlen);
int etoupper(int ch);
bool LowAscii(const char *Str);

View File

@ -96,13 +96,13 @@ char* StringList::GetString()
bool StringList::GetString(char **Str,wchar **StrW)
{
if (CurPos>=(uint)StringData.Size())
if (CurPos>=StringData.Size())
{
*Str=NULL;
return(false);
}
*Str=&StringData[CurPos];
if (PosDataItem<(uint)PosDataW.Size() && (uint)PosDataW[PosDataItem]==CurPos)
if (PosDataItem<PosDataW.Size() && PosDataW[PosDataItem]==CurPos)
{
PosDataItem++;
if (StrW!=NULL)
@ -119,7 +119,7 @@ bool StringList::GetString(char **Str,wchar **StrW)
char* StringList::GetString(unsigned int StringPos)
{
if (StringPos>=(uint)StringData.Size())
if (StringPos>=StringData.Size())
return(NULL);
return(&StringData[StringPos]);
}

View File

@ -77,3 +77,26 @@ void Wait()
#if defined(_WIN_32) && !defined(_WIN_CE) && !defined(SFX_MODULE) && !defined(SHELL_EXT)
#ifndef SHTDN_REASON_MAJOR_APPLICATION
#define SHTDN_REASON_MAJOR_APPLICATION 0x00040000
#define SHTDN_REASON_FLAG_PLANNED 0x80000000
#define SHTDN_REASON_MINOR_MAINTENANCE 0x00000001
#endif
void Shutdown()
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
{
LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken,FALSE,&tkp,0,(PTOKEN_PRIVILEGES)NULL,0);
}
ExitWindowsEx(EWX_SHUTDOWN|EWX_FORCE|EWX_POWEROFF,SHTDN_REASON_FLAG_PLANNED);
}
#endif

View File

@ -223,7 +223,7 @@ void RarTime::SetAgeText(char *TimeText)
Value=Value*10+Ch-'0';
else
{
switch(toupper(Ch))
switch(etoupper(Ch))
{
case 'D':
Seconds+=Value*24*3600;

View File

@ -18,6 +18,17 @@ bool WideToChar(const wchar *Src,char *Dest,int DestSize)
// TODO: haiku fix this!
if (wcstombs(Dest,Src,DestSize)==(size_t)-1)
RetCode=false;
if ((!RetCode || *Dest==0 && *Src!=0) && DestSize>NM && strlenw(Src)<NM)
{
/* Workaround for strange Linux Unicode functions bug.
Some of wcstombs and mbstowcs implementations in some situations
(we are yet to find out what it depends on) can return an empty
string and success code if buffer size value is too large.
*/
return(WideToChar(Src,Dest,NM));
}
#else
if (UnicodeEnabled())
{
@ -57,6 +68,16 @@ bool CharToWide(const char *Src,wchar *Dest,int DestSize)
// TODO: haiku fix this!
if (mbstowcs(Dest,Src,DestSize)==(size_t)-1)
RetCode=false;
if ((!RetCode || *Dest==0 && *Src!=0) && DestSize>NM && strlen(Src)<NM)
{
/* Workaround for strange Linux Unicode functions bug.
Some of wcstombs and mbstowcs implementations in some situations
(we are yet to find out what it depends on) can return an empty
string and success code if buffer size value is too large.
*/
return(CharToWide(Src,Dest,NM));
}
#else
if (UnicodeEnabled())
{
@ -300,8 +321,8 @@ inline int strnicmpw_w2c(const wchar *s1,const wchar *s2,int n)
wchar Wide1[NM*2],Wide2[NM*2];
strncpyw(Wide1,s1,sizeof(Wide1)/sizeof(Wide1[0])-1);
strncpyw(Wide2,s2,sizeof(Wide2)/sizeof(Wide2[0])-1);
Wide1[Min(sizeof(Wide1)/sizeof(Wide1[0])-1,(uint)n)]=0;
Wide2[Min(sizeof(Wide2)/sizeof(Wide2[0])-1,(uint)n)]=0;
Wide1[Min(sizeof(Wide1)/sizeof(Wide1[0])-1,n)]=0;
Wide2[Min(sizeof(Wide2)/sizeof(Wide2[0])-1,n)]=0;
char Ansi1[NM*2],Ansi2[NM*2];
WideToChar(Wide1,Ansi1,sizeof(Ansi1));
WideToChar(Wide2,Ansi2,sizeof(Ansi2));

View File

@ -18,10 +18,10 @@ int uni_init(int codepage);
int uni_done();
#endif
bool WideToChar(const wchar *Src,char *Dest,int DestSize=0x10000000);
bool CharToWide(const char *Src,wchar *Dest,int DestSize=0x10000000);
byte* WideToRaw(const wchar *Src,byte *Dest,int DestSize=0x10000000);
wchar* RawToWide(const byte *Src,wchar *Dest,int DestSize=0x10000000);
bool WideToChar(const wchar *Src,char *Dest,int DestSize=0x1000000);
bool CharToWide(const char *Src,wchar *Dest,int DestSize=0x1000000);
byte* WideToRaw(const wchar *Src,byte *Dest,int DestSize=0x1000000);
wchar* RawToWide(const byte *Src,wchar *Dest,int DestSize=0x1000000);
void WideToUtf(const wchar *Src,char *Dest,int DestSize);
void UtfToWide(const char *Src,wchar *Dest,int DestSize);
bool UnicodeEnabled();

View File

@ -492,28 +492,35 @@ bool Unpack::AddVMCode(unsigned int FirstByte,byte *Code,int CodeSize)
FiltPos--;
}
else
FiltPos=LastFilter;
FiltPos=LastFilter; // use the same filter as last time
if (FiltPos>Filters.Size() || FiltPos>OldFilterLengths.Size())
return(false);
LastFilter=FiltPos;
bool NewFilter=(FiltPos==Filters.Size());
UnpackFilter *StackFilter=new UnpackFilter; // new filter for PrgStack
UnpackFilter *Filter;
if (NewFilter)
if (NewFilter) // new filter code, never used before since VM reset
{
// too many different filters, corrupt archive
if (FiltPos>1024)
return(false);
Filters.Add(1);
Filters[Filters.Size()-1]=Filter=new UnpackFilter;
StackFilter->ParentFilter=Filters.Size()-1;
OldFilterLengths.Add(1);
Filter->ExecCount=0;
}
else
else // filter was used in the past
{
Filter=Filters[FiltPos];
StackFilter->ParentFilter=FiltPos;
Filter->ExecCount++;
}
UnpackFilter *StackFilter=new UnpackFilter;
int EmptyCount=0;
for (int I=0;I<PrgStack.Size();I++)
{
@ -550,7 +557,8 @@ bool Unpack::AddVMCode(unsigned int FirstByte,byte *Code,int CodeSize)
StackFilter->Prg.InitR[3]=VM_GLOBALMEMADDR;
StackFilter->Prg.InitR[4]=StackFilter->BlockLength;
StackFilter->Prg.InitR[5]=StackFilter->ExecCount;
if (FirstByte & 0x10)
if (FirstByte & 0x10) // set registers to optional parameters if any
{
unsigned int InitMask=Inp.fgetbits()>>9;
Inp.faddbits(7);
@ -558,6 +566,7 @@ bool Unpack::AddVMCode(unsigned int FirstByte,byte *Code,int CodeSize)
if (InitMask & (1<<I))
StackFilter->Prg.InitR[I]=RarVM::ReadData(Inp);
}
if (NewFilter)
{
uint VMCodeSize=RarVM::ReadData(Inp);
@ -566,6 +575,8 @@ bool Unpack::AddVMCode(unsigned int FirstByte,byte *Code,int CodeSize)
Array<byte> VMCode(VMCodeSize);
for (int I=0;I<VMCodeSize;I++)
{
if (Inp.Overflow(3))
return(false);
VMCode[I]=Inp.fgetbits()>>8;
Inp.faddbits(8);
}
@ -577,6 +588,7 @@ bool Unpack::AddVMCode(unsigned int FirstByte,byte *Code,int CodeSize)
int StaticDataSize=Filter->Prg.StaticData.Size();
if (StaticDataSize>0 && StaticDataSize<VM_GLOBALMEMSIZE)
{
// read statically defined data contained in DB commands
StackFilter->Prg.StaticData.Add(StaticDataSize);
memcpy(&StackFilter->Prg.StaticData[0],&Filter->Prg.StaticData[0],StaticDataSize);
}
@ -588,16 +600,18 @@ bool Unpack::AddVMCode(unsigned int FirstByte,byte *Code,int CodeSize)
}
byte *GlobalData=&StackFilter->Prg.GlobalData[0];
for (int I=0;I<7;I++)
VM.SetValue((uint *)&GlobalData[I*4],StackFilter->Prg.InitR[I]);
VM.SetValue((uint *)&GlobalData[0x1c],StackFilter->BlockLength);
VM.SetValue((uint *)&GlobalData[0x20],0);
VM.SetValue((uint *)&GlobalData[0x2c],StackFilter->ExecCount);
VM.SetLowEndianValue((uint *)&GlobalData[I*4],StackFilter->Prg.InitR[I]);
VM.SetLowEndianValue((uint *)&GlobalData[0x1c],StackFilter->BlockLength);
VM.SetLowEndianValue((uint *)&GlobalData[0x20],0);
VM.SetLowEndianValue((uint *)&GlobalData[0x2c],StackFilter->ExecCount);
memset(&GlobalData[0x30],0,16);
if (FirstByte & 8)
if (FirstByte & 8) // put data block passed as parameter if any
{
if (Inp.Overflow(3))
return(false);
uint DataSize=RarVM::ReadData(Inp);
if (DataSize>=0x10000)
if (DataSize>VM_GLOBALMEMSIZE-VM_FIXEDGLOBALSIZE)
return(false);
unsigned int CurSize=StackFilter->Prg.GlobalData.Size();
if (CurSize<DataSize+VM_FIXEDGLOBALSIZE)
@ -605,6 +619,8 @@ bool Unpack::AddVMCode(unsigned int FirstByte,byte *Code,int CodeSize)
byte *GlobalData=&StackFilter->Prg.GlobalData[VM_FIXEDGLOBALSIZE];
for (int I=0;I<DataSize;I++)
{
if (Inp.Overflow(3))
return(false);
GlobalData[I]=Inp.fgetbits()>>8;
Inp.faddbits(8);
}
@ -670,9 +686,29 @@ void Unpack::UnpWriteBuf()
VM.SetMemory(0,Window+BlockStart,FirstPartLength);
VM.SetMemory(FirstPartLength,Window,BlockEnd);
}
VM_PreparedProgram *ParentPrg=&Filters[flt->ParentFilter]->Prg;
VM_PreparedProgram *Prg=&flt->Prg;
if (ParentPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
{
// copy global data from previous script execution if any
Prg->GlobalData.Alloc(ParentPrg->GlobalData.Size());
memcpy(&Prg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
}
ExecuteCode(Prg);
if (Prg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
{
// save global data for next script execution
if (ParentPrg->GlobalData.Size()<Prg->GlobalData.Size())
ParentPrg->GlobalData.Alloc(Prg->GlobalData.Size());
memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&Prg->GlobalData[VM_FIXEDGLOBALSIZE],Prg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
}
else
ParentPrg->GlobalData.Reset();
byte *FilteredData=Prg->FilteredData;
unsigned int FilteredDataSize=Prg->FilteredDataSize;
@ -684,9 +720,33 @@ void Unpack::UnpWriteBuf()
if (NextFilter==NULL || NextFilter->BlockStart!=BlockStart ||
NextFilter->BlockLength!=FilteredDataSize || NextFilter->NextWindow)
break;
// apply several filters to same data block
VM.SetMemory(0,FilteredData,FilteredDataSize);
VM_PreparedProgram *NextPrg=&PrgStack[I+1]->Prg;
VM_PreparedProgram *ParentPrg=&Filters[NextFilter->ParentFilter]->Prg;
VM_PreparedProgram *NextPrg=&NextFilter->Prg;
if (ParentPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
{
// copy global data from previous script execution if any
NextPrg->GlobalData.Alloc(ParentPrg->GlobalData.Size());
memcpy(&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
}
ExecuteCode(NextPrg);
if (NextPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
{
// save global data for next script execution
if (ParentPrg->GlobalData.Size()<NextPrg->GlobalData.Size())
ParentPrg->GlobalData.Alloc(NextPrg->GlobalData.Size());
memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],NextPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
}
else
ParentPrg->GlobalData.Reset();
FilteredData=NextPrg->FilteredData;
FilteredDataSize=NextPrg->FilteredDataSize;
I++;
@ -723,8 +783,8 @@ void Unpack::ExecuteCode(VM_PreparedProgram *Prg)
if (Prg->GlobalData.Size()>0)
{
Prg->InitR[6]=int64to32(WrittenFileSize);
VM.SetValue((uint *)&Prg->GlobalData[0x24],int64to32(WrittenFileSize));
VM.SetValue((uint *)&Prg->GlobalData[0x28],int64to32(WrittenFileSize>>32));
VM.SetLowEndianValue((uint *)&Prg->GlobalData[0x24],int64to32(WrittenFileSize));
VM.SetLowEndianValue((uint *)&Prg->GlobalData[0x28],int64to32(WrittenFileSize>>32));
VM.Execute(Prg);
}
}

View File

@ -57,6 +57,11 @@ struct UnpackFilter
unsigned int BlockLength;
unsigned int ExecCount;
bool NextWindow;
// position of parent filter in Filters array used as prototype for filter
// in PrgStack array. Not defined for filters in Filters array.
unsigned int ParentFilter;
VM_PreparedProgram Prg;
};
@ -111,9 +116,17 @@ class Unpack:private BitInput
int PPMEscChar;
RarVM VM;
/* Filters code, one entry per filter */
Array<UnpackFilter*> Filters;
/* Filters stack, several entrances of same filter are possible */
Array<UnpackFilter*> PrgStack;
/* lengths of preceding blocks, one length per filter. Used to reduce
size required to write block length if lengths are repeating */
Array<int> OldFilterLengths;
int LastFilter;
bool TablesRead;

View File

@ -136,6 +136,9 @@ void Unpack::OldUnpWriteBuf()
}
#define GetShortLen1(pos) ((pos)==1 ? Buf60+3:ShortLen1[pos])
#define GetShortLen2(pos) ((pos)==3 ? Buf60+3:ShortLen2[pos])
void Unpack::ShortLZ()
{
static unsigned int ShortLen1[]={1,3,4,4,5,6,7,8,8,4,4,5,6,6,4,0};
@ -167,21 +170,22 @@ void Unpack::ShortLZ()
BitField>>=8;
ShortLen1[1]=ShortLen2[3]=Buf60+3;
// not thread safe, replaced by GetShortLen1 and GetShortLen2 macro
// ShortLen1[1]=ShortLen2[3]=Buf60+3;
if (AvrLn1<37)
{
for (Length=0;;Length++)
if (((BitField^ShortXor1[Length]) & (~(0xff>>ShortLen1[Length])))==0)
if (((BitField^ShortXor1[Length]) & (~(0xff>>GetShortLen1(Length))))==0)
break;
faddbits(ShortLen1[Length]);
faddbits(GetShortLen1(Length));
}
else
{
for (Length=0;;Length++)
if (((BitField^ShortXor2[Length]) & (~(0xff>>ShortLen2[Length])))==0)
if (((BitField^ShortXor2[Length]) & (~(0xff>>GetShortLen2(Length))))==0)
break;
faddbits(ShortLen2[Length]);
faddbits(GetShortLen2(Length));
}
if (Length >= 9)

View File

@ -4,10 +4,10 @@ resource app_flags B_MULTIPLE_LAUNCH | B_BACKGROUND_APP;
resource app_version {
major = 3,
middle = 6,
minor = 7,
middle = 7,
minor = 6,
variety = 0,
internal = 0,
short_info = "3.67",
long_info = "3.67 Alexander Roshal"
short_info = "3.76",
long_info = "3.76 Alexander Roshal"
};

View File

@ -1,6 +1,6 @@
#define RARVER_MAJOR 3
#define RARVER_MINOR 60
#define RARVER_BETA 7
#define RARVER_DAY 13
#define RARVER_MONTH 7
#define RARVER_YEAR 2006
#define RARVER_MINOR 70
#define RARVER_BETA 0
#define RARVER_DAY 22
#define RARVER_MONTH 5
#define RARVER_YEAR 2007

View File

@ -22,15 +22,43 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,char Comman
Arc.Close();
char NextName[NM];
wchar NextNameW[NM];
*NextNameW=0;
strcpy(NextName,Arc.FileName);
NextVolumeName(NextName,(Arc.NewMhd.Flags & MHD_NEWNUMBERING)==0 || Arc.OldFormat);
if (*Arc.FileNameW!=0)
{
// Copy incremented trailing low ASCII volume name part to Unicode name.
// It is simpler than also implementing Unicode version of NextVolumeName.
strcpyw(NextNameW,Arc.FileNameW);
char *NumPtr=GetVolNumPart(NextName);
// moving to first digit in volume number
while (NumPtr>NextName && isdigit(*NumPtr) && isdigit(*(NumPtr-1)))
NumPtr--;
// also copy the first character before volume number,
// because it can be changed when going from .r99 to .s00
if (NumPtr>NextName)
NumPtr--;
int CharsToCopy=strlen(NextName)-(NumPtr-NextName);
int DestPos=strlenw(NextNameW)-CharsToCopy;
if (DestPos>0)
{
CharToWide(NumPtr,NextNameW+DestPos,ASIZE(NextNameW)-DestPos-1);
NextNameW[ASIZE(NextNameW)-1]=0;
}
}
#if !defined(SFX_MODULE) && !defined(RARDLL)
bool RecoveryDone=false;
#endif
bool FailedOpen=false,OldSchemeTested=false;
while (!Arc.Open(NextName))
while (!Arc.Open(NextName,NextNameW))
{
if (!OldSchemeTested)
{
@ -41,6 +69,7 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,char Comman
if (Arc.Open(AltNextName))
{
strcpy(NextName,AltNextName);
*NextNameW=0;
break;
}
}
@ -94,6 +123,7 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,char Comman
FailedOpen=true;
break;
}
*NextNameW=0;
#endif
}
if (FailedOpen)

View File

@ -33,7 +33,8 @@ void ExtractStreams(Archive &Arc,char *FileName,wchar *FileNameW)
}
else
strcpy(StreamName,FileName);
if (strlen(StreamName)+strlen((char *)Arc.StreamHead.StreamName)>=sizeof(StreamName))
if (strlen(StreamName)+strlen((char *)Arc.StreamHead.StreamName)>=sizeof(StreamName) ||
Arc.StreamHead.StreamName[0]!=':')
{
#ifndef SILENT
Log(Arc.FileName,St(MStreamBroken),FileName);
@ -42,6 +43,8 @@ void ExtractStreams(Archive &Arc,char *FileName,wchar *FileNameW)
return;
}
ConvertPath((char *)Arc.StreamHead.StreamName+1,(char *)Arc.StreamHead.StreamName+1);
strcat(StreamName,(char *)Arc.StreamHead.StreamName);
FindData fd;
@ -119,6 +122,17 @@ void ExtractStreamsNew(Archive &Arc,char *FileName,wchar *FileNameW)
RawToWide(SrcName,DestName,DestSize);
DestName[DestSize]=0;
if (*DestName!=':')
{
#if !defined(SILENT) && !defined(SFX_MODULE)
Log(Arc.FileName,St(MStreamBroken),FileName);
#endif
ErrHandler.SetErrorCode(CRC_ERROR);
return;
}
ConvertPath(DestName+1,DestName+1);
FindData fd;
bool Found=FindFile::FastFind(FileName,FileNameW,&fd);
@ -133,6 +147,8 @@ void ExtractStreamsNew(Archive &Arc,char *FileName,wchar *FileNameW)
if (Found && HostFile.Open(FileName,FileNameW,true,true))
SetFileTime(HostFile.GetHandle(),&fd.ftCreationTime,&fd.ftLastAccessTime,
&fd.ftLastWriteTime);
if (fd.FileAttr & FILE_ATTRIBUTE_READONLY)
SetFileAttr(FileName,FileNameW,fd.FileAttr);
// Restoring original file attributes. Important if file was read only
// or did not have "Archive" attribute
SetFileAttr(FileName,FileNameW,fd.FileAttr);
}