diff options
Diffstat (limited to 'src/thirdparty/unrar')
27 files changed, 191 insertions, 92 deletions
diff --git a/src/thirdparty/unrar/archive.cpp b/src/thirdparty/unrar/archive.cpp index 9e9e72424..7ca0b7461 100644 --- a/src/thirdparty/unrar/archive.cpp +++ b/src/thirdparty/unrar/archive.cpp @@ -234,6 +234,7 @@ bool Archive::IsArchive(bool EnableBroken) { SaveFilePos SavePos(*this); int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos; + HEADER_TYPE SaveCurHeaderType=CurHeaderType; while (ReadHeader()!=0) { @@ -250,6 +251,7 @@ bool Archive::IsArchive(bool EnableBroken) } CurBlockPos=SaveCurBlockPos; NextBlockPos=SaveNextBlockPos; + CurHeaderType=SaveCurHeaderType; } if (!Volume || FirstVolume) wcscpy(FirstVolumeName,FileName); diff --git a/src/thirdparty/unrar/archive.hpp b/src/thirdparty/unrar/archive.hpp index 1d8444bfb..522709608 100644 --- a/src/thirdparty/unrar/archive.hpp +++ b/src/thirdparty/unrar/archive.hpp @@ -85,8 +85,8 @@ class Archive:public File void AddSubData(byte *SrcData,uint64 DataSize,File *SrcFile, const wchar *Name,uint Flags); bool ReadSubData(Array<byte> *UnpData,File *DestFile); - HEADER_TYPE GetHeaderType() {return(CurHeaderType);}; - RAROptions* GetRAROptions() {return(Cmd);} + HEADER_TYPE GetHeaderType() {return CurHeaderType;}; + RAROptions* GetRAROptions() {return Cmd;} void SetSilentOpen(bool Mode) {SilentOpen=Mode;} #ifdef USE_QOPEN bool Open(const wchar *Name,uint Mode=FMF_READ); diff --git a/src/thirdparty/unrar/arcread.cpp b/src/thirdparty/unrar/arcread.cpp index e4c3f87d5..047289b7a 100644 --- a/src/thirdparty/unrar/arcread.cpp +++ b/src/thirdparty/unrar/arcread.cpp @@ -44,10 +44,10 @@ size_t Archive::SearchBlock(HEADER_TYPE HeaderType) if ((++Count & 127)==0) Wait(); if (GetHeaderType()==HeaderType) - return(Size); + return Size; SeekToNext(); } - return(0); + return 0; } @@ -128,7 +128,7 @@ size_t Archive::ReadHeader15() if (Read(Salt,SIZE_SALT30)!=SIZE_SALT30) { UnexpEndArcMsg(); - return(0); + return 0; } HeadersCrypt.SetCryptKeys(false,CRYPT_RAR30,&Cmd->Password,Salt,NULL,0,NULL,NULL); Raw.SetCrypt(&HeadersCrypt); @@ -155,7 +155,7 @@ size_t Archive::ReadHeader15() if (ShortBlock.HeadSize<SIZEOF_SHORTBLOCKHEAD) { BrokenHeaderMsg(); - return(0); + return 0; } // For simpler further processing we map header types common @@ -562,7 +562,7 @@ size_t Archive::ReadHeader50() if (Decrypt) { #if defined(SHELL_EXT) || defined(RAR_NOCRYPT) - return(0); + return 0; #else RequestArcPassword(); @@ -570,7 +570,7 @@ size_t Archive::ReadHeader50() if (Read(HeadersInitV,SIZE_INITV)!=SIZE_INITV) { UnexpEndArcMsg(); - return(0); + return 0; } byte PswCheck[SIZE_PSWCHECK]; @@ -886,7 +886,8 @@ void Archive::RequestArcPassword() ErrHandler.Exit(RARX_USERBREAK); } #else - if (!uiGetPassword(UIPASSWORD_ARCHIVE,FileName,&Cmd->Password)) + if (!uiGetPassword(UIPASSWORD_ARCHIVE,FileName,&Cmd->Password) || + !Cmd->Password.IsSet()) { Close(); uiMsg(UIERROR_INCERRCOUNT); @@ -1168,7 +1169,7 @@ size_t Archive::ReadHeader14() NextBlockPos=CurBlockPos+FileHead.HeadSize+FileHead.PackSize; CurHeaderType=HEAD_FILE; } - return(NextBlockPos>CurBlockPos ? Raw.Size():0); + return NextBlockPos>CurBlockPos ? Raw.Size() : 0; } #endif diff --git a/src/thirdparty/unrar/cmddata.cpp b/src/thirdparty/unrar/cmddata.cpp index b56410ae9..3f84cc373 100644 --- a/src/thirdparty/unrar/cmddata.cpp +++ b/src/thirdparty/unrar/cmddata.cpp @@ -616,6 +616,8 @@ void CommandData::ProcessSwitch(const wchar *Switch) #ifdef SAVE_LINKS case 'L': SaveSymLinks=true; + if (toupperw(Switch[2])=='A') + AbsoluteLinks=true; break; #endif case 'R': @@ -958,7 +960,7 @@ void CommandData::OutHelp(RAR_EXIT ExitCode) MCHelpSwCm,MCHelpSwCFGm,MCHelpSwCL,MCHelpSwCU, MCHelpSwDH,MCHelpSwEP,MCHelpSwEP3,MCHelpSwF,MCHelpSwIDP,MCHelpSwIERR, MCHelpSwINUL,MCHelpSwIOFF,MCHelpSwKB,MCHelpSwN,MCHelpSwNa,MCHelpSwNal, - MCHelpSwO,MCHelpSwOC,MCHelpSwOR,MCHelpSwOW,MCHelpSwP, + MCHelpSwO,MCHelpSwOC,MCHelpSwOL,MCHelpSwOR,MCHelpSwOW,MCHelpSwP, MCHelpSwPm,MCHelpSwR,MCHelpSwRI,MCHelpSwSC,MCHelpSwSL,MCHelpSwSM, MCHelpSwTA,MCHelpSwTB,MCHelpSwTN,MCHelpSwTO,MCHelpSwTS,MCHelpSwU, MCHelpSwVUnr,MCHelpSwVER,MCHelpSwVP,MCHelpSwX,MCHelpSwXa,MCHelpSwXal, @@ -1157,8 +1159,11 @@ bool CommandData::SizeCheck(int64 Size) -int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType) +int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType, + wchar *MatchedArg,uint MatchedArgSize) { + if (MatchedArg!=NULL && MatchedArgSize>0) + *MatchedArg=0; if (wcslen(FileHead.FileName)>=NM) return 0; bool Dir=FileHead.Dir; @@ -1179,6 +1184,8 @@ int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchTy { if (ExactMatch!=NULL) *ExactMatch=wcsicompc(ArgName,FileHead.FileName)==0; + if (MatchedArg!=NULL) + wcsncpyz(MatchedArg,ArgName,MatchedArgSize); return StringCount; } return 0; diff --git a/src/thirdparty/unrar/cmddata.hpp b/src/thirdparty/unrar/cmddata.hpp index 3ed4ef1d8..d2cdbb94d 100644 --- a/src/thirdparty/unrar/cmddata.hpp +++ b/src/thirdparty/unrar/cmddata.hpp @@ -37,7 +37,8 @@ class CommandData:public RAROptions bool TimeCheck(RarTime &ft); bool SizeCheck(int64 Size); bool AnyFiltersActive(); - int IsProcessFile(FileHeader &FileHead,bool *ExactMatch=NULL,int MatchType=MATCH_WILDSUBPATH); + int IsProcessFile(FileHeader &FileHead,bool *ExactMatch=NULL,int MatchType=MATCH_WILDSUBPATH, + wchar *MatchedArg=NULL,uint MatchedArgSize=0); void ProcessCommand(); void AddArcName(const wchar *Name); bool GetArcName(wchar *Name,int MaxSize); diff --git a/src/thirdparty/unrar/dll.rc b/src/thirdparty/unrar/dll.rc index 1481d7632..fa7ab25cb 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, 20, 100, 1433
-PRODUCTVERSION 5, 20, 100, 1433
+FILEVERSION 5, 21, 100, 1510
+PRODUCTVERSION 5, 21, 100, 1510
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", "5.20.0\0"
- VALUE "ProductVersion", "5.20.0\0"
- VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2014\0"
+ VALUE "FileVersion", "5.21.0\0"
+ VALUE "ProductVersion", "5.21.0\0"
+ VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2015\0"
VALUE "OriginalFilename", "Unrar.dll\0"
}
}
diff --git a/src/thirdparty/unrar/extinfo.cpp b/src/thirdparty/unrar/extinfo.cpp index 141967f2a..01827eba0 100644 --- a/src/thirdparty/unrar/extinfo.cpp +++ b/src/thirdparty/unrar/extinfo.cpp @@ -60,14 +60,45 @@ void SetExtraInfo(CommandData *Cmd,Archive &Arc,wchar *Name) +bool IsRelativeSymlinkSafe(const wchar *SrcName,const wchar *TargetName) +{ + if (IsFullRootPath(SrcName)) + return false; + int AllowedDepth=0; + while (*SrcName!=0) + { + if (IsPathDiv(SrcName[0]) && SrcName[1]!=0 && !IsPathDiv(SrcName[1])) + { + bool Dot=SrcName[1]=='.' && (IsPathDiv(SrcName[2]) || SrcName[2]==0); + bool Dot2=SrcName[1]=='.' && SrcName[2]=='.' && (IsPathDiv(SrcName[3]) || SrcName[3]==0); + if (!Dot && !Dot2) + AllowedDepth++; + } + SrcName++; + } + if (IsFullRootPath(TargetName)) // Catch root dir based /path/file paths. + return false; + for (int Pos=0;*TargetName!=0;Pos++) + { + bool Dot2=TargetName[0]=='.' && TargetName[1]=='.' && + (IsPathDiv(TargetName[2]) || TargetName[2]==0) && + (Pos==0 || IsPathDiv(*(TargetName-1))); + if (Dot2) + AllowedDepth--; + TargetName++; + } + return AllowedDepth>=0; +} + + bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName) { #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(DataIO,Arc,LinkName); + return ExtractUnixLink30(Cmd,DataIO,Arc,LinkName); if (Arc.Format==RARFMT50) - return ExtractUnixLink50(LinkName,&Arc.FileHead); + return ExtractUnixLink50(Cmd,LinkName,&Arc.FileHead); #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. diff --git a/src/thirdparty/unrar/extinfo.hpp b/src/thirdparty/unrar/extinfo.hpp index 224564da8..b974bf489 100644 --- a/src/thirdparty/unrar/extinfo.hpp +++ b/src/thirdparty/unrar/extinfo.hpp @@ -1,6 +1,7 @@ #ifndef _RAR_EXTINFO_ #define _RAR_EXTINFO_ +bool IsRelativeSymlinkSafe(const wchar *SrcName,const wchar *TargetName); bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName); #ifdef _UNIX void SetUnixOwner(Archive &Arc,const wchar *FileName); diff --git a/src/thirdparty/unrar/extract.cpp b/src/thirdparty/unrar/extract.cpp index cab669fe9..a24eb9405 100644 --- a/src/thirdparty/unrar/extract.cpp +++ b/src/thirdparty/unrar/extract.cpp @@ -213,6 +213,8 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) #ifdef NOVOLUME
return false;
#else
+ // Supposing we unpack an old RAR volume without end of archive record
+ // and last file is not split between volumes.
if (!MergeArchive(Arc,&DataIO,false,Command))
{
ErrHandler.SetErrorCode(RARX_WARNING);
@@ -257,17 +259,19 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) int MatchType=MATCH_WILDSUBPATH;
bool EqualNames=false;
- int MatchNumber=Cmd->IsProcessFile(Arc.FileHead,&EqualNames,MatchType);
- bool ExactMatch=MatchNumber!=0;
+ wchar MatchedArg[NM];
+ int MatchNumber=Cmd->IsProcessFile(Arc.FileHead,&EqualNames,MatchType,MatchedArg,ASIZE(MatchedArg));
+ bool MatchFound=MatchNumber!=0;
#ifndef SFX_MODULE
- if (*Cmd->ArcPath==0 && Cmd->ExclPath==EXCL_BASEPATH && ExactMatch)
+ if (Cmd->ExclPath==EXCL_BASEPATH)
{
- Cmd->FileArgs.Rewind();
- if (Cmd->FileArgs.GetString(Cmd->ArcPath,ASIZE(Cmd->ArcPath),MatchNumber-1))
- *PointToName(Cmd->ArcPath)=0;
+ wcsncpyz(Cmd->ArcPath,MatchedArg,ASIZE(Cmd->ArcPath));
+ *PointToName(Cmd->ArcPath)=0;
+ if (IsWildcard(Cmd->ArcPath)) // Cannot correctly process path*\* masks here.
+ *Cmd->ArcPath=0;
}
#endif
- if (ExactMatch && !EqualNames)
+ if (MatchFound && !EqualNames)
AllMatchesExact=false;
Arc.ConvertAttributes();
@@ -309,17 +313,17 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) if (Cmd->VersionControl!=1 && !EqualNames)
{
if (Cmd->VersionControl==0)
- ExactMatch=false;
+ MatchFound=false;
int Version=ParseVersionFileName(ArcFileName,false);
if (Cmd->VersionControl-1==Version)
ParseVersionFileName(ArcFileName,true);
else
- ExactMatch=false;
+ MatchFound=false;
}
}
else
if (!Arc.IsArcDir() && Cmd->VersionControl>1)
- ExactMatch=false;
+ MatchFound=false;
DataIO.UnpVolume=Arc.FileHead.SplitAfter;
DataIO.NextVolumeMissing=false;
@@ -330,9 +334,9 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) bool SkipSolid=false;
#ifndef SFX_MODULE
- if (FirstFile && (ExactMatch || Arc.Solid) && Arc.FileHead.SplitBefore)
+ if (FirstFile && (MatchFound || Arc.Solid) && Arc.FileHead.SplitBefore)
{
- if (ExactMatch)
+ if (MatchFound)
{
uiMsg(UIERROR_NEEDPREVVOL,Arc.FileName,ArcFileName);
#ifdef RARDLL
@@ -340,13 +344,13 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) #endif
ErrHandler.SetErrorCode(RARX_OPEN);
}
- ExactMatch=false;
+ MatchFound=false;
}
FirstFile=false;
#endif
- if (ExactMatch || (SkipSolid=Arc.Solid)!=0)
+ if (MatchFound || (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
@@ -383,9 +387,13 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) if (Arc.FileHead.Encrypted)
{
+ // Stop archive extracting if user cancelled a password prompt.
#ifdef RARDLL
if (!ExtrDllGetPassword())
+ {
+ Cmd->DllError=ERAR_MISSING_PASSWORD;
return false;
+ }
#else
if (!ExtrGetPassword(Arc,ArcFileName))
{
@@ -394,6 +402,9 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) }
#endif
// Skip only the current encrypted file if empty password is entered.
+ // Actually our "cancel" code above intercepts empty passwords too now,
+ // so we keep the code below just in case we'll decide process empty
+ // and cancelled passwords differently sometimes.
if (!Cmd->Password.IsSet())
{
ErrHandler.SetErrorCode(RARX_WARNING);
@@ -406,13 +417,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) #ifdef RARDLL
if (*Cmd->DllDestName!=0)
- {
wcsncpyz(DestFileName,Cmd->DllDestName,ASIZE(DestFileName));
-
-// Do we need this code?
-// if (Cmd->DllOpMode!=RAR_EXTRACT)
-// ExtrFile=false;
- }
#endif
if (!CheckUnpVer(Arc,ArcFileName))
@@ -711,7 +716,7 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) }
}
}
- if (ExactMatch)
+ if (MatchFound)
MatchedArgs++;
if (DataIO.NextVolumeMissing)
return false;
@@ -882,8 +887,10 @@ bool CmdExtract::ExtrGetPassword(Archive &Arc,const wchar *ArcFileName) {
if (!Cmd->Password.IsSet())
{
- if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password))
+ if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password) || !Cmd->Password.IsSet())
{
+ // Suppress "test is ok" message in GUI if user entered
+ // an empty password or cancelled a password prompt.
uiMsg(UIERROR_INCERRCOUNT);
return false;
diff --git a/src/thirdparty/unrar/filcreat.cpp b/src/thirdparty/unrar/filcreat.cpp index 8b20b3fa9..6717eee90 100644 --- a/src/thirdparty/unrar/filcreat.cpp +++ b/src/thirdparty/unrar/filcreat.cpp @@ -45,7 +45,6 @@ bool FileCreate(RAROptions *Cmd,File *NewFile,wchar *Name,size_t MaxNameSize, uint FileMode=WriteOnly ? FMF_WRITE|FMF_SHAREREAD:FMF_UPDATE|FMF_SHAREREAD; if (NewFile!=NULL && NewFile->Create(Name,FileMode)) return true; - PrepareToDelete(Name); CreatePath(Name,true); return NewFile!=NULL ? NewFile->Create(Name,FileMode):DelFile(Name); } diff --git a/src/thirdparty/unrar/file.cpp b/src/thirdparty/unrar/file.cpp index 8fba34adb..185474c25 100644 --- a/src/thirdparty/unrar/file.cpp +++ b/src/thirdparty/unrar/file.cpp @@ -281,10 +281,10 @@ bool File::Rename(const wchar *NewName) } -void File::Write(const void *Data,size_t Size) +bool File::Write(const void *Data,size_t Size) { if (Size==0) - return; + return true; if (HandleType==FILE_HANDLESTD) { #ifdef _WIN_ALL @@ -301,9 +301,10 @@ void File::Write(const void *Data,size_t Size) } #endif } + bool Success; while (1) { - bool Success=false; + Success=false; #ifdef _WIN_ALL DWORD Written=0; if (HandleType!=FILE_HANDLENORMAL) @@ -352,6 +353,7 @@ void File::Write(const void *Data,size_t Size) break; } LastWrite=true; + return Success; // It can return false only if AllowExceptions is disabled. } diff --git a/src/thirdparty/unrar/file.hpp b/src/thirdparty/unrar/file.hpp index 93aac89f3..0d6534ff7 100644 --- a/src/thirdparty/unrar/file.hpp +++ b/src/thirdparty/unrar/file.hpp @@ -80,7 +80,7 @@ class File bool Close(); bool Delete(); bool Rename(const wchar *NewName); - void Write(const void *Data,size_t Size); + bool Write(const void *Data,size_t Size); virtual int Read(void *Data,size_t Size); int DirectRead(void *Data,size_t Size); virtual void Seek(int64 Offset,int Method); diff --git a/src/thirdparty/unrar/filestr.cpp b/src/thirdparty/unrar/filestr.cpp index a87384f24..5fa946a4d 100644 --- a/src/thirdparty/unrar/filestr.cpp +++ b/src/thirdparty/unrar/filestr.cpp @@ -38,16 +38,20 @@ bool ReadTextFile( unsigned int DataSize=0,ReadSize; const int ReadBlock=4096; - Array<char> Data(ReadBlock+3); + + // Our algorithm below needs at least two trailing zeroes after data. + // So for Unicode we provide 2 Unicode zeroes and one more byte + // in case read Unicode data contains uneven number of bytes. + const size_t ZeroPadding=5; + + Array<char> Data(ReadBlock+ZeroPadding); while ((ReadSize=SrcFile.Read(&Data[DataSize],ReadBlock))!=0) { DataSize+=ReadSize; - Data.Add(ReadSize); + Data.Add(ReadSize); // Always have ReadBlock available for next data. } - - // 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); + + memset(&Data[DataSize],0,ZeroPadding); // Provide at least 2 Unicode zero bytes. Array<wchar> WideStr; diff --git a/src/thirdparty/unrar/loclang.hpp b/src/thirdparty/unrar/loclang.hpp index fb560713a..52bcafe92 100644 --- a/src/thirdparty/unrar/loclang.hpp +++ b/src/thirdparty/unrar/loclang.hpp @@ -99,7 +99,7 @@ #define MCHelpSwOC L"\n oc Set NTFS Compressed attribute" #define MCHelpSwOH L"\n oh Save hard links as the link instead of the file" #define MCHelpSwOI L"\n oi[0-4][:min] Save identical files as references" -#define MCHelpSwOL L"\n ol Save symbolic links as the link instead of the file" +#define MCHelpSwOL L"\n ol[a] Process symbolic links as the link [absolute paths]" #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" diff --git a/src/thirdparty/unrar/options.hpp b/src/thirdparty/unrar/options.hpp index ba9c0ca82..a6ec227f0 100644 --- a/src/thirdparty/unrar/options.hpp +++ b/src/thirdparty/unrar/options.hpp @@ -132,6 +132,7 @@ class RAROptions bool ProcessOwners; bool SaveSymLinks; bool SaveHardLinks; + bool AbsoluteLinks; int Priority; int SleepTime; bool KeepBroken; diff --git a/src/thirdparty/unrar/os.hpp b/src/thirdparty/unrar/os.hpp index 84f8fc92a..1b0813f6c 100644 --- a/src/thirdparty/unrar/os.hpp +++ b/src/thirdparty/unrar/os.hpp @@ -79,6 +79,7 @@ #include <time.h> #include <signal.h> + #define SAVE_LINKS #define ENABLE_ACCESS @@ -154,6 +155,7 @@ #include <utime.h> #include <locale.h> + #ifdef S_IFLNK #define SAVE_LINKS #endif diff --git a/src/thirdparty/unrar/pathfn.cpp b/src/thirdparty/unrar/pathfn.cpp index bfd3b588e..b6e220eee 100644 --- a/src/thirdparty/unrar/pathfn.cpp +++ b/src/thirdparty/unrar/pathfn.cpp @@ -29,7 +29,7 @@ wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath) while (*DestPtr!=0) { const wchar *s=DestPtr; - if (s[0] && IsDriveDiv(s[1])) + if (s[0]!=0 && IsDriveDiv(s[1])) s+=2; if (s[0]=='\\' && s[1]=='\\') { @@ -541,6 +541,12 @@ bool IsFullPath(const wchar *Path) } +bool IsFullRootPath(const wchar *Path) +{ + return IsFullPath(Path) || IsPathDiv(Path[0]); +} + + bool IsDiskLetter(const wchar *Path) { wchar Letter=etoupperw(Path[0]); diff --git a/src/thirdparty/unrar/pathfn.hpp b/src/thirdparty/unrar/pathfn.hpp index fabb29340..ae1f8c2e8 100644 --- a/src/thirdparty/unrar/pathfn.hpp +++ b/src/thirdparty/unrar/pathfn.hpp @@ -56,6 +56,7 @@ inline void SlashToNative(const wchar *SrcName,wchar *DestName,size_t MaxLength) void ConvertNameToFull(const wchar *Src,wchar *Dest,size_t MaxSize); bool IsFullPath(const wchar *Path); +bool IsFullRootPath(const wchar *Path); bool IsDiskLetter(const wchar *Path); void GetPathRoot(const wchar *Path,wchar *Root,size_t MaxSize); int ParseVersionFileName(wchar *Name,bool Truncate); diff --git a/src/thirdparty/unrar/strfn.cpp b/src/thirdparty/unrar/strfn.cpp index f83482fb2..e234da834 100644 --- a/src/thirdparty/unrar/strfn.cpp +++ b/src/thirdparty/unrar/strfn.cpp @@ -19,7 +19,7 @@ void IntToExt(const char *Src,char *Dest,size_t DestSize) Dest[DestSize-1]=0; #elif defined(_ANDROID) wchar DestW[NM]; - UnkToWide(Src,DestW,ASIZE(DestW)); + JniCharToWide(Src,DestW,ASIZE(DestW),true); WideToChar(DestW,Dest,DestSize); #else if (Dest!=Src) diff --git a/src/thirdparty/unrar/timefn.cpp b/src/thirdparty/unrar/timefn.cpp index 3fa535f4c..ba9f49686 100644 --- a/src/thirdparty/unrar/timefn.cpp +++ b/src/thirdparty/unrar/timefn.cpp @@ -223,7 +223,7 @@ void RarTime::GetText(wchar *DateStr,size_t MaxSize,bool FullYear,bool FullMS) RarLocalTime lt; GetLocal(<); if (FullMS) - swprintf(DateStr,MaxSize,L"%u-%02u-%02u %02u:%02u,%03u",lt.Year,lt.Month,lt.Day,lt.Hour,lt.Minute,lt.Reminder/10000); + swprintf(DateStr,MaxSize,L"%u-%02u-%02u %02u:%02u:%02u,%03u",lt.Year,lt.Month,lt.Day,lt.Hour,lt.Minute,lt.Second,lt.Reminder/10000); else if (FullYear) swprintf(DateStr,MaxSize,L"%02u-%02u-%u %02u:%02u",lt.Day,lt.Month,lt.Year,lt.Hour,lt.Minute); diff --git a/src/thirdparty/unrar/uicommon.cpp b/src/thirdparty/unrar/uicommon.cpp index 7238c1936..5be551a42 100644 --- a/src/thirdparty/unrar/uicommon.cpp +++ b/src/thirdparty/unrar/uicommon.cpp @@ -22,11 +22,18 @@ UIASKREP_RESULT uiAskReplaceEx(RAROptions *Cmd,wchar *Name,size_t MaxNameSize,in // This check must be after OVERWRITE_AUTORENAME processing or -y switch // would override -or. if (Cmd->AllYes || Cmd->Overwrite==OVERWRITE_ALL) + { + PrepareToDelete(Name); return UIASKREP_R_REPLACE; + } wchar NewName[NM]; wcsncpyz(NewName,Name,ASIZE(NewName)); UIASKREP_RESULT Choice=uiAskReplace(NewName,ASIZE(NewName),FileSize,FileTime,Flags); + + if (Choice==UIASKREP_R_REPLACE || Choice==UIASKREP_R_REPLACEALL) + PrepareToDelete(Name); + if (Choice==UIASKREP_R_REPLACEALL) { Cmd->Overwrite=OVERWRITE_ALL; diff --git a/src/thirdparty/unrar/uiconsole.cpp b/src/thirdparty/unrar/uiconsole.cpp index b9129c4f7..ba7550c6b 100644 --- a/src/thirdparty/unrar/uiconsole.cpp +++ b/src/thirdparty/unrar/uiconsole.cpp @@ -9,10 +9,17 @@ UIASKREP_RESULT uiAskReplace(wchar *Name,size_t MaxNameSize,int64 FileSize,RarTi 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); + if (FileSize==INT64NDF || FileTime==NULL) + { + eprintf(L"\n"); + eprintf(St(MAskOverwrite),Name); + } + else + { + 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; int Choice=0; diff --git a/src/thirdparty/unrar/ulinks.cpp b/src/thirdparty/unrar/ulinks.cpp index b51ff6282..c6d2f874a 100644 --- a/src/thirdparty/unrar/ulinks.cpp +++ b/src/thirdparty/unrar/ulinks.cpp @@ -30,7 +30,13 @@ static bool UnixSymlink(const char *Target,const wchar *LinkName,RarTime *ftm,Ra } -bool ExtractUnixLink30(ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName) +static bool IsFullPath(const char *PathA) // Unix ASCII version. +{ + return *PathA==CPATHDIVIDER; +} + + +bool ExtractUnixLink30(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName) { char Target[NM]; if (IsLink(Arc.FileHead.FileAttr)) @@ -48,13 +54,16 @@ bool ExtractUnixLink30(ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName) if (!DataIO.UnpHash.Cmp(&Arc.FileHead.FileHash,Arc.FileHead.UseHashKey ? Arc.FileHead.HashKey:NULL)) return true; + if (!Cmd->AbsoluteLinks && (IsFullPath(Target) || + !IsRelativeSymlinkSafe(Arc.FileHead.FileName,Arc.FileHead.RedirName))) + return false; return UnixSymlink(Target,LinkName,&Arc.FileHead.mtime,&Arc.FileHead.atime); } return false; } -bool ExtractUnixLink50(const wchar *Name,FileHeader *hd) +bool ExtractUnixLink50(CommandData *Cmd,const wchar *Name,FileHeader *hd) { char Target[NM]; WideToChar(hd->RedirName,Target,ASIZE(Target)); @@ -68,5 +77,8 @@ bool ExtractUnixLink50(const wchar *Name,FileHeader *hd) return false; DosSlashToUnix(Target,Target,ASIZE(Target)); } + if (!Cmd->AbsoluteLinks && (IsFullPath(Target) || + !IsRelativeSymlinkSafe(hd->FileName,hd->RedirName))) + return false; return UnixSymlink(Target,Name,&hd->mtime,&hd->atime); } diff --git a/src/thirdparty/unrar/unpack50.cpp b/src/thirdparty/unrar/unpack50.cpp index d1188ee85..7821a3e6b 100644 --- a/src/thirdparty/unrar/unpack50.cpp +++ b/src/thirdparty/unrar/unpack50.cpp @@ -570,7 +570,7 @@ bool Unpack::ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTable else { ZeroCount+=2; - while (ZeroCount-- > 0 && I<sizeof(BitLength)/sizeof(BitLength[0])) + while (ZeroCount-- > 0 && I<ASIZE(BitLength)) BitLength[I++]=0; I--; } @@ -587,7 +587,7 @@ bool Unpack::ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTable { if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-5) if (!UnpReadBuf()) - return(false); + return false; int Number=DecodeNumber(Inp,&Tables.BD); if (Number<16) { @@ -633,12 +633,12 @@ bool Unpack::ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTable } } if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop) - return(false); + return false; MakeDecodeTables(&Table[0],&Tables.LD,NC); MakeDecodeTables(&Table[NC],&Tables.DD,DC); MakeDecodeTables(&Table[NC+DC],&Tables.LDD,LDC); MakeDecodeTables(&Table[NC+DC+LDC],&Tables.RD,RC); - return(true); + return true; } diff --git a/src/thirdparty/unrar/unpack50mt.cpp b/src/thirdparty/unrar/unpack50mt.cpp index 6015379cc..9925cf2b8 100644 --- a/src/thirdparty/unrar/unpack50mt.cpp +++ b/src/thirdparty/unrar/unpack50mt.cpp @@ -80,6 +80,10 @@ void Unpack::Unpack5MT(bool Solid) bool Done=false; while (!Done) { + // Data amount, which is guaranteed to fit block header and tables, + // so we can safely read them without additional checks. + const int TooSmallToProcess=1024; + int ReadSize=UnpIO->UnpRead(ReadBufMT+DataSize,(UNP_READ_SIZE_MT-DataSize)&~0xf); if (ReadSize<0) break; @@ -87,13 +91,14 @@ void Unpack::Unpack5MT(bool Solid) if (DataSize==0) break; + // First read chunk can be small if we are near the end of volume + // and we want it to fit block header and tables. + if (ReadSize>0 && DataSize<TooSmallToProcess) + continue; + bool BufferProcessed=false; while (BlockStart<DataSize && !Done) { - // Data amount, which is guaranteed to fit block header and tables, - // so we can safely read them without additional checks. - const int TooSmallToProcess=1024; - uint BlockNumber=0,BlockNumberMT=0; while (BlockNumber<MaxUserThreads*UNP_BLOCKS_PER_THREAD) { diff --git a/src/thirdparty/unrar/version.hpp b/src/thirdparty/unrar/version.hpp index 3a36f22b3..8518b5516 100644 --- a/src/thirdparty/unrar/version.hpp +++ b/src/thirdparty/unrar/version.hpp @@ -1,6 +1,6 @@ #define RARVER_MAJOR 5 -#define RARVER_MINOR 20 +#define RARVER_MINOR 21 #define RARVER_BETA 0 -#define RARVER_DAY 2 -#define RARVER_MONTH 12 -#define RARVER_YEAR 2014 +#define RARVER_DAY 15 +#define RARVER_MONTH 2 +#define RARVER_YEAR 2015 diff --git a/src/thirdparty/unrar/win32lnk.cpp b/src/thirdparty/unrar/win32lnk.cpp index f911be98e..b291056f0 100644 --- a/src/thirdparty/unrar/win32lnk.cpp +++ b/src/thirdparty/unrar/win32lnk.cpp @@ -40,23 +40,6 @@ bool CreateReparsePoint(CommandData *Cmd,const wchar *Name,FileHeader *hd) PrivSet=true; } - CreatePath(Name,true); - - // 'DirTarget' check is important for Unix symlinks to directories. - // Unix symlinks do not have their own 'directory' attribute. - if (hd->Dir || hd->DirTarget) - { - if (!CreateDirectory(Name,NULL)) - return false; - } - else - { - HANDLE hFile=CreateFile(Name,GENERIC_WRITE,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL); - if (hFile == INVALID_HANDLE_VALUE) - return false; - CloseHandle(hFile); - } - const DWORD BufSize=sizeof(REPARSE_DATA_BUFFER)+2*NM+1024; Array<byte> Buf(BufSize); REPARSE_DATA_BUFFER *rdb=(REPARSE_DATA_BUFFER *)&Buf[0]; @@ -79,6 +62,26 @@ bool CreateReparsePoint(CommandData *Cmd,const wchar *Name,FileHeader *hd) size_t PrintLength=wcslen(PrintName); bool AbsPath=WinPrefix; + if (!Cmd->AbsoluteLinks && (AbsPath || !IsRelativeSymlinkSafe(hd->FileName,hd->RedirName))) + return false; + + CreatePath(Name,true); + + // 'DirTarget' check is important for Unix symlinks to directories. + // Unix symlinks do not have their own 'directory' attribute. + if (hd->Dir || hd->DirTarget) + { + if (!CreateDirectory(Name,NULL)) + return false; + } + else + { + HANDLE hFile=CreateFile(Name,GENERIC_WRITE,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL); + if (hFile == INVALID_HANDLE_VALUE) + return false; + CloseHandle(hFile); + } + if (hd->RedirType==FSREDIR_JUNCTION) { |