This commit is contained in:
Igor Pavlov
2018-12-30 14:01:47 +00:00
committed by Kornel
parent 18dc2b4161
commit 5b2a99c548
113 changed files with 1805 additions and 932 deletions

View File

@@ -236,6 +236,13 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
prop = v;
break;
}
case kpidReadOnly:
{
if (!_db.CanUpdate())
prop = true;
break;
}
}
prop.Detach(value);
return S_OK;

View File

@@ -267,6 +267,9 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
db = &_db;
#endif
if (db && !db->CanUpdate())
return E_NOTIMPL;
/*
CMyComPtr<IArchiveGetRawProps> getRawProps;
updateCallback->QueryInterface(IID_IArchiveGetRawProps, (void **)&getRawProps);

View File

@@ -1465,21 +1465,24 @@ void CDbEx::FillLinks()
}
if (indexInFolder != 0)
{
folderIndex++;
/*
if (indexInFolder != 0)
ThrowIncorrect();
*/
// 18.06
ThereIsHeaderError = true;
// ThrowIncorrect();
}
for (;;)
{
if (folderIndex >= NumFolders)
return;
FolderStartFileIndex[folderIndex] = i;
/*
if (NumUnpackStreamsVector[folderIndex] != 0)
ThrowIncorrect();;
*/
{
// 18.06
ThereIsHeaderError = true;
// ThrowIncorrect();
}
folderIndex++;
}
}

View File

@@ -257,6 +257,16 @@ struct CDbEx: public CDatabase
PhySize = 0;
}
bool CanUpdate() const
{
if (ThereIsHeaderError
|| UnexpectedEnd
|| StartHeaderWasRecovered
|| UnsupportedFeatureError)
return false;
return true;
}
void FillLinks();
UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const

View File

