mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 11:14:58 -06:00
18.06
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user