Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/mpc-hc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/thirdparty/unrar')
-rw-r--r--src/thirdparty/unrar/archive.cpp2
-rw-r--r--src/thirdparty/unrar/archive.hpp4
-rw-r--r--src/thirdparty/unrar/arcread.cpp17
-rw-r--r--src/thirdparty/unrar/cmddata.cpp11
-rw-r--r--src/thirdparty/unrar/cmddata.hpp3
-rw-r--r--src/thirdparty/unrar/dll.rc10
-rw-r--r--src/thirdparty/unrar/extinfo.cpp35
-rw-r--r--src/thirdparty/unrar/extinfo.hpp1
-rw-r--r--src/thirdparty/unrar/extract.cpp51
-rw-r--r--src/thirdparty/unrar/filcreat.cpp1
-rw-r--r--src/thirdparty/unrar/file.cpp8
-rw-r--r--src/thirdparty/unrar/file.hpp2
-rw-r--r--src/thirdparty/unrar/filestr.cpp16
-rw-r--r--src/thirdparty/unrar/loclang.hpp2
-rw-r--r--src/thirdparty/unrar/options.hpp1
-rw-r--r--src/thirdparty/unrar/os.hpp2
-rw-r--r--src/thirdparty/unrar/pathfn.cpp8
-rw-r--r--src/thirdparty/unrar/pathfn.hpp1
-rw-r--r--src/thirdparty/unrar/strfn.cpp2
-rw-r--r--src/thirdparty/unrar/timefn.cpp2
-rw-r--r--src/thirdparty/unrar/uicommon.cpp7
-rw-r--r--src/thirdparty/unrar/uiconsole.cpp15
-rw-r--r--src/thirdparty/unrar/ulinks.cpp16
-rw-r--r--src/thirdparty/unrar/unpack50.cpp8
-rw-r--r--src/thirdparty/unrar/unpack50mt.cpp13
-rw-r--r--src/thirdparty/unrar/version.hpp8
-rw-r--r--src/thirdparty/unrar/win32lnk.cpp37
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(&lt);
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)
{