174 lines
4.6 KiB
C++
174 lines
4.6 KiB
C++
static bool IsAnsiEscComment(const wchar *Data,size_t Size);
|
|
|
|
bool Archive::GetComment(Array<wchar> *CmtData)
|
|
{
|
|
if (!MainComment)
|
|
return false;
|
|
SaveFilePos SavePos(*this);
|
|
|
|
#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);
|
|
return SearchSubBlock(SUBHEAD_TYPE_CMT)!=0 && ReadCommentData(CmtData);
|
|
}
|
|
#ifndef SFX_MODULE
|
|
// Old style (RAR 2.9) comment header embedded into the main
|
|
// archive header.
|
|
if (BrokenHeader)
|
|
{
|
|
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);
|
|
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);
|
|
#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
|
|
CmtData->Alloc(UnpDataSize+1);
|
|
memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar));
|
|
CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size());
|
|
CmtData->Alloc(wcslen(CmtData->Addr(0)));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (CmtLength==0)
|
|
return false;
|
|
Array<byte> CmtRaw(CmtLength);
|
|
int ReadSize=Read(&CmtRaw[0],CmtLength);
|
|
if (ReadSize>=0 && (uint)ReadSize<CmtLength) // Comment is shorter than declared.
|
|
{
|
|
CmtLength=ReadSize;
|
|
CmtRaw.Alloc(CmtLength);
|
|
}
|
|
|
|
if (Format!=RARFMT14 && CommHead.CommCRC!=(~CRC32(0xffffffff,&CmtRaw[0],CmtLength)&0xffff))
|
|
{
|
|
uiMsg(UIERROR_CMTBROKEN,FileName);
|
|
return false;
|
|
}
|
|
CmtData->Alloc(CmtLength+1);
|
|
CmtRaw.Push(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[0],(char *)&CmtRaw[0]);
|
|
#endif
|
|
CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
|
|
CmtData->Alloc(wcslen(CmtData->Addr(0)));
|
|
}
|
|
#endif
|
|
return CmtData->Size() > 0;
|
|
}
|
|
|
|
|
|
bool Archive::ReadCommentData(Array<wchar> *CmtData)
|
|
{
|
|
Array<byte> CmtRaw;
|
|
if (!ReadSubData(&CmtRaw,NULL))
|
|
return false;
|
|
size_t CmtSize=CmtRaw.Size();
|
|
CmtRaw.Push(0);
|
|
CmtData->Alloc(CmtSize+1);
|
|
if (Format==RARFMT50)
|
|
UtfToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
|
|
else
|
|
if ((SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE)!=0)
|
|
{
|
|
RawToWide(&CmtRaw[0],CmtData->Addr(0),CmtSize/2);
|
|
(*CmtData)[CmtSize/2]=0;
|
|
|
|
}
|
|
else
|
|
{
|
|
CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
|
|
}
|
|
CmtData->Alloc(wcslen(CmtData->Addr(0))); // Set buffer size to actual comment length.
|
|
return true;
|
|
}
|
|
|
|
|
|
void Archive::ViewComment()
|
|
{
|
|
if (Cmd->DisableComment)
|
|
return;
|
|
Array<wchar> CmtBuf;
|
|
if (GetComment(&CmtBuf)) // In GUI too, so "Test" command detects broken comments.
|
|
{
|
|
size_t CmtSize=CmtBuf.Size();
|
|
wchar *ChPtr=wcschr(&CmtBuf[0],0x1A);
|
|
if (ChPtr!=NULL)
|
|
CmtSize=ChPtr-&CmtBuf[0];
|
|
mprintf(L"\n");
|
|
OutComment(&CmtBuf[0],CmtSize);
|
|
}
|
|
}
|
|
|
|
|