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:
authorXhmikosR <xhmikosr@users.sourceforge.net>2013-05-05 11:39:47 +0400
committerXhmikosR <xhmikosr@users.sourceforge.net>2013-05-06 02:56:22 +0400
commit00f8520475b119d50d40b8a4b2298f04afa821b9 (patch)
treee389319284c45b5305bb5156e1d8f8310849902a /src/thirdparty/unrar/archive.cpp
parentb18faab4208d8368d28c7b51afe5a73bbc90b05e (diff)
update unrar to v5.0.2
Diffstat (limited to 'src/thirdparty/unrar/archive.cpp')
-rw-r--r--src/thirdparty/unrar/archive.cpp234
1 files changed, 143 insertions, 91 deletions
diff --git a/src/thirdparty/unrar/archive.cpp b/src/thirdparty/unrar/archive.cpp
index b061e540a..b05eef462 100644
--- a/src/thirdparty/unrar/archive.cpp
+++ b/src/thirdparty/unrar/archive.cpp
@@ -7,48 +7,48 @@
Archive::Archive(RAROptions *InitCmd)
{
- Cmd=InitCmd==NULL ? &DummyCmd:InitCmd;
+ Cmd=NULL; // Just in case we'll have an exception in 'new' below.
+
+ DummyCmd=(InitCmd==NULL);
+ Cmd=DummyCmd ? (new RAROptions):InitCmd;
+
OpenShared=Cmd->OpenShared;
- OldFormat=false;
+ Format=RARFMT15;
Solid=false;
Volume=false;
MainComment=false;
Locked=false;
Signed=false;
- NotFirstVolume=false;
+ FirstVolume=false;
+ NewNumbering=false;
SFXSize=0;
LatestTime.Reset();
Protected=false;
Encrypted=false;
FailedHeaderDecryption=false;
- BrokenFileHeader=false;
+ BrokenHeader=false;
LastReadBlock=0;
CurBlockPos=0;
NextBlockPos=0;
- RecoveryPos=SIZEOF_MARKHEAD;
- RecoverySectors=-1;
+ RecoverySize=-1;
+ RecoveryPercent=-1;
- memset(&NewMhd,0,sizeof(NewMhd));
- NewMhd.HeadType=MAIN_HEAD;
- NewMhd.HeadSize=SIZEOF_NEWMHD;
- HeaderCRC=0;
+ memset(&MainHead,0,sizeof(MainHead));
+ memset(&CryptHead,0,sizeof(CryptHead));
+ memset(&EndArcHead,0,sizeof(EndArcHead));
+
+ VolNumber=0;
VolWrite=0;
AddingFilesSize=0;
AddingHeadersSize=0;
-#if !defined(SHELL_EXT) && !defined(RAR_NOCRYPT)
- *HeadersSalt=0;
- *SubDataSalt=0;
-#endif
*FirstVolumeName=0;
- *FirstVolumeNameW=0;
Splitting=false;
NewArchive=false;
SilentOpen=false;
-
}
@@ -66,37 +66,37 @@ void Archive::CheckArc(bool EnableBroken)
#if !defined(SHELL_EXT) && !defined(SFX_MODULE)
-void Archive::CheckOpen(const char *Name,const wchar *NameW)
+void Archive::CheckOpen(const wchar *Name)
{
- TOpen(Name,NameW);
+ TOpen(Name);
CheckArc(false);
}
#endif
-bool Archive::WCheckOpen(const char *Name,const wchar *NameW)
+bool Archive::WCheckOpen(const wchar *Name)
{
- if (!WOpen(Name,NameW))
- return(false);
+ if (!WOpen(Name))
+ return false;
if (!IsArchive(false))
{
#ifndef SHELL_EXT
Log(FileName,St(MNotRAR),FileName);
#endif
Close();
- return(false);
+ return false;
}
- return(true);
+ return true;
}
-ARCSIGN_TYPE Archive::IsSignature(const byte *D,size_t Size)
+RARFORMAT Archive::IsSignature(const byte *D,size_t Size)
{
- ARCSIGN_TYPE Type=ARCSIGN_NONE;
+ RARFORMAT Type=RARFMT_NONE;
if (Size>=1 && D[0]==0x52)
#ifndef SFX_MODULE
if (Size>=4 && D[1]==0x45 && D[2]==0x7e && D[3]==0x5e)
- Type=ARCSIGN_OLD;
+ Type=RARFMT14;
else
#endif
if (Size>=7 && D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07)
@@ -104,7 +104,14 @@ ARCSIGN_TYPE Archive::IsSignature(const byte *D,size_t Size)
// We check for non-zero last signature byte, so we can return
// a sensible warning in case we'll want to change the archive
// format sometimes in the future.
- Type=D[6]==0 ? ARCSIGN_CURRENT:ARCSIGN_FUTURE;
+ if (D[6]==0)
+ Type=RARFMT15;
+ else
+ if (D[6]==1)
+ Type=RARFMT50;
+ else
+ if (D[6]==2)
+ Type=RARFMT_FUTURE;
}
return Type;
}
@@ -113,24 +120,32 @@ ARCSIGN_TYPE Archive::IsSignature(const byte *D,size_t Size)
bool Archive::IsArchive(bool EnableBroken)
{
Encrypted=false;
+#ifdef USE_QOPEN
+ QOpen.Unload();
+#endif
+
+ // Important if we reuse Archive object and it has virtual QOpen
+ // file position not matching real. For example, for 'l -v volname'.
+ Seek(0,SEEK_SET);
+
#ifndef SFX_MODULE
if (IsDevice())
{
#ifndef SHELL_EXT
Log(FileName,St(MInvalidName),FileName);
#endif
- return(false);
+ return false;
}
#endif
- if (Read(MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD)
+ if (Read(MarkHead.Mark,SIZEOF_MARKHEAD3)!=SIZEOF_MARKHEAD3)
return(false);
SFXSize=0;
- ARCSIGN_TYPE Type;
- if ((Type=IsSignature(MarkHead.Mark,sizeof(MarkHead.Mark)))!=ARCSIGN_NONE)
+ RARFORMAT Type;
+ if ((Type=IsSignature(MarkHead.Mark,SIZEOF_MARKHEAD3))!=RARFMT_NONE)
{
- OldFormat=(Type==ARCSIGN_OLD);
- if (OldFormat)
+ Format=Type;
+ if (Format==RARFMT14)
Seek(0,SEEK_SET);
}
else
@@ -139,10 +154,10 @@ bool Archive::IsArchive(bool EnableBroken)
long CurPos=(long)Tell();
int ReadSize=Read(&Buffer[0],Buffer.Size()-16);
for (int I=0;I<ReadSize;I++)
- if (Buffer[I]==0x52 && (Type=IsSignature((byte *)&Buffer[I],ReadSize-I))!=ARCSIGN_NONE)
+ if (Buffer[I]==0x52 && (Type=IsSignature((byte *)&Buffer[I],ReadSize-I))!=RARFMT_NONE)
{
- OldFormat=(Type==ARCSIGN_OLD);
- if (OldFormat && I>0 && CurPos<28 && ReadSize>31)
+ Format=Type;
+ if (Format==RARFMT14 && I>0 && CurPos<28 && ReadSize>31)
{
char *D=&Buffer[28-CurPos];
if (D[0]!=0x52 || D[1]!=0x53 || D[2]!=0x46 || D[3]!=0x58)
@@ -150,50 +165,52 @@ bool Archive::IsArchive(bool EnableBroken)
}
SFXSize=CurPos+I;
Seek(SFXSize,SEEK_SET);
- if (!OldFormat)
- Read(MarkHead.Mark,SIZEOF_MARKHEAD);
+ if (Format==RARFMT15 || Format==RARFMT50)
+ Read(MarkHead.Mark,SIZEOF_MARKHEAD3);
break;
}
if (SFXSize==0)
return false;
}
- if (Type==ARCSIGN_FUTURE)
+ if (Format==RARFMT_FUTURE)
{
#if !defined(SHELL_EXT) && !defined(SFX_MODULE)
Log(FileName,St(MNewRarFormat));
#endif
return false;
}
- ReadHeader();
- SeekToNext();
-#ifndef SFX_MODULE
- if (OldFormat)
+ if (Format==RARFMT50) // RAR 5.0 signature is by one byte longer.
{
- NewMhd.Flags=OldMhd.Flags & 0x3f;
- NewMhd.HeadSize=OldMhd.HeadSize;
+ Read(MarkHead.Mark+SIZEOF_MARKHEAD3,1);
+ if (MarkHead.Mark[SIZEOF_MARKHEAD3]!=0)
+ return false;
+ MarkHead.HeadSize=SIZEOF_MARKHEAD5;
}
else
-#endif
+ MarkHead.HeadSize=SIZEOF_MARKHEAD3;
+
+ // Skip the archive encryption header if any and read the main header.
+ while (ReadHeader()!=0 && GetHeaderType()!=HEAD_MAIN)
+ SeekToNext();
+
+ // This check allows to make RS based recovery even if password is incorrect.
+ // But we should not do it for EnableBroken or we'll get 'not RAR archive'
+ // messages when extracting encrypted archives with wrong password.
+ if (FailedHeaderDecryption && !EnableBroken)
+ return false;
+
+ SeekToNext();
+ if (BrokenHeader)
{
- if (HeaderCRC!=NewMhd.HeadCRC)
- {
#ifndef SHELL_EXT
- Log(FileName,St(MLogMainHead));
+ Log(FileName,St(MMainHeaderBroken));
#endif
- Alarm();
- if (!EnableBroken)
- return(false);
- }
+ if (!EnableBroken)
+ return false;
}
- Volume=(NewMhd.Flags & MHD_VOLUME);
- Solid=(NewMhd.Flags & MHD_SOLID)!=0;
- MainComment=(NewMhd.Flags & MHD_COMMENT)!=0;
- Locked=(NewMhd.Flags & MHD_LOCK)!=0;
- Signed=(NewMhd.PosAV!=0);
- Protected=(NewMhd.Flags & MHD_PROTECT)!=0;
- Encrypted=(NewMhd.Flags & MHD_PASSWORD)!=0;
-
- if (NewMhd.EncryptVer>UNP_VER)
+
+/*
+ if (MainHead.EncryptVer>VER_UNPACK)
{
#ifdef RARDLL
Cmd->DllError=ERAR_UNKNOWN_FORMAT;
@@ -201,11 +218,13 @@ bool Archive::IsArchive(bool EnableBroken)
ErrHandler.SetErrorCode(RARX_WARNING);
#if !defined(SILENT) && !defined(SFX_MODULE)
Log(FileName,St(MUnknownMeth),FileName);
- Log(FileName,St(MVerRequired),NewMhd.EncryptVer/10,NewMhd.EncryptVer%10);
+ Log(FileName,St(MVerRequired),MainHead.EncryptVer/10,MainHead.EncryptVer%10);
#endif
#endif
return(false);
}
+*/
+
#ifdef RARDLL
// If callback function is not set, we cannot get the password,
// so we skip the initial header processing for encrypted header archive.
@@ -215,31 +234,37 @@ bool Archive::IsArchive(bool EnableBroken)
SilentOpen=true;
#endif
- // If not encrypted, we'll check it below.
- NotFirstVolume=Encrypted && (NewMhd.Flags & MHD_FIRSTVOLUME)==0;
+ MainComment=MainHead.CommentInHeader;
+#ifdef USE_QOPEN
+ if (MainHead.Locator && MainHead.QOpenOffset>0 && Cmd->QOpenMode!=QOPEN_NONE)
+ {
+ QOpen.Init(this,false);
+ QOpen.Load(MainHead.QOpenOffset);
+ }
+#endif
+
+ // If we process non-encrypted archive or can request a password,
+ // we set 'first volume' flag based on file attributes below.
+ // It is necessary for RAR 2.x archives, which did not have 'first volume'
+ // flag in main header.
if (!SilentOpen || !Encrypted)
{
SaveFilePos SavePos(*this);
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
- NotFirstVolume=false;
while (ReadHeader()!=0)
{
- int HeaderType=GetHeaderType();
- if (HeaderType==NEWSUB_HEAD)
+ HEADER_TYPE HeaderType=GetHeaderType();
+ if (HeaderType==HEAD_SERVICE)
{
if (SubHead.CmpName(SUBHEAD_TYPE_CMT))
MainComment=true;
- if ((SubHead.Flags & LHD_SPLIT_BEFORE) ||
- Volume && (NewMhd.Flags & MHD_FIRSTVOLUME)==0)
- NotFirstVolume=true;
+ FirstVolume=!SubHead.SplitBefore;
}
else
{
- if (HeaderType==FILE_HEAD && ((NewLhd.Flags & LHD_SPLIT_BEFORE)!=0 ||
- Volume && NewLhd.UnpVer>=29 && (NewMhd.Flags & MHD_FIRSTVOLUME)==0))
- NotFirstVolume=true;
+ FirstVolume=HeaderType==HEAD_FILE && !FileHead.SplitBefore;
break;
}
SeekToNext();
@@ -247,13 +272,10 @@ bool Archive::IsArchive(bool EnableBroken)
CurBlockPos=SaveCurBlockPos;
NextBlockPos=SaveNextBlockPos;
}
- if (!Volume || !NotFirstVolume)
- {
- strcpy(FirstVolumeName,FileName);
- wcscpy(FirstVolumeNameW,FileNameW);
- }
+ if (!Volume || FirstVolume)
+ wcscpy(FirstVolumeName,FileName);
- return(true);
+ return true;
}
@@ -265,20 +287,50 @@ void Archive::SeekToNext()
}
-#ifndef SFX_MODULE
-int Archive::GetRecoverySize(bool Required)
+
+
+
+
+// Calculate the block size including encryption fields and padding if any.
+uint Archive::FullHeaderSize(size_t Size)
{
- if (!Protected)
- return(0);
- if (RecoverySectors!=-1 || !Required)
- return(RecoverySectors);
- SaveFilePos SavePos(*this);
- Seek(SFXSize,SEEK_SET);
- SearchSubBlock(SUBHEAD_TYPE_RR);
- return(RecoverySectors);
+ if (Encrypted)
+ {
+ Size = ALIGN_VALUE(Size, CRYPT_BLOCK_SIZE); // Align to encryption block size.
+ if (Format == RARFMT50)
+ Size += SIZE_INITV;
+ else
+ Size += SIZE_SALT30;
+ }
+ return uint(Size);
}
-#endif
+#ifdef USE_QOPEN
+int Archive::Read(void *Data,size_t Size)
+{
+ size_t Result;
+ if (QOpen.Read(Data,Size,Result))
+ return (int)Result;
+ return File::Read(Data,Size);
+}
+
+
+void Archive::Seek(int64 Offset,int Method)
+{
+ if (!QOpen.Seek(Offset,Method))
+ File::Seek(Offset,Method);
+}
+
+
+int64 Archive::Tell()
+{
+ int64 QPos;
+ if (QOpen.Tell(&QPos))
+ return QPos;
+ return File::Tell();
+}
+#endif
+