diff options
Diffstat (limited to 'src/thirdparty/unrar/arcread.cpp')
-rw-r--r-- | src/thirdparty/unrar/arcread.cpp | 52 |
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); |