diff options
author | Underground78 <underground78@users.sourceforge.net> | 2015-01-25 15:47:48 +0300 |
---|---|---|
committer | Underground78 <underground78@users.sourceforge.net> | 2015-01-25 15:47:48 +0300 |
commit | 6fcba1bead7608fb480ab943ab9689bc66f4e009 (patch) | |
tree | ef5a968e7749e8f80f310fd44a43fc5b1d394193 /src/thirdparty/unrar | |
parent | 46ce9d630e7891230c9648afb0c17088681573e6 (diff) | |
parent | 013ebae50427b2e985939439202e206373ed5aee (diff) |
Merge branch 'release-1.7.8'1.7.8
Diffstat (limited to 'src/thirdparty/unrar')
32 files changed, 359 insertions, 201 deletions
diff --git a/src/thirdparty/unrar/arcread.cpp b/src/thirdparty/unrar/arcread.cpp index 5b70988ea..e4c3f87d5 100644 --- a/src/thirdparty/unrar/arcread.cpp +++ b/src/thirdparty/unrar/arcread.cpp @@ -811,7 +811,7 @@ size_t Archive::ReadHeader50() Raw.GetB((byte *)FileName,ReadNameSize); FileName[ReadNameSize]=0; - UtfToWide(FileName,hd->FileName,ASIZE(hd->FileName)-1); + UtfToWide(FileName,hd->FileName,ASIZE(hd->FileName)); // Should do it before converting names, because extra fields can // affect name processing, like in case of NTFS streams. @@ -893,6 +893,7 @@ void Archive::RequestArcPassword() ErrHandler.Exit(RARX_USERBREAK); } #endif + Cmd->ManualPassword=true; } } #endif diff --git a/src/thirdparty/unrar/cmddata.cpp b/src/thirdparty/unrar/cmddata.cpp index f2374f146..b56410ae9 100644 --- a/src/thirdparty/unrar/cmddata.cpp +++ b/src/thirdparty/unrar/cmddata.cpp @@ -13,7 +13,6 @@ void CommandData::Init() *Command=0; *ArcName=0; FileLists=false; - NoMoreSwitches=false; ListMode=RCLM_AUTO; @@ -47,6 +46,8 @@ static const wchar *AllocCmdParam(const wchar *CmdLine,wchar **Par) #if !defined(SFX_MODULE) && !defined(_ANDROID) void CommandData::ParseCommandLine(bool Preprocess,int argc, char *argv[]) { + *Command=0; + NoMoreSwitches=false; #ifdef CUSTOM_CMDLINE_PARSER // In Windows we may prefer to implement our own command line parser // to avoid replacing \" by " in standard parser. Such replacing corrupts @@ -58,15 +59,12 @@ void CommandData::ParseCommandLine(bool Preprocess,int argc, char *argv[]) { if ((CmdLine=AllocCmdParam(CmdLine,&Par))==NULL) break; - bool Code=true; if (!FirstParam) // First parameter is the executable name. if (Preprocess) - Code=PreprocessSwitch(Par); + PreprocessArg(Par); else ParseArg(Par); free(Par); - if (Preprocess && !Code) - break; } #else Array<wchar> Arg; @@ -75,10 +73,7 @@ void CommandData::ParseCommandLine(bool Preprocess,int argc, char *argv[]) Arg.Alloc(strlen(argv[I])+1); CharToWide(argv[I],&Arg[0],Arg.Size()); if (Preprocess) - { - if (!PreprocessSwitch(&Arg[0])) - break; - } + PreprocessArg(&Arg[0]); else ParseArg(&Arg[0]); } @@ -93,7 +88,7 @@ void CommandData::ParseCommandLine(bool Preprocess,int argc, char *argv[]) void CommandData::ParseArg(wchar *Arg) { if (IsSwitch(*Arg) && !NoMoreSwitches) - if (Arg[1]=='-') + if (Arg[1]=='-' && Arg[2]==0) NoMoreSwitches=true; else ProcessSwitch(Arg+1); @@ -199,37 +194,37 @@ void CommandData::ParseEnvVar() #if !defined(SFX_MODULE) && !defined(_ANDROID) // Preprocess those parameters, which must be processed before the rest of // command line. Return 'false' to stop further processing. -bool CommandData::PreprocessSwitch(const wchar *Switch) +void CommandData::PreprocessArg(const wchar *Arg) { - if (IsSwitch(Switch[0])) + if (IsSwitch(Arg[0]) && !NoMoreSwitches) { - Switch++; - char SwitchA[1024]; - WideToChar(Switch,SwitchA,ASIZE(SwitchA)); - if (wcsicomp(Switch,L"-")==0) // Switch "--". - return false; - if (wcsicomp(Switch,L"cfg-")==0) + Arg++; + if (Arg[0]=='-' && Arg[1]==0) // Switch "--". + NoMoreSwitches=true; + if (wcsicomp(Arg,L"cfg-")==0) ConfigDisabled=true; #ifndef GUI - if (wcsnicomp(Switch,L"ilog",4)==0) + if (wcsnicomp(Arg,L"ilog",4)==0) { // Ensure that correct log file name is already set // if we need to report an error when processing the command line. - ProcessSwitch(Switch); + ProcessSwitch(Arg); InitLogOptions(LogName,ErrlogCharset); } #endif - if (wcsnicomp(Switch,L"sc",2)==0) + if (wcsnicomp(Arg,L"sc",2)==0) { // Process -sc before reading any file lists. - ProcessSwitch(Switch); + ProcessSwitch(Arg); #ifndef GUI if (*LogName!=0) InitLogOptions(LogName,ErrlogCharset); #endif } } - return true; + else + if (*Command==0) + wcsncpy(Command,Arg,ASIZE(Command)); // Need for rar.ini. } #endif @@ -247,6 +242,22 @@ void CommandData::ReadConfig() Str++; if (wcsnicomp(Str,L"switches=",9)==0) ProcessSwitchesString(Str+9); + if (*Command!=0) + { + wchar Cmd[16]; + wcsncpyz(Cmd,Command,ASIZE(Cmd)); + wchar C0=toupperw(Cmd[0]); + wchar C1=toupperw(Cmd[1]); + if (C0=='I' || C0=='L' || C0=='M' || C0=='S' || C0=='V') + Cmd[1]=0; + if (C0=='R' && (C1=='R' || C1=='V')) + Cmd[2]=0; + wchar SwName[16+ASIZE(Cmd)]; + swprintf(SwName,ASIZE(SwName),L"switches_%s=",Cmd); + size_t Length=wcslen(SwName); + if (wcsnicomp(Str,SwName,Length)==0) + ProcessSwitchesString(Str+Length); + } } } } @@ -1010,7 +1021,7 @@ bool CommandData::ExclCheck(const wchar *CheckName,bool Dir,bool CheckFullPath,b return true; if (!CheckInclList || InclArgs.ItemsCount()==0) return false; - if (ExclCheckArgs(&InclArgs,Dir,CheckName,false,MATCH_WILDSUBPATH)) + if (ExclCheckArgs(&InclArgs,Dir,CheckName,CheckFullPath,MATCH_WILDSUBPATH)) return false; return true; } diff --git a/src/thirdparty/unrar/cmddata.hpp b/src/thirdparty/unrar/cmddata.hpp index b2f3b1ae1..3ed4ef1d8 100644 --- a/src/thirdparty/unrar/cmddata.hpp +++ b/src/thirdparty/unrar/cmddata.hpp @@ -28,7 +28,7 @@ class CommandData:public RAROptions void ParseDone(); void ParseEnvVar(); void ReadConfig(); - bool PreprocessSwitch(const wchar *Switch); + void PreprocessArg(const wchar *Arg); void OutTitle(); void OutHelp(RAR_EXIT ExitCode); bool IsSwitch(int Ch); diff --git a/src/thirdparty/unrar/crypt.cpp b/src/thirdparty/unrar/crypt.cpp index ef2e68a11..1a9764008 100644 --- a/src/thirdparty/unrar/crypt.cpp +++ b/src/thirdparty/unrar/crypt.cpp @@ -11,15 +11,18 @@ CryptData::CryptData() { Method=CRYPT_NONE; - memset(KDFCache,0,sizeof(KDFCache)); - KDFCachePos=0; + memset(KDF3Cache,0,sizeof(KDF3Cache)); + memset(KDF5Cache,0,sizeof(KDF5Cache)); + KDF3CachePos=0; + KDF5CachePos=0; memset(CRCTab,0,sizeof(CRCTab)); } CryptData::~CryptData() { - cleandata(KDFCache,sizeof(KDFCache)); + cleandata(KDF3Cache,sizeof(KDF3Cache)); + cleandata(KDF5Cache,sizeof(KDF5Cache)); } diff --git a/src/thirdparty/unrar/crypt.hpp b/src/thirdparty/unrar/crypt.hpp index 1dc244600..f6382ef50 100644 --- a/src/thirdparty/unrar/crypt.hpp +++ b/src/thirdparty/unrar/crypt.hpp @@ -20,18 +20,28 @@ enum CRYPT_METHOD { #define CRYPT_VERSION 0 // Supported encryption version. -struct KDFCacheItem -{ - SecPassword Pwd; - byte Salt[SIZE_SALT50]; - uint Lg2Count; // Log2 of PBKDF2 repetition count. - byte Key[32]; - byte PswCheckValue[SHA256_DIGEST_SIZE]; - byte HashKeyValue[SHA256_DIGEST_SIZE]; -}; - class CryptData { + struct KDF5CacheItem + { + SecPassword Pwd; + byte Salt[SIZE_SALT50]; + byte Key[32]; + uint Lg2Count; // Log2 of PBKDF2 repetition count. + byte PswCheckValue[SHA256_DIGEST_SIZE]; + byte HashKeyValue[SHA256_DIGEST_SIZE]; + }; + + struct KDF3CacheItem + { + SecPassword Pwd; + byte Salt[SIZE_SALT30]; + byte Key[16]; + byte Init[16]; + bool SaltPresent; + }; + + private: void SetKey13(const char *Password); void Decrypt13(byte *Data,size_t Count); @@ -46,10 +56,13 @@ class CryptData void DecryptBlock20(byte *Buf); void SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt); - void SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt,const byte *InitV,uint Lg2Cnt,byte *HashKey,byte *PswCheck); - KDFCacheItem KDFCache[4]; - uint KDFCachePos; + + KDF3CacheItem KDF3Cache[4]; + uint KDF3CachePos; + + KDF5CacheItem KDF5Cache[4]; + uint KDF5CachePos; CRYPT_METHOD Method; diff --git a/src/thirdparty/unrar/crypt3.cpp b/src/thirdparty/unrar/crypt3.cpp index ffaced56d..bcc7cfa6d 100644 --- a/src/thirdparty/unrar/crypt3.cpp +++ b/src/thirdparty/unrar/crypt3.cpp @@ -1,38 +1,15 @@ -struct CryptKeyCacheItem -{ - CryptKeyCacheItem() - { - Password.Set(L""); - } - - ~CryptKeyCacheItem() - { - cleandata(AESKey,sizeof(AESKey)); - cleandata(AESInit,sizeof(AESInit)); - cleandata(&Password,sizeof(Password)); - } - - byte AESKey[16],AESInit[16]; - SecPassword Password; - bool SaltPresent; - byte Salt[SIZE_SALT30]; -}; - -static CryptKeyCacheItem Cache[4]; -static int CachePos=0; - void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,const byte *Salt) { byte AESKey[16],AESInit[16]; bool Cached=false; - for (uint I=0;I<ASIZE(Cache);I++) - if (Cache[I].Password==*Password && - (Salt==NULL && !Cache[I].SaltPresent || Salt!=NULL && - Cache[I].SaltPresent && memcmp(Cache[I].Salt,Salt,SIZE_SALT30)==0)) + for (uint I=0;I<ASIZE(KDF3Cache);I++) + if (KDF3Cache[I].Pwd==*Password && + (Salt==NULL && !KDF3Cache[I].SaltPresent || Salt!=NULL && + KDF3Cache[I].SaltPresent && memcmp(KDF3Cache[I].Salt,Salt,SIZE_SALT30)==0)) { - memcpy(AESKey,Cache[I].AESKey,sizeof(AESKey)); - memcpy(AESInit,Cache[I].AESInit,sizeof(AESInit)); + memcpy(AESKey,KDF3Cache[I].Key,sizeof(AESKey)); + memcpy(AESInit,KDF3Cache[I].Init,sizeof(AESInit)); Cached=true; break; } @@ -73,12 +50,12 @@ void CryptData::SetKey30(bool Encrypt,SecPassword *Password,const wchar *PwdW,co for (int J=0;J<4;J++) AESKey[I*4+J]=(byte)(digest[I]>>(J*8)); - Cache[CachePos].Password=*Password; - if ((Cache[CachePos].SaltPresent=(Salt!=NULL))==true) - memcpy(Cache[CachePos].Salt,Salt,SIZE_SALT30); - memcpy(Cache[CachePos].AESKey,AESKey,sizeof(AESKey)); - memcpy(Cache[CachePos].AESInit,AESInit,sizeof(AESInit)); - CachePos=(CachePos+1)%ASIZE(Cache); + KDF3Cache[KDF3CachePos].Pwd=*Password; + if ((KDF3Cache[KDF3CachePos].SaltPresent=(Salt!=NULL))==true) + memcpy(KDF3Cache[KDF3CachePos].Salt,Salt,SIZE_SALT30); + memcpy(KDF3Cache[KDF3CachePos].Key,AESKey,sizeof(AESKey)); + memcpy(KDF3Cache[KDF3CachePos].Init,AESInit,sizeof(AESInit)); + KDF3CachePos=(KDF3CachePos+1)%ASIZE(KDF3Cache); cleandata(RawPsw,sizeof(RawPsw)); } diff --git a/src/thirdparty/unrar/crypt5.cpp b/src/thirdparty/unrar/crypt5.cpp index fab3cc975..abc5d34a7 100644 --- a/src/thirdparty/unrar/crypt5.cpp +++ b/src/thirdparty/unrar/crypt5.cpp @@ -98,15 +98,15 @@ void CryptData::SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW, byte Key[32],PswCheckValue[SHA256_DIGEST_SIZE],HashKeyValue[SHA256_DIGEST_SIZE]; bool Found=false; - for (uint I=0;I<ASIZE(KDFCache);I++) + for (uint I=0;I<ASIZE(KDF5Cache);I++) { - KDFCacheItem *Item=KDFCache+I; + KDF5CacheItem *Item=KDF5Cache+I; if (Item->Lg2Count==Lg2Cnt && Item->Pwd==*Password && memcmp(Item->Salt,Salt,SIZE_SALT50)==0) { - SecHideData(Item->Key,sizeof(Item->Key),false); + SecHideData(Item->Key,sizeof(Item->Key),false,false); memcpy(Key,Item->Key,sizeof(Key)); - SecHideData(Item->Key,sizeof(Item->Key),true); + SecHideData(Item->Key,sizeof(Item->Key),true,false); memcpy(PswCheckValue,Item->PswCheckValue,sizeof(PswCheckValue)); memcpy(HashKeyValue,Item->HashKeyValue,sizeof(HashKeyValue)); @@ -123,14 +123,14 @@ void CryptData::SetKey50(bool Encrypt,SecPassword *Password,const wchar *PwdW, pbkdf2((byte *)PwdUtf,strlen(PwdUtf),Salt,SIZE_SALT50,Key,HashKeyValue,PswCheckValue,(1<<Lg2Cnt)); cleandata(PwdUtf,sizeof(PwdUtf)); - KDFCacheItem *Item=KDFCache+(KDFCachePos++ % ASIZE(KDFCache)); + KDF5CacheItem *Item=KDF5Cache+(KDF5CachePos++ % ASIZE(KDF5Cache)); Item->Lg2Count=Lg2Cnt; Item->Pwd=*Password; memcpy(Item->Salt,Salt,SIZE_SALT50); memcpy(Item->Key,Key,sizeof(Key)); memcpy(Item->PswCheckValue,PswCheckValue,sizeof(PswCheckValue)); memcpy(Item->HashKeyValue,HashKeyValue,sizeof(HashKeyValue)); - SecHideData(Item->Key,sizeof(Key),true); + SecHideData(Item->Key,sizeof(Key),true,false); } if (HashKey!=NULL) memcpy(HashKey,HashKeyValue,SHA256_DIGEST_SIZE); diff --git a/src/thirdparty/unrar/dll.rc b/src/thirdparty/unrar/dll.rc index aedb0fc5e..1481d7632 100644 --- a/src/thirdparty/unrar/dll.rc +++ b/src/thirdparty/unrar/dll.rc @@ -2,8 +2,8 @@ #include <commctrl.h>
VS_VERSION_INFO VERSIONINFO
-FILEVERSION 5, 11, 1, 1315
-PRODUCTVERSION 5, 11, 1, 1315
+FILEVERSION 5, 20, 100, 1433
+PRODUCTVERSION 5, 20, 100, 1433
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
{
@@ -14,8 +14,8 @@ FILETYPE VFT_APP VALUE "CompanyName", "Alexander Roshal\0"
VALUE "ProductName", "RAR decompression library\0"
VALUE "FileDescription", "RAR decompression library\0"
- VALUE "FileVersion", "5.11.1\0"
- VALUE "ProductVersion", "5.11.1\0"
+ VALUE "FileVersion", "5.20.0\0"
+ VALUE "ProductVersion", "5.20.0\0"
VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2014\0"
VALUE "OriginalFilename", "Unrar.dll\0"
}
diff --git a/src/thirdparty/unrar/extract.cpp b/src/thirdparty/unrar/extract.cpp index 770cae4d7..cab669fe9 100644 --- a/src/thirdparty/unrar/extract.cpp +++ b/src/thirdparty/unrar/extract.cpp @@ -9,7 +9,6 @@ CmdExtract::CmdExtract(CommandData *Cmd) *DestFileName=0;
TotalFileCount=0;
- Password.Set(L"");
Unp=new Unpack(&DataIO);
#ifdef RAR_SMP
Unp->SetThreads(Cmd->Threads);
@@ -25,6 +24,9 @@ CmdExtract::~CmdExtract() void CmdExtract::DoExtract()
{
+#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
+ Fat32=NotFat32=false;
+#endif
PasswordCancelled=false;
DataIO.SetCurrentCommand(Cmd->Command[0]);
@@ -36,17 +38,11 @@ void CmdExtract::DoExtract() Cmd->ArcNames.Rewind();
while (Cmd->GetArcName(ArcName,ASIZE(ArcName)))
{
+ if (Cmd->ManualPassword)
+ Cmd->Password.Clean(); // Clean user entered password before processing next archive.
while (true)
{
- SecPassword PrevCmdPassword;
- PrevCmdPassword=Cmd->Password;
-
EXTRACT_ARC_CODE Code=ExtractArchive();
-
- // Restore Cmd->Password, which could be changed in IsArchive() call
- // for next header encrypted archive.
- Cmd->Password=PrevCmdPassword;
-
if (Code!=EXTRACT_ARC_REPEAT)
break;
}
@@ -54,6 +50,10 @@ void CmdExtract::DoExtract() DataIO.ProcessedArcSize+=FD.Size;
}
+ // Clean user entered password. Not really required, just for extra safety.
+ if (Cmd->ManualPassword)
+ Cmd->Password.Clean();
+
if (TotalFileCount==0 && Cmd->Command[0]!='I' &&
ErrHandler.GetErrorCode()!=RARX_BADPWD) // Not in case of wrong archive password.
{
@@ -86,8 +86,6 @@ void CmdExtract::ExtractArchiveInit(Archive &Arc) #endif
PasswordAll=(Cmd->Password.IsSet());
- if (PasswordAll)
- Password=Cmd->Password;
DataIO.UnpVolume=false;
@@ -262,15 +260,11 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) int MatchNumber=Cmd->IsProcessFile(Arc.FileHead,&EqualNames,MatchType);
bool ExactMatch=MatchNumber!=0;
#ifndef SFX_MODULE
- if (Cmd->ExclPath==EXCL_BASEPATH)
+ if (*Cmd->ArcPath==0 && Cmd->ExclPath==EXCL_BASEPATH && ExactMatch)
{
- *Cmd->ArcPath=0;
- if (ExactMatch)
- {
- Cmd->FileArgs.Rewind();
- if (Cmd->FileArgs.GetString(Cmd->ArcPath,ASIZE(Cmd->ArcPath),MatchNumber-1))
- *PointToName(Cmd->ArcPath)=0;
- }
+ Cmd->FileArgs.Rewind();
+ if (Cmd->FileArgs.GetString(Cmd->ArcPath,ASIZE(Cmd->ArcPath),MatchNumber-1))
+ *PointToName(Cmd->ArcPath)=0;
}
#endif
if (ExactMatch && !EqualNames)
@@ -400,7 +394,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) }
#endif
// Skip only the current encrypted file if empty password is entered.
- if (!Password.IsSet())
+ if (!Cmd->Password.IsSet())
{
ErrHandler.SetErrorCode(RARX_WARNING);
#ifdef RARDLL
@@ -430,7 +424,6 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) #endif
}
-
File CurFile;
bool LinkEntry=Arc.FileHead.RedirType!=FSREDIR_NONE;
@@ -510,7 +503,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) mprintf(L" ");
#endif
- SecPassword FilePassword=Password;
+ SecPassword FilePassword=Cmd->Password;
#if defined(_WIN_ALL) && !defined(SFX_MODULE)
ConvertDosPassword(Arc,FilePassword);
#endif
@@ -540,6 +533,18 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) DataIO.SetFiles(&Arc,&CurFile);
DataIO.SetTestMode(TestMode);
DataIO.SetSkipUnpCRC(SkipSolid);
+
+#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
+ if (!TestMode && !WrongPassword && !Arc.BrokenHeader &&
+ Arc.FileHead.UnpSize>0xffffffff && (Fat32 || !NotFat32))
+ {
+ if (!Fat32) // Not detected yet.
+ NotFat32=!(Fat32=IsFAT(Cmd->ExtrPath));
+ if (Fat32)
+ uiMsg(UIMSG_FAT32SIZE); // Inform user about FAT32 size limit.
+ }
+#endif
+
if (!TestMode && !WrongPassword && !Arc.BrokenHeader &&
(Arc.FileHead.PackSize<<11)>Arc.FileHead.UnpSize &&
(Arc.FileHead.UnpSize<100000000 || Arc.FileLength()>Arc.FileHead.PackSize))
@@ -862,11 +867,11 @@ bool CmdExtract::ExtrDllGetPassword() }
Cmd->Password.Set(PasswordW);
cleandata(PasswordW,sizeof(PasswordW));
+ Cmd->ManualPassword=true;
}
if (!Cmd->Password.IsSet())
return false;
}
- Password=Cmd->Password;
return true;
}
#endif
@@ -875,14 +880,15 @@ bool CmdExtract::ExtrDllGetPassword() #ifndef RARDLL
bool CmdExtract::ExtrGetPassword(Archive &Arc,const wchar *ArcFileName)
{
- if (!Password.IsSet())
+ if (!Cmd->Password.IsSet())
{
- if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Password))
+ if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password))
{
uiMsg(UIERROR_INCERRCOUNT);
return false;
}
+ Cmd->ManualPassword=true;
}
#if !defined(GUI) && !defined(SILENT)
else
@@ -894,7 +900,7 @@ bool CmdExtract::ExtrGetPassword(Archive &Arc,const wchar *ArcFileName) case -1:
ErrHandler.Exit(RARX_USERBREAK);
case 2:
- if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Password))
+ if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password))
return false;
break;
case 3:
@@ -916,7 +922,7 @@ void CmdExtract::ConvertDosPassword(Archive &Arc,SecPassword &DestPwd) // We need the password in OEM encoding if file was encrypted by
// native RAR/DOS (not extender based). Let's make the conversion.
wchar PlainPsw[MAXPASSWORD];
- Password.Get(PlainPsw,ASIZE(PlainPsw));
+ Cmd->Password.Get(PlainPsw,ASIZE(PlainPsw));
char PswA[MAXPASSWORD];
CharToOemBuffW(PlainPsw,PswA,ASIZE(PswA));
PswA[ASIZE(PswA)-1]=0;
@@ -957,6 +963,18 @@ void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName) {
CreatePath(DestFileName,true);
MDCode=MakeDir(DestFileName,!Cmd->IgnoreGeneralAttr,Arc.FileHead.FileAttr);
+ if (MDCode!=MKDIR_SUCCESS)
+ {
+ wchar OrigName[ASIZE(DestFileName)];
+ wcsncpyz(OrigName,DestFileName,ASIZE(OrigName));
+ MakeNameUsable(DestFileName,true);
+ CreatePath(DestFileName,true);
+ MDCode=MakeDir(DestFileName,!Cmd->IgnoreGeneralAttr,Arc.FileHead.FileAttr);
+#ifndef SFX_MODULE
+ if (MDCode==MKDIR_SUCCESS)
+ uiMsg(UIERROR_RENAMING,Arc.FileName,OrigName,DestFileName);
+#endif
+ }
}
}
if (MDCode==MKDIR_SUCCESS)
diff --git a/src/thirdparty/unrar/extract.hpp b/src/thirdparty/unrar/extract.hpp index 1539ed61a..4ea317b61 100644 --- a/src/thirdparty/unrar/extract.hpp +++ b/src/thirdparty/unrar/extract.hpp @@ -43,11 +43,13 @@ class CmdExtract wchar ArcName[NM]; - SecPassword Password; bool PasswordAll; bool PrevExtracted; wchar DestFileName[NM]; bool PasswordCancelled; +#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT) + bool Fat32,NotFat32; +#endif public: CmdExtract(CommandData *Cmd); ~CmdExtract(); diff --git a/src/thirdparty/unrar/file.cpp b/src/thirdparty/unrar/file.cpp index 51100acd6..8fba34adb 100644 --- a/src/thirdparty/unrar/file.cpp +++ b/src/thirdparty/unrar/file.cpp @@ -2,7 +2,7 @@ File::File() { - hFile=BAD_HANDLE; + hFile=FILE_BAD_HANDLE; *FileName=0; NewFile=false; LastWrite=false; @@ -22,7 +22,7 @@ File::File() File::~File() { - if (hFile!=BAD_HANDLE && !SkipClose) + if (hFile!=FILE_BAD_HANDLE && !SkipClose) if (NewFile) Delete(); else @@ -52,14 +52,14 @@ bool File::Open(const wchar *Name,uint Mode) uint Access=WriteMode ? GENERIC_WRITE:GENERIC_READ; if (UpdateMode) Access|=GENERIC_WRITE; - uint ShareMode=FILE_SHARE_READ; + uint ShareMode=(Mode & FMF_OPENEXCLUSIVE) ? 0 : FILE_SHARE_READ; if (OpenShared) ShareMode|=FILE_SHARE_WRITE; uint Flags=NoSequentialRead ? 0:FILE_FLAG_SEQUENTIAL_SCAN; hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL); DWORD LastError; - if (hNewFile==BAD_HANDLE) + if (hNewFile==FILE_BAD_HANDLE) { LastError=GetLastError(); @@ -85,7 +85,7 @@ bool File::Open(const wchar *Name,uint Mode) } } - if (hNewFile==BAD_HANDLE && LastError==ERROR_FILE_NOT_FOUND) + if (hNewFile==FILE_BAD_HANDLE && LastError==ERROR_FILE_NOT_FOUND) ErrorType=FILE_NOTFOUND; #else int flags=UpdateMode ? O_RDWR:(WriteMode ? O_WRONLY:O_RDONLY); @@ -112,7 +112,7 @@ bool File::Open(const wchar *Name,uint Mode) } #endif if (handle==-1) - hNewFile=BAD_HANDLE; + hNewFile=FILE_BAD_HANDLE; else { #ifdef FILE_USE_OPEN @@ -121,13 +121,13 @@ bool File::Open(const wchar *Name,uint Mode) hNewFile=fdopen(handle,UpdateMode ? UPDATEBINARY:READBINARY); #endif } - if (hNewFile==BAD_HANDLE && errno==ENOENT) + if (hNewFile==FILE_BAD_HANDLE && errno==ENOENT) ErrorType=FILE_NOTFOUND; #endif NewFile=false; HandleType=FILE_HANDLENORMAL; SkipClose=false; - bool Success=hNewFile!=BAD_HANDLE; + bool Success=hNewFile!=FILE_BAD_HANDLE; if (Success) { hFile=hNewFile; @@ -167,9 +167,18 @@ bool File::Create(const wchar *Name,uint Mode) CreateMode=Mode; uint Access=WriteMode ? GENERIC_WRITE:GENERIC_READ|GENERIC_WRITE; DWORD ShareMode=ShareRead ? FILE_SHARE_READ:0; - hFile=CreateFile(Name,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL); - if (hFile==BAD_HANDLE) + // Windows automatically removes dots and spaces in the end of file name, + // So we detect such names and process them with \\?\ prefix. + wchar *LastChar=PointToLastChar(Name); + bool Special=*LastChar=='.' || *LastChar==' '; + + if (Special) + hFile=FILE_BAD_HANDLE; + else + hFile=CreateFile(Name,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL); + + if (hFile==FILE_BAD_HANDLE) { wchar LongName[NM]; if (GetWinLongPath(Name,LongName,ASIZE(LongName))) @@ -181,6 +190,10 @@ bool File::Create(const wchar *Name,uint Mode) WideToChar(Name,NameA,ASIZE(NameA)); #ifdef FILE_USE_OPEN hFile=open(NameA,(O_CREAT|O_TRUNC) | (WriteMode ? O_WRONLY : O_RDWR)); +#ifdef _ANDROID + if (hFile==FILE_BAD_HANDLE) + hFile=JniCreateFile(Name); // If external card is read-only for usual file API. +#endif #else hFile=fopen(NameA,WriteMode ? WRITEBINARY:CREATEBINARY); #endif @@ -189,7 +202,7 @@ bool File::Create(const wchar *Name,uint Mode) HandleType=FILE_HANDLENORMAL; SkipClose=false; wcsncpyz(FileName,Name,ASIZE(FileName)); - return hFile!=BAD_HANDLE; + return hFile!=FILE_BAD_HANDLE; } @@ -215,7 +228,7 @@ bool File::Close() { bool Success=true; - if (hFile!=BAD_HANDLE) + if (hFile!=FILE_BAD_HANDLE) { if (!SkipClose) { @@ -232,7 +245,7 @@ bool File::Close() #endif #endif } - hFile=BAD_HANDLE; + hFile=FILE_BAD_HANDLE; } HandleType=FILE_HANDLENORMAL; if (!Success && AllowExceptions) @@ -245,7 +258,7 @@ bool File::Delete() { if (HandleType!=FILE_HANDLENORMAL) return false; - if (hFile!=BAD_HANDLE) + if (hFile!=FILE_BAD_HANDLE) Close(); if (!AllowDelete) return false; @@ -278,7 +291,7 @@ void File::Write(const void *Data,size_t Size) hFile=GetStdHandle(STD_OUTPUT_HANDLE); #else // Cannot use the standard stdout here, because it already has wide orientation. - if (hFile==BAD_HANDLE) + if (hFile==FILE_BAD_HANDLE) { #ifdef FILE_USE_OPEN hFile=dup(STDOUT_FILENO); // Open new stdout stream. @@ -390,8 +403,8 @@ int File::DirectRead(void *Data,size_t Size) if (HandleType==FILE_HANDLESTD) { #ifdef _WIN_ALL - if (Size>MaxDeviceRead) - Size=MaxDeviceRead; +// if (Size>MaxDeviceRead) +// Size=MaxDeviceRead; hFile=GetStdHandle(STD_INPUT_HANDLE); #else #ifdef FILE_USE_OPEN @@ -402,6 +415,8 @@ int File::DirectRead(void *Data,size_t Size) #endif } #ifdef _WIN_ALL + // For pipes like 'type file.txt | rar -si arcname' ReadFile may return + // data in small ~4KB blocks. It may slightly reduce the compression ratio. DWORD Read; if (!ReadFile(hFile,Data,(DWORD)Size,&Read,NULL)) { @@ -454,7 +469,7 @@ void File::Seek(int64 Offset,int Method) bool File::RawSeek(int64 Offset,int Method) { - if (hFile==BAD_HANDLE) + if (hFile==FILE_BAD_HANDLE) return true; if (Offset<0 && Method!=SEEK_SET) { @@ -485,7 +500,7 @@ bool File::RawSeek(int64 Offset,int Method) int64 File::Tell() { - if (hFile==BAD_HANDLE) + if (hFile==FILE_BAD_HANDLE) if (AllowExceptions) ErrHandler.SeekError(FileName); else @@ -636,7 +651,7 @@ int64 File::FileLength() bool File::IsDevice() { - if (hFile==BAD_HANDLE) + if (hFile==FILE_BAD_HANDLE) return false; #ifdef _WIN_ALL uint Type=GetFileType(hFile); @@ -650,7 +665,7 @@ bool File::IsDevice() #ifndef SFX_MODULE int64 File::Copy(File &Dest,int64 Length) { - Array<char> Buffer(0x10000); + Array<char> Buffer(0x40000); int64 CopySize=0; bool CopyAll=(Length==INT64NDF); @@ -667,7 +682,7 @@ int64 File::Copy(File &Dest,int64 Length) // For FAT32 USB flash drives in Windows if first write is 4 KB or more, // write caching is disabled and "write through" is enabled, resulting // in bad performance, especially for many small files. It happens when - // we create SFX archive on USB drive, because SFX module is writetn first. + // we create SFX archive on USB drive, because SFX module is written first. // So we split the first write to small 1 KB followed by rest of data. if (CopySize==0 && WriteSize>=4096) { diff --git a/src/thirdparty/unrar/file.hpp b/src/thirdparty/unrar/file.hpp index 7829aaeb0..93aac89f3 100644 --- a/src/thirdparty/unrar/file.hpp +++ b/src/thirdparty/unrar/file.hpp @@ -7,13 +7,13 @@ #ifdef _WIN_ALL typedef HANDLE FileHandle; - #define BAD_HANDLE INVALID_HANDLE_VALUE + #define FILE_BAD_HANDLE INVALID_HANDLE_VALUE #elif defined(FILE_USE_OPEN) typedef off_t FileHandle; - #define BAD_HANDLE -1 + #define FILE_BAD_HANDLE -1 #else typedef FILE* FileHandle; - #define BAD_HANDLE NULL + #define FILE_BAD_HANDLE NULL #endif class RAROptions; @@ -35,8 +35,11 @@ enum FILE_MODE_FLAGS { // Open files which are already opened for write by other programs. FMF_OPENSHARED=4, + // Open files only if no other program is opened it even in shared mode. + FMF_OPENEXCLUSIVE=8, + // Provide read access to created file for other programs. - FMF_SHAREREAD=8, + FMF_SHAREREAD=16, // Mode flags are not defined yet. FMF_UNDEFINED=256 @@ -91,7 +94,7 @@ class File void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL); static void SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta); void GetOpenFileTime(RarTime *ft); - bool IsOpened() {return hFile!=BAD_HANDLE;}; + bool IsOpened() {return hFile!=FILE_BAD_HANDLE;}; int64 FileLength(); void SetHandleType(FILE_HANDLETYPE Type) {HandleType=Type;} FILE_HANDLETYPE GetHandleType() {return HandleType;} diff --git a/src/thirdparty/unrar/filefn.cpp b/src/thirdparty/unrar/filefn.cpp index 679060578..6526f4337 100644 --- a/src/thirdparty/unrar/filefn.cpp +++ b/src/thirdparty/unrar/filefn.cpp @@ -3,7 +3,11 @@ MKDIR_CODE MakeDir(const wchar *Name,bool SetAttr,uint Attr) { #ifdef _WIN_ALL - BOOL RetCode=CreateDirectory(Name,NULL); + // Windows automatically removes dots and spaces in the end of directory + // name. So we detect such names and process them with \\?\ prefix. + wchar *LastChar=PointToLastChar(Name); + bool Special=*LastChar=='.' || *LastChar==' '; + BOOL RetCode=Special ? FALSE : CreateDirectory(Name,NULL); if (RetCode==0 && !FileExist(Name)) { wchar LongName[NM]; @@ -25,6 +29,10 @@ MKDIR_CODE MakeDir(const wchar *Name,bool SetAttr,uint Attr) WideToChar(Name,NameA,ASIZE(NameA)); mode_t uattr=SetAttr ? (mode_t)Attr:0777; int ErrCode=mkdir(NameA,uattr); +#ifdef _ANDROID + if (ErrCode==-1 && errno!=ENOENT) + ErrCode=JniMkdir(Name) ? 0 : -1; // If external card is read-only for usual file API. +#endif if (ErrCode==-1) return errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR; return MKDIR_SUCCESS; @@ -54,8 +62,9 @@ bool CreatePath(const wchar *Path,bool SkipLastName) break; // Process all kinds of path separators, so user can enter Unix style - // path in Windows or Windows in Unix. - if (IsPathDiv(*s)) + // path in Windows or Windows in Unix. s>Path check avoids attempting + // creating an empty directory for paths starting from path separator. + if (IsPathDiv(*s) && s>Path) { #ifdef _WIN_ALL // We must not attempt to create "D:" directory, because first @@ -169,6 +178,19 @@ int64 GetFreeDisk(const wchar *Name) #endif +#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT) +// Return 'true' for FAT and FAT32, so we can adjust the maximum supported +// file size to 4 GB for these file systems. +bool IsFAT(const wchar *Name) +{ + wchar Root[NM]; + GetPathRoot(Name,Root,ASIZE(Root)); + wchar FileSystem[MAX_PATH+1]; + if (GetVolumeInformation(Root,NULL,0,NULL,NULL,NULL,FileSystem,ASIZE(FileSystem))) + return wcscmp(FileSystem,L"FAT")==0 || wcscmp(FileSystem,L"FAT32")==0; + return false; +} +#endif bool FileExist(const wchar *Name) @@ -394,7 +416,12 @@ bool RenameFile(const wchar *SrcName,const wchar *DestName) char SrcNameA[NM],DestNameA[NM]; WideToChar(SrcName,SrcNameA,ASIZE(SrcNameA)); WideToChar(DestName,DestNameA,ASIZE(DestNameA)); - return rename(SrcNameA,DestNameA)==0; + bool Success=rename(SrcNameA,DestNameA)==0; +#ifdef _ANDROID + if (!Success) + Success=JniRename(SrcName,DestName); // If external card is read-only for usual file API. +#endif + return Success; #endif } @@ -413,7 +440,12 @@ bool DelFile(const wchar *Name) #else char NameA[NM]; WideToChar(Name,NameA,ASIZE(NameA)); - return remove(NameA)==0; + bool Success=remove(NameA)==0; +#ifdef _ANDROID + if (!Success) + Success=JniDelete(Name); +#endif + return Success; #endif } diff --git a/src/thirdparty/unrar/filefn.hpp b/src/thirdparty/unrar/filefn.hpp index d89329471..b06cc64e1 100644 --- a/src/thirdparty/unrar/filefn.hpp +++ b/src/thirdparty/unrar/filefn.hpp @@ -12,6 +12,9 @@ bool IsRemovable(const wchar *Name); int64 GetFreeDisk(const wchar *Name); #endif +#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT) +bool IsFAT(const wchar *Root); +#endif bool FileExist(const wchar *Name); bool WildFileExist(const wchar *Name); diff --git a/src/thirdparty/unrar/filestr.cpp b/src/thirdparty/unrar/filestr.cpp index b719206c7..a87384f24 100644 --- a/src/thirdparty/unrar/filestr.cpp +++ b/src/thirdparty/unrar/filestr.cpp @@ -37,15 +37,17 @@ bool ReadTextFile( SrcFile.SetHandleType(FILE_HANDLESTD); unsigned int DataSize=0,ReadSize; - const int ReadBlock=1024; - Array<char> Data(ReadBlock+5); + const int ReadBlock=4096; + Array<char> Data(ReadBlock+3); while ((ReadSize=SrcFile.Read(&Data[DataSize],ReadBlock))!=0) { DataSize+=ReadSize; Data.Add(ReadSize); } - memset(&Data[DataSize],0,5); + // Add trailing Unicode zero after text data. We add 3 bytes instead of 2 + // in case read Unicode data contains uneven number of bytes. + memset(&Data[DataSize],0,3); Array<wchar> WideStr; @@ -136,7 +138,7 @@ bool ReadTextFile( break; *SpacePtr=0; } - if (*CurStr) + if (*CurStr!=0) { if (Unquote && *CurStr=='\"') { diff --git a/src/thirdparty/unrar/list.cpp b/src/thirdparty/unrar/list.cpp index 7f1e3cd95..d64e274a6 100644 --- a/src/thirdparty/unrar/list.cpp +++ b/src/thirdparty/unrar/list.cpp @@ -18,6 +18,9 @@ void ListArchive(CommandData *Cmd) wchar ArcName[NM]; while (Cmd->GetArcName(ArcName,ASIZE(ArcName))) { + if (Cmd->ManualPassword) + Cmd->Password.Clean(); // Clean user entered password before processing next archive. + Archive Arc(Cmd); #ifdef _WIN_ALL Arc.RemoveSequentialFlag(); @@ -162,6 +165,10 @@ void ListArchive(CommandData *Cmd) } } + // Clean user entered password. Not really required, just for extra safety. + if (Cmd->ManualPassword) + Cmd->Password.Clean(); + if (ArcCount>1 && !Bare && !Technical) { wchar UnpSizeText[20],PackSizeText[20]; diff --git a/src/thirdparty/unrar/loclang.hpp b/src/thirdparty/unrar/loclang.hpp index d07df1cef..fb560713a 100644 --- a/src/thirdparty/unrar/loclang.hpp +++ b/src/thirdparty/unrar/loclang.hpp @@ -216,7 +216,7 @@ #define MExtrNoFiles L"\nNo files to extract" #define MExtrAllOk L"\nAll OK" #define MExtrTotalErr L"\nTotal errors: %ld" -#define MFileExists L"\n\n%s already exists. Overwrite it ?" +#define MAskReplace L"\n\nWould you like to replace the existing file %s\n%6s bytes, modified on %s\nwith a new one\n%6s bytes, modified on %s\n" #define MAskOverwrite L"\nOverwrite %s ?" #define MAskNewName L"\nEnter new name: " #define MHeaderBroken L"\nCorrupt header is found" @@ -344,6 +344,7 @@ #define MCreating L"\nCreating %s" #define MRenaming L"\nRenaming %s to %s" #define MNTFSRequired L"\nWrite error: only NTFS file system supports files larger than 4 GB" +#define MFAT32Size L"\nWARNING: FAT32 file system does not support 4 GB or larger files" #define MErrChangeAttr L"\nWARNING: Cannot change attributes of %s" #define MWrongSFXVer L"\nERROR: default SFX module does not support RAR %d.%d archives" #define MCannotEncName L"\nCannot encrypt archive already contained encrypted files" diff --git a/src/thirdparty/unrar/options.hpp b/src/thirdparty/unrar/options.hpp index 7b61ba2fb..ba9c0ca82 100644 --- a/src/thirdparty/unrar/options.hpp +++ b/src/thirdparty/unrar/options.hpp @@ -99,6 +99,9 @@ class RAROptions wchar ArcPath[NM]; SecPassword Password; bool EncryptHeaders; + + bool ManualPassword; // Password entered manually during operation, might need to clean for next archive. + wchar LogName[NM]; MESSAGE_TYPE MsgStream; bool Sound; diff --git a/src/thirdparty/unrar/pathfn.cpp b/src/thirdparty/unrar/pathfn.cpp index 016a0e824..bfd3b588e 100644 --- a/src/thirdparty/unrar/pathfn.cpp +++ b/src/thirdparty/unrar/pathfn.cpp @@ -196,7 +196,7 @@ void RemoveNameFromPath(wchar *Path) #if defined(_WIN_ALL) && !defined(SFX_MODULE) -static void GetAppDataPath(wchar *Path,size_t MaxSize,bool Create) +bool GetAppDataPath(wchar *Path,size_t MaxSize,bool Create) { LPMALLOC g_pMalloc; SHGetMalloc(&g_pMalloc); @@ -212,12 +212,8 @@ static void GetAppDataPath(wchar *Path,size_t MaxSize,bool Create) if (!Success && Create) Success=MakeDir(Path,false,0)==MKDIR_SUCCESS; } - if (!Success) - { - GetModuleFileName(NULL,Path,(DWORD)MaxSize); - RemoveNameFromPath(Path); - } g_pMalloc->Free(ppidl); + return Success; } #endif @@ -237,7 +233,11 @@ void GetRarDataPath(wchar *Path,size_t MaxSize,bool Create) } if (*Path==0 || !FileExist(Path)) - GetAppDataPath(Path,MaxSize,Create); + if (!GetAppDataPath(Path,MaxSize,Create)) + { + GetModuleFileName(NULL,Path,(DWORD)MaxSize); + RemoveNameFromPath(Path); + } } #endif @@ -436,10 +436,13 @@ void MakeNameUsable(wchar *Name,bool Extended) #ifndef _UNIX if (s-Name>1 && *s==':') *s='_'; +#if 0 // We already can create such files. // Remove ' ' and '.' before path separator, but allow .\ and ..\. - if ((*s==' ' || *s=='.' && s>Name && !IsPathDiv(s[-1]) && s[-1]!='.') && IsPathDiv(s[1])) + if (IsPathDiv(s[1]) && (*s==' ' || *s=='.' && s>Name && + !IsPathDiv(s[-1]) && (s[-1]!='.' || s>Name+1 && !IsPathDiv(s[-2])))) *s='_'; #endif +#endif } } diff --git a/src/thirdparty/unrar/pathfn.hpp b/src/thirdparty/unrar/pathfn.hpp index b34727355..fabb29340 100644 --- a/src/thirdparty/unrar/pathfn.hpp +++ b/src/thirdparty/unrar/pathfn.hpp @@ -17,9 +17,14 @@ void AddEndSlash(wchar *Path,size_t MaxLength); void MakeName(const wchar *Path,const wchar *Name,wchar *Pathname,size_t MaxSize); void GetFilePath(const wchar *FullName,wchar *Path,size_t MaxLength); void RemoveNameFromPath(wchar *Path); +#if defined(_WIN_ALL) && !defined(SFX_MODULE) +bool GetAppDataPath(wchar *Path,size_t MaxSize,bool Create); void GetRarDataPath(wchar *Path,size_t MaxSize,bool Create); +#endif +#ifndef SFX_MODULE bool EnumConfigPaths(uint Number,wchar *Path,size_t MaxSize,bool Create); void GetConfigName(const wchar *Name,wchar *FullName,size_t MaxSize,bool CheckExist,bool Create); +#endif wchar* GetVolNumPart(const wchar *ArcName); void NextVolumeName(wchar *ArcName,uint MaxLength,bool OldNumbering); bool IsNameUsable(const wchar *Name); diff --git a/src/thirdparty/unrar/secpassword.cpp b/src/thirdparty/unrar/secpassword.cpp index ba7152595..2ac289b72 100644 --- a/src/thirdparty/unrar/secpassword.cpp +++ b/src/thirdparty/unrar/secpassword.cpp @@ -7,6 +7,7 @@ typedef BOOL (WINAPI *CRYPTUNPROTECTMEMORY)(LPVOID pData,DWORD cbData,DWORD dwFl #ifndef CRYPTPROTECTMEMORY_BLOCK_SIZE #define CRYPTPROTECTMEMORY_BLOCK_SIZE 16 #define CRYPTPROTECTMEMORY_SAME_PROCESS 0x00 +#define CRYPTPROTECTMEMORY_CROSS_PROCESS 0x01 #endif class CryptLoader @@ -48,12 +49,13 @@ class CryptLoader CRYPTUNPROTECTMEMORY pCryptUnprotectMemory; }; -// We want to call FreeLibrary when RAR is exiting. +// We need to call FreeLibrary when RAR is exiting. CryptLoader GlobalCryptLoader; #endif SecPassword::SecPassword() { + CrossProcess=false; Set(L""); } @@ -99,7 +101,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); + SecHideData(Dst,DstSize*sizeof(*Dst),Encode,CrossProcess); } @@ -156,18 +158,19 @@ bool SecPassword::operator == (SecPassword &psw) } -void SecHideData(void *Data,size_t DataSize,bool Encode) +void SecHideData(void *Data,size_t DataSize,bool Encode,bool CrossProcess) { #ifdef _WIN_ALL // Try to utilize the secure Crypt[Un]ProtectMemory if possible. if (GlobalCryptLoader.pCryptProtectMemory==NULL) GlobalCryptLoader.Load(); size_t Aligned=DataSize-DataSize%CRYPTPROTECTMEMORY_BLOCK_SIZE; + DWORD Flags=CrossProcess ? CRYPTPROTECTMEMORY_CROSS_PROCESS : CRYPTPROTECTMEMORY_SAME_PROCESS; if (Encode) { if (GlobalCryptLoader.pCryptProtectMemory!=NULL) { - if (!GlobalCryptLoader.pCryptProtectMemory(Data,DWORD(Aligned),CRYPTPROTECTMEMORY_SAME_PROCESS)) + if (!GlobalCryptLoader.pCryptProtectMemory(Data,DWORD(Aligned),Flags)) { ErrHandler.GeneralErrMsg(L"CryptProtectMemory failed"); ErrHandler.SysErrMsg(); @@ -180,7 +183,7 @@ void SecHideData(void *Data,size_t DataSize,bool Encode) { if (GlobalCryptLoader.pCryptUnprotectMemory!=NULL) { - if (!GlobalCryptLoader.pCryptUnprotectMemory(Data,DWORD(Aligned),CRYPTPROTECTMEMORY_SAME_PROCESS)) + if (!GlobalCryptLoader.pCryptUnprotectMemory(Data,DWORD(Aligned),Flags)) { ErrHandler.GeneralErrMsg(L"CryptUnprotectMemory failed"); ErrHandler.SysErrMsg(); diff --git a/src/thirdparty/unrar/secpassword.hpp b/src/thirdparty/unrar/secpassword.hpp index 7e166a23b..375d3887a 100644 --- a/src/thirdparty/unrar/secpassword.hpp +++ b/src/thirdparty/unrar/secpassword.hpp @@ -22,10 +22,14 @@ 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; }; void cleandata(void *data,size_t size); -void SecHideData(void *Data,size_t DataSize,bool Encode); +void SecHideData(void *Data,size_t DataSize,bool Encode,bool CrossProcess); #endif diff --git a/src/thirdparty/unrar/smallfn.cpp b/src/thirdparty/unrar/smallfn.cpp index 5b5e6f66b..fe7cb1dc2 100644 --- a/src/thirdparty/unrar/smallfn.cpp +++ b/src/thirdparty/unrar/smallfn.cpp @@ -4,7 +4,7 @@ int ToPercent(int64 N1,int64 N2) { if (N2<N1) return(100); - return(ToPercentUnlim(N1,N2)); + return ToPercentUnlim(N1,N2); } @@ -13,5 +13,7 @@ int ToPercentUnlim(int64 N1,int64 N2) { if (N2==0) return(0); - return((int)(N1*100/N2)); + return (int)(N1*100/N2); } + + diff --git a/src/thirdparty/unrar/strfn.cpp b/src/thirdparty/unrar/strfn.cpp index c2888a09c..f83482fb2 100644 --- a/src/thirdparty/unrar/strfn.cpp +++ b/src/thirdparty/unrar/strfn.cpp @@ -265,8 +265,9 @@ wchar* wcsncpyz(wchar *dest, const wchar *src, size_t maxlen) char* strncatz(char* dest, const char* src, size_t maxlen) { size_t Length = strlen(dest); - if (Length + 1 < maxlen) - strncat(dest, src, maxlen - Length - 1); + int avail=int(maxlen - Length - 1); + if (avail > 0) + strncat(dest, src, avail); return dest; } @@ -277,8 +278,9 @@ char* strncatz(char* dest, const char* src, size_t maxlen) wchar* wcsncatz(wchar* dest, const wchar* src, size_t maxlen) { size_t Length = wcslen(dest); - if (Length + 1 < maxlen) - wcsncat(dest, src, maxlen - Length - 1); + int avail=int(maxlen - Length - 1); + if (avail > 0) + wcsncat(dest, src, avail); return dest; } diff --git a/src/thirdparty/unrar/threadmisc.cpp b/src/thirdparty/unrar/threadmisc.cpp index d56867be4..d1524e0cf 100644 --- a/src/thirdparty/unrar/threadmisc.cpp +++ b/src/thirdparty/unrar/threadmisc.cpp @@ -58,6 +58,20 @@ ThreadPool* CreateThreadPool() if (GlobalPoolUseCount++ == 0) GlobalPool=new ThreadPool(MaxPoolThreads); +#ifdef RARDLL + // We use a simple thread pool, which does not allow to add tasks from + // different functions and threads in the same time. It is ok for RAR, + // but UnRAR.dll can be used in multithreaded environment. So if one of + // threads requests a copy of global pool and another copy is already + // in use, we create and return a new pool instead of existing global. + if (GlobalPoolUseCount > 1) + { + ThreadPool *Pool = new ThreadPool(MaxPoolThreads); + CriticalSectionEnd(&PoolCreateSync.CritSection); + return Pool; + } +#endif + CriticalSectionEnd(&PoolCreateSync.CritSection); return GlobalPool; } @@ -69,6 +83,12 @@ void DestroyThreadPool(ThreadPool *Pool) if (Pool!=NULL && Pool==GlobalPool && GlobalPoolUseCount > 0 && --GlobalPoolUseCount == 0) delete GlobalPool; +#ifdef RARDLL + // To correctly work in multithreaded environment UnRAR.dll creates + // new pools if global pool is already in use. We delete such pools here. + if (Pool!=NULL && Pool!=GlobalPool) + delete Pool; +#endif CriticalSectionEnd(&PoolCreateSync.CritSection); } diff --git a/src/thirdparty/unrar/timefn.hpp b/src/thirdparty/unrar/timefn.hpp index f8c914b87..355baaf74 100644 --- a/src/thirdparty/unrar/timefn.hpp +++ b/src/thirdparty/unrar/timefn.hpp @@ -32,6 +32,7 @@ class RarTime RarTime& operator =(time_t ut); time_t GetUnix(); bool operator == (RarTime &rt) {return itime==rt.itime;} + bool operator != (RarTime &rt) {return itime!=rt.itime;} bool operator < (RarTime &rt) {return itime<rt.itime;} bool operator <= (RarTime &rt) {return itime<rt.itime || itime==rt.itime;} bool operator > (RarTime &rt) {return itime>rt.itime;} diff --git a/src/thirdparty/unrar/ui.hpp b/src/thirdparty/unrar/ui.hpp index 9803b78ab..ae1b8839a 100644 --- a/src/thirdparty/unrar/ui.hpp +++ b/src/thirdparty/unrar/ui.hpp @@ -45,7 +45,7 @@ enum UIMESSAGE_CODE { UIMSG_SECTORRECOVERED, UIMSG_SECTORNOTRECOVERED, UIMSG_FOUND, UIMSG_CORRECTINGNAME, UIMSG_BADARCHIVE, UIMSG_CREATING, UIMSG_RENAMING, UIMSG_RECVOLCALCCHECKSUM, UIMSG_RECVOLFOUND, UIMSG_RECVOLMISSING, - UIMSG_MISSINGVOL, UIMSG_RECONSTRUCTING, UIMSG_CHECKSUM, + UIMSG_MISSINGVOL, UIMSG_RECONSTRUCTING, UIMSG_CHECKSUM, UIMSG_FAT32SIZE, UIWAIT_FIRST, UIWAIT_DISKFULLNEXT, UIWAIT_FCREATEERROR, @@ -55,9 +55,8 @@ enum UIMESSAGE_CODE { UIEVENT_DELADDEDSTART, UIEVENT_DELADDEDFILE, UIEVENT_FILESFOUND, UIEVENT_ERASEDISK, UIEVENT_FILESUMSTART, UIEVENT_FILESUMPROGRESS, UIEVENT_FILESUMEND, UIEVENT_PROTECTSTART, UIEVENT_PROTECTEND, - UIEVENT_TESTADDEDSTART, UIEVENT_TESTADDEDEND, UIEVENT_RRTESTING, - UIEVENT_NEWARCHIVE, UIEVENT_NEWREVFILE - + UIEVENT_TESTADDEDSTART, UIEVENT_TESTADDEDEND, UIEVENT_RRTESTINGSTART, + UIEVENT_RRTESTINGEND, UIEVENT_NEWARCHIVE, UIEVENT_NEWREVFILE }; // Flags for uiAskReplace function. diff --git a/src/thirdparty/unrar/uiconsole.cpp b/src/thirdparty/unrar/uiconsole.cpp index 5ddaf09f4..b9129c4f7 100644 --- a/src/thirdparty/unrar/uiconsole.cpp +++ b/src/thirdparty/unrar/uiconsole.cpp @@ -1,8 +1,20 @@ // Purely user interface function. Gets and returns user input. UIASKREP_RESULT uiAskReplace(wchar *Name,size_t MaxNameSize,int64 FileSize,RarTime *FileTime,uint Flags) { + wchar SizeText1[20],DateStr1[50],SizeText2[20],DateStr2[50]; + + FindData ExistingFD; + memset(&ExistingFD,0,sizeof(ExistingFD)); // In case find fails. + FindFile::FastFind(Name,&ExistingFD); + itoa(ExistingFD.Size,SizeText1); + ExistingFD.mtime.GetText(DateStr1,ASIZE(DateStr1),true,false); + + itoa(FileSize,SizeText2); + FileTime->GetText(DateStr2,ASIZE(DateStr2),true,false); + + eprintf(St(MAskReplace),Name,SizeText1,DateStr1,SizeText2,DateStr2); + bool AllowRename=(Flags & UIASKREP_F_NORENAME)==0; - eprintf(St(MFileExists),Name); int Choice=0; do { @@ -299,11 +311,14 @@ void uiMsgStore::Msg() case UIMSG_CHECKSUM: mprintf(St(MCRCFailed),Str[0]); break; + case UIMSG_FAT32SIZE: + mprintf(St(MFAT32Size)); + mprintf(L" "); // For progress percent. + break; - - case UIEVENT_RRTESTING: + case UIEVENT_RRTESTINGSTART: mprintf(L"%s ",St(MTestingRR)); break; } diff --git a/src/thirdparty/unrar/unicode.cpp b/src/thirdparty/unrar/unicode.cpp index cff2358d0..9c1080aa7 100644 --- a/src/thirdparty/unrar/unicode.cpp +++ b/src/thirdparty/unrar/unicode.cpp @@ -433,7 +433,7 @@ const wchar_t* wcscasestr(const wchar_t *str, const wchar_t *search) { if (search[j]==0) return str+i; - if (towlower(str[i+j])!=towlower(search[j])) + if (tolowerw(str[i+j])!=tolowerw(search[j])) break; } return NULL; @@ -472,31 +472,50 @@ wchar* wcsupper(wchar *s) int toupperw(int ch) { +#ifdef _WIN_ALL + // CharUpper is more reliable than towupper in Windows, which seems to be + // C locale dependent even in Unicode version. For example, towupper failed + // to convert lowercase Russian characters. + return (int)CharUpper((wchar *)ch); +#else return towupper(ch); +#endif } int tolowerw(int ch) { +#ifdef _WIN_ALL + // CharLower is more reliable than towlower in Windows. + // See comment for towupper above. + return (int)CharLower((wchar *)ch); +#else return towlower(ch); +#endif } -uint atoiw(const wchar *s) +int atoiw(const wchar *s) { - return (uint)atoilw(s); + return (int)atoilw(s); } -uint64 atoilw(const wchar *s) +int64 atoilw(const wchar *s) { - uint64 n=0; + int sign=1; + if (*s=='-') + { + s++; + sign=-1; + } + int64 n=0; while (*s>='0' && *s<='9') { n=n*10+(*s-'0'); s++; } - return n; + return sign*n; } diff --git a/src/thirdparty/unrar/unicode.hpp b/src/thirdparty/unrar/unicode.hpp index 29eeb0edd..e2f45b0b9 100644 --- a/src/thirdparty/unrar/unicode.hpp +++ b/src/thirdparty/unrar/unicode.hpp @@ -22,8 +22,8 @@ wchar* wcsupper(wchar *s); #endif int toupperw(int ch); int tolowerw(int ch); -uint atoiw(const wchar *s); -uint64 atoilw(const wchar *s); +int atoiw(const wchar *s); +int64 atoilw(const wchar *s); #ifdef DBCS_SUPPORTED class SupportDBCS diff --git a/src/thirdparty/unrar/unrar.vcxproj b/src/thirdparty/unrar/unrar.vcxproj index 3a0aafb89..88eede44a 100644 --- a/src/thirdparty/unrar/unrar.vcxproj +++ b/src/thirdparty/unrar/unrar.vcxproj @@ -47,52 +47,46 @@ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\common.props" />
+ <Import Project="..\..\common-3rd-party.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\common.props" />
+ <Import Project="..\..\common-3rd-party.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\common.props" />
+ <Import Project="..\..\common-3rd-party.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\common.props" />
+ <Import Project="..\..\common-3rd-party.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
- <PropertyGroup>
- </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
<PreprocessorDefinitions>_LIB;RARDLL;SILENT;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <WarningLevel>TurnOffAllWarnings</WarningLevel>
- <EnablePREfast>false</EnablePREfast>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
- <WarningLevel>TurnOffAllWarnings</WarningLevel>
<PreprocessorDefinitions>_LIB;RARDLL;SILENT;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <EnablePREfast>false</EnablePREfast>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
- <WarningLevel>TurnOffAllWarnings</WarningLevel>
<PreprocessorDefinitions>_LIB;RARDLL;SILENT;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <EnablePREfast>false</EnablePREfast>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeaderFile>rar.hpp</PrecompiledHeaderFile>
- <WarningLevel>TurnOffAllWarnings</WarningLevel>
<PreprocessorDefinitions>_LIB;RARDLL;SILENT;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <EnablePREfast>false</EnablePREfast>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/src/thirdparty/unrar/version.hpp b/src/thirdparty/unrar/version.hpp index ef0b664db..3a36f22b3 100644 --- a/src/thirdparty/unrar/version.hpp +++ b/src/thirdparty/unrar/version.hpp @@ -1,6 +1,6 @@ #define RARVER_MAJOR 5 -#define RARVER_MINOR 11 -#define RARVER_BETA 1 -#define RARVER_DAY 6 -#define RARVER_MONTH 8 +#define RARVER_MINOR 20 +#define RARVER_BETA 0 +#define RARVER_DAY 2 +#define RARVER_MONTH 12 #define RARVER_YEAR 2014 |