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/arcread.cpp')
-rw-r--r--src/thirdparty/unrar/arcread.cpp52
1 files changed, 43 insertions, 9 deletions
diff --git a/src/thirdparty/unrar/arcread.cpp b/src/thirdparty/unrar/arcread.cpp
index 047289b7a..146393872 100644
--- a/src/thirdparty/unrar/arcread.cpp
+++ b/src/thirdparty/unrar/arcread.cpp
@@ -53,9 +53,11 @@ size_t Archive::SearchBlock(HEADER_TYPE HeaderType)
size_t Archive::SearchSubBlock(const wchar *Type)
{
- size_t Size;
+ size_t Size,Count=0;
while ((Size=ReadHeader())!=0 && GetHeaderType()!=HEAD_ENDARC)
{
+ if ((++Count & 127)==0)
+ Wait();
if (GetHeaderType()==HEAD_SERVICE && SubHead.CmpName(Type))
return Size;
SeekToNext();
@@ -318,9 +320,8 @@ size_t Archive::ReadHeader15()
else
*hd->FileName=0;
- char AnsiName[NM];
- IntToExt(FileName,AnsiName,ASIZE(AnsiName));
- GetWideName(AnsiName,hd->FileName,hd->FileName,ASIZE(hd->FileName));
+ if (*hd->FileName==0)
+ ArcCharToWide(FileName,hd->FileName,ASIZE(hd->FileName),ACTW_OEM);
#ifndef SFX_MODULE
ConvertNameCase(hd->FileName);
@@ -784,7 +785,12 @@ size_t Archive::ReadHeader50()
uint CompInfo=(uint)Raw.GetV();
hd->Method=(CompInfo>>7) & 7;
- hd->UnpVer=CompInfo & 0x3f;
+
+ // "+ 50" to not mix with old RAR format algorithms. For example,
+ // we may need to use the compression algorithm 15 in the future,
+ // but it was already used in RAR 1.5 and Unpack needs to distinguish
+ // them.
+ hd->UnpVer=(CompInfo & 0x3f) + 50;
hd->HostOS=(byte)Raw.GetV();
size_t NameSize=(size_t)Raw.GetV();
@@ -915,7 +921,7 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
size_t NextPos=size_t(Raw->GetPos()+FieldSize);
uint64 FieldType=Raw->GetV();
- FieldSize=Raw->DataLeft(); // Field size without size and type fields.
+ FieldSize=int64(NextPos-Raw->GetPos()); // Field size without size and type fields.
if (bb->HeaderType==HEAD_MAIN)
{
@@ -982,6 +988,11 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
sha256_done(&ctx, Digest);
hd->UsePswCheck=memcmp(csum,Digest,SIZE_PSWCHECK_CSUM)==0;
+
+ // RAR 5.21 and earlier set PswCheck field in service records to 0
+ // even if UsePswCheck was present.
+ if (bb->HeaderType==HEAD_SERVICE && memcmp(hd->PswCheck,"\0\0\0\0\0\0\0\0",SIZE_PSWCHECK)==0)
+ hd->UsePswCheck=0;
}
hd->SaltSet=true;
hd->CryptMethod=CRYPT_RAR50;
@@ -1095,6 +1106,19 @@ void Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
break;
case FHEXTRA_SUBDATA:
{
+ // RAR 5.21 and earlier set FHEXTRA_SUBDATA size to 1 less than
+ // required. It did not hurt extraction, because UnRAR 5.21
+ // and earlier ignored this field and set FieldSize as data left
+ // in entire extra area. But now we set the correct field size
+ // and set FieldSize based on actual extra record size,
+ // so we need to adjust it for those older archives here.
+ // FHEXTRA_SUBDATA in those archives always belongs to HEAD_SERVICE
+ // and always is last in extra area. So since its size is by 1
+ // less than needed, we always have 1 byte left in extra area,
+ // which fact we use here to detect such archives.
+ if (bb->HeaderType==HEAD_SERVICE && Raw->Size()-NextPos==1)
+ FieldSize++;
+
hd->SubData.Alloc((size_t)FieldSize);
Raw->GetB(hd->SubData.Addr(0),(size_t)FieldSize);
}
@@ -1266,6 +1290,11 @@ void Archive::ConvertFileHeader(FileHeader *hd)
else
hd->FileAttr=0x20;
+#ifdef _WIN_ALL
+ if (hd->HSType==HSYS_UNIX) // Convert Unix, OS X and Android decomposed chracters to Windows precomposed.
+ ConvertToPrecomposed(hd->FileName,ASIZE(hd->FileName));
+#endif
+
for (wchar *s=hd->FileName;*s!=0;s++)
{
#ifdef _UNIX
@@ -1344,14 +1373,19 @@ bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
uiMsg(UIERROR_SUBHEADERUNKNOWN,FileName);
return false;
}
- UnpData->Alloc((size_t)SubHead.UnpSize);
- SubDataIO.SetUnpackToMemory(&(*UnpData)[0],(uint)SubHead.UnpSize);
+ if (UnpData==NULL)
+ SubDataIO.SetTestMode(true);
+ else
+ {
+ UnpData->Alloc((size_t)SubHead.UnpSize);
+ SubDataIO.SetUnpackToMemory(&(*UnpData)[0],(uint)SubHead.UnpSize);
+ }
}
if (SubHead.Encrypted)
if (Cmd->Password.IsSet())
SubDataIO.SetEncryption(false,SubHead.CryptMethod,&Cmd->Password,
SubHead.SaltSet ? SubHead.Salt:NULL,SubHead.InitV,
- SubHead.Lg2Count,SubHead.PswCheck,SubHead.HashKey);
+ SubHead.Lg2Count,SubHead.HashKey,SubHead.PswCheck);
else
return false;
SubDataIO.UnpHash.Init(SubHead.FileHash.Type,1);