mirror of
https://github.com/hashcat/hashcat.git
synced 2024-11-25 01:18:15 +00:00
Merge pull request #3734 from matrix/fix_rar_segfault_AppleSilicon
Dependencies: Updated unrar source to 6.2.7 | Fixed bug in 23800/unrar with Apple Silicon
This commit is contained in:
commit
11502c77e2
12
deps/unrar/UnRARDll.vcxproj
vendored
12
deps/unrar/UnRARDll.vcxproj
vendored
@ -138,7 +138,7 @@
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||
<StructMemberAlignment>Default</StructMemberAlignment>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||
@ -168,7 +168,7 @@
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||
<StructMemberAlignment>Default</StructMemberAlignment>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
|
||||
@ -198,7 +198,7 @@
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||
<StructMemberAlignment>Default</StructMemberAlignment>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
@ -239,7 +239,7 @@
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||
<StructMemberAlignment>Default</StructMemberAlignment>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
@ -274,7 +274,7 @@
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||
<StructMemberAlignment>Default</StructMemberAlignment>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
@ -315,7 +315,7 @@
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<StructMemberAlignment>4Bytes</StructMemberAlignment>
|
||||
<StructMemberAlignment>Default</StructMemberAlignment>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
|
47
deps/unrar/acknow.txt
vendored
47
deps/unrar/acknow.txt
vendored
@ -7,49 +7,16 @@
|
||||
for samples and ideas allowed to make Reed-Solomon coding
|
||||
more efficient.
|
||||
|
||||
* RAR text compression algorithm is based on Dmitry Shkarin PPMII
|
||||
* RAR4 text compression algorithm is based on Dmitry Shkarin PPMII
|
||||
and Dmitry Subbotin carryless rangecoder public domain source code.
|
||||
You may find it in ftp.elf.stuba.sk/pub/pc/pack.
|
||||
You can find it in ftp.elf.stuba.sk/pub/pc/pack.
|
||||
|
||||
* RAR encryption includes parts of code from Szymon Stefanek
|
||||
and Brian Gladman AES implementations also as Steve Reid SHA-1 source.
|
||||
* RAR encryption includes parts of public domain code
|
||||
from Szymon Stefanek AES and Steve Reid SHA-1 implementations.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
|
||||
All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The free distribution and use of this software in both source and binary
|
||||
form is allowed (with or without changes) provided that:
|
||||
|
||||
1. distributions of this source code include the above copyright
|
||||
notice, this list of conditions and the following disclaimer;
|
||||
|
||||
2. distributions in binary form include the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other associated materials;
|
||||
|
||||
3. the copyright holder's name is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
ALTERNATIVELY, provided that this notice is retained in full, this product
|
||||
may be distributed under the terms of the GNU General Public License (GPL),
|
||||
in which case the provisions of the GPL apply INSTEAD OF those given above.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
Source code of this package also as other cryptographic technology
|
||||
and computing project related links are available on Brian Gladman's
|
||||
web site: http://www.gladman.me.uk
|
||||
|
||||
* RAR uses CRC32 function based on Intel Slicing-by-8 algorithm.
|
||||
Original Intel Slicing-by-8 code is available here:
|
||||
* With exception of SFX modules, RAR uses CRC32 function based
|
||||
on Intel Slicing-by-8 algorithm. Original Intel Slicing-by-8 code
|
||||
is available here:
|
||||
|
||||
https://sourceforge.net/projects/slicing-by-8/
|
||||
|
||||
|
14
deps/unrar/archive.cpp
vendored
14
deps/unrar/archive.cpp
vendored
@ -3,15 +3,15 @@
|
||||
#include "arccmt.cpp"
|
||||
|
||||
|
||||
Archive::Archive(RAROptions *InitCmd)
|
||||
Archive::Archive(CommandData *InitCmd)
|
||||
{
|
||||
Cmd=NULL; // Just in case we'll have an exception in 'new' below.
|
||||
|
||||
DummyCmd=(InitCmd==NULL);
|
||||
Cmd=DummyCmd ? (new RAROptions):InitCmd;
|
||||
Cmd=DummyCmd ? (new CommandData):InitCmd;
|
||||
|
||||
OpenShared=Cmd->OpenShared;
|
||||
Format=RARFMT15;
|
||||
Format=RARFMT_NONE;
|
||||
Solid=false;
|
||||
Volume=false;
|
||||
MainComment=false;
|
||||
@ -31,9 +31,9 @@ Archive::Archive(RAROptions *InitCmd)
|
||||
NextBlockPos=0;
|
||||
|
||||
|
||||
memset(&MainHead,0,sizeof(MainHead));
|
||||
memset(&CryptHead,0,sizeof(CryptHead));
|
||||
memset(&EndArcHead,0,sizeof(EndArcHead));
|
||||
MainHead.Reset();
|
||||
CryptHead={};
|
||||
EndArcHead.Reset();
|
||||
|
||||
VolNumber=0;
|
||||
VolWrite=0;
|
||||
@ -231,7 +231,7 @@ bool Archive::IsArchive(bool EnableBroken)
|
||||
// first file header to set "comment" flag when reading service header.
|
||||
// Unless we are in silent mode, we need to know about presence of comment
|
||||
// immediately after IsArchive call.
|
||||
if (HeadersLeft && (!SilentOpen || !Encrypted))
|
||||
if (HeadersLeft && (!SilentOpen || !Encrypted) && IsSeekable())
|
||||
{
|
||||
int64 SavePos=Tell();
|
||||
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
|
||||
|
10
deps/unrar/archive.hpp
vendored
10
deps/unrar/archive.hpp
vendored
@ -32,8 +32,8 @@ class Archive:public File
|
||||
size_t ReadHeader14();
|
||||
size_t ReadHeader15();
|
||||
size_t ReadHeader50();
|
||||
void ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb);
|
||||
void RequestArcPassword();
|
||||
void ProcessExtra50(RawRead *Raw,size_t ExtraSize,const BaseBlock *bb);
|
||||
void RequestArcPassword(RarCheckPassword *SelPwd);
|
||||
void UnexpEndArcMsg();
|
||||
void BrokenHeaderMsg();
|
||||
void UnkEncVerMsg(const wchar *Name,const wchar *Info);
|
||||
@ -45,7 +45,7 @@ class Archive:public File
|
||||
#endif
|
||||
ComprDataIO SubDataIO;
|
||||
bool DummyCmd;
|
||||
RAROptions *Cmd;
|
||||
CommandData *Cmd;
|
||||
|
||||
|
||||
RarTime LatestTime;
|
||||
@ -58,7 +58,7 @@ class Archive:public File
|
||||
bool ProhibitQOpen;
|
||||
#endif
|
||||
public:
|
||||
Archive(RAROptions *InitCmd=NULL);
|
||||
Archive(CommandData *InitCmd=NULL);
|
||||
~Archive();
|
||||
static RARFORMAT IsSignature(const byte *D,size_t Size);
|
||||
bool IsArchive(bool EnableBroken);
|
||||
@ -83,7 +83,7 @@ class Archive:public File
|
||||
const wchar *Name,uint Flags);
|
||||
bool ReadSubData(Array<byte> *UnpData,File *DestFile,bool TestMode);
|
||||
HEADER_TYPE GetHeaderType() {return CurHeaderType;}
|
||||
RAROptions* GetRAROptions() {return Cmd;}
|
||||
CommandData* GetCommandData() {return Cmd;}
|
||||
void SetSilentOpen(bool Mode) {SilentOpen=Mode;}
|
||||
#if 0
|
||||
void GetRecoveryInfo(bool Required,int64 *Size,int *Percent);
|
||||
|
91
deps/unrar/arcread.cpp
vendored
91
deps/unrar/arcread.cpp
vendored
@ -100,6 +100,9 @@ void Archive::UnexpEndArcMsg()
|
||||
// If block positions are equal to file size, this is not an error.
|
||||
// It can happen when we reached the end of older RAR 1.5 archive,
|
||||
// which did not have the end of archive block.
|
||||
// We can't replace this check by checking that read size is exactly 0
|
||||
// in the beginning of file header, because in this case the read position
|
||||
// still can be beyond the end of archive.
|
||||
if (CurBlockPos!=ArcSize || NextBlockPos!=ArcSize)
|
||||
{
|
||||
uiMsg(UIERROR_UNEXPEOF,FileName);
|
||||
@ -145,7 +148,7 @@ size_t Archive::ReadHeader15()
|
||||
#ifdef RAR_NOCRYPT // For rarext.dll and unrar_nocrypt.dll.
|
||||
return 0;
|
||||
#else
|
||||
RequestArcPassword();
|
||||
RequestArcPassword(NULL);
|
||||
|
||||
byte Salt[SIZE_SALT30];
|
||||
if (Read(Salt,SIZE_SALT30)!=SIZE_SALT30)
|
||||
@ -251,7 +254,11 @@ size_t Archive::ReadHeader15()
|
||||
hd->SplitAfter=(hd->Flags & LHD_SPLIT_AFTER)!=0;
|
||||
hd->Encrypted=(hd->Flags & LHD_PASSWORD)!=0;
|
||||
hd->SaltSet=(hd->Flags & LHD_SALT)!=0;
|
||||
|
||||
// RAR versions earlier than 2.0 do not set the solid flag
|
||||
// in file header. They use only a global solid archive flag.
|
||||
hd->Solid=FileBlock && (hd->Flags & LHD_SOLID)!=0;
|
||||
|
||||
hd->SubBlock=!FileBlock && (hd->Flags & LHD_SOLID)!=0;
|
||||
hd->Dir=(hd->Flags & LHD_WINDOWMASK)==LHD_DIRECTORY;
|
||||
hd->WinSize=hd->Dir ? 0:0x10000<<((hd->Flags & LHD_WINDOWMASK)>>5);
|
||||
@ -558,6 +565,13 @@ size_t Archive::ReadHeader50()
|
||||
return 0;
|
||||
#else
|
||||
|
||||
if (Cmd->SkipEncrypted)
|
||||
{
|
||||
uiMsg(UIMSG_SKIPENCARC,FileName);
|
||||
FailedHeaderDecryption=true; // Suppress error messages and quit quietly.
|
||||
return 0;
|
||||
}
|
||||
|
||||
byte HeadersInitV[SIZE_INITV];
|
||||
if (Read(HeadersInitV,SIZE_INITV)!=SIZE_INITV)
|
||||
{
|
||||
@ -570,14 +584,20 @@ size_t Archive::ReadHeader50()
|
||||
// in -p<pwd> to not stop batch processing for encrypted archives.
|
||||
bool GlobalPassword=Cmd->Password.IsSet() || uiIsGlobalPasswordSet();
|
||||
|
||||
RarCheckPassword CheckPwd;
|
||||
if (CryptHead.UsePswCheck && !BrokenHeader)
|
||||
CheckPwd.Set(CryptHead.Salt,HeadersInitV,CryptHead.Lg2Count,CryptHead.PswCheck);
|
||||
|
||||
while (true) // Repeat the password prompt for wrong passwords.
|
||||
{
|
||||
RequestArcPassword();
|
||||
RequestArcPassword(CheckPwd.IsSet() ? &CheckPwd:NULL);
|
||||
|
||||
byte PswCheck[SIZE_PSWCHECK];
|
||||
HeadersCrypt.SetCryptKeys(false,CRYPT_RAR50,&Cmd->Password,CryptHead.Salt,HeadersInitV,CryptHead.Lg2Count,NULL,PswCheck);
|
||||
// Verify password validity.
|
||||
if (CryptHead.UsePswCheck && memcmp(PswCheck,CryptHead.PswCheck,SIZE_PSWCHECK)!=0)
|
||||
// Verify password validity. If header is damaged, we cannot rely on
|
||||
// password check value, because it can be damaged too.
|
||||
if (CryptHead.UsePswCheck && !BrokenHeader &&
|
||||
memcmp(PswCheck,CryptHead.PswCheck,SIZE_PSWCHECK)!=0)
|
||||
{
|
||||
if (GlobalPassword) // For -p<pwd> or Ctrl+P.
|
||||
{
|
||||
@ -843,8 +863,6 @@ size_t Archive::ReadHeader50()
|
||||
hd->Dir=(hd->FileFlags & FHFL_DIRECTORY)!=0;
|
||||
hd->WinSize=hd->Dir ? 0:size_t(0x20000)<<((CompInfo>>10)&0xf);
|
||||
|
||||
hd->CryptMethod=hd->Encrypted ? CRYPT_RAR50:CRYPT_NONE;
|
||||
|
||||
char FileName[NM*4];
|
||||
size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1);
|
||||
Raw.GetB((byte *)FileName,ReadNameSize);
|
||||
@ -868,20 +886,6 @@ size_t Archive::ReadHeader50()
|
||||
if (!FileBlock && hd->CmpName(SUBHEAD_TYPE_CMT))
|
||||
MainComment=true;
|
||||
|
||||
#if 0
|
||||
// For RAR5 format we read the user specified recovery percent here.
|
||||
// It would be useful to do it for shell extension too, so we display
|
||||
// the correct recovery record size in archive properties. But then
|
||||
// we would need to include the entire recovery record processing
|
||||
// code to shell extension, which is not done now.
|
||||
if (!FileBlock && hd->CmpName(SUBHEAD_TYPE_RR) && hd->SubData.Size()>0)
|
||||
{
|
||||
RecoveryPercent=hd->SubData[0];
|
||||
RSBlockHeader Header;
|
||||
GetRRInfo(this,&Header);
|
||||
RecoverySize=Header.RecSectionSize*Header.RecCount;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (BadCRC) // Add the file name to broken header message displayed above.
|
||||
uiMsg(UIERROR_FHEADERBROKEN,Archive::FileName,hd->FileName);
|
||||
@ -904,7 +908,7 @@ size_t Archive::ReadHeader50()
|
||||
|
||||
|
||||
#if !defined(RAR_NOCRYPT)
|
||||
void Archive::RequestArcPassword()
|
||||
void Archive::RequestArcPassword(RarCheckPassword *CheckPwd)
|
||||
{
|
||||
if (!Cmd->Password.IsSet())
|
||||
{
|
||||
@ -934,7 +938,7 @@ void Archive::RequestArcPassword()
|
||||
ErrHandler.Exit(RARX_USERBREAK);
|
||||
}
|
||||
#else
|
||||
if (!uiGetPassword(UIPASSWORD_ARCHIVE,FileName,&Cmd->Password))
|
||||
if (!uiGetPassword(UIPASSWORD_ARCHIVE,FileName,&Cmd->Password,CheckPwd))
|
||||
{
|
||||
Close();
|
||||
uiMsg(UIERROR_INCERRCOUNT); // Prevent archive deleting if delete after extraction is on.
|
||||
@ -947,7 +951,7 @@ void Archive::RequestArcPassword()
|
||||
#endif
|
||||
|
||||
|
||||
void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
|
||||
void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,const BaseBlock *bb)
|
||||
{
|
||||
// Read extra data from the end of block skipping any fields before it.
|
||||
size_t ExtraStart=Raw->Size()-ExtraSize;
|
||||
@ -970,7 +974,9 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
|
||||
if (bb->HeaderType==HEAD_MAIN)
|
||||
{
|
||||
MainHeader *hd=(MainHeader *)bb;
|
||||
if (FieldType==MHEXTRA_LOCATOR)
|
||||
switch(FieldType)
|
||||
{
|
||||
case MHEXTRA_LOCATOR:
|
||||
{
|
||||
hd->Locator=true;
|
||||
uint Flags=(uint)Raw->GetV();
|
||||
@ -987,6 +993,39 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
|
||||
hd->RROffset=Offset+CurBlockPos;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MHEXTRA_METADATA:
|
||||
{
|
||||
uint Flags=(uint)Raw->GetV();
|
||||
if ((Flags & MHEXTRA_METADATA_NAME)!=0)
|
||||
{
|
||||
uint64 NameSize=Raw->GetV();
|
||||
if (NameSize<0x10000) // Prevent excessive allocation.
|
||||
{
|
||||
std::vector<char> NameU((size_t)NameSize); // UTF-8 name.
|
||||
Raw->GetB(&NameU[0],(size_t)NameSize);
|
||||
// If starts from 0, the name was longer than reserved space
|
||||
// when saving this extra field.
|
||||
if (NameU[0]!=0)
|
||||
{
|
||||
NameU.push_back(0);
|
||||
std::vector<wchar> NameW(NameU.size()*4);
|
||||
UtfToWide(&NameU[0],&NameW[0],NameW.size());
|
||||
hd->OrigName.assign(&NameW[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((Flags & MHEXTRA_METADATA_CTIME)!=0)
|
||||
if ((Flags & MHEXTRA_METADATA_UNIXTIME)!=0)
|
||||
if ((Flags & MHEXTRA_METADATA_UNIX_NS)!=0)
|
||||
hd->OrigTime.SetUnixNS(Raw->Get8());
|
||||
else
|
||||
hd->OrigTime.SetUnix((time_t)Raw->Get4());
|
||||
else
|
||||
hd->OrigTime.SetWin(Raw->Get8());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bb->HeaderType==HEAD_FILE || bb->HeaderType==HEAD_SERVICE)
|
||||
@ -1441,7 +1480,9 @@ bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile,bool TestMode)
|
||||
{
|
||||
if (SubHead.UnpSize>0x1000000)
|
||||
{
|
||||
// So huge allocation must never happen in valid archives.
|
||||
// Prevent the excessive allocation. When reading to memory, normally
|
||||
// this function operates with reasonably small blocks, such as
|
||||
// the archive comment, NTFS ACL or "Zone.Identifier" NTFS stream.
|
||||
uiMsg(UIERROR_SUBHEADERUNKNOWN,FileName);
|
||||
return false;
|
||||
}
|
||||
|
30
deps/unrar/array.hpp
vendored
30
deps/unrar/array.hpp
vendored
@ -10,7 +10,6 @@ template <class T> class Array
|
||||
size_t BufSize;
|
||||
size_t AllocSize;
|
||||
size_t MaxSize;
|
||||
bool Secure; // Clean memory if true.
|
||||
public:
|
||||
Array();
|
||||
Array(size_t Size);
|
||||
@ -24,14 +23,13 @@ template <class T> class Array
|
||||
void Alloc(size_t Items);
|
||||
void Reset();
|
||||
void SoftReset();
|
||||
void operator = (Array<T> &Src);
|
||||
Array<T>& operator = (const Array<T> &Src);
|
||||
void Push(T Item);
|
||||
void Append(T *Item,size_t Count);
|
||||
T* Addr(size_t Item) {return Buffer+Item;}
|
||||
void SetMaxSize(size_t Size) {MaxSize=Size;}
|
||||
T* Begin() {return Buffer;}
|
||||
T* End() {return Buffer==NULL ? NULL:Buffer+BufSize;}
|
||||
void SetSecure() {Secure=true;}
|
||||
};
|
||||
|
||||
|
||||
@ -41,7 +39,6 @@ template <class T> void Array<T>::CleanData()
|
||||
BufSize=0;
|
||||
AllocSize=0;
|
||||
MaxSize=0;
|
||||
Secure=false;
|
||||
}
|
||||
|
||||
|
||||
@ -71,11 +68,7 @@ template <class T> Array<T>::Array(const Array &Src)
|
||||
template <class T> Array<T>::~Array()
|
||||
{
|
||||
if (Buffer!=NULL)
|
||||
{
|
||||
if (Secure)
|
||||
cleandata(Buffer,AllocSize*sizeof(T));
|
||||
free(Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -111,25 +104,9 @@ template <class T> void Array<T>::Add(size_t Items)
|
||||
size_t Suggested=AllocSize+AllocSize/4+32;
|
||||
size_t NewSize=Max(BufSize,Suggested);
|
||||
|
||||
T *NewBuffer;
|
||||
if (Secure)
|
||||
{
|
||||
NewBuffer=(T *)malloc(NewSize*sizeof(T));
|
||||
T *NewBuffer=(T *)realloc(Buffer,NewSize*sizeof(T));
|
||||
if (NewBuffer==NULL)
|
||||
ErrHandler.MemoryError();
|
||||
if (Buffer!=NULL)
|
||||
{
|
||||
memcpy(NewBuffer,Buffer,AllocSize*sizeof(T));
|
||||
cleandata(Buffer,AllocSize*sizeof(T));
|
||||
free(Buffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NewBuffer=(T *)realloc(Buffer,NewSize*sizeof(T));
|
||||
if (NewBuffer==NULL)
|
||||
ErrHandler.MemoryError();
|
||||
}
|
||||
Buffer=NewBuffer;
|
||||
AllocSize=NewSize;
|
||||
}
|
||||
@ -165,12 +142,13 @@ template <class T> void Array<T>::SoftReset()
|
||||
}
|
||||
|
||||
|
||||
template <class T> void Array<T>::operator =(Array<T> &Src)
|
||||
template <class T> Array<T>& Array<T>::operator =(const Array<T> &Src)
|
||||
{
|
||||
Reset();
|
||||
Alloc(Src.BufSize);
|
||||
if (Src.BufSize!=0)
|
||||
memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
9
deps/unrar/blake2s.hpp
vendored
9
deps/unrar/blake2s.hpp
vendored
@ -20,10 +20,15 @@ enum blake2s_constant
|
||||
// 'new' operator.
|
||||
struct blake2s_state
|
||||
{
|
||||
enum { BLAKE_ALIGNMENT = 64 };
|
||||
// Use constexpr instead of enums, because otherwise clang -std=c++20
|
||||
// issues a warning about "arithmetic between different enumeration types"
|
||||
// in ubuf[BLAKE_DATA_SIZE + BLAKE_ALIGNMENT] declaration.
|
||||
static constexpr size_t BLAKE_ALIGNMENT = 64;
|
||||
|
||||
// buffer and uint32 h[8], t[2], f[2];
|
||||
enum { BLAKE_DATA_SIZE = 48 + 2 * BLAKE2S_BLOCKBYTES };
|
||||
// 2 * BLAKE2S_BLOCKBYTES is the buf size in blake2_code_20140114.zip.
|
||||
// It might differ in later versions.
|
||||
static constexpr size_t BLAKE_DATA_SIZE = 48 + 2 * BLAKE2S_BLOCKBYTES;
|
||||
|
||||
byte ubuf[BLAKE_DATA_SIZE + BLAKE_ALIGNMENT];
|
||||
|
||||
|
50
deps/unrar/cmddata.cpp
vendored
50
deps/unrar/cmddata.cpp
vendored
@ -26,9 +26,10 @@ void CommandData::Init()
|
||||
FileArgs.Reset();
|
||||
ExclArgs.Reset();
|
||||
InclArgs.Reset();
|
||||
StoreArgs.Reset();
|
||||
ArcNames.Reset();
|
||||
NextVolSizes.Reset();
|
||||
StoreArgs.Reset();
|
||||
Password.Clean();
|
||||
NextVolSizes.clear();
|
||||
}
|
||||
|
||||
|
||||
@ -108,6 +109,11 @@ void CommandData::ParseArg(wchar *Arg)
|
||||
// 'S' can contain SFX name, which case is important in Unix.
|
||||
if (*Command!='I' && *Command!='S')
|
||||
wcsupper(Command);
|
||||
if (*Command=='P') // Enforce -idq for print command.
|
||||
{
|
||||
MsgStream=MSG_ERRONLY;
|
||||
SetConsoleMsgStream(MSG_ERRONLY);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (*ArcName==0)
|
||||
@ -309,6 +315,21 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
case 'I':
|
||||
IgnoreGeneralAttr=true;
|
||||
break;
|
||||
case 'M':
|
||||
switch(toupperw(Switch[2]))
|
||||
{
|
||||
case 0:
|
||||
case 'S':
|
||||
ArcMetadata=ARCMETA_SAVE;
|
||||
break;
|
||||
case 'R':
|
||||
ArcMetadata=ARCMETA_RESTORE;
|
||||
break;
|
||||
default:
|
||||
BadSwitch(Switch);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'N': // Reserved for archive name.
|
||||
break;
|
||||
case 'O':
|
||||
@ -373,6 +394,9 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
case '3':
|
||||
ExclPath=EXCL_ABSPATH;
|
||||
break;
|
||||
case '4':
|
||||
wcsncpyz(ExclArcPath,Switch+3,ASIZE(ExclArcPath));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -399,13 +423,15 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
EncryptHeaders=true;
|
||||
if (Switch[2]!=0)
|
||||
{
|
||||
if (wcslen(Switch+2)>=MAXPASSWORD)
|
||||
uiMsg(UIERROR_TRUNCPSW,MAXPASSWORD-1);
|
||||
Password.Set(Switch+2);
|
||||
cleandata((void *)Switch,wcslen(Switch)*sizeof(Switch[0]));
|
||||
}
|
||||
else
|
||||
if (!Password.IsSet())
|
||||
{
|
||||
uiGetPassword(UIPASSWORD_GLOBAL,NULL,&Password);
|
||||
uiGetPassword(UIPASSWORD_GLOBAL,NULL,&Password,NULL);
|
||||
eprintf(L"\n");
|
||||
}
|
||||
break;
|
||||
@ -561,6 +587,10 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
break;
|
||||
case 'D':
|
||||
break;
|
||||
case 'E':
|
||||
if (toupperw(Switch[2])=='S' && Switch[3]==0)
|
||||
SkipEncrypted=true;
|
||||
break;
|
||||
case 'S':
|
||||
{
|
||||
wchar StoreNames[1024];
|
||||
@ -648,6 +678,10 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
AllowIncompatNames=true;
|
||||
break;
|
||||
#endif
|
||||
case 'P':
|
||||
wcsncpyz(ExtrPath,Switch+2,ASIZE(ExtrPath));
|
||||
AddEndSlash(ExtrPath,ASIZE(ExtrPath));
|
||||
break;
|
||||
case 'R':
|
||||
Overwrite=OVERWRITE_AUTORENAME;
|
||||
break;
|
||||
@ -667,11 +701,13 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
case 'P':
|
||||
if (Switch[1]==0)
|
||||
{
|
||||
uiGetPassword(UIPASSWORD_GLOBAL,NULL,&Password);
|
||||
uiGetPassword(UIPASSWORD_GLOBAL,NULL,&Password,NULL);
|
||||
eprintf(L"\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wcslen(Switch+1)>=MAXPASSWORD)
|
||||
uiMsg(UIERROR_TRUNCPSW,MAXPASSWORD-1);
|
||||
Password.Set(Switch+1);
|
||||
cleandata((void *)Switch,wcslen(Switch)*sizeof(Switch[0]));
|
||||
}
|
||||
@ -752,6 +788,10 @@ void CommandData::ProcessSwitch(const wchar *Switch)
|
||||
case 'D':
|
||||
Solid|=SOLID_VOLUME_DEPENDENT;
|
||||
break;
|
||||
case 'I':
|
||||
ProhibitConsoleInput();
|
||||
wcsncpyz(UseStdin,Switch[2] ? Switch+2:L"stdin",ASIZE(UseStdin));
|
||||
break;
|
||||
case 'L':
|
||||
if (IsDigit(Switch[2]))
|
||||
FileSizeLess=atoilw(Switch+2);
|
||||
@ -935,7 +975,7 @@ void CommandData::ProcessCommand()
|
||||
wcsncpyz(ArcName,Name,ASIZE(ArcName));
|
||||
}
|
||||
|
||||
if (wcschr(L"AFUMD",*Command)==NULL)
|
||||
if (wcschr(L"AFUMD",*Command)==NULL && *UseStdin==0)
|
||||
{
|
||||
if (GenerateArcName)
|
||||
{
|
||||
|
8
deps/unrar/cmddata.hpp
vendored
8
deps/unrar/cmddata.hpp
vendored
@ -2,7 +2,7 @@
|
||||
#define _RAR_CMDDATA_
|
||||
|
||||
|
||||
#define DefaultStoreList L"7z;ace;arj;bz2;cab;gz;jpeg;jpg;lha;lz;lzh;mp3;rar;taz;tgz;xz;z;zip;zipx"
|
||||
#define DefaultStoreList L"7z;ace;arj;bz2;cab;gz;jpeg;jpg;lha;lz;lzh;mp3;rar;taz;tbz;tbz2;tgz;txz;xz;z;zip;zipx;zst;tzst"
|
||||
|
||||
enum RAR_CMD_LIST_MODE {RCLM_AUTO,RCLM_REJECT_LISTS,RCLM_ACCEPT_LISTS};
|
||||
|
||||
@ -50,7 +50,7 @@ class CommandData:public RAROptions
|
||||
bool GetArcName(wchar *Name,int MaxSize);
|
||||
bool CheckWinSize();
|
||||
|
||||
int GetRecoverySize(const wchar *Str,int DefSize);
|
||||
int GetRecoverySize(const wchar *CmdStr,const wchar *Value,int DefSize);
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
void ReportWrongSwitches(RARFORMAT Format);
|
||||
@ -65,6 +65,10 @@ class CommandData:public RAROptions
|
||||
StringList InclArgs;
|
||||
StringList ArcNames;
|
||||
StringList StoreArgs;
|
||||
|
||||
SecPassword Password;
|
||||
|
||||
std::vector<int64> NextVolSizes;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
6
deps/unrar/cmdfilter.cpp
vendored
6
deps/unrar/cmdfilter.cpp
vendored
@ -262,6 +262,8 @@ bool CommandData::TimeCheck(RarTime &ftm,RarTime &ftc,RarTime &fta)
|
||||
// Return 'true' if we need to exclude the file from processing.
|
||||
bool CommandData::SizeCheck(int64 Size)
|
||||
{
|
||||
if (Size==INT64NDF) // If called from archive formats like bzip2, not storing the file size.
|
||||
return false;
|
||||
if (FileSizeLess!=INT64NDF && Size>=FileSizeLess)
|
||||
return true;
|
||||
if (FileSizeMore!=INT64NDF && Size<=FileSizeMore)
|
||||
@ -287,8 +289,8 @@ int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchTy
|
||||
return 0;
|
||||
if ((FileHead.FileAttr & ExclFileAttr)!=0 || FileHead.Dir && ExclDir)
|
||||
return 0;
|
||||
if (InclAttrSet && (!FileHead.Dir && (FileHead.FileAttr & InclFileAttr)==0 ||
|
||||
FileHead.Dir && !InclDir))
|
||||
if (InclAttrSet && (FileHead.FileAttr & InclFileAttr)==0 &&
|
||||
(!FileHead.Dir || !InclDir))
|
||||
return 0;
|
||||
if (!Dir && SizeCheck(FileHead.UnpSize))
|
||||
return 0;
|
||||
|
23
deps/unrar/cmdmix.cpp
vendored
23
deps/unrar/cmdmix.cpp
vendored
@ -61,14 +61,14 @@ void CommandData::OutHelp(RAR_EXIT ExitCode)
|
||||
MUNRARTitle1,MRARTitle2,MCHelpCmd,MCHelpCmdE,MCHelpCmdL,
|
||||
MCHelpCmdP,MCHelpCmdT,MCHelpCmdV,MCHelpCmdX,MCHelpSw,MCHelpSwm,
|
||||
MCHelpSwAT,MCHelpSwAC,MCHelpSwAD,MCHelpSwAG,MCHelpSwAI,MCHelpSwAP,
|
||||
MCHelpSwCm,MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU,
|
||||
MCHelpSwDH,MCHelpSwEP,MCHelpSwEP3,MCHelpSwF,MCHelpSwIDP,MCHelpSwIERR,
|
||||
MCHelpSwINUL,MCHelpSwIOFF,MCHelpSwKB,MCHelpSwN,MCHelpSwNa,MCHelpSwNal,
|
||||
MCHelpSwO,MCHelpSwOC,MCHelpSwOL,MCHelpSwOR,MCHelpSwOW,MCHelpSwP,
|
||||
MCHelpSwPm,MCHelpSwR,MCHelpSwRI,MCHelpSwSC,MCHelpSwSL,MCHelpSwSM,
|
||||
MCHelpSwTA,MCHelpSwTB,MCHelpSwTN,MCHelpSwTO,MCHelpSwTS,MCHelpSwU,
|
||||
MCHelpSwVUnr,MCHelpSwVER,MCHelpSwVP,MCHelpSwX,MCHelpSwXa,MCHelpSwXal,
|
||||
MCHelpSwY
|
||||
MCHelpSwCm,MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU,MCHelpSwDH,MCHelpSwEP,
|
||||
MCHelpSwEP3,MCHelpSwEP4,MCHelpSwF,MCHelpSwIDP,MCHelpSwIERR,
|
||||
MCHelpSwINUL,MCHelpSwIOFF,MCHelpSwKB,MCHelpSwME,MCHelpSwN,MCHelpSwNa,
|
||||
MCHelpSwNal,MCHelpSwO,MCHelpSwOC,MCHelpSwOL,MCHelpSwOP,MCHelpSwOR,
|
||||
MCHelpSwOW,MCHelpSwP,MCHelpSwR,MCHelpSwRI,MCHelpSwSC,MCHelpSwSI,
|
||||
MCHelpSwSL,MCHelpSwSM,MCHelpSwTA,MCHelpSwTB,MCHelpSwTN,MCHelpSwTO,
|
||||
MCHelpSwTS,MCHelpSwU,MCHelpSwVUnr,MCHelpSwVER,MCHelpSwVP,MCHelpSwX,
|
||||
MCHelpSwXa,MCHelpSwXal,MCHelpSwY
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -92,6 +92,13 @@ void CommandData::OutHelp(RAR_EXIT ExitCode)
|
||||
if (Found)
|
||||
continue;
|
||||
#endif
|
||||
#ifdef _UNIX
|
||||
if (CmpMSGID(Help[I],MRARTitle2))
|
||||
{
|
||||
mprintf(St(MFwrSlTitle2));
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#if !defined(_UNIX) && !defined(_WIN_ALL)
|
||||
if (CmpMSGID(Help[I],MCHelpSwOW))
|
||||
continue;
|
||||
|
1
deps/unrar/compress.hpp
vendored
1
deps/unrar/compress.hpp
vendored
@ -17,6 +17,7 @@ class PackDef
|
||||
static const uint MAX_INC_LZ_MATCH = MAX_LZ_MATCH + 3;
|
||||
|
||||
static const uint MAX3_LZ_MATCH = 0x101; // Maximum match length for RAR v3.
|
||||
static const uint MAX3_INC_LZ_MATCH = MAX3_LZ_MATCH + 3;
|
||||
static const uint LOW_DIST_REP_COUNT = 16;
|
||||
|
||||
static const uint NC = 306; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
|
61
deps/unrar/consio.cpp
vendored
61
deps/unrar/consio.cpp
vendored
@ -3,6 +3,7 @@
|
||||
|
||||
static MESSAGE_TYPE MsgStream=MSG_STDOUT;
|
||||
static RAR_CHARSET RedirectCharset=RCH_DEFAULT;
|
||||
static bool ProhibitInput=false;
|
||||
|
||||
const int MaxMsgSize=2*NM+2048;
|
||||
|
||||
@ -61,6 +62,12 @@ void SetConsoleRedirectCharset(RAR_CHARSET RedirectCharset)
|
||||
}
|
||||
|
||||
|
||||
void ProhibitConsoleInput()
|
||||
{
|
||||
ProhibitInput=true;
|
||||
}
|
||||
|
||||
|
||||
#ifndef SILENT
|
||||
static void cvt_wprintf(FILE *dest,const wchar *fmt,va_list arglist)
|
||||
{
|
||||
@ -141,28 +148,56 @@ void eprintf(const wchar *fmt,...)
|
||||
|
||||
|
||||
#ifndef SILENT
|
||||
static void QuitIfInputProhibited()
|
||||
{
|
||||
// We cannot handle user prompts if -si is used to read file or archive data
|
||||
// from stdin.
|
||||
if (ProhibitInput)
|
||||
{
|
||||
mprintf(St(MStdinNoInput));
|
||||
ErrHandler.Exit(RARX_FATAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void GetPasswordText(wchar *Str,uint MaxLength)
|
||||
{
|
||||
if (MaxLength==0)
|
||||
return;
|
||||
QuitIfInputProhibited();
|
||||
if (StdinRedirected)
|
||||
getwstr(Str,MaxLength); // Read from pipe or redirected file.
|
||||
else
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
HANDLE hConIn=GetStdHandle(STD_INPUT_HANDLE);
|
||||
HANDLE hConOut=GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DWORD ConInMode,ConOutMode;
|
||||
DWORD Read=0;
|
||||
DWORD ConInMode;
|
||||
GetConsoleMode(hConIn,&ConInMode);
|
||||
GetConsoleMode(hConOut,&ConOutMode);
|
||||
SetConsoleMode(hConIn,ENABLE_LINE_INPUT);
|
||||
SetConsoleMode(hConOut,ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT);
|
||||
SetConsoleMode(hConIn,ENABLE_LINE_INPUT); // Remove ENABLE_ECHO_INPUT.
|
||||
|
||||
// We prefer ReadConsole to ReadFile, so we can read Unicode input.
|
||||
DWORD Read=0;
|
||||
ReadConsole(hConIn,Str,MaxLength-1,&Read,NULL);
|
||||
Str[Read]=0;
|
||||
SetConsoleMode(hConIn,ConInMode);
|
||||
SetConsoleMode(hConOut,ConOutMode);
|
||||
|
||||
// If entered password is longer than MAXPASSWORD and truncated,
|
||||
// read its unread part anyway, so it isn't read later as the second
|
||||
// password for -p switch. Low level FlushConsoleInputBuffer doesn't help
|
||||
// for high level ReadConsole, which in line input mode seems to store
|
||||
// the rest of string in its own internal buffer.
|
||||
if (wcschr(Str,'\r')==NULL) // If '\r' is missing, the password was truncated.
|
||||
while (true)
|
||||
{
|
||||
wchar Trail[64];
|
||||
DWORD TrailRead=0;
|
||||
// Use ASIZE(Trail)-1 to reserve the space for trailing 0.
|
||||
ReadConsole(hConIn,Trail,ASIZE(Trail)-1,&TrailRead,NULL);
|
||||
Trail[TrailRead]=0;
|
||||
if (TrailRead==0 || wcschr(Trail,'\r')!=NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
#else
|
||||
char StrA[MAXPASSWORD*4]; // "*4" for multibyte UTF-8 characters.
|
||||
#if defined(_EMX) || defined (__VMS)
|
||||
@ -190,16 +225,21 @@ bool GetConsolePassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (!StdinRedirected)
|
||||
// if (!StdinRedirected)
|
||||
if (Type==UIPASSWORD_GLOBAL)
|
||||
eprintf(L"\n%s: ",St(MAskPsw));
|
||||
else
|
||||
eprintf(St(MAskPswFor),FileName);
|
||||
|
||||
wchar PlainPsw[MAXPASSWORD];
|
||||
wchar PlainPsw[MAXPASSWORD+1];
|
||||
GetPasswordText(PlainPsw,ASIZE(PlainPsw));
|
||||
if (*PlainPsw==0 && Type==UIPASSWORD_GLOBAL)
|
||||
return false;
|
||||
if (wcslen(PlainPsw)>=MAXPASSWORD)
|
||||
{
|
||||
PlainPsw[MAXPASSWORD-1]=0;
|
||||
uiMsg(UIERROR_TRUNCPSW,MAXPASSWORD-1);
|
||||
}
|
||||
if (!StdinRedirected && Type==UIPASSWORD_GLOBAL)
|
||||
{
|
||||
eprintf(St(MReAskPsw));
|
||||
@ -229,6 +269,8 @@ bool getwstr(wchar *str,size_t n)
|
||||
// Print buffered prompt title function before waiting for input.
|
||||
fflush(stderr);
|
||||
|
||||
QuitIfInputProhibited();
|
||||
|
||||
*str=0;
|
||||
#if defined(_WIN_ALL)
|
||||
// fgetws does not work well with non-English text in Windows,
|
||||
@ -240,6 +282,7 @@ bool getwstr(wchar *str,size_t n)
|
||||
Array<char> StrA(n*4); // Up to 4 UTF-8 characters per wchar_t.
|
||||
File SrcFile;
|
||||
SrcFile.SetHandleType(FILE_HANDLESTD);
|
||||
SrcFile.SetLineInputMode(true);
|
||||
int ReadSize=SrcFile.Read(&StrA[0],StrA.Size()-1);
|
||||
if (ReadSize<=0)
|
||||
{
|
||||
|
1
deps/unrar/consio.hpp
vendored
1
deps/unrar/consio.hpp
vendored
@ -4,6 +4,7 @@
|
||||
void InitConsole();
|
||||
void SetConsoleMsgStream(MESSAGE_TYPE MsgStream);
|
||||
void SetConsoleRedirectCharset(RAR_CHARSET RedirectCharset);
|
||||
void ProhibitConsoleInput();
|
||||
void OutComment(const wchar *Comment,size_t Size);
|
||||
|
||||
#ifndef SILENT
|
||||
|
171
deps/unrar/crc.cpp
vendored
171
deps/unrar/crc.cpp
vendored
@ -14,6 +14,12 @@
|
||||
|
||||
#include "rar.hpp"
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
// User suggested to avoid BSD license in SFX module, so they do not need
|
||||
// to include the license to SFX archive.
|
||||
#define USE_SLICING
|
||||
#endif
|
||||
|
||||
static uint crc_tables[8][256]; // Tables for Slicing-by-8.
|
||||
|
||||
|
||||
@ -37,6 +43,7 @@ static void InitTables()
|
||||
{
|
||||
InitCRC32(crc_tables[0]);
|
||||
|
||||
#ifdef USE_SLICING
|
||||
for (uint I=0;I<256;I++) // Build additional lookup tables.
|
||||
{
|
||||
uint C=crc_tables[0][I];
|
||||
@ -46,6 +53,7 @@ static void InitTables()
|
||||
crc_tables[J][I]=C;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -55,6 +63,7 @@ uint CRC32(uint StartCRC,const void *Addr,size_t Size)
|
||||
{
|
||||
byte *Data=(byte *)Addr;
|
||||
|
||||
#ifdef USE_SLICING
|
||||
// Align Data to 8 for better performance.
|
||||
for (;Size>0 && ((size_t)Data & 7);Size--,Data++)
|
||||
StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
|
||||
@ -77,6 +86,7 @@ uint CRC32(uint StartCRC,const void *Addr,size_t Size)
|
||||
crc_tables[1][(byte)(NextData >> 16)] ^
|
||||
crc_tables[0][(byte)(NextData >> 24)];
|
||||
}
|
||||
#endif
|
||||
|
||||
for (;Size>0;Size--,Data++) // Process left data.
|
||||
StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
|
||||
@ -100,3 +110,164 @@ ushort Checksum14(ushort StartCRC,const void *Addr,size_t Size)
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
static uint64 crc64_tables[8][256]; // Tables for Slicing-by-8 for CRC64.
|
||||
|
||||
void InitCRC64(uint64 *CRCTab)
|
||||
{
|
||||
const uint64 poly=INT32TO64(0xC96C5795, 0xD7870F42); // 0xC96C5795D7870F42;
|
||||
for (uint I=0;I<256;I++)
|
||||
{
|
||||
uint64 C=I;
|
||||
for (uint J=0;J<8;J++)
|
||||
C=(C & 1) ? (C>>1)^poly: (C>>1);
|
||||
CRCTab[I]=C;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void InitTables64()
|
||||
{
|
||||
InitCRC64(crc64_tables[0]);
|
||||
|
||||
for (uint I=0;I<256;I++) // Build additional lookup tables.
|
||||
{
|
||||
uint64 C=crc64_tables[0][I];
|
||||
for (uint J=1;J<8;J++)
|
||||
{
|
||||
C=crc64_tables[0][(byte)C]^(C>>8);
|
||||
crc64_tables[J][I]=C;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// We cannot place the intialization to CRC64(), because we use this function
|
||||
// in multithreaded mode and it conflicts with multithreading.
|
||||
struct CallInitCRC64 {CallInitCRC64() {InitTables64();}} static CallInit64;
|
||||
|
||||
uint64 CRC64(uint64 StartCRC,const void *Addr,size_t Size)
|
||||
{
|
||||
byte *Data=(byte *)Addr;
|
||||
|
||||
// Align Data to 8 for better performance.
|
||||
for (;Size>0 && ((size_t)Data & 7)!=0;Size--,Data++)
|
||||
StartCRC=crc64_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
|
||||
|
||||
for (byte *DataEnd=Data+Size/8*8; Data<DataEnd; Data+=8 )
|
||||
{
|
||||
uint64 Index=StartCRC;
|
||||
#ifdef BIG_ENDIAN
|
||||
Index ^= (uint64(Data[0])|(uint64(Data[1])<<8)|(uint64(Data[2])<<16)|(uint64(Data[3])<<24))|
|
||||
(uint64(Data[4])<<32)|(uint64(Data[5])<<40)|(uint64(Data[6])<<48)|(uint64(Data[7])<<56);
|
||||
#else
|
||||
Index ^= *(uint64 *)Data;
|
||||
#endif
|
||||
StartCRC = crc64_tables[ 7 ] [ ( byte ) (Index ) ] ^
|
||||
crc64_tables[ 6 ] [ ( byte ) (Index >> 8 ) ] ^
|
||||
crc64_tables[ 5 ] [ ( byte ) (Index >> 16 ) ] ^
|
||||
crc64_tables[ 4 ] [ ( byte ) (Index >> 24 ) ] ^
|
||||
crc64_tables[ 3 ] [ ( byte ) (Index >> 32 ) ] ^
|
||||
crc64_tables[ 2 ] [ ( byte ) (Index >> 40 ) ] ^
|
||||
crc64_tables[ 1 ] [ ( byte ) (Index >> 48 ) ] ^
|
||||
crc64_tables[ 0 ] [ ( byte ) (Index >> 56 ) ] ;
|
||||
}
|
||||
|
||||
for (Size%=8;Size>0;Size--,Data++) // Process left data.
|
||||
StartCRC=crc64_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
|
||||
|
||||
return StartCRC;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static void TestCRC();
|
||||
struct TestCRCStruct {TestCRCStruct() {TestCRC();exit(0);}} GlobalTesCRC;
|
||||
|
||||
void TestCRC()
|
||||
{
|
||||
const uint FirstSize=300;
|
||||
byte b[FirstSize];
|
||||
|
||||
if ((CRC32(0xffffffff,(byte*)"testtesttest",12)^0xffffffff)==0x44608e84)
|
||||
mprintf(L"\nCRC32 test1 OK");
|
||||
else
|
||||
mprintf(L"\nCRC32 test1 FAILED");
|
||||
|
||||
if (CRC32(0,(byte*)"te\x80st",5)==0xB2E5C5AE)
|
||||
mprintf(L"\nCRC32 test2 OK");
|
||||
else
|
||||
mprintf(L"\nCRC32 test2 FAILED");
|
||||
|
||||
for (uint I=0;I<14;I++) // Check for possible int sign extension.
|
||||
b[I]=(byte)0x7f+I;
|
||||
if ((CRC32(0xffffffff,b,14)^0xffffffff)==0x1DFA75DA)
|
||||
mprintf(L"\nCRC32 test3 OK");
|
||||
else
|
||||
mprintf(L"\nCRC32 test3 FAILED");
|
||||
|
||||
for (uint I=0;I<FirstSize;I++)
|
||||
b[I]=(byte)I;
|
||||
uint r32=CRC32(0xffffffff,b,FirstSize);
|
||||
for (uint I=FirstSize;I<1024;I++)
|
||||
{
|
||||
b[0]=(byte)I;
|
||||
r32=CRC32(r32,b,1);
|
||||
}
|
||||
if ((r32^0xffffffff)==0xB70B4C26)
|
||||
mprintf(L"\nCRC32 test4 OK");
|
||||
else
|
||||
mprintf(L"\nCRC32 test4 FAILED");
|
||||
|
||||
if ((CRC64(0xffffffffffffffff,(byte*)"testtesttest",12)^0xffffffffffffffff)==0x7B1C2D230EDEB436)
|
||||
mprintf(L"\nCRC64 test1 OK");
|
||||
else
|
||||
mprintf(L"\nCRC64 test1 FAILED");
|
||||
|
||||
if (CRC64(0,(byte*)"te\x80st",5)==0xB5DBF9583A6EED4A)
|
||||
mprintf(L"\nCRC64 test2 OK");
|
||||
else
|
||||
mprintf(L"\nCRC64 test2 FAILED");
|
||||
|
||||
for (uint I=0;I<14;I++) // Check for possible int sign extension.
|
||||
b[I]=(byte)0x7f+I;
|
||||
if ((CRC64(0xffffffffffffffff,b,14)^0xffffffffffffffff)==0xE019941C05B2820C)
|
||||
mprintf(L"\nCRC64 test3 OK");
|
||||
else
|
||||
mprintf(L"\nCRC64 test3 FAILED");
|
||||
|
||||
for (uint I=0;I<FirstSize;I++)
|
||||
b[I]=(byte)I;
|
||||
uint64 r64=CRC64(0xffffffffffffffff,b,FirstSize);
|
||||
for (uint I=FirstSize;I<1024;I++)
|
||||
{
|
||||
b[0]=(byte)I;
|
||||
r64=CRC64(r64,b,1);
|
||||
}
|
||||
if ((r64^0xffffffffffffffff)==0xD51FB58DC789C400)
|
||||
mprintf(L"\nCRC64 test4 OK");
|
||||
else
|
||||
mprintf(L"\nCRC64 test4 FAILED");
|
||||
|
||||
const size_t BufSize=0x100000;
|
||||
byte *Buf=new byte[BufSize];
|
||||
memset(Buf,0,BufSize);
|
||||
|
||||
clock_t StartTime=clock();
|
||||
r32=0xffffffff;
|
||||
const uint BufCount=5000;
|
||||
for (uint I=0;I<BufCount;I++)
|
||||
r32=CRC32(r32,Buf,BufSize);
|
||||
if (r32!=0) // Otherwise compiler optimizer removes CRC calculation.
|
||||
mprintf(L"\nCRC32 speed: %d MB/s",BufCount*1000/(clock()-StartTime));
|
||||
|
||||
StartTime=clock();
|
||||
r64=0xffffffffffffffff;
|
||||
for (uint I=0;I<BufCount;I++)
|
||||
r64=CRC64(r64,Buf,BufSize);
|
||||
if (r64!=0) // Otherwise compiler optimizer removes CRC calculation.
|
||||
mprintf(L"\nCRC64 speed: %d MB/s",BufCount*1000/(clock()-StartTime));
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
4
deps/unrar/crc.hpp
vendored
4
deps/unrar/crc.hpp
vendored
@ -11,5 +11,9 @@ uint CRC32(uint StartCRC,const void *Addr,size_t Size);
|
||||
ushort Checksum14(ushort StartCRC,const void *Addr,size_t Size);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void InitCRC64(uint64 *CRCTab);
|
||||
uint64 CRC64(uint64 StartCRC,const void *Addr,size_t Size);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
14
deps/unrar/crypt.cpp
vendored
14
deps/unrar/crypt.cpp
vendored
@ -11,21 +11,12 @@
|
||||
CryptData::CryptData()
|
||||
{
|
||||
Method=CRYPT_NONE;
|
||||
memset(KDF3Cache,0,sizeof(KDF3Cache));
|
||||
memset(KDF5Cache,0,sizeof(KDF5Cache));
|
||||
KDF3CachePos=0;
|
||||
KDF5CachePos=0;
|
||||
memset(CRCTab,0,sizeof(CRCTab));
|
||||
}
|
||||
|
||||
|
||||
CryptData::~CryptData()
|
||||
{
|
||||
cleandata(KDF3Cache,sizeof(KDF3Cache));
|
||||
cleandata(KDF5Cache,sizeof(KDF5Cache));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void CryptData::DecryptBlock(byte *Buf,size_t Size)
|
||||
@ -56,15 +47,18 @@ bool CryptData::SetCryptKeys(bool Encrypt,CRYPT_METHOD Method,
|
||||
SecPassword *Password,const byte *Salt,
|
||||
const byte *InitV,uint Lg2Cnt,byte *HashKey,byte *PswCheck)
|
||||
{
|
||||
if (!Password->IsSet() || Method==CRYPT_NONE)
|
||||
if (Method==CRYPT_NONE || !Password->IsSet())
|
||||
return false;
|
||||
|
||||
CryptData::Method=Method;
|
||||
|
||||
wchar PwdW[MAXPASSWORD];
|
||||
Password->Get(PwdW,ASIZE(PwdW));
|
||||
PwdW[Min(MAXPASSWORD_RAR,MAXPASSWORD)-1]=0; // For compatibility with existing archives.
|
||||
|
||||
char PwdA[MAXPASSWORD];
|
||||
WideToChar(PwdW,PwdA,ASIZE(PwdA));
|
||||
PwdA[Min(MAXPASSWORD_RAR,MAXPASSWORD)-1]=0; // For compatibility with existing archives.
|
||||
|
||||
switch(Method)
|
||||
{
|
||||
|
72
deps/unrar/crypt.hpp
vendored
72
deps/unrar/crypt.hpp
vendored
@ -30,6 +30,18 @@ class CryptData
|
||||
uint Lg2Count; // Log2 of PBKDF2 repetition count.
|
||||
byte PswCheckValue[SHA256_DIGEST_SIZE];
|
||||
byte HashKeyValue[SHA256_DIGEST_SIZE];
|
||||
|
||||
KDF5CacheItem() {Clean();}
|
||||
~KDF5CacheItem() {Clean();}
|
||||
|
||||
void Clean()
|
||||
{
|
||||
cleandata(Salt,sizeof(Salt));
|
||||
cleandata(Key,sizeof(Key));
|
||||
cleandata(&Lg2Count,sizeof(Lg2Count));
|
||||
cleandata(PswCheckValue,sizeof(PswCheckValue));
|
||||
cleandata(HashKeyValue,sizeof(HashKeyValue));
|
||||
}
|
||||
};
|
||||
|
||||
struct KDF3CacheItem
|
||||
@ -39,6 +51,17 @@ class CryptData
|
||||
byte Key[16];
|
||||
byte Init[16];
|
||||
bool SaltPresent;
|
||||
|
||||
KDF3CacheItem() {Clean();}
|
||||
~KDF3CacheItem() {Clean();}
|
||||
|
||||
void Clean()
|
||||
{
|
||||
cleandata(Salt,sizeof(Salt));
|
||||
cleandata(Key,sizeof(Key));
|
||||
cleandata(Init,sizeof(Init));
|
||||
cleandata(&SaltPresent,sizeof(SaltPresent));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -77,7 +100,6 @@ class CryptData
|
||||
ushort Key15[4];
|
||||
public:
|
||||
CryptData();
|
||||
~CryptData();
|
||||
bool SetCryptKeys(bool Encrypt,CRYPT_METHOD Method,SecPassword *Password,
|
||||
const byte *Salt,const byte *InitV,uint Lg2Cnt,
|
||||
byte *HashKey,byte *PswCheck);
|
||||
@ -89,6 +111,54 @@ class CryptData
|
||||
static void SetSalt(byte *Salt,size_t SaltSize);
|
||||
};
|
||||
|
||||
|
||||
class CheckPassword
|
||||
{
|
||||
public:
|
||||
enum CONFIDENCE {CONFIDENCE_HIGH,CONFIDENCE_MEDIUM,CONFIDENCE_LOW};
|
||||
virtual CONFIDENCE GetConfidence()=0;
|
||||
virtual bool Check(SecPassword *Password)=0;
|
||||
};
|
||||
|
||||
class RarCheckPassword:public CheckPassword
|
||||
{
|
||||
private:
|
||||
CryptData *Crypt;
|
||||
uint Lg2Count;
|
||||
byte Salt[SIZE_SALT50];
|
||||
byte InitV[SIZE_INITV];
|
||||
byte PswCheck[SIZE_PSWCHECK];
|
||||
public:
|
||||
RarCheckPassword()
|
||||
{
|
||||
Crypt=NULL;
|
||||
}
|
||||
~RarCheckPassword()
|
||||
{
|
||||
delete Crypt;
|
||||
}
|
||||
void Set(byte *Salt,byte *InitV,uint Lg2Count,byte *PswCheck)
|
||||
{
|
||||
if (Crypt==NULL)
|
||||
Crypt=new CryptData;
|
||||
memcpy(this->Salt,Salt,sizeof(this->Salt));
|
||||
memcpy(this->InitV,InitV,sizeof(this->InitV));
|
||||
this->Lg2Count=Lg2Count;
|
||||
memcpy(this->PswCheck,PswCheck,sizeof(this->PswCheck));
|
||||
}
|
||||
bool IsSet() {return Crypt!=NULL;}
|
||||
|
||||
// RAR5 provides the higly reliable 64 bit password verification value.
|
||||
CONFIDENCE GetConfidence() {return CONFIDENCE_HIGH;}
|
||||
|
||||
bool Check(SecPassword *Password)
|
||||
{
|
||||
byte PswCheck[SIZE_PSWCHECK];
|
||||
Crypt->SetCryptKeys(false,CRYPT_RAR50,Password,Salt,InitV,Lg2Count,NULL,PswCheck);
|
||||
return memcmp(PswCheck,this->PswCheck,sizeof(this->PswCheck))==0;
|
||||
}
|
||||
};
|
||||
|
||||
void GetRnd(byte *RndBuf,size_t BufSize);
|
||||
|
||||
void hmac_sha256(const byte *Key,size_t KeyLength,const byte *Data,
|
||||
|
5
deps/unrar/crypt3.cpp
vendored
5
deps/unrar/crypt3.cpp
vendored
@ -18,8 +18,9 @@ void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,co
|
||||
if (!Cached)
|
||||
{
|
||||
byte RawPsw[2*MAXPASSWORD+SIZE_SALT30];
|
||||
WideToRaw(PwdW,RawPsw,ASIZE(RawPsw));
|
||||
size_t RawLength=2*wcslen(PwdW);
|
||||
size_t PswLength=wcslen(PwdW);
|
||||
size_t RawLength=2*PswLength;
|
||||
WideToRaw(PwdW,PswLength,RawPsw,RawLength);
|
||||
if (Salt!=NULL)
|
||||
{
|
||||
memcpy(RawPsw+RawLength,Salt,SIZE_SALT30);
|
||||
|
12
deps/unrar/crypt5.cpp
vendored
12
deps/unrar/crypt5.cpp
vendored
@ -21,7 +21,7 @@ static void hmac_sha256(const byte *Key,size_t KeyLength,const byte *Data,
|
||||
sha256_context ICtx;
|
||||
|
||||
if (ICtxOpt!=NULL && *SetIOpt)
|
||||
ICtx=*ICtxOpt; // Use already calculated first block context.
|
||||
ICtx=*ICtxOpt; // Use already calculated the first block context.
|
||||
else
|
||||
{
|
||||
// This calculation is the same for all iterations with same password.
|
||||
@ -90,10 +90,10 @@ void pbkdf2(const byte *Pwd, size_t PwdLength,
|
||||
byte SaltData[MaxSalt+4];
|
||||
memcpy(SaltData, Salt, Min(SaltLength,MaxSalt));
|
||||
|
||||
SaltData[SaltLength + 0] = 0; // Salt concatenated to 1.
|
||||
SaltData[SaltLength + 1] = 0;
|
||||
SaltData[SaltLength + 2] = 0;
|
||||
SaltData[SaltLength + 3] = 1;
|
||||
SaltData[SaltLength + 0] = 0; // Block index appened to salt.
|
||||
SaltData[SaltLength + 1] = 0; //
|
||||
SaltData[SaltLength + 2] = 0; // Since we do not request the key width
|
||||
SaltData[SaltLength + 3] = 1; // exceeding HMAC width, it is always 1.
|
||||
|
||||
// First iteration: HMAC of password, salt and block index (1).
|
||||
byte U1[SHA256_DIGEST_SIZE];
|
||||
@ -140,7 +140,7 @@ void CryptData::SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW,
|
||||
for (uint I=0;I<ASIZE(KDF5Cache);I++)
|
||||
{
|
||||
KDF5CacheItem *Item=KDF5Cache+I;
|
||||
if (Item->Lg2Count==Lg2Cnt && Item->Pwd==*Password &&
|
||||
if (Item->Pwd==*Password && Item->Lg2Count==Lg2Cnt &&
|
||||
memcmp(Item->Salt,Salt,SIZE_SALT50)==0)
|
||||
{
|
||||
memcpy(Key,Item->Key,sizeof(Key));
|
||||
|
10
deps/unrar/dll.rc
vendored
10
deps/unrar/dll.rc
vendored
@ -2,8 +2,8 @@
|
||||
#include <commctrl.h>
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 6, 1, 100, 3756
|
||||
PRODUCTVERSION 6, 1, 100, 3756
|
||||
FILEVERSION 6, 22, 1, 865
|
||||
PRODUCTVERSION 6, 22, 1, 865
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
{
|
||||
@ -14,9 +14,9 @@ FILETYPE VFT_APP
|
||||
VALUE "CompanyName", "Alexander Roshal\0"
|
||||
VALUE "ProductName", "RAR decompression library\0"
|
||||
VALUE "FileDescription", "RAR decompression library\0"
|
||||
VALUE "FileVersion", "6.1.0\0"
|
||||
VALUE "ProductVersion", "6.1.0\0"
|
||||
VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2021\0"
|
||||
VALUE "FileVersion", "6.22.1\0"
|
||||
VALUE "ProductVersion", "6.22.1\0"
|
||||
VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2023\0"
|
||||
VALUE "OriginalFilename", "Unrar.dll\0"
|
||||
}
|
||||
}
|
||||
|
2
deps/unrar/encname.cpp
vendored
2
deps/unrar/encname.cpp
vendored
@ -20,8 +20,6 @@ void EncodeFileName::Decode(char *Name,size_t NameSize,byte *EncName,size_t EncS
|
||||
{
|
||||
if (FlagBits==0)
|
||||
{
|
||||
if (EncPos>=EncSize)
|
||||
break;
|
||||
Flags=EncName[EncPos++];
|
||||
FlagBits=8;
|
||||
}
|
||||
|
3
deps/unrar/encname.hpp
vendored
3
deps/unrar/encname.hpp
vendored
@ -4,9 +4,8 @@
|
||||
class EncodeFileName
|
||||
{
|
||||
private:
|
||||
void AddFlags(int Value);
|
||||
void AddFlags(byte Value,byte *EncName);
|
||||
|
||||
byte *EncName;
|
||||
byte Flags;
|
||||
uint FlagBits;
|
||||
size_t FlagsPos;
|
||||
|
7
deps/unrar/errhnd.cpp
vendored
7
deps/unrar/errhnd.cpp
vendored
@ -169,10 +169,13 @@ void ErrorHandler::OpenErrorMsg(const wchar *FileName)
|
||||
|
||||
void ErrorHandler::OpenErrorMsg(const wchar *ArcName,const wchar *FileName)
|
||||
{
|
||||
Wait(); // Keep GUI responsive if many files cannot be opened when archiving.
|
||||
uiMsg(UIERROR_FILEOPEN,ArcName,FileName);
|
||||
SysErrMsg();
|
||||
SetErrorCode(RARX_OPEN);
|
||||
|
||||
// Keep GUI responsive if many files cannot be opened when archiving.
|
||||
// Call after SysErrMsg to avoid modifying the error code and SysErrMsg text.
|
||||
Wait();
|
||||
}
|
||||
|
||||
|
||||
@ -367,7 +370,7 @@ bool ErrorHandler::GetSysErrMsg(wchar *Msg,size_t Size)
|
||||
|
||||
void ErrorHandler::SysErrMsg()
|
||||
{
|
||||
#if !defined(SFX_MODULE) && !defined(SILENT)
|
||||
#ifndef SILENT
|
||||
wchar Msg[1024];
|
||||
if (!GetSysErrMsg(Msg,ASIZE(Msg)))
|
||||
return;
|
||||
|
89
deps/unrar/extinfo.cpp
vendored
89
deps/unrar/extinfo.cpp
vendored
@ -112,6 +112,68 @@ static bool LinkInPath(const wchar *Name)
|
||||
}
|
||||
|
||||
|
||||
// Delete symbolic links in file path, if any, and replace them by directories.
|
||||
// Prevents extracting files outside of destination folder with symlink chains.
|
||||
bool LinksToDirs(const wchar *SrcName,const wchar *SkipPart,std::wstring &LastChecked)
|
||||
{
|
||||
// Unlike Unix, Windows doesn't expand lnk1 in symlink targets like
|
||||
// "lnk1/../dir", but converts the path to "dir". In Unix we need to call
|
||||
// this function to prevent placing unpacked files outside of destination
|
||||
// folder if previously we unpacked "dir/lnk1" -> "..",
|
||||
// "dir/lnk2" -> "lnk1/.." and "dir/lnk2/anypath/poc.txt".
|
||||
// We may still need this function to prevent abusing symlink chains
|
||||
// in link source path if we remove detection of such chains
|
||||
// in IsRelativeSymlinkSafe. This function seems to make other symlink
|
||||
// related safety checks redundant, but for now we prefer to keep them too.
|
||||
//
|
||||
// 2022.12.01: the performance impact is minimized after adding the check
|
||||
// against the previous path and enabling this verification only after
|
||||
// extracting a symlink with ".." in target. So we enabled it for Windows
|
||||
// as well for extra safety.
|
||||
//#ifdef _UNIX
|
||||
wchar Path[NM];
|
||||
if (wcslen(SrcName)>=ASIZE(Path))
|
||||
return false; // It should not be that long, skip.
|
||||
wcsncpyz(Path,SrcName,ASIZE(Path));
|
||||
|
||||
size_t SkipLength=wcslen(SkipPart);
|
||||
|
||||
if (SkipLength>0 && wcsncmp(Path,SkipPart,SkipLength)!=0)
|
||||
SkipLength=0; // Parameter validation, not really needed now.
|
||||
|
||||
// Do not check parts already checked in previous path to improve performance.
|
||||
for (uint I=0;Path[I]!=0 && I<LastChecked.size() && Path[I]==LastChecked[I];I++)
|
||||
if (IsPathDiv(Path[I]) && I>SkipLength)
|
||||
SkipLength=I;
|
||||
|
||||
wchar *Name=Path;
|
||||
if (SkipLength>0)
|
||||
{
|
||||
// Avoid converting symlinks in destination path part specified by user.
|
||||
Name+=SkipLength;
|
||||
while (IsPathDiv(*Name))
|
||||
Name++;
|
||||
}
|
||||
|
||||
for (wchar *s=Path+wcslen(Path)-1;s>Name;s--)
|
||||
if (IsPathDiv(*s))
|
||||
{
|
||||
*s=0;
|
||||
FindData FD;
|
||||
if (FindFile::FastFind(Path,&FD,true) && FD.IsLink)
|
||||
#ifdef _WIN_ALL
|
||||
if (!DelDir(Path))
|
||||
#else
|
||||
if (!DelFile(Path))
|
||||
#endif
|
||||
return false; // Couldn't delete the symlink to replace it with directory.
|
||||
}
|
||||
LastChecked=SrcName;
|
||||
//#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *PrepSrcName,const wchar *TargetName)
|
||||
{
|
||||
// Catch root dir based /path/file paths also as stuff like \\?\.
|
||||
@ -131,10 +193,14 @@ bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *Pr
|
||||
UpLevels++;
|
||||
TargetName++;
|
||||
}
|
||||
// If link target includes "..", it must not have another links
|
||||
// in the path, because they can bypass our safety check. For example,
|
||||
// If link target includes "..", it must not have another links in its
|
||||
// source path, because they can bypass our safety check. For example,
|
||||
// suppose we extracted "lnk1" -> "." first and "lnk1/lnk2" -> ".." next
|
||||
// or "dir/lnk1" -> ".." first and "dir/lnk1/lnk2" -> ".." next.
|
||||
// or "dir/lnk1" -> ".." first, "dir/lnk1/lnk2" -> ".." next and
|
||||
// file "dir/lnk1/lnk2/poc.txt" last.
|
||||
// Do not confuse with link chains in target, this is in link source path.
|
||||
// It is important for Windows too, though this check can be omitted
|
||||
// if LinksToDirs is invoked in Windows as well.
|
||||
if (UpLevels>0 && LinkInPath(PrepSrcName))
|
||||
return false;
|
||||
|
||||
@ -160,15 +226,26 @@ bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *Pr
|
||||
}
|
||||
|
||||
|
||||
bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName)
|
||||
bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName,bool &UpLink)
|
||||
{
|
||||
// Returning true in Uplink indicates that link target might include ".."
|
||||
// and enables additional checks. It is ok to falsely return true here,
|
||||
// as it implies only the minor performance penalty. But we shall always
|
||||
// return true for links with ".." in target for security reason.
|
||||
|
||||
UpLink=true; // Assume the target might include potentially unsafe "..".
|
||||
#if defined(SAVE_LINKS) && defined(_UNIX) || defined(_WIN_ALL)
|
||||
if (Arc.Format==RARFMT50) // For RAR5 archives we can check RedirName for both Unix and Windows.
|
||||
UpLink=wcsstr(Arc.FileHead.RedirName,L"..")!=NULL;
|
||||
#endif
|
||||
|
||||
#if defined(SAVE_LINKS) && defined(_UNIX)
|
||||
// For RAR 3.x archives we process links even in test mode to skip link data.
|
||||
if (Arc.Format==RARFMT15)
|
||||
return ExtractUnixLink30(Cmd,DataIO,Arc,LinkName);
|
||||
return ExtractUnixLink30(Cmd,DataIO,Arc,LinkName,UpLink);
|
||||
if (Arc.Format==RARFMT50)
|
||||
return ExtractUnixLink50(Cmd,LinkName,&Arc.FileHead);
|
||||
#elif defined _WIN_ALL
|
||||
#elif defined(_WIN_ALL)
|
||||
// RAR 5.0 archives store link information in file header, so there is
|
||||
// no need to additionally test it if we do not create a file.
|
||||
if (Arc.Format==RARFMT50)
|
||||
|
3
deps/unrar/extinfo.hpp
vendored
3
deps/unrar/extinfo.hpp
vendored
@ -1,8 +1,9 @@
|
||||
#ifndef _RAR_EXTINFO_
|
||||
#define _RAR_EXTINFO_
|
||||
|
||||
bool LinksToDirs(const wchar *SrcName,const wchar *SkipPart,std::wstring &LastChecked);
|
||||
bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *PrepSrcName,const wchar *TargetName);
|
||||
bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName);
|
||||
bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName,bool &UpLink);
|
||||
#ifdef _UNIX
|
||||
void SetUnixOwner(Archive &Arc,const wchar *FileName);
|
||||
#endif
|
||||
|
485
deps/unrar/extract.cpp
vendored
485
deps/unrar/extract.cpp
vendored
@ -5,10 +5,30 @@ CmdExtract::CmdExtract(CommandData *Cmd)
|
||||
CmdExtract::Cmd=Cmd;
|
||||
|
||||
*ArcName=0;
|
||||
|
||||
*DestFileName=0;
|
||||
|
||||
ArcAnalyzed=false;
|
||||
Analyze=new AnalyzeData;
|
||||
memset(Analyze,0,sizeof(*Analyze));
|
||||
|
||||
TotalFileCount=0;
|
||||
|
||||
// Common for all archives involved. Set here instead of DoExtract()
|
||||
// to use in unrar.dll too. Allows to avoid LinksToDirs() calls
|
||||
// and save CPU time in no symlinks including ".." in target were extracted.
|
||||
#if defined(_WIN_ALL)
|
||||
// We can't expand symlink path components in another symlink target
|
||||
// in Windows. We can't create symlinks in Android now. Even though we do not
|
||||
// really need LinksToDirs() calls in these systems, we still call it
|
||||
// for extra safety, but only if symlink with ".." in target was extracted.
|
||||
ConvertSymlinkPaths=false;
|
||||
#else
|
||||
// We enable it by default in Unix to care about the case when several
|
||||
// archives are unpacked to same directory with several independent RAR runs.
|
||||
// Worst case performance penalty for a lot of small files seems to be ~3%.
|
||||
ConvertSymlinkPaths=true;
|
||||
#endif
|
||||
|
||||
Unp=new Unpack(&DataIO);
|
||||
#ifdef RAR_SMP
|
||||
Unp->SetThreads(Cmd->Threads);
|
||||
@ -18,7 +38,26 @@ CmdExtract::CmdExtract(CommandData *Cmd)
|
||||
|
||||
CmdExtract::~CmdExtract()
|
||||
{
|
||||
FreeAnalyzeData();
|
||||
delete Unp;
|
||||
delete Analyze;
|
||||
}
|
||||
|
||||
|
||||
void CmdExtract::FreeAnalyzeData()
|
||||
{
|
||||
for (size_t I=0;I<RefList.Size();I++)
|
||||
{
|
||||
// We can have undeleted temporary reference source here if extraction
|
||||
// was interrupted early or if user refused to overwrite prompt.
|
||||
if (RefList[I].TmpName!=NULL)
|
||||
DelFile(RefList[I].TmpName);
|
||||
free(RefList[I].RefName);
|
||||
free(RefList[I].TmpName);
|
||||
}
|
||||
RefList.Reset();
|
||||
|
||||
memset(Analyze,0,sizeof(*Analyze));
|
||||
}
|
||||
|
||||
|
||||
@ -30,10 +69,13 @@ void CmdExtract::DoExtract()
|
||||
PasswordCancelled=false;
|
||||
DataIO.SetCurrentCommand(Cmd->Command[0]);
|
||||
|
||||
if (*Cmd->UseStdin==0)
|
||||
{
|
||||
FindData FD;
|
||||
while (Cmd->GetArcName(ArcName,ASIZE(ArcName)))
|
||||
if (FindFile::FastFind(ArcName,&FD))
|
||||
DataIO.TotalArcSize+=FD.Size;
|
||||
}
|
||||
|
||||
Cmd->ArcNames.Rewind();
|
||||
while (Cmd->GetArcName(ArcName,ASIZE(ArcName)))
|
||||
@ -49,8 +91,7 @@ void CmdExtract::DoExtract()
|
||||
if (Code!=EXTRACT_ARC_REPEAT)
|
||||
break;
|
||||
}
|
||||
if (FindFile::FastFind(ArcName,&FD))
|
||||
DataIO.ProcessedArcSize+=FD.Size;
|
||||
DataIO.ProcessedArcSize+=DataIO.LastArcSize;
|
||||
}
|
||||
|
||||
// Clean user entered password. Not really required, just for extra safety.
|
||||
@ -82,7 +123,7 @@ void CmdExtract::DoExtract()
|
||||
|
||||
void CmdExtract::ExtractArchiveInit(Archive &Arc)
|
||||
{
|
||||
DataIO.UnpArcSize=Arc.FileLength();
|
||||
DataIO.AdjustTotalArcSize(&Arc);
|
||||
|
||||
FileCount=0;
|
||||
MatchedArgs=0;
|
||||
@ -98,15 +139,33 @@ void CmdExtract::ExtractArchiveInit(Archive &Arc)
|
||||
AllMatchesExact=true;
|
||||
AnySolidDataUnpackedWell=false;
|
||||
|
||||
ArcAnalyzed=false;
|
||||
|
||||
StartTime.SetCurrentTime();
|
||||
|
||||
LastCheckedSymlink.clear();
|
||||
}
|
||||
|
||||
|
||||
EXTRACT_ARC_CODE CmdExtract::ExtractArchive()
|
||||
{
|
||||
Archive Arc(Cmd);
|
||||
if (*Cmd->UseStdin!=0)
|
||||
{
|
||||
Arc.SetHandleType(FILE_HANDLESTD);
|
||||
#ifdef USE_QOPEN
|
||||
Arc.SetProhibitQOpen(true);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE) // WinRAR GUI code also resets the cache.
|
||||
if (*Cmd->Command=='T' || Cmd->Test)
|
||||
ResetFileCache(ArcName); // Reset the file cache when testing an archive.
|
||||
#endif
|
||||
if (!Arc.WOpen(ArcName))
|
||||
return EXTRACT_ARC_NEXT;
|
||||
}
|
||||
|
||||
if (!Arc.IsArchive(true))
|
||||
{
|
||||
@ -155,15 +214,28 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive()
|
||||
}
|
||||
#endif
|
||||
|
||||
Arc.ViewComment(); // Must be before possible EXTRACT_ARC_REPEAT.
|
||||
|
||||
int64 VolumeSetSize=0; // Total size of volumes after the current volume.
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
if (!ArcAnalyzed && *Cmd->UseStdin==0)
|
||||
{
|
||||
AnalyzeArchive(Arc.FileName,Arc.Volume,Arc.NewNumbering);
|
||||
ArcAnalyzed=true; // Avoid repeated analysis on EXTRACT_ARC_REPEAT.
|
||||
}
|
||||
#endif
|
||||
|
||||
if (Arc.Volume)
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
// Try to speed up extraction for independent solid volumes by starting
|
||||
// extraction from non-first volume if we can.
|
||||
if (!UseExactVolName && Arc.Solid && DetectStartVolume(Arc.FileName,Arc.NewNumbering))
|
||||
if (*Analyze->StartName!=0)
|
||||
{
|
||||
wcsncpyz(ArcName,Analyze->StartName,ASIZE(ArcName));
|
||||
*Analyze->StartName=0;
|
||||
|
||||
UseExactVolName=true;
|
||||
return EXTRACT_ARC_REPEAT;
|
||||
}
|
||||
@ -203,7 +275,13 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive()
|
||||
else
|
||||
uiStartArchiveExtract(!Cmd->Test,ArcName);
|
||||
|
||||
Arc.ViewComment();
|
||||
#ifndef SFX_MODULE
|
||||
if (Analyze->StartPos!=0)
|
||||
{
|
||||
Arc.Seek(Analyze->StartPos,SEEK_SET);
|
||||
Analyze->StartPos=0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
while (1)
|
||||
@ -216,14 +294,11 @@ EXTRACT_ARC_CODE CmdExtract::ExtractArchive()
|
||||
if (Repeat)
|
||||
{
|
||||
// If we started extraction from not first volume and need to
|
||||
// restart it from first, we must correct DataIO.TotalArcSize
|
||||
// for correct total progress display. We subtract the size
|
||||
// of current volume and all volumes after it and add the size
|
||||
// of new (first) volume.
|
||||
FindData OldArc,NewArc;
|
||||
if (FindFile::FastFind(Arc.FileName,&OldArc) &&
|
||||
FindFile::FastFind(ArcName,&NewArc))
|
||||
DataIO.TotalArcSize-=VolumeSetSize+OldArc.Size-NewArc.Size;
|
||||
// restart it from first, we must set DataIO.TotalArcSize to size
|
||||
// of new first volume to display the total progress correctly.
|
||||
FindData NewArc;
|
||||
if (FindFile::FastFind(ArcName,&NewArc))
|
||||
DataIO.TotalArcSize=NewArc.Size;
|
||||
return EXTRACT_ARC_REPEAT;
|
||||
}
|
||||
else
|
||||
@ -262,7 +337,14 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
return false;
|
||||
|
||||
HEADER_TYPE HeaderType=Arc.GetHeaderType();
|
||||
if (HeaderType!=HEAD_FILE)
|
||||
if (HeaderType==HEAD_FILE)
|
||||
{
|
||||
// Unlike Arc.FileName, ArcName might store an old volume name here.
|
||||
if (Analyze->EndPos!=0 && Analyze->EndPos==Arc.CurBlockPos &&
|
||||
(*Analyze->EndName==0 || wcscmp(Analyze->EndName,Arc.FileName)==0))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef SFX_MODULE
|
||||
if (Arc.Format==RARFMT15 && HeaderType==HEAD3_OLDSERVICE && PrevProcessed)
|
||||
@ -305,6 +387,9 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
if (Arc.FileHead.UnpSize<0)
|
||||
Arc.FileHead.UnpSize=0;
|
||||
|
||||
// 2022.03.20: We might remove this check in the future.
|
||||
// It duplicates Analyze->EndPos and Analyze->EndName in all cases except
|
||||
// volumes on removable media.
|
||||
if (!Cmd->Recurse && MatchedArgs>=Cmd->FileArgs.ItemsCount() && AllMatchesExact)
|
||||
return false;
|
||||
|
||||
@ -403,7 +488,39 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
FirstFile=false;
|
||||
#endif
|
||||
|
||||
if (MatchFound || (SkipSolid=Arc.Solid)!=0)
|
||||
bool RefTarget=false;
|
||||
if (!MatchFound)
|
||||
for (size_t I=0;I<RefList.Size();I++)
|
||||
if (wcscmp(ArcFileName,RefList[I].RefName)==0)
|
||||
{
|
||||
ExtractRef *MatchedRef=&RefList[I];
|
||||
|
||||
if (!Cmd->Test) // While harmless, it is useless for 't'.
|
||||
{
|
||||
// If reference source isn't selected, but target is selected,
|
||||
// we unpack the source under the temporary name and then rename
|
||||
// or copy it to target name. We do not unpack it under the target
|
||||
// name immediately, because the same source can be used by multiple
|
||||
// targets and it is possible that first target isn't unpacked
|
||||
// for some reason. Also targets might have associated service blocks
|
||||
// like ACLs. All this would complicate processing a lot.
|
||||
wcsncpyz(DestFileName,*Cmd->TempPath!=0 ? Cmd->TempPath:Cmd->ExtrPath,ASIZE(DestFileName));
|
||||
AddEndSlash(DestFileName,ASIZE(DestFileName));
|
||||
wcsncatz(DestFileName,L"__tmp_reference_source_",ASIZE(DestFileName));
|
||||
MkTemp(DestFileName,ASIZE(DestFileName));
|
||||
MatchedRef->TmpName=wcsdup(DestFileName);
|
||||
}
|
||||
RefTarget=true; // Need it even for 't' to test the reference source.
|
||||
break;
|
||||
}
|
||||
|
||||
if (Arc.FileHead.Encrypted && Cmd->SkipEncrypted)
|
||||
if (Arc.Solid)
|
||||
return false; // Abort the entire extraction for solid archive.
|
||||
else
|
||||
MatchFound=false; // Skip only the current file for non-solid archive.
|
||||
|
||||
if (MatchFound || RefTarget || (SkipSolid=Arc.Solid)!=0)
|
||||
{
|
||||
// First common call of uiStartFileExtract. It is done before overwrite
|
||||
// prompts, so if SkipSolid state is changed below, we'll need to make
|
||||
@ -411,6 +528,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
if (!uiStartFileExtract(ArcFileName,!Cmd->Test,Cmd->Test && Command!='I',SkipSolid))
|
||||
return false;
|
||||
|
||||
if (!RefTarget)
|
||||
ExtrPrepareName(Arc,ArcFileName,DestFileName,ASIZE(DestFileName));
|
||||
|
||||
// DestFileName can be set empty in case of excessive -ap switch.
|
||||
@ -448,9 +566,13 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
return !Arc.Solid; // Can try extracting next file only in non-solid archive.
|
||||
}
|
||||
|
||||
while (true) // Repeat the password prompt for wrong and empty passwords.
|
||||
{
|
||||
if (Arc.FileHead.Encrypted)
|
||||
{
|
||||
RarCheckPassword CheckPwd;
|
||||
if (Arc.Format==RARFMT50 && Arc.FileHead.UsePswCheck && !Arc.BrokenHeader)
|
||||
CheckPwd.Set(Arc.FileHead.Salt,Arc.FileHead.InitV,Arc.FileHead.Lg2Count,Arc.FileHead.PswCheck);
|
||||
|
||||
while (true) // Repeat the password prompt for wrong and empty passwords.
|
||||
{
|
||||
// Stop archive extracting if user cancelled a password prompt.
|
||||
#ifdef RARDLL
|
||||
@ -460,20 +582,19 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if (!ExtrGetPassword(Arc,ArcFileName))
|
||||
if (!ExtrGetPassword(Arc,ArcFileName,CheckPwd.IsSet() ? &CheckPwd:NULL))
|
||||
{
|
||||
PasswordCancelled=true;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set a password before creating the file, so we can skip creating
|
||||
// in case of wrong password.
|
||||
SecPassword FilePassword=Cmd->Password;
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
ConvertDosPassword(Arc,FilePassword);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
byte PswCheck[SIZE_PSWCHECK];
|
||||
DataIO.SetEncryption(false,Arc.FileHead.CryptMethod,&FilePassword,
|
||||
@ -483,9 +604,8 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
|
||||
// If header is damaged, we cannot rely on password check value,
|
||||
// because it can be damaged too.
|
||||
if (Arc.FileHead.Encrypted && Arc.FileHead.UsePswCheck &&
|
||||
memcmp(Arc.FileHead.PswCheck,PswCheck,SIZE_PSWCHECK)!=0 &&
|
||||
!Arc.BrokenHeader)
|
||||
if (Arc.FileHead.UsePswCheck && !Arc.BrokenHeader &&
|
||||
memcmp(Arc.FileHead.PswCheck,PswCheck,SIZE_PSWCHECK)!=0)
|
||||
{
|
||||
if (GlobalPassword) // For -p<pwd> or Ctrl+P to avoid the infinite loop.
|
||||
{
|
||||
@ -502,35 +622,43 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
|
||||
// Avoid new requests for unrar.dll to prevent the infinite loop
|
||||
// if app always returns the same password.
|
||||
#ifndef RARDLL
|
||||
#ifndef RARDLL
|
||||
continue; // Request a password again.
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#ifdef RARDLL
|
||||
#ifdef RARDLL
|
||||
// If we already have ERAR_EOPEN as result of missing volume,
|
||||
// we should not replace it with less precise ERAR_BAD_PASSWORD.
|
||||
if (Cmd->DllError!=ERAR_EOPEN)
|
||||
Cmd->DllError=ERAR_BAD_PASSWORD;
|
||||
#endif
|
||||
#endif
|
||||
ErrHandler.SetErrorCode(RARX_BADPWD);
|
||||
ExtrFile=false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
DataIO.SetEncryption(false,CRYPT_NONE,NULL,NULL,NULL,0,NULL,NULL);
|
||||
|
||||
#ifdef RARDLL
|
||||
if (*Cmd->DllDestName!=0)
|
||||
wcsncpyz(DestFileName,Cmd->DllDestName,ASIZE(DestFileName));
|
||||
#endif
|
||||
|
||||
if (ExtrFile && Command!='P' && !Cmd->Test && !Cmd->AbsoluteLinks &&
|
||||
ConvertSymlinkPaths)
|
||||
ExtrFile=LinksToDirs(DestFileName,Cmd->ExtrPath,LastCheckedSymlink);
|
||||
|
||||
File CurFile;
|
||||
|
||||
bool LinkEntry=Arc.FileHead.RedirType!=FSREDIR_NONE;
|
||||
if (LinkEntry && Arc.FileHead.RedirType!=FSREDIR_FILECOPY)
|
||||
if (LinkEntry && (Arc.FileHead.RedirType!=FSREDIR_FILECOPY))
|
||||
{
|
||||
if (ExtrFile && Command!='P' && !Cmd->Test)
|
||||
{
|
||||
// Overwrite prompt for symbolic and hard links.
|
||||
// Overwrite prompt for symbolic and hard links and when we move
|
||||
// a temporary file to the file reference instead of copying it.
|
||||
bool UserReject=false;
|
||||
if (FileExist(DestFileName) && !UserReject)
|
||||
FileCreate(Cmd,NULL,DestFileName,ASIZE(DestFileName),&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime);
|
||||
@ -632,7 +760,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
|
||||
uint64 Preallocated=0;
|
||||
if (!TestMode && !Arc.BrokenHeader && Arc.FileHead.UnpSize>1000000 &&
|
||||
Arc.FileHead.PackSize*1024>Arc.FileHead.UnpSize &&
|
||||
Arc.FileHead.PackSize*1024>Arc.FileHead.UnpSize && Arc.IsSeekable() &&
|
||||
(Arc.FileHead.UnpSize<100000000 || Arc.FileLength()>Arc.FileHead.PackSize))
|
||||
{
|
||||
CurFile.Prealloc(Arc.FileHead.UnpSize);
|
||||
@ -650,23 +778,51 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
|
||||
if (Type==FSREDIR_HARDLINK || Type==FSREDIR_FILECOPY)
|
||||
{
|
||||
wchar RedirName[NM];
|
||||
|
||||
// 2022.11.15: Might be needed when unpacking WinRAR 5.0 links with
|
||||
// Unix RAR. WinRAR 5.0 used \ path separators here, when beginning
|
||||
// from 5.10 even Windows version uses / internally and converts
|
||||
// them to \ when reading FHEXTRA_REDIR.
|
||||
// We must perform this conversion before ConvertPath call,
|
||||
// so paths mixing different slashes like \dir1/dir2\file are
|
||||
// processed correctly.
|
||||
SlashToNative(Arc.FileHead.RedirName,RedirName,ASIZE(RedirName));
|
||||
|
||||
ConvertPath(RedirName,RedirName,ASIZE(RedirName));
|
||||
|
||||
wchar NameExisting[NM];
|
||||
ExtrPrepareName(Arc,Arc.FileHead.RedirName,NameExisting,ASIZE(NameExisting));
|
||||
ExtrPrepareName(Arc,RedirName,NameExisting,ASIZE(NameExisting));
|
||||
if (FileCreateMode && *NameExisting!=0) // *NameExisting can be 0 in case of excessive -ap switch.
|
||||
if (Type==FSREDIR_HARDLINK)
|
||||
LinkSuccess=ExtractHardlink(Cmd,DestFileName,NameExisting,ASIZE(NameExisting));
|
||||
else
|
||||
LinkSuccess=ExtractFileCopy(CurFile,Arc.FileName,DestFileName,NameExisting,ASIZE(NameExisting));
|
||||
LinkSuccess=ExtractFileCopy(CurFile,Arc.FileName,RedirName,DestFileName,NameExisting,ASIZE(NameExisting),Arc.FileHead.UnpSize);
|
||||
}
|
||||
else
|
||||
if (Type==FSREDIR_UNIXSYMLINK || Type==FSREDIR_WINSYMLINK || Type==FSREDIR_JUNCTION)
|
||||
{
|
||||
if (FileCreateMode)
|
||||
LinkSuccess=ExtractSymlink(Cmd,DataIO,Arc,DestFileName);
|
||||
{
|
||||
bool UpLink;
|
||||
LinkSuccess=ExtractSymlink(Cmd,DataIO,Arc,DestFileName,UpLink);
|
||||
ConvertSymlinkPaths|=LinkSuccess && UpLink;
|
||||
|
||||
// We do not actually need to reset the cache here if we cache
|
||||
// only the single last checked path, because at this point
|
||||
// it will always contain the link own path and link can't
|
||||
// overwrite its parent folder. But if we ever decide to cache
|
||||
// several already checked paths, we'll need to reset them here.
|
||||
// Otherwise if no files were created in one of such paths,
|
||||
// let's say because of file create error, it might be possible
|
||||
// to overwrite the path with link and avoid checks. We keep this
|
||||
// code here as a reminder in case of possible modifications.
|
||||
LastCheckedSymlink.clear(); // Reset cache for safety reason.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uiMsg(UIERROR_UNKNOWNEXTRA,Arc.FileName,DestFileName);
|
||||
uiMsg(UIERROR_UNKNOWNEXTRA,Arc.FileName,ArcFileName);
|
||||
LinkSuccess=false;
|
||||
}
|
||||
|
||||
@ -690,6 +846,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat)
|
||||
Unp->Init(Arc.FileHead.WinSize,Arc.FileHead.Solid);
|
||||
Unp->SetDestSize(Arc.FileHead.UnpSize);
|
||||
#ifndef SFX_MODULE
|
||||
// RAR 1.3 - 1.5 archives do not set per file solid flag.
|
||||
if (Arc.Format!=RARFMT50 && Arc.FileHead.UnpVer<=15)
|
||||
Unp->DoUnpack(15,FileCount>1 && Arc.Solid);
|
||||
else
|
||||
@ -847,13 +1004,54 @@ void CmdExtract::UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize)
|
||||
}
|
||||
|
||||
|
||||
bool CmdExtract::ExtractFileCopy(File &New,wchar *ArcName,wchar *NameNew,wchar *NameExisting,size_t NameExistingSize)
|
||||
bool CmdExtract::ExtractFileCopy(File &New,wchar *ArcName,const wchar *RedirName,wchar *NameNew,wchar *NameExisting,size_t NameExistingSize,int64 UnpSize)
|
||||
{
|
||||
SlashToNative(NameExisting,NameExisting,NameExistingSize); // Not needed for RAR 5.1+ archives.
|
||||
|
||||
File Existing;
|
||||
if (!Existing.WOpen(NameExisting))
|
||||
if (!Existing.Open(NameExisting))
|
||||
{
|
||||
bool OpenFailed=true;
|
||||
// If we couldn't find the existing file, check if match is present
|
||||
// in temporary reference sources list.
|
||||
for (size_t I=0;I<RefList.Size();I++)
|
||||
if (wcscmp(RedirName,RefList[I].RefName)==0 && RefList[I].TmpName!=NULL)
|
||||
{
|
||||
// If only one reference left targeting to this temporary file,
|
||||
// it is faster to move the file instead of copying and deleting it.
|
||||
bool RefMove=RefList[I].RefCount-- == 1;
|
||||
NameExisting=RefList[I].TmpName;
|
||||
if (RefMove) // Only one reference left for this temporary file.
|
||||
{
|
||||
New.Delete(); // Delete the previously opened destination file.
|
||||
// Try moving the file first.
|
||||
bool MoveFailed=!RenameFile(NameExisting,NameNew);
|
||||
if (MoveFailed)
|
||||
{
|
||||
// If move failed, re-create the destination and try coping.
|
||||
if (!New.WCreate(NameNew,FMF_WRITE|FMF_SHAREREAD))
|
||||
return false;
|
||||
RefMove=false; // Try copying below.
|
||||
}
|
||||
else
|
||||
{
|
||||
// If moved successfully, reopen the destination file and seek to
|
||||
// end for SetOpenFileTime() and possible Truncate() calls later.
|
||||
if (New.Open(NameNew))
|
||||
New.Seek(0,SEEK_END);
|
||||
// We already moved the file, so clean the name to not try
|
||||
// deleting non-existent temporary file later.
|
||||
free(RefList[I].TmpName);
|
||||
RefList[I].TmpName=NULL;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!RefMove)
|
||||
OpenFailed=!Existing.Open(NameExisting);
|
||||
break;
|
||||
}
|
||||
|
||||
if (OpenFailed)
|
||||
{
|
||||
ErrHandler.OpenErrorMsg(NameExisting);
|
||||
uiMsg(UIERROR_FILECOPY,ArcName,NameExisting,NameNew);
|
||||
uiMsg(UIERROR_FILECOPYHINT,ArcName);
|
||||
#ifdef RARDLL
|
||||
@ -861,8 +1059,9 @@ bool CmdExtract::ExtractFileCopy(File &New,wchar *ArcName,wchar *NameNew,wchar *
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Array<char> Buffer(0x100000);
|
||||
Array<byte> Buffer(0x100000);
|
||||
int64 CopySize=0;
|
||||
|
||||
while (true)
|
||||
@ -871,6 +1070,10 @@ bool CmdExtract::ExtractFileCopy(File &New,wchar *ArcName,wchar *NameNew,wchar *
|
||||
int ReadSize=Existing.Read(&Buffer[0],Buffer.Size());
|
||||
if (ReadSize==0)
|
||||
break;
|
||||
// Update only the current file progress in WinRAR, set the total to 0
|
||||
// to keep it as is. It looks better for WinRAR.
|
||||
uiExtractProgress(CopySize,UnpSize,0,0);
|
||||
|
||||
New.Write(&Buffer[0],ReadSize);
|
||||
CopySize+=ReadSize;
|
||||
}
|
||||
@ -881,6 +1084,16 @@ bool CmdExtract::ExtractFileCopy(File &New,wchar *ArcName,wchar *NameNew,wchar *
|
||||
|
||||
void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *DestName,size_t DestSize)
|
||||
{
|
||||
if (Cmd->Test)
|
||||
{
|
||||
// Destination name conversion isn't needed for simple archive test.
|
||||
// This check also allows to avoid issuing "Attempting to correct...
|
||||
// Renaming..." messages in MakeNameCompatible() below for problematic
|
||||
// names like aux.txt when testing an archive.
|
||||
wcsncpyz(DestName,ArcFileName,DestSize);
|
||||
return;
|
||||
}
|
||||
|
||||
wcsncpyz(DestName,Cmd->ExtrPath,DestSize);
|
||||
|
||||
if (*Cmd->ExtrPath!=0)
|
||||
@ -888,6 +1101,8 @@ void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *De
|
||||
wchar LastChar=*PointToLastChar(Cmd->ExtrPath);
|
||||
// We need IsPathDiv check here to correctly handle Unix forward slash
|
||||
// in the end of destination path in Windows: rar x arc dest/
|
||||
// so we call IsPathDiv first instead of just calling AddEndSlash,
|
||||
// which checks for only one type of path separator.
|
||||
// IsDriveDiv is needed for current drive dir: rar x arc d:
|
||||
if (!IsPathDiv(LastChar) && !IsDriveDiv(LastChar))
|
||||
{
|
||||
@ -919,19 +1134,13 @@ void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *De
|
||||
#endif
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
size_t ArcPathLength=wcslen(Cmd->ArcPath);
|
||||
wchar *ArcPath=*Cmd->ExclArcPath!=0 ? Cmd->ExclArcPath:Cmd->ArcPath;
|
||||
size_t ArcPathLength=wcslen(ArcPath);
|
||||
if (ArcPathLength>0)
|
||||
{
|
||||
size_t NameLength=wcslen(ArcFileName);
|
||||
|
||||
// Earlier we compared lengths only here, but then noticed a cosmetic bug
|
||||
// in WinRAR. When extracting a file reference from subfolder with
|
||||
// "Extract relative paths", so WinRAR sets ArcPath, if reference target
|
||||
// is missing, error message removed ArcPath both from reference and target
|
||||
// names. If target was stored in another folder, its name looked wrong.
|
||||
if (NameLength>=ArcPathLength &&
|
||||
wcsnicompc(Cmd->ArcPath,ArcFileName,ArcPathLength)==0 &&
|
||||
(IsPathDiv(Cmd->ArcPath[ArcPathLength-1]) ||
|
||||
if (NameLength>=ArcPathLength && wcsnicompc(ArcPath,ArcFileName,ArcPathLength)==0 &&
|
||||
(IsPathDiv(ArcPath[ArcPathLength-1]) ||
|
||||
IsPathDiv(ArcFileName[ArcPathLength]) || ArcFileName[ArcPathLength]==0))
|
||||
{
|
||||
ArcFileName+=Min(ArcPathLength,NameLength);
|
||||
@ -964,7 +1173,7 @@ void CmdExtract::ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *De
|
||||
// Must do after Cmd->ArcPath processing above, so file name and arc path
|
||||
// trailing spaces are in sync.
|
||||
if (!Cmd->AllowIncompatNames)
|
||||
MakeNameCompatible(DestName);
|
||||
MakeNameCompatible(DestName,DestSize);
|
||||
#endif
|
||||
|
||||
wchar DiskLetter=toupperw(DestName[0]);
|
||||
@ -1018,18 +1227,14 @@ bool CmdExtract::ExtrDllGetPassword()
|
||||
|
||||
|
||||
#ifndef RARDLL
|
||||
bool CmdExtract::ExtrGetPassword(Archive &Arc,const wchar *ArcFileName)
|
||||
bool CmdExtract::ExtrGetPassword(Archive &Arc,const wchar *ArcFileName,RarCheckPassword *CheckPwd)
|
||||
{
|
||||
if (!Cmd->Password.IsSet())
|
||||
{
|
||||
if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password)/* || !Cmd->Password.IsSet()*/)
|
||||
if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password,CheckPwd)/* || !Cmd->Password.IsSet()*/)
|
||||
{
|
||||
// Suppress "test is ok" message if user cancelled the password prompt.
|
||||
// 2019.03.23: If some archives are tested ok and prompt is cancelled for others,
|
||||
// do we really need to suppress "test is ok"? Also if we set an empty password
|
||||
// and "Use for all archives" in WinRAR Ctrl+P and skip some encrypted archives.
|
||||
// We commented out this UIERROR_INCERRCOUNT for now.
|
||||
// uiMsg(UIERROR_INCERRCOUNT);
|
||||
uiMsg(UIERROR_INCERRCOUNT);
|
||||
return false;
|
||||
}
|
||||
Cmd->ManualPassword=true;
|
||||
@ -1044,7 +1249,7 @@ bool CmdExtract::ExtrGetPassword(Archive &Arc,const wchar *ArcFileName)
|
||||
case -1:
|
||||
ErrHandler.Exit(RARX_USERBREAK);
|
||||
case 2:
|
||||
if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password))
|
||||
if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password,CheckPwd))
|
||||
return false;
|
||||
break;
|
||||
case 3:
|
||||
@ -1120,6 +1325,8 @@ void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName)
|
||||
DirExist=FileExist(DestFileName) && IsDir(GetFileAttr(DestFileName));
|
||||
if (!DirExist)
|
||||
{
|
||||
if (!Cmd->AbsoluteLinks && ConvertSymlinkPaths)
|
||||
LinksToDirs(DestFileName,Cmd->ExtrPath,LastCheckedSymlink);
|
||||
CreatePath(DestFileName,true,Cmd->DisableNames);
|
||||
MDCode=MakeDir(DestFileName,!Cmd->IgnoreGeneralAttr,Arc.FileHead.FileAttr);
|
||||
}
|
||||
@ -1201,6 +1408,8 @@ bool CmdExtract::ExtrCreateFile(Archive &Arc,File &CurFile)
|
||||
|
||||
MakeNameUsable(DestFileName,true);
|
||||
|
||||
if (!Cmd->AbsoluteLinks && ConvertSymlinkPaths)
|
||||
LinksToDirs(DestFileName,Cmd->ExtrPath,LastCheckedSymlink);
|
||||
CreatePath(DestFileName,true,Cmd->DisableNames);
|
||||
if (FileCreate(Cmd,&CurFile,DestFileName,ASIZE(DestFileName),&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime,true))
|
||||
{
|
||||
@ -1247,31 +1456,59 @@ bool CmdExtract::CheckUnpVer(Archive &Arc,const wchar *ArcFileName)
|
||||
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
// To speed up solid volumes extraction, try to find a non-first start volume,
|
||||
// which still allows to unpack all files. It is possible for independent
|
||||
// solid volumes with solid statistics reset in the beginning.
|
||||
bool CmdExtract::DetectStartVolume(const wchar *VolName,bool NewNumbering)
|
||||
// Find non-matched reference sources in solid and non-solid archives.
|
||||
// Detect the optimal start position for semi-solid archives
|
||||
// and optimal start volume for independent solid volumes.
|
||||
//
|
||||
// Alternatively we could collect references while extracting an archive
|
||||
// and perform the second extraction pass for references only.
|
||||
// But it would be slower for solid archives than scaning headers
|
||||
// in first pass and extracting everything in second, as implemented now.
|
||||
//
|
||||
void CmdExtract::AnalyzeArchive(const wchar *ArcName,bool Volume,bool NewNumbering)
|
||||
{
|
||||
FreeAnalyzeData(); // If processing non-first archive in multiple archives set.
|
||||
|
||||
wchar *ArgName=Cmd->FileArgs.GetString();
|
||||
Cmd->FileArgs.Rewind();
|
||||
if (ArgName!=NULL && (wcscmp(ArgName,L"*")==0 || wcscmp(ArgName,L"*.*")==0))
|
||||
return false; // No need to check further for * and *.* masks.
|
||||
|
||||
wchar StartName[NM];
|
||||
*StartName=0;
|
||||
return; // No need to check further for * and *.* masks.
|
||||
|
||||
// Start search from first volume if all volumes preceding current are available.
|
||||
wchar NextName[NM];
|
||||
GetFirstVolIfFullSet(VolName,NewNumbering,NextName,ASIZE(NextName));
|
||||
if (Volume)
|
||||
GetFirstVolIfFullSet(ArcName,NewNumbering,NextName,ASIZE(NextName));
|
||||
else
|
||||
wcsncpyz(NextName,ArcName,ASIZE(NextName));
|
||||
|
||||
bool Matched=false;
|
||||
while (!Matched)
|
||||
bool MatchFound=false;
|
||||
bool PrevMatched=false;
|
||||
bool OpenNext=false;
|
||||
|
||||
bool FirstVolume=true;
|
||||
|
||||
// We shall set FirstFile once for all volumes and not for each volume.
|
||||
// So we do not reuse the outdated Analyze->StartPos from previous volume
|
||||
// if extracted file resides completely in the beginning of current one.
|
||||
bool FirstFile=true;
|
||||
|
||||
while (true)
|
||||
{
|
||||
Archive Arc(Cmd);
|
||||
if (!Arc.Open(NextName) || !Arc.IsArchive(false) || !Arc.Volume)
|
||||
if (!Arc.Open(NextName) || !Arc.IsArchive(false))
|
||||
{
|
||||
if (OpenNext)
|
||||
{
|
||||
// If we couldn't open trailing volumes, we can't set early exit
|
||||
// parameters. It is possible that some volume are on removable media
|
||||
// and will be provided by user when extracting.
|
||||
*Analyze->EndName=0;
|
||||
Analyze->EndPos=0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
bool OpenNext=false;
|
||||
OpenNext=false;
|
||||
while (Arc.ReadHeader()>0)
|
||||
{
|
||||
Wait();
|
||||
@ -1284,17 +1521,88 @@ bool CmdExtract::DetectStartVolume(const wchar *VolName,bool NewNumbering)
|
||||
}
|
||||
if (HeaderType==HEAD_FILE)
|
||||
{
|
||||
if ((Arc.Format==RARFMT14 || Arc.Format==RARFMT15) && Arc.FileHead.UnpVer<=15)
|
||||
{
|
||||
// RAR versions earlier than 2.0 do not set per file solid flag.
|
||||
// They have only the global archive solid flag, so we can't
|
||||
// reliably analyze them here.
|
||||
OpenNext=false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!Arc.FileHead.SplitBefore)
|
||||
{
|
||||
if (!Arc.FileHead.Solid) // Can start extraction from here.
|
||||
wcsncpyz(StartName,NextName,ASIZE(StartName));
|
||||
if (!MatchFound && !Arc.FileHead.Solid) // Can start extraction from here.
|
||||
{
|
||||
// We would gain nothing and unnecessarily complicate extraction
|
||||
// if we set StartName for first volume or StartPos for first
|
||||
// archived file.
|
||||
if (!FirstVolume)
|
||||
wcsncpyz(Analyze->StartName,NextName,ASIZE(Analyze->StartName));
|
||||
|
||||
// We shall set FirstFile once for all volumes for this code
|
||||
// to work properly. Alternatively we could append
|
||||
// "|| Analyze->StartPos!=0" to the condition, so we do not reuse
|
||||
// the outdated Analyze->StartPos value from previous volume.
|
||||
if (!FirstFile)
|
||||
Analyze->StartPos=Arc.CurBlockPos;
|
||||
}
|
||||
|
||||
if (Cmd->IsProcessFile(Arc.FileHead,NULL,MATCH_WILDSUBPATH,0,NULL,0)!=0)
|
||||
{
|
||||
Matched=true; // First matched file found, must stop further scan.
|
||||
MatchFound = true;
|
||||
PrevMatched = true;
|
||||
|
||||
// Reset the previously set early exit position, if any, because
|
||||
// we found a new matched file.
|
||||
Analyze->EndPos=0;
|
||||
|
||||
// Matched file reference pointing at maybe non-matched source file.
|
||||
// Even though we know RedirName, we can't check if source file
|
||||
// is certainly non-matched, because it can be filtered out by
|
||||
// date or attributes, which we do not know here.
|
||||
if (Arc.FileHead.RedirType==FSREDIR_FILECOPY)
|
||||
{
|
||||
bool AlreadyAdded=false;
|
||||
for (size_t I=0;I<RefList.Size();I++)
|
||||
if (wcscmp(Arc.FileHead.RedirName,RefList[I].RefName)==0)
|
||||
{
|
||||
// Increment the reference count if we added such reference
|
||||
// source earlier.
|
||||
RefList[I].RefCount++;
|
||||
AlreadyAdded=true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Limit the maximum size of reference sources list to some
|
||||
// sensible value to prevent the excessive memory allocation.
|
||||
size_t MaxListSize=1000000;
|
||||
|
||||
if (!AlreadyAdded && RefList.Size()<MaxListSize)
|
||||
{
|
||||
ExtractRef Ref={0};
|
||||
Ref.RefName=wcsdup(Arc.FileHead.RedirName);
|
||||
Ref.RefCount=1;
|
||||
RefList.Push(Ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PrevMatched) // First non-matched item after matched.
|
||||
{
|
||||
// We would perform the unnecessarily string comparison
|
||||
// when extracting if we set this value for first volume
|
||||
// or non-volume archive.
|
||||
if (!FirstVolume)
|
||||
wcsncpyz(Analyze->EndName,NextName,ASIZE(Analyze->EndName));
|
||||
Analyze->EndPos=Arc.CurBlockPos;
|
||||
}
|
||||
PrevMatched=false;
|
||||
}
|
||||
}
|
||||
|
||||
FirstFile=false;
|
||||
if (Arc.FileHead.SplitAfter)
|
||||
{
|
||||
OpenNext=true; // Allow open next volume.
|
||||
@ -1305,16 +1613,25 @@ bool CmdExtract::DetectStartVolume(const wchar *VolName,bool NewNumbering)
|
||||
}
|
||||
Arc.Close();
|
||||
|
||||
if (!OpenNext)
|
||||
break;
|
||||
|
||||
if (Volume && OpenNext)
|
||||
{
|
||||
NextVolumeName(NextName,ASIZE(NextName),!Arc.NewNumbering);
|
||||
}
|
||||
bool NewStartFound=wcscmp(VolName,StartName)!=0;
|
||||
if (NewStartFound) // Found a new volume to start extraction.
|
||||
wcsncpyz(ArcName,StartName,ASIZE(ArcName));
|
||||
FirstVolume=false;
|
||||
|
||||
return NewStartFound;
|
||||
// Needed for multivolume archives. Added in case some 'break'
|
||||
// will quit early from loop above, so we do not set it in the loop.
|
||||
// Now it can happen for hypothetical archive without file records
|
||||
// and with HEAD_ENDARC record.
|
||||
FirstFile=false;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// If file references are present, we can't reliably skip in semi-solid
|
||||
// archives, because reference source can be present in skipped data.
|
||||
if (RefList.Size()!=0)
|
||||
memset(Analyze,0,sizeof(*Analyze));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
34
deps/unrar/extract.hpp
vendored
34
deps/unrar/extract.hpp
vendored
@ -6,13 +6,32 @@ enum EXTRACT_ARC_CODE {EXTRACT_ARC_NEXT,EXTRACT_ARC_REPEAT};
|
||||
class CmdExtract
|
||||
{
|
||||
private:
|
||||
struct ExtractRef
|
||||
{
|
||||
wchar *RefName;
|
||||
wchar *TmpName;
|
||||
uint64 RefCount;
|
||||
};
|
||||
Array<ExtractRef> RefList;
|
||||
|
||||
struct AnalyzeData
|
||||
{
|
||||
wchar StartName[NM];
|
||||
uint64 StartPos;
|
||||
wchar EndName[NM];
|
||||
uint64 EndPos;
|
||||
} *Analyze;
|
||||
|
||||
bool ArcAnalyzed;
|
||||
|
||||
void FreeAnalyzeData();
|
||||
EXTRACT_ARC_CODE ExtractArchive();
|
||||
bool ExtractFileCopy(File &New,wchar *ArcName,wchar *NameNew,wchar *NameExisting,size_t NameExistingSize);
|
||||
bool ExtractFileCopy(File &New,wchar *ArcName,const wchar *RedirName,wchar *NameNew,wchar *NameExisting,size_t NameExistingSize,int64 UnpSize);
|
||||
void ExtrPrepareName(Archive &Arc,const wchar *ArcFileName,wchar *DestName,size_t DestSize);
|
||||
#ifdef RARDLL
|
||||
bool ExtrDllGetPassword();
|
||||
#else
|
||||
bool ExtrGetPassword(Archive &Arc,const wchar *ArcFileName);
|
||||
bool ExtrGetPassword(Archive &Arc,const wchar *ArcFileName,RarCheckPassword *CheckPwd);
|
||||
#endif
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
void ConvertDosPassword(Archive &Arc,SecPassword &DestPwd);
|
||||
@ -21,7 +40,7 @@ class CmdExtract
|
||||
bool ExtrCreateFile(Archive &Arc,File &CurFile);
|
||||
bool CheckUnpVer(Archive &Arc,const wchar *ArcFileName);
|
||||
#ifndef SFX_MODULE
|
||||
bool DetectStartVolume(const wchar *VolName,bool NewNumbering);
|
||||
void AnalyzeArchive(const wchar *ArcName,bool Volume,bool NewNumbering);
|
||||
void GetFirstVolIfFullSet(const wchar *SrcName,bool NewNumbering,wchar *DestName,size_t DestSize);
|
||||
#endif
|
||||
|
||||
@ -52,6 +71,15 @@ class CmdExtract
|
||||
bool PrevProcessed; // If previous file was successfully extracted or tested.
|
||||
wchar DestFileName[NM];
|
||||
bool PasswordCancelled;
|
||||
|
||||
// In Windows it is set to true if at least one symlink with ".."
|
||||
// in target was extracted.
|
||||
bool ConvertSymlinkPaths;
|
||||
|
||||
// Last path checked for symlinks. We use it to improve the performance,
|
||||
// so we do not check recently checked folders again.
|
||||
std::wstring LastCheckedSymlink;
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
|
||||
bool Fat32,NotFat32;
|
||||
#endif
|
||||
|
8
deps/unrar/filcreat.cpp
vendored
8
deps/unrar/filcreat.cpp
vendored
@ -1,9 +1,9 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
// If NewFile==NULL, we delete created file after user confirmation.
|
||||
// It is useful we we need to overwrite an existing folder or file,
|
||||
// It is useful if we need to overwrite an existing folder or file,
|
||||
// but need user confirmation for that.
|
||||
bool FileCreate(RAROptions *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize,
|
||||
bool FileCreate(CommandData *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize,
|
||||
bool *UserReject,int64 FileSize,RarTime *FileTime,bool WriteOnly)
|
||||
{
|
||||
if (UserReject!=NULL)
|
||||
@ -44,7 +44,9 @@ bool FileCreate(RAROptions *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize,
|
||||
}
|
||||
|
||||
// Try to truncate the existing file first instead of delete,
|
||||
// so we preserve existing file permissions such as NTFS permissions.
|
||||
// so we preserve existing file permissions, such as NTFS permissions,
|
||||
// also as "Compressed" attribute and hard links. In GUI version we avoid
|
||||
// deleting an existing file for non-.rar archive formats as well.
|
||||
uint FileMode=WriteOnly ? FMF_WRITE|FMF_SHAREREAD:FMF_UPDATE|FMF_SHAREREAD;
|
||||
if (NewFile!=NULL && NewFile->Create(Name,FileMode))
|
||||
return true;
|
||||
|
2
deps/unrar/filcreat.hpp
vendored
2
deps/unrar/filcreat.hpp
vendored
@ -1,7 +1,7 @@
|
||||
#ifndef _RAR_FILECREATE_
|
||||
#define _RAR_FILECREATE_
|
||||
|
||||
bool FileCreate(RAROptions *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize,
|
||||
bool FileCreate(CommandData *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize,
|
||||
bool *UserReject,int64 FileSize=INT64NDF,
|
||||
RarTime *FileTime=NULL,bool WriteOnly=false);
|
||||
|
||||
|
102
deps/unrar/file.cpp
vendored
102
deps/unrar/file.cpp
vendored
@ -7,6 +7,7 @@ File::File()
|
||||
NewFile=false;
|
||||
LastWrite=false;
|
||||
HandleType=FILE_HANDLENORMAL;
|
||||
LineInput=false;
|
||||
SkipClose=false;
|
||||
ErrorType=FILE_SUCCESS;
|
||||
OpenShared=false;
|
||||
@ -14,11 +15,11 @@ File::File()
|
||||
AllowExceptions=true;
|
||||
PreserveAtime=false;
|
||||
#ifdef _WIN_ALL
|
||||
NoSequentialRead=false;
|
||||
CreateMode=FMF_UNDEFINED;
|
||||
#endif
|
||||
ReadErrorMode=FREM_ASK;
|
||||
TruncatedAfterReadError=false;
|
||||
CurFilePos=0;
|
||||
}
|
||||
|
||||
|
||||
@ -58,7 +59,7 @@ bool File::Open(const wchar *Name,uint Mode)
|
||||
uint ShareMode=(Mode & FMF_OPENEXCLUSIVE) ? 0 : FILE_SHARE_READ;
|
||||
if (OpenShared)
|
||||
ShareMode|=FILE_SHARE_WRITE;
|
||||
uint Flags=NoSequentialRead ? 0:FILE_FLAG_SEQUENTIAL_SCAN;
|
||||
uint Flags=FILE_FLAG_SEQUENTIAL_SCAN;
|
||||
FindData FD;
|
||||
if (PreserveAtime)
|
||||
Access|=FILE_WRITE_ATTRIBUTES; // Needed to preserve atime.
|
||||
@ -379,10 +380,11 @@ int File::Read(void *Data,size_t Size)
|
||||
|
||||
if (ReadErrorMode==FREM_IGNORE)
|
||||
FilePos=Tell();
|
||||
int ReadSize;
|
||||
int TotalRead=0;
|
||||
while (true)
|
||||
{
|
||||
ReadSize=DirectRead(Data,Size);
|
||||
int ReadSize=DirectRead(Data,Size);
|
||||
|
||||
if (ReadSize==-1)
|
||||
{
|
||||
ErrorType=FILE_READERROR;
|
||||
@ -396,6 +398,8 @@ int File::Read(void *Data,size_t Size)
|
||||
size_t SizeToRead=Min(Size-I,512);
|
||||
int ReadCode=DirectRead(Data,SizeToRead);
|
||||
ReadSize+=(ReadCode==-1) ? 512:ReadCode;
|
||||
if (ReadSize!=-1)
|
||||
TotalRead+=ReadSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -415,9 +419,28 @@ int File::Read(void *Data,size_t Size)
|
||||
ErrHandler.ReadError(FileName);
|
||||
}
|
||||
}
|
||||
TotalRead+=ReadSize; // If ReadSize is -1, TotalRead is also set to -1 here.
|
||||
|
||||
if (HandleType==FILE_HANDLESTD && !LineInput && ReadSize>0 && (uint)ReadSize<Size)
|
||||
{
|
||||
// Unlike regular files, for pipe we can read only as much as was
|
||||
// written at the other end of pipe. We had seen data coming in small
|
||||
// ~80 byte chunks when piping from 'type arc.rar'. Extraction code
|
||||
// would fail if we read an incomplete archive header from stdin.
|
||||
// So here we ensure that requested size is completely read.
|
||||
// But we return the available data immediately in "line input" mode,
|
||||
// when processing user's input in console prompts. Otherwise apps
|
||||
// piping user responses to multiple Ask() prompts can hang if no more
|
||||
// data is available yet and pipe isn't closed.
|
||||
Data=(byte*)Data+ReadSize;
|
||||
Size-=ReadSize;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ReadSize; // It can return -1 only if AllowExceptions is disabled.
|
||||
if (TotalRead>0) // Can be -1 for error and AllowExceptions disabled.
|
||||
CurFilePos+=TotalRead;
|
||||
return TotalRead; // It can return -1 only if AllowExceptions is disabled.
|
||||
}
|
||||
|
||||
|
||||
@ -499,6 +522,36 @@ bool File::RawSeek(int64 Offset,int Method)
|
||||
{
|
||||
if (hFile==FILE_BAD_HANDLE)
|
||||
return true;
|
||||
if (!IsSeekable()) // To extract archives from stdin with -si.
|
||||
{
|
||||
// We tried to dynamically allocate 32 KB buffer here, but it improved
|
||||
// speed in Windows 10 by mere ~1.5%.
|
||||
byte Buf[4096];
|
||||
if (Method==SEEK_CUR || Method==SEEK_SET && Offset>=CurFilePos)
|
||||
{
|
||||
uint64 SkipSize=Method==SEEK_CUR ? Offset:Offset-CurFilePos;
|
||||
while (SkipSize>0) // Reading to emulate seek forward.
|
||||
{
|
||||
int ReadSize=Read(Buf,(size_t)Min(SkipSize,ASIZE(Buf)));
|
||||
if (ReadSize<=0)
|
||||
return false;
|
||||
SkipSize-=ReadSize;
|
||||
CurFilePos+=ReadSize;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// May need it in FileLength() in Archive::UnexpEndArcMsg() when unpacking
|
||||
// RAR 4.x archives without the end of archive block created with -en.
|
||||
if (Method==SEEK_END)
|
||||
{
|
||||
int ReadSize;
|
||||
while ((ReadSize=Read(Buf,ASIZE(Buf)))>0)
|
||||
CurFilePos+=ReadSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // Backward seek on unseekable file.
|
||||
}
|
||||
if (Offset<0 && Method!=SEEK_SET)
|
||||
{
|
||||
Offset=(Method==SEEK_CUR ? Tell():FileLength())+Offset;
|
||||
@ -533,6 +586,8 @@ int64 File::Tell()
|
||||
ErrHandler.SeekError(FileName);
|
||||
else
|
||||
return -1;
|
||||
if (!IsSeekable())
|
||||
return CurFilePos;
|
||||
#ifdef _WIN_ALL
|
||||
LONG HighDist=0;
|
||||
uint LowDist=SetFilePointer(hFile,0,&HighDist,FILE_CURRENT);
|
||||
@ -683,17 +738,40 @@ void File::SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta)
|
||||
}
|
||||
|
||||
|
||||
void File::GetOpenFileTime(RarTime *ft)
|
||||
#ifdef _UNIX
|
||||
void File::StatToRarTime(struct stat &st,RarTime *ftm,RarTime *ftc,RarTime *fta)
|
||||
{
|
||||
#ifdef UNIX_TIME_NS
|
||||
#if defined(_APPLE)
|
||||
if (ftm!=NULL) ftm->SetUnixNS(st.st_mtimespec.tv_sec*(uint64)1000000000+st.st_mtimespec.tv_nsec);
|
||||
if (ftc!=NULL) ftc->SetUnixNS(st.st_ctimespec.tv_sec*(uint64)1000000000+st.st_ctimespec.tv_nsec);
|
||||
if (fta!=NULL) fta->SetUnixNS(st.st_atimespec.tv_sec*(uint64)1000000000+st.st_atimespec.tv_nsec);
|
||||
#else
|
||||
if (ftm!=NULL) ftm->SetUnixNS(st.st_mtim.tv_sec*(uint64)1000000000+st.st_mtim.tv_nsec);
|
||||
if (ftc!=NULL) ftc->SetUnixNS(st.st_ctim.tv_sec*(uint64)1000000000+st.st_ctim.tv_nsec);
|
||||
if (fta!=NULL) fta->SetUnixNS(st.st_atim.tv_sec*(uint64)1000000000+st.st_atim.tv_nsec);
|
||||
#endif
|
||||
#else
|
||||
if (ftm!=NULL) ftm->SetUnix(st.st_mtime);
|
||||
if (ftc!=NULL) ftc->SetUnix(st.st_ctime);
|
||||
if (fta!=NULL) fta->SetUnix(st.st_atime);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void File::GetOpenFileTime(RarTime *ftm,RarTime *ftc,RarTime *fta)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
FILETIME FileTime;
|
||||
GetFileTime(hFile,NULL,NULL,&FileTime);
|
||||
ft->SetWinFT(&FileTime);
|
||||
#endif
|
||||
#if defined(_UNIX) || defined(_EMX)
|
||||
FILETIME ctime,atime,mtime;
|
||||
GetFileTime(hFile,&ctime,&atime,&mtime);
|
||||
if (ftm!=NULL) ftm->SetWinFT(&mtime);
|
||||
if (ftc!=NULL) ftc->SetWinFT(&ctime);
|
||||
if (fta!=NULL) fta->SetWinFT(&atime);
|
||||
#elif defined(_UNIX)
|
||||
struct stat st;
|
||||
fstat(GetFD(),&st);
|
||||
ft->SetUnix(st.st_mtime);
|
||||
StatToRarTime(st,ftm,ftc,fta);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
27
deps/unrar/file.hpp
vendored
27
deps/unrar/file.hpp
vendored
@ -14,8 +14,6 @@
|
||||
#define FILE_BAD_HANDLE NULL
|
||||
#endif
|
||||
|
||||
class RAROptions;
|
||||
|
||||
enum FILE_HANDLETYPE {FILE_HANDLENORMAL,FILE_HANDLESTD};
|
||||
|
||||
enum FILE_ERRORTYPE {FILE_SUCCESS,FILE_NOTFOUND,FILE_READERROR};
|
||||
@ -59,6 +57,16 @@ class File
|
||||
FileHandle hFile;
|
||||
bool LastWrite;
|
||||
FILE_HANDLETYPE HandleType;
|
||||
|
||||
// If we read the user input in console prompts from stdin, we shall
|
||||
// process the available line immediately, not waiting for rest of data.
|
||||
// Otherwise apps piping user responses to multiple Ask() prompts can
|
||||
// hang if no more data is available yet and pipe isn't closed.
|
||||
// If we read RAR archive or other file data from stdin, we shall collect
|
||||
// the entire requested block as long as pipe isn't closed, so we get
|
||||
// complete archive headers, not split between different reads.
|
||||
bool LineInput;
|
||||
|
||||
bool SkipClose;
|
||||
FILE_READ_ERROR_MODE ReadErrorMode;
|
||||
bool NewFile;
|
||||
@ -70,12 +78,17 @@ class File
|
||||
#endif
|
||||
bool PreserveAtime;
|
||||
bool TruncatedAfterReadError;
|
||||
|
||||
int64 CurFilePos; // Used for forward seeks in stdin files.
|
||||
protected:
|
||||
bool OpenShared; // Set by 'Archive' class.
|
||||
public:
|
||||
wchar FileName[NM];
|
||||
|
||||
FILE_ERRORTYPE ErrorType;
|
||||
|
||||
byte *SeekBuf; // To read instead of seek for stdin files.
|
||||
static const size_t SeekBufSize=0x10000;
|
||||
public:
|
||||
File();
|
||||
virtual ~File();
|
||||
@ -106,11 +119,16 @@ class File
|
||||
void SetOpenFileTime(RarTime *ftm,RarTime *ftc=NULL,RarTime *fta=NULL);
|
||||
void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL);
|
||||
static void SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta);
|
||||
void GetOpenFileTime(RarTime *ft);
|
||||
#ifdef _UNIX
|
||||
static void StatToRarTime(struct stat &st,RarTime *ftm,RarTime *ftc,RarTime *fta);
|
||||
#endif
|
||||
void GetOpenFileTime(RarTime *ftm,RarTime *ftc=NULL,RarTime *fta=NULL);
|
||||
virtual bool IsOpened() {return hFile!=FILE_BAD_HANDLE;} // 'virtual' for MultiFile class.
|
||||
int64 FileLength();
|
||||
void SetHandleType(FILE_HANDLETYPE Type) {HandleType=Type;}
|
||||
void SetLineInputMode(bool Mode) {LineInput=Mode;}
|
||||
FILE_HANDLETYPE GetHandleType() {return HandleType;}
|
||||
bool IsSeekable() {return HandleType!=FILE_HANDLESTD;}
|
||||
bool IsDevice();
|
||||
static bool RemoveCreated();
|
||||
FileHandle GetHandle() {return hFile;}
|
||||
@ -119,9 +137,6 @@ class File
|
||||
int64 Copy(File &Dest,int64 Length=INT64NDF);
|
||||
void SetAllowDelete(bool Allow) {AllowDelete=Allow;}
|
||||
void SetExceptions(bool Allow) {AllowExceptions=Allow;}
|
||||
#ifdef _WIN_ALL
|
||||
void RemoveSequentialFlag() {NoSequentialRead=true;}
|
||||
#endif
|
||||
void SetPreserveAtime(bool Preserve) {PreserveAtime=Preserve;}
|
||||
bool IsTruncatedAfterReadError() {return TruncatedAfterReadError;}
|
||||
#ifdef _UNIX
|
||||
|
20
deps/unrar/filefn.cpp
vendored
20
deps/unrar/filefn.cpp
vendored
@ -320,7 +320,6 @@ bool SetFileAttr(const wchar *Name,uint Attr)
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
wchar *MkTemp(wchar *Name,size_t MaxSize)
|
||||
{
|
||||
size_t Length=wcslen(Name);
|
||||
@ -354,7 +353,6 @@ wchar *MkTemp(wchar *Name,size_t MaxSize)
|
||||
}
|
||||
return Name;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(SFX_MODULE)
|
||||
@ -397,7 +395,11 @@ void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,
|
||||
{
|
||||
#ifndef SILENT
|
||||
if ((Flags & CALCFSUM_SHOWPROGRESS)!=0)
|
||||
uiExtractProgress(TotalRead,FileLength,TotalRead,FileLength);
|
||||
{
|
||||
// Update only the current file progress in WinRAR, set the total to 0
|
||||
// to keep it as is. It looks better for WinRAR.
|
||||
uiExtractProgress(TotalRead,FileLength,0,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
|
||||
@ -517,6 +519,18 @@ bool SetFileCompression(const wchar *Name,bool State)
|
||||
CloseHandle(hFile);
|
||||
return RetCode!=0;
|
||||
}
|
||||
|
||||
|
||||
void ResetFileCache(const wchar *Name)
|
||||
{
|
||||
// To reset file cache in Windows it is enough to open it with
|
||||
// FILE_FLAG_NO_BUFFERING and then close it.
|
||||
HANDLE hSrc=CreateFile(Name,GENERIC_READ,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
NULL,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING,NULL);
|
||||
if (hSrc!=INVALID_HANDLE_VALUE)
|
||||
CloseHandle(hSrc);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
3
deps/unrar/filefn.hpp
vendored
3
deps/unrar/filefn.hpp
vendored
@ -27,9 +27,7 @@ bool IsDeleteAllowed(uint FileAttr);
|
||||
void PrepareToDelete(const wchar *Name);
|
||||
uint GetFileAttr(const wchar *Name);
|
||||
bool SetFileAttr(const wchar *Name,uint Attr);
|
||||
#if 0
|
||||
wchar* MkTemp(wchar *Name,size_t MaxSize);
|
||||
#endif
|
||||
|
||||
enum CALCFSUM_FLAGS {CALCFSUM_SHOWTEXT=1,CALCFSUM_SHOWPERCENT=2,CALCFSUM_SHOWPROGRESS=4,CALCFSUM_CURPOS=8};
|
||||
|
||||
@ -41,6 +39,7 @@ bool DelDir(const wchar *Name);
|
||||
|
||||
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
|
||||
bool SetFileCompression(const wchar *Name,bool State);
|
||||
void ResetFileCache(const wchar *Name);
|
||||
#endif
|
||||
|
||||
|
||||
|
12
deps/unrar/find.cpp
vendored
12
deps/unrar/find.cpp
vendored
@ -117,7 +117,7 @@ bool FindFile::FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink)
|
||||
if (hFind==INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
FindClose(hFind);
|
||||
#else
|
||||
#elif defined(_UNIX)
|
||||
char FindMaskA[NM];
|
||||
WideToChar(FindMask,FindMaskA,ASIZE(FindMaskA));
|
||||
|
||||
@ -143,15 +143,7 @@ bool FindFile::FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink)
|
||||
fd->FileAttr=st.st_mode;
|
||||
fd->Size=st.st_size;
|
||||
|
||||
#ifdef UNIX_TIME_NS
|
||||
fd->mtime.SetUnixNS(st.st_mtim.tv_sec*(uint64)1000000000+st.st_mtim.tv_nsec);
|
||||
fd->atime.SetUnixNS(st.st_atim.tv_sec*(uint64)1000000000+st.st_atim.tv_nsec);
|
||||
fd->ctime.SetUnixNS(st.st_ctim.tv_sec*(uint64)1000000000+st.st_ctim.tv_nsec);
|
||||
#else
|
||||
fd->mtime.SetUnix(st.st_mtime);
|
||||
fd->atime.SetUnix(st.st_atime);
|
||||
fd->ctime.SetUnix(st.st_ctime);
|
||||
#endif
|
||||
File::StatToRarTime(st,&fd->mtime,&fd->ctime,&fd->atime);
|
||||
|
||||
wcsncpyz(fd->Name,FindMask,ASIZE(fd->Name));
|
||||
#endif
|
||||
|
2
deps/unrar/getbits.cpp
vendored
2
deps/unrar/getbits.cpp
vendored
@ -5,7 +5,7 @@ BitInput::BitInput(bool AllocBuffer)
|
||||
ExternalBuffer=false;
|
||||
if (AllocBuffer)
|
||||
{
|
||||
// getbits32 attempts to read data from InAddr, ... InAddr+3 positions.
|
||||
// getbits*() attempt to read data from InAddr, ... InAddr+3 positions.
|
||||
// So let's allocate 3 additional bytes for situation, when we need to
|
||||
// read only 1 byte from the last position of buffer and avoid a crash
|
||||
// from access to next 3 bytes, which contents we do not need.
|
||||
|
14
deps/unrar/getbits.hpp
vendored
14
deps/unrar/getbits.hpp
vendored
@ -4,7 +4,7 @@
|
||||
class BitInput
|
||||
{
|
||||
public:
|
||||
enum BufferSize {MAX_SIZE=0x50000}; // Size of input buffer.
|
||||
enum BufferSize {MAX_SIZE=0x8000}; // Size of input buffer.
|
||||
|
||||
int InAddr; // Curent byte position in the buffer.
|
||||
int InBit; // Current bit position in the current byte.
|
||||
@ -33,21 +33,33 @@ class BitInput
|
||||
// Bit at (InAddr,InBit) has the highest position in returning data.
|
||||
uint getbits()
|
||||
{
|
||||
#if defined(LITTLE_ENDIAN) && defined(ALLOW_MISALIGNED)
|
||||
uint32 BitField=*(uint32*)(InBuf+InAddr);
|
||||
BitField=ByteSwap32(BitField);
|
||||
BitField >>= (16-InBit);
|
||||
#else
|
||||
uint BitField=(uint)InBuf[InAddr] << 16;
|
||||
BitField|=(uint)InBuf[InAddr+1] << 8;
|
||||
BitField|=(uint)InBuf[InAddr+2];
|
||||
BitField >>= (8-InBit);
|
||||
#endif
|
||||
return BitField & 0xffff;
|
||||
}
|
||||
|
||||
|
||||
// Return 32 bits from current position in the buffer.
|
||||
// Bit at (InAddr,InBit) has the highest position in returning data.
|
||||
uint getbits32()
|
||||
{
|
||||
#if defined(LITTLE_ENDIAN) && defined(ALLOW_MISALIGNED)
|
||||
uint32 BitField=*(uint32*)(InBuf+InAddr);
|
||||
BitField=ByteSwap32(BitField);
|
||||
#else
|
||||
uint BitField=(uint)InBuf[InAddr] << 24;
|
||||
BitField|=(uint)InBuf[InAddr+1] << 16;
|
||||
BitField|=(uint)InBuf[InAddr+2] << 8;
|
||||
BitField|=(uint)InBuf[InAddr+3];
|
||||
#endif
|
||||
BitField <<= InBit;
|
||||
BitField|=(uint)InBuf[InAddr+4] >> (8-InBit);
|
||||
return BitField & 0xffffffff;
|
||||
|
2
deps/unrar/global.cpp
vendored
2
deps/unrar/global.cpp
vendored
@ -1,6 +1,6 @@
|
||||
#define INCLUDEGLOBAL
|
||||
|
||||
#if defined(__BORLANDC__) || defined(_MSC_VER)
|
||||
#ifdef _MSC_VER
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
|
2
deps/unrar/hardlinks.cpp
vendored
2
deps/unrar/hardlinks.cpp
vendored
@ -1,7 +1,5 @@
|
||||
bool ExtractHardlink(CommandData *Cmd,wchar *NameNew,wchar *NameExisting,size_t NameExistingSize)
|
||||
{
|
||||
SlashToNative(NameExisting,NameExisting,NameExistingSize); // Not needed for RAR 5.1+ archives.
|
||||
|
||||
if (!FileExist(NameExisting))
|
||||
{
|
||||
uiMsg(UIERROR_HLINKCREATE,NameNew);
|
||||
|
2
deps/unrar/hash.cpp
vendored
2
deps/unrar/hash.cpp
vendored
@ -26,7 +26,7 @@ void HashValue::Init(HASH_TYPE Type)
|
||||
}
|
||||
|
||||
|
||||
bool HashValue::operator == (const HashValue &cmp)
|
||||
bool HashValue::operator == (const HashValue &cmp) const
|
||||
{
|
||||
if (Type==HASH_NONE || cmp.Type==HASH_NONE)
|
||||
return true;
|
||||
|
10
deps/unrar/hash.hpp
vendored
10
deps/unrar/hash.hpp
vendored
@ -6,8 +6,14 @@ enum HASH_TYPE {HASH_NONE,HASH_RAR14,HASH_CRC32,HASH_BLAKE2};
|
||||
struct HashValue
|
||||
{
|
||||
void Init(HASH_TYPE Type);
|
||||
bool operator == (const HashValue &cmp);
|
||||
bool operator != (const HashValue &cmp) {return !(*this==cmp);}
|
||||
|
||||
// Use the const member, so types on both sides of "==" match.
|
||||
// Otherwise clang -std=c++20 issues "ambiguity is between a regular call
|
||||
// to this operator and a call with the argument order reversed" warning.
|
||||
bool operator == (const HashValue &cmp) const;
|
||||
|
||||
// Not actually used now. Const member for same reason as operator == above.
|
||||
bool operator != (const HashValue &cmp) const {return !(*this==cmp);}
|
||||
|
||||
HASH_TYPE Type;
|
||||
union
|
||||
|
10
deps/unrar/headers.cpp
vendored
10
deps/unrar/headers.cpp
vendored
@ -49,13 +49,5 @@ FileHeader& FileHeader::operator = (FileHeader &hd)
|
||||
|
||||
void MainHeader::Reset()
|
||||
{
|
||||
HighPosAV=0;
|
||||
PosAV=0;
|
||||
CommentInHeader=false;
|
||||
PackComment=false;
|
||||
Locator=false;
|
||||
QOpenOffset=0;
|
||||
QOpenMaxSize=0;
|
||||
RROffset=0;
|
||||
RRMaxSize=0;
|
||||
*this={};
|
||||
}
|
||||
|
8
deps/unrar/headers.hpp
vendored
8
deps/unrar/headers.hpp
vendored
@ -6,7 +6,7 @@
|
||||
#define SIZEOF_MAINHEAD3 13 // Size of RAR 4.x main archive header.
|
||||
#define SIZEOF_FILEHEAD14 21 // Size of RAR 1.4 file header.
|
||||
#define SIZEOF_FILEHEAD3 32 // Size of RAR 3.0 file header.
|
||||
#define SIZEOF_SHORTBLOCKHEAD 7
|
||||
#define SIZEOF_SHORTBLOCKHEAD 7 // Smallest RAR 4.x block size.
|
||||
#define SIZEOF_LONGBLOCKHEAD 11
|
||||
#define SIZEOF_SUBBLOCKHEAD 14
|
||||
#define SIZEOF_COMMHEAD 13
|
||||
@ -168,6 +168,10 @@ struct MainHeader:BaseBlock
|
||||
uint64 QOpenMaxSize; // Maximum size of QOpen offset in locator extra field.
|
||||
uint64 RROffset; // Offset of recovery record.
|
||||
uint64 RRMaxSize; // Maximum size of RR offset in locator extra field.
|
||||
size_t MetaNameMaxSize; // Maximum size of archive name in metadata extra field.
|
||||
std::wstring OrigName; // Original archive name.
|
||||
RarTime OrigTime; // Original archive time.
|
||||
|
||||
void Reset();
|
||||
};
|
||||
|
||||
@ -230,7 +234,7 @@ struct FileHeader:BlockHeader
|
||||
bool LargeFile;
|
||||
|
||||
// 'true' for HEAD_SERVICE block, which is a child of preceding file block.
|
||||
// RAR 4.x uses 'solid' flag to indicate child subheader blocks in archives.
|
||||
// RAR 4.x uses 'solid' flag to indicate children subheader blocks in archives.
|
||||
bool SubBlock;
|
||||
|
||||
HOST_SYSTEM_TYPE HSType;
|
||||
|
7
deps/unrar/headers5.hpp
vendored
7
deps/unrar/headers5.hpp
vendored
@ -59,11 +59,18 @@
|
||||
|
||||
// Main header extra field values.
|
||||
#define MHEXTRA_LOCATOR 0x01 // Position of quick list and other blocks.
|
||||
#define MHEXTRA_METADATA 0x02 // Archive metadata.
|
||||
|
||||
// Flags for MHEXTRA_LOCATOR.
|
||||
#define MHEXTRA_LOCATOR_QLIST 0x01 // Quick open offset is present.
|
||||
#define MHEXTRA_LOCATOR_RR 0x02 // Recovery record offset is present.
|
||||
|
||||
// Flags for MHEXTRA_METADATA.
|
||||
#define MHEXTRA_METADATA_NAME 0x01 // Archive name is present.
|
||||
#define MHEXTRA_METADATA_CTIME 0x02 // Archive creation time is present.
|
||||
#define MHEXTRA_METADATA_UNIXTIME 0x04 // Use Unix nanosecond time format.
|
||||
#define MHEXTRA_METADATA_UNIX_NS 0x08 // Unix format with nanosecond precision.
|
||||
|
||||
// File and service header extra field values.
|
||||
#define FHEXTRA_CRYPT 0x01 // Encryption parameters.
|
||||
#define FHEXTRA_HASH 0x02 // File hash.
|
||||
|
101
deps/unrar/isnt.cpp
vendored
101
deps/unrar/isnt.cpp
vendored
@ -13,6 +13,7 @@ DWORD WinNT()
|
||||
dwPlatformId=WinVer.dwPlatformId;
|
||||
dwMajorVersion=WinVer.dwMajorVersion;
|
||||
dwMinorVersion=WinVer.dwMinorVersion;
|
||||
|
||||
}
|
||||
DWORD Result=0;
|
||||
if (dwPlatformId==VER_PLATFORM_WIN32_NT)
|
||||
@ -21,4 +22,102 @@ DWORD WinNT()
|
||||
|
||||
return Result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Replace it with documented Windows 11 check when available.
|
||||
#include <comdef.h>
|
||||
#include <wbemidl.h>
|
||||
#pragma comment(lib, "wbemuuid.lib")
|
||||
|
||||
static bool WMI_IsWindows10()
|
||||
{
|
||||
IWbemLocator *pLoc = NULL;
|
||||
|
||||
HRESULT hres = CoCreateInstance(CLSID_WbemLocator,0,CLSCTX_INPROC_SERVER,
|
||||
IID_IWbemLocator,(LPVOID *)&pLoc);
|
||||
|
||||
if (FAILED(hres))
|
||||
return false;
|
||||
|
||||
IWbemServices *pSvc = NULL;
|
||||
|
||||
BSTR bstr_root_cimv2 = SysAllocString(L"ROOT\\CIMV2");
|
||||
|
||||
hres = pLoc->ConnectServer(bstr_root_cimv2,NULL,NULL,NULL,0,0,0,&pSvc);
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
pLoc->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
hres = CoSetProxyBlanket(pSvc,RPC_C_AUTHN_WINNT,RPC_C_AUTHZ_NONE,NULL,
|
||||
RPC_C_AUTHN_LEVEL_CALL,RPC_C_IMP_LEVEL_IMPERSONATE,NULL,EOAC_NONE);
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
IEnumWbemClassObject *pEnumerator = NULL;
|
||||
|
||||
BSTR bstr_wql = SysAllocString(L"WQL");
|
||||
BSTR bstr_sql = SysAllocString(L"SELECT * FROM Win32_OperatingSystem");
|
||||
|
||||
hres = pSvc->ExecQuery(bstr_wql, bstr_sql,
|
||||
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
IWbemClassObject *pclsObj = NULL;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
bool Win10=false;
|
||||
while (pEnumerator!=NULL)
|
||||
{
|
||||
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
|
||||
|
||||
if (uReturn==0)
|
||||
break;
|
||||
|
||||
VARIANT vtProp;
|
||||
|
||||
hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
|
||||
Win10|=wcsstr(vtProp.bstrVal,L"Windows 10")!=NULL;
|
||||
VariantClear(&vtProp);
|
||||
|
||||
pclsObj->Release();
|
||||
}
|
||||
|
||||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
pEnumerator->Release();
|
||||
|
||||
return Win10;
|
||||
}
|
||||
|
||||
|
||||
// Replace it with actual check when available.
|
||||
bool IsWindows11OrGreater()
|
||||
{
|
||||
static bool IsSet=false,IsWin11=false;
|
||||
if (!IsSet)
|
||||
{
|
||||
OSVERSIONINFO WinVer;
|
||||
WinVer.dwOSVersionInfoSize=sizeof(WinVer);
|
||||
GetVersionEx(&WinVer);
|
||||
IsWin11=WinVer.dwMajorVersion>10 ||
|
||||
WinVer.dwMajorVersion==10 && WinVer.dwBuildNumber >= 22000 && !WMI_IsWindows10();
|
||||
IsSet=true;
|
||||
}
|
||||
return IsWin11;
|
||||
}
|
||||
|
||||
#endif // _WIN_ALL
|
||||
|
3
deps/unrar/isnt.hpp
vendored
3
deps/unrar/isnt.hpp
vendored
@ -10,4 +10,7 @@ enum WINNT_VERSION {
|
||||
DWORD WinNT();
|
||||
|
||||
|
||||
// Replace it with actual check when available.
|
||||
bool IsWindows11OrGreater();
|
||||
|
||||
#endif
|
||||
|
81
deps/unrar/list.cpp
vendored
81
deps/unrar/list.cpp
vendored
@ -1,6 +1,6 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
static void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bool Technical,bool Bare);
|
||||
static void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bool Technical,bool Bare,bool DisableNames);
|
||||
static void ListSymLink(Archive &Arc);
|
||||
static void ListFileAttr(uint A,HOST_SYSTEM_TYPE HostType,wchar *AttrStr,size_t AttrSize);
|
||||
static void ListOldSubHeader(Archive &Arc);
|
||||
@ -22,9 +22,6 @@ void ListArchive(CommandData *Cmd)
|
||||
Cmd->Password.Clean(); // Clean user entered password before processing next archive.
|
||||
|
||||
Archive Arc(Cmd);
|
||||
#ifdef _WIN_ALL
|
||||
Arc.RemoveSequentialFlag();
|
||||
#endif
|
||||
if (!Arc.WOpen(ArcName))
|
||||
continue;
|
||||
bool FileMatched=true;
|
||||
@ -39,6 +36,7 @@ void ListArchive(CommandData *Cmd)
|
||||
{
|
||||
Arc.ViewComment();
|
||||
mprintf(L"\n%s: %s",St(MListArchive),Arc.FileName);
|
||||
|
||||
mprintf(L"\n%s: ",St(MListDetails));
|
||||
uint SetCount=0;
|
||||
const wchar *Fmt=Arc.Format==RARFMT14 ? L"RAR 1.4":(Arc.Format==RARFMT15 ? L"RAR 4":L"RAR 5");
|
||||
@ -64,6 +62,16 @@ void ListArchive(CommandData *Cmd)
|
||||
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListLock));
|
||||
if (Arc.Encrypted)
|
||||
mprintf(L"%s%s", SetCount++ > 0 ? L", ":L"", St(MListEncHead));
|
||||
|
||||
if (!Arc.MainHead.OrigName.empty())
|
||||
mprintf(L"\n%s: %s",St(MOrigName),Arc.MainHead.OrigName.c_str());
|
||||
if (Arc.MainHead.OrigTime.IsSet())
|
||||
{
|
||||
wchar DateStr[50];
|
||||
Arc.MainHead.OrigTime.GetText(DateStr,ASIZE(DateStr),Technical);
|
||||
mprintf(L"\n%s: %s",St(MOriginalTime),DateStr);
|
||||
}
|
||||
|
||||
mprintf(L"\n");
|
||||
}
|
||||
|
||||
@ -95,7 +103,7 @@ void ListArchive(CommandData *Cmd)
|
||||
FileMatched=Cmd->IsProcessFile(Arc.FileHead,NULL,MATCH_WILDSUBPATH,0,NULL,0)!=0;
|
||||
if (FileMatched)
|
||||
{
|
||||
ListFileHeader(Arc,Arc.FileHead,TitleShown,Verbose,Technical,Bare);
|
||||
ListFileHeader(Arc,Arc.FileHead,TitleShown,Verbose,Technical,Bare,Cmd->DisableNames);
|
||||
if (!Arc.FileHead.SplitBefore)
|
||||
{
|
||||
TotalUnpSize+=Arc.FileHead.UnpSize;
|
||||
@ -108,7 +116,7 @@ void ListArchive(CommandData *Cmd)
|
||||
if (FileMatched && !Bare)
|
||||
{
|
||||
if (Technical && ShowService)
|
||||
ListFileHeader(Arc,Arc.SubHead,TitleShown,Verbose,true,false);
|
||||
ListFileHeader(Arc,Arc.SubHead,TitleShown,Verbose,true,false,Cmd->DisableNames);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -188,8 +196,29 @@ enum LISTCOL_TYPE {
|
||||
};
|
||||
|
||||
|
||||
void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bool Technical,bool Bare)
|
||||
void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bool Technical,bool Bare,bool DisableNames)
|
||||
{
|
||||
if (!TitleShown && !Technical && !Bare)
|
||||
{
|
||||
if (Verbose)
|
||||
{
|
||||
mprintf(L"\n%ls",St(MListTitleV));
|
||||
if (!DisableNames)
|
||||
mprintf(L"\n----------- --------- -------- ----- ---------- ----- -------- ----");
|
||||
}
|
||||
else
|
||||
{
|
||||
mprintf(L"\n%ls",St(MListTitleL));
|
||||
if (!DisableNames)
|
||||
mprintf(L"\n----------- --------- ---------- ----- ----");
|
||||
}
|
||||
// Must be set even in DisableNames mode to suppress "0 files" output
|
||||
// unless no files are matched.
|
||||
TitleShown=true;
|
||||
}
|
||||
if (DisableNames)
|
||||
return;
|
||||
|
||||
wchar *Name=hd.FileName;
|
||||
RARFORMAT Format=Arc.Format;
|
||||
|
||||
@ -199,21 +228,6 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TitleShown && !Technical)
|
||||
{
|
||||
if (Verbose)
|
||||
{
|
||||
mprintf(L"\n%ls",St(MListTitleV));
|
||||
mprintf(L"\n----------- --------- -------- ----- ---------- ----- -------- ----");
|
||||
}
|
||||
else
|
||||
{
|
||||
mprintf(L"\n%ls",St(MListTitleL));
|
||||
mprintf(L"\n----------- --------- ---------- ----- ----");
|
||||
}
|
||||
TitleShown=true;
|
||||
}
|
||||
|
||||
wchar UnpSizeText[30],PackSizeText[30];
|
||||
if (hd.UnpSize==INT64NDF)
|
||||
wcsncpyz(UnpSizeText,L"?",ASIZE(UnpSizeText));
|
||||
@ -304,17 +318,21 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo
|
||||
mprintf(L"\n%12ls: %ls",St(MListPacked),PackSizeText);
|
||||
mprintf(L"\n%12ls: %ls",St(MListRatio),RatioStr);
|
||||
}
|
||||
bool WinTitles=false;
|
||||
#ifdef _WIN_ALL
|
||||
WinTitles=true;
|
||||
#endif
|
||||
if (hd.mtime.IsSet())
|
||||
mprintf(L"\n%12ls: %ls",St(MListMtime),DateStr);
|
||||
mprintf(L"\n%12ls: %ls",St(WinTitles ? MListModified:MListMtime),DateStr);
|
||||
if (hd.ctime.IsSet())
|
||||
{
|
||||
hd.ctime.GetText(DateStr,ASIZE(DateStr),true);
|
||||
mprintf(L"\n%12ls: %ls",St(MListCtime),DateStr);
|
||||
mprintf(L"\n%12ls: %ls",St(WinTitles ? MListCreated:MListCtime),DateStr);
|
||||
}
|
||||
if (hd.atime.IsSet())
|
||||
{
|
||||
hd.atime.GetText(DateStr,ASIZE(DateStr),true);
|
||||
mprintf(L"\n%12ls: %ls",St(MListAtime),DateStr);
|
||||
mprintf(L"\n%12ls: %ls",St(WinTitles ? MListAccessed:MListAtime),DateStr);
|
||||
}
|
||||
mprintf(L"\n%12ls: %ls",St(MListAttr),AttrStr);
|
||||
if (hd.FileHash.Type==HASH_CRC32)
|
||||
@ -370,15 +388,16 @@ void ListFileHeader(Archive &Arc,FileHeader &hd,bool &TitleShown,bool Verbose,bo
|
||||
{
|
||||
mprintf(L"\n%12ls: ",L"Unix owner");
|
||||
if (*hd.UnixOwnerName!=0)
|
||||
mprintf(L"%ls:",GetWide(hd.UnixOwnerName));
|
||||
mprintf(L"%ls",GetWide(hd.UnixOwnerName));
|
||||
else
|
||||
if (hd.UnixOwnerNumeric)
|
||||
mprintf(L"#%d",hd.UnixOwnerID);
|
||||
mprintf(L":");
|
||||
if (*hd.UnixGroupName!=0)
|
||||
mprintf(L"%ls",GetWide(hd.UnixGroupName));
|
||||
if ((*hd.UnixOwnerName!=0 || *hd.UnixGroupName!=0) && (hd.UnixOwnerNumeric || hd.UnixGroupNumeric))
|
||||
mprintf(L" ");
|
||||
if (hd.UnixOwnerNumeric)
|
||||
mprintf(L"#%d:",hd.UnixOwnerID);
|
||||
else
|
||||
if (hd.UnixGroupNumeric)
|
||||
mprintf(L"#%d:",hd.UnixGroupID);
|
||||
mprintf(L"#%d",hd.UnixGroupID);
|
||||
}
|
||||
|
||||
mprintf(L"\n");
|
||||
|
18
deps/unrar/loclang.hpp
vendored
18
deps/unrar/loclang.hpp
vendored
@ -28,6 +28,7 @@
|
||||
#define MRARTitle1 L"\nUsage: rar <command> -<switch 1> -<switch N> <archive> <files...>"
|
||||
#define MUNRARTitle1 L"\nUsage: unrar <command> -<switch 1> -<switch N> <archive> <files...>"
|
||||
#define MRARTitle2 L"\n <@listfiles...> <path_to_extract\\>"
|
||||
#define MFwrSlTitle2 L"\n <@listfiles...> <path_to_extract/>"
|
||||
#define MCHelpCmd L"\n\n<Commands>"
|
||||
#define MCHelpCmdA L"\n a Add files to archive"
|
||||
#define MCHelpCmdC L"\n c Add archive comment"
|
||||
@ -58,6 +59,7 @@
|
||||
#define MCHelpSwAD L"\n ad[1,2] Alternate destination path"
|
||||
#define MCHelpSwAG L"\n ag[format] Generate archive name using the current date"
|
||||
#define MCHelpSwAI L"\n ai Ignore file attributes"
|
||||
#define MCHelpSwAM L"\n am[s,r] Archive name and time [save, restore]"
|
||||
#define MCHelpSwAO L"\n ao Add files with Archive attribute set"
|
||||
#define MCHelpSwAP L"\n ap<path> Set path inside archive"
|
||||
#define MCHelpSwAS L"\n as Synchronize archive contents"
|
||||
@ -72,11 +74,11 @@
|
||||
#define MCHelpSwDW L"\n dw Wipe files after archiving"
|
||||
#define MCHelpSwEa L"\n e[+]<attr> Set file exclude and include attributes"
|
||||
#define MCHelpSwED L"\n ed Do not add empty directories"
|
||||
#define MCHelpSwEN L"\n en Do not put 'end of archive' block"
|
||||
#define MCHelpSwEP L"\n ep Exclude paths from names"
|
||||
#define MCHelpSwEP1 L"\n ep1 Exclude base directory from names"
|
||||
#define MCHelpSwEP2 L"\n ep2 Expand paths to full"
|
||||
#define MCHelpSwEP3 L"\n ep3 Expand paths to full including the drive letter"
|
||||
#define MCHelpSwEP4 L"\n ep4<path> Exclude the path prefix from names"
|
||||
#define MCHelpSwF L"\n f Freshen files"
|
||||
#define MCHelpSwHP L"\n hp[password] Encrypt both file data and headers"
|
||||
#define MCHelpSwHT L"\n ht[b|c] Select hash type [BLAKE2,CRC32] for file checksum"
|
||||
@ -95,6 +97,7 @@
|
||||
#define MCHelpSwMA L"\n ma[4|5] Specify a version of archiving format"
|
||||
#define MCHelpSwMC L"\n mc<par> Set advanced compression parameters"
|
||||
#define MCHelpSwMD L"\n md<n>[k,m,g] Dictionary size in KB, MB or GB"
|
||||
#define MCHelpSwME L"\n me[par] Set encryption parameters"
|
||||
#define MCHelpSwMS L"\n ms[ext;ext] Specify file types to store"
|
||||
#define MCHelpSwMT L"\n mt<threads> Set the number of threads"
|
||||
#define MCHelpSwN L"\n n<file> Additionally filter included files"
|
||||
@ -106,11 +109,11 @@
|
||||
#define MCHelpSwOI L"\n oi[0-4][:min] Save identical files as references"
|
||||
#define MCHelpSwOL L"\n ol[a] Process symbolic links as the link [absolute paths]"
|
||||
#define MCHelpSwONI L"\n oni Allow potentially incompatible names"
|
||||
#define MCHelpSwOP L"\n op<path> Set the output path for extracted files"
|
||||
#define MCHelpSwOR L"\n or Rename files automatically"
|
||||
#define MCHelpSwOS L"\n os Save NTFS streams"
|
||||
#define MCHelpSwOW L"\n ow Save or restore file owner and group"
|
||||
#define MCHelpSwP L"\n p[password] Set password"
|
||||
#define MCHelpSwPm L"\n p- Do not query password"
|
||||
#define MCHelpSwQO L"\n qo[-|+] Add quick open information [none|force]"
|
||||
#define MCHelpSwR L"\n r Recurse subdirectories"
|
||||
#define MCHelpSwRm L"\n r- Disable recursion"
|
||||
@ -272,6 +275,9 @@
|
||||
#define MListMtime L"mtime"
|
||||
#define MListCtime L"ctime"
|
||||
#define MListAtime L"atime"
|
||||
#define MListModified L"Modified"
|
||||
#define MListCreated L"Created"
|
||||
#define MListAccessed L"Accessed"
|
||||
#define MListAttr L"Attributes"
|
||||
#define MListFlags L"Flags"
|
||||
#define MListCompInfo L"Compression"
|
||||
@ -385,3 +391,11 @@
|
||||
#define MErrReadTrunc L"\n%s is archived incompletely because of read error.\n"
|
||||
#define MErrReadCount L"\n%u files are archived incompletely because of read errors."
|
||||
#define MDirNameExists L"\nDirectory with such name already exists"
|
||||
#define MStdinNoInput L"\nKeyboard input is not allowed when reading data from stdin"
|
||||
#define MTruncPsw L"\nPassword exceeds the maximum allowed length of %u characters and will be truncated."
|
||||
#define MAdjustValue L"\nAdjusting %s value to %s."
|
||||
#define MOpFailed L"\nOperation failed"
|
||||
#define MSkipEncArc L"\nSkipping the encrypted archive %s"
|
||||
#define MOrigName L"Original name"
|
||||
#define MOriginalTime L"Original time"
|
||||
#define MFileRenamed L"\n%s is renamed to %s"
|
||||
|
11
deps/unrar/makefile
vendored
11
deps/unrar/makefile
vendored
@ -123,7 +123,7 @@ UNRAR_OBJ=filestr.o recvol.o rs.o scantree.o qopen.o
|
||||
LIB_OBJ=filestr.o scantree.o dll.o qopen.o
|
||||
|
||||
OBJECTS=rar.o strlist.o strfn.o pathfn.o smallfn.o global.o file.o filefn.o filcreat.o \
|
||||
archive.o arcread.o unicode.o system.o isnt.o crypt.o crc.o rawread.o encname.o \
|
||||
archive.o arcread.o unicode.o system.o crypt.o crc.o rawread.o encname.o \
|
||||
resource.o match.o timefn.o rdwrfn.o consio.o options.o errhnd.o rarvm.o secpassword.o \
|
||||
rijndael.o getbits.o sha1.o sha256.o blake2s.o hash.o extinfo.o extract.o volume.o \
|
||||
list.o find.o unpack.o headers.o threadpool.o rs16.o cmddata.o ui.o
|
||||
@ -142,20 +142,23 @@ clean:
|
||||
@rm -f $(OBJECTS) $(UNRAR_OBJ) $(LIB_OBJ)
|
||||
@rm -f unrar libunrar.*
|
||||
|
||||
unrar: clean $(OBJECTS) $(UNRAR_OBJ)
|
||||
# We removed 'clean' from dependencies, because it prevented parallel
|
||||
# 'make -Jn' builds.
|
||||
|
||||
unrar: $(OBJECTS) $(UNRAR_OBJ)
|
||||
@rm -f unrar
|
||||
$(LINK) -o unrar $(LDFLAGS) $(OBJECTS) $(UNRAR_OBJ) $(LIBS)
|
||||
$(STRIP) unrar
|
||||
|
||||
sfx: WHAT=SFX_MODULE
|
||||
sfx: clean $(OBJECTS)
|
||||
sfx: $(OBJECTS)
|
||||
@rm -f default.sfx
|
||||
$(LINK) -o default.sfx $(LDFLAGS) $(OBJECTS)
|
||||
$(STRIP) default.sfx
|
||||
|
||||
lib: WHAT=RARDLL
|
||||
lib: CXXFLAGS+=$(LIBFLAGS)
|
||||
lib: clean $(OBJECTS) $(LIB_OBJ)
|
||||
lib: $(OBJECTS) $(LIB_OBJ)
|
||||
@rm -f libunrar.*
|
||||
$(LINK) -shared -o libunrar.so $(LDFLAGS) $(OBJECTS) $(LIB_OBJ)
|
||||
$(AR) rcs libunrar.a $(OBJECTS) $(LIB_OBJ)
|
||||
|
12
deps/unrar/model.cpp
vendored
12
deps/unrar/model.cpp
vendored
@ -532,13 +532,15 @@ inline bool RARPPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
|
||||
Model->Coder.SubRange.LowCount=HiCnt;
|
||||
Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale;
|
||||
i=NumStats-Model->NumMasked;
|
||||
pps--;
|
||||
|
||||
// 2022.12.02: we removed pps-- here and changed the code below to avoid
|
||||
// "array subscript -1 is outside array bounds" warning in some compilers.
|
||||
do
|
||||
{
|
||||
pps++;
|
||||
if (pps>=ps+ASIZE(ps)) // Extra safety check.
|
||||
return false;
|
||||
Model->CharMask[(*pps)->Symbol]=Model->EscCount;
|
||||
pps++;
|
||||
} while ( --i );
|
||||
psee2c->Summ += Model->Coder.SubRange.scale;
|
||||
Model->NumMasked = NumStats;
|
||||
@ -566,17 +568,14 @@ void ModelPPM::CleanUp()
|
||||
}
|
||||
|
||||
|
||||
bool ModelPPM::DecodeInit(Unpack *UnpackRead,int &EscChar,byte *hcppm)
|
||||
bool ModelPPM::DecodeInit(Unpack *UnpackRead,int &EscChar)
|
||||
{
|
||||
int MaxOrder=UnpackRead->GetChar();
|
||||
bool Reset=(MaxOrder & 0x20)!=0;
|
||||
|
||||
int MaxMB;
|
||||
if (Reset)
|
||||
{
|
||||
MaxMB=UnpackRead->GetChar();
|
||||
if (MaxMB>128) return(false);
|
||||
}
|
||||
else
|
||||
if (SubAlloc.GetAllocatedMemory()==0)
|
||||
return(false);
|
||||
@ -593,7 +592,6 @@ bool ModelPPM::DecodeInit(Unpack *UnpackRead,int &EscChar,byte *hcppm)
|
||||
SubAlloc.StopSubAllocator();
|
||||
return(false);
|
||||
}
|
||||
SubAlloc.SetHeapStartFixed(hcppm);
|
||||
SubAlloc.StartSubAllocator(MaxMB+1);
|
||||
StartModelRare(MaxOrder);
|
||||
}
|
||||
|
2
deps/unrar/model.hpp
vendored
2
deps/unrar/model.hpp
vendored
@ -115,7 +115,7 @@ class ModelPPM : RARPPM_DEF
|
||||
public:
|
||||
ModelPPM();
|
||||
void CleanUp(); // reset PPM variables after data error
|
||||
bool DecodeInit(Unpack *UnpackRead,int &EscChar,byte *hcppm);
|
||||
bool DecodeInit(Unpack *UnpackRead,int &EscChar);
|
||||
int DecodeChar();
|
||||
};
|
||||
|
||||
|
8
deps/unrar/options.cpp
vendored
8
deps/unrar/options.cpp
vendored
@ -6,14 +6,6 @@ RAROptions::RAROptions()
|
||||
}
|
||||
|
||||
|
||||
RAROptions::~RAROptions()
|
||||
{
|
||||
// It is important for security reasons, so we do not have the unnecessary
|
||||
// password data left in memory.
|
||||
memset(this,0,sizeof(RAROptions));
|
||||
}
|
||||
|
||||
|
||||
void RAROptions::Init()
|
||||
{
|
||||
memset(this,0,sizeof(RAROptions));
|
||||
|
22
deps/unrar/options.hpp
vendored
22
deps/unrar/options.hpp
vendored
@ -45,6 +45,12 @@ enum OVERWRITE_MODE
|
||||
OVERWRITE_FORCE_ASK
|
||||
};
|
||||
|
||||
enum ARC_METADATA
|
||||
{
|
||||
ARCMETA_NONE=0,
|
||||
ARCMETA_SAVE, // -ams
|
||||
ARCMETA_RESTORE // -amr
|
||||
};
|
||||
|
||||
enum QOPEN_MODE { QOPEN_NONE, QOPEN_AUTO, QOPEN_ALWAYS };
|
||||
|
||||
@ -84,11 +90,12 @@ struct FilterMode
|
||||
#define MAX_GENERATE_MASK 128
|
||||
|
||||
|
||||
// Here we store simple data types, which we can clear and move all together
|
||||
// quickly. Rest of data types goes to CommandData.
|
||||
class RAROptions
|
||||
{
|
||||
public:
|
||||
RAROptions();
|
||||
~RAROptions();
|
||||
void Init();
|
||||
|
||||
uint ExclFileAttr;
|
||||
@ -116,9 +123,10 @@ class RAROptions
|
||||
RAR_CHARSET ErrlogCharset;
|
||||
RAR_CHARSET RedirectCharset;
|
||||
|
||||
wchar ArcPath[NM];
|
||||
SecPassword Password;
|
||||
wchar ArcPath[NM]; // For -ap<path>.
|
||||
wchar ExclArcPath[NM]; // For -ep4<path> switch.
|
||||
bool EncryptHeaders;
|
||||
bool SkipEncrypted;
|
||||
|
||||
bool ManualPassword; // Password entered manually during operation, might need to clean for next archive.
|
||||
|
||||
@ -130,6 +138,7 @@ class RAROptions
|
||||
HASH_TYPE HashType;
|
||||
int Recovery;
|
||||
int RecVolNumber;
|
||||
ARC_METADATA ArcMetadata;
|
||||
bool DisablePercentage;
|
||||
bool DisableCopyright;
|
||||
bool DisableDone;
|
||||
@ -145,7 +154,6 @@ class RAROptions
|
||||
PATH_EXCL_MODE ExclPath;
|
||||
RECURSE_MODE Recurse;
|
||||
int64 VolSize;
|
||||
Array<int64> NextVolSizes;
|
||||
uint CurVolNum;
|
||||
bool AllYes;
|
||||
bool VerboseOutput; // -iv, display verbose output, used only in "WinRAR t" now.
|
||||
@ -195,7 +203,11 @@ class RAROptions
|
||||
EXTTIME_MODE xctime;
|
||||
EXTTIME_MODE xatime;
|
||||
bool PreserveAtime;
|
||||
wchar CompressStdin[NM];
|
||||
|
||||
// Read data from stdin and store in archive under a name specified here
|
||||
// when archiving. Read an archive from stdin if any non-empty string
|
||||
// is specified here when extracting.
|
||||
wchar UseStdin[NM];
|
||||
|
||||
uint Threads; // We use it to init hash even if RAR_SMP is not defined.
|
||||
|
||||
|
29
deps/unrar/os.hpp
vendored
29
deps/unrar/os.hpp
vendored
@ -13,6 +13,8 @@
|
||||
#endif
|
||||
|
||||
#include <new>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
#if defined(_WIN_ALL) || defined(_EMX)
|
||||
@ -36,12 +38,23 @@
|
||||
// re-definition warnings in third party projects.
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#define _UNICODE // Set _T() macro to convert from narrow to wide strings.
|
||||
#endif
|
||||
|
||||
#undef WINVER
|
||||
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
#define WINVER 0x0501
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// 2021.09.05: Allow newer Vista+ APIs like IFileOpenDialog for WinRAR,
|
||||
// but still keep SFX modules XP compatible.
|
||||
#define WINVER _WIN32_WINNT_VISTA
|
||||
#define _WIN32_WINNT _WIN32_WINNT_VISTA
|
||||
#else
|
||||
#define WINVER _WIN32_WINNT_WINXP
|
||||
#define _WIN32_WINNT _WIN32_WINNT_WINXP
|
||||
#endif
|
||||
|
||||
#if !defined(ZIPSFX)
|
||||
#define RAR_SMP
|
||||
@ -73,14 +86,14 @@
|
||||
#include <dir.h>
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#if _MSC_VER<1500
|
||||
#define for if (0) ; else for
|
||||
#endif
|
||||
#include <direct.h>
|
||||
#include <intrin.h>
|
||||
|
||||
// Use SSE only for x86/x64, not ARM Windows.
|
||||
#if defined(_M_IX86) || defined(_M_X64)
|
||||
#define USE_SSE
|
||||
#define SSE_ALIGNMENT 16
|
||||
#endif
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#endif // _MSC_VER
|
||||
@ -96,7 +109,6 @@
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
#define SAVE_LINKS
|
||||
|
||||
#define ENABLE_ACCESS
|
||||
@ -212,7 +224,8 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if _POSIX_C_SOURCE >= 200809L
|
||||
// Unlike Apple x64, utimensat shall be available in all Apple M1 systems.
|
||||
#if _POSIX_C_SOURCE >= 200809L || defined(__APPLE__) && defined(__arm64__)
|
||||
#define UNIX_TIME_NS // Nanosecond time precision in Unix.
|
||||
#endif
|
||||
|
||||
|
169
deps/unrar/pathfn.cpp
vendored
169
deps/unrar/pathfn.cpp
vendored
@ -5,7 +5,7 @@ wchar* PointToName(const wchar *Path)
|
||||
for (int I=(int)wcslen(Path)-1;I>=0;I--)
|
||||
if (IsPathDiv(Path[I]))
|
||||
return (wchar*)&Path[I+1];
|
||||
return (wchar*)((*Path && IsDriveDiv(Path[1])) ? Path+2:Path);
|
||||
return (wchar*)((*Path!=0 && IsDriveDiv(Path[1])) ? Path+2:Path);
|
||||
}
|
||||
|
||||
|
||||
@ -31,11 +31,17 @@ wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath,size_t DestSize)
|
||||
const wchar *s=DestPtr;
|
||||
if (s[0]!=0 && IsDriveDiv(s[1]))
|
||||
s+=2;
|
||||
if (s[0]=='\\' && s[1]=='\\')
|
||||
|
||||
// Skip UNC Windows \\server\share\ or Unix //server/share/
|
||||
if (IsPathDiv(s[0]) && IsPathDiv(s[1]))
|
||||
{
|
||||
const wchar *Slash=wcschr(s+2,'\\');
|
||||
if (Slash!=NULL && (Slash=wcschr(Slash+1,'\\'))!=NULL)
|
||||
s=Slash+1;
|
||||
uint SlashCount=0;
|
||||
for (const wchar *t=s+2;*t!=0;t++)
|
||||
if (IsPathDiv(*t) && ++SlashCount==2)
|
||||
{
|
||||
s=t+1; // Found two more path separators after leading two.
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (const wchar *t=s;*t!=0;t++)
|
||||
if (IsPathDiv(*t))
|
||||
@ -184,6 +190,8 @@ void MakeName(const wchar *Path,const wchar *Name,wchar *Pathname,size_t MaxSize
|
||||
// the temporary buffer instead of constructing the name in 'Pathname'.
|
||||
wchar OutName[NM];
|
||||
wcsncpyz(OutName,Path,ASIZE(OutName));
|
||||
// Do not add slash to d:, we want to allow relative paths like d:filename.
|
||||
if (!IsDriveLetter(Path) || Path[2]!=0)
|
||||
AddEndSlash(OutName,ASIZE(OutName));
|
||||
wcsncatz(OutName,Name,ASIZE(OutName));
|
||||
wcsncpyz(Pathname,OutName,MaxSize);
|
||||
@ -317,6 +325,9 @@ void GetConfigName(const wchar *Name,wchar *FullName,size_t MaxSize,bool CheckEx
|
||||
// of file name if numeric part is missing.
|
||||
wchar* GetVolNumPart(const wchar *ArcName)
|
||||
{
|
||||
// We do not want to increment any characters in path component.
|
||||
ArcName=PointToName(ArcName);
|
||||
|
||||
if (*ArcName==0)
|
||||
return (wchar *)ArcName;
|
||||
|
||||
@ -340,7 +351,7 @@ wchar* GetVolNumPart(const wchar *ArcName)
|
||||
{
|
||||
// Validate the first numeric part only if it has a dot somewhere
|
||||
// before it.
|
||||
wchar *Dot=wcschr(PointToName(ArcName),'.');
|
||||
const wchar *Dot=wcschr(ArcName,'.');
|
||||
if (Dot!=NULL && Dot<NumPtr)
|
||||
ChPtr=NumPtr;
|
||||
break;
|
||||
@ -417,50 +428,39 @@ void NextVolumeName(wchar *ArcName,uint MaxLength,bool OldNumbering)
|
||||
|
||||
bool IsNameUsable(const wchar *Name)
|
||||
{
|
||||
#ifndef _UNIX
|
||||
if (Name[0] && Name[1] && wcschr(Name+2,':')!=NULL)
|
||||
// We were asked to apply Windows-like conversion in Linux in case
|
||||
// files are unpacked to Windows share. This code is invoked only
|
||||
// if file failed to be created, so it doesn't affect extraction
|
||||
// of Unix compatible names to native Unix drives.
|
||||
#ifdef _UNIX
|
||||
// Windows shares in Unix do not allow the drive letter,
|
||||
// so unlike Windows version, we check all characters here.
|
||||
if (wcschr(Name,':')!=NULL)
|
||||
return false;
|
||||
#else
|
||||
if (Name[0]!=0 && Name[1]!=0 && wcschr(Name+2,':')!=NULL)
|
||||
return false;
|
||||
#endif
|
||||
for (const wchar *s=Name;*s!=0;s++)
|
||||
{
|
||||
if ((uint)*s<32)
|
||||
return false;
|
||||
|
||||
// It is for Windows shares in Unix. We can create such names in Windows.
|
||||
#ifdef _UNIX
|
||||
// No spaces or dots before the path separator are allowed in Windows
|
||||
// shares. But they are allowed and automtically removed at the end of
|
||||
// file or folder name, so it is useless to replace them here.
|
||||
// Since such files or folders are created successfully, a supposed
|
||||
// conversion here would never be invoked.
|
||||
if ((*s==' ' || *s=='.') && IsPathDiv(s[1]))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return *Name!=0 && wcspbrk(Name,L"?*<>|\"")==NULL;
|
||||
}
|
||||
|
||||
|
||||
void MakeNameUsable(char *Name,bool Extended)
|
||||
{
|
||||
#ifdef _WIN_ALL
|
||||
// In Windows we also need to convert characters not defined in current
|
||||
// code page. This double conversion changes them to '?', which is
|
||||
// catched by code below.
|
||||
size_t NameLength=strlen(Name);
|
||||
wchar NameW[NM];
|
||||
CharToWide(Name,NameW,ASIZE(NameW));
|
||||
WideToChar(NameW,Name,NameLength+1);
|
||||
Name[NameLength]=0;
|
||||
#endif
|
||||
for (char *s=Name;*s!=0;s=charnext(s))
|
||||
{
|
||||
if (strchr(Extended ? "?*<>|\"":"?*",*s)!=NULL || Extended && (byte)*s<32)
|
||||
*s='_';
|
||||
#ifdef _EMX
|
||||
if (*s=='=')
|
||||
*s='_';
|
||||
#endif
|
||||
#ifndef _UNIX
|
||||
if (s-Name>1 && *s==':')
|
||||
*s='_';
|
||||
// Remove ' ' and '.' before path separator, but allow .\ and ..\.
|
||||
if ((*s==' ' || *s=='.' && s>Name && !IsPathDiv(s[-1]) && s[-1]!='.') && IsPathDiv(s[1]))
|
||||
*s='_';
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MakeNameUsable(wchar *Name,bool Extended)
|
||||
@ -469,7 +469,27 @@ void MakeNameUsable(wchar *Name,bool Extended)
|
||||
{
|
||||
if (wcschr(Extended ? L"?*<>|\"":L"?*",*s)!=NULL || Extended && (uint)*s<32)
|
||||
*s='_';
|
||||
#ifndef _UNIX
|
||||
#ifdef _UNIX
|
||||
// We were asked to apply Windows-like conversion in Linux in case
|
||||
// files are unpacked to Windows share. This code is invoked only
|
||||
// if file failed to be created, so it doesn't affect extraction
|
||||
// of Unix compatible names to native Unix drives.
|
||||
if (Extended)
|
||||
{
|
||||
// Windows shares in Unix do not allow the drive letter,
|
||||
// so unlike Windows version, we check all characters here.
|
||||
if (*s==':')
|
||||
*s='_';
|
||||
|
||||
// No spaces or dots before the path separator are allowed on Windows
|
||||
// shares. But they are allowed and automtically removed at the end of
|
||||
// file or folder name, so it is useless to replace them here.
|
||||
// Since such files or folders are created successfully, a supposed
|
||||
// conversion here would never be invoked.
|
||||
if ((*s==' ' || *s=='.') && IsPathDiv(s[1]))
|
||||
*s='_';
|
||||
}
|
||||
#else
|
||||
if (s-Name>1 && *s==':')
|
||||
*s='_';
|
||||
#if 0 // We already can create such files.
|
||||
@ -692,7 +712,8 @@ static void GenArcName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask,u
|
||||
wchar Mask[MAX_GENERATE_MASK];
|
||||
wcsncpyz(Mask,*GenerateMask!=0 ? GenerateMask:L"yyyymmddhhmmss",ASIZE(Mask));
|
||||
|
||||
bool QuoteMode=false,Hours=false;
|
||||
bool QuoteMode=false;
|
||||
uint MAsMinutes=0; // By default we treat 'M' as months.
|
||||
for (uint I=0;Mask[I]!=0;I++)
|
||||
{
|
||||
if (Mask[I]=='{' || Mask[I]=='}')
|
||||
@ -704,13 +725,16 @@ static void GenArcName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask,u
|
||||
continue;
|
||||
int CurChar=toupperw(Mask[I]);
|
||||
if (CurChar=='H')
|
||||
Hours=true;
|
||||
MAsMinutes=2; // Treat next two 'M' after 'H' as minutes.
|
||||
if (CurChar=='D' || CurChar=='Y')
|
||||
MAsMinutes=0; // Treat 'M' in HHDDMMYY and HHYYMMDD as month.
|
||||
|
||||
if (Hours && CurChar=='M')
|
||||
if (MAsMinutes>0 && CurChar=='M')
|
||||
{
|
||||
// Replace minutes with 'I'. We use 'M' both for months and minutes,
|
||||
// so we treat as minutes only those 'M' which are found after hours.
|
||||
// so we treat as minutes only those 'M', which are found after hours.
|
||||
Mask[I]='I';
|
||||
MAsMinutes--;
|
||||
}
|
||||
if (CurChar=='N')
|
||||
{
|
||||
@ -774,7 +798,9 @@ static void GenArcName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask,u
|
||||
|
||||
const wchar *MaskChars=L"YMDHISWAEN";
|
||||
|
||||
// How many times every modifier character was encountered in the mask.
|
||||
int CField[sizeof(Field)/sizeof(Field[0])];
|
||||
|
||||
memset(CField,0,sizeof(CField));
|
||||
QuoteMode=false;
|
||||
for (uint I=0;Mask[I]!=0;I++)
|
||||
@ -816,13 +842,22 @@ static void GenArcName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask,u
|
||||
{
|
||||
size_t FieldPos=ChPtr-MaskChars;
|
||||
int CharPos=(int)strlen(Field[FieldPos])-CField[FieldPos]--;
|
||||
if (FieldPos==1 && toupperw(Mask[I+1])=='M' && toupperw(Mask[I+2])=='M')
|
||||
|
||||
// CField[FieldPos] shall have exactly 3 "MMM" symbols, so we do not
|
||||
// repeat the month name in case "MMMMMMMM" mask. But since we
|
||||
// decremented CField[FieldPos] above, we compared it with 2.
|
||||
if (FieldPos==1 && CField[FieldPos]==2 &&
|
||||
toupperw(Mask[I+1])=='M' && toupperw(Mask[I+2])=='M')
|
||||
{
|
||||
wcsncpyz(DateText+J,GetMonthName(rlt.Month-1),ASIZE(DateText)-J);
|
||||
J=wcslen(DateText);
|
||||
I+=2;
|
||||
continue;
|
||||
}
|
||||
// If CharPos is negative, we have more modifier characters than
|
||||
// matching time data. We prefer to issue a modifier character
|
||||
// instead of repeating time data from beginning, so user can notice
|
||||
// excessive modifiers added by mistake.
|
||||
if (CharPos<0)
|
||||
DateText[J]=Mask[I];
|
||||
else
|
||||
@ -985,9 +1020,9 @@ void ConvertToPrecomposed(wchar *Name,size_t NameSize)
|
||||
}
|
||||
|
||||
|
||||
// Remove trailing spaces and dots in file name and in dir names in path.
|
||||
void MakeNameCompatible(wchar *Name)
|
||||
void MakeNameCompatible(wchar *Name,size_t MaxSize)
|
||||
{
|
||||
// Remove trailing spaces and dots in file name and in dir names in path.
|
||||
int Src=0,Dest=0;
|
||||
while (true)
|
||||
{
|
||||
@ -1005,5 +1040,47 @@ void MakeNameCompatible(wchar *Name)
|
||||
Src++;
|
||||
Dest++;
|
||||
}
|
||||
|
||||
// Rename reserved device names, such as aux.txt to _aux.txt.
|
||||
// We check them in path components too, where they are also prohibited.
|
||||
for (uint I=0;Name[I]!=0;I++)
|
||||
if (I==0 || I>0 && IsPathDiv(Name[I-1]))
|
||||
{
|
||||
static const wchar *Devices[]={L"CON",L"PRN",L"AUX",L"NUL",L"COM#",L"LPT#"};
|
||||
wchar *s=Name+I;
|
||||
bool MatchFound=false;
|
||||
for (uint J=0;J<ASIZE(Devices);J++)
|
||||
for (uint K=0;;K++)
|
||||
if (Devices[J][K]=='#')
|
||||
{
|
||||
if (!IsDigit(s[K]))
|
||||
break;
|
||||
}
|
||||
else
|
||||
if (Devices[J][K]==0)
|
||||
{
|
||||
// Names like aux.txt are accessible without \\?\ prefix
|
||||
// since Windows 11. Pure aux is still prohibited.
|
||||
MatchFound=s[K]==0 || s[K]=='.' && !IsWindows11OrGreater() || IsPathDiv(s[K]);
|
||||
break;
|
||||
}
|
||||
else
|
||||
if (Devices[J][K]!=toupperw(s[K]))
|
||||
break;
|
||||
if (MatchFound)
|
||||
{
|
||||
wchar OrigName[NM];
|
||||
wcsncpyz(OrigName,Name,ASIZE(OrigName));
|
||||
if (MaxSize>I+1) // I+1, because we do not move the trailing 0.
|
||||
memmove(s+1,s,(MaxSize-I-1)*sizeof(*s));
|
||||
*s='_';
|
||||
#ifndef SFX_MODULE
|
||||
uiMsg(UIMSG_CORRECTINGNAME,nullptr);
|
||||
uiMsg(UIERROR_RENAMING,nullptr,OrigName,Name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
4
deps/unrar/pathfn.hpp
vendored
4
deps/unrar/pathfn.hpp
vendored
@ -29,7 +29,6 @@ void GetConfigName(const wchar *Name,wchar *FullName,size_t MaxSize,bool CheckEx
|
||||
wchar* GetVolNumPart(const wchar *ArcName);
|
||||
void NextVolumeName(wchar *ArcName,uint MaxLength,bool OldNumbering);
|
||||
bool IsNameUsable(const wchar *Name);
|
||||
void MakeNameUsable(char *Name,bool Extended);
|
||||
void MakeNameUsable(wchar *Name,bool Extended);
|
||||
|
||||
void UnixSlashToDos(const char *SrcName,char *DestName,size_t MaxLength);
|
||||
@ -70,7 +69,8 @@ void GenerateArchiveName(wchar *ArcName,size_t MaxSize,const wchar *GenerateMask
|
||||
#ifdef _WIN_ALL
|
||||
bool GetWinLongPath(const wchar *Src,wchar *Dest,size_t MaxSize);
|
||||
void ConvertToPrecomposed(wchar *Name,size_t NameSize);
|
||||
void MakeNameCompatible(wchar *Name);
|
||||
void MakeNameCompatible(wchar *Name,size_t MaxSize);
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
2
deps/unrar/qopen.cpp
vendored
2
deps/unrar/qopen.cpp
vendored
@ -97,7 +97,7 @@ void QuickOpen::Load(uint64 BlockPos)
|
||||
|
||||
if (Arc->SubHead.Encrypted)
|
||||
{
|
||||
RAROptions *Cmd=Arc->GetRAROptions();
|
||||
CommandData *Cmd=Arc->GetCommandData();
|
||||
#ifndef RAR_NOCRYPT
|
||||
if (Cmd->Password.IsSet())
|
||||
Crypt.SetCryptKeys(false,CRYPT_RAR50,&Cmd->Password,Arc->SubHead.Salt,
|
||||
|
6
deps/unrar/rar.hpp
vendored
6
deps/unrar/rar.hpp
vendored
@ -12,10 +12,12 @@
|
||||
#include "version.hpp"
|
||||
#include "rardefs.hpp"
|
||||
#include "rarlang.hpp"
|
||||
#include "rawint.hpp"
|
||||
#include "unicode.hpp"
|
||||
#include "errhnd.hpp"
|
||||
#include "secpassword.hpp"
|
||||
#include "array.hpp"
|
||||
#include "strlist.hpp"
|
||||
#include "timefn.hpp"
|
||||
#include "sha1.hpp"
|
||||
#include "sha256.hpp"
|
||||
@ -28,13 +30,11 @@
|
||||
#include "headers.hpp"
|
||||
#include "pathfn.hpp"
|
||||
#include "strfn.hpp"
|
||||
#include "strlist.hpp"
|
||||
#ifdef _WIN_ALL
|
||||
#include "isnt.hpp"
|
||||
#endif
|
||||
#include "file.hpp"
|
||||
#include "crc.hpp"
|
||||
#include "ui.hpp"
|
||||
#include "filefn.hpp"
|
||||
#include "filestr.hpp"
|
||||
#include "find.hpp"
|
||||
@ -47,11 +47,11 @@
|
||||
#include "archive.hpp"
|
||||
#include "match.hpp"
|
||||
#include "cmddata.hpp"
|
||||
#include "ui.hpp"
|
||||
#include "filcreat.hpp"
|
||||
#include "consio.hpp"
|
||||
#include "system.hpp"
|
||||
#include "log.hpp"
|
||||
#include "rawint.hpp"
|
||||
#include "rawread.hpp"
|
||||
#include "encname.hpp"
|
||||
#include "resource.hpp"
|
||||
|
10
deps/unrar/rardefs.hpp
vendored
10
deps/unrar/rardefs.hpp
vendored
@ -9,9 +9,13 @@
|
||||
|
||||
#define ASIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
// MAXPASSWORD is expected to be multiple of CRYPTPROTECTMEMORY_BLOCK_SIZE (16)
|
||||
// for CryptProtectMemory in SecPassword.
|
||||
#define MAXPASSWORD 128
|
||||
// MAXPASSWORD and MAXPASSWORD_RAR are expected to be multiple of
|
||||
// CRYPTPROTECTMEMORY_BLOCK_SIZE (16) for CryptProtectMemory in SecPassword.
|
||||
// We allow a larger MAXPASSWORD to unpack archives with lengthy passwords
|
||||
// in non-RAR formats in GUI versions. For RAR format we set MAXPASSWORD_RAR
|
||||
// to 128 for compatibility and because it is enough for AES-256.
|
||||
#define MAXPASSWORD 512
|
||||
#define MAXPASSWORD_RAR 128
|
||||
|
||||
#define MAXSFXSIZE 0x200000
|
||||
|
||||
|
6
deps/unrar/rawint.hpp
vendored
6
deps/unrar/rawint.hpp
vendored
@ -84,7 +84,7 @@ inline uint32 RawGetBE4(const byte *m)
|
||||
{
|
||||
#if defined(USE_MEM_BYTESWAP) && defined(_MSC_VER)
|
||||
return _byteswap_ulong(*(uint32 *)m);
|
||||
#elif defined(USE_MEM_BYTESWAP) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 2)
|
||||
#elif defined(USE_MEM_BYTESWAP) && (defined(__clang__) || defined(__GNUC__))
|
||||
return __builtin_bswap32(*(uint32 *)m);
|
||||
#else
|
||||
return uint32(m[0]<<24) | uint32(m[1]<<16) | uint32(m[2]<<8) | m[3];
|
||||
@ -97,7 +97,7 @@ inline void RawPutBE4(uint32 i,byte *mem)
|
||||
{
|
||||
#if defined(USE_MEM_BYTESWAP) && defined(_MSC_VER)
|
||||
*(uint32*)mem = _byteswap_ulong(i);
|
||||
#elif defined(USE_MEM_BYTESWAP) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 2)
|
||||
#elif defined(USE_MEM_BYTESWAP) && (defined(__clang__) || defined(__GNUC__))
|
||||
*(uint32*)mem = __builtin_bswap32(i);
|
||||
#else
|
||||
mem[0]=byte(i>>24);
|
||||
@ -112,7 +112,7 @@ inline uint32 ByteSwap32(uint32 i)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return _byteswap_ulong(i);
|
||||
#elif (__GNUC__ > 3) && (__GNUC_MINOR__ > 2)
|
||||
#elif defined(__clang__) || defined(__GNUC__)
|
||||
return __builtin_bswap32(i);
|
||||
#else
|
||||
return (rotl32(i,24)&0xFF00FF00)|(rotl32(i,8)&0x00FF00FF);
|
||||
|
92
deps/unrar/rdwrfn.cpp
vendored
92
deps/unrar/rdwrfn.cpp
vendored
@ -16,6 +16,7 @@ void ComprDataIO::Init()
|
||||
UnpackFromMemory=false;
|
||||
UnpackToMemory=false;
|
||||
UnpPackedSize=0;
|
||||
UnpPackedLeft=0;
|
||||
ShowProgress=true;
|
||||
TestMode=false;
|
||||
SkipUnpCRC=false;
|
||||
@ -35,7 +36,9 @@ void ComprDataIO::Init()
|
||||
SubHead=NULL;
|
||||
SubHeadPos=NULL;
|
||||
CurrentCommand=0;
|
||||
ProcessedArcSize=TotalArcSize=0;
|
||||
ProcessedArcSize=0;
|
||||
LastArcSize=0;
|
||||
TotalArcSize=0;
|
||||
}
|
||||
|
||||
|
||||
@ -75,10 +78,10 @@ int ComprDataIO::UnpRead(byte *Addr,size_t Count)
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t SizeToRead=((int64)Count>UnpPackedSize) ? (size_t)UnpPackedSize:Count;
|
||||
size_t SizeToRead=((int64)Count>UnpPackedLeft) ? (size_t)UnpPackedLeft:Count;
|
||||
if (SizeToRead > 0)
|
||||
{
|
||||
if (UnpVolume && Decryption && (int64)Count>UnpPackedSize)
|
||||
if (UnpVolume && Decryption && (int64)Count>UnpPackedLeft)
|
||||
{
|
||||
// We need aligned blocks for decryption and we want "Keep broken
|
||||
// files" to work efficiently with missing encrypted volumes.
|
||||
@ -109,7 +112,7 @@ int ComprDataIO::UnpRead(byte *Addr,size_t Count)
|
||||
ReadAddr+=ReadSize;
|
||||
Count-=ReadSize;
|
||||
#endif
|
||||
UnpPackedSize-=ReadSize;
|
||||
UnpPackedLeft-=ReadSize;
|
||||
|
||||
// Do not ask for next volume if we read something from current volume.
|
||||
// If next volume is missing, we need to process all data from current
|
||||
@ -118,7 +121,7 @@ int ComprDataIO::UnpRead(byte *Addr,size_t Count)
|
||||
// we ask for next volume also if we have non-aligned encryption block.
|
||||
// Since we adjust data size for decryption earlier above,
|
||||
// it does not hurt "Keep broken files" mode efficiency.
|
||||
if (UnpVolume && UnpPackedSize == 0 &&
|
||||
if (UnpVolume && UnpPackedLeft == 0 &&
|
||||
(ReadSize==0 || Decryption && (TotalRead & CRYPT_BLOCK_MASK) != 0) )
|
||||
{
|
||||
#ifndef NOVOLUME
|
||||
@ -134,7 +137,7 @@ int ComprDataIO::UnpRead(byte *Addr,size_t Count)
|
||||
}
|
||||
Archive *SrcArc=(Archive *)SrcFile;
|
||||
if (SrcArc!=NULL)
|
||||
ShowUnpRead(SrcArc->CurBlockPos+CurUnpRead,UnpArcSize);
|
||||
ShowUnpRead(SrcArc->NextBlockPos-UnpPackedSize+CurUnpRead,TotalArcSize);
|
||||
if (ReadSize!=-1)
|
||||
{
|
||||
ReadSize=TotalRead;
|
||||
@ -148,18 +151,11 @@ int ComprDataIO::UnpRead(byte *Addr,size_t Count)
|
||||
}
|
||||
|
||||
|
||||
#if defined(RARDLL) && defined(_MSC_VER) && !defined(_WIN_64)
|
||||
// Disable the run time stack check for unrar.dll, so we can manipulate
|
||||
// with ProcessDataProc call type below. Run time check would intercept
|
||||
// a wrong ESP before we restore it.
|
||||
#pragma runtime_checks( "s", off )
|
||||
#endif
|
||||
|
||||
void ComprDataIO::UnpWrite(byte *Addr,size_t Count)
|
||||
{
|
||||
|
||||
#ifdef RARDLL
|
||||
RAROptions *Cmd=((Archive *)SrcFile)->GetRAROptions();
|
||||
CommandData *Cmd=((Archive *)SrcFile)->GetCommandData();
|
||||
if (Cmd->DllOpMode!=RAR_SKIP)
|
||||
{
|
||||
if (Cmd->Callback!=NULL &&
|
||||
@ -167,28 +163,7 @@ void ComprDataIO::UnpWrite(byte *Addr,size_t Count)
|
||||
ErrHandler.Exit(RARX_USERBREAK);
|
||||
if (Cmd->ProcessDataProc!=NULL)
|
||||
{
|
||||
// Here we preserve ESP value. It is necessary for those developers,
|
||||
// who still define ProcessDataProc callback as "C" type function,
|
||||
// even though in year 2001 we announced in unrar.dll whatsnew.txt
|
||||
// that it will be PASCAL type (for compatibility with Visual Basic).
|
||||
#if defined(_MSC_VER)
|
||||
#ifndef _WIN_64
|
||||
__asm mov ebx,esp
|
||||
#endif
|
||||
#elif defined(_WIN_ALL) && defined(__BORLANDC__)
|
||||
_EBX=_ESP;
|
||||
#endif
|
||||
int RetCode=Cmd->ProcessDataProc(Addr,(int)Count);
|
||||
|
||||
// Restore ESP after ProcessDataProc with wrongly defined calling
|
||||
// convention broken it.
|
||||
#if defined(_MSC_VER)
|
||||
#ifndef _WIN_64
|
||||
__asm mov esp,ebx
|
||||
#endif
|
||||
#elif defined(_WIN_ALL) && defined(__BORLANDC__)
|
||||
_ESP=_EBX;
|
||||
#endif
|
||||
if (RetCode==0)
|
||||
ErrHandler.Exit(RARX_USERBREAK);
|
||||
}
|
||||
@ -216,11 +191,6 @@ void ComprDataIO::UnpWrite(byte *Addr,size_t Count)
|
||||
Wait();
|
||||
}
|
||||
|
||||
#if defined(RARDLL) && defined(_MSC_VER) && !defined(_WIN_64)
|
||||
// Restore the run time stack check for unrar.dll.
|
||||
#pragma runtime_checks( "s", restore )
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@ -230,15 +200,11 @@ void ComprDataIO::ShowUnpRead(int64 ArcPos,int64 ArcSize)
|
||||
{
|
||||
if (ShowProgress && SrcFile!=NULL)
|
||||
{
|
||||
if (TotalArcSize!=0)
|
||||
{
|
||||
// important when processing several archives or multivolume archive
|
||||
ArcSize=TotalArcSize;
|
||||
// Important when processing several archives or multivolume archive.
|
||||
ArcPos+=ProcessedArcSize;
|
||||
}
|
||||
|
||||
Archive *SrcArc=(Archive *)SrcFile;
|
||||
RAROptions *Cmd=SrcArc->GetRAROptions();
|
||||
CommandData *Cmd=SrcArc->GetCommandData();
|
||||
|
||||
int CurPercent=ToPercent(ArcPos,ArcSize);
|
||||
if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
|
||||
@ -333,3 +299,37 @@ void ComprDataIO::SetUnpackFromMemory(byte *Addr,uint Size)
|
||||
UnpackFromMemoryAddr=Addr;
|
||||
UnpackFromMemorySize=Size;
|
||||
}
|
||||
|
||||
// Extraction progress is based on the position in archive and we adjust
|
||||
// the total archives size here, so trailing blocks do not prevent progress
|
||||
// reaching 100% at the end of extraction. Alternatively we could print "100%"
|
||||
// after completing the entire archive extraction, but then we would need
|
||||
// to take into account possible messages like the checksum error after
|
||||
// last file percent progress.
|
||||
void ComprDataIO::AdjustTotalArcSize(Archive *Arc)
|
||||
{
|
||||
// If we know a position of QO or RR blocks, use them to adjust the total
|
||||
// packed size to beginning of these blocks. Earlier we already calculated
|
||||
// the total size based on entire archive sizes. We also set LastArcSize
|
||||
// to start of first trailing block, to add it later to ProcessedArcSize.
|
||||
int64 ArcLength=Arc->IsSeekable() ? Arc->FileLength() : 0;
|
||||
if (Arc->MainHead.QOpenOffset!=0) // QO is always preceding RR record.
|
||||
LastArcSize=Arc->MainHead.QOpenOffset;
|
||||
else
|
||||
if (Arc->MainHead.RROffset!=0)
|
||||
LastArcSize=Arc->MainHead.RROffset;
|
||||
else
|
||||
{
|
||||
// If neither QO nor RR are found, exclude the approximate size of
|
||||
// end of archive block.
|
||||
// We select EndBlock to be larger than typical 8 bytes HEAD_ENDARC,
|
||||
// but to not exceed the smallest 22 bytes HEAD_FILE with 1 byte file
|
||||
// name, so we do not have two files with 100% at the end of archive.
|
||||
const uint EndBlock=23;
|
||||
|
||||
if (ArcLength>EndBlock)
|
||||
LastArcSize=ArcLength-EndBlock;
|
||||
}
|
||||
|
||||
TotalArcSize-=ArcLength-LastArcSize;
|
||||
}
|
||||
|
9
deps/unrar/rdwrfn.hpp
vendored
9
deps/unrar/rdwrfn.hpp
vendored
@ -1,6 +1,7 @@
|
||||
#ifndef _RAR_DATAIO_
|
||||
#define _RAR_DATAIO_
|
||||
|
||||
class Archive;
|
||||
class CmdAdd;
|
||||
class Unpack;
|
||||
class ArcFileSearch;
|
||||
@ -29,6 +30,7 @@ class ComprDataIO
|
||||
byte *UnpWrAddr;
|
||||
|
||||
int64 UnpPackedSize;
|
||||
int64 UnpPackedLeft;
|
||||
|
||||
bool ShowProgress;
|
||||
bool TestMode;
|
||||
@ -61,7 +63,7 @@ class ComprDataIO
|
||||
void UnpWrite(byte *Addr,size_t Count);
|
||||
void EnableShowProgress(bool Show) {ShowProgress=Show;}
|
||||
void GetUnpackedData(byte **Data,size_t *Size);
|
||||
void SetPackedSizeToRead(int64 Size) {UnpPackedSize=Size;}
|
||||
void SetPackedSizeToRead(int64 Size) {UnpPackedSize=UnpPackedLeft=Size;}
|
||||
void SetTestMode(bool Mode) {TestMode=Mode;}
|
||||
void SetSkipUnpCRC(bool Skip) {SkipUnpCRC=Skip;}
|
||||
void SetNoFileHeader(bool Mode) {NoFileHeader=Mode;}
|
||||
@ -76,12 +78,12 @@ class ComprDataIO
|
||||
void SetUnpackToMemory(byte *Addr,uint Size);
|
||||
void SetUnpackFromMemory(byte *Addr,uint Size);
|
||||
void SetCurrentCommand(wchar Cmd) {CurrentCommand=Cmd;}
|
||||
void AdjustTotalArcSize(Archive *Arc);
|
||||
|
||||
|
||||
bool PackVolume;
|
||||
bool UnpVolume;
|
||||
bool NextVolumeMissing;
|
||||
int64 UnpArcSize;
|
||||
int64 CurPackRead,CurPackWrite,CurUnpRead,CurUnpWrite;
|
||||
|
||||
|
||||
@ -89,6 +91,9 @@ class ComprDataIO
|
||||
// Used to calculate the total operation progress.
|
||||
int64 ProcessedArcSize;
|
||||
|
||||
// Last extracted archive size up to QO or RR block.
|
||||
int64 LastArcSize;
|
||||
|
||||
int64 TotalArcSize;
|
||||
|
||||
DataHash PackedDataHash; // Packed write and unpack read hash.
|
||||
|
4
deps/unrar/recvol.cpp
vendored
4
deps/unrar/recvol.cpp
vendored
@ -5,7 +5,7 @@
|
||||
|
||||
|
||||
|
||||
bool RecVolumesRestore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
bool RecVolumesRestore(CommandData *Cmd,const wchar *Name,bool Silent)
|
||||
{
|
||||
Archive Arc(Cmd);
|
||||
if (!Arc.Open(Name))
|
||||
@ -42,7 +42,7 @@ bool RecVolumesRestore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
}
|
||||
|
||||
|
||||
void RecVolumesTest(RAROptions *Cmd,Archive *Arc,const wchar *Name)
|
||||
void RecVolumesTest(CommandData *Cmd,Archive *Arc,const wchar *Name)
|
||||
{
|
||||
wchar RevName[NM];
|
||||
*RevName=0;
|
||||
|
22
deps/unrar/recvol.hpp
vendored
22
deps/unrar/recvol.hpp
vendored
@ -14,11 +14,11 @@ class RecVolumes3
|
||||
ThreadPool *RSThreadPool;
|
||||
#endif
|
||||
public:
|
||||
RecVolumes3(RAROptions *Cmd,bool TestOnly);
|
||||
RecVolumes3(CommandData *Cmd,bool TestOnly);
|
||||
~RecVolumes3();
|
||||
void Make(RAROptions *Cmd,wchar *ArcName);
|
||||
bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent);
|
||||
void Test(RAROptions *Cmd,const wchar *Name);
|
||||
void Make(CommandData *Cmd,wchar *ArcName);
|
||||
bool Restore(CommandData *Cmd,const wchar *Name,bool Silent);
|
||||
void Test(CommandData *Cmd,const wchar *Name);
|
||||
};
|
||||
|
||||
|
||||
@ -48,8 +48,8 @@ struct RecRSThreadData
|
||||
class RecVolumes5
|
||||
{
|
||||
private:
|
||||
void ProcessRS(RAROptions *Cmd,uint DataNum,const byte *Data,uint MaxRead,bool Encode);
|
||||
void ProcessRS(RAROptions *Cmd,uint MaxRead,bool Encode);
|
||||
void ProcessRS(CommandData *Cmd,uint DataNum,const byte *Data,uint MaxRead,bool Encode);
|
||||
void ProcessRS(CommandData *Cmd,uint MaxRead,bool Encode);
|
||||
uint ReadHeader(File *RecFile,bool FirstRev);
|
||||
|
||||
Array<RecVolItem> RecItems;
|
||||
@ -76,13 +76,13 @@ class RecVolumes5
|
||||
public: // 'public' only because called from thread functions.
|
||||
void ProcessAreaRS(RecRSThreadData *td);
|
||||
public:
|
||||
RecVolumes5(RAROptions *Cmd,bool TestOnly);
|
||||
RecVolumes5(CommandData *Cmd,bool TestOnly);
|
||||
~RecVolumes5();
|
||||
bool Restore(RAROptions *Cmd,const wchar *Name,bool Silent);
|
||||
void Test(RAROptions *Cmd,const wchar *Name);
|
||||
bool Restore(CommandData *Cmd,const wchar *Name,bool Silent);
|
||||
void Test(CommandData *Cmd,const wchar *Name);
|
||||
};
|
||||
|
||||
bool RecVolumesRestore(RAROptions *Cmd,const wchar *Name,bool Silent);
|
||||
void RecVolumesTest(RAROptions *Cmd,Archive *Arc,const wchar *Name);
|
||||
bool RecVolumesRestore(CommandData *Cmd,const wchar *Name,bool Silent);
|
||||
void RecVolumesTest(CommandData *Cmd,Archive *Arc,const wchar *Name);
|
||||
|
||||
#endif
|
||||
|
6
deps/unrar/recvol3.cpp
vendored
6
deps/unrar/recvol3.cpp
vendored
@ -36,7 +36,7 @@ THREAD_PROC(RSDecodeThread)
|
||||
}
|
||||
#endif
|
||||
|
||||
RecVolumes3::RecVolumes3(RAROptions *Cmd,bool TestOnly)
|
||||
RecVolumes3::RecVolumes3(CommandData *Cmd,bool TestOnly)
|
||||
{
|
||||
memset(SrcFile,0,sizeof(SrcFile));
|
||||
if (TestOnly)
|
||||
@ -99,7 +99,7 @@ static bool IsNewStyleRev(const wchar *Name)
|
||||
}
|
||||
|
||||
|
||||
bool RecVolumes3::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
bool RecVolumes3::Restore(CommandData *Cmd,const wchar *Name,bool Silent)
|
||||
{
|
||||
wchar ArcName[NM];
|
||||
wcsncpyz(ArcName,Name,ASIZE(ArcName));
|
||||
@ -497,7 +497,7 @@ void RSEncode::DecodeBuf()
|
||||
}
|
||||
|
||||
|
||||
void RecVolumes3::Test(RAROptions *Cmd,const wchar *Name)
|
||||
void RecVolumes3::Test(CommandData *Cmd,const wchar *Name)
|
||||
{
|
||||
if (!IsNewStyleRev(Name)) // RAR 3.0 name#_#_#.rev do not include CRC32.
|
||||
{
|
||||
|
39
deps/unrar/recvol5.cpp
vendored
39
deps/unrar/recvol5.cpp
vendored
@ -1,6 +1,10 @@
|
||||
static const uint MaxVolumes=65535;
|
||||
|
||||
RecVolumes5::RecVolumes5(RAROptions *Cmd,bool TestOnly)
|
||||
// We select this limit arbitrarily, to prevent user creating too many
|
||||
// rev files by mistake.
|
||||
#define MAX_REV_TO_DATA_RATIO 10 // 1000% of rev files.
|
||||
|
||||
RecVolumes5::RecVolumes5(CommandData *Cmd,bool TestOnly)
|
||||
{
|
||||
RealBuf=NULL;
|
||||
RealReadBuffer=NULL;
|
||||
@ -66,7 +70,7 @@ THREAD_PROC(RecThreadRS)
|
||||
#endif
|
||||
|
||||
|
||||
void RecVolumes5::ProcessRS(RAROptions *Cmd,uint DataNum,const byte *Data,uint MaxRead,bool Encode)
|
||||
void RecVolumes5::ProcessRS(CommandData *Cmd,uint DataNum,const byte *Data,uint MaxRead,bool Encode)
|
||||
{
|
||||
/*
|
||||
RSCoder16 RS;
|
||||
@ -137,7 +141,7 @@ void RecVolumes5::ProcessAreaRS(RecRSThreadData *td)
|
||||
|
||||
|
||||
|
||||
bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
bool RecVolumes5::Restore(CommandData *Cmd,const wchar *Name,bool Silent)
|
||||
{
|
||||
wchar ArcName[NM];
|
||||
wcsncpyz(ArcName,Name,ASIZE(ArcName));
|
||||
@ -145,13 +149,16 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
wchar *Num=GetVolNumPart(ArcName);
|
||||
while (Num>ArcName && IsDigit(*(Num-1)))
|
||||
Num--;
|
||||
if (Num==ArcName)
|
||||
if (Num<=PointToName(ArcName))
|
||||
return false; // Numeric part is missing or entire volume name is numeric, not possible for RAR or REV volume.
|
||||
wcsncpyz(Num,L"*.*",ASIZE(ArcName)-(Num-ArcName));
|
||||
|
||||
wchar FirstVolName[NM];
|
||||
*FirstVolName=0;
|
||||
|
||||
wchar LongestRevName[NM];
|
||||
*LongestRevName=0;
|
||||
|
||||
int64 RecFileSize=0;
|
||||
|
||||
FindFile VolFind;
|
||||
@ -164,7 +171,7 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
|
||||
Archive *Vol=new Archive(Cmd);
|
||||
int ItemPos=-1;
|
||||
if (Vol->WOpen(fd.Name))
|
||||
if (!fd.IsDir && Vol->WOpen(fd.Name))
|
||||
{
|
||||
if (CmpExt(fd.Name,L"rev"))
|
||||
{
|
||||
@ -176,6 +183,9 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
|
||||
ItemPos=RecNum;
|
||||
FoundRecVolumes++;
|
||||
|
||||
if (wcslen(fd.Name)>wcslen(LongestRevName))
|
||||
wcsncpyz(LongestRevName,fd.Name,ASIZE(LongestRevName));
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -231,6 +241,15 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
if (FoundRecVolumes==0)
|
||||
return false;
|
||||
|
||||
// If we did not find even a single .rar volume, create .rar volume name
|
||||
// based on the longest .rev file name. Use longest .rev, so we have
|
||||
// enough space for volume number.
|
||||
if (*FirstVolName==0)
|
||||
{
|
||||
SetExt(LongestRevName,L"rar",ASIZE(LongestRevName));
|
||||
VolNameToFirstName(LongestRevName,FirstVolName,ASIZE(FirstVolName),true);
|
||||
}
|
||||
|
||||
uiMsg(UIMSG_RECVOLCALCCHECKSUM);
|
||||
|
||||
MissingVolumes=0;
|
||||
@ -301,7 +320,7 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
Item->f=NULL;
|
||||
}
|
||||
|
||||
if ((Item->New=(Item->f==NULL))) // Additional parentheses to avoid GCC warning.
|
||||
if ((Item->New=(Item->f==NULL))==true)
|
||||
{
|
||||
wcsncpyz(Item->Name,FirstVolName,ASIZE(Item->Name));
|
||||
uiMsg(UIMSG_CREATING,Item->Name);
|
||||
@ -316,7 +335,6 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
}
|
||||
NewVol->Prealloc(Item->FileSize);
|
||||
Item->f=NewVol;
|
||||
Item->New=true;
|
||||
}
|
||||
NextVolumeName(FirstVolName,ASIZE(FirstVolName),false);
|
||||
}
|
||||
@ -346,13 +364,11 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
RecBufferSize&=~(SSE_ALIGNMENT-1); // Align for SSE.
|
||||
#endif
|
||||
|
||||
uint *Data=new uint[TotalCount];
|
||||
|
||||
RSCoder16 RS;
|
||||
if (!RS.Init(DataCount,RecCount,ValidFlags))
|
||||
{
|
||||
uiMsg(UIERROR_OPFAILED);
|
||||
delete[] ValidFlags;
|
||||
delete[] Data;
|
||||
return false; // Should not happen, we check parameter validity above.
|
||||
}
|
||||
|
||||
@ -415,7 +431,6 @@ bool RecVolumes5::Restore(RAROptions *Cmd,const wchar *Name,bool Silent)
|
||||
RecItems[I].f->Close();
|
||||
|
||||
delete[] ValidFlags;
|
||||
delete[] Data;
|
||||
#if !defined(SILENT)
|
||||
if (!Cmd->DisablePercentage)
|
||||
mprintf(L"\b\b\b\b100%%");
|
||||
@ -479,7 +494,7 @@ uint RecVolumes5::ReadHeader(File *RecFile,bool FirstRev)
|
||||
}
|
||||
|
||||
|
||||
void RecVolumes5::Test(RAROptions *Cmd,const wchar *Name)
|
||||
void RecVolumes5::Test(CommandData *Cmd,const wchar *Name)
|
||||
{
|
||||
wchar VolName[NM];
|
||||
wcsncpyz(VolName,Name,ASIZE(VolName));
|
||||
|
211
deps/unrar/rijndael.cpp
vendored
211
deps/unrar/rijndael.cpp
vendored
@ -1,22 +1,40 @@
|
||||
/***************************************************************************
|
||||
* This code is based on public domain Szymon Stefanek AES implementation: *
|
||||
* http://www.pragmaware.net/software/rijndael/index.php *
|
||||
* *
|
||||
* Dynamic tables generation is based on the Brian Gladman work: *
|
||||
* http://fp.gladman.plus.com/cryptography_technology/rijndael *
|
||||
***************************************************************************/
|
||||
/**************************************************************************
|
||||
* This code is based on Szymon Stefanek public domain AES implementation *
|
||||
**************************************************************************/
|
||||
#include "rar.hpp"
|
||||
|
||||
#ifdef USE_SSE
|
||||
#include <wmmintrin.h>
|
||||
#endif
|
||||
|
||||
// not thread-safe ?
|
||||
//static byte S[256],S5[256],rcon[30];
|
||||
//static byte T1[256][4],T2[256][4],T3[256][4],T4[256][4];
|
||||
//static byte T5[256][4],T6[256][4],T7[256][4],T8[256][4];
|
||||
//static byte U1[256][4],U2[256][4],U3[256][4],U4[256][4];
|
||||
static byte S[256]=
|
||||
{
|
||||
99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
|
||||
202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
|
||||
183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
|
||||
4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
|
||||
9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
|
||||
83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
|
||||
208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
|
||||
81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
|
||||
205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
|
||||
96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
|
||||
224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
|
||||
231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
|
||||
186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
|
||||
112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
|
||||
225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
|
||||
140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22
|
||||
};
|
||||
|
||||
static byte S5[256];
|
||||
|
||||
// Round constants. 10 items are used by AES-128, 8 by AES-192, 7 by AES-256.
|
||||
static byte rcon[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36};
|
||||
|
||||
static byte T1[256][4],T2[256][4],T3[256][4],T4[256][4];
|
||||
static byte T5[256][4],T6[256][4],T7[256][4],T8[256][4];
|
||||
static byte U1[256][4],U2[256][4],U3[256][4],U4[256][4];
|
||||
|
||||
inline void Xor128(void *dest,const void *arg1,const void *arg2)
|
||||
{
|
||||
@ -64,7 +82,7 @@ inline void Copy128(byte *dest,const byte *src)
|
||||
|
||||
Rijndael::Rijndael()
|
||||
{
|
||||
//if (S[0]==0)
|
||||
if (S5[0]==0)
|
||||
GenerateTables();
|
||||
CBCMode = true; // Always true for RAR.
|
||||
}
|
||||
@ -72,18 +90,20 @@ Rijndael::Rijndael()
|
||||
|
||||
void Rijndael::Init(bool Encrypt,const byte *key,uint keyLen,const byte * initVector)
|
||||
{
|
||||
#ifdef USE_SSE
|
||||
// Check SSE here instead of constructor, so if object is a part of some
|
||||
// structure memset'ed before use, this variable is not lost.
|
||||
// Check SIMD here instead of constructor, so if object is a part of some
|
||||
// structure memset'ed before use, these variables are not lost.
|
||||
#if defined(USE_SSE)
|
||||
int CPUInfo[4];
|
||||
__cpuid(CPUInfo, 0x80000000); // Get the maximum supported cpuid function.
|
||||
if ((CPUInfo[0] & 0x7fffffff)>=1)
|
||||
__cpuid(CPUInfo, 0);
|
||||
if (CPUInfo[0]>=1) // Check the maximum supported cpuid function.
|
||||
{
|
||||
__cpuid(CPUInfo, 1);
|
||||
AES_NI=(CPUInfo[2] & 0x2000000)!=0;
|
||||
}
|
||||
else
|
||||
AES_NI=0;
|
||||
AES_NI=false;
|
||||
#elif defined(USE_NEON)
|
||||
AES_Neon=(getauxval(AT_HWCAP) & HWCAP_AES)!=0;
|
||||
#endif
|
||||
|
||||
// Other developers asked us to initialize it to suppress "may be used
|
||||
@ -123,18 +143,25 @@ void Rijndael::Init(bool Encrypt,const byte *key,uint keyLen,const byte * initVe
|
||||
keyEncToDec();
|
||||
}
|
||||
|
||||
|
||||
void Rijndael::blockEncrypt(const byte *input,size_t inputLen,byte *outBuffer)
|
||||
{
|
||||
if (inputLen <= 0)
|
||||
return;
|
||||
|
||||
size_t numBlocks = inputLen/16;
|
||||
#ifdef USE_SSE
|
||||
#if defined(USE_SSE)
|
||||
if (AES_NI)
|
||||
{
|
||||
blockEncryptSSE(input,numBlocks,outBuffer);
|
||||
return;
|
||||
}
|
||||
#elif defined(USE_NEON)
|
||||
if (AES_Neon)
|
||||
{
|
||||
blockEncryptNeon(input,numBlocks,outBuffer);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
byte *prevBlock = m_initVector;
|
||||
@ -222,18 +249,58 @@ void Rijndael::blockEncryptSSE(const byte *input,size_t numBlocks,byte *outBuffe
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_NEON
|
||||
void Rijndael::blockEncryptNeon(const byte *input,size_t numBlocks,byte *outBuffer)
|
||||
{
|
||||
byte *prevBlock = m_initVector;
|
||||
while (numBlocks > 0)
|
||||
{
|
||||
byte block[16];
|
||||
if (CBCMode)
|
||||
vst1q_u8(block, veorq_u8(vld1q_u8(prevBlock), vld1q_u8(input)));
|
||||
else
|
||||
vst1q_u8(block, vld1q_u8(input));
|
||||
|
||||
uint8x16_t data = vld1q_u8(block);
|
||||
for (uint i = 0; i < m_uRounds-1; i++)
|
||||
{
|
||||
data = vaeseq_u8(data, vld1q_u8((byte *)m_expandedKey[i]));
|
||||
data = vaesmcq_u8(data);
|
||||
}
|
||||
data = vaeseq_u8(data, vld1q_u8((byte *)(m_expandedKey[m_uRounds-1])));
|
||||
data = veorq_u8(data, vld1q_u8((byte *)(m_expandedKey[m_uRounds])));
|
||||
vst1q_u8(outBuffer, data);
|
||||
|
||||
prevBlock=outBuffer;
|
||||
|
||||
outBuffer += 16;
|
||||
input += 16;
|
||||
numBlocks--;
|
||||
}
|
||||
vst1q_u8(m_initVector, vld1q_u8(prevBlock));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void Rijndael::blockDecrypt(const byte *input, size_t inputLen, byte *outBuffer)
|
||||
{
|
||||
if (inputLen <= 0)
|
||||
return;
|
||||
|
||||
size_t numBlocks=inputLen/16;
|
||||
#ifdef USE_SSE
|
||||
#if defined(USE_SSE)
|
||||
if (AES_NI)
|
||||
{
|
||||
blockDecryptSSE(input,numBlocks,outBuffer);
|
||||
return;
|
||||
}
|
||||
#elif defined(USE_NEON)
|
||||
if (AES_Neon)
|
||||
{
|
||||
blockDecryptNeon(input,numBlocks,outBuffer);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
byte block[16], iv[4][4];
|
||||
@ -325,6 +392,41 @@ void Rijndael::blockDecryptSSE(const byte *input, size_t numBlocks, byte *outBuf
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_NEON
|
||||
void Rijndael::blockDecryptNeon(const byte *input, size_t numBlocks, byte *outBuffer)
|
||||
{
|
||||
byte iv[16];
|
||||
memcpy(iv,m_initVector,16);
|
||||
|
||||
while (numBlocks > 0)
|
||||
{
|
||||
uint8x16_t data = vld1q_u8(input);
|
||||
|
||||
for (int i=m_uRounds-1; i>0; i--)
|
||||
{
|
||||
data = vaesdq_u8(data, vld1q_u8((byte *)m_expandedKey[i+1]));
|
||||
data = vaesimcq_u8(data);
|
||||
}
|
||||
|
||||
data = vaesdq_u8(data, vld1q_u8((byte *)m_expandedKey[1]));
|
||||
data = veorq_u8(data, vld1q_u8((byte *)m_expandedKey[0]));
|
||||
|
||||
if (CBCMode)
|
||||
data = veorq_u8(data, vld1q_u8(iv));
|
||||
|
||||
vst1q_u8(iv, vld1q_u8(input));
|
||||
vst1q_u8(outBuffer, data);
|
||||
|
||||
input += 16;
|
||||
outBuffer += 16;
|
||||
numBlocks--;
|
||||
}
|
||||
|
||||
memcpy(m_initVector,iv,16);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ALGORITHM
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -417,51 +519,40 @@ void Rijndael::keyEncToDec()
|
||||
}
|
||||
|
||||
|
||||
#define ff_poly 0x011b
|
||||
#define ff_hi 0x80
|
||||
static byte gmul(byte a, byte b) // Galois field "peasant's algorithm" multiplication.
|
||||
{
|
||||
const byte poly=0x1b; // Lower byte of AES 0x11b irreducible polynomial.
|
||||
byte result = 0;
|
||||
while (b>0)
|
||||
{
|
||||
if ((b & 1) != 0)
|
||||
result ^= a;
|
||||
a = (a & 0x80) ? (a<<1)^poly : a<<1;
|
||||
b >>= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#define FFinv(x) ((x) ? pow[255 - log[x]]: 0)
|
||||
|
||||
#define FFmul02(x) (x ? pow[log[x] + 0x19] : 0)
|
||||
#define FFmul03(x) (x ? pow[log[x] + 0x01] : 0)
|
||||
#define FFmul09(x) (x ? pow[log[x] + 0xc7] : 0)
|
||||
#define FFmul0b(x) (x ? pow[log[x] + 0x68] : 0)
|
||||
#define FFmul0d(x) (x ? pow[log[x] + 0xee] : 0)
|
||||
#define FFmul0e(x) (x ? pow[log[x] + 0xdf] : 0)
|
||||
#define fwd_affine(x) \
|
||||
(w = (uint)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), (byte)(0x63^(w^(w>>8))))
|
||||
|
||||
#define inv_affine(x) \
|
||||
(w = (uint)x, w = (w<<1)^(w<<3)^(w<<6), (byte)(0x05^(w^(w>>8))))
|
||||
|
||||
// 2021-09-24: changed to slower and simpler code without interim tables.
|
||||
// It is still fast enough for our purpose.
|
||||
void Rijndael::GenerateTables()
|
||||
{
|
||||
unsigned char pow[512],log[256];
|
||||
int i = 0, w = 1;
|
||||
do
|
||||
{
|
||||
pow[i] = (byte)w;
|
||||
pow[i + 255] = (byte)w;
|
||||
log[w] = (byte)i++;
|
||||
w ^= (w << 1) ^ (w & ff_hi ? ff_poly : 0);
|
||||
} while (w != 1);
|
||||
for (int I=0;I<256;I++)
|
||||
S5[S[I]]=I;
|
||||
|
||||
for (int i = 0,w = 1; i < sizeof(rcon)/sizeof(rcon[0]); i++)
|
||||
for (int I=0;I<256;I++)
|
||||
{
|
||||
rcon[i] = w;
|
||||
w = (w << 1) ^ (w & ff_hi ? ff_poly : 0);
|
||||
}
|
||||
for(int i = 0; i < 256; ++i)
|
||||
{
|
||||
unsigned char b=S[i]=fwd_affine(FFinv((byte)i));
|
||||
T1[i][1]=T1[i][2]=T2[i][2]=T2[i][3]=T3[i][0]=T3[i][3]=T4[i][0]=T4[i][1]=b;
|
||||
T1[i][0]=T2[i][1]=T3[i][2]=T4[i][3]=FFmul02(b);
|
||||
T1[i][3]=T2[i][0]=T3[i][1]=T4[i][2]=FFmul03(b);
|
||||
S5[i] = b = FFinv(inv_affine((byte)i));
|
||||
U1[b][3]=U2[b][0]=U3[b][1]=U4[b][2]=T5[i][3]=T6[i][0]=T7[i][1]=T8[i][2]=FFmul0b(b);
|
||||
U1[b][1]=U2[b][2]=U3[b][3]=U4[b][0]=T5[i][1]=T6[i][2]=T7[i][3]=T8[i][0]=FFmul09(b);
|
||||
U1[b][2]=U2[b][3]=U3[b][0]=U4[b][1]=T5[i][2]=T6[i][3]=T7[i][0]=T8[i][1]=FFmul0d(b);
|
||||
U1[b][0]=U2[b][1]=U3[b][2]=U4[b][3]=T5[i][0]=T6[i][1]=T7[i][2]=T8[i][3]=FFmul0e(b);
|
||||
byte s=S[I];
|
||||
T1[I][1]=T1[I][2]=T2[I][2]=T2[I][3]=T3[I][0]=T3[I][3]=T4[I][0]=T4[I][1]=s;
|
||||
T1[I][0]=T2[I][1]=T3[I][2]=T4[I][3]=gmul(s,2);
|
||||
T1[I][3]=T2[I][0]=T3[I][1]=T4[I][2]=gmul(s,3);
|
||||
|
||||
byte b=S5[I];
|
||||
U1[b][3]=U2[b][0]=U3[b][1]=U4[b][2]=T5[I][3]=T6[I][0]=T7[I][1]=T8[I][2]=gmul(b,0xb);
|
||||
U1[b][1]=U2[b][2]=U3[b][3]=U4[b][0]=T5[I][1]=T6[I][2]=T7[I][3]=T8[I][0]=gmul(b,0x9);
|
||||
U1[b][2]=U2[b][3]=U3[b][0]=U4[b][1]=T5[I][2]=T6[I][3]=T7[I][0]=T8[I][1]=gmul(b,0xd);
|
||||
U1[b][0]=U2[b][1]=U3[b][2]=U4[b][3]=T5[I][0]=T6[I][1]=T7[I][2]=T8[I][3]=gmul(b,0xe);
|
||||
}
|
||||
}
|
||||
|
||||
|
21
deps/unrar/rijndael.hpp
vendored
21
deps/unrar/rijndael.hpp
vendored
@ -2,11 +2,7 @@
|
||||
#define _RIJNDAEL_H_
|
||||
|
||||
/**************************************************************************
|
||||
* This code is based on Szymon Stefanek AES implementation: *
|
||||
* http://www.esat.kuleuven.ac.be/~rijmen/rijndael/rijndael-cpplib.tar.gz *
|
||||
* *
|
||||
* Dynamic tables generation is based on the Brian Gladman's work: *
|
||||
* http://fp.gladman.plus.com/cryptography_technology/rijndael *
|
||||
* This code is based on Szymon Stefanek public domain AES implementation *
|
||||
**************************************************************************/
|
||||
|
||||
#define _MAX_KEY_COLUMNS (256/32)
|
||||
@ -22,6 +18,16 @@ class Rijndael
|
||||
|
||||
bool AES_NI;
|
||||
#endif
|
||||
#ifdef USE_NEON
|
||||
// Set "crypto" attribute as replacement of -march=armv8-a+crypto switch.
|
||||
__attribute__((target("crypto")))
|
||||
void blockEncryptNeon(const byte *input,size_t numBlocks,byte *outBuffer);
|
||||
__attribute__((target("crypto")))
|
||||
void blockDecryptNeon(const byte *input, size_t numBlocks, byte *outBuffer);
|
||||
|
||||
bool AES_Neon;
|
||||
#endif
|
||||
|
||||
void keySched(byte key[_MAX_KEY_COLUMNS][4]);
|
||||
void keyEncToDec();
|
||||
void GenerateTables();
|
||||
@ -33,11 +39,6 @@ class Rijndael
|
||||
int m_uRounds;
|
||||
byte m_initVector[MAX_IV_SIZE];
|
||||
byte m_expandedKey[_MAX_ROUNDS+1][4][4];
|
||||
|
||||
byte S[256],S5[256],rcon[30];
|
||||
byte T1[256][4],T2[256][4],T3[256][4],T4[256][4];
|
||||
byte T5[256][4],T6[256][4],T7[256][4],T8[256][4];
|
||||
byte U1[256][4],U2[256][4],U3[256][4],U4[256][4];
|
||||
public:
|
||||
Rijndael();
|
||||
void Init(bool Encrypt,const byte *key,uint keyLen,const byte *initVector);
|
||||
|
4
deps/unrar/rs16.cpp
vendored
4
deps/unrar/rs16.cpp
vendored
@ -95,7 +95,9 @@ bool RSCoder16::Init(uint DataCount, uint RecCount, bool *ValidityFlags)
|
||||
if (NE > ValidECC || NE == 0 || ValidECC == 0)
|
||||
return false;
|
||||
}
|
||||
if (ND + NR > gfSize || NR > ND || ND == 0 || NR == 0)
|
||||
|
||||
// 2021.09.01 - we allowed RR and REV >100%, so no more NR > ND check.
|
||||
if (ND + NR > gfSize || /*NR > ND ||*/ ND == 0 || NR == 0)
|
||||
return false;
|
||||
|
||||
delete[] MX;
|
||||
|
40
deps/unrar/savepos.hpp
vendored
40
deps/unrar/savepos.hpp
vendored
@ -1,40 +0,0 @@
|
||||
#ifndef _RAR_SAVEPOS_
|
||||
#define _RAR_SAVEPOS_
|
||||
|
||||
class SaveFilePos
|
||||
{
|
||||
private:
|
||||
File *SaveFile;
|
||||
int64 SavePos;
|
||||
public:
|
||||
SaveFilePos(File &Src)
|
||||
{
|
||||
SaveFile=&Src;
|
||||
SavePos=Src.Tell();
|
||||
}
|
||||
~SaveFilePos()
|
||||
{
|
||||
// Unless the file is already closed either by current exception
|
||||
// processing or intentionally by external code.
|
||||
if (SaveFile->IsOpened())
|
||||
{
|
||||
try
|
||||
{
|
||||
SaveFile->Seek(SavePos,SEEK_SET);
|
||||
}
|
||||
catch(RAR_EXIT)
|
||||
{
|
||||
// Seek() can throw an exception and it terminates process
|
||||
// if we are already processing another exception. Also in C++ 11
|
||||
// an exception in destructor always terminates process unless
|
||||
// we mark destructor with noexcept(false). So we do not want to
|
||||
// throw here. To prevent data loss we do not want to continue
|
||||
// execution after seek error, so we close the file.
|
||||
// Any next access to this file will return an error.
|
||||
SaveFile->Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
19
deps/unrar/scantree.cpp
vendored
19
deps/unrar/scantree.cpp
vendored
@ -215,11 +215,24 @@ bool ScanTree::GetNextMask()
|
||||
UnixSlashToDos(CurMask,CurMask,ASIZE(CurMask));
|
||||
#endif
|
||||
|
||||
// We wish to scan entire disk if mask like c:\ is specified
|
||||
// regardless of recursion mode. Use c:\*.* mask when need to scan only
|
||||
// the root directory.
|
||||
/*
|
||||
We prefer to scan entire disk if mask like \\server\share\ or c:\
|
||||
is specified regardless of recursion mode. Use \\server\share\*.*
|
||||
or c:\*.* mask to scan only the root directory.
|
||||
*/
|
||||
if (CurMask[0]=='\\' && CurMask[1]=='\\')
|
||||
{
|
||||
const wchar *Slash=wcschr(CurMask+2,'\\');
|
||||
if (Slash!=NULL)
|
||||
{
|
||||
Slash=wcschr(Slash+1,'\\');
|
||||
ScanEntireDisk=Slash!=NULL && *(Slash+1)==0;
|
||||
}
|
||||
}
|
||||
else
|
||||
ScanEntireDisk=IsDriveLetter(CurMask) && IsPathDiv(CurMask[2]) && CurMask[3]==0;
|
||||
|
||||
|
||||
wchar *Name=PointToName(CurMask);
|
||||
if (*Name==0)
|
||||
wcsncatz(CurMask,MASKALL,ASIZE(CurMask));
|
||||
|
24
deps/unrar/secpassword.cpp
vendored
24
deps/unrar/secpassword.cpp
vendored
@ -56,7 +56,6 @@ static CryptLoader GlobalCryptLoader;
|
||||
|
||||
SecPassword::SecPassword()
|
||||
{
|
||||
CrossProcess=false;
|
||||
Set(L"");
|
||||
}
|
||||
|
||||
@ -70,7 +69,8 @@ SecPassword::~SecPassword()
|
||||
void SecPassword::Clean()
|
||||
{
|
||||
PasswordSet=false;
|
||||
cleandata(Password,sizeof(Password));
|
||||
if (Password.size()>0)
|
||||
cleandata(&Password[0],Password.size());
|
||||
}
|
||||
|
||||
|
||||
@ -104,7 +104,7 @@ void SecPassword::Process(const wchar *Src,size_t SrcSize,wchar *Dst,size_t DstS
|
||||
// Source string can be shorter than destination as in case when we process
|
||||
// -p<pwd> parameter, so we need to take into account both sizes.
|
||||
memcpy(Dst,Src,Min(SrcSize,DstSize)*sizeof(*Dst));
|
||||
SecHideData(Dst,DstSize*sizeof(*Dst),Encode,CrossProcess);
|
||||
SecHideData(Dst,DstSize*sizeof(*Dst),Encode,false);
|
||||
}
|
||||
|
||||
|
||||
@ -112,7 +112,7 @@ void SecPassword::Get(wchar *Psw,size_t MaxSize)
|
||||
{
|
||||
if (PasswordSet)
|
||||
{
|
||||
Process(Password,ASIZE(Password),Psw,MaxSize,false);
|
||||
Process(&Password[0],Password.size(),Psw,MaxSize,false);
|
||||
Psw[MaxSize-1]=0;
|
||||
}
|
||||
else
|
||||
@ -124,15 +124,14 @@ void SecPassword::Get(wchar *Psw,size_t MaxSize)
|
||||
|
||||
void SecPassword::Set(const wchar *Psw)
|
||||
{
|
||||
if (*Psw==0)
|
||||
{
|
||||
PasswordSet=false;
|
||||
memset(Password,0,sizeof(Password));
|
||||
}
|
||||
else
|
||||
// Eliminate any traces of previously stored password for security reason
|
||||
// in case it was longer than new one.
|
||||
Clean();
|
||||
|
||||
if (*Psw!=0)
|
||||
{
|
||||
PasswordSet=true;
|
||||
Process(Psw,wcslen(Psw)+1,Password,ASIZE(Password),true);
|
||||
Process(Psw,wcslen(Psw)+1,&Password[0],Password.size(),true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,6 +162,9 @@ bool SecPassword::operator == (SecPassword &psw)
|
||||
}
|
||||
|
||||
|
||||
// Set CrossProcess to true if we need to pass a password to another process.
|
||||
// We use CrossProcess when transferring parameters to UAC elevated WinRAR
|
||||
// and Windows GUI SFX modules.
|
||||
void SecHideData(void *Data,size_t DataSize,bool Encode,bool CrossProcess)
|
||||
{
|
||||
// CryptProtectMemory is not available in UWP and CryptProtectData
|
||||
|
9
deps/unrar/secpassword.hpp
vendored
9
deps/unrar/secpassword.hpp
vendored
@ -8,10 +8,7 @@ class SecPassword
|
||||
private:
|
||||
void Process(const wchar *Src,size_t SrcSize,wchar *Dst,size_t DstSize,bool Encode);
|
||||
|
||||
wchar Password[MAXPASSWORD];
|
||||
|
||||
// It is important to have this 'bool' value, so if our object is cleaned
|
||||
// with memset as a part of larger structure, it is handled correctly.
|
||||
std::vector<wchar> Password = std::vector<wchar>(MAXPASSWORD);
|
||||
bool PasswordSet;
|
||||
public:
|
||||
SecPassword();
|
||||
@ -22,10 +19,6 @@ class SecPassword
|
||||
bool IsSet() {return PasswordSet;}
|
||||
size_t Length();
|
||||
bool operator == (SecPassword &psw);
|
||||
|
||||
// Set to true if we need to pass a password to another process.
|
||||
// We use it when transferring parameters to UAC elevated WinRAR.
|
||||
bool CrossProcess;
|
||||
};
|
||||
|
||||
|
||||
|
76
deps/unrar/strfn.cpp
vendored
76
deps/unrar/strfn.cpp
vendored
@ -121,48 +121,26 @@ wchar* RemoveLF(wchar *Str)
|
||||
}
|
||||
|
||||
|
||||
unsigned char loctolower(unsigned char ch)
|
||||
{
|
||||
#if defined(_WIN_ALL)
|
||||
// Convert to LPARAM first to avoid a warning in 64 bit mode.
|
||||
// Convert to uintptr_t to avoid Clang/win error: cast to 'char *' from smaller integer type 'unsigned char' [-Werror,-Wint-to-pointer-cast]
|
||||
return (int)(LPARAM)CharLowerA((LPSTR)(uintptr_t)ch);
|
||||
#else
|
||||
return tolower(ch);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
unsigned char loctoupper(unsigned char ch)
|
||||
{
|
||||
#if defined(_WIN_ALL)
|
||||
// Convert to LPARAM first to avoid a warning in 64 bit mode.
|
||||
// Convert to uintptr_t to avoid Clang/win error: cast to 'char *' from smaller integer type 'unsigned char' [-Werror,-Wint-to-pointer-cast]
|
||||
return (int)(LPARAM)CharUpperA((LPSTR)(uintptr_t)ch);
|
||||
#else
|
||||
return toupper(ch);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// toupper with English only results if English input is provided.
|
||||
// It avoids Turkish (small i) -> (big I with dot) conversion problem.
|
||||
// We do not define 'ch' as 'int' to avoid necessity to cast all
|
||||
#if defined(SFX_MODULE)
|
||||
// char version of etoupperw. Used in console SFX module only.
|
||||
// Fast toupper for English only input and output. Additionally to speed,
|
||||
// it also avoids Turkish small i to big I with dot conversion problem.
|
||||
// We do not define 'c' as 'int' to avoid necessity to cast all
|
||||
// signed chars passed to this function to unsigned char.
|
||||
unsigned char etoupper(unsigned char ch)
|
||||
unsigned char etoupper(unsigned char c)
|
||||
{
|
||||
if (ch=='i')
|
||||
return 'I';
|
||||
return toupper(ch);
|
||||
return c>='a' && c<='z' ? c-'a'+'A' : c;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Unicode version of etoupper.
|
||||
wchar etoupperw(wchar ch)
|
||||
// Fast toupper for English only input and output. Additionally to speed,
|
||||
// it also avoids Turkish small i to big I with dot conversion problem.
|
||||
// We do not define 'c' as 'int' to avoid necessity to cast all
|
||||
// signed wchars passed to this function to unsigned char.
|
||||
wchar etoupperw(wchar c)
|
||||
{
|
||||
if (ch=='i')
|
||||
return 'I';
|
||||
return toupperw(ch);
|
||||
return c>='a' && c<='z' ? c-'a'+'A' : c;
|
||||
}
|
||||
|
||||
|
||||
@ -379,6 +357,32 @@ void itoa(int64 n,wchar *Str,size_t MaxSize)
|
||||
}
|
||||
|
||||
|
||||
// Convert the number to string using thousand separators.
|
||||
void fmtitoa(int64 n,wchar *Str,size_t MaxSize)
|
||||
{
|
||||
static wchar ThSep=0; // Thousands separator.
|
||||
#ifdef _WIN_ALL
|
||||
wchar Info[10];
|
||||
if (!ThSep!=0 && GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_STHOUSAND,Info,ASIZE(Info))>0)
|
||||
ThSep=*Info;
|
||||
#elif defined(_UNIX)
|
||||
ThSep=*localeconv()->thousands_sep;
|
||||
#endif
|
||||
if (ThSep==0) // If failed to detect the actual separator value.
|
||||
ThSep=' ';
|
||||
wchar RawText[30]; // 20 characters are enough for largest unsigned 64 bit int.
|
||||
itoa(n,RawText,ASIZE(RawText));
|
||||
uint S=0,D=0,L=wcslen(RawText)%3;
|
||||
while (RawText[S]!=0 && D+1<MaxSize)
|
||||
{
|
||||
if (S!=0 && (S+3-L)%3==0)
|
||||
Str[D++]=ThSep;
|
||||
Str[D++]=RawText[S++];
|
||||
}
|
||||
Str[D]=0;
|
||||
}
|
||||
|
||||
|
||||
const wchar* GetWide(const char *Src)
|
||||
{
|
||||
const size_t MaxLength=NM;
|
||||
|
9
deps/unrar/strfn.hpp
vendored
9
deps/unrar/strfn.hpp
vendored
@ -13,16 +13,16 @@ int stricomp(const char *s1,const char *s2);
|
||||
int strnicomp(const char *s1,const char *s2,size_t n);
|
||||
wchar* RemoveEOL(wchar *Str);
|
||||
wchar* RemoveLF(wchar *Str);
|
||||
unsigned char loctolower(unsigned char ch);
|
||||
unsigned char loctoupper(unsigned char ch);
|
||||
|
||||
void strncpyz(char *dest, const char *src, size_t maxlen);
|
||||
void wcsncpyz(wchar *dest, const wchar *src, size_t maxlen);
|
||||
void strncatz(char* dest, const char* src, size_t maxlen);
|
||||
void wcsncatz(wchar* dest, const wchar* src, size_t maxlen);
|
||||
|
||||
unsigned char etoupper(unsigned char ch);
|
||||
wchar etoupperw(wchar ch);
|
||||
#if defined(SFX_MODULE)
|
||||
unsigned char etoupper(unsigned char c);
|
||||
#endif
|
||||
wchar etoupperw(wchar c);
|
||||
|
||||
bool IsDigit(int ch);
|
||||
bool IsSpace(int ch);
|
||||
@ -42,6 +42,7 @@ int wcsnicompc(const wchar *s1,const wchar *s2,size_t n);
|
||||
|
||||
void itoa(int64 n,char *Str,size_t MaxSize);
|
||||
void itoa(int64 n,wchar *Str,size_t MaxSize);
|
||||
void fmtitoa(int64 n,wchar *Str,size_t MaxSize);
|
||||
const wchar* GetWide(const char *Src);
|
||||
const wchar* GetCmdParam(const wchar *CmdLine,wchar *Param,size_t MaxSize);
|
||||
#ifndef RARDLL
|
||||
|
5
deps/unrar/suballoc.cpp
vendored
5
deps/unrar/suballoc.cpp
vendored
@ -71,7 +71,7 @@ void SubAllocator::StopSubAllocator()
|
||||
if ( SubAllocatorSize )
|
||||
{
|
||||
SubAllocatorSize=0;
|
||||
//free(HeapStart);
|
||||
free(HeapStart);
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,8 +88,7 @@ bool SubAllocator::StartSubAllocator(int SASize)
|
||||
// units: one as reserve for HeapEnd overflow checks and another
|
||||
// to provide the space to correctly align UnitsStart.
|
||||
uint AllocSize=t/FIXED_UNIT_SIZE*UNIT_SIZE+2*UNIT_SIZE;
|
||||
//if ((HeapStart=(byte *)malloc(AllocSize)) == NULL)
|
||||
if ((HeapStart=(byte *)HeapStartFixed) == NULL)
|
||||
if ((HeapStart=(byte *)malloc(AllocSize)) == NULL)
|
||||
{
|
||||
ErrHandler.MemoryError();
|
||||
return false;
|
||||
|
3
deps/unrar/suballoc.hpp
vendored
3
deps/unrar/suballoc.hpp
vendored
@ -80,9 +80,6 @@ class SubAllocator
|
||||
long GetAllocatedMemory() {return(SubAllocatorSize);}
|
||||
|
||||
byte *pText, *UnitsStart,*HeapEnd,*FakeUnitsStart;
|
||||
|
||||
byte *HeapStartFixed;
|
||||
void SetHeapStartFixed(byte *p) {HeapStartFixed=p;}
|
||||
};
|
||||
|
||||
|
||||
|
6
deps/unrar/system.cpp
vendored
6
deps/unrar/system.cpp
vendored
@ -187,10 +187,10 @@ SSE_VERSION _SSE_Version=GetSSEVersion();
|
||||
SSE_VERSION GetSSEVersion()
|
||||
{
|
||||
int CPUInfo[4];
|
||||
__cpuid(CPUInfo, 0x80000000);
|
||||
__cpuid(CPUInfo, 0);
|
||||
|
||||
// Maximum supported cpuid function. For example, Pentium M 755 returns 4 here.
|
||||
uint MaxSupported=CPUInfo[0] & 0x7fffffff;
|
||||
// Maximum supported cpuid function.
|
||||
uint MaxSupported=CPUInfo[0];
|
||||
|
||||
if (MaxSupported>=7)
|
||||
{
|
||||
|
2
deps/unrar/threadmisc.cpp
vendored
2
deps/unrar/threadmisc.cpp
vendored
@ -149,3 +149,5 @@ uint GetNumberOfThreads()
|
||||
return NumCPU;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
4
deps/unrar/timefn.cpp
vendored
4
deps/unrar/timefn.cpp
vendored
@ -273,12 +273,12 @@ void RarTime::SetAgeText(const wchar *TimeText)
|
||||
uint Seconds=0,Value=0;
|
||||
for (uint I=0;TimeText[I]!=0;I++)
|
||||
{
|
||||
int Ch=TimeText[I];
|
||||
wchar Ch=TimeText[I];
|
||||
if (IsDigit(Ch))
|
||||
Value=Value*10+Ch-'0';
|
||||
else
|
||||
{
|
||||
switch(etoupper(Ch))
|
||||
switch(etoupperw(Ch))
|
||||
{
|
||||
case 'D':
|
||||
Seconds+=Value*24*3600;
|
||||
|
11
deps/unrar/timefn.hpp
vendored
11
deps/unrar/timefn.hpp
vendored
@ -22,6 +22,17 @@ class RarTime
|
||||
|
||||
// Internal time representation in 1/TICKS_PER_SECOND since 01.01.1601.
|
||||
// We use nanoseconds here to handle the high precision Unix time.
|
||||
// It allows dates up to July 2185.
|
||||
//
|
||||
// If we'll ever need to extend the date range, we can define a lower
|
||||
// precision Windows version of TICKS_PER_SECOND. But then Unix and Windows
|
||||
// versions can differ in least significant digits of "lt" time output
|
||||
// for Unix archives.
|
||||
// Alternatively we can introduce 'bool HighPrecision' set to true
|
||||
// in SetUnixNS() and TicksPerSecond() instead of constant above.
|
||||
// It might be more reliable than defining TicksPerSecond variable,
|
||||
// which wouldn't survive memset of any structure hosting RarTime.
|
||||
// We would need to eliminate all such memsets in the entire code first.
|
||||
uint64 itime;
|
||||
public:
|
||||
// RarLocalTime::Reminder precision. Must be equal to TICKS_PER_SECOND.
|
||||
|
38
deps/unrar/ui.hpp
vendored
38
deps/unrar/ui.hpp
vendored
@ -39,7 +39,7 @@ enum UIMESSAGE_CODE {
|
||||
UIERROR_UOWNERBROKEN, UIERROR_UOWNERGETOWNERID, UIERROR_UOWNERGETGROUPID,
|
||||
UIERROR_UOWNERSET, UIERROR_ULINKREAD, UIERROR_ULINKEXIST,
|
||||
UIERROR_OPENPRESERVEATIME, UIERROR_READERRTRUNCATED, UIERROR_READERRCOUNT,
|
||||
UIERROR_DIRNAMEEXISTS,
|
||||
UIERROR_DIRNAMEEXISTS,UIERROR_TRUNCPSW,UIERROR_ADJUSTVALUE,
|
||||
|
||||
UIMSG_FIRST,
|
||||
UIMSG_STRING, UIMSG_BUILD, UIMSG_RRSEARCH, UIMSG_ANALYZEFILEDATA,
|
||||
@ -49,6 +49,7 @@ enum UIMESSAGE_CODE {
|
||||
UIMSG_CORRECTINGNAME, UIMSG_BADARCHIVE, UIMSG_CREATING, UIMSG_RENAMING,
|
||||
UIMSG_RECVOLCALCCHECKSUM, UIMSG_RECVOLFOUND, UIMSG_RECVOLMISSING,
|
||||
UIMSG_MISSINGVOL, UIMSG_RECONSTRUCTING, UIMSG_CHECKSUM, UIMSG_FAT32SIZE,
|
||||
UIMSG_SKIPENCARC, UIMSG_FILERENAME,
|
||||
|
||||
UIWAIT_FIRST,
|
||||
UIWAIT_DISKFULLNEXT, UIWAIT_FCREATEERROR, UIWAIT_BADPSW,
|
||||
@ -76,7 +77,7 @@ enum UIASKREP_RESULT {
|
||||
};
|
||||
|
||||
UIASKREP_RESULT uiAskReplace(wchar *Name,size_t MaxNameSize,int64 FileSize,RarTime *FileTime,uint Flags);
|
||||
UIASKREP_RESULT uiAskReplaceEx(RAROptions *Cmd,wchar *Name,size_t MaxNameSize,int64 FileSize,RarTime *FileTime,uint Flags);
|
||||
UIASKREP_RESULT uiAskReplaceEx(CommandData *Cmd,wchar *Name,size_t MaxNameSize,int64 FileSize,RarTime *FileTime,uint Flags);
|
||||
|
||||
void uiInit(SOUND_NOTIFY_MODE Sound);
|
||||
|
||||
@ -87,7 +88,7 @@ void uiExtractProgress(int64 CurFileSize,int64 TotalFileSize,int64 CurSize,int64
|
||||
void uiProcessProgress(const char *Command,int64 CurSize,int64 TotalSize);
|
||||
|
||||
enum UIPASSWORD_TYPE {UIPASSWORD_GLOBAL,UIPASSWORD_FILE,UIPASSWORD_ARCHIVE};
|
||||
bool uiGetPassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password);
|
||||
bool uiGetPassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password,CheckPassword *CheckPwd);
|
||||
bool uiIsGlobalPasswordSet();
|
||||
|
||||
enum UIALARM_TYPE {UIALARM_ERROR, UIALARM_INFO, UIALARM_QUESTION};
|
||||
@ -144,30 +145,31 @@ class uiMsgStore
|
||||
// Templates recognize usual NULL as integer, not wchar*.
|
||||
#define UINULL ((wchar *)NULL)
|
||||
|
||||
inline void uiMsg(UIMESSAGE_CODE Code)
|
||||
inline void uiMsgBase(uiMsgStore &Store)
|
||||
{
|
||||
uiMsgStore Store(Code);
|
||||
Store.Msg();
|
||||
// Called last, when no parameters are left.
|
||||
}
|
||||
|
||||
template<class T1> void uiMsg(UIMESSAGE_CODE Code,T1 a1)
|
||||
template<class T1,class... TN> void uiMsgBase(uiMsgStore &Store,T1&& a1,TN&&... aN)
|
||||
{
|
||||
uiMsgStore Store(Code);
|
||||
// Process first parameter and pass the rest to same uiMsgBase.
|
||||
Store<<a1;
|
||||
Store.Msg();
|
||||
uiMsgBase(Store,aN...);
|
||||
}
|
||||
|
||||
template<class T1,class T2> void uiMsg(UIMESSAGE_CODE Code,T1 a1,T2 a2)
|
||||
|
||||
// Use variadic templates.
|
||||
//
|
||||
// We must pass variable parameters by reference, so no temporary copies are
|
||||
// created for custom string objects like CStringBase in 7-Zip decompression
|
||||
// code. Such temporary copies would be destroyed inside of recursive
|
||||
// uiMsgBase calls, leaving us with Str[] items pointing at released memory.
|
||||
// Since we pass integer values as well, we can't use & references
|
||||
// and must resort to && rvalue references.
|
||||
template<class... TN> void uiMsg(UIMESSAGE_CODE Code,TN&&... aN)
|
||||
{
|
||||
uiMsgStore Store(Code);
|
||||
Store<<a1<<a2;
|
||||
Store.Msg();
|
||||
}
|
||||
|
||||
template<class T1,class T2,class T3> void uiMsg(UIMESSAGE_CODE code,T1 a1,T2 a2,T3 a3)
|
||||
{
|
||||
uiMsgStore Store(code);
|
||||
Store<<a1<<a2<<a3;
|
||||
uiMsgBase(Store,aN...);
|
||||
Store.Msg();
|
||||
}
|
||||
|
||||
|
2
deps/unrar/uicommon.cpp
vendored
2
deps/unrar/uicommon.cpp
vendored
@ -8,7 +8,7 @@ void uiInit(SOUND_NOTIFY_MODE Sound)
|
||||
|
||||
// Additionally to handling user input, it analyzes and sets command options.
|
||||
// Returns only 'replace', 'skip' and 'cancel' codes.
|
||||
UIASKREP_RESULT uiAskReplaceEx(RAROptions *Cmd,wchar *Name,size_t MaxNameSize,int64 FileSize,RarTime *FileTime,uint Flags)
|
||||
UIASKREP_RESULT uiAskReplaceEx(CommandData *Cmd,wchar *Name,size_t MaxNameSize,int64 FileSize,RarTime *FileTime,uint Flags)
|
||||
{
|
||||
if (Cmd->Overwrite==OVERWRITE_NONE)
|
||||
return UIASKREP_R_SKIP;
|
||||
|
22
deps/unrar/uiconsole.cpp
vendored
22
deps/unrar/uiconsole.cpp
vendored
@ -71,7 +71,10 @@ bool uiStartFileExtract(const wchar *FileName,bool Extract,bool Test,bool Skip)
|
||||
|
||||
void uiExtractProgress(int64 CurFileSize,int64 TotalFileSize,int64 CurSize,int64 TotalSize)
|
||||
{
|
||||
int CurPercent=ToPercent(CurSize,TotalSize);
|
||||
// We set the total size to 0 to update only the current progress and keep
|
||||
// the total progress intact in WinRAR. Unlike WinRAR, console RAR has only
|
||||
// the total progress and updates it with current values in such case.
|
||||
int CurPercent=TotalSize!=0 ? ToPercent(CurSize,TotalSize) : ToPercent(CurFileSize,TotalFileSize);
|
||||
mprintf(L"\b\b\b\b%3d%%",CurPercent);
|
||||
}
|
||||
|
||||
@ -247,6 +250,9 @@ void uiMsgStore::Msg()
|
||||
mprintf(L"\n"); // Needed when called from CmdExtract::ExtractCurrentFile.
|
||||
break;
|
||||
#ifndef SFX_MODULE
|
||||
case UIERROR_OPFAILED:
|
||||
Log(NULL,St(MOpFailed));
|
||||
break;
|
||||
case UIERROR_NEWRARFORMAT:
|
||||
Log(Str[0],St(MNewRarFormat));
|
||||
break;
|
||||
@ -256,6 +262,7 @@ void uiMsgStore::Msg()
|
||||
break;
|
||||
case UIERROR_MISSINGVOL:
|
||||
Log(Str[0],St(MAbsNextVol),Str[0]);
|
||||
mprintf(L" "); // For progress percent.
|
||||
break;
|
||||
#ifndef SFX_MODULE
|
||||
case UIERROR_NEEDPREVVOL:
|
||||
@ -329,6 +336,13 @@ void uiMsgStore::Msg()
|
||||
case UIERROR_DIRNAMEEXISTS:
|
||||
Log(NULL,St(MDirNameExists));
|
||||
break;
|
||||
case UIERROR_TRUNCPSW:
|
||||
eprintf(St(MTruncPsw),Num[0]);
|
||||
eprintf(L"\n");
|
||||
break;
|
||||
case UIERROR_ADJUSTVALUE:
|
||||
Log(NULL,St(MAdjustValue),Str[0],Str[1]);
|
||||
break;
|
||||
|
||||
#ifndef SFX_MODULE
|
||||
case UIMSG_STRING:
|
||||
@ -369,6 +383,9 @@ void uiMsgStore::Msg()
|
||||
mprintf(St(MFAT32Size));
|
||||
mprintf(L" "); // For progress percent.
|
||||
break;
|
||||
case UIMSG_SKIPENCARC:
|
||||
Log(NULL,St(MSkipEncArc),Str[0]);
|
||||
break;
|
||||
|
||||
|
||||
|
||||
@ -379,7 +396,8 @@ void uiMsgStore::Msg()
|
||||
}
|
||||
|
||||
|
||||
bool uiGetPassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password)
|
||||
bool uiGetPassword(UIPASSWORD_TYPE Type,const wchar *FileName,
|
||||
SecPassword *Password,CheckPassword *CheckPwd)
|
||||
{
|
||||
// Unlike GUI we cannot provide Cancel button here, so we use the empty
|
||||
// password to abort. Otherwise user not knowing a password would need to
|
||||
|
3
deps/unrar/uisilent.cpp
vendored
3
deps/unrar/uisilent.cpp
vendored
@ -33,7 +33,8 @@ void uiMsgStore::Msg()
|
||||
}
|
||||
|
||||
|
||||
bool uiGetPassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password)
|
||||
bool uiGetPassword(UIPASSWORD_TYPE Type,const wchar *FileName,
|
||||
SecPassword *Password,CheckPassword *CheckPwd)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
40
deps/unrar/ulinks.cpp
vendored
40
deps/unrar/ulinks.cpp
vendored
@ -50,7 +50,28 @@ static bool IsFullPath(const char *PathA) // Unix ASCII version.
|
||||
}
|
||||
|
||||
|
||||
bool ExtractUnixLink30(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName)
|
||||
// For security purpose we prefer to be sure that CharToWide completed
|
||||
// successfully and even if it truncated a string for some reason,
|
||||
// it didn't affect the number of path related characters we analyze
|
||||
// in IsRelativeSymlinkSafe later.
|
||||
// This check is likely to be excessive, but let's keep it anyway.
|
||||
static bool SafeCharToWide(const char *Src,wchar *Dest,size_t DestSize)
|
||||
{
|
||||
if (!CharToWide(Src,Dest,DestSize) || *Dest==0)
|
||||
return false;
|
||||
uint SrcChars=0,DestChars=0;
|
||||
for (uint I=0;Src[I]!=0;I++)
|
||||
if (Src[I]=='/' || Src[I]=='.')
|
||||
SrcChars++;
|
||||
for (uint I=0;Dest[I]!=0;I++)
|
||||
if (Dest[I]=='/' || Dest[I]=='.')
|
||||
DestChars++;
|
||||
return SrcChars==DestChars;
|
||||
}
|
||||
|
||||
|
||||
static bool ExtractUnixLink30(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,
|
||||
const wchar *LinkName,bool &UpLink)
|
||||
{
|
||||
char Target[NM];
|
||||
if (IsLink(Arc.FileHead.FileAttr))
|
||||
@ -72,21 +93,22 @@ bool ExtractUnixLink30(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const w
|
||||
return true;
|
||||
|
||||
wchar TargetW[NM];
|
||||
CharToWide(Target,TargetW,ASIZE(TargetW));
|
||||
// Check for *TargetW==0 to catch CharToWide failure.
|
||||
if (!SafeCharToWide(Target,TargetW,ASIZE(TargetW)))
|
||||
return false;
|
||||
// Use Arc.FileHead.FileName instead of LinkName, since LinkName
|
||||
// can include the destination path as a prefix, which can
|
||||
// confuse IsRelativeSymlinkSafe algorithm.
|
||||
if (!Cmd->AbsoluteLinks && (*TargetW==0 || IsFullPath(TargetW) ||
|
||||
if (!Cmd->AbsoluteLinks && (IsFullPath(TargetW) ||
|
||||
!IsRelativeSymlinkSafe(Cmd,Arc.FileHead.FileName,LinkName,TargetW)))
|
||||
return false;
|
||||
UpLink=strstr(Target,"..")!=NULL;
|
||||
return UnixSymlink(Cmd,Target,LinkName,&Arc.FileHead.mtime,&Arc.FileHead.atime);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ExtractUnixLink50(CommandData *Cmd,const wchar *Name,FileHeader *hd)
|
||||
static bool ExtractUnixLink50(CommandData *Cmd,const wchar *Name,FileHeader *hd)
|
||||
{
|
||||
char Target[NM];
|
||||
WideToChar(hd->RedirName,Target,ASIZE(Target));
|
||||
@ -100,11 +122,15 @@ bool ExtractUnixLink50(CommandData *Cmd,const wchar *Name,FileHeader *hd)
|
||||
return false;
|
||||
DosSlashToUnix(Target,Target,ASIZE(Target));
|
||||
}
|
||||
|
||||
wchar TargetW[NM];
|
||||
if (!SafeCharToWide(Target,TargetW,ASIZE(TargetW)))
|
||||
return false;
|
||||
// Use hd->FileName instead of LinkName, since LinkName can include
|
||||
// the destination path as a prefix, which can confuse
|
||||
// IsRelativeSymlinkSafe algorithm.
|
||||
if (!Cmd->AbsoluteLinks && (IsFullPath(Target) ||
|
||||
!IsRelativeSymlinkSafe(Cmd,hd->FileName,Name,hd->RedirName)))
|
||||
if (!Cmd->AbsoluteLinks && (IsFullPath(TargetW) ||
|
||||
!IsRelativeSymlinkSafe(Cmd,hd->FileName,Name,TargetW)))
|
||||
return false;
|
||||
return UnixSymlink(Cmd,Target,Name,&hd->mtime,&hd->atime);
|
||||
}
|
||||
|
60
deps/unrar/unicode.cpp
vendored
60
deps/unrar/unicode.cpp
vendored
@ -229,10 +229,11 @@ void CharToWideMap(const char *Src,wchar *Dest,size_t DestSize,bool &Success)
|
||||
#endif
|
||||
|
||||
|
||||
// SrcSize is in wide characters, not in bytes.
|
||||
byte* WideToRaw(const wchar *Src,byte *Dest,size_t SrcSize)
|
||||
// SrcSize is source data size in wide characters, not in bytes.
|
||||
// DestSize is the maximum allowed destination size.
|
||||
byte* WideToRaw(const wchar *Src,size_t SrcSize,byte *Dest,size_t DestSize)
|
||||
{
|
||||
for (size_t I=0;I<SrcSize;I++,Src++)
|
||||
for (size_t I=0;I<SrcSize && I*2+1<DestSize;I++,Src++)
|
||||
{
|
||||
Dest[I*2]=(byte)*Src;
|
||||
Dest[I*2+1]=(byte)(*Src>>8);
|
||||
@ -601,59 +602,6 @@ char* SupportDBCS::charnext(const char *s)
|
||||
// to break string processing loops.
|
||||
return (char *)(IsLeadByte[(byte)*s] && s[1]!=0 ? s+2:s+1);
|
||||
}
|
||||
|
||||
|
||||
size_t SupportDBCS::strlend(const char *s)
|
||||
{
|
||||
size_t Length=0;
|
||||
while (*s!=0)
|
||||
{
|
||||
if (IsLeadByte[(byte)*s])
|
||||
s+=2;
|
||||
else
|
||||
s++;
|
||||
Length++;
|
||||
}
|
||||
return(Length);
|
||||
}
|
||||
|
||||
|
||||
char* SupportDBCS::strchrd(const char *s, int c)
|
||||
{
|
||||
while (*s!=0)
|
||||
if (IsLeadByte[(byte)*s])
|
||||
s+=2;
|
||||
else
|
||||
if (*s==c)
|
||||
return((char *)s);
|
||||
else
|
||||
s++;
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
void SupportDBCS::copychrd(char *dest,const char *src)
|
||||
{
|
||||
dest[0]=src[0];
|
||||
if (IsLeadByte[(byte)src[0]])
|
||||
dest[1]=src[1];
|
||||
}
|
||||
|
||||
|
||||
char* SupportDBCS::strrchrd(const char *s, int c)
|
||||
{
|
||||
const char *found=NULL;
|
||||
while (*s!=0)
|
||||
if (IsLeadByte[(byte)*s])
|
||||
s+=2;
|
||||
else
|
||||
{
|
||||
if (*s==c)
|
||||
found=s;
|
||||
s++;
|
||||
}
|
||||
return((char *)found);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
21
deps/unrar/unicode.hpp
vendored
21
deps/unrar/unicode.hpp
vendored
@ -7,7 +7,7 @@
|
||||
|
||||
bool WideToChar(const wchar *Src,char *Dest,size_t DestSize);
|
||||
bool CharToWide(const char *Src,wchar *Dest,size_t DestSize);
|
||||
byte* WideToRaw(const wchar *Src,byte *Dest,size_t SrcSize);
|
||||
byte* WideToRaw(const wchar *Src,size_t SrcSize,byte *Dest,size_t DestSize);
|
||||
wchar* RawToWide(const byte *Src,wchar *Dest,size_t DestSize);
|
||||
void WideToUtf(const wchar *Src,char *Dest,size_t DestSize);
|
||||
size_t WideToUtfSize(const wchar *Src);
|
||||
@ -33,34 +33,19 @@ class SupportDBCS
|
||||
public:
|
||||
SupportDBCS();
|
||||
void Init();
|
||||
|
||||
char* charnext(const char *s);
|
||||
size_t strlend(const char *s);
|
||||
char *strchrd(const char *s, int c);
|
||||
char *strrchrd(const char *s, int c);
|
||||
void copychrd(char *dest,const char *src);
|
||||
|
||||
bool IsLeadByte[256];
|
||||
bool DBCSMode;
|
||||
};
|
||||
|
||||
extern SupportDBCS gdbcs;
|
||||
|
||||
inline char* charnext(const char *s) {return (char *)(gdbcs.DBCSMode ? gdbcs.charnext(s):s+1);}
|
||||
inline size_t strlend(const char *s) {return (uint)(gdbcs.DBCSMode ? gdbcs.strlend(s):strlen(s));}
|
||||
inline char* strchrd(const char *s, int c) {return (char *)(gdbcs.DBCSMode ? gdbcs.strchrd(s,c):strchr(s,c));}
|
||||
inline char* strrchrd(const char *s, int c) {return (char *)(gdbcs.DBCSMode ? gdbcs.strrchrd(s,c):strrchr(s,c));}
|
||||
inline void copychrd(char *dest,const char *src) {if (gdbcs.DBCSMode) gdbcs.copychrd(dest,src); else *dest=*src;}
|
||||
inline bool IsDBCSMode() {return(gdbcs.DBCSMode);}
|
||||
inline void InitDBCS() {gdbcs.Init();}
|
||||
inline bool IsDBCSMode() {return gdbcs.DBCSMode;}
|
||||
|
||||
#else
|
||||
#define charnext(s) ((s)+1)
|
||||
#define strlend strlen
|
||||
#define strchrd strchr
|
||||
#define strrchrd strrchr
|
||||
#define IsDBCSMode() (true)
|
||||
inline void copychrd(char *dest,const char *src) {*dest=*src;}
|
||||
#define IsDBCSMode() (false)
|
||||
#endif
|
||||
|
||||
|
||||
|
18
deps/unrar/unpack.cpp
vendored
18
deps/unrar/unpack.cpp
vendored
@ -16,7 +16,7 @@
|
||||
#include "unpack50frag.cpp"
|
||||
|
||||
Unpack::Unpack(ComprDataIO *DataIO)
|
||||
:Inp(false),VMCodeInp(false)
|
||||
:Inp(true),VMCodeInp(true)
|
||||
{
|
||||
UnpIO=DataIO;
|
||||
Window=NULL;
|
||||
@ -49,8 +49,8 @@ Unpack::~Unpack()
|
||||
{
|
||||
InitFilters30(false);
|
||||
|
||||
//if (Window!=NULL)
|
||||
// free(Window);
|
||||
if (Window!=NULL)
|
||||
free(Window);
|
||||
#ifdef RAR_SMP
|
||||
delete UnpThreadPool;
|
||||
delete[] ReadBufMT;
|
||||
@ -117,7 +117,7 @@ void Unpack::Init(size_t WinSize,bool Solid)
|
||||
if (Grow && Fragmented)
|
||||
throw std::bad_alloc();
|
||||
|
||||
byte *NewWindow=Fragmented ? NULL : (byte *)hcwin;
|
||||
byte *NewWindow=Fragmented ? NULL : (byte *)malloc(WinSize);
|
||||
|
||||
if (NewWindow==NULL)
|
||||
if (Grow || WinSize<0x1000000)
|
||||
@ -130,7 +130,7 @@ void Unpack::Init(size_t WinSize,bool Solid)
|
||||
{
|
||||
if (Window!=NULL) // If allocated by preceding files.
|
||||
{
|
||||
//free(Window);
|
||||
free(Window);
|
||||
Window=NULL;
|
||||
}
|
||||
FragWindow.Init(WinSize);
|
||||
@ -141,7 +141,7 @@ void Unpack::Init(size_t WinSize,bool Solid)
|
||||
{
|
||||
// Clean the window to generate the same output when unpacking corrupt
|
||||
// RAR files, which may access unused areas of sliding dictionary.
|
||||
//memset(NewWindow,0,WinSize);
|
||||
memset(NewWindow,0,WinSize);
|
||||
|
||||
// If Window is not NULL, it means that window size has grown.
|
||||
// In solid streams we need to copy data to a new window in such case.
|
||||
@ -151,8 +151,8 @@ void Unpack::Init(size_t WinSize,bool Solid)
|
||||
for (size_t I=1;I<=MaxWinSize;I++)
|
||||
NewWindow[(UnpPtr-I)&(WinSize-1)]=Window[(UnpPtr-I)&(MaxWinSize-1)];
|
||||
|
||||
//if (Window!=NULL)
|
||||
// free(Window);
|
||||
if (Window!=NULL)
|
||||
free(Window);
|
||||
Window=NewWindow;
|
||||
}
|
||||
|
||||
@ -324,7 +324,7 @@ void Unpack::MakeDecodeTables(byte *LengthTable,DecodeTable *Dec,uint Size)
|
||||
Dec->QuickBits=MAX_QUICK_DECODE_BITS;
|
||||
break;
|
||||
default:
|
||||
Dec->QuickBits=MAX_QUICK_DECODE_BITS-3;
|
||||
Dec->QuickBits=MAX_QUICK_DECODE_BITS>3 ? MAX_QUICK_DECODE_BITS-3 : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
10
deps/unrar/unpack.hpp
vendored
10
deps/unrar/unpack.hpp
vendored
@ -23,8 +23,8 @@
|
||||
// allocation. Must be equal or larger than MAX_ANALYZE_SIZE.
|
||||
#define MAX_FILTER_BLOCK_SIZE 0x400000
|
||||
|
||||
// Write data in 4 MB or smaller blocks. Must not exceed PACK_MAX_WRITE,
|
||||
// so we keep a number of buffered filters in unpacker reasonable.
|
||||
// Write data in 4 MB or smaller blocks. Must not exceed PACK_MAX_READ,
|
||||
// so we keep the number of buffered filters in unpacker reasonable.
|
||||
#define UNPACK_MAX_WRITE 0x400000
|
||||
|
||||
// Decode compressed bit fields to alphabet numbers.
|
||||
@ -93,17 +93,17 @@ struct UnpackBlockTables
|
||||
|
||||
#ifdef RAR_SMP
|
||||
enum UNP_DEC_TYPE {
|
||||
UNPDT_LITERAL,UNPDT_MATCH,UNPDT_FULLREP,UNPDT_REP,UNPDT_FILTER
|
||||
UNPDT_LITERAL=0,UNPDT_MATCH,UNPDT_FULLREP,UNPDT_REP,UNPDT_FILTER
|
||||
};
|
||||
|
||||
struct UnpackDecodedItem
|
||||
{
|
||||
UNP_DEC_TYPE Type;
|
||||
byte Type; // 'byte' instead of enum type to reduce memory use.
|
||||
ushort Length;
|
||||
union
|
||||
{
|
||||
uint Distance;
|
||||
byte Literal[4];
|
||||
byte Literal[8]; // Store up to 8 chars here to speed up extraction.
|
||||
};
|
||||
};
|
||||
|
||||
|
4
deps/unrar/unpack30.cpp
vendored
4
deps/unrar/unpack30.cpp
vendored
@ -55,7 +55,7 @@ void Unpack::Unpack29(bool Solid)
|
||||
if (!UnpReadBuf30())
|
||||
break;
|
||||
}
|
||||
if (((WrPtr-UnpPtr) & MaxWinMask)<260 && WrPtr!=UnpPtr)
|
||||
if (((WrPtr-UnpPtr) & MaxWinMask)<=MAX3_INC_LZ_MATCH && WrPtr!=UnpPtr)
|
||||
{
|
||||
UnpWriteBuf30();
|
||||
if (WrittenFileSize>DestUnpSize)
|
||||
@ -637,7 +637,7 @@ bool Unpack::ReadTables30()
|
||||
if (BitField & 0x8000)
|
||||
{
|
||||
UnpBlockType=BLOCK_PPM;
|
||||
return(PPM.DecodeInit(this,PPMEscChar,hcppm));
|
||||
return(PPM.DecodeInit(this,PPMEscChar));
|
||||
}
|
||||
UnpBlockType=BLOCK_LZ;
|
||||
|
||||
|
4
deps/unrar/unpack50.cpp
vendored
4
deps/unrar/unpack50.cpp
vendored
@ -42,7 +42,7 @@ void Unpack::Unpack5(bool Solid)
|
||||
break;
|
||||
}
|
||||
|
||||
if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr)
|
||||
if (((WriteBorder-UnpPtr) & MaxWinMask)<=MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr)
|
||||
{
|
||||
UnpWriteBuf();
|
||||
if (WrittenFileSize>DestUnpSize)
|
||||
@ -93,7 +93,7 @@ void Unpack::Unpack5(bool Solid)
|
||||
}
|
||||
else
|
||||
{
|
||||
Distance+=Inp.getbits32()>>(32-DBits);
|
||||
Distance+=Inp.getbits()>>(16-DBits);
|
||||
Inp.addbits(DBits);
|
||||
}
|
||||
}
|
||||
|
14
deps/unrar/unpack50mt.cpp
vendored
14
deps/unrar/unpack50mt.cpp
vendored
@ -345,7 +345,7 @@ void Unpack::UnpackDecode(UnpackThreadData &D)
|
||||
if (D.DecodedSize>1)
|
||||
{
|
||||
UnpackDecodedItem *PrevItem=CurItem-1;
|
||||
if (PrevItem->Type==UNPDT_LITERAL && PrevItem->Length<3)
|
||||
if (PrevItem->Type==UNPDT_LITERAL && PrevItem->Length<ASIZE(PrevItem->Literal)-1)
|
||||
{
|
||||
PrevItem->Length++;
|
||||
PrevItem->Literal[PrevItem->Length]=(byte)MainSlot;
|
||||
@ -388,7 +388,7 @@ void Unpack::UnpackDecode(UnpackThreadData &D)
|
||||
}
|
||||
else
|
||||
{
|
||||
Distance+=D.Inp.getbits32()>>(32-DBits);
|
||||
Distance+=D.Inp.getbits()>>(16-DBits);
|
||||
D.Inp.addbits(DBits);
|
||||
}
|
||||
}
|
||||
@ -451,7 +451,7 @@ bool Unpack::ProcessDecoded(UnpackThreadData &D)
|
||||
while (Item<Border)
|
||||
{
|
||||
UnpPtr&=MaxWinMask;
|
||||
if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr)
|
||||
if (((WriteBorder-UnpPtr) & MaxWinMask)<=MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr)
|
||||
{
|
||||
UnpWriteBuf();
|
||||
if (WrittenFileSize>DestUnpSize)
|
||||
@ -461,10 +461,10 @@ bool Unpack::ProcessDecoded(UnpackThreadData &D)
|
||||
if (Item->Type==UNPDT_LITERAL)
|
||||
{
|
||||
#if defined(LITTLE_ENDIAN) && defined(ALLOW_MISALIGNED)
|
||||
if (Item->Length==3 && UnpPtr<MaxWinSize-4)
|
||||
if (Item->Length==7 && UnpPtr<MaxWinSize-8)
|
||||
{
|
||||
*(uint32 *)(Window+UnpPtr)=*(uint32 *)Item->Literal;
|
||||
UnpPtr+=4;
|
||||
*(uint64 *)(Window+UnpPtr)=*(uint64 *)(Item->Literal);
|
||||
UnpPtr+=8;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -559,7 +559,7 @@ bool Unpack::UnpackLargeBlock(UnpackThreadData &D)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr)
|
||||
if (((WriteBorder-UnpPtr) & MaxWinMask)<=MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr)
|
||||
{
|
||||
UnpWriteBuf();
|
||||
if (WrittenFileSize>DestUnpSize)
|
||||
|
10
deps/unrar/version.hpp
vendored
10
deps/unrar/version.hpp
vendored
@ -1,6 +1,6 @@
|
||||
#define RARVER_MAJOR 6
|
||||
#define RARVER_MINOR 1
|
||||
#define RARVER_BETA 0
|
||||
#define RARVER_DAY 7
|
||||
#define RARVER_MONTH 4
|
||||
#define RARVER_YEAR 2021
|
||||
#define RARVER_MINOR 22
|
||||
#define RARVER_BETA 1
|
||||
#define RARVER_DAY 14
|
||||
#define RARVER_MONTH 5
|
||||
#define RARVER_YEAR 2023
|
||||
|
78
deps/unrar/volume.cpp
vendored
78
deps/unrar/volume.cpp
vendored
@ -1,15 +1,15 @@
|
||||
#include "rar.hpp"
|
||||
|
||||
#ifdef RARDLL
|
||||
static bool DllVolChange(RAROptions *Cmd,wchar *NextName,size_t NameSize);
|
||||
static bool DllVolNotify(RAROptions *Cmd,wchar *NextName);
|
||||
static bool DllVolChange(CommandData *Cmd,wchar *NextName,size_t NameSize);
|
||||
static bool DllVolNotify(CommandData *Cmd,wchar *NextName);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,wchar Command)
|
||||
{
|
||||
RAROptions *Cmd=Arc.GetRAROptions();
|
||||
CommandData *Cmd=Arc.GetCommandData();
|
||||
|
||||
HEADER_TYPE HeaderType=Arc.GetHeaderType();
|
||||
FileHeader *hd=HeaderType==HEAD_SERVICE ? &Arc.SubHead:&Arc.FileHead;
|
||||
@ -25,10 +25,12 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,wchar Comma
|
||||
uiMsg(UIERROR_CHECKSUMPACKED, Arc.FileName, hd->FileName);
|
||||
}
|
||||
|
||||
bool PrevVolEncrypted=Arc.Encrypted;
|
||||
|
||||
int64 PosBeforeClose=Arc.Tell();
|
||||
|
||||
if (DataIO!=NULL)
|
||||
DataIO->ProcessedArcSize+=Arc.FileLength();
|
||||
DataIO->ProcessedArcSize+=DataIO->LastArcSize;
|
||||
|
||||
|
||||
Arc.Close();
|
||||
@ -40,12 +42,20 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,wchar Comma
|
||||
#if !defined(SFX_MODULE) && !defined(RARDLL)
|
||||
bool RecoveryDone=false;
|
||||
#endif
|
||||
bool FailedOpen=false,OldSchemeTested=false;
|
||||
bool OldSchemeTested=false;
|
||||
|
||||
bool FailedOpen=false; // No more next volume open attempts if true.
|
||||
#if !defined(SILENT)
|
||||
// In -vp mode we force the pause before next volume even if it is present
|
||||
// and even if we are on the hard disk. It is important when user does not
|
||||
// want to process partially downloaded volumes preliminary.
|
||||
// 2022.01.11: In WinRAR 6.10 beta versions we tried to ignore VolumePause
|
||||
// if we could open the next volume with FMF_OPENEXCLUSIVE. But another
|
||||
// developer asked us to return the previous behavior and always prompt
|
||||
// for confirmation. They want to control when unrar continues, because
|
||||
// the next file might not be fully decoded yet. They write chunks of data
|
||||
// and then close the file again until the next chunk comes in.
|
||||
|
||||
if (Cmd->VolumePause && !uiAskNextVolume(NextName,ASIZE(NextName)))
|
||||
FailedOpen=true;
|
||||
#endif
|
||||
@ -127,6 +137,16 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,wchar Comma
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (Arc.Encrypted!=PrevVolEncrypted)
|
||||
{
|
||||
// There is no legitimate reason for encrypted header state to be
|
||||
// changed in the middle of volume sequence. So we abort here to prevent
|
||||
// replacing an encrypted header volume to unencrypted and adding
|
||||
// unexpected files by third party to encrypted extraction.
|
||||
uiMsg(UIERROR_BADARCHIVE,Arc.FileName);
|
||||
ErrHandler.Exit(RARX_FATAL);
|
||||
}
|
||||
|
||||
if (SplitHeader)
|
||||
Arc.SearchBlock(HeaderType);
|
||||
else
|
||||
@ -151,9 +171,8 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,wchar Comma
|
||||
DataIO->UnpVolume=hd->SplitAfter;
|
||||
DataIO->SetPackedSizeToRead(hd->PackSize);
|
||||
}
|
||||
#ifdef SFX_MODULE
|
||||
DataIO->UnpArcSize=Arc.FileLength();
|
||||
#endif
|
||||
|
||||
DataIO->AdjustTotalArcSize(&Arc);
|
||||
|
||||
// Reset the size of packed data read from current volume. It is used
|
||||
// to display the total progress and preceding volumes are already
|
||||
@ -171,14 +190,7 @@ bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,wchar Comma
|
||||
|
||||
|
||||
#ifdef RARDLL
|
||||
#if defined(RARDLL) && defined(_MSC_VER) && !defined(_WIN_64)
|
||||
// Disable the run time stack check for unrar.dll, so we can manipulate
|
||||
// with ChangeVolProc call type below. Run time check would intercept
|
||||
// a wrong ESP before we restore it.
|
||||
#pragma runtime_checks( "s", off )
|
||||
#endif
|
||||
|
||||
bool DllVolChange(RAROptions *Cmd,wchar *NextName,size_t NameSize)
|
||||
bool DllVolChange(CommandData *Cmd,wchar *NextName,size_t NameSize)
|
||||
{
|
||||
bool DllVolChanged=false,DllVolAborted=false;
|
||||
|
||||
@ -212,28 +224,7 @@ bool DllVolChange(RAROptions *Cmd,wchar *NextName,size_t NameSize)
|
||||
{
|
||||
char NextNameA[NM];
|
||||
WideToChar(NextName,NextNameA,ASIZE(NextNameA));
|
||||
// Here we preserve ESP value. It is necessary for those developers,
|
||||
// who still define ChangeVolProc callback as "C" type function,
|
||||
// even though in year 2001 we announced in unrar.dll whatsnew.txt
|
||||
// that it will be PASCAL type (for compatibility with Visual Basic).
|
||||
#if defined(_MSC_VER)
|
||||
#ifndef _WIN_64
|
||||
__asm mov ebx,esp
|
||||
#endif
|
||||
#elif defined(_WIN_ALL) && defined(__BORLANDC__)
|
||||
_EBX=_ESP;
|
||||
#endif
|
||||
int RetCode=Cmd->ChangeVolProc(NextNameA,RAR_VOL_ASK);
|
||||
|
||||
// Restore ESP after ChangeVolProc with wrongly defined calling
|
||||
// convention broken it.
|
||||
#if defined(_MSC_VER)
|
||||
#ifndef _WIN_64
|
||||
__asm mov esp,ebx
|
||||
#endif
|
||||
#elif defined(_WIN_ALL) && defined(__BORLANDC__)
|
||||
_ESP=_EBX;
|
||||
#endif
|
||||
if (RetCode==0)
|
||||
DllVolAborted=true;
|
||||
else
|
||||
@ -255,7 +246,7 @@ bool DllVolChange(RAROptions *Cmd,wchar *NextName,size_t NameSize)
|
||||
|
||||
|
||||
#ifdef RARDLL
|
||||
bool DllVolNotify(RAROptions *Cmd,wchar *NextName)
|
||||
bool DllVolNotify(CommandData *Cmd,wchar *NextName)
|
||||
{
|
||||
char NextNameA[NM];
|
||||
WideToChar(NextName,NextNameA,ASIZE(NextNameA));
|
||||
@ -268,21 +259,10 @@ bool DllVolNotify(RAROptions *Cmd,wchar *NextName)
|
||||
}
|
||||
if (Cmd->ChangeVolProc!=NULL)
|
||||
{
|
||||
#if defined(_WIN_ALL) && !defined(_MSC_VER) && !defined(__MINGW32__)
|
||||
_EBX=_ESP;
|
||||
#endif
|
||||
int RetCode=Cmd->ChangeVolProc(NextNameA,RAR_VOL_NOTIFY);
|
||||
#if defined(_WIN_ALL) && !defined(_MSC_VER) && !defined(__MINGW32__)
|
||||
_ESP=_EBX;
|
||||
#endif
|
||||
if (RetCode==0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(RARDLL) && defined(_MSC_VER) && !defined(_WIN_64)
|
||||
// Restore the run time stack check for unrar.dll.
|
||||
#pragma runtime_checks( "s", restore )
|
||||
#endif
|
||||
#endif
|
||||
|
3
deps/unrar/volume.hpp
vendored
3
deps/unrar/volume.hpp
vendored
@ -1,10 +1,7 @@
|
||||
#ifndef _RAR_VOLUME_
|
||||
#define _RAR_VOLUME_
|
||||
|
||||
void SplitArchive(Archive &Arc,FileHeader *fh,int64 *HeaderPos,
|
||||
ComprDataIO *DataIO);
|
||||
bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,
|
||||
wchar Command);
|
||||
void SetVolWrite(Archive &Dest,int64 VolSize);
|
||||
|
||||
#endif
|
||||
|
13
deps/unrar/win32stm.cpp
vendored
13
deps/unrar/win32stm.cpp
vendored
@ -111,16 +111,23 @@ void ExtractStreams(Archive &Arc,const wchar *FileName,bool TestMode)
|
||||
|
||||
wcsncatz(FullName,StreamName,ASIZE(FullName));
|
||||
|
||||
|
||||
FindData fd;
|
||||
bool Found=FindFile::FastFind(FileName,&fd);
|
||||
bool HostFound=FindFile::FastFind(FileName,&fd);
|
||||
|
||||
if ((fd.FileAttr & FILE_ATTRIBUTE_READONLY)!=0)
|
||||
SetFileAttr(FileName,fd.FileAttr & ~FILE_ATTRIBUTE_READONLY);
|
||||
File CurFile;
|
||||
if (CurFile.WCreate(FullName) && Arc.ReadSubData(NULL,&CurFile,false))
|
||||
|
||||
if (CurFile.WCreate(FullName))
|
||||
{
|
||||
if (Arc.ReadSubData(NULL,&CurFile,false))
|
||||
CurFile.Close();
|
||||
}
|
||||
|
||||
// Restoring original file timestamps.
|
||||
File HostFile;
|
||||
if (Found && HostFile.Open(FileName,FMF_OPENSHARED|FMF_UPDATE))
|
||||
if (HostFound && HostFile.Open(FileName,FMF_OPENSHARED|FMF_UPDATE))
|
||||
SetFileTime(HostFile.GetHandle(),&fd.ftCreationTime,&fd.ftLastAccessTime,
|
||||
&fd.ftLastWriteTime);
|
||||
|
||||
|
@ -90,6 +90,7 @@
|
||||
- Fixed minimum password length in module of hash-mode 29800
|
||||
- Fixed maximum password length in module/test_module of hash-mode 2400
|
||||
- Fixed buffer overflow on module_26600.c / module_hash_encode()
|
||||
- Fixed bug in 23800/unrar with Apple Silicon
|
||||
- Fixed vector datatypes usage for HIP
|
||||
|
||||
##
|
||||
@ -101,6 +102,7 @@
|
||||
- Apple Driver: Updated requirements to use Apple OpenCL API to macOS 13.0 - use
|
||||
- Backend Checks: Describe workaround in error message when detecting more than 64 backend devices
|
||||
- Brain: Added sanity check and corresponding error message for invalid --brain-port values
|
||||
- Dependencies: Updated unrar source to 6.2.7
|
||||
- Building: Support building windows binaries on macOS using MinGW
|
||||
- Dependencies: Updated OpenCL-Headers to v2023.04.17
|
||||
- Documents: Updated BUILD.md and added BUILD_macOS.md (containing instructions for building windows binaries on macOS)
|
||||
|
@ -217,6 +217,8 @@ ifneq ($(CC),clang)
|
||||
CFLAGS_UNRAR += -Wno-class-memaccess
|
||||
CFLAGS_UNRAR += -Wno-misleading-indentation
|
||||
CFLAGS_UNRAR += -Wno-format-overflow
|
||||
else
|
||||
CFLAGS_UNRAR += -std=c++11
|
||||
endif
|
||||
CFLAGS_UNRAR += -Wno-missing-braces
|
||||
CFLAGS_UNRAR += -Wno-unused-variable
|
||||
@ -761,6 +763,7 @@ LFLAGS_CROSS_WIN += -lpsapi
|
||||
LFLAGS_CROSS_WIN += -lws2_32
|
||||
LFLAGS_CROSS_WIN += -lpowrprof
|
||||
LFLAGS_CROSS_WIN += -static -static-libgcc -static-libstdc++
|
||||
LFLAGS_CROSS_WIN += -lole32 -loleaut32 -lwbemuuid
|
||||
|
||||
CFLAGS_LZMA_WIN := $(CFLAGS_LZMA)
|
||||
CFLAGS_UNRAR_WIN := $(CFLAGS_UNRAR)
|
||||
|
Loading…
Reference in New Issue
Block a user