mirror of
https://github.com/LisherSong/ps5-web-file-manager.git
synced 2026-10-06 10:00:24 +02:00
New RAR engine for v1.9, replacing dmc_unrar 1.7.0. dmc_unrar only
dispatches RAR5 compression version 5 (switch(file->version) case
0x5000); WinRAR 6.x/7.x writes version 6 -> DMC_UNRAR_FILE_UNSUPPORTED_VERSION
-> user-facing "corrupt archive" on real v6 archives (diagnosed 2026-09-05
from a v6:8M:m0:m3 test file). unrar 7.20.1 natively supports v6,
encrypted and multi-volume RAR.
Vendored into third_party/unrar7/ (new dir) so the tree stays buildable
while src/rar_extract.c still references the dmc facade. Contents are a
verbatim copy of opello/unrar @97e1780 (159 files, v7.20.1) plus two
project files:
- unrar_c_api.h (C facade shim: platform types + dll.hpp re-export)
- VENDORED.md (source pin, build model, license notes)
Build model verified on host (MinGW g++ 16.2, Windows):
- all 49 UnRARDll.vcxproj sources compile with
-std=c++17 -DRARDLL -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
- links + runs: RARGetDllVersion() = 9 (smoke binary in .build/, ignored)
- Windows link additionally needs -lpowrprof
License: UnRAR freeware license (not GPL) - free to use for handling RAR
archives; cannot be used to build a RAR-compatible archiver. THIRD_PARTY_NOTICES
update lands with the engine swap commit.
Next (v1.9 work items): engine swap in rar_extract.c, Makefile .cpp rules,
fixtures + host tests, frontend password/multi-volume, then ELF build.
188 lines
4.8 KiB
C++
188 lines
4.8 KiB
C++
static bool IsAnsiEscComment(const wchar *Data,size_t Size);
|
|
|
|
bool Archive::GetComment(std::wstring &CmtData)
|
|
{
|
|
if (!MainComment)
|
|
return false;
|
|
int64 SavePos=Tell();
|
|
bool Success=DoGetComment(CmtData);
|
|
Seek(SavePos,SEEK_SET);
|
|
return Success;
|
|
}
|
|
|
|
|
|
bool Archive::DoGetComment(std::wstring &CmtData)
|
|
{
|
|
#ifndef SFX_MODULE
|
|
uint CmtLength;
|
|
if (Format==RARFMT14)
|
|
{
|
|
Seek(SFXSize+SIZEOF_MAINHEAD14,SEEK_SET);
|
|
CmtLength=GetByte();
|
|
CmtLength+=(GetByte()<<8);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if (MainHead.CommentInHeader)
|
|
{
|
|
// Old style (RAR 2.9) archive comment embedded into the main
|
|
// archive header.
|
|
Seek(SFXSize+SIZEOF_MARKHEAD3+SIZEOF_MAINHEAD3,SEEK_SET);
|
|
if (!ReadHeader() || GetHeaderType()!=HEAD3_CMT)
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
// Current (RAR 3.0+) version of archive comment.
|
|
Seek(GetStartPos(),SEEK_SET);
|
|
if (SearchSubBlock(SUBHEAD_TYPE_CMT)!=0)
|
|
if (ReadCommentData(CmtData))
|
|
return true;
|
|
else
|
|
uiMsg(UIERROR_CMTBROKEN,FileName);
|
|
return false;
|
|
}
|
|
#ifndef SFX_MODULE
|
|
// Old style (RAR 2.9) comment header embedded into the main
|
|
// archive header.
|
|
if (BrokenHeader || CommHead.HeadSize<SIZEOF_COMMHEAD)
|
|
{
|
|
uiMsg(UIERROR_CMTBROKEN,FileName);
|
|
return false;
|
|
}
|
|
CmtLength=CommHead.HeadSize-SIZEOF_COMMHEAD;
|
|
#endif
|
|
}
|
|
#ifndef SFX_MODULE
|
|
if (Format==RARFMT14 && MainHead.PackComment || Format!=RARFMT14 && CommHead.Method!=0x30)
|
|
{
|
|
if (Format!=RARFMT14 && (CommHead.UnpVer < 15 || CommHead.UnpVer > VER_UNPACK || CommHead.Method > 0x35))
|
|
return false;
|
|
ComprDataIO DataIO;
|
|
DataIO.SetTestMode(true);
|
|
uint UnpCmtLength;
|
|
if (Format==RARFMT14)
|
|
{
|
|
#ifdef RAR_NOCRYPT
|
|
return false;
|
|
#else
|
|
UnpCmtLength=GetByte();
|
|
UnpCmtLength+=(GetByte()<<8);
|
|
if (CmtLength<2)
|
|
return false;
|
|
CmtLength-=2;
|
|
DataIO.SetCmt13Encryption();
|
|
CommHead.UnpVer=15;
|
|
#endif
|
|
}
|
|
else
|
|
UnpCmtLength=CommHead.UnpSize;
|
|
DataIO.SetFiles(this,NULL);
|
|
DataIO.EnableShowProgress(false);
|
|
DataIO.SetPackedSizeToRead(CmtLength);
|
|
DataIO.UnpHash.Init(HASH_CRC32,1);
|
|
DataIO.SetNoFileHeader(true); // this->FileHead is not filled yet.
|
|
|
|
Unpack CmtUnpack(&DataIO);
|
|
CmtUnpack.Init(0x10000,false);
|
|
CmtUnpack.SetDestSize(UnpCmtLength);
|
|
CmtUnpack.DoUnpack(CommHead.UnpVer,false);
|
|
|
|
if (Format!=RARFMT14 && (DataIO.UnpHash.GetCRC32()&0xffff)!=CommHead.CommCRC)
|
|
{
|
|
uiMsg(UIERROR_CMTBROKEN,FileName);
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
byte *UnpData;
|
|
size_t UnpDataSize;
|
|
DataIO.GetUnpackedData(&UnpData,&UnpDataSize);
|
|
if (UnpDataSize>0)
|
|
{
|
|
#ifdef _WIN_ALL
|
|
// If we ever decide to extend it to Android, we'll need to alloc
|
|
// 4x memory for OEM to UTF-8 output here.
|
|
OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize);
|
|
#endif
|
|
std::string UnpStr((char*)UnpData,UnpDataSize);
|
|
CharToWide(UnpStr,CmtData);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (CmtLength==0)
|
|
return false;
|
|
std::vector<byte> CmtRaw(CmtLength);
|
|
int ReadSize=Read(CmtRaw.data(),CmtLength);
|
|
if (ReadSize>=0 && (uint)ReadSize<CmtLength) // Comment is shorter than declared.
|
|
{
|
|
CmtLength=ReadSize;
|
|
CmtRaw.resize(CmtLength);
|
|
}
|
|
|
|
if (Format!=RARFMT14 && CommHead.CommCRC!=(~CRC32(0xffffffff,&CmtRaw[0],CmtLength)&0xffff))
|
|
{
|
|
uiMsg(UIERROR_CMTBROKEN,FileName);
|
|
return false;
|
|
}
|
|
// CmtData.resize(CmtLength+1);
|
|
CmtRaw.push_back(0);
|
|
#ifdef _WIN_ALL
|
|
// If we ever decide to extend it to Android, we'll need to alloc
|
|
// 4x memory for OEM to UTF-8 output here.
|
|
OemToCharA((char *)CmtRaw.data(),(char *)CmtRaw.data());
|
|
#endif
|
|
CharToWide((const char *)CmtRaw.data(),CmtData);
|
|
// CmtData->resize(wcslen(CmtData->data()));
|
|
}
|
|
#endif
|
|
return CmtData.size() > 0;
|
|
}
|
|
|
|
|
|
bool Archive::ReadCommentData(std::wstring &CmtData)
|
|
{
|
|
std::vector<byte> CmtRaw;
|
|
if (!ReadSubData(&CmtRaw,NULL,false))
|
|
return false;
|
|
size_t CmtSize=CmtRaw.size();
|
|
CmtRaw.push_back(0);
|
|
// CmtData->resize(CmtSize+1);
|
|
if (Format==RARFMT50)
|
|
UtfToWide((char *)CmtRaw.data(),CmtData);
|
|
else
|
|
if ((SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE)!=0)
|
|
{
|
|
CmtData=RawToWide(CmtRaw);
|
|
}
|
|
else
|
|
{
|
|
CharToWide((const char *)CmtRaw.data(),CmtData);
|
|
}
|
|
// CmtData->resize(wcslen(CmtData->data())); // Set buffer size to actual comment length.
|
|
return true;
|
|
}
|
|
|
|
|
|
void Archive::ViewComment()
|
|
{
|
|
if (Cmd->DisableComment)
|
|
return;
|
|
std::wstring CmtBuf;
|
|
if (GetComment(CmtBuf)) // In GUI too, so "Test" command detects broken comments.
|
|
{
|
|
size_t CmtSize=CmtBuf.size();
|
|
auto EndPos=CmtBuf.find(0x1A);
|
|
if (EndPos!=std::wstring::npos)
|
|
CmtSize=EndPos;
|
|
mprintf(St(MArcComment));
|
|
mprintf(L":\n");
|
|
OutComment(CmtBuf);
|
|
}
|
|
}
|
|
|
|
|