@@ -124,13 +124,13 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
#define ELF_DATA_2LSB 1
#define ELF_DATA_2MSB 2
static UInt16 Get16(const Byte *p, Bool be) { if (be) return (UInt16)GetBe16(p); return (UInt16)GetUi16(p); }
static UInt32 Get32(const Byte *p, Bool be) { if (be) return GetBe32(p); return GetUi32(p); }
// static UInt64 Get64(const Byte *p, Bool be) { if (be) return GetBe64(p); return GetUi64(p); }
static UInt16 Get16(const Byte *p, BoolInt be) { if (be) return (UInt16)GetBe16(p); return (UInt16)GetUi16(p); }
static UInt32 Get32(const Byte *p, BoolInt be) { if (be) return GetBe32(p); return GetUi32(p); }
// static UInt64 Get64(const Byte *p, BoolInt be) { if (be) return GetBe64(p); return GetUi64(p); }
static int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode)
{
Bool /* is32, */ be;
BoolInt /* is32, */ be;
UInt32 filterId;
if (size < 512 || buf[6] != 1) /* ver */
@@ -200,7 +200,7 @@ static unsigned Parse_MACH(const Byte *buf, size_t size, CFilterMode *filterMode
if (size < 512)
return 0;
Bool /* mode64, */ be;
BoolInt /* mode64, */ be;
switch (GetUi32(buf))
{
case MACH_SIG_BE_32: /* mode64 = False; */ be = True; break;
@@ -239,7 +239,7 @@ static unsigned Parse_MACH(const Byte *buf, size_t size, CFilterMode *filterMode
#define RIFF_SIG 0x46464952
static Bool Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode)
static BoolInt Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode)
{
UInt32 subChunkSize, pos;
if (size < 0x2C)
@@ -285,7 +285,7 @@ static Bool Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode)
return False;
}
static Bool ParseFile(const Byte *buf, size_t size, CFilterMode *filterMode)
static BoolInt ParseFile(const Byte *buf, size_t size, CFilterMode *filterMode)
{
filterMode->Id = 0;
filterMode->Delta = 0;
@@ -894,7 +894,7 @@ HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMo
// RINOK(Callback->SetOperationResult2(index, NUpdate::NOperationResult::kOK));
if (result == S_OK)
{
Bool parseRes = ParseFile(Buffer, size, &filterModeTemp);
BoolInt parseRes = ParseFile(Buffer, size, &filterModeTemp);
if (parseRes && filterModeTemp.Delta == 0)
{
filterModeTemp.SetDelta();
@@ -1648,6 +1648,9 @@ HRESULT Update(
for (CNum fi = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fi++)
{
if (fi >= db->Files.Size())
return E_FAIL;
const CFileItem &file = db->Files[fi];
if (file.HasStream)
{

View File

@@ -170,8 +170,8 @@ static bool OctalToNumber32(const char *s, unsigned size, UInt32 &res)
res = 0;
char sz[32];
size = RemoveTailSpaces(sz, s, size);
if (size == 0)
return true; // some items doesn't contaion any numbers
if (size == 0 || strcmp(sz, "-1") == 0)
return true; // some items don't contain any numbers
const char *end;
UInt64 res64 = ConvertOctStringToUInt64(sz, &end);
if ((unsigned)(end - sz) != size)
@@ -185,8 +185,8 @@ static bool DecimalToNumber(const char *s, unsigned size, UInt64 &res)
res = 0;
char sz[32];
size = RemoveTailSpaces(sz, s, size);
if (size == 0)
return true; // some items doesn't contaion any numbers
if (size == 0 || strcmp(sz, "-1") == 0)
return true; // some items don't contain any numbers
const char *end;
res = ConvertStringToUInt64(sz, &end);
return ((unsigned)(end - sz) == size);

View File

@@ -366,7 +366,13 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return E_INVALIDARG;
size = prop.uhVal.QuadPart;
}
return UpdateArchive(size, outStream, _props, updateCallback);
CMethodProps props2 = _props;
#ifndef _7ZIP_ST
props2.AddProp_NumThreads(_props._numThreads);
#endif
return UpdateArchive(size, outStream, props2, updateCallback);
}
if (indexInArchive != 0)

View File

@@ -91,6 +91,7 @@ HRESULT CCoder::CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPa
{
CMyComPtr<ICompressGetInStreamProcessedSize2> getInStreamProcessedSize2;
Coder2.QueryInterface(IID_ICompressGetInStreamProcessedSize2, (void **)&getInStreamProcessedSize2);
if (getInStreamProcessedSize2)
FOR_VECTOR (i, PackSizePointers)
{
if (!PackSizePointers[i])

View File

@@ -788,9 +788,21 @@ HRESULT CHandler::Open2(IInStream *stream)
if (headSize != RSRC_HEAD_SIZE
|| footerOffset >= rsrcPair.Len
|| mainDataSize >= rsrcPair.Len
|| footerOffset + footerSize != rsrcPair.Len
|| footerOffset < mainDataSize
|| footerOffset != headSize + mainDataSize)
return S_FALSE;
const UInt32 footerEnd = footerOffset + footerSize;
if (footerEnd != rsrcPair.Len)
{
// there is rare case dmg example, where there are 4 additional bytes
UInt64 rem = rsrcPair.Len - footerOffset;
if (rem < footerSize
|| rem - footerSize != 4
|| Get32(p + footerEnd) != 0)
return S_FALSE;
}
if (footerSize < 16)
return S_FALSE;
if (memcmp(p, p + footerOffset, 16) != 0)

View File

@@ -1596,6 +1596,17 @@ STDMETHODIMP CHandler::Close()
}
static void ChangeSeparatorsInName(char *s, unsigned num)
{
for (unsigned i = 0; i < num; i++)
{
char c = s[i];
if (c == CHAR_PATH_SEPARATOR || c == '/')
s[i] = '_';
}
}
void CHandler::GetPath(unsigned index, AString &s) const
{
s.Empty();
@@ -1612,6 +1623,8 @@ void CHandler::GetPath(unsigned index, AString &s) const
if (!s.IsEmpty())
s.InsertAtFront(CHAR_PATH_SEPARATOR);
s.Insert(0, item.Name);
// 18.06
ChangeSeparatorsInName(s.GetBuf(), item.Name.Len());
if (item.ParentNode == k_INODE_ROOT)
return;

View File

@@ -161,7 +161,8 @@ bool CHeader::Parse(const Byte *p)
return false;
// we also support images that contain 0 in offset field.
bool isOkOffset = (codeOffset == 0 || (p[0] == 0xEB && p[1] == 0));
bool isOkOffset = (codeOffset == 0)
|| (codeOffset == (p[0] == 0xEB ? 2 : 3));
UInt16 numRootDirEntries = Get16(p + 17);
if (numRootDirEntries == 0)

View File

@@ -419,7 +419,13 @@ void CDatabase::GetItemPath(unsigned index, NWindows::NCOM::CPropVariant &path)
const wchar_t *src = (const wchar_t *)*s;
wchar_t *dest = p + len;
for (unsigned j = 0; j < curLen; j++)
dest[j] = src[j];
{
wchar_t c = src[j];
// 18.06
if (c == CHAR_PATH_SEPARATOR || c == '/')
c = '_';
dest[j] = c;
}
if (len == 0)
break;

View File

@@ -131,13 +131,7 @@ HRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,
if (header.FilterID > 1)
return E_NOTIMPL;
{
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
_lzmaDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
if (!setDecoderProperties)
return E_NOTIMPL;
RINOK(setDecoderProperties->SetDecoderProperties2(header.LzmaProps, 5));
}
RINOK(_lzmaDecoderSpec->SetDecoderProperties2(header.LzmaProps, 5));
bool filteredMode = (header.FilterID == 1);
@@ -357,24 +351,54 @@ API_FUNC_static_IsArc IsArc_Lzma86(const Byte *p, size_t size)
}
}
STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *)
{
Close();
const UInt32 kBufSize = 1 + 5 + 8 + 2;
const unsigned headerSize = GetHeaderSize();
const UInt32 kBufSize = 1 << 7;
Byte buf[kBufSize];
RINOK(ReadStream_FALSE(inStream, buf, kBufSize));
size_t processedSize = kBufSize;
RINOK(ReadStream(inStream, buf, &processedSize));
if (processedSize < headerSize + 2)
return S_FALSE;
if (!_header.Parse(buf, _lzma86))
return S_FALSE;
const Byte *start = buf + GetHeaderSize();
const Byte *start = buf + headerSize;
if (start[0] != 0 /* || (start[1] & 0x80) != 0 */ ) // empty stream with EOS is not 0x80
return S_FALSE;
RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize));
if (_packSize >= 24 && _header.Size == 0 && _header.FilterID == 0 && _header.LzmaProps[0] == 0)
SizeT srcLen = processedSize - headerSize;
if (srcLen > 10
&& _header.Size == 0
// && _header.FilterID == 0
&& _header.LzmaProps[0] == 0
)
return S_FALSE;
CDecoder state;
const UInt32 outLimit = 1 << 11;
Byte outBuf[outLimit];
SizeT outSize = outLimit;
if (outSize > _header.Size)
outSize = (SizeT)_header.Size;
SizeT destLen = outSize;
ELzmaStatus status;
SRes res = LzmaDecode(outBuf, &destLen, start, &srcLen,
_header.LzmaProps, 5, LZMA_FINISH_ANY,
&status, &g_Alloc);
if (res != SZ_OK)
if (res != SZ_ERROR_INPUT_EOF)
return S_FALSE;
_isArc = true;
_stream = inStream;
_seqStream = inStream;

View File

@@ -2445,23 +2445,24 @@ void CInArchive::DetectNsisType(const CBlockHeader &bh, const Byte *p)
bool strongPark = false;
bool strongNsis = false;
if (NumStringChars > 2)
{
const Byte *strData = _data + _stringsPos;
if (IsUnicode)
{
UInt32 num = NumStringChars;
UInt32 num = NumStringChars - 2;
for (UInt32 i = 0; i < num; i++)
{
if (Get16(strData + i * 2) == 0)
{
unsigned c2 = Get16(strData + 2 + i * 2);
// it can be TXT/RTF with marker char (1 or 2). so we must check next char
// if (c2 <= NS_3_CODE_SKIP && c2 != NS_3_CODE_SHELL)
if (c2 == NS_3_CODE_VAR)
{
// it can be TXT/RTF string with marker char (1 or 2). so we must next char
// const wchar_t *p2 = (const wchar_t *)(strData + i * 2 + 2);
// p2 = p2;
if ((Get16(strData + 3 + i * 2) & 0x8000) != 0)
// 18.06: fixed: is it correct ?
// if ((Get16(strData + 3 + i * 2) & 0x8000) != 0)
if ((Get16(strData + 4 + i * 2) & 0x8080) == 0x8080)
{
NsisType = k_NsisType_Nsis3;
strongNsis = true;
@@ -2478,7 +2479,7 @@ void CInArchive::DetectNsisType(const CBlockHeader &bh, const Byte *p)
}
else
{
UInt32 num = NumStringChars;
UInt32 num = NumStringChars - 2;
for (UInt32 i = 0; i < num; i++)
{
if (strData[i] == 0)

View File

@@ -1475,6 +1475,21 @@ void CDatabase::ClearAndClose()
InStream.Release();
}
static void CopyName(wchar_t *dest, const wchar_t *src)
{
for (;;)
{
wchar_t c = *src++;
// 18.06
if (c == '\\' || c == '/')
c = '_';
*dest++ = c;
if (c == 0)
return;
}
}
void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
{
const CItem *item = &Items[index];
@@ -1492,7 +1507,7 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
wchar_t *s = path.AllocBstr(data.Name.Len() + 1);
s[0] = L':';
if (!data.Name.IsEmpty())
MyStringCopy(s + 1, data.Name.GetRawPtr());
CopyName(s + 1, data.Name.GetRawPtr());
return;
}
@@ -1541,7 +1556,7 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
if (!name.IsEmpty())
{
size -= name.Len();
MyStringCopy(s + size, name.GetRawPtr());
CopyName(s + size, name.GetRawPtr());
}
s[--size] = ':';
needColon = true;
@@ -1551,7 +1566,7 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
const UString2 &name = rec.FileNames[item->NameIndex].Name;
unsigned len = name.Len();
if (len != 0)
MyStringCopy(s + size - len, name.GetRawPtr());
CopyName(s + size - len, name.GetRawPtr());
if (needColon)
s[size] = ':';
size -= len;
@@ -1575,7 +1590,7 @@ void CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const
if (len != 0)
{
size -= len;
MyStringCopy(s + size, name.GetRawPtr());
CopyName(s + size, name.GetRawPtr());
}
s[size + len] = WCHAR_PATH_SEPARATOR;
continue;

View File

@@ -1000,7 +1000,7 @@ bool CInArchive::ReadFileHeader(const CHeader &header, CItem &item)
struct CLinkFile
{
unsigned Index;
unsigned NumLinks;
unsigned NumLinks; // the number of links to Data
CByteBuffer Data;
HRESULT Res;
bool crcOK;
@@ -1015,7 +1015,7 @@ struct CUnpacker
CMyComPtr<ICompressCoder> copyCoder;
CMyComPtr<ICompressCoder> LzCoders[2];
bool NeedClearSolid[2];
bool SolidAllowed;
CFilterCoder *filterStreamSpec;
CMyComPtr<ISequentialInStream> filterStream;
@@ -1032,7 +1032,7 @@ struct CUnpacker
CLinkFile *linkFile;
CUnpacker(): linkFile(NULL) { NeedClearSolid[0] = NeedClearSolid[1] = true; }
CUnpacker(): linkFile(NULL) { SolidAllowed = false; }
HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, bool isSolid, bool &wrongPassword);
@@ -1142,7 +1142,9 @@ HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSiz
if (method > kLzMethodMax)
return E_NOTIMPL;
if (linkFile && !lastItem.Is_UnknownSize())
bool needBuf = (linkFile && linkFile->NumLinks != 0);
if (needBuf && !lastItem.Is_UnknownSize())
{
size_t dataSize = (size_t)lastItem.Size;
if (dataSize != lastItem.Size)
@@ -1167,15 +1169,15 @@ HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSiz
ICompressCoder *commonCoder = (method == 0) ? copyCoder : LzCoders[item.IsService() ? 1 : 0];
outStreamSpec->SetStream(realOutStream);
outStreamSpec->Init(lastItem, (linkFile ? (Byte *)linkFile->Data : NULL));
NeedClearSolid[item.IsService() ? 1 : 0] = false;
outStreamSpec->Init(lastItem, (needBuf ? (Byte *)linkFile->Data : NULL));
HRESULT res = S_OK;
if (packSize != 0 || lastItem.Is_UnknownSize() || lastItem.Size != 0)
{
res = commonCoder->Code(inStream, outStream, &packSize,
lastItem.Is_UnknownSize() ? NULL : &lastItem.Size, progress);
if (!item.IsService())
SolidAllowed = true;
}
else
{
@@ -1210,7 +1212,9 @@ HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSiz
{
linkFile->Res = res;
linkFile->crcOK = isCrcOK;
if (!lastItem.Is_UnknownSize() && processedSize != lastItem.Size)
if (needBuf
&& !lastItem.Is_UnknownSize()
&& processedSize != lastItem.Size)
linkFile->Data.ChangeSize_KeepData((size_t)processedSize, (size_t)processedSize);
}
@@ -2578,6 +2582,15 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
const Byte kStatus_Skip = 1 << 1;
const Byte kStatus_Link = 1 << 2;
/*
In original RAR:
1) service streams are not allowed to be solid,
and solid flag must be ignored for service streams.
2) If RAR creates new solid block and first file in solid block is Link file,
then it can clear solid flag for Link file and
clear solid flag for first non-Link file after Link file.
*/
CObjectVector<CLinkFile> linkFiles;
{
@@ -2603,13 +2616,15 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (ref.Link >= 0)
{
if (!testMode)
// 18.06 fixed: we use links for Test mode too
// if (!testMode)
{
if ((unsigned)ref.Link < index)
{
const CRefItem &linkRef = _refs[(unsigned)ref.Link];
const CItem &linkItem = _items[linkRef.Item];
if (linkItem.IsSolid() && linkItem.Size <= k_CopyLinkFile_MaxSize)
if (linkItem.IsSolid())
if (testMode || linkItem.Size <= k_CopyLinkFile_MaxSize)
{
if (extractStatuses[(unsigned)ref.Link] == 0)
{
@@ -2664,19 +2679,25 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
unsigned solidLimit = 0;
FOR_VECTOR(i, _refs)
FOR_VECTOR (i, _refs)
{
if ((extractStatuses[i] & kStatus_Link) == 0)
continue;
// We use CLinkFile for testMode too.
// So we can show errors for copy files.
// if (!testMode)
{
CLinkFile &linkFile = linkFiles.AddNew();
linkFile.Index = i;
}
const CItem &item = _items[_refs[i].Item];
/*
if (item.IsService())
continue;
*/
CLinkFile &linkFile = linkFiles.AddNew();
linkFile.Index = i;
if (item.IsSolid())
{
unsigned j = i;
@@ -2707,6 +2728,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
solidLimit = i + 1;
}
if (!testMode)
for (UInt32 t = 0; t < numItems; t++)
{
unsigned index = allFilesMode ? t : indices[t];
@@ -2748,7 +2770,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
// bool needClearSolid = true;
FOR_VECTOR(i, _refs)
FOR_VECTOR (i, _refs)
{
if (extractStatuses[i] == 0)
continue;
@@ -2761,15 +2783,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CMyComPtr<ISequentialOutStream> realOutStream;
// isExtract means that we don't skip that item. So we need read data.
bool isExtract = ((extractStatuses[i] & kStatus_Extract) != 0);
Int32 askMode =
((extractStatuses[i] & kStatus_Extract) != 0) ? (testMode ?
isExtract ? (testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract) :
NExtract::NAskMode::kSkip;
unpacker.linkFile = NULL;
if (((extractStatuses[i] & kStatus_Link) != 0))
// if (!testMode)
if ((extractStatuses[i] & kStatus_Link) != 0)
{
int bufIndex = FindLinkBuf(linkFiles, i);
if (bufIndex < 0)
@@ -2791,13 +2817,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
bool isSolid;
bool isSolid = false;
if (!item->IsService())
{
bool &needClearSolid = unpacker.NeedClearSolid[item->IsService() ? 1 : 0];
isSolid = (item->IsSolid() && !needClearSolid);
if (item->IsService())
isSolid = false;
needClearSolid = !item->IsSolid();
if (item->IsSolid())
isSolid = unpacker.SolidAllowed;
unpacker.SolidAllowed = isSolid;
}
if (item->IsDir())
@@ -2826,18 +2851,30 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
curUnpackSize = 0;
curPackSize = GetPackSize(index2);
}
else if ((unsigned)index2 < index)
bufIndex = FindLinkBuf(linkFiles, index2);
else
{
if ((unsigned)index2 < index)
bufIndex = FindLinkBuf(linkFiles, index2);
}
}
bool needCallback = true;
if (!realOutStream)
{
if (testMode)
{
if (item->NeedUse_as_CopyLink_or_HardLink())
{
Int32 opRes = NExtract::NOperationResult::kOK;
if (bufIndex >= 0)
{
const CLinkFile &linkFile = linkFiles[bufIndex];
opRes = DecoderRes_to_OpRes(linkFile.Res, linkFile.crcOK);
}
RINOK(extractCallback->PrepareOperation(askMode));
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
RINOK(extractCallback->SetOperationResult(opRes));
continue;
}
}
@@ -2846,10 +2883,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (item->IsService())
continue;
if (item->NeedUse_as_HardLink())
continue;
needCallback = false;
bool needDecode = false;
if (!item->NeedUse_as_HardLink())
if (index2 < 0)
for (unsigned n = i + 1; n < _refs.Size(); n++)
{
@@ -2860,41 +2897,56 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
break;
if (extractStatuses[i] != 0)
{
needDecode = true;
needCallback = true;
break;
}
}
if (!needDecode)
continue;
askMode = NExtract::NAskMode::kSkip;
}
}
RINOK(extractCallback->PrepareOperation(askMode));
if (needCallback)
{
RINOK(extractCallback->PrepareOperation(askMode));
}
if (bufIndex >= 0)
{
CLinkFile &linkFile = linkFiles[bufIndex];
if (linkFile.NumLinks == 0)
return E_FAIL;
if (realOutStream)
if (isExtract)
{
RINOK(CopyData_with_Progress(linkFile.Data, linkFile.Data.Size(), realOutStream, progress));
if (linkFile.NumLinks == 0)
return E_FAIL;
if (needCallback)
if (realOutStream)
{
RINOK(CopyData_with_Progress(linkFile.Data, linkFile.Data.Size(), realOutStream, progress));
}
if (--linkFile.NumLinks == 0)
linkFile.Data.Free();
}
if (needCallback)
{
RINOK(extractCallback->SetOperationResult(DecoderRes_to_OpRes(linkFile.Res, linkFile.crcOK)));
}
if (--linkFile.NumLinks == 0)
linkFile.Data.Free();
RINOK(extractCallback->SetOperationResult(DecoderRes_to_OpRes(linkFile.Res, linkFile.crcOK)));
continue;
}
if (!needCallback)
continue;
if (item->NeedUse_as_CopyLink())
{
RINOK(extractCallback->SetOperationResult(
realOutStream ?
NExtract::NOperationResult::kUnsupportedMethod:
NExtract::NOperationResult::kOK));
int opRes = realOutStream ?
NExtract::NOperationResult::kUnsupportedMethod:
NExtract::NOperationResult::kOK;
realOutStream.Release();
RINOK(extractCallback->SetOperationResult(opRes));
continue;
}
@@ -2941,7 +2993,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
{
FOR_VECTOR(i, linkFiles)
FOR_VECTOR (i, linkFiles)
if (linkFiles[i].NumLinks != 0)
return E_FAIL;
}

View File

@@ -415,6 +415,8 @@ bool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item)
if (size < 8)
return false;
item.PackSize |= ((UInt64)Get32(p) << 32);
if (item.PackSize >= ((UInt64)1 << 63))
return false;
item.Size |= ((UInt64)Get32(p + 4) << 32);
p += 8;
size -= 8;
@@ -667,7 +669,8 @@ HRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPass
{
if (processed < offset + 2)
error = k_ErrorType_Corrupted;
ArcInfo.VolNumber = (UInt32)Get16(m_FileHeaderData + offset);
else
ArcInfo.VolNumber = (UInt32)Get16(m_FileHeaderData + offset);
}
ArcInfo.EndOfArchive_was_Read = true;

View File

@@ -4,6 +4,7 @@
#include "../../../C/Alloc.h"
#include "../../../C/CpuArch.h"
#include "../../../C/LzmaDec.h"
#include "../../../C/Xz.h"
#include "../../Common/ComTry.h"
@@ -24,7 +25,7 @@
#include "../Compress/CopyCoder.h"
#include "../Compress/ZlibDecoder.h"
#include "../Compress/LzmaDecoder.h"
// #include "../Compress/LzmaDecoder.h"
namespace NArchive {
namespace NSquashfs {
@@ -866,8 +867,8 @@ class CHandler:
CBufPtrSeqOutStream *_outStreamSpec;
CMyComPtr<ISequentialOutStream> _outStream;
NCompress::NLzma::CDecoder *_lzmaDecoderSpec;
CMyComPtr<ICompressCoder> _lzmaDecoder;
// NCompress::NLzma::CDecoder *_lzmaDecoderSpec;
// CMyComPtr<ICompressCoder> _lzmaDecoder;
NCompress::NZlib::CDecoder *_zlibDecoderSpec;
CMyComPtr<ICompressCoder> _zlibDecoder;
@@ -1155,12 +1156,13 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool
if (inSize != _zlibDecoderSpec->GetInputProcessedSize())
return S_FALSE;
}
/*
else if (method == kMethod_LZMA)
{
if (!_lzmaDecoder)
{
_lzmaDecoderSpec = new NCompress::NLzma::CDecoder();
_lzmaDecoderSpec->FinishStream = true;
// _lzmaDecoderSpec->FinishStream = true;
_lzmaDecoder = _lzmaDecoderSpec;
}
const UInt32 kPropsSize = LZMA_PROPS_SIZE + 8;
@@ -1187,6 +1189,7 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool
if (inSize != propsSize + _lzmaDecoderSpec->GetInputProcessedSize())
return S_FALSE;
}
*/
else
{
if (_inputBuffer.Size() < inSize)
@@ -1200,11 +1203,49 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool
if (!dest)
return E_OUTOFMEMORY;
}
SizeT destLen = outSizeMax, srcLen = inSize;
if (method == kMethod_LZO)
{
RINOK(LzoDecode(dest, &destLen, _inputBuffer, &srcLen));
}
else if (method == kMethod_LZMA)
{
Byte props[5];
const Byte *src = _inputBuffer;
if (_noPropsLZMA)
{
props[0] = 0x5D;
SetUi32(&props[1], _h.BlockSize);
}
else
{
const UInt32 kPropsSize = LZMA_PROPS_SIZE + 8;
if (inSize < kPropsSize)
return S_FALSE;
memcpy(props, src, LZMA_PROPS_SIZE);
UInt64 outSize = GetUi64(src + LZMA_PROPS_SIZE);
if (outSize > outSizeMax)
return S_FALSE;
destLen = (SizeT)outSize;
src += kPropsSize;
inSize -= kPropsSize;
srcLen = inSize;
}
ELzmaStatus status;
SRes res = LzmaDecode(dest, &destLen,
src, &srcLen,
props, LZMA_PROPS_SIZE,
LZMA_FINISH_END,
&status, &g_Alloc);
if (res != 0)
return SResToHRESULT(res);
if (status != LZMA_STATUS_FINISHED_WITH_MARK)
return S_FALSE;
}
else
{
ECoderStatus status;
@@ -1217,6 +1258,7 @@ HRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool
if (status != CODER_STATUS_NEEDS_MORE_INPUT || !XzUnpacker_IsStreamWasFinished(&_xz))
return S_FALSE;
}
if (inSize != srcLen)
return S_FALSE;
if (outBuf)

View File

@@ -46,7 +46,7 @@ static const Byte SWF_COMPRESSED_LZMA = 'Z';
static const Byte SWF_MIN_COMPRESSED_ZLIB_VER = 6;
static const Byte SWF_MIN_COMPRESSED_LZMA_VER = 13;
static const Byte kVerLim = 20;
static const Byte kVerLim = 64;
API_FUNC_static_IsArc IsArc_Swf(const Byte *p, size_t size)
{

View File

@@ -443,14 +443,14 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro
case 'X':
{
// pax Extended Header
if (item.Name.IsPrefixedBy("PaxHeader/"))
if (item.Name.IsPrefixedBy("PaxHeader/")
|| item.Name.Find("PaxHeaders.4467/") >= 0)
{
RINOK(ReadDataToString(stream, item, pax, error));
if (error != k_ErrorType_OK)
return S_OK;
continue;
}
break;
}
case NFileHeader::NLinkFlag::kDumpDir:
@@ -488,7 +488,11 @@ HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item, EErro
if (ParsePaxLongName(pax, name))
item.Name = name;
else
error = k_ErrorType_Warning;
{
// no "path" property is allowed in pax4467
// error = k_ErrorType_Warning;
}
pax.Empty();
}
return S_OK;

View File

@@ -111,7 +111,9 @@ HRESULT CUnpacker::UnpackChunk(
}
else if (method == NMethod::kLZX)
{
lzxDecoderSpec->SetExternalWindow(unpackBuf.Data, chunkSizeBits);
res = lzxDecoderSpec->SetExternalWindow(unpackBuf.Data, chunkSizeBits);
if (res != S_OK)
return E_NOTIMPL;
lzxDecoderSpec->KeepHistoryForNext = false;
lzxDecoderSpec->SetKeepHistory(false);
res = lzxDecoderSpec->Code(packBuf.Data, inSize, (UInt32)outSize);
@@ -563,7 +565,13 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO
wchar_t *dest = s + size;
meta += 2;
for (unsigned i = 0; i < len; i++)
dest[i] = Get16(meta + i * 2);
{
wchar_t c = Get16(meta + i * 2);
// 18.06
if (c == CHAR_PATH_SEPARATOR || c == '/')
c = '_';
dest[i] = c;
}
}
if (index < 0)
return;
@@ -866,7 +874,11 @@ HRESULT CDatabase::ParseImageDirs(CByteBuffer &buf, int parent)
if (DirProcessed == DirSize - 8 && Get64(p + DirSize - 8) != 0)
return S_OK;
return S_FALSE;
// 18.06: we support cases, when some old dism can capture images
// where DirProcessed much smaller than DirSize
HeadersError = true;
return S_OK;
// return S_FALSE;
}

View File

@@ -468,7 +468,7 @@ public:
int ExludedItem; // -1 : if there are no exclude items
CUIntVector VirtualRoots; // we use them for old 1.10 WIM archives
bool ThereIsError() const { return RefCountError; }
bool ThereIsError() const { return RefCountError || HeadersError; }
unsigned GetNumUserItemsInImage(unsigned imageIndex) const
{
@@ -544,7 +544,10 @@ public:
HeadersError = false;
}
CDatabase(): RefCountError(false) {}
CDatabase():
RefCountError(false),
HeadersError(false)
{}
void GetShortName(unsigned index, NWindows::NCOM::CPropVariant &res) const;
void GetItemName(unsigned index1, NWindows::NCOM::CPropVariant &res) const;

View File

@@ -488,7 +488,7 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
{
CXzBlock block;
Bool isIndex;
BoolInt isIndex;
UInt32 headerSizeRes;
SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.vt, &isIndex, &headerSizeRes);
if (res2 == SZ_OK && !isIndex)
@@ -820,7 +820,7 @@ static HRESULT DecodeBlock(CXzUnpackerCPP2 &xzu,
packRem -= inLen;
Bool blockFinished = XzUnpacker_IsBlockFinished(&xzu.p);
BoolInt blockFinished = XzUnpacker_IsBlockFinished(&xzu.p);
if ((inLen == 0 && outLen == 0) || blockFinished)
{

View File

@@ -599,8 +599,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidHostOS:
{
const Byte hostOS = item.GetHostOS();
TYPE_TO_PROP(kHostOS, hostOS, prop);
if (item.FromCentral)
{
// 18.06: now we use HostOS only from Central::MadeByVersion
const Byte hostOS = item.MadeByVersion.HostOS;
TYPE_TO_PROP(kHostOS, hostOS, prop);
}
break;
}

View File

@@ -155,6 +155,7 @@ void CInArchive::Close()
HeadersError = false;
HeadersWarning = false;
ExtraMinorError = false;
UnexpectedEnd = false;
LocalsWereRead = false;
LocalsCenterMerged = false;
@@ -1729,6 +1730,9 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode)
HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdInfo, UInt64 cdOffset, UInt64 cdSize)
{
items.Clear();
// _startLocalFromCd_Disk = (UInt32)(Int32)-1;
// _startLocalFromCd_Offset = (UInt64)(Int64)-1;
RINOK(SeekToVol(IsMultiVol ? cdInfo.CdDisk : -1, cdOffset));
@@ -1752,6 +1756,17 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdIn
{
CItemEx cdItem;
RINOK(ReadCdItem(cdItem));
/*
if (cdItem.Disk < _startLocalFromCd_Disk ||
cdItem.Disk == _startLocalFromCd_Disk &&
cdItem.LocalHeaderPos < _startLocalFromCd_Offset)
{
_startLocalFromCd_Disk = cdItem.Disk;
_startLocalFromCd_Offset = cdItem.LocalHeaderPos;
}
*/
items.Add(cdItem);
}
if (Callback && (items.Size() & 0xFFF) == 0)
@@ -2509,6 +2524,8 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)
{
ArcInfo.CdWasRead = true;
ArcInfo.FirstItemRelatOffset = items[0].LocalHeaderPos;
// ArcInfo.FirstItemRelatOffset = _startLocalFromCd_Offset;
}
}
}
@@ -2535,6 +2552,10 @@ HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)
items.Clear();
localsWereRead = true;
HeadersError = false;
HeadersWarning = false;
ExtraMinorError = false;
// we can use any mode: with buffer and without buffer
// without buffer : skips packed data : fast for big files : slow for small files
// with buffer : reads packed data : slow for big files : fast for small files

View File

@@ -250,6 +250,9 @@ class CInArchive
UInt64 _streamPos;
UInt64 _cnt;
// UInt32 _startLocalFromCd_Disk;
// UInt64 _startLocalFromCd_Offset;
size_t GetAvail() const { return _bufCached - _bufPos; }
void InitBuf() { _bufPos = 0; _bufCached = 0; }
@@ -383,6 +386,9 @@ public:
UInt64 GetEmbeddedStubSize() const
{
// it's possible that first item in CD doesn refers to first local item
// so FirstItemRelatOffset is not first local item
if (ArcInfo.CdWasRead)
return ArcInfo.FirstItemRelatOffset;
if (IsMultiVol)

View File

@@ -214,6 +214,12 @@ class CLocalItem
public:
UInt16 Flags;
UInt16 Method;
/*
Zip specification doesn't mention that ExtractVersion field uses HostOS subfield.
18.06: 7-Zip now doesn't use ExtractVersion::HostOS to detect codePage
*/
CVersion ExtractVersion;
UInt64 Size;
@@ -309,7 +315,8 @@ public:
UInt32 GetWinAttrib() const;
bool GetPosixAttrib(UInt32 &attrib) const;
Byte GetHostOS() const { return FromCentral ? MadeByVersion.HostOS : ExtractVersion.HostOS; }
// 18.06: 0 instead of ExtractVersion.HostOS for local item
Byte GetHostOS() const { return FromCentral ? MadeByVersion.HostOS : (Byte)0; }
void GetUnicodeString(UString &res, const AString &s, bool isComment, bool useSpecifiedCodePage, UINT codePage) const;
@@ -326,7 +333,10 @@ public:
UINT GetCodePage() const
{
Byte hostOS = GetHostOS();
// 18.06: now we use HostOS only from Central::MadeByVersion
if (!FromCentral)
return CP_OEMCP;
Byte hostOS = MadeByVersion.HostOS;
return (UINT)((
hostOS == NFileHeader::NHostOS::kFAT
|| hostOS == NFileHeader::NHostOS::kNTFS

View File

@@ -40,7 +40,10 @@ static const Byte kHostOS =
#endif
static const Byte kMadeByHostOS = kHostOS;
static const Byte kExtractHostOS = kHostOS;
// 18.06: now we always write zero to high byte of ExtractVersion field.
// Previous versions of p7zip wrote (NFileHeader::NHostOS::kUnix) there, that is not correct
static const Byte kExtractHostOS = 0;
static const Byte kMethodForDirectory = NFileHeader::NCompressionMethod::kStore;