Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Archive')
-rw-r--r--CPP/7zip/Archive/7z/7zDecode.cpp20
-rw-r--r--CPP/7zip/Archive/7z/7zDecode.h2
-rw-r--r--CPP/7zip/Archive/7z/7zEncode.cpp6
-rw-r--r--CPP/7zip/Archive/7z/7zExtract.cpp19
-rw-r--r--CPP/7zip/Archive/7z/7zHandler.cpp4
-rw-r--r--CPP/7zip/Archive/7z/7zHandler.h1
-rw-r--r--CPP/7zip/Archive/7z/7zHandlerOut.cpp34
-rw-r--r--CPP/7zip/Archive/7z/7zIn.cpp136
-rw-r--r--CPP/7zip/Archive/7z/7zIn.h4
-rw-r--r--CPP/7zip/Archive/7z/7zItem.h47
-rw-r--r--CPP/7zip/Archive/7z/7zOut.cpp93
-rw-r--r--CPP/7zip/Archive/7z/7zOut.h32
-rw-r--r--CPP/7zip/Archive/7z/7zUpdate.cpp76
-rw-r--r--CPP/7zip/Archive/ApmHandler.cpp13
-rw-r--r--CPP/7zip/Archive/ArHandler.cpp4
-rw-r--r--CPP/7zip/Archive/ArjHandler.cpp15
-rw-r--r--CPP/7zip/Archive/Bz2Handler.cpp111
-rw-r--r--CPP/7zip/Archive/Cab/CabHandler.cpp11
-rw-r--r--CPP/7zip/Archive/Chm/ChmHandler.cpp2
-rw-r--r--CPP/7zip/Archive/Chm/ChmIn.cpp107
-rw-r--r--CPP/7zip/Archive/Chm/ChmIn.h6
-rw-r--r--CPP/7zip/Archive/ComHandler.cpp19
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2.cpp88
-rw-r--r--CPP/7zip/Archive/Common/CoderMixer2.h30
-rw-r--r--CPP/7zip/Archive/Common/HandlerOut.cpp17
-rw-r--r--CPP/7zip/Archive/Common/HandlerOut.h12
-rw-r--r--CPP/7zip/Archive/Common/ItemNameUtils.cpp78
-rw-r--r--CPP/7zip/Archive/Common/ItemNameUtils.h27
-rw-r--r--CPP/7zip/Archive/CpioHandler.cpp4
-rw-r--r--CPP/7zip/Archive/DmgHandler.cpp335
-rw-r--r--CPP/7zip/Archive/ElfHandler.cpp465
-rw-r--r--CPP/7zip/Archive/ExtHandler.cpp254
-rw-r--r--CPP/7zip/Archive/GptHandler.cpp50
-rw-r--r--CPP/7zip/Archive/GzHandler.cpp9
-rw-r--r--CPP/7zip/Archive/HfsHandler.cpp34
-rw-r--r--CPP/7zip/Archive/Iso/IsoHandler.cpp9
-rw-r--r--CPP/7zip/Archive/Iso/IsoHeader.cpp2
-rw-r--r--CPP/7zip/Archive/Iso/IsoHeader.h2
-rw-r--r--CPP/7zip/Archive/Iso/IsoIn.cpp8
-rw-r--r--CPP/7zip/Archive/Iso/IsoIn.h1
-rw-r--r--CPP/7zip/Archive/Iso/IsoItem.h1
-rw-r--r--CPP/7zip/Archive/LzhHandler.cpp162
-rw-r--r--CPP/7zip/Archive/LzmaHandler.cpp78
-rw-r--r--CPP/7zip/Archive/MachoHandler.cpp56
-rw-r--r--CPP/7zip/Archive/MbrHandler.cpp26
-rw-r--r--CPP/7zip/Archive/MslzHandler.cpp2
-rw-r--r--CPP/7zip/Archive/MubHandler.cpp10
-rw-r--r--CPP/7zip/Archive/Nsis/NsisDecode.cpp49
-rw-r--r--CPP/7zip/Archive/Nsis/NsisDecode.h16
-rw-r--r--CPP/7zip/Archive/Nsis/NsisHandler.cpp18
-rw-r--r--CPP/7zip/Archive/Nsis/NsisIn.cpp51
-rw-r--r--CPP/7zip/Archive/Nsis/NsisIn.h19
-rw-r--r--CPP/7zip/Archive/NtfsHandler.cpp27
-rw-r--r--CPP/7zip/Archive/PeHandler.cpp94
-rw-r--r--CPP/7zip/Archive/PpmdHandler.cpp78
-rw-r--r--CPP/7zip/Archive/QcowHandler.cpp6
-rw-r--r--CPP/7zip/Archive/Rar/Rar5Handler.cpp366
-rw-r--r--CPP/7zip/Archive/Rar/Rar5Handler.h38
-rw-r--r--CPP/7zip/Archive/Rar/RarHandler.cpp134
-rw-r--r--CPP/7zip/Archive/Rar/RarVol.h6
-rw-r--r--CPP/7zip/Archive/RpmHandler.cpp111
-rw-r--r--CPP/7zip/Archive/SplitHandler.cpp2
-rw-r--r--CPP/7zip/Archive/SquashfsHandler.cpp86
-rw-r--r--CPP/7zip/Archive/SwfHandler.cpp15
-rw-r--r--CPP/7zip/Archive/Tar/TarHandler.cpp17
-rw-r--r--CPP/7zip/Archive/Tar/TarHandlerOut.cpp4
-rw-r--r--CPP/7zip/Archive/Tar/TarHeader.cpp10
-rw-r--r--CPP/7zip/Archive/Tar/TarHeader.h12
-rw-r--r--CPP/7zip/Archive/Tar/TarIn.cpp14
-rw-r--r--CPP/7zip/Archive/Tar/TarItem.h28
-rw-r--r--CPP/7zip/Archive/Udf/UdfIn.cpp44
-rw-r--r--CPP/7zip/Archive/UefiHandler.cpp550
-rw-r--r--CPP/7zip/Archive/VdiHandler.cpp167
-rw-r--r--CPP/7zip/Archive/VhdHandler.cpp48
-rw-r--r--CPP/7zip/Archive/VmdkHandler.cpp38
-rw-r--r--CPP/7zip/Archive/Wim/WimHandler.cpp73
-rw-r--r--CPP/7zip/Archive/Wim/WimHandlerOut.cpp2
-rw-r--r--CPP/7zip/Archive/Wim/WimIn.cpp2
-rw-r--r--CPP/7zip/Archive/Wim/WimRegister.cpp2
-rw-r--r--CPP/7zip/Archive/XarHandler.cpp18
-rw-r--r--CPP/7zip/Archive/XzHandler.cpp330
-rw-r--r--CPP/7zip/Archive/XzHandler.h54
-rw-r--r--CPP/7zip/Archive/Zip/ZipAddCommon.cpp197
-rw-r--r--CPP/7zip/Archive/Zip/ZipAddCommon.h9
-rw-r--r--CPP/7zip/Archive/Zip/ZipCompressionMode.h20
-rw-r--r--CPP/7zip/Archive/Zip/ZipHandler.cpp555
-rw-r--r--CPP/7zip/Archive/Zip/ZipHandler.h10
-rw-r--r--CPP/7zip/Archive/Zip/ZipHandlerOut.cpp281
-rw-r--r--CPP/7zip/Archive/Zip/ZipHeader.h48
-rw-r--r--CPP/7zip/Archive/Zip/ZipIn.cpp2112
-rw-r--r--CPP/7zip/Archive/Zip/ZipIn.h162
-rw-r--r--CPP/7zip/Archive/Zip/ZipItem.cpp98
-rw-r--r--CPP/7zip/Archive/Zip/ZipItem.h27
-rw-r--r--CPP/7zip/Archive/Zip/ZipOut.cpp211
-rw-r--r--CPP/7zip/Archive/Zip/ZipOut.h39
-rw-r--r--CPP/7zip/Archive/Zip/ZipRegister.cpp11
-rw-r--r--CPP/7zip/Archive/Zip/ZipUpdate.cpp303
-rw-r--r--CPP/7zip/Archive/Zip/ZipUpdate.h13
98 files changed, 5767 insertions, 3380 deletions
diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp
index b0d6dd83..d2687479 100644
--- a/CPP/7zip/Archive/7z/7zDecode.cpp
+++ b/CPP/7zip/Archive/7z/7zDecode.cpp
@@ -226,11 +226,13 @@ HRESULT CDecoder::Decode(
, ISequentialOutStream *outStream
, ICompressProgressInfo *compressProgress
+
, ISequentialInStream **
+ #ifdef USE_MIXER_ST
+ inStreamMainRes
+ #endif
- #ifdef USE_MIXER_ST
- inStreamMainRes
- #endif
+ , bool &dataAfterEnd_Error
_7Z_DECODER_CRYPRO_VARS_DECL
@@ -239,6 +241,8 @@ HRESULT CDecoder::Decode(
#endif
)
{
+ dataAfterEnd_Error = false;
+
const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];
CFolderEx folderInfo;
folders.ParseFolderEx(folderIndex, folderInfo);
@@ -415,12 +419,14 @@ HRESULT CDecoder::Decode(
}
#endif
+ bool finishMode = false;
{
CMyComPtr<ICompressSetFinishMode> setFinishMode;
decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);
if (setFinishMode)
{
- RINOK(setFinishMode->SetFinishMode(BoolToInt(fullUnpack)));
+ finishMode = fullUnpack;
+ RINOK(setFinishMode->SetFinishMode(BoolToInt(finishMode)));
}
}
@@ -450,7 +456,7 @@ HRESULT CDecoder::Decode(
unpackSize :
&folders.CoderUnpackSizes[unpackStreamIndexStart + i];
- _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers);
+ _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers, finishMode);
}
if (outStream)
@@ -530,7 +536,9 @@ HRESULT CDecoder::Decode(
progress2 = new CDecProgress(compressProgress);
ISequentialOutStream *outStreamPointer = outStream;
- return _mixer->Code(inStreamPointers, &outStreamPointer, progress2 ? (ICompressProgressInfo *)progress2 : compressProgress);
+ return _mixer->Code(inStreamPointers, &outStreamPointer,
+ progress2 ? (ICompressProgressInfo *)progress2 : compressProgress,
+ dataAfterEnd_Error);
}
#ifdef USE_MIXER_ST
diff --git a/CPP/7zip/Archive/7z/7zDecode.h b/CPP/7zip/Archive/7z/7zDecode.h
index 5b729f6c..62a38038 100644
--- a/CPP/7zip/Archive/7z/7zDecode.h
+++ b/CPP/7zip/Archive/7z/7zDecode.h
@@ -53,7 +53,9 @@ public:
, ISequentialOutStream *outStream
, ICompressProgressInfo *compressProgress
+
, ISequentialInStream **inStreamMainRes
+ , bool &dataAfterEnd_Error
_7Z_DECODER_CRYPRO_VARS_DECL
diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp
index 97e9ad7a..b206faa5 100644
--- a/CPP/7zip/Archive/7z/7zEncode.cpp
+++ b/CPP/7zip/Archive/7z/7zEncode.cpp
@@ -333,7 +333,7 @@ HRESULT CEncoder::Encode(
}
for (i = 0; i < numMethods; i++)
- _mixer->SetCoderInfo(i, NULL, NULL);
+ _mixer->SetCoderInfo(i, NULL, NULL, false);
/* inStreamSize can be used by BCJ2 to set optimal range of conversion.
@@ -429,10 +429,12 @@ HRESULT CEncoder::Encode(
for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
outStreamPointers.Add(tempBuffers[i - 1]);
+ bool dataAfterEnd_Error;
+
RINOK(_mixer->Code(
&inStreamPointer,
&outStreamPointers.Front(),
- mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress));
+ mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress, dataAfterEnd_Error));
if (_bindInfo.PackStreams.Size() != 0)
packSizes.Add(outStreamSizeCountSpec->GetSize());
diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp
index 05fd80de..8fea5aa5 100644
--- a/CPP/7zip/Archive/7z/7zExtract.cpp
+++ b/CPP/7zip/Archive/7z/7zExtract.cpp
@@ -348,6 +348,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
#endif
+ bool dataAfterEnd_Error = false;
+
HRESULT result = decoder.Decode(
EXTERNAL_CODECS_VARS
_inStream,
@@ -358,6 +360,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
outStream,
progress,
NULL // *inStreamMainRes
+ , dataAfterEnd_Error
_7Z_DECODER_CRYPRO_VARS
#if !defined(_7ZIP_ST) && !defined(_SFX)
@@ -365,13 +368,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
#endif
);
- if (result == S_FALSE || result == E_NOTIMPL)
+ if (result == S_FALSE || result == E_NOTIMPL || dataAfterEnd_Error)
{
bool wasFinished = folderOutStream->WasWritingFinished();
-
- int resOp = (result == S_FALSE ?
- NExtract::NOperationResult::kDataError :
- NExtract::NOperationResult::kUnsupportedMethod);
+
+ int resOp = NExtract::NOperationResult::kDataError;
+
+ if (result != S_FALSE)
+ {
+ if (result == E_NOTIMPL)
+ resOp = NExtract::NOperationResult::kUnsupportedMethod;
+ else if (wasFinished && dataAfterEnd_Error)
+ resOp = NExtract::NOperationResult::kDataAfterEnd;
+ }
RINOK(folderOutStream->FlushCorrupted(resOp));
diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp
index ccd2c624..2642e691 100644
--- a/CPP/7zip/Archive/7z/7zHandler.cpp
+++ b/CPP/7zip/Archive/7z/7zHandler.cpp
@@ -540,7 +540,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
*/
const CFileItem &item = _db.Files[index];
- UInt32 index2 = index;
+ const UInt32 index2 = index;
switch (propID)
{
@@ -575,7 +575,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidCTime: SetFileTimeProp_From_UInt64Def(value, _db.CTime, index2); break;
case kpidATime: SetFileTimeProp_From_UInt64Def(value, _db.ATime, index2); break;
case kpidMTime: SetFileTimeProp_From_UInt64Def(value, _db.MTime, index2); break;
- case kpidAttrib: if (item.AttribDefined) PropVarEm_Set_UInt32(value, item.Attrib); break;
+ case kpidAttrib: if (_db.Attrib.ValidAndDefined(index2)) PropVarEm_Set_UInt32(value, _db.Attrib.Vals[index2]); break;
case kpidCRC: if (item.CrcDefined) PropVarEm_Set_UInt32(value, item.Crc); break;
case kpidEncrypted: PropVarEm_Set_Bool(value, IsFolderEncrypted(_db.FileIndexToFolderIndexMap[index2])); break;
case kpidIsAnti: PropVarEm_Set_Bool(value, _db.IsItemAnti(index2)); break;
diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h
index d46401af..89e3275f 100644
--- a/CPP/7zip/Archive/7z/7zHandler.h
+++ b/CPP/7zip/Archive/7z/7zHandler.h
@@ -54,6 +54,7 @@ public:
CBoolPair Write_CTime;
CBoolPair Write_ATime;
CBoolPair Write_MTime;
+ CBoolPair Write_Attrib;
bool _useMultiThreadMixer;
diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
index 2b86ed26..c4fabed7 100644
--- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp
+++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
@@ -18,11 +18,12 @@ using namespace NWindows;
namespace NArchive {
namespace N7z {
-static const char *k_LZMA_Name = "LZMA";
-static const char *kDefaultMethodName = "LZMA2";
-static const char *k_Copy_Name = "Copy";
+#define k_LZMA_Name "LZMA"
+#define kDefaultMethodName "LZMA2"
+#define k_Copy_Name "Copy"
+
+#define k_MatchFinder_ForHeaders "BT2"
-static const char *k_MatchFinder_ForHeaders = "BT2";
static const UInt32 k_NumFastBytes_ForHeaders = 273;
static const UInt32 k_Level_ForHeaders = 5;
static const UInt32 k_Dictionary_ForHeaders =
@@ -113,11 +114,11 @@ HRESULT CHandler::SetMainMethod(
FOR_VECTOR (i, methods)
{
COneMethodInfo &oneMethodInfo = methods[i];
- SetGlobalLevelAndThreads(oneMethodInfo
- #ifndef _7ZIP_ST
- , numThreads
- #endif
- );
+
+ SetGlobalLevelTo(oneMethodInfo);
+ #ifndef _7ZIP_ST
+ CMultiMethodProps::SetMethodThreadsTo(oneMethodInfo, numThreads);
+ #endif
CMethodFull &methodFull = methodMode.Methods.AddNew();
RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo));
@@ -282,15 +283,18 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
bool need_CTime = (Write_CTime.Def && Write_CTime.Val);
bool need_ATime = (Write_ATime.Def && Write_ATime.Val);
bool need_MTime = (Write_MTime.Def && Write_MTime.Val || !Write_MTime.Def);
+ bool need_Attrib = (Write_Attrib.Def && Write_Attrib.Val || !Write_Attrib.Def);
if (db && !db->Files.IsEmpty())
{
if (!Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty();
if (!Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty();
if (!Write_MTime.Def) need_MTime = !db->MTime.Defs.IsEmpty();
+ if (!Write_Attrib.Def) need_Attrib = !db->Attrib.Defs.IsEmpty();
}
- UString s;
+ // UString s;
+ UString name;
for (UInt32 i = 0; i < numItems; i++)
{
@@ -307,7 +311,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
ui.IsAnti = false;
ui.Size = 0;
- UString name;
+ name.Empty();
// bool isAltStream = false;
if (ui.IndexInArchive != -1)
{
@@ -334,6 +338,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (ui.NewProps)
{
bool folderStatusIsDefined;
+ if (need_Attrib)
{
NCOM::CPropVariant prop;
RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop));
@@ -377,7 +382,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return E_INVALIDARG;
else
{
- name = NItemName::MakeLegalName(prop.bstrVal);
+ name = prop.bstrVal;
+ NItemName::ReplaceSlashes_OsToUnix(name);
}
}
{
@@ -614,6 +620,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
options.HeaderOptions.WriteCTime = Write_CTime;
options.HeaderOptions.WriteATime = Write_ATime;
options.HeaderOptions.WriteMTime = Write_MTime;
+ options.HeaderOptions.WriteAttrib = Write_Attrib;
*/
options.NumSolidFiles = _numSolidFiles;
@@ -705,6 +712,7 @@ void COutHandler::InitProps()
Write_CTime.Init();
Write_ATime.Init();
Write_MTime.Init();
+ Write_Attrib.Init();
_useMultiThreadMixer = true;
@@ -830,6 +838,8 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
if (name.IsEqualTo("ta")) return PROPVARIANT_to_BoolPair(value, Write_ATime);
if (name.IsEqualTo("tm")) return PROPVARIANT_to_BoolPair(value, Write_MTime);
+ if (name.IsEqualTo("tr")) return PROPVARIANT_to_BoolPair(value, Write_Attrib);
+
if (name.IsEqualTo("mtf")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);
if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting);
diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp
index d8c27175..3db5f515 100644
--- a/CPP/7zip/Archive/7z/7zIn.cpp
+++ b/CPP/7zip/Archive/7z/7zIn.cpp
@@ -32,6 +32,21 @@ using namespace NCOM;
namespace NArchive {
namespace N7z {
+unsigned BoolVector_CountSum(const CBoolVector &v)
+{
+ unsigned sum = 0;
+ const unsigned size = v.Size();
+ for (unsigned i = 0; i < size; i++)
+ if (v[i])
+ sum++;
+ return sum;
+}
+
+static inline bool BoolVector_Item_IsValidAndTrue(const CBoolVector &v, unsigned i)
+{
+ return (i < v.Size() ? v[i] : false);
+}
+
static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
{
v.ClearAndSetSize(size);
@@ -40,6 +55,7 @@ static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
p[i] = false;
}
+
class CInArchiveException {};
class CUnsupportedFeatureException: public CInArchiveException {};
@@ -566,21 +582,30 @@ void CInArchive::WaitId(UInt64 id)
}
}
-void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs)
+
+void CInArchive::Read_UInt32_Vector(CUInt32DefVector &v)
{
- ReadBoolVector2(numItems, crcs.Defs);
- crcs.Vals.ClearAndSetSize(numItems);
- UInt32 *p = &crcs.Vals[0];
- const bool *defs = &crcs.Defs[0];
+ unsigned numItems = v.Defs.Size();
+ v.Vals.ClearAndSetSize(numItems);
+ UInt32 *p = &v.Vals[0];
+ const bool *defs = &v.Defs[0];
for (unsigned i = 0; i < numItems; i++)
{
- UInt32 crc = 0;
+ UInt32 a = 0;
if (defs[i])
- crc = ReadUInt32();
- p[i] = crc;
+ a = ReadUInt32();
+ p[i] = a;
}
}
+
+void CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs)
+{
+ ReadBoolVector2(numItems, crcs.Defs);
+ Read_UInt32_Vector(crcs);
+}
+
+
#define k_Scan_NumCoders_MAX 64
#define k_Scan_NumCodersStreams_in_Folder_MAX 64
@@ -1075,6 +1100,8 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
outStreamSpec->Init(data, unpackSize);
+ bool dataAfterEnd_Error = false;
+
HRESULT result = decoder.Decode(
EXTERNAL_CODECS_LOC_VARS
_stream, baseOffset + dataOffset,
@@ -1083,16 +1110,23 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
outStream,
NULL, // *compressProgress
+
NULL // **inStreamMainRes
+ , dataAfterEnd_Error
_7Z_DECODER_CRYPRO_VARS
#if !defined(_7ZIP_ST) && !defined(_SFX)
, false // mtMode
, 1 // numThreads
#endif
+
);
+
RINOK(result);
+ if (dataAfterEnd_Error)
+ ThereIsHeaderError = true;
+
if (folders.FolderCRCs.ValidAndDefined(i))
if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i])
ThrowIncorrect();
@@ -1148,19 +1182,10 @@ HRESULT CInArchive::ReadHeader(
type = ReadID();
}
- db.Files.Clear();
-
if (type == NID::kFilesInfo)
{
const CNum numFiles = ReadNum();
- db.Files.ClearAndSetSize(numFiles);
- /*
- db.Files.Reserve(numFiles);
- CNum i;
- for (i = 0; i < numFiles; i++)
- db.Files.Add(CFileItem());
- */
db.ArcInfo.FileInfoPopIDs.Add(NID::kSize);
// if (!db.PackSizes.IsEmpty())
@@ -1169,7 +1194,6 @@ HRESULT CInArchive::ReadHeader(
db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC);
CBoolVector emptyStreamVector;
- BoolVector_Fill_False(emptyStreamVector, (unsigned)numFiles);
CBoolVector emptyFileVector;
CBoolVector antiFileVector;
CNum numEmptyStreams = 0;
@@ -1197,10 +1221,10 @@ HRESULT CInArchive::ReadHeader(
size_t rem = _inByteBack->GetRem();
db.NamesBuf.Alloc(rem);
ReadBytes(db.NamesBuf, rem);
- db.NameOffsets.Alloc(db.Files.Size() + 1);
+ db.NameOffsets.Alloc(numFiles + 1);
size_t pos = 0;
unsigned i;
- for (i = 0; i < db.Files.Size(); i++)
+ for (i = 0; i < numFiles; i++)
{
size_t curRem = (rem - pos) / 2;
const UInt16 *buf = (const UInt16 *)(db.NamesBuf + pos);
@@ -1216,36 +1240,31 @@ HRESULT CInArchive::ReadHeader(
ThereIsHeaderError = true;
break;
}
+
case NID::kWinAttrib:
{
- CBoolVector boolVector;
- ReadBoolVector2(db.Files.Size(), boolVector);
+ ReadBoolVector2(numFiles, db.Attrib.Defs);
CStreamSwitch streamSwitch;
streamSwitch.Set(this, &dataVector);
- for (CNum i = 0; i < numFiles; i++)
- {
- CFileItem &file = db.Files[i];
- file.AttribDefined = boolVector[i];
- if (file.AttribDefined)
- file.Attrib = ReadUInt32();
- }
+ Read_UInt32_Vector(db.Attrib);
break;
}
+
/*
case NID::kIsAux:
{
- ReadBoolVector(db.Files.Size(), db.IsAux);
+ ReadBoolVector(numFiles, db.IsAux);
break;
}
case NID::kParent:
{
db.IsTree = true;
// CBoolVector boolVector;
- // ReadBoolVector2(db.Files.Size(), boolVector);
+ // ReadBoolVector2(numFiles, boolVector);
// CStreamSwitch streamSwitch;
// streamSwitch.Set(this, &dataVector);
CBoolVector boolVector;
- ReadBoolVector2(db.Files.Size(), boolVector);
+ ReadBoolVector2(numFiles, boolVector);
db.ThereAreAltStreams = false;
for (i = 0; i < numFiles; i++)
@@ -1264,14 +1283,9 @@ HRESULT CInArchive::ReadHeader(
case NID::kEmptyStream:
{
ReadBoolVector(numFiles, emptyStreamVector);
- numEmptyStreams = 0;
- for (CNum i = 0; i < (CNum)emptyStreamVector.Size(); i++)
- if (emptyStreamVector[i])
- numEmptyStreams++;
-
- BoolVector_Fill_False(emptyFileVector, numEmptyStreams);
- BoolVector_Fill_False(antiFileVector, numEmptyStreams);
-
+ numEmptyStreams = BoolVector_CountSum(emptyStreamVector);
+ emptyFileVector.Clear();
+ antiFileVector.Clear();
break;
}
case NID::kEmptyFile: ReadBoolVector(numEmptyStreams, emptyFileVector); break;
@@ -1314,7 +1328,7 @@ HRESULT CInArchive::ReadHeader(
ReadBytes(db.SecureBuf + offset, db.SecureOffsets[i + 1] - offset);
}
db.SecureIDs.Clear();
- for (unsigned i = 0; i < db.Files.Size(); i++)
+ for (unsigned i = 0; i < numFiles; i++)
{
db.SecureIDs.Add(ReadNum());
// db.SecureIDs.Add(ReadUInt32());
@@ -1359,22 +1373,21 @@ HRESULT CInArchive::ReadHeader(
CNum emptyFileIndex = 0;
CNum sizeIndex = 0;
- CNum numAntiItems = 0;
+ const CNum numAntiItems = BoolVector_CountSum(antiFileVector);
- CNum i;
+ if (numAntiItems != 0)
+ db.IsAnti.ClearAndSetSize(numFiles);
- for (i = 0; i < numEmptyStreams; i++)
- if (antiFileVector[i])
- numAntiItems++;
+ db.Files.ClearAndSetSize(numFiles);
- for (i = 0; i < numFiles; i++)
+ for (CNum i = 0; i < numFiles; i++)
{
CFileItem &file = db.Files[i];
bool isAnti;
- file.HasStream = !emptyStreamVector[i];
file.Crc = 0;
- if (file.HasStream)
+ if (!BoolVector_Item_IsValidAndTrue(emptyStreamVector, i))
{
+ file.HasStream = true;
file.IsDir = false;
isAnti = false;
file.Size = unpackSizes[sizeIndex];
@@ -1385,26 +1398,31 @@ HRESULT CInArchive::ReadHeader(
}
else
{
- file.IsDir = !emptyFileVector[emptyFileIndex];
- isAnti = antiFileVector[emptyFileIndex];
+ file.HasStream = false;
+ file.IsDir = !BoolVector_Item_IsValidAndTrue(emptyFileVector, emptyFileIndex);
+ isAnti = BoolVector_Item_IsValidAndTrue(antiFileVector, emptyFileIndex);
emptyFileIndex++;
file.Size = 0;
file.CrcDefined = false;
}
if (numAntiItems != 0)
- db.IsAnti.Add(isAnti);
+ db.IsAnti[i] = isAnti;
}
+
}
+
db.FillLinks();
- /*
- if (type != NID::kEnd)
- ThrowIncorrect();
- if (_inByteBack->GetRem() != 0)
- ThrowIncorrect();
- */
+
+ if (type != NID::kEnd || _inByteBack->GetRem() != 0)
+ {
+ db.UnsupportedFeatureWarning = true;
+ // ThrowIncorrect();
+ }
+
return S_OK;
}
+
void CDbEx::FillLinks()
{
FolderStartFileIndex.Alloc(NumFolders);
@@ -1466,6 +1484,7 @@ void CDbEx::FillLinks()
}
}
+
HRESULT CInArchive::ReadDatabase2(
DECL_EXTERNAL_CODECS_LOC_VARS
CDbEx &db
@@ -1610,6 +1629,7 @@ HRESULT CInArchive::ReadDatabase2(
);
}
+
HRESULT CInArchive::ReadDatabase(
DECL_EXTERNAL_CODECS_LOC_VARS
CDbEx &db
diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h
index 3592e99b..2d5fbb79 100644
--- a/CPP/7zip/Archive/7z/7zIn.h
+++ b/CPP/7zip/Archive/7z/7zIn.h
@@ -115,6 +115,7 @@ struct CDatabase: public CFolders
CUInt64DefVector ATime;
CUInt64DefVector MTime;
CUInt64DefVector StartPos;
+ CUInt32DefVector Attrib;
CBoolVector IsAnti;
/*
CBoolVector IsAux;
@@ -146,6 +147,7 @@ struct CDatabase: public CFolders
ATime.Clear();
MTime.Clear();
StartPos.Clear();
+ Attrib.Clear();
IsAnti.Clear();
// IsAux.Clear();
}
@@ -369,6 +371,8 @@ class CInArchive
void SkipData() { _inByteBack->SkipData(); }
void WaitId(UInt64 id);
+ void Read_UInt32_Vector(CUInt32DefVector &v);
+
void ReadArchiveProperties(CInArchiveInfo &archiveInfo);
void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs);
diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h
index 5e2b58f2..ee4aed3f 100644
--- a/CPP/7zip/Archive/7z/7zItem.h
+++ b/CPP/7zip/Archive/7z/7zItem.h
@@ -26,12 +26,14 @@ struct CCoderInfo
bool IsSimpleCoder() const { return NumStreams == 1; }
};
+
struct CBond
{
UInt32 PackIndex;
UInt32 UnpackIndex;
};
+
struct CFolder
{
CLASS_NO_COPY(CFolder)
@@ -87,6 +89,7 @@ public:
}
};
+
struct CUInt32DefVector
{
CBoolVector Defs;
@@ -110,9 +113,25 @@ struct CUInt32DefVector
Vals.ReserveDown();
}
+ bool GetItem(unsigned index, UInt32 &value) const
+ {
+ if (index < Defs.Size() && Defs[index])
+ {
+ value = Vals[index];
+ return true;
+ }
+ value = 0;
+ return false;
+ }
+
bool ValidAndDefined(unsigned i) const { return i < Defs.Size() && Defs[i]; }
+
+ bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; }
+
+ void SetItem(unsigned index, bool defined, UInt32 value);
};
+
struct CUInt64DefVector
{
CBoolVector Defs;
@@ -141,15 +160,15 @@ struct CUInt64DefVector
return false;
}
- void SetItem(unsigned index, bool defined, UInt64 value);
-
bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; }
+
+ void SetItem(unsigned index, bool defined, UInt64 value);
};
+
struct CFileItem
{
UInt64 Size;
- UInt32 Attrib;
UInt32 Crc;
/*
int Parent;
@@ -159,23 +178,23 @@ struct CFileItem
// stream in some folder. It can be empty stream
bool IsDir;
bool CrcDefined;
- bool AttribDefined;
+
+ /*
+ void Clear()
+ {
+ HasStream = true;
+ IsDir = false;
+ CrcDefined = false;
+ }
CFileItem():
- /*
- Parent(-1),
- IsAltStream(false),
- */
+ // Parent(-1),
+ // IsAltStream(false),
HasStream(true),
IsDir(false),
CrcDefined(false),
- AttribDefined(false)
{}
- void SetAttrib(UInt32 attrib)
- {
- AttribDefined = true;
- Attrib = attrib;
- }
+ */
};
}}
diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp
index 3e70f466..904e32c5 100644
--- a/CPP/7zip/Archive/7z/7zOut.cpp
+++ b/CPP/7zip/Archive/7z/7zOut.cpp
@@ -330,13 +330,11 @@ void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector)
WriteBoolVector(boolVector);
}
+unsigned BoolVector_CountSum(const CBoolVector &v);
+
void COutArchive::WriteHashDigests(const CUInt32DefVector &digests)
{
- unsigned numDefined = 0;
- unsigned i;
- for (i = 0; i < digests.Defs.Size(); i++)
- if (digests.Defs[i])
- numDefined++;
+ const unsigned numDefined = BoolVector_CountSum(digests.Defs);
if (numDefined == 0)
return;
@@ -348,7 +346,8 @@ void COutArchive::WriteHashDigests(const CUInt32DefVector &digests)
WriteByte(0);
WriteBoolVector(digests.Defs);
}
- for (i = 0; i < digests.Defs.Size(); i++)
+
+ for (unsigned i = 0; i < digests.Defs.Size(); i++)
if (digests.Defs[i])
WriteUInt32(digests.Vals[i]);
}
@@ -453,10 +452,12 @@ void COutArchive::WriteSubStreamsInfo(const CObjectVector<CFolder> &folders,
// 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field.
-void COutArchive::SkipAlign(unsigned pos, unsigned alignSize)
+void COutArchive::SkipToAligned(unsigned pos, unsigned alignShifts)
{
if (!_useAlign)
return;
+
+ const unsigned alignSize = (unsigned)1 << alignShifts;
pos += (unsigned)GetPos();
pos &= (alignSize - 1);
if (pos == 0)
@@ -471,11 +472,11 @@ void COutArchive::SkipAlign(unsigned pos, unsigned alignSize)
WriteByte(0);
}
-void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize)
+void COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts)
{
const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v);
- const UInt64 dataSize = (UInt64)numDefined * itemSize + bvSize + 2;
- SkipAlign(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSize);
+ const UInt64 dataSize = ((UInt64)numDefined << itemSizeShifts) + bvSize + 2;
+ SkipToAligned(3 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), itemSizeShifts);
WriteByte(type);
WriteNumber(dataSize);
@@ -486,24 +487,18 @@ void COutArchive::WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefin
WriteByte(0);
WriteBoolVector(v);
}
- WriteByte(0);
+ WriteByte(0); // 0 means no switching to external stream
}
void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type)
{
- unsigned numDefined = 0;
-
- unsigned i;
- for (i = 0; i < v.Defs.Size(); i++)
- if (v.Defs[i])
- numDefined++;
-
+ const unsigned numDefined = BoolVector_CountSum(v.Defs);
if (numDefined == 0)
return;
- WriteAlignedBoolHeader(v.Defs, numDefined, type, 8);
+ WriteAlignedBools(v.Defs, numDefined, type, 3);
- for (i = 0; i < v.Defs.Size(); i++)
+ for (unsigned i = 0; i < v.Defs.Size(); i++)
if (v.Defs[i])
WriteUInt64(v.Vals[i]);
}
@@ -648,7 +643,7 @@ void COutArchive::WriteHeader(
if (numDefined > 0)
{
namesDataSize++;
- SkipAlign(2 + GetBigNumberSize(namesDataSize), 16);
+ SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4);
WriteByte(NID::kName);
WriteNumber(namesDataSize);
@@ -673,28 +668,15 @@ void COutArchive::WriteHeader(
{
/* ---------- Write Attrib ---------- */
- CBoolVector boolVector;
- boolVector.ClearAndSetSize(db.Files.Size());
- unsigned numDefined = 0;
-
- {
- FOR_VECTOR (i, db.Files)
- {
- bool defined = db.Files[i].AttribDefined;
- boolVector[i] = defined;
- if (defined)
- numDefined++;
- }
- }
+ const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs);
if (numDefined != 0)
{
- WriteAlignedBoolHeader(boolVector, numDefined, NID::kWinAttrib, 4);
- FOR_VECTOR (i, db.Files)
+ WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2);
+ FOR_VECTOR (i, db.Attrib.Defs)
{
- const CFileItem &file = db.Files[i];
- if (file.AttribDefined)
- WriteUInt32(file.Attrib);
+ if (db.Attrib.Defs[i])
+ WriteUInt32(db.Attrib.Vals[i]);
}
}
}
@@ -702,18 +684,8 @@ void COutArchive::WriteHeader(
/*
{
// ---------- Write IsAux ----------
- unsigned numAux = 0;
- const CBoolVector &isAux = db.IsAux;
- for (i = 0; i < isAux.Size(); i++)
- if (isAux[i])
- numAux++;
- if (numAux > 0)
- {
- const unsigned bvSize = Bv_GetSizeInBytes(isAux);
- WriteByte(NID::kIsAux);
- WriteNumber(bvSize);
- WriteBoolVector(isAux);
- }
+ if (BoolVector_CountSum(db.IsAux) != 0)
+ WritePropBoolVector(NID::kIsAux, db.IsAux);
}
{
@@ -734,10 +706,10 @@ void COutArchive::WriteHeader(
}
if (numParentLinks > 0)
{
- // WriteAlignedBoolHeader(boolVector, numDefined, NID::kParent, 4);
+ // WriteAlignedBools(boolVector, numDefined, NID::kParent, 2);
const unsigned bvSize = (numIsDir == boolVector.Size()) ? 0 : Bv_GetSizeInBytes(boolVector);
const UInt64 dataSize = (UInt64)db.Files.Size() * 4 + bvSize + 1;
- SkipAlign(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 4);
+ SkipToAligned(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 2);
WriteByte(NID::kParent);
WriteNumber(dataSize);
@@ -765,7 +737,7 @@ void COutArchive::WriteHeader(
// secureDataSize += db.SecureIDs.Size() * 4;
for (i = 0; i < db.SecureIDs.Size(); i++)
secureDataSize += GetBigNumberSize(db.SecureIDs[i]);
- SkipAlign(2 + GetBigNumberSize(secureDataSize), 4);
+ SkipToAligned(2 + GetBigNumberSize(secureDataSize), 2);
WriteByte(NID::kNtSecure);
WriteNumber(secureDataSize);
WriteByte(0);
@@ -888,6 +860,18 @@ HRESULT COutArchive::WriteDatabase(
}
}
+void CUInt32DefVector::SetItem(unsigned index, bool defined, UInt32 value)
+{
+ while (index >= Defs.Size())
+ Defs.Add(false);
+ Defs[index] = defined;
+ if (!defined)
+ return;
+ while (index >= Vals.Size())
+ Vals.Add(0);
+ Vals[index] = value;
+}
+
void CUInt64DefVector::SetItem(unsigned index, bool defined, UInt64 value)
{
while (index >= Defs.Size())
@@ -907,6 +891,7 @@ void CArchiveDatabaseOut::AddFile(const CFileItem &file, const CFileItem2 &file2
ATime.SetItem(index, file2.ATimeDefined, file2.ATime);
MTime.SetItem(index, file2.MTimeDefined, file2.MTime);
StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos);
+ Attrib.SetItem(index, file2.AttribDefined, file2.Attrib);
SetItem_Anti(index, file2.IsAnti);
// SetItem_Aux(index, file2.IsAux);
Names.Add(name);
diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h
index 6c902668..1ebad56d 100644
--- a/CPP/7zip/Archive/7z/7zOut.h
+++ b/CPP/7zip/Archive/7z/7zOut.h
@@ -45,6 +45,7 @@ public:
size_t GetPos() const { return _pos; }
};
+
struct CHeaderOptions
{
bool CompressMainHeader;
@@ -71,24 +72,31 @@ struct CFileItem2
UInt64 ATime;
UInt64 MTime;
UInt64 StartPos;
+ UInt32 Attrib;
+
bool CTimeDefined;
bool ATimeDefined;
bool MTimeDefined;
bool StartPosDefined;
+ bool AttribDefined;
bool IsAnti;
// bool IsAux;
+ /*
void Init()
{
CTimeDefined = false;
ATimeDefined = false;
MTimeDefined = false;
StartPosDefined = false;
+ AttribDefined = false;
IsAnti = false;
// IsAux = false;
}
+ */
};
+
struct COutFolders
{
CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only.
@@ -111,6 +119,7 @@ struct COutFolders
}
};
+
struct CArchiveDatabaseOut: public COutFolders
{
CRecordVector<UInt64> PackSizes;
@@ -123,10 +132,11 @@ struct CArchiveDatabaseOut: public COutFolders
CUInt64DefVector ATime;
CUInt64DefVector MTime;
CUInt64DefVector StartPos;
- CRecordVector<bool> IsAnti;
+ CUInt32DefVector Attrib;
+ CBoolVector IsAnti;
/*
- CRecordVector<bool> IsAux;
+ CBoolVector IsAux;
CByteBuffer SecureBuf;
CRecordVector<UInt32> SecureSizes;
@@ -154,6 +164,7 @@ struct CArchiveDatabaseOut: public COutFolders
ATime.Clear();
MTime.Clear();
StartPos.Clear();
+ Attrib.Clear();
IsAnti.Clear();
/*
@@ -176,6 +187,7 @@ struct CArchiveDatabaseOut: public COutFolders
ATime.ReserveDown();
MTime.ReserveDown();
StartPos.ReserveDown();
+ Attrib.ReserveDown();
IsAnti.ReserveDown();
/*
@@ -196,11 +208,12 @@ struct CArchiveDatabaseOut: public COutFolders
{
unsigned size = Files.Size();
return (
- CTime.CheckSize(size) &&
- ATime.CheckSize(size) &&
- MTime.CheckSize(size) &&
- StartPos.CheckSize(size) &&
- (size == IsAnti.Size() || IsAnti.Size() == 0));
+ CTime.CheckSize(size)
+ && ATime.CheckSize(size)
+ && MTime.CheckSize(size)
+ && StartPos.CheckSize(size)
+ && Attrib.CheckSize(size)
+ && (size == IsAnti.Size() || IsAnti.Size() == 0));
}
bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }
@@ -224,6 +237,7 @@ struct CArchiveDatabaseOut: public COutFolders
void AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name);
};
+
class COutArchive
{
UInt64 _prefixHeaderPos;
@@ -261,8 +275,8 @@ class COutArchive
const CRecordVector<UInt64> &unpackSizes,
const CUInt32DefVector &digests);
- void SkipAlign(unsigned pos, unsigned alignSize);
- void WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize);
+ void SkipToAligned(unsigned pos, unsigned alignShifts);
+ void WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts);
void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type);
HRESULT EncodeStream(
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp
index 68e57f09..e0740e46 100644
--- a/CPP/7zip/Archive/7z/7zUpdate.cpp
+++ b/CPP/7zip/Archive/7z/7zUpdate.cpp
@@ -1088,18 +1088,23 @@ static HRESULT MakeExeMethod(CCompressionMethodMode &mode,
}
-static void FromUpdateItemToFileItem(const CUpdateItem &ui,
- CFileItem &file, CFileItem2 &file2)
+static void UpdateItem_To_FileItem2(const CUpdateItem &ui, CFileItem2 &file2)
{
- if (ui.AttribDefined)
- file.SetAttrib(ui.Attrib);
-
+ file2.Attrib = ui.Attrib; file2.AttribDefined = ui.AttribDefined;
file2.CTime = ui.CTime; file2.CTimeDefined = ui.CTimeDefined;
file2.ATime = ui.ATime; file2.ATimeDefined = ui.ATimeDefined;
file2.MTime = ui.MTime; file2.MTimeDefined = ui.MTimeDefined;
file2.IsAnti = ui.IsAnti;
// file2.IsAux = false;
file2.StartPosDefined = false;
+ // file2.StartPos = 0;
+}
+
+
+static void UpdateItem_To_FileItem(const CUpdateItem &ui,
+ CFileItem &file, CFileItem2 &file2)
+{
+ UpdateItem_To_FileItem2(ui, file2);
file.Size = ui.Size;
file.IsDir = ui.IsDir;
@@ -1107,6 +1112,8 @@ static void FromUpdateItemToFileItem(const CUpdateItem &ui,
// file.IsAltStream = ui.IsAltStream;
}
+
+
class CRepackInStreamWithSizes:
public ISequentialInStream,
public ICompressGetSubStreamSize,
@@ -1437,6 +1444,7 @@ public:
#ifndef _7ZIP_ST
+ bool dataAfterEnd_Error;
HRESULT Result;
CMyComPtr<IInStream> InStream;
@@ -1479,7 +1487,9 @@ void CThreadDecoder::Execute()
bool passwordIsDefined = false;
UString password;
#endif
-
+
+ dataAfterEnd_Error = false;
+
Result = Decoder.Decode(
EXTERNAL_CODECS_LOC_VARS
InStream,
@@ -1491,12 +1501,15 @@ void CThreadDecoder::Execute()
Fos,
NULL, // compressProgress
+
NULL // *inStreamMainRes
+ , dataAfterEnd_Error
_7Z_DECODER_CRYPRO_VARS
#ifndef _7ZIP_ST
, MtMode, NumThreads
#endif
+
);
}
catch(...)
@@ -1541,6 +1554,7 @@ static void GetFile(const CDatabase &inDb, unsigned index, CFileItem &file, CFil
file2.ATimeDefined = inDb.ATime.GetItem(index, file2.ATime);
file2.MTimeDefined = inDb.MTime.GetItem(index, file2.MTime);
file2.StartPosDefined = inDb.StartPos.GetItem(index, file2.StartPos);
+ file2.AttribDefined = inDb.Attrib.GetItem(index, file2.Attrib);
file2.IsAnti = inDb.IsItemAnti(index);
// file2.IsAux = inDb.IsItemAux(index);
}
@@ -1837,7 +1851,7 @@ HRESULT Update(
continue;
secureID = ui.SecureIndex;
if (ui.NewProps)
- FromUpdateItemToFileItem(ui, file, file2);
+ UpdateItem_To_FileItem(ui, file, file2);
else
GetFile(*db, ui.IndexInArchive, file, file2);
}
@@ -1887,7 +1901,8 @@ HRESULT Update(
UString name;
if (ui.NewProps)
{
- FromUpdateItemToFileItem(ui, file, file2);
+ UpdateItem_To_FileItem(ui, file, file2);
+ file.CrcDefined = false;
name = ui.Name;
}
else
@@ -2107,6 +2122,8 @@ HRESULT Update(
#endif
CMyComPtr<ISequentialInStream> decodedStream;
+ bool dataAfterEnd_Error = false;
+
HRESULT res = threadDecoder.Decoder.Decode(
EXTERNAL_CODECS_LOC_VARS
inStream,
@@ -2117,13 +2134,16 @@ HRESULT Update(
NULL, // *outStream
NULL, // *compressProgress
+
&decodedStream
+ , dataAfterEnd_Error
_7Z_DECODER_CRYPRO_VARS
#ifndef _7ZIP_ST
, false // mtMode
, 1 // numThreads
#endif
+
);
RINOK(res);
@@ -2175,16 +2195,19 @@ HRESULT Update(
HRESULT decodeRes = threadDecoder.Result;
// if (res == k_My_HRESULT_CRC_ERROR)
- if (decodeRes == S_FALSE)
+ if (decodeRes == S_FALSE || threadDecoder.dataAfterEnd_Error)
{
if (extractCallback)
{
RINOK(extractCallback->ReportExtractResult(
NEventIndexType::kInArcIndex, db->FolderStartFileIndex[folderIndex],
// NEventIndexType::kBlockIndex, (UInt32)folderIndex,
- NExtract::NOperationResult::kDataError));
+ (decodeRes != S_OK ?
+ NExtract::NOperationResult::kDataError :
+ NExtract::NOperationResult::kDataAfterEnd)));
}
- return E_FAIL;
+ if (decodeRes != S_OK)
+ return E_FAIL;
}
RINOK(decodeRes);
if (encodeRes == S_OK)
@@ -2224,12 +2247,7 @@ HRESULT Update(
CNum indexInFolder = 0;
for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)
{
- CFileItem file;
- CFileItem2 file2;
- GetFile(*db, fi, file, file2);
- UString name;
- db->GetPath(fi, name);
- if (file.HasStream)
+ if (db->Files[fi].HasStream)
{
indexInFolder++;
int updateIndex = fileIndexToUpdateIndexMap[fi];
@@ -2238,17 +2256,21 @@ HRESULT Update(
const CUpdateItem &ui = updateItems[updateIndex];
if (ui.NewData)
continue;
+
+ UString name;
+ CFileItem file;
+ CFileItem2 file2;
+ GetFile(*db, fi, file, file2);
+
if (ui.NewProps)
{
- CFileItem uf;
- FromUpdateItemToFileItem(ui, uf, file2);
- uf.Size = file.Size;
- uf.Crc = file.Crc;
- uf.CrcDefined = file.CrcDefined;
- uf.HasStream = file.HasStream;
- file = uf;
+ UpdateItem_To_FileItem2(ui, file2);
+ file.IsDir = ui.IsDir;
name = ui.Name;
}
+ else
+ db->GetPath(fi, name);
+
/*
file.Parent = ui.ParentFolderIndex;
if (ui.TreeFolderIndex >= 0)
@@ -2292,7 +2314,7 @@ HRESULT Update(
const CUpdateItem &ui = updateItems[index];
CFileItem file;
if (ui.NewProps)
- FromUpdateItemToFileItem(ui, file);
+ UpdateItem_To_FileItem(ui, file);
else
file = db.Files[ui.IndexInArchive];
if (file.IsAnti || file.IsDir)
@@ -2367,7 +2389,7 @@ HRESULT Update(
UString name;
if (ui.NewProps)
{
- FromUpdateItemToFileItem(ui, file, file2);
+ UpdateItem_To_FileItem(ui, file, file2);
name = ui.Name;
}
else
@@ -2386,7 +2408,7 @@ HRESULT Update(
{
skippedSize += ui.Size;
continue;
- // file.Name.AddAscii(".locked");
+ // file.Name += ".locked";
}
file.Crc = inStreamSpec->CRCs[subIndex];
diff --git a/CPP/7zip/Archive/ApmHandler.cpp b/CPP/7zip/Archive/ApmHandler.cpp
index 51719d53..4d3f2728 100644
--- a/CPP/7zip/Archive/ApmHandler.cpp
+++ b/CPP/7zip/Archive/ApmHandler.cpp
@@ -6,7 +6,6 @@
#include "../../Common/ComTry.h"
#include "../../Common/Defs.h"
-#include "../../Common/IntToString.h"
#include "../../Windows/PropVariant.h"
@@ -232,7 +231,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
int mainIndex = -1;
FOR_VECTOR (i, _items)
{
- AString s = GetString(_items[i].Type);
+ AString s (GetString(_items[i].Type));
if (s != "Apple_Free" &&
s != "Apple_partition_map")
{
@@ -279,14 +278,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
case kpidPath:
{
- AString s = GetString(item.Name);
+ AString s (GetString(item.Name));
if (s.IsEmpty())
- {
- char s2[32];
- ConvertUInt32ToString(index, s2);
- s = s2;
- }
- AString type = GetString(item.Type);
+ s.Add_UInt32(index);
+ AString type (GetString(item.Type));
if (type == "Apple_HFS")
type = "hfs";
if (!type.IsEmpty())
diff --git a/CPP/7zip/Archive/ArHandler.cpp b/CPP/7zip/Archive/ArHandler.cpp
index 83ed5a02..816a84e4 100644
--- a/CPP/7zip/Archive/ArHandler.cpp
+++ b/CPP/7zip/Archive/ArHandler.cpp
@@ -688,7 +688,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidShortComment:
case kpidSubType:
{
- AString s = k_TypeExtionsions[(unsigned)_type];
+ AString s (k_TypeExtionsions[(unsigned)_type]);
if (_subType == kSubType_BSD)
s += ":BSD";
prop = s;
@@ -720,7 +720,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
if (item.TextFileIndex >= 0)
prop = (item.TextFileIndex == 0) ? "1.txt" : "2.txt";
else
- prop = (const wchar_t *)NItemName::GetOSName2(MultiByteToUnicodeString(item.Name, CP_OEMCP));
+ prop = (const wchar_t *)NItemName::GetOsPath_Remove_TailSlash(MultiByteToUnicodeString(item.Name, CP_OEMCP));
break;
case kpidSize:
case kpidPackSize:
diff --git a/CPP/7zip/Archive/ArjHandler.cpp b/CPP/7zip/Archive/ArjHandler.cpp
index 90819753..fb9e3e7a 100644
--- a/CPP/7zip/Archive/ArjHandler.cpp
+++ b/CPP/7zip/Archive/ArjHandler.cpp
@@ -5,10 +5,10 @@
#include "../../../C/CpuArch.h"
#include "../../Common/ComTry.h"
-#include "../../Common/IntToString.h"
#include "../../Common/StringConvert.h"
#include "../../Windows/PropVariant.h"
+#include "../../Windows/PropVariantUtils.h"
#include "../../Windows/TimeUtils.h"
#include "../Common/LimitedStreams.h"
@@ -642,16 +642,7 @@ static void SetTime(UInt32 dosTime, NCOM::CPropVariant &prop)
static void SetHostOS(Byte hostOS, NCOM::CPropVariant &prop)
{
- char temp[16];
- const char *s = NULL;
- if (hostOS < ARRAY_SIZE(kHostOS))
- s = kHostOS[hostOS];
- else
- {
- ConvertUInt32ToString(hostOS, temp);
- s = temp;
- }
- prop = s;
+ TYPE_TO_PROP(kHostOS, hostOS, prop);
}
static void SetUnicodeString(const AString &s, NCOM::CPropVariant &prop)
@@ -703,7 +694,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
const CItem &item = _items[index];
switch (propID)
{
- case kpidPath: prop = NItemName::GetOSName(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break;
+ case kpidPath: prop = NItemName::GetOsPath(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break;
case kpidIsDir: prop = item.IsDir(); break;
case kpidSize: prop = item.Size; break;
case kpidPackSize: prop = item.PackSize; break;
diff --git a/CPP/7zip/Archive/Bz2Handler.cpp b/CPP/7zip/Archive/Bz2Handler.cpp
index d1d5f727..98428430 100644
--- a/CPP/7zip/Archive/Bz2Handler.cpp
+++ b/CPP/7zip/Archive/Bz2Handler.cpp
@@ -179,6 +179,7 @@ STDMETHODIMP CHandler::Close()
return S_OK;
}
+
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
@@ -191,8 +192,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (_packSize_Defined)
extractCallback->SetTotal(_packSize);
- // RINOK(extractCallback->SetCompleted(&packSize));
-
CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
@@ -203,7 +202,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
extractCallback->PrepareOperation(askMode);
-
if (_needSeekToStart)
{
if (!_stream)
@@ -213,14 +211,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
else
_needSeekToStart = true;
- Int32 opRes;
-
- try
- {
+ // try {
NCompress::NBZip2::CDecoder *decoderSpec = new NCompress::NBZip2::CDecoder;
CMyComPtr<ICompressCoder> decoder = decoderSpec;
- decoderSpec->SetInStream(_seqStream);
#ifndef _7ZIP_ST
RINOK(decoderSpec->SetNumberOfThreads(_props._numThreads));
@@ -237,74 +231,43 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, true);
- UInt64 packSize = 0;
- UInt64 unpackedSize = 0;
- UInt64 numStreams = 0;
-
- decoderSpec->InitNumBlocks();
+ decoderSpec->FinishMode = true;
+ decoderSpec->Base.DecodeAllStreams = true;
- HRESULT result = S_OK;
+ _dataAfterEnd = false;
+ _needMoreInput = false;
- for (;;)
+ lps->InSize = 0;
+ lps->OutSize = 0;
+
+ HRESULT result = decoderSpec->Code(_seqStream, outStream, NULL, NULL, progress);
+
+ if (result != S_FALSE && result != S_OK)
+ return result;
+
+ if (decoderSpec->Base.NumStreams == 0)
{
- lps->InSize = packSize;
- lps->OutSize = unpackedSize;
-
- RINOK(lps->SetCur());
-
- result = decoderSpec->CodeResume(outStream, progress);
-
- if (result != S_FALSE && result != S_OK)
- return result;
-
- if (decoderSpec->IsBz)
- numStreams++;
- else if (numStreams == 0)
- {
- _isArc = false;
- result = S_FALSE;
- break;
- }
-
- unpackedSize = outStreamSpec->GetSize();
- UInt64 streamSize = decoderSpec->GetStreamSize();
+ _isArc = false;
+ result = S_FALSE;
+ }
+ else
+ {
+ const UInt64 inProcessedSize = decoderSpec->GetInputProcessedSize();
+ UInt64 packSize = inProcessedSize;
- if (streamSize == packSize)
- {
- // no new bytes in input stream, So it's good end of archive.
- result = S_OK;
- break;
- }
+ if (decoderSpec->Base.NeedMoreInput)
+ _needMoreInput = true;
- if (!decoderSpec->IsBz)
+ if (!decoderSpec->Base.IsBz)
{
- _dataAfterEnd = true;
- result = S_FALSE;
- break;
+ packSize = decoderSpec->Base.FinishedPackSize;
+ if (packSize != inProcessedSize)
+ _dataAfterEnd = true;
}
- if (decoderSpec->Base.BitDecoder.ExtraBitsWereRead())
- {
- _needMoreInput = true;
- packSize = streamSize;
- result = S_FALSE;
- break;
- }
-
- packSize = decoderSpec->GetInputProcessedSize();
-
- if (packSize > streamSize)
- return E_FAIL;
-
- if (result != S_OK)
- break;
- }
-
- if (numStreams != 0)
- {
_packSize = packSize;
- _unpackSize = unpackedSize;
- _numStreams = numStreams;
+ _unpackSize = decoderSpec->GetOutProcessedSize();
+ _numStreams = decoderSpec->Base.NumStreams;
_numBlocks = decoderSpec->GetNumBlocks();
_packSize_Defined = true;
@@ -313,32 +276,36 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
_numBlocks_Defined = true;
}
- decoderSpec->ReleaseInStream();
outStream.Release();
+ Int32 opRes;
+
if (!_isArc)
opRes = NExtract::NOperationResult::kIsNotArc;
else if (_needMoreInput)
opRes = NExtract::NOperationResult::kUnexpectedEnd;
- else if (decoderSpec->CrcError)
+ else if (decoderSpec->GetCrcError())
opRes = NExtract::NOperationResult::kCRCError;
else if (_dataAfterEnd)
opRes = NExtract::NOperationResult::kDataAfterEnd;
else if (result == S_FALSE)
opRes = NExtract::NOperationResult::kDataError;
+ else if (decoderSpec->Base.MinorError)
+ opRes = NExtract::NOperationResult::kDataError;
else if (result == S_OK)
opRes = NExtract::NOperationResult::kOK;
else
return result;
- }
- catch(const CInBufferException &e) { return e.ErrorCode; }
-
return extractCallback->SetOperationResult(opRes);
+ // } catch(...) { return E_FAIL; }
+
COM_TRY_END
}
+
+
static HRESULT UpdateArchive(
UInt64 unpackSize,
ISequentialOutStream *outStream,
diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp
index 18f58b3d..c62efbd8 100644
--- a/CPP/7zip/Archive/Cab/CabHandler.cpp
+++ b/CPP/7zip/Archive/Cab/CabHandler.cpp
@@ -226,12 +226,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
if (ai.SetID != 0)
{
AString s;
- char temp[32];
- ConvertUInt32ToString(ai.SetID, temp);
- s += temp;
- ConvertUInt32ToString(ai.CabinetNumber + 1, temp);
+ s.Add_UInt32(ai.SetID);
s += '_';
- s += temp;
+ s.Add_UInt32(ai.CabinetNumber + 1);
s += ".cab";
prop = s;
}
@@ -288,7 +285,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
ConvertUTF8ToUnicode(item.Name, unicodeName);
else
unicodeName = MultiByteToUnicodeString(item.Name, CP_ACP);
- prop = (const wchar_t *)NItemName::WinNameToOSName(unicodeName);
+ prop = (const wchar_t *)NItemName::WinPathToOsPath(unicodeName);
break;
}
@@ -491,7 +488,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
if (!_errorMessage.IsEmpty())
_errorMessage.Add_LF();
- _errorMessage.AddAscii("Can't open volume: ");
+ _errorMessage += "Can't open volume: ";
_errorMessage += fullName;
if (prevChecked)
diff --git a/CPP/7zip/Archive/Chm/ChmHandler.cpp b/CPP/7zip/Archive/Chm/ChmHandler.cpp
index b890d8ff..7ffdafe0 100644
--- a/CPP/7zip/Archive/Chm/ChmHandler.cpp
+++ b/CPP/7zip/Archive/Chm/ChmHandler.cpp
@@ -135,7 +135,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
if (us.Len() > 1 && us[0] == L'/')
us.Delete(0);
}
- NItemName::ConvertToOSName2(us);
+ NItemName::ReplaceToOsSlashes_Remove_TailSlash(us);
prop = us;
}
break;
diff --git a/CPP/7zip/Archive/Chm/ChmIn.cpp b/CPP/7zip/Archive/Chm/ChmIn.cpp
index 02ecfadd..7e3f155b 100644
--- a/CPP/7zip/Archive/Chm/ChmIn.cpp
+++ b/CPP/7zip/Archive/Chm/ChmIn.cpp
@@ -38,20 +38,13 @@ struct CHeaderErrorException {};
// define CHM_LOW, if you want to see low level items
// #define CHM_LOW
-static const GUID kChmLzxGuid = { 0x7FC28940, 0x9D31, 0x11D0, { 0x9B, 0x27, 0x00, 0xA0, 0xC9, 0x1E, 0x9C, 0x7C } };
-static const GUID kHelp2LzxGuid = { 0x0A9007C6, 0x4076, 0x11D3, { 0x87, 0x89, 0x00, 0x00, 0xF8, 0x10, 0x57, 0x54 } };
-static const GUID kDesGuid = { 0x67F6E4A2, 0x60BF, 0x11D3, { 0x85, 0x40, 0x00, 0xC0, 0x4F, 0x58, 0xC3, 0xCF } };
+static const Byte kChmLzxGuid[16] = { 0x40, 0x89, 0xC2, 0x7F, 0x31, 0x9D, 0xD0, 0x11, 0x9B, 0x27, 0x00, 0xA0, 0xC9, 0x1E, 0x9C, 0x7C };
+static const Byte kHelp2LzxGuid[16] = { 0xC6, 0x07, 0x90, 0x0A, 0x76, 0x40, 0xD3, 0x11, 0x87, 0x89, 0x00, 0x00, 0xF8, 0x10, 0x57, 0x54 };
+static const Byte kDesGuid[16] = { 0xA2, 0xE4, 0xF6, 0x67, 0xBF, 0x60, 0xD3, 0x11, 0x85, 0x40, 0x00, 0xC0, 0x4F, 0x58, 0xC3, 0xCF };
-static bool AreGuidsEqual(REFGUID g1, REFGUID g2)
+static bool inline AreGuidsEqual(const Byte *g1, const Byte *g2)
{
- if (g1.Data1 != g2.Data1 ||
- g1.Data2 != g2.Data2 ||
- g1.Data3 != g2.Data3)
- return false;
- for (int i = 0; i < 8; i++)
- if (g1.Data4[i] != g2.Data4[i])
- return false;
- return true;
+ return memcmp(g1, g2, 16) == 0;
}
static char GetHex(unsigned v)
@@ -65,35 +58,12 @@ static void PrintByte(Byte b, AString &s)
s += GetHex(b & 0xF);
}
-static void PrintUInt16(UInt16 v, AString &s)
-{
- PrintByte((Byte)(v >> 8), s);
- PrintByte((Byte)v, s);
-}
-
-static void PrintUInt32(UInt32 v, AString &s)
-{
- PrintUInt16((UInt16)(v >> 16), s);
- PrintUInt16((UInt16)v, s);
-}
-
AString CMethodInfo::GetGuidString() const
{
- AString s;
- s += '{';
- PrintUInt32(Guid.Data1, s);
- s += '-';
- PrintUInt16(Guid.Data2, s);
- s += '-';
- PrintUInt16(Guid.Data3, s);
- s += '-';
- PrintByte(Guid.Data4[0], s);
- PrintByte(Guid.Data4[1], s);
- s += '-';
- for (int i = 2; i < 8; i++)
- PrintByte(Guid.Data4[i], s);
- s += '}';
- return s;
+ char s[48];
+ RawLeGuidToString_Braced(Guid, s);
+ // MyStringUpper_Ascii(s);
+ return (AString)s;
}
bool CMethodInfo::IsLzx() const
@@ -108,32 +78,28 @@ bool CMethodInfo::IsDes() const
return AreGuidsEqual(Guid, kDesGuid);
}
-UString CMethodInfo::GetName() const
+AString CMethodInfo::GetName() const
{
- UString s;
+ AString s;
if (IsLzx())
{
- s.SetFromAscii("LZX:");
- char temp[16];
- ConvertUInt32ToString(LzxInfo.GetNumDictBits(), temp);
- s.AddAscii(temp);
+ s = "LZX:";
+ s.Add_UInt32(LzxInfo.GetNumDictBits());
}
else
{
- AString s2;
if (IsDes())
- s2 = "DES";
+ s = "DES";
else
{
- s2 = GetGuidString();
+ s = GetGuidString();
if (ControlData.Size() > 0)
{
- s2 += ':';
+ s += ':';
for (size_t i = 0; i < ControlData.Size(); i++)
- PrintByte(ControlData[i], s2);
+ PrintByte(ControlData[i], s);
}
}
- ConvertUTF8ToUnicode(s2, s);
}
return s;
}
@@ -153,7 +119,7 @@ UString CSectionInfo::GetMethodName() const
UString temp;
if (ConvertUTF8ToUnicode(Name, temp))
s += temp;
- s.AddAscii(": ");
+ s += ": ";
}
FOR_VECTOR (i, Methods)
{
@@ -220,12 +186,9 @@ UInt64 CInArchive::ReadEncInt()
throw CHeaderErrorException();
}
-void CInArchive::ReadGUID(GUID &g)
+void CInArchive::ReadGUID(Byte *g)
{
- g.Data1 = ReadUInt32();
- g.Data2 = ReadUInt16();
- g.Data3 = ReadUInt16();
- ReadBytes(g.Data4, 8);
+ ReadBytes(g, 16);
}
void CInArchive::ReadString(unsigned size, AString &s)
@@ -299,7 +262,7 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)
// The third and fourth bytes may contain even more fractional bits.
// The 4 least significant bits in the last byte are constant.
/* UInt32 lang = */ ReadUInt32();
- GUID g;
+ Byte g[16];
ReadGUID(g); // {7C01FD10-7BAA-11D0-9E0C-00A0-C922-E6EC}
ReadGUID(g); // {7C01FD11-7BAA-11D0-9E0C-00A0-C922-E6EC}
const unsigned kNumSections = 2;
@@ -422,7 +385,7 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
IsArc = true;
ReadUInt32(); // Len of post-header table
- GUID g;
+ Byte g[16];
ReadGUID(g); // {0A9007C1-4076-11D3-8789-0000F8105754}
// header section table
@@ -637,18 +600,18 @@ HRESULT CInArchive::DecompressStream(IInStream *inStream, const CDatabase &datab
#define DATA_SPACE "::DataSpace/"
-static const char *kNameList = DATA_SPACE "NameList";
-static const char *kStorage = DATA_SPACE "Storage/";
-static const char *kContent = "Content";
-static const char *kControlData = "ControlData";
-static const char *kSpanInfo = "SpanInfo";
-static const char *kTransform = "Transform/";
-static const char *kResetTable = "/InstanceData/ResetTable";
-static const char *kTransformList = "List";
+#define kNameList DATA_SPACE "NameList"
+#define kStorage DATA_SPACE "Storage/"
+#define kContent "Content"
+#define kControlData "ControlData"
+#define kSpanInfo "SpanInfo"
+#define kTransform "Transform/"
+#define kResetTable "/InstanceData/ResetTable"
+#define kTransformList "List"
static AString GetSectionPrefix(const AString &name)
{
- AString s = kStorage;
+ AString s (kStorage);
s += name;
s += '/';
return s;
@@ -743,7 +706,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
{
{
// The NameList file
- RINOK(DecompressStream(inStream, database, kNameList));
+ RINOK(DecompressStream(inStream, database, (AString)kNameList));
/* UInt16 length = */ ReadUInt16();
UInt16 numSections = ReadUInt16();
for (unsigned i = 0; i < numSections; i++)
@@ -764,7 +727,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
for (si = 1; si < database.Sections.Size(); si++)
{
CSectionInfo &section = database.Sections[si];
- AString sectionPrefix = GetSectionPrefix(section.Name);
+ AString sectionPrefix (GetSectionPrefix(section.Name));
{
// Content
int index = database.FindItem(sectionPrefix + kContent);
@@ -774,7 +737,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
section.Offset = item.Offset;
section.CompressedSize = item.Size;
}
- AString transformPrefix = sectionPrefix + kTransform;
+ AString transformPrefix (sectionPrefix + kTransform);
if (database.Help2Format)
{
// Transform List
@@ -794,7 +757,7 @@ HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
else
{
CMethodInfo method;
- method.Guid = kChmLzxGuid;
+ memcpy(method.Guid, kChmLzxGuid, 16);
section.Methods.Add(method);
}
diff --git a/CPP/7zip/Archive/Chm/ChmIn.h b/CPP/7zip/Archive/Chm/ChmIn.h
index bf51616f..f7b75d81 100644
--- a/CPP/7zip/Archive/Chm/ChmIn.h
+++ b/CPP/7zip/Archive/Chm/ChmIn.h
@@ -149,14 +149,14 @@ struct CLzxInfo
struct CMethodInfo
{
- GUID Guid;
+ Byte Guid[16];
CByteBuffer ControlData;
CLzxInfo LzxInfo;
bool IsLzx() const;
bool IsDes() const;
AString GetGuidString() const;
- UString GetName() const;
+ AString GetName() const;
};
@@ -243,7 +243,7 @@ class CInArchive
UInt64 ReadEncInt();
void ReadString(unsigned size, AString &s);
void ReadUString(unsigned size, UString &s);
- void ReadGUID(GUID &g);
+ void ReadGUID(Byte *g);
HRESULT ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size);
diff --git a/CPP/7zip/Archive/ComHandler.cpp b/CPP/7zip/Archive/ComHandler.cpp
index c6d2bd25..d2dc6c5f 100644
--- a/CPP/7zip/Archive/ComHandler.cpp
+++ b/CPP/7zip/Archive/ComHandler.cpp
@@ -239,9 +239,6 @@ HRESULT CDatabase::AddNode(int parent, UInt32 did)
return S_OK;
}
-static const wchar_t kCharOpenBracket = L'[';
-static const wchar_t kCharCloseBracket = L']';
-
static UString CompoundNameToFileName(const UString &s)
{
UString res;
@@ -250,11 +247,9 @@ static UString CompoundNameToFileName(const UString &s)
wchar_t c = s[i];
if (c < 0x20)
{
- res += kCharOpenBracket;
- wchar_t buf[32];
- ConvertUInt32ToString(c, buf);
- res += buf;
- res += kCharCloseBracket;
+ res += '[';
+ res.Add_UInt32(c);
+ res += ']';
}
else
res += c;
@@ -265,8 +260,8 @@ static UString CompoundNameToFileName(const UString &s)
static const char k_Msi_Chars[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._";
-// static const char *k_Msi_ID = ""; // "{msi}";
-static const wchar_t k_Msi_SpecChar = L'!';
+// static const char * const k_Msi_ID = ""; // "{msi}";
+static const char k_Msi_SpecChar = '!';
static const unsigned k_Msi_NumBits = 6;
static const unsigned k_Msi_NumChars = 1 << k_Msi_NumBits;
@@ -316,10 +311,10 @@ static bool CompoundMsiNameToFileName(const UString &name, UString &res)
if (c1 <= k_Msi_NumChars)
{
- res += (wchar_t)(Byte)k_Msi_Chars[c0];
+ res += k_Msi_Chars[c0];
if (c1 == k_Msi_NumChars)
break;
- res += (wchar_t)(Byte)k_Msi_Chars[c1];
+ res += k_Msi_Chars[c1];
}
else
res += k_Msi_SpecChar;
diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp
index 41b5805c..7834c605 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp
@@ -60,6 +60,62 @@ static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
p[i] = false;
}
+
+HRESULT CCoder::CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const
+{
+ if (Coder)
+ {
+ if (PackSizePointers.IsEmpty() || !PackSizePointers[0])
+ return S_OK;
+ CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize;
+ Coder.QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize);
+ // if (!getInStreamProcessedSize) return E_FAIL;
+ if (getInStreamProcessedSize)
+ {
+ UInt64 processed;
+ RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&processed));
+ if (processed != (UInt64)(Int64)-1)
+ {
+ const UInt64 size = PackSizes[0];
+ if (processed < size && Finish)
+ dataAfterEnd_Error = true;
+ if (processed > size)
+ {
+ // InternalPackSizeError = true;
+ // return S_FALSE;
+ }
+ }
+ }
+ }
+ else if (Coder2)
+ {
+ CMyComPtr<ICompressGetInStreamProcessedSize2> getInStreamProcessedSize2;
+ Coder2.QueryInterface(IID_ICompressGetInStreamProcessedSize2, (void **)&getInStreamProcessedSize2);
+ FOR_VECTOR (i, PackSizePointers)
+ {
+ if (!PackSizePointers[i])
+ continue;
+ UInt64 processed;
+ RINOK(getInStreamProcessedSize2->GetInStreamProcessedSize2(i, &processed));
+ if (processed != (UInt64)(Int64)-1)
+ {
+ const UInt64 size = PackSizes[i];
+ if (processed < size && Finish)
+ dataAfterEnd_Error = true;
+ else if (processed > size)
+ {
+ // InternalPackSizeError = true;
+ // return S_FALSE;
+ }
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+
+
class CBondsChecks
{
CBoolVector _coderUsed;
@@ -151,8 +207,10 @@ bool CBindInfo::CalcMapsAndCheck()
}
-void CCoder::SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes)
+void CCoder::SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
{
+ Finish = finish;
+
if (unpackSize)
{
UnpackSize = *unpackSize;
@@ -640,8 +698,12 @@ void CMixerST::SelectMainCoder(bool useFirst)
HRESULT CMixerST::Code(
ISequentialInStream * const *inStreams,
ISequentialOutStream * const *outStreams,
- ICompressProgressInfo *progress)
+ ICompressProgressInfo *progress,
+ bool &dataAfterEnd_Error)
{
+ // InternalPackSizeError = false;
+ dataAfterEnd_Error = false;
+
_binderStreams.Clear();
unsigned ci = MainCoderIndex;
@@ -742,7 +804,16 @@ HRESULT CMixerST::Code(
if (res == k_My_HRESULT_WritingWasCut)
res = S_OK;
- return res;
+
+ if (res != S_OK)
+ return res;
+
+ for (i = 0; i < _coders.Size(); i++)
+ {
+ RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /*, InternalPackSizeError */));
+ }
+
+ return S_OK;
}
@@ -988,8 +1059,12 @@ HRESULT CMixerMT::ReturnIfError(HRESULT code)
HRESULT CMixerMT::Code(
ISequentialInStream * const *inStreams,
ISequentialOutStream * const *outStreams,
- ICompressProgressInfo *progress)
+ ICompressProgressInfo *progress,
+ bool &dataAfterEnd_Error)
{
+ // InternalPackSizeError = false;
+ dataAfterEnd_Error = false;
+
Init(inStreams, outStreams);
unsigned i;
@@ -1031,6 +1106,11 @@ HRESULT CMixerMT::Code(
return result;
}
+ for (i = 0; i < _coders.Size(); i++)
+ {
+ RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /* , InternalPackSizeError */));
+ }
+
return S_OK;
}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2.h b/CPP/7zip/Archive/Common/CoderMixer2.h
index e63f2ff0..798411ab 100644
--- a/CPP/7zip/Archive/Common/CoderMixer2.h
+++ b/CPP/7zip/Archive/Common/CoderMixer2.h
@@ -201,9 +201,13 @@ public:
CRecordVector<UInt64> PackSizes;
CRecordVector<const UInt64 *> PackSizePointers;
- CCoder() {}
+ bool Finish;
- void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes);
+ CCoder(): Finish(false) {}
+
+ void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish);
+
+ HRESULT CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const;
IUnknown *GetUnknown() const
{
@@ -239,9 +243,12 @@ protected:
public:
unsigned MainCoderIndex;
+ // bool InternalPackSizeError;
+
CMixer(bool encodeMode):
EncodeMode(encodeMode),
MainCoderIndex(0)
+ // , InternalPackSizeError(false)
{}
/*
@@ -273,11 +280,12 @@ public:
virtual CCoder &GetCoder(unsigned index) = 0;
virtual void SelectMainCoder(bool useFirst) = 0;
virtual void ReInit() = 0;
- virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) = 0;
+ virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) = 0;
virtual HRESULT Code(
ISequentialInStream * const *inStreams,
ISequentialOutStream * const *outStreams,
- ICompressProgressInfo *progress) = 0;
+ ICompressProgressInfo *progress,
+ bool &dataAfterEnd_Error) = 0;
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0;
bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex);
@@ -338,12 +346,13 @@ public:
virtual CCoder &GetCoder(unsigned index);
virtual void SelectMainCoder(bool useFirst);
virtual void ReInit();
- virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
- { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
+ virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
+ { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
virtual HRESULT Code(
ISequentialInStream * const *inStreams,
ISequentialOutStream * const *outStreams,
- ICompressProgressInfo *progress);
+ ICompressProgressInfo *progress,
+ bool &dataAfterEnd_Error);
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
HRESULT GetMainUnpackStream(
@@ -419,12 +428,13 @@ public:
virtual CCoder &GetCoder(unsigned index);
virtual void SelectMainCoder(bool useFirst);
virtual void ReInit();
- virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes)
- { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); }
+ virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)
+ { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }
virtual HRESULT Code(
ISequentialInStream * const *inStreams,
ISequentialOutStream * const *outStreams,
- ICompressProgressInfo *progress);
+ ICompressProgressInfo *progress,
+ bool &dataAfterEnd_Error);
virtual UInt64 GetBondStreamSize(unsigned bondIndex) const;
CMixerMT(bool encodeMode): CMixer(encodeMode) {}
diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp
index 30ca73bd..ea320e66 100644
--- a/CPP/7zip/Archive/Common/HandlerOut.cpp
+++ b/CPP/7zip/Archive/Common/HandlerOut.cpp
@@ -20,20 +20,19 @@ static void SetMethodProp32(COneMethodInfo &m, PROPID propID, UInt32 value)
m.AddProp32(propID, value);
}
-void CMultiMethodProps::SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo
- #ifndef _7ZIP_ST
- , UInt32 numThreads
- #endif
- )
+void CMultiMethodProps::SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const
{
UInt32 level = _level;
if (level != (UInt32)(Int32)-1)
SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level);
-
- #ifndef _7ZIP_ST
+}
+
+#ifndef _7ZIP_ST
+void CMultiMethodProps::SetMethodThreadsTo(COneMethodInfo &oneMethodInfo, UInt32 numThreads)
+{
SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
- #endif
}
+#endif
void CMultiMethodProps::Init()
{
@@ -73,7 +72,7 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN
return S_OK;
}
- if (name.IsEqualTo("crc"))
+ if (name.IsPrefixedBy_Ascii_NoCase("crc"))
{
name.Delete(0, 3);
_crcSize = 4;
diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h
index 5a18d980..e24686da 100644
--- a/CPP/7zip/Archive/Common/HandlerOut.h
+++ b/CPP/7zip/Archive/Common/HandlerOut.h
@@ -22,11 +22,13 @@ public:
COneMethodInfo _filterMethod;
bool _autoFilter;
- void SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo
- #ifndef _7ZIP_ST
- , UInt32 numThreads
- #endif
- );
+
+ void SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const;
+
+ #ifndef _7ZIP_ST
+ static void SetMethodThreadsTo(COneMethodInfo &oneMethodInfo, UInt32 numThreads);
+ #endif
+
unsigned GetNumEmptyMethods() const
{
diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp
index 7cd3037b..d5093a24 100644
--- a/CPP/7zip/Archive/Common/ItemNameUtils.cpp
+++ b/CPP/7zip/Archive/Common/ItemNameUtils.cpp
@@ -7,58 +7,57 @@
namespace NArchive {
namespace NItemName {
-static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR;
-static const wchar_t kDirDelimiter = L'/';
+static const wchar_t kOsPathSepar = WCHAR_PATH_SEPARATOR;
+static const wchar_t kUnixPathSepar = L'/';
-void ReplaceToOsPathSeparator(wchar_t *s)
-{
- #ifdef _WIN32
- for (;;)
+void ReplaceSlashes_OsToUnix
+#if WCHAR_PATH_SEPARATOR != L'/'
+ (UString &name)
{
- wchar_t c = *s;
- if (c == 0)
- break;
- if (c == kDirDelimiter)
- *s = kOSDirDelimiter;
- s++;
+ name.Replace(kOsPathSepar, kUnixPathSepar);
}
- #endif
-}
+#else
+ (UString &) {}
+#endif
-UString MakeLegalName(const UString &name)
-{
- UString zipName = name;
- zipName.Replace(kOSDirDelimiter, kDirDelimiter);
- return zipName;
-}
-UString GetOSName(const UString &name)
+UString GetOsPath(const UString &name)
{
- UString newName = name;
- newName.Replace(kDirDelimiter, kOSDirDelimiter);
- return newName;
+ #if WCHAR_PATH_SEPARATOR != L'/'
+ UString newName = name;
+ newName.Replace(kUnixPathSepar, kOsPathSepar);
+ return newName;
+ #else
+ return name;
+ #endif
}
-UString GetOSName2(const UString &name)
+
+UString GetOsPath_Remove_TailSlash(const UString &name)
{
if (name.IsEmpty())
return UString();
- UString newName = GetOSName(name);
- if (newName.Back() == kOSDirDelimiter)
+ UString newName = GetOsPath(name);
+ if (newName.Back() == kOsPathSepar)
newName.DeleteBack();
return newName;
}
-void ConvertToOSName2(UString &name)
+
+void ReplaceToOsSlashes_Remove_TailSlash(UString &name)
{
if (!name.IsEmpty())
{
- name.Replace(kDirDelimiter, kOSDirDelimiter);
- if (name.Back() == kOSDirDelimiter)
+ #if WCHAR_PATH_SEPARATOR != L'/'
+ name.Replace(kUnixPathSepar, kOsPathSepar);
+ #endif
+
+ if (name.Back() == kOsPathSepar)
name.DeleteBack();
}
}
+
bool HasTailSlash(const AString &name, UINT
#if defined(_WIN32) && !defined(UNDER_CE)
codePage
@@ -67,20 +66,21 @@ bool HasTailSlash(const AString &name, UINT
{
if (name.IsEmpty())
return false;
- LPCSTR prev =
- #if defined(_WIN32) && !defined(UNDER_CE)
- CharPrevExA((WORD)codePage, name, &name[name.Len()], 0);
- #else
- (LPCSTR)(name) + (name.Len() - 1);
- #endif
- return (*prev == '/');
+ char c =
+ #if defined(_WIN32) && !defined(UNDER_CE)
+ *CharPrevExA((WORD)codePage, name, name.Ptr(name.Len()), 0);
+ #else
+ name.Back();
+ #endif
+ return (c == '/');
}
+
#ifndef _WIN32
-UString WinNameToOSName(const UString &name)
+UString WinPathToOsPath(const UString &name)
{
UString newName = name;
- newName.Replace(L'\\', kOSDirDelimiter);
+ newName.Replace(L'\\', WCHAR_PATH_SEPARATOR);
return newName;
}
#endif
diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.h b/CPP/7zip/Archive/Common/ItemNameUtils.h
index d0dc76a4..31150864 100644
--- a/CPP/7zip/Archive/Common/ItemNameUtils.h
+++ b/CPP/7zip/Archive/Common/ItemNameUtils.h
@@ -8,19 +8,20 @@
namespace NArchive {
namespace NItemName {
- void ReplaceToOsPathSeparator(wchar_t *s);
-
- UString MakeLegalName(const UString &name);
- UString GetOSName(const UString &name);
- UString GetOSName2(const UString &name);
- void ConvertToOSName2(UString &name);
- bool HasTailSlash(const AString &name, UINT codePage);
-
- #ifdef _WIN32
- inline UString WinNameToOSName(const UString &name) { return name; }
- #else
- UString WinNameToOSName(const UString &name);
- #endif
+void ReplaceSlashes_OsToUnix(UString &name);
+
+UString GetOsPath(const UString &name);
+UString GetOsPath_Remove_TailSlash(const UString &name);
+
+void ReplaceToOsSlashes_Remove_TailSlash(UString &name);
+
+bool HasTailSlash(const AString &name, UINT codePage);
+
+#ifdef _WIN32
+ inline UString WinPathToOsPath(const UString &name) { return name; }
+#else
+ UString WinPathToOsPath(const UString &name);
+#endif
}}
diff --git a/CPP/7zip/Archive/CpioHandler.cpp b/CPP/7zip/Archive/CpioHandler.cpp
index e8898cac..b8fb530f 100644
--- a/CPP/7zip/Archive/CpioHandler.cpp
+++ b/CPP/7zip/Archive/CpioHandler.cpp
@@ -36,7 +36,7 @@ static const Byte kMagicHex = '1'; // New ASCII Format
static const Byte kMagicHexCrc = '2'; // New CRC Format
static const Byte kMagicOct = '7'; // Portable ASCII Format
-static const char *kName_TRAILER = "TRAILER!!!";
+static const char * const kName_TRAILER = "TRAILER!!!";
static const unsigned k_BinRecord_Size = 2 + 8 * 2 + 2 * 4;
static const unsigned k_OctRecord_Size = 6 + 8 * 6 + 2 * 11;
@@ -627,7 +627,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
#endif
if (needConvert)
res = MultiByteToUnicodeString(item.Name, CP_OEMCP);
- prop = NItemName::GetOSName(res);
+ prop = NItemName::GetOsPath(res);
break;
}
case kpidIsDir: prop = item.IsDir(); break;
diff --git a/CPP/7zip/Archive/DmgHandler.cpp b/CPP/7zip/Archive/DmgHandler.cpp
index 09952ac8..8acbcea6 100644
--- a/CPP/7zip/Archive/DmgHandler.cpp
+++ b/CPP/7zip/Archive/DmgHandler.cpp
@@ -183,6 +183,30 @@ struct CExtraFile
};
#endif
+
+struct CForkPair
+{
+ UInt64 Offset;
+ UInt64 Len;
+
+ void Parse(const Byte *p)
+ {
+ Offset = Get64(p);
+ Len = Get64(p + 8);
+ }
+
+ bool UpdateTop(UInt64 limit, UInt64 &top)
+ {
+ if (Offset > limit || Len > limit - Offset)
+ return false;
+ UInt64 top2 = Offset + Len;
+ if (top <= top2)
+ top = top2;
+ return true;
+ }
+};
+
+
class CHandler:
public IInArchive,
public IInArchiveGetStream,
@@ -191,14 +215,19 @@ class CHandler:
CMyComPtr<IInStream> _inStream;
CObjectVector<CFile> _files;
bool _masterCrcError;
+ bool _headersError;
UInt64 _startPos;
UInt64 _phySize;
+
+ AString _name;
#ifdef DMG_SHOW_RAW
CObjectVector<CExtraFile> _extras;
#endif
+ HRESULT ReadData(IInStream *stream, const CForkPair &pair, CByteBuffer &buf);
+ bool ParseBlob(const CByteBuffer &data);
HRESULT Open2(IInStream *stream);
HRESULT Extract(IInStream *stream);
public:
@@ -249,24 +278,20 @@ void CMethods::GetString(AString &res) const
case METHOD_BZIP2: s = "BZip2"; break;
default: ConvertUInt32ToString(type, buf); s = buf;
}
- res.Add_Space_if_NotEmpty();
- res += s;
+ res.Add_OptSpaced(s);
}
for (i = 0; i < ChecksumTypes.Size(); i++)
{
+ res.Add_Space_if_NotEmpty();
UInt32 type = ChecksumTypes[i];
- char buf[32];
- const char *s;
switch (type)
{
- case kCheckSumType_CRC: s = "CRC"; break;
+ case kCheckSumType_CRC: res += "CRC"; break;
default:
- ConvertUInt32ToString(type, MyStpCpy(buf, "Check"));
- s = buf;
+ res += "Check";
+ res.Add_UInt32(type);
}
- res.Add_Space_if_NotEmpty();
- res += s;
}
}
@@ -308,7 +333,8 @@ IMP_IInArchive_Props
static const Byte kArcProps[] =
{
kpidMethod,
- kpidNumBlocks
+ kpidNumBlocks,
+ kpidComment
};
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
@@ -372,9 +398,30 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidWarning:
if (_masterCrcError)
prop = "Master CRC error";
+
+ case kpidWarningFlags:
+ {
+ UInt32 v = 0;
+ if (_headersError) v |= kpv_ErrorFlags_HeadersError;
+ if (v != 0)
+ prop = v;
break;
+ }
+
case kpidOffset: prop = _startPos; break;
case kpidPhySize: prop = _phySize; break;
+
+ case kpidComment:
+ if (!_name.IsEmpty() && _name.Len() < 256)
+ prop = _name;
+ break;
+
+ case kpidName:
+ if (!_name.IsEmpty() && _name.Len() < 256)
+ {
+ prop = _name + ".dmg";
+ }
+ break;
}
prop.Detach(value);
return S_OK;
@@ -461,7 +508,7 @@ HRESULT CFile::Parse(const Byte *p, UInt32 size)
return S_OK;
}
-static int FindKeyPair(const CXmlItem &item, const AString &key, const AString &nextTag)
+static int FindKeyPair(const CXmlItem &item, const char *key, const char *nextTag)
{
for (unsigned i = 0; i + 1 < item.SubItems.Size(); i++)
{
@@ -472,7 +519,7 @@ static int FindKeyPair(const CXmlItem &item, const AString &key, const AString &
return -1;
}
-static const AString *GetStringFromKeyPair(const CXmlItem &item, const AString &key, const AString &nextTag)
+static const AString *GetStringFromKeyPair(const CXmlItem &item, const char *key, const char *nextTag)
{
int index = FindKeyPair(item, key, nextTag);
if (index >= 0)
@@ -498,6 +545,83 @@ static inline bool IsKoly(const Byte *p)
*/
}
+
+HRESULT CHandler::ReadData(IInStream *stream, const CForkPair &pair, CByteBuffer &buf)
+{
+ size_t size = (size_t)pair.Len;
+ if (size != pair.Len)
+ return E_OUTOFMEMORY;
+ buf.Alloc(size);
+ RINOK(stream->Seek(_startPos + pair.Offset, STREAM_SEEK_SET, NULL));
+ return ReadStream_FALSE(stream, buf, size);
+}
+
+
+bool CHandler::ParseBlob(const CByteBuffer &data)
+{
+ if (data.Size() < 12)
+ return false;
+ const Byte *p = (const Byte *)data;
+ if (Get32(p) != 0xFADE0CC0)
+ return true;
+ const UInt32 size = Get32(p + 4);
+ if (size != data.Size())
+ return false;
+ const UInt32 num = Get32(p + 8);
+ if (num > (size - 12) / 8)
+ return false;
+
+ for (UInt32 i = 0; i < num; i++)
+ {
+ // UInt32 type = Get32(p + i * 8 + 12);
+ UInt32 offset = Get32(p + i * 8 + 12 + 4);
+ if (size - offset < 8)
+ return false;
+ const Byte *p2 = (const Byte *)data + offset;
+ const UInt32 magic = Get32(p2);
+ const UInt32 len = Get32(p2 + 4);
+ if (size - offset < len || len < 8)
+ return false;
+
+ #ifdef DMG_SHOW_RAW
+ CExtraFile &extra = _extras.AddNew();
+ extra.Name = "_blob_";
+ extra.Data.CopyFrom(p2, len);
+ #endif
+
+ if (magic == 0xFADE0C02)
+ {
+ #ifdef DMG_SHOW_RAW
+ extra.Name += "codedir";
+ #endif
+
+ if (len < 11 * 4)
+ return false;
+ UInt32 idOffset = Get32(p2 + 0x14);
+ if (idOffset >= len)
+ return false;
+ UInt32 len2 = len - idOffset;
+ if (len2 < (1 << 10))
+ _name.SetFrom_CalcLen((const char *)(p2 + idOffset), len2);
+ }
+ #ifdef DMG_SHOW_RAW
+ else if (magic == 0xFADE0C01)
+ extra.Name += "requirements";
+ else if (magic == 0xFADE0B01)
+ extra.Name += "signed";
+ else
+ {
+ char temp[16];
+ ConvertUInt32ToHex8Digits(magic, temp);
+ extra.Name += temp;
+ }
+ #endif
+ }
+
+ return true;
+}
+
+
HRESULT CHandler::Open2(IInStream *stream)
{
RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_startPos));
@@ -522,35 +646,69 @@ HRESULT CHandler::Open2(IInStream *stream)
// UInt32 flags = Get32(buf + 12);
// UInt64 runningDataForkOffset = Get64(buf + 0x10);
- UInt64 dataForkOffset = Get64(buf + 0x18);
- UInt64 dataForkLen = Get64(buf + 0x20);
- UInt64 rsrcOffset = Get64(buf + 0x28);
- UInt64 rsrcLen = Get64(buf + 0x30);
+
+ CForkPair dataForkPair, rsrcPair, xmlPair, blobPair;
+
+ dataForkPair.Parse(buf + 0x18);
+ rsrcPair.Parse(buf + 0x28);
+ xmlPair.Parse(buf + 0xD8);
+ blobPair.Parse(buf + 0x128);
+
// UInt32 segmentNumber = Get32(buf + 0x38);
// UInt32 segmentCount = Get32(buf + 0x3C);
// Byte segmentGUID[16];
// CChecksum dataForkChecksum;
// dataForkChecksum.Parse(buf + 0x50);
- UInt64 xmlOffset = Get64(buf + 0xD8);
- UInt64 xmlLen = Get64(buf + 0xE0);
-
- if ( headerPos < dataForkOffset
- || headerPos - dataForkOffset < dataForkLen
- || headerPos < rsrcOffset
- || headerPos - rsrcOffset < rsrcLen
- || headerPos < xmlOffset
- || headerPos - xmlOffset < xmlLen)
- return S_FALSE;
- UInt64 totalLen = dataForkLen + rsrcLen + xmlLen;
- if (totalLen > headerPos)
- return S_FALSE;
- _startPos = headerPos - totalLen;
- _phySize = totalLen + HEADER_SIZE;
- headerPos = totalLen;
+ _startPos = 0;
+
+ UInt64 top = 0;
+ if (!dataForkPair.UpdateTop(headerPos, top)) return S_FALSE;
+ if (!xmlPair.UpdateTop(headerPos, top)) return S_FALSE;
+ if (!rsrcPair.UpdateTop(headerPos, top)) return S_FALSE;
+
+ /* Some old dmg files contain garbage data in blobPair field.
+ So we need to ignore such garbage case;
+ And we still need to detect offset of start of archive for "parser" mode. */
+
+ bool useBlob = blobPair.UpdateTop(headerPos, top);
+
+ _startPos = 0;
+ _phySize = headerPos + HEADER_SIZE;
+
+ if (top != headerPos)
+ {
+ CForkPair xmlPair2 = xmlPair;
+ const char *sz = "<?xml version";
+ const unsigned len = (unsigned)strlen(sz);
+ if (xmlPair2.Len > len)
+ xmlPair2.Len = len;
+ CByteBuffer buf2;
+ if (ReadData(stream, xmlPair2, buf2) != S_OK
+ || memcmp(buf2, sz, len) != 0)
+ {
+ _startPos = headerPos - top;
+ _phySize = top + HEADER_SIZE;
+ }
+ }
// Byte reserved[0x78]
+ if (useBlob && blobPair.Len != 0)
+ {
+ #ifdef DMG_SHOW_RAW
+ CExtraFile &extra = _extras.AddNew();
+ extra.Name = "_blob.bin";
+ CByteBuffer &blobBuf = extra.Data;
+ #else
+ CByteBuffer blobBuf;
+ #endif
+ RINOK(ReadData(stream, blobPair, blobBuf));
+ if (!ParseBlob(blobBuf))
+ _headersError = true;
+ }
+
+
CChecksum masterChecksum;
masterChecksum.Parse(buf + 0x160);
@@ -562,7 +720,7 @@ HRESULT CHandler::Open2(IInStream *stream)
// We don't know the size of the field "offset" in rsrc.
// We suppose that it uses 24 bits. So we use Rsrc, only if the rsrcLen < (1 << 24).
- bool useRsrc = (rsrcLen > RSRC_HEAD_SIZE && rsrcLen < ((UInt32)1 << 24));
+ bool useRsrc = (rsrcPair.Len > RSRC_HEAD_SIZE && rsrcPair.Len < ((UInt32)1 << 24));
// useRsrc = false;
if (useRsrc)
@@ -575,21 +733,18 @@ HRESULT CHandler::Open2(IInStream *stream)
CByteBuffer rsrcBuf;
#endif
- size_t rsrcLenT = (size_t)rsrcLen;
- rsrcBuf.Alloc(rsrcLenT);
- RINOK(stream->Seek(_startPos + rsrcOffset, STREAM_SEEK_SET, NULL));
- RINOK(ReadStream_FALSE(stream, rsrcBuf, rsrcLenT));
+ RINOK(ReadData(stream, rsrcPair, rsrcBuf));
const Byte *p = rsrcBuf;
UInt32 headSize = Get32(p + 0);
UInt32 footerOffset = Get32(p + 4);
UInt32 mainDataSize = Get32(p + 8);
UInt32 footerSize = Get32(p + 12);
- if (headSize != RSRC_HEAD_SIZE ||
- footerOffset >= rsrcLenT ||
- mainDataSize >= rsrcLenT ||
- footerOffset + footerSize != rsrcLenT ||
- footerOffset != headSize + mainDataSize)
+ if (headSize != RSRC_HEAD_SIZE
+ || footerOffset >= rsrcPair.Len
+ || mainDataSize >= rsrcPair.Len
+ || footerOffset + footerSize != rsrcPair.Len
+ || footerOffset != headSize + mainDataSize)
return S_FALSE;
if (footerSize < 16)
return S_FALSE;
@@ -600,7 +755,7 @@ HRESULT CHandler::Open2(IInStream *stream)
if ((UInt32)Get16(p + 0x18) != 0x1C)
return S_FALSE;
- UInt32 namesOffset = Get16(p + 0x1A);
+ const UInt32 namesOffset = Get16(p + 0x1A);
if (namesOffset > footerSize)
return S_FALSE;
@@ -612,12 +767,15 @@ HRESULT CHandler::Open2(IInStream *stream)
{
const Byte *p2 = p + 0x1E + i * 8;
- UInt32 typeId = Get32(p2);
+ const UInt32 typeId = Get32(p2);
+
+ #ifndef DMG_SHOW_RAW
if (typeId != 0x626C6B78) // blkx
continue;
+ #endif
- UInt32 numFiles = (UInt32)Get16(p2 + 4) + 1;
- UInt32 offs = Get16(p2 + 6);
+ const UInt32 numFiles = (UInt32)Get16(p2 + 4) + 1;
+ const UInt32 offs = Get16(p2 + 6);
if (0x1C + offs + 12 * numFiles > namesOffset)
return S_FALSE;
@@ -625,7 +783,7 @@ HRESULT CHandler::Open2(IInStream *stream)
{
const Byte *p3 = p + 0x1C + offs + k * 12;
// UInt32 id = Get16(p3);
- UInt32 namePos = Get16(p3 + 2);
+ const UInt32 namePos = Get16(p3 + 2);
// Byte attributes = p3[4]; // = 0x50 for blkx
// we don't know how many bits we can use. So we use 24 bits only
UInt32 blockOffset = Get32(p3 + 4);
@@ -634,21 +792,12 @@ HRESULT CHandler::Open2(IInStream *stream)
if (blockOffset + 4 >= mainDataSize)
return S_FALSE;
const Byte *pBlock = rsrcBuf + headSize + blockOffset;
- UInt32 blockSize = Get32(pBlock);
-
- #ifdef DMG_SHOW_RAW
- {
- CExtraFile &extra = _extras.AddNew();
- {
- char extraName[16];
- ConvertUInt32ToString(_files.Size(), extraName);
- extra.Name = extraName;
- }
- extra.Data.CopyFrom(pBlock + 4, blockSize);
- }
- #endif
+ const UInt32 blockSize = Get32(pBlock);
+ if (mainDataSize - (blockOffset + 4) < blockSize)
+ return S_FALSE;
+
+ AString name;
- CFile &file = _files.AddNew();
if (namePos != 0xFFFF)
{
UInt32 namesBlockSize = footerSize - namesOffset;
@@ -663,22 +812,56 @@ HRESULT CHandler::Open2(IInStream *stream)
Byte c = namePtr[r];
if (c < 0x20 || c >= 0x80)
break;
- file.Name += (char)c;
+ name += (char)c;
+ }
+ }
+
+ if (typeId == 0x626C6B78) // blkx
+ {
+ CFile &file = _files.AddNew();
+ file.Name = name;
+ RINOK(file.Parse(pBlock + 4, blockSize));
+ }
+
+ #ifdef DMG_SHOW_RAW
+ {
+ AString name2;
+
+ name2.Add_UInt32(i);
+ name2 += '_';
+
+ {
+ char temp[4 + 1] = { 0 };
+ memcpy(temp, p2, 4);
+ name2 += temp;
+ }
+ name2.Trim();
+ name2 += '_';
+ name2.Add_UInt32(k);
+
+ if (!name.IsEmpty())
+ {
+ name2 += '_';
+ name2 += name;
}
+
+ CExtraFile &extra = _extras.AddNew();
+ extra.Name = name2;
+ extra.Data.CopyFrom(pBlock + 4, blockSize);
}
- RINOK(file.Parse(pBlock + 4, blockSize));
+ #endif
}
}
}
else
{
- if (xmlLen >= kXmlSizeMax || xmlLen == 0)
+ if (xmlPair.Len >= kXmlSizeMax || xmlPair.Len == 0)
return S_FALSE;
- size_t size = (size_t)xmlLen;
- if (size != xmlLen)
+ size_t size = (size_t)xmlPair.Len;
+ if (size != xmlPair.Len)
return S_FALSE;
- RINOK(stream->Seek(_startPos + dataForkLen, STREAM_SEEK_SET, NULL));
+ RINOK(stream->Seek(_startPos + xmlPair.Offset, STREAM_SEEK_SET, NULL));
CXml xml;
{
@@ -733,16 +916,12 @@ HRESULT CHandler::Open2(IInStream *stream)
const Byte *endPtr = Base64ToBin(rawBuf, *dataString);
if (!endPtr)
return S_FALSE;
- destLen = (unsigned)(endPtr - rawBuf);
+ destLen = (unsigned)(endPtr - (const Byte *)rawBuf);
}
#ifdef DMG_SHOW_RAW
CExtraFile &extra = _extras.AddNew();
- {
- char extraName[16];
- ConvertUInt32ToString(_files.Size(), extraName);
- extra.Name = extraName;
- }
+ extra.Name.Add_UInt32(_files.Size());
extra.Data.CopyFrom(rawBuf, destLen);
#endif
}
@@ -800,6 +979,8 @@ STDMETHODIMP CHandler::Close()
_inStream.Release();
_files.Clear();
_masterCrcError = false;
+ _headersError = false;
+ _name.Empty();
#ifdef DMG_SHOW_RAW
_extras.Clear();
#endif
@@ -867,9 +1048,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidPath:
{
UString name;
- wchar_t s[16];
- ConvertUInt32ToString(index, s);
- name = s;
+ name.Add_UInt32(index);
unsigned num = 10;
unsigned numDigits;
for (numDigits = 1; num < _files.Size(); numDigits++)
@@ -908,7 +1087,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
}
UString name2;
ConvertUTF8ToUnicode(subName, name2);
- name += L'.';
+ name += '.';
name += name2;
}
else
@@ -916,7 +1095,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
UString name2;
ConvertUTF8ToUnicode(item.Name, name2);
if (!name2.IsEmpty())
- name.AddAscii(" - ");
+ name += "_";
name += name2;
}
prop = name;
diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp
index 4543b067..62674774 100644
--- a/CPP/7zip/Archive/ElfHandler.cpp
+++ b/CPP/7zip/Archive/ElfHandler.cpp
@@ -158,21 +158,21 @@ bool CHeader::Parse(const Byte *p)
static const char * const g_SegnmentTypes[] =
{
- "Unused",
- "Loadable segment",
- "Dynamic linking tables",
- "Program interpreter path name",
- "Note section",
- "SHLIB",
- "Program header table",
- "TLS"
+ "Unused"
+ , "Loadable segment"
+ , "Dynamic linking tables"
+ , "Program interpreter path name"
+ , "Note section"
+ , "SHLIB"
+ , "Program header table"
+ , "TLS"
};
-static const CUInt32PCharPair g_SegmentFlags[] =
+static const char * const g_SegmentFlags[] =
{
- { 0, "Execute" },
- { 1, "Write" },
- { 2, "Read" }
+ "Execute"
+ , "Write"
+ , "Read"
};
struct CSegment
@@ -359,173 +359,215 @@ bool CSection::Parse(const Byte *p, bool mode64, bool be)
return true;
}
-static const CUInt32PCharPair g_Machines[] =
+
+static const char * const g_Machines[] =
{
- { 0, "None" },
- { 1, "AT&T WE 32100" },
- { 2, "SPARC" },
- { 3, "Intel 386" },
- { 4, "Motorola 68000" },
- { 5, "Motorola 88000" },
- { 6, "Intel 486" },
- { 7, "Intel i860" },
- { 8, "MIPS" },
- { 9, "IBM S/370" },
- { 10, "MIPS RS3000 LE" },
- { 11, "RS6000" },
-
- { 15, "PA-RISC" },
- { 16, "nCUBE" },
- { 17, "Fujitsu VPP500" },
- { 18, "SPARC 32+" },
- { 19, "Intel i960" },
- { 20, "PowerPC" },
- { 21, "PowerPC 64-bit" },
- { 22, "IBM S/390" },
- { 23, "SPU" },
-
- { 36, "NEX v800" },
- { 37, "Fujitsu FR20" },
- { 38, "TRW RH-32" },
- { 39, "Motorola RCE" },
- { 40, "ARM" },
- { 41, "Alpha" },
- { 42, "Hitachi SH" },
- { 43, "SPARC-V9" },
- { 44, "Siemens Tricore" },
- { 45, "ARC" },
- { 46, "H8/300" },
- { 47, "H8/300H" },
- { 48, "H8S" },
- { 49, "H8/500" },
- { 50, "IA-64" },
- { 51, "Stanford MIPS-X" },
- { 52, "Motorola ColdFire" },
- { 53, "M68HC12" },
- { 54, "Fujitsu MMA" },
- { 55, "Siemens PCP" },
- { 56, "Sony nCPU" },
- { 57, "Denso NDR1" },
- { 58, "Motorola StarCore" },
- { 59, "Toyota ME16" },
- { 60, "ST100" },
- { 61, "Advanced Logic TinyJ" },
- { 62, "AMD64" },
- { 63, "Sony DSP" },
-
-
- { 66, "Siemens FX66" },
- { 67, "ST9+" },
- { 68, "ST7" },
- { 69, "MC68HC16" },
- { 70, "MC68HC11" },
- { 71, "MC68HC08" },
- { 72, "MC68HC05" },
- { 73, "Silicon Graphics SVx" },
- { 74, "ST19" },
- { 75, "Digital VAX" },
- { 76, "Axis CRIS" },
- { 77, "Infineon JAVELIN" },
- { 78, "Element 14 FirePath" },
- { 79, "LSI ZSP" },
- { 80, "MMIX" },
- { 81, "HUANY" },
- { 82, "SiTera Prism" },
- { 83, "Atmel AVR" },
- { 84, "Fujitsu FR30" },
- { 85, "Mitsubishi D10V" },
- { 86, "Mitsubishi D30V" },
- { 87, "NEC v850" },
- { 88, "Mitsubishi M32R" },
- { 89, "Matsushita MN10300" },
- { 90, "Matsushita MN10200" },
- { 91, "picoJava" },
- { 92, "OpenRISC" },
- { 93, "ARC Tangent-A5" },
- { 94, "Tensilica Xtensa" },
- { 95, "Alphamosaic VideoCore" },
- { 96, "Thompson MM GPP" },
- { 97, "National Semiconductor 32K" },
- { 98, "Tenor Network TPC" },
- { 99, "Trebia SNP 1000" },
- { 100, "ST200" },
- { 101, "Ubicom IP2xxx" },
- { 102, "MAX" },
- { 103, "NS CompactRISC" },
- { 104, "Fujitsu F2MC16" },
- { 105, "TI msp430" },
- { 106, "Blackfin (DSP)" },
- { 107, "SE S1C33" },
- { 108, "Sharp embedded" },
- { 109, "Arca RISC" },
- { 110, "Unicore" },
- { 111, "eXcess" },
- { 112, "DXP" },
- { 113, "Altera Nios II" },
- { 114, "NS CRX" },
- { 115, "Motorola XGATE" },
- { 116, "Infineon C16x/XC16x" },
- { 117, "Renesas M16C" },
- { 118, "Microchip Technology dsPIC30F" },
- { 119, "Freescale CE" },
- { 120, "Renesas M32C" },
-
- { 131, "Altium TSK3000" },
- { 132, "Freescale RS08" },
- { 133, "Analog Devices SHARC" },
- { 134, "Cyan Technology eCOG2" },
- { 135, "Sunplus S+core7 RISC" },
- { 136, "NJR 24-bit DSP" },
- { 137, "Broadcom VideoCore III" },
- { 138, "Lattice FPGA" },
- { 139, "SE C17" },
- { 140, "TI TMS320C6000" },
- { 141, "TI TMS320C2000" },
- { 142, "TI TMS320C55x" },
-
- { 160, "STM 64bit VLIW Data Signal" },
- { 161, "Cypress M8C" },
- { 162, "Renesas R32C" },
- { 163, "NXP TriMedia" },
- { 164, "Qualcomm Hexagon" },
- { 165, "Intel 8051" },
- { 166, "STMicroelectronics STxP7x" },
- { 167, "Andes" },
- { 168, "Cyan Technology eCOG1X" },
- { 169, "Dallas Semiconductor MAXQ30" },
- { 170, "NJR 16-bit DSP" },
- { 171, "M2000" },
- { 172, "Cray NV2" },
- { 173, "Renesas RX" },
- { 174, "Imagination Technologies META" },
- { 175, "MCST Elbrus" },
- { 176, "Cyan Technology eCOG16" },
- { 177, "National Semiconductor CR16" },
- { 178, "Freescale ETPUnit" },
- { 179, "Infineon SLE9X" },
- { 180, "Intel L10M" },
- { 181, "Intel K10M" },
-
- { 183, "ARM64" },
-
- { 185, "Atmel AVR32" },
- { 186, "STM8" },
- { 187, "Tilera TILE64" },
- { 188, "Tilera TILEPro" },
- { 189, "Xilinx MicroBlaze" },
- { 190, "NVIDIA CUDA" },
- { 191, "Tilera TILE-Gx" },
- { 192, "CloudShield" },
- { 193, "KIPO-KAIST Core-A 1st" },
- { 194, "KIPO-KAIST Core-A 2nd" },
- { 195, "Synopsys ARCompact V2" },
- { 196, "Open8" },
- { 197, "Renesas RL78" },
- { 198, "Broadcom VideoCore V" },
- { 199, "Renesas 78KOR" },
- { 200, "Freescale 56800EX" },
-
- { 47787, "Xilinx MicroBlaze" },
+ "None"
+ , "AT&T WE 32100"
+ , "SPARC"
+ , "Intel 386"
+ , "Motorola 68000"
+ , "Motorola 88000"
+ , "Intel 486"
+ , "Intel i860"
+ , "MIPS"
+ , "IBM S/370"
+ , "MIPS RS3000 LE"
+ , "RS6000"
+ , NULL
+ , NULL
+ , NULL
+ , "PA-RISC"
+ , "nCUBE"
+ , "Fujitsu VPP500"
+ , "SPARC 32+"
+ , "Intel i960"
+ , "PowerPC"
+ , "PowerPC 64-bit"
+ , "IBM S/390"
+ , "SPU"
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , "NEX v800"
+ , "Fujitsu FR20"
+ , "TRW RH-32"
+ , "Motorola RCE"
+ , "ARM"
+ , "Alpha"
+ , "Hitachi SH"
+ , "SPARC-V9"
+ , "Siemens Tricore"
+ , "ARC"
+ , "H8/300"
+ , "H8/300H"
+ , "H8S"
+ , "H8/500"
+ , "IA-64"
+ , "Stanford MIPS-X"
+ , "Motorola ColdFire"
+ , "M68HC12"
+ , "Fujitsu MMA"
+ , "Siemens PCP"
+ , "Sony nCPU"
+ , "Denso NDR1"
+ , "Motorola StarCore"
+ , "Toyota ME16"
+ , "ST100"
+ , "Advanced Logic TinyJ"
+ , "AMD64"
+ , "Sony DSP"
+ , NULL
+ , NULL
+ , "Siemens FX66"
+ , "ST9+"
+ , "ST7"
+ , "MC68HC16"
+ , "MC68HC11"
+ , "MC68HC08"
+ , "MC68HC05"
+ , "Silicon Graphics SVx"
+ , "ST19"
+ , "Digital VAX"
+ , "Axis CRIS"
+ , "Infineon JAVELIN"
+ , "Element 14 FirePath"
+ , "LSI ZSP"
+ , "MMIX"
+ , "HUANY"
+ , "SiTera Prism"
+ , "Atmel AVR"
+ , "Fujitsu FR30"
+ , "Mitsubishi D10V"
+ , "Mitsubishi D30V"
+ , "NEC v850"
+ , "Mitsubishi M32R"
+ , "Matsushita MN10300"
+ , "Matsushita MN10200"
+ , "picoJava"
+ , "OpenRISC"
+ , "ARC Tangent-A5"
+ , "Tensilica Xtensa"
+ , "Alphamosaic VideoCore"
+ , "Thompson MM GPP"
+ , "National Semiconductor 32K"
+ , "Tenor Network TPC"
+ , "Trebia SNP 1000"
+ , "ST200"
+ , "Ubicom IP2xxx"
+ , "MAX"
+ , "NS CompactRISC"
+ , "Fujitsu F2MC16"
+ , "TI msp430"
+ , "Blackfin (DSP)"
+ , "SE S1C33"
+ , "Sharp embedded"
+ , "Arca RISC"
+ , "Unicore"
+ , "eXcess"
+ , "DXP"
+ , "Altera Nios II"
+ , "NS CRX"
+ , "Motorola XGATE"
+ , "Infineon C16x/XC16x"
+ , "Renesas M16C"
+ , "Microchip Technology dsPIC30F"
+ , "Freescale CE"
+ , "Renesas M32C"
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , "Altium TSK3000"
+ , "Freescale RS08"
+ , "Analog Devices SHARC"
+ , "Cyan Technology eCOG2"
+ , "Sunplus S+core7 RISC"
+ , "NJR 24-bit DSP"
+ , "Broadcom VideoCore III"
+ , "Lattice FPGA"
+ , "SE C17"
+ , "TI TMS320C6000"
+ , "TI TMS320C2000"
+ , "TI TMS320C55x"
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , "STM 64bit VLIW Data Signal"
+ , "Cypress M8C"
+ , "Renesas R32C"
+ , "NXP TriMedia"
+ , "Qualcomm Hexagon"
+ , "Intel 8051"
+ , "STMicroelectronics STxP7x"
+ , "Andes"
+ , "Cyan Technology eCOG1X"
+ , "Dallas Semiconductor MAXQ30"
+ , "NJR 16-bit DSP"
+ , "M2000"
+ , "Cray NV2"
+ , "Renesas RX"
+ , "Imagination Technologies META"
+ , "MCST Elbrus"
+ , "Cyan Technology eCOG16"
+ , "National Semiconductor CR16"
+ , "Freescale ETPUnit"
+ , "Infineon SLE9X"
+ , "Intel L10M"
+ , "Intel K10M"
+ , NULL
+ , "ARM64"
+ , NULL
+ , "Atmel AVR32"
+ , "STM8"
+ , "Tilera TILE64"
+ , "Tilera TILEPro"
+ , "Xilinx MicroBlaze"
+ , "NVIDIA CUDA"
+ , "Tilera TILE-Gx"
+ , "CloudShield"
+ , "KIPO-KAIST Core-A 1st"
+ , "KIPO-KAIST Core-A 2nd"
+ , "Synopsys ARCompact V2"
+ , "Open8"
+ , "Renesas RL78"
+ , "Broadcom VideoCore V"
+ , "Renesas 78KOR"
+ , "Freescale 56800EX" // 200
+};
+
+static const CUInt32PCharPair g_MachinePairs[] =
+{
+ { 47787, "Xilinx MicroBlaze" }
// { 0x9026, "Alpha" }
};
@@ -554,6 +596,7 @@ static const CUInt32PCharPair g_OS[] =
{ 255, "Standalone" }
};
+#define k_Machine_MIPS 8
#define k_Machine_ARM 40
/*
@@ -566,12 +609,29 @@ static const CUInt32PCharPair g_OS[] =
static const CUInt32PCharPair g_ARM_Flags[] =
{
+ { 1, "HasEntry" },
{ 9, "SF" },
{ 10, "HF" },
{ 23, "BE8" }
};
+static const CUInt32PCharPair g_MIPS_Flags[] =
+{
+ { 0, "NOREORDER" },
+ { 1, "PIC" },
+ { 2, "CPIC" },
+ { 3, "XGOT" },
+ { 4, "64BIT_WHIRL" },
+ { 5, "ABI2" },
+ { 6, "ABI_ON32" },
+ { 10, "NAN2008" },
+ { 25, "MicroMIPS" },
+ { 26, "M16" },
+ { 27, "MDMX" }
+};
+
+
#define ET_NONE 0
#define ET_REL 1
#define ET_EXEC 2
@@ -580,11 +640,11 @@ static const CUInt32PCharPair g_ARM_Flags[] =
static const char * const g_Types[] =
{
- "None",
- "Relocatable file",
- "Executable file",
- "Shared object file",
- "Core file"
+ "None"
+ , "Relocatable file"
+ , "Executable file"
+ , "Shared object file"
+ , "Core file"
};
@@ -643,8 +703,7 @@ static const Byte kArcProps[] =
kpidBigEndian,
kpidHostOS,
kpidCharacts,
- kpidHeadersSize,
- kpidName
+ kpidHeadersSize
};
enum
@@ -683,21 +742,49 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidCpu:
{
- AString s = TypePairToString(g_Machines, ARRAY_SIZE(g_Machines), _header.Machine);
+ AString s;
+ if (_header.Machine < ARRAY_SIZE(g_Machines))
+ {
+ const char *name = g_Machines[_header.Machine];
+ if (name)
+ s = name;
+ }
+ if (s.IsEmpty())
+ s = TypePairToString(g_MachinePairs, ARRAY_SIZE(g_MachinePairs), _header.Machine);
UInt32 flags = _header.Flags;
if (flags != 0)
{
- char sz[16];
s.Add_Space();
if (_header.Machine == k_Machine_ARM)
{
s += FlagsToString(g_ARM_Flags, ARRAY_SIZE(g_ARM_Flags), flags & (((UInt32)1 << 24) - 1));
s += " ABI:";
- ConvertUInt32ToString(flags >> 24, sz);
+ s.Add_UInt32(flags >> 24);
+ }
+ else if (_header.Machine == k_Machine_MIPS)
+ {
+ UInt32 ver = flags >> 28;
+ s += "v";
+ s.Add_UInt32(ver);
+ flags &= (((UInt32)1 << 28) - 1);
+
+ UInt32 abi = (flags >> 12) & 7;
+ if (abi != 0)
+ {
+ s += " ABI:";
+ s.Add_UInt32(abi);
+ }
+ flags &= ~((UInt32)7 << 12);
+
+ s.Add_Space();
+ s += FlagsToString(g_MIPS_Flags, ARRAY_SIZE(g_MIPS_Flags), flags);
}
else
+ {
+ char sz[16];
ConvertUInt32ToHex(flags, sz);
- s += sz;
+ s += sz;
+ }
}
prop = s;
break;
diff --git a/CPP/7zip/Archive/ExtHandler.cpp b/CPP/7zip/Archive/ExtHandler.cpp
index 6c2cd726..3b690d07 100644
--- a/CPP/7zip/Archive/ExtHandler.cpp
+++ b/CPP/7zip/Archive/ExtHandler.cpp
@@ -20,7 +20,6 @@
#include "../../../C/CpuArch.h"
#include "../../Common/ComTry.h"
-#include "../../Common/IntToString.h"
#include "../../Common/MyLinux.h"
#include "../../Common/StringConvert.h"
#include "../../Common/UTFConvert.h"
@@ -37,6 +36,8 @@
using namespace NWindows;
+UInt32 LzhCrc16Update(UInt32 crc, const void *data, size_t size);
+
namespace NArchive {
namespace NExt {
@@ -87,33 +88,9 @@ static UInt32 Crc32C_Calc(Byte const *data, size_t size)
*/
-// CRC-16-ANSI. The poly is 0x8005 (x^16 + x^15 + x^2 + 1)
-static UInt16 g_Crc16Table[256];
-
-static struct CInitCrc16
-{
- CInitCrc16()
- {
- for (unsigned i = 0; i < 256; i++)
- {
- UInt32 r = i;
- unsigned j;
- for (j = 0; j < 8; j++)
- r = (r >> 1) ^ (0xA001 & ~((r & 1) - 1));
- g_Crc16Table[i] = (UInt16)r;
- }
- }
-} g_InitCrc16;
-
-#define CRC16_UPDATE_BYTE(crc, b) (g_Crc16Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
#define CRC16_INIT_VAL 0xFFFF
-static UInt32 Crc16Update(UInt32 crc, Byte const *data, size_t size)
-{
- for (size_t i = 0; i < size; i++)
- crc = CRC16_UPDATE_BYTE(crc, data[i]);
- return crc;
-}
+#define Crc16Update(crc, data, size) LzhCrc16Update(crc, data, size)
static UInt32 Crc16Calc(Byte const *data, size_t size)
{
@@ -161,64 +138,64 @@ static const char * const kHostOS[] =
, "Lites"
};
-static const CUInt32PCharPair g_FeatureCompat_Flags[] =
-{
- { 0, "DIR_PREALLOC" },
- { 1, "IMAGIC_INODES" },
- { 2, "HAS_JOURNAL" },
- { 3, "EXT_ATTR" },
- { 4, "RESIZE_INODE" },
- { 5, "DIR_INDEX" },
- { 6, "LAZY_BG" }, // not in Linux
- // { 7, "EXCLUDE_INODE" }, // not used
- // { 8, "EXCLUDE_BITMAP" }, // not in kernel
- { 9, "SPARSE_SUPER2" }
+static const char * const g_FeatureCompat_Flags[] =
+{
+ "DIR_PREALLOC"
+ , "IMAGIC_INODES"
+ , "HAS_JOURNAL"
+ , "EXT_ATTR"
+ , "RESIZE_INODE"
+ , "DIR_INDEX"
+ , "LAZY_BG" // not in Linux
+ , NULL // { 7, "EXCLUDE_INODE" // not used
+ , NULL // { 8, "EXCLUDE_BITMAP" // not in kernel
+ , "SPARSE_SUPER2"
};
#define EXT4_FEATURE_INCOMPAT_FILETYPE (1 << 1)
#define EXT4_FEATURE_INCOMPAT_64BIT (1 << 7)
-static const CUInt32PCharPair g_FeatureIncompat_Flags[] =
-{
- { 0, "COMPRESSION" },
- { 1, "FILETYPE" },
- { 2, "RECOVER" }, /* Needs recovery */
- { 3, "JOURNAL_DEV" }, /* Journal device */
- { 4, "META_BG" },
-
- { 6, "EXTENTS" }, /* extents support */
- { 7, "64BIT" },
- { 8, "MMP" },
- { 9, "FLEX_BG" },
- { 10, "EA_INODE" }, /* EA in inode */
-
- { 12, "DIRDATA" }, /* data in dirent */
- { 13, "BG_USE_META_CSUM" }, /* use crc32c for bg */
- { 14, "LARGEDIR" }, /* >2GB or 3-lvl htree */
- { 15, "INLINE_DATA" }, /* data in inode */
- { 16, "ENCRYPT" }
+static const char * const g_FeatureIncompat_Flags[] =
+{
+ "COMPRESSION"
+ , "FILETYPE"
+ , "RECOVER" /* Needs recovery */
+ , "JOURNAL_DEV" /* Journal device */
+ , "META_BG"
+ , NULL
+ , "EXTENTS" /* extents support */
+ , "64BIT"
+ , "MMP"
+ , "FLEX_BG"
+ , "EA_INODE" /* EA in inode */
+ , NULL
+ , "DIRDATA" /* data in dirent */
+ , "BG_USE_META_CSUM" /* use crc32c for bg */
+ , "LARGEDIR" /* >2GB or 3-lvl htree */
+ , "INLINE_DATA" /* data in inode */
+ , "ENCRYPT" // 16
};
static const UInt32 RO_COMPAT_GDT_CSUM = 1 << 4;
static const UInt32 RO_COMPAT_METADATA_CSUM = 1 << 10;
-static const CUInt32PCharPair g_FeatureRoCompat_Flags[] =
-{
- { 0, "SPARSE_SUPER" },
- { 1, "LARGE_FILE" },
- { 2, "BTREE_DIR" },
- { 3, "HUGE_FILE" },
- { 4, "GDT_CSUM" },
- { 5, "DIR_NLINK" },
- { 6, "EXTRA_ISIZE" },
- { 7, "HAS_SNAPSHOT" },
- { 8, "QUOTA" },
- { 9, "BIGALLOC" },
- { 10, "METADATA_CSUM" },
- { 11, "REPLICA" },
- { 12, "READONLY" }
+static const char * const g_FeatureRoCompat_Flags[] =
+{
+ "SPARSE_SUPER"
+ , "LARGE_FILE"
+ , "BTREE_DIR"
+ , "HUGE_FILE"
+ , "GDT_CSUM"
+ , "DIR_NLINK"
+ , "EXTRA_ISIZE"
+ , "HAS_SNAPSHOT"
+ , "QUOTA"
+ , "BIGALLOC"
+ , "METADATA_CSUM"
+ , "REPLICA"
+ , "READONLY" // 12
};
@@ -227,33 +204,37 @@ static const UInt32 k_NodeFlags_HUGE = (UInt32)1 << 18;
static const UInt32 k_NodeFlags_EXTENTS = (UInt32)1 << 19;
-static const CUInt32PCharPair g_NodeFlags[] =
-{
- { 0, "SECRM" },
- { 1, "UNRM" },
- { 2, "COMPR" },
- { 3, "SYNC" },
- { 4, "IMMUTABLE" },
- { 5, "APPEND" },
- { 6, "NODUMP" },
- { 7, "NOATIME" },
- { 8, "DIRTY" },
- { 9, "COMPRBLK" },
- { 10, "NOCOMPR" },
- { 11, "ENCRYPT" },
- { 12, "INDEX" },
- { 13, "IMAGIC" },
- { 14, "JOURNAL_DATA" },
- { 15, "NOTAIL" },
- { 16, "DIRSYNC" },
- { 17, "TOPDIR" },
- { 18, "HUGE_FILE" },
- { 19, "EXTENTS" },
-
- { 21, "EA_INODE" },
- { 22, "EOFBLOCKS" },
-
- { 28, "INLINE_DATA" }
+static const char * const g_NodeFlags[] =
+{
+ "SECRM"
+ , "UNRM"
+ , "COMPR"
+ , "SYNC"
+ , "IMMUTABLE"
+ , "APPEND"
+ , "NODUMP"
+ , "NOATIME"
+ , "DIRTY"
+ , "COMPRBLK"
+ , "NOCOMPR"
+ , "ENCRYPT"
+ , "INDEX"
+ , "IMAGIC"
+ , "JOURNAL_DATA"
+ , "NOTAIL"
+ , "DIRSYNC"
+ , "TOPDIR"
+ , "HUGE_FILE"
+ , "EXTENTS"
+ , NULL
+ , "EA_INODE"
+ , "EOFBLOCKS"
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , "INLINE_DATA" // 28
};
@@ -1540,20 +1521,16 @@ HRESULT CHandler::Open2(IInStream *inStream)
useUnknown = true;
if (item.Name.IsEmpty())
- {
- char temp[16];
- ConvertUInt32ToString(item.Node, temp);
- item.Name = temp;
- }
+ item.Name.Add_UInt32(item.Node);
_items.Add(item);
}
}
if (useSys)
- _auxSysIndex = _auxItems.Add("[SYS]");
+ _auxSysIndex = _auxItems.Add((AString)"[SYS]");
if (useUnknown)
- _auxUnknownIndex = _auxItems.Add("[UNKNOWN]");
+ _auxUnknownIndex = _auxItems.Add((AString)"[UNKNOWN]");
}
return S_OK;
@@ -1834,16 +1811,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidHostOS:
{
- char temp[16];
- const char *s = NULL;
- if (_h.CreatorOs < ARRAY_SIZE(kHostOS))
- s = kHostOS[_h.CreatorOs];
- else
- {
- ConvertUInt32ToString(_h.CreatorOs, temp);
- s = temp;
- }
- prop = s;
+ TYPE_TO_PROP(kHostOS, _h.CreatorOs, prop);
break;
}
@@ -1995,39 +1963,34 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data
static void ExtTimeToProp(const CExtTime &t, NCOM::CPropVariant &prop)
{
- /*
- UInt32 nano = 0;
- if (t.Extra != 0)
- {
- UInt32 mask = t.Extra & 3;
- if (mask != 0)
- return;
- nano = t.Extra >> 2;
- }
- UInt64 v;
- if (t.Val == 0 && nano == 0)
+ if (t.Val == 0 && t.Extra == 0)
return;
- if (!NTime::UnixTime_to_FileTime64(t.Val, v))
- return;
- if (nano != 0)
- v += nano / 100;
FILETIME ft;
- ft.dwLowDateTime = (DWORD)v;
- ft.dwHighDateTime = (DWORD)(v >> 32);
- prop = ft;
- */
- if (t.Val == 0)
- return;
- if (t.Extra != 0)
+ // if (t.Extra != 0)
{
- UInt32 mask = t.Extra & 3;
- if (mask != 0)
- return;
+ // 1901-2446 :
+ Int64 v = (Int64)(Int32)t.Val;
+ v += (UInt64)(t.Extra & 3) << 32; // 2 low bits are offset for main timestamp
+ UInt64 ft64 = NTime::UnixTime64ToFileTime64(v);
+ const UInt32 ns = (t.Extra >> 2);
+ if (ns < 1000000000)
+ ft64 += ns / 100;
+ ft.dwLowDateTime = (DWORD)ft64;
+ ft.dwHighDateTime = (DWORD)(ft64 >> 32);
}
- FILETIME ft;
- if (NTime::UnixTime64ToFileTime(t.Val, ft))
- prop = ft;
+ /*
+ else
+ {
+ // 1901-2038 : that code is good for ext4 and compatibility with Extra
+ NTime::UnixTime64ToFileTime((Int32)t.Val, ft); // for
+
+ // 1970-2106 : that code is good if timestamp is used as unsigned 32-bit
+ // are there such systems?
+ // NTime::UnixTimeToFileTime(t.Val, ft); // for
+ }
+ */
+ prop = ft;
}
@@ -2043,8 +2006,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidPath:
case kpidName:
{
- AString s = _auxItems[index - _items.Size()];
- prop = s;
+ prop = _auxItems[index - _items.Size()];
break;
}
case kpidIsDir: prop = true; break;
diff --git a/CPP/7zip/Archive/GptHandler.cpp b/CPP/7zip/Archive/GptHandler.cpp
index 52c7aab9..a86ad37c 100644
--- a/CPP/7zip/Archive/GptHandler.cpp
+++ b/CPP/7zip/Archive/GptHandler.cpp
@@ -123,33 +123,11 @@ static int FindPartType(const Byte *guid)
return -1;
}
-static inline char GetHex(unsigned t) { return (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))); }
-static void PrintHex(unsigned v, char *s)
+static void RawLeGuidToString_Upper(const Byte *g, char *s)
{
- s[0] = GetHex((v >> 4) & 0xF);
- s[1] = GetHex(v & 0xF);
-}
-
-static void ConvertUInt16ToHex4Digits(UInt32 val, char *s) throw()
-{
- PrintHex(val >> 8, s);
- PrintHex(val & 0xFF, s + 2);
-}
-
-static void GuidToString(const Byte *g, char *s)
-{
- ConvertUInt32ToHex8Digits(Get32(g ), s); s += 8; *s++ = '-';
- ConvertUInt16ToHex4Digits(Get16(g + 4), s); s += 4; *s++ = '-';
- ConvertUInt16ToHex4Digits(Get16(g + 6), s); s += 4; *s++ = '-';
- for (unsigned i = 0; i < 8; i++)
- {
- if (i == 2)
- *s++ = '-';
- PrintHex(g[8 + i], s);
- s += 2;
- }
- *s = 0;
+ RawLeGuidToString(g, s);
+ // MyStringUpper_Ascii(s);
}
@@ -328,7 +306,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidId:
{
char s[48];
- GuidToString(Guid, s);
+ RawLeGuidToString_Upper(Guid, s);
prop = s;
break;
}
@@ -364,18 +342,16 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
s += c;
}
if (s.IsEmpty())
+ s.Add_UInt32(index);
{
- char temp[16];
- ConvertUInt32ToString(index, temp);
- s.AddAscii(temp);
- }
- {
+ s += '.';
+ const char *ext = NULL;
int typeIndex = FindPartType(item.Type);
- s += L'.';
- const char *ext = "img";
- if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Ext)
+ if (typeIndex >= 0)
ext = kPartTypes[(unsigned)typeIndex].Ext;
- s.AddAscii(ext);
+ if (!ext)
+ ext = "img";
+ s += ext;
}
prop = s;
break;
@@ -394,7 +370,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
res = kPartTypes[(unsigned)typeIndex].Type;
else
{
- GuidToString(item.Type, s);
+ RawLeGuidToString_Upper(item.Type, s);
res = s;
}
prop = res;
@@ -404,7 +380,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidId:
{
char s[48];
- GuidToString(item.Id, s);
+ RawLeGuidToString_Upper(item.Id, s);
prop = s;
break;
}
diff --git a/CPP/7zip/Archive/GzHandler.cpp b/CPP/7zip/Archive/GzHandler.cpp
index d8979ada..130f8b35 100644
--- a/CPP/7zip/Archive/GzHandler.cpp
+++ b/CPP/7zip/Archive/GzHandler.cpp
@@ -11,6 +11,7 @@
#include "../../Common/StringConvert.h"
#include "../../Windows/PropVariant.h"
+#include "../../Windows/PropVariantUtils.h"
#include "../../Windows/TimeUtils.h"
#include "../Common/ProgressUtils.h"
@@ -109,7 +110,6 @@ static const char * const kHostOSes[] =
, "OS/X"
};
-static const char *kUnknownOS = "Unknown";
class CItem
{
@@ -537,7 +537,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
if (_item.NameIsPresent())
{
UString s = MultiByteToUnicodeString(_item.Name, CP_ACP);
- s.AddAscii(".gz");
+ s += ".gz";
prop = s;
}
break;
@@ -587,8 +587,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
prop = _packSize;
break;
}
- case kpidHostOS: prop = (_item.HostOS < ARRAY_SIZE(kHostOSes)) ?
- kHostOSes[_item.HostOS] : kUnknownOS; break;
+ case kpidHostOS: TYPE_TO_PROP(kHostOSes, _item.HostOS, prop); break;
case kpidCRC: if (_stream) prop = _item.Crc; break;
}
prop.Detach(value);
@@ -1035,7 +1034,7 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
static const Byte k_Signature[] = { kSignature_0, kSignature_1, kSignature_2 };
REGISTER_ARC_IO(
- "gzip", "gz gzip tgz tpz", "* * .tar .tar", 0xEF,
+ "gzip", "gz gzip tgz tpz apk", "* * .tar .tar .tar", 0xEF,
k_Signature,
0,
NArcInfoFlags::kKeepName,
diff --git a/CPP/7zip/Archive/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp
index 185df7f0..d02f0725 100644
--- a/CPP/7zip/Archive/HfsHandler.cpp
+++ b/CPP/7zip/Archive/HfsHandler.cpp
@@ -28,7 +28,7 @@
namespace NArchive {
namespace NHfs {
-static const char *kResFileName = "rsrc"; // "com.apple.ResourceFork";
+static const char * const kResFileName = "rsrc"; // "com.apple.ResourceFork";
struct CExtent
{
@@ -497,11 +497,14 @@ struct CHeaderRec
// UInt32 Attributes;
// UInt32 Reserved3[16];
- HRESULT Parse(const Byte *p);
+ HRESULT Parse2(const CByteBuffer &buf);
};
-HRESULT CHeaderRec::Parse(const Byte *p)
+HRESULT CHeaderRec::Parse2(const CByteBuffer &buf)
{
+ if (buf.Size() < kNodeDescriptor_Size + 0x2A + 16 * 4)
+ return S_FALSE;
+ const Byte * p = (const Byte *)buf + kNodeDescriptor_Size;
// TreeDepth = Get16(p);
// RootNode = Get32(p + 2);
// LeafRecords = Get32(p + 6);
@@ -527,6 +530,10 @@ HRESULT CHeaderRec::Parse(const Byte *p)
for (int i = 0; i < 16; i++)
Reserved3[i] = Get32(p + 0x2A + i * 4);
*/
+
+ if ((buf.Size() >> NodeSizeLog) < TotalNodes)
+ return S_FALSE;
+
return S_OK;
}
@@ -553,10 +560,7 @@ HRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjec
// CNodeDescriptor nodeDesc;
// nodeDesc.Parse(p);
CHeaderRec hr;
- RINOK(hr.Parse(p + kNodeDescriptor_Size));
-
- if ((buf.Size() >> hr.NodeSizeLog) < hr.TotalNodes)
- return S_FALSE;
+ RINOK(hr.Parse2(buf));
UInt32 node = hr.FirstLeafNode;
if (node == 0)
@@ -695,13 +699,10 @@ HRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpe
// CNodeDescriptor nodeDesc;
// nodeDesc.Parse(p);
CHeaderRec hr;
- RINOK(hr.Parse(p + kNodeDescriptor_Size));
+ RINOK(hr.Parse2(AttrBuf));
// CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC);
- if ((AttrBuf.Size() >> hr.NodeSizeLog) < hr.TotalNodes)
- return S_FALSE;
-
UInt32 node = hr.FirstLeafNode;
if (node == 0)
return S_OK;
@@ -876,13 +877,10 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
// CNodeDescriptor nodeDesc;
// nodeDesc.Parse(p);
CHeaderRec hr;
- RINOK(hr.Parse(p + kNodeDescriptor_Size));
+ RINOK(hr.Parse2(buf));
// CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC);
- if ((buf.Size() >> hr.NodeSizeLog) < hr.TotalNodes)
- return S_FALSE;
-
CByteBuffer usedBuf(hr.TotalNodes);
memset(usedBuf, 0, hr.TotalNodes);
@@ -966,13 +964,13 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents
IsNameEqualTo(name + 8, "HFS+ Private Data"))
{
// it's folder for "Hard Links" files
- item.Name.SetFromAscii("[HFS+ Private Data]");
+ item.Name = "[HFS+ Private Data]";
}
}
// Some dmg files have ' ' folder item.
if (item.Name.IsEmpty() || item.Name[0] == L' ')
- item.Name.SetFromAscii("[]");
+ item.Name = "[]";
}
}
@@ -1228,7 +1226,7 @@ HRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress)
return S_FALSE;
*/
- ResFileName.SetFromAscii(kResFileName);
+ ResFileName = kResFileName;
CFork extentsFork, catalogFork, attrFork;
// allocationFork.Parse(p + 0x70 + 0x50 * 0);
diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp
index 5a19516c..2230cd23 100644
--- a/CPP/7zip/Archive/Iso/IsoHandler.cpp
+++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp
@@ -3,7 +3,6 @@
#include "StdAfx.h"
#include "../../../Common/ComTry.h"
-#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
#include "../../../Windows/PropVariant.h"
@@ -176,12 +175,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
case kpidPath:
{
- AString s = "[BOOT]" STRING_PATH_SEPARATOR;
+ AString s ("[BOOT]" STRING_PATH_SEPARATOR);
if (_archive.BootEntries.Size() != 1)
{
- char temp[16];
- ConvertUInt32ToString(index + 1, temp);
- s += temp;
+ s.Add_UInt32(index + 1);
s += '-';
}
s += be.GetName();
@@ -216,7 +213,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
if (!s.IsEmpty() && s.Back() == L'.')
s.DeleteBack();
- NItemName::ConvertToOSName2(s);
+ NItemName::ReplaceToOsSlashes_Remove_TailSlash(s);
prop = s;
}
break;
diff --git a/CPP/7zip/Archive/Iso/IsoHeader.cpp b/CPP/7zip/Archive/Iso/IsoHeader.cpp
index 59c283c1..3b59060a 100644
--- a/CPP/7zip/Archive/Iso/IsoHeader.cpp
+++ b/CPP/7zip/Archive/Iso/IsoHeader.cpp
@@ -7,6 +7,6 @@
namespace NArchive {
namespace NIso {
-const char *kElToritoSpec = "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0";
+const char * const kElToritoSpec = "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0";
}}
diff --git a/CPP/7zip/Archive/Iso/IsoHeader.h b/CPP/7zip/Archive/Iso/IsoHeader.h
index db0b1df9..e6a4d327 100644
--- a/CPP/7zip/Archive/Iso/IsoHeader.h
+++ b/CPP/7zip/Archive/Iso/IsoHeader.h
@@ -25,7 +25,7 @@ namespace NFileFlags
const Byte kNonFinalExtent = 1 << 7;
}
-extern const char *kElToritoSpec;
+extern const char * const kElToritoSpec;
const UInt32 kStartPos = 0x8000;
diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp
index 8530a25e..65be1146 100644
--- a/CPP/7zip/Archive/Iso/IsoIn.cpp
+++ b/CPP/7zip/Archive/Iso/IsoIn.cpp
@@ -47,17 +47,13 @@ bool CBootInitialEntry::Parse(const Byte *p)
AString CBootInitialEntry::GetName() const
{
- AString s = (Bootable ? "Boot" : "NotBoot");
+ AString s (Bootable ? "Boot" : "NotBoot");
s += '-';
if (BootMediaType < ARRAY_SIZE(kMediaTypes))
s += kMediaTypes[BootMediaType];
else
- {
- char name[16];
- ConvertUInt32ToString(BootMediaType, name);
- s += name;
- }
+ s.Add_UInt32(BootMediaType);
if (VendorSpec[0] == 1)
{
diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h
index 4000fc92..347f9e9b 100644
--- a/CPP/7zip/Archive/Iso/IsoIn.h
+++ b/CPP/7zip/Archive/Iso/IsoIn.h
@@ -3,7 +3,6 @@
#ifndef __ARCHIVE_ISO_IN_H
#define __ARCHIVE_ISO_IN_H
-#include "../../../Common/IntToString.h"
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h
index c4950e60..5ae13a60 100644
--- a/CPP/7zip/Archive/Iso/IsoItem.h
+++ b/CPP/7zip/Archive/Iso/IsoItem.h
@@ -223,6 +223,7 @@ struct CDirRecord
const bool GetPx(int skipSize, unsigned pxType, UInt32 &val) const
{
+ val = 0;
const Byte *p = NULL;
unsigned len = 0;
p = FindSuspRecord(skipSize, 'P', 'X', len);
diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp
index c8d3ff6d..53d69db7 100644
--- a/CPP/7zip/Archive/LzhHandler.cpp
+++ b/CPP/7zip/Archive/LzhHandler.cpp
@@ -9,6 +9,7 @@
#include "../../Common/StringConvert.h"
#include "../../Windows/PropVariant.h"
+#include "../../Windows/PropVariantUtils.h"
#include "../../Windows/TimeUtils.h"
#include "../ICoder.h"
@@ -31,10 +32,44 @@ using namespace NTime;
#define Get16(p) GetUi16(p)
#define Get32(p) GetUi32(p)
+
+// CRC-16 (-IBM, -ANSI). The poly is 0x8005 (x^16 + x^15 + x^2 + 1)
+
+static const UInt16 kCrc16Poly = 0xA001;
+
+static UInt16 g_LzhCrc16Table[256];
+
+#define CRC16_UPDATE_BYTE(crc, b) (g_LzhCrc16Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
+
+UInt32 LzhCrc16Update(UInt32 crc, const void *data, size_t size)
+{
+ const Byte *p = (const Byte *)data;
+ const Byte *pEnd = p + size;
+ for (; p != pEnd; p++)
+ crc = CRC16_UPDATE_BYTE(crc, *p);
+ return crc;
+}
+
+static class CLzhCrc16TableInit
+{
+public:
+ CLzhCrc16TableInit()
+ {
+ for (UInt32 i = 0; i < 256; i++)
+ {
+ UInt32 r = i;
+ for (unsigned j = 0; j < 8; j++)
+ r = (r >> 1) ^ (kCrc16Poly & ((UInt32)0 - (r & 1)));
+ g_LzhCrc16Table[i] = (UInt16)r;
+ }
+ }
+} g_LzhCrc16TableInit;
+
+
namespace NArchive {
namespace NLzh{
-const int kMethodIdSize = 5;
+const unsigned kMethodIdSize = 5;
const Byte kExtIdFileName = 0x01;
const Byte kExtIdDirName = 0x02;
@@ -125,7 +160,7 @@ struct CItem
return false;
}
- int GetNumDictBits() const
+ unsigned GetNumDictBits() const
{
if (!IsLhMethod())
return 0;
@@ -185,7 +220,7 @@ struct CItem
AString GetName() const
{
- AString dirName = GetDirName();
+ AString dirName (GetDirName());
const char kDirSeparator = '\\';
// check kDirSeparator in Linux
dirName.Replace((char)(unsigned char)0xFF, kDirSeparator);
@@ -310,13 +345,8 @@ static HRESULT GetNextItem(ISequentialInStream *stream, bool &filled, CItem &ite
return S_OK;
}
-struct COsPair
-{
- Byte Id;
- const char *Name;
-};
-static const COsPair g_OsPairs[] =
+static const CUInt32PCharPair g_OsPairs[] =
{
{ 0, "MS-DOS" },
{ 'M', "MS-DOS" },
@@ -337,15 +367,6 @@ static const COsPair g_OsPairs[] =
{ 'J', "Java VM" }
};
-static const char *kUnknownOS = "Unknown";
-
-static const char *GetOS(Byte osId)
-{
- for (unsigned i = 0; i < ARRAY_SIZE(g_OsPairs); i++)
- if (g_OsPairs[i].Id == osId)
- return g_OsPairs[i].Name;
- return kUnknownOS;
-}
static const Byte kProps[] =
{
@@ -360,52 +381,6 @@ static const Byte kProps[] =
kpidHostOS
};
-class CCRC
-{
- UInt16 _value;
-public:
- static UInt16 Table[256];
- static void InitTable();
-
- CCRC(): _value(0) {}
- void Init() { _value = 0; }
- void Update(const void *data, size_t size);
- UInt16 GetDigest() const { return _value; }
-};
-
-static const UInt16 kCRCPoly = 0xA001;
-
-UInt16 CCRC::Table[256];
-
-void CCRC::InitTable()
-{
- for (UInt32 i = 0; i < 256; i++)
- {
- UInt32 r = i;
- for (int j = 0; j < 8; j++)
- if (r & 1)
- r = (r >> 1) ^ kCRCPoly;
- else
- r >>= 1;
- CCRC::Table[i] = (UInt16)r;
- }
-}
-
-class CCRCTableInit
-{
-public:
- CCRCTableInit() { CCRC::InitTable(); }
-} g_CRCTableInit;
-
-void CCRC::Update(const void *data, size_t size)
-{
- UInt16 v = _value;
- const Byte *p = (const Byte *)data;
- for (; size > 0; size--, p++)
- v = (UInt16)(Table[((Byte)(v)) ^ *p] ^ (v >> 8));
- _value = v;
-}
-
class COutStreamWithCRC:
public ISequentialOutStream,
@@ -416,41 +391,36 @@ public:
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
private:
- CCRC _crc;
+ UInt32 _crc;
CMyComPtr<ISequentialOutStream> _stream;
public:
void Init(ISequentialOutStream *stream)
{
_stream = stream;
- _crc.Init();
+ _crc = 0;
}
void ReleaseStream() { _stream.Release(); }
- UInt32 GetCRC() const { return _crc.GetDigest(); }
- void InitCRC() { _crc.Init(); }
+ UInt32 GetCRC() const { return _crc; }
};
STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
- UInt32 realProcessedSize;
- HRESULT result;
- if (!_stream)
- {
- realProcessedSize = size;
- result = S_OK;
- }
- else
- result = _stream->Write(data, size, &realProcessedSize);
- _crc.Update(data, realProcessedSize);
- if (processedSize != NULL)
- *processedSize = realProcessedSize;
- return result;
+ HRESULT res = S_OK;
+ if (_stream)
+ res = _stream->Write(data, size, &size);
+ _crc = LzhCrc16Update(_crc, data, size);
+ if (processedSize)
+ *processedSize = size;
+ return res;
}
+
struct CItemEx: public CItem
{
UInt64 DataPosition;
};
+
class CHandler:
public IInArchive,
public CMyUnknownImp
@@ -503,7 +473,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
case kpidPath:
{
- UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetName(), CP_OEMCP));
+ UString s = NItemName::WinPathToOsPath(MultiByteToUnicodeString(item.GetName(), CP_OEMCP));
if (!s.IsEmpty())
{
if (s.Back() == WCHAR_PATH_SEPARATOR)
@@ -516,7 +486,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidSize: prop = item.Size; break;
case kpidPackSize: prop = item.PackSize; break;
case kpidCRC: prop = (UInt32)item.CRC; break;
- case kpidHostOS: prop = GetOS(item.OsId); break;
+ case kpidHostOS: PAIR_TO_PROP(g_OsPairs, item.OsId, prop); break;
case kpidMTime:
{
FILETIME utc;
@@ -571,15 +541,15 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
{
CItemEx item;
bool filled;
- HRESULT result = GetNextItem(stream, filled, item);
+ HRESULT res = GetNextItem(stream, filled, item);
RINOK(stream->Seek(0, STREAM_SEEK_CUR, &item.DataPosition));
- if (result == S_FALSE)
+ if (res == S_FALSE)
{
_errorFlags = kpv_ErrorFlags_HeadersError;
break;
}
- if (result != S_OK)
+ if (res != S_OK)
return S_FALSE;
_phySize = item.DataPosition;
if (!filled)
@@ -720,14 +690,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
streamSpec->Init(item.PackSize);
- HRESULT result = S_OK;
+ HRESULT res = S_OK;
Int32 opRes = NExtract::NOperationResult::kOK;
if (item.IsCopyMethod())
{
- result = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
- if (result == S_OK && copyCoderSpec->TotalSize != item.PackSize)
- result = S_FALSE;
+ res = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
+ if (res == S_OK && copyCoderSpec->TotalSize != item.PackSize)
+ res = S_FALSE;
}
else if (item.IsLh4GroupMethod())
{
@@ -738,9 +708,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
lzhDecoderSpec->FinishMode = true;
lzhDecoderSpec->SetDictSize(1 << item.GetNumDictBits());
- result = lzhDecoder->Code(inStream, outStream, NULL, &currentItemUnPacked, progress);
- if (result == S_OK && lzhDecoderSpec->GetInputProcessedSize() != item.PackSize)
- result = S_FALSE;
+ res = lzhDecoder->Code(inStream, outStream, NULL, &currentItemUnPacked, progress);
+ if (res == S_OK && lzhDecoderSpec->GetInputProcessedSize() != item.PackSize)
+ res = S_FALSE;
}
/*
else if (item.IsLh1GroupMethod())
@@ -751,7 +721,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
lzh1Decoder = lzh1DecoderSpec;
}
lzh1DecoderSpec->SetDictionary(item.GetNumDictBits());
- result = lzh1Decoder->Code(inStream, outStream, NULL, &currentItemUnPacked, progress);
+ res = lzh1Decoder->Code(inStream, outStream, NULL, &currentItemUnPacked, progress);
}
*/
else
@@ -759,11 +729,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (opRes == NExtract::NOperationResult::kOK)
{
- if (result == S_FALSE)
+ if (res == S_FALSE)
opRes = NExtract::NOperationResult::kDataError;
else
{
- RINOK(result);
+ RINOK(res);
if (outStreamSpec->GetCRC() != item.CRC)
opRes = NExtract::NOperationResult::kCRCError;
}
diff --git a/CPP/7zip/Archive/LzmaHandler.cpp b/CPP/7zip/Archive/LzmaHandler.cpp
index 121cd67c..afdc2bfa 100644
--- a/CPP/7zip/Archive/LzmaHandler.cpp
+++ b/CPP/7zip/Archive/LzmaHandler.cpp
@@ -44,7 +44,8 @@ static const Byte kProps[] =
static const Byte kArcProps[] =
{
- kpidNumStreams
+ kpidNumStreams,
+ kpidMethod
};
struct CHeader
@@ -53,6 +54,7 @@ struct CHeader
Byte FilterID;
Byte LzmaProps[5];
+ Byte GetProp() const { return LzmaProps[0]; }
UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); }
bool HasSize() const { return (Size != (UInt64)(Int64)-1); }
bool Parse(const Byte *buf, bool isThereFilter);
@@ -197,6 +199,8 @@ class CHandler:
UInt64 _unpackSize;
UInt64 _numStreams;
+ void GetMethod(NCOM::CPropVariant &prop);
+
public:
MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq)
@@ -220,6 +224,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidPhySize: if (_packSize_Defined) prop = _packSize; break;
case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break;
case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break;
+ case kpidMethod: GetMethod(prop); break;
case kpidErrorFlags:
{
UInt32 v = 0;
@@ -229,6 +234,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;
if (_dataError) v |= kpv_ErrorFlags_DataError;
prop = v;
+ break;
}
}
prop.Detach(value);
@@ -241,23 +247,60 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
return S_OK;
}
-static void DictSizeToString(UInt32 value, char *s)
+
+static void DictSizeToString(UInt32 val, char *s)
{
- for (int i = 0; i <= 31; i++)
- if (((UInt32)1 << i) == value)
+ for (unsigned i = 0; i <= 31; i++)
+ if (((UInt32)1 << i) == val)
{
::ConvertUInt32ToString(i, s);
return;
}
char c = 'b';
- if ((value & ((1 << 20) - 1)) == 0) { value >>= 20; c = 'm'; }
- else if ((value & ((1 << 10) - 1)) == 0) { value >>= 10; c = 'k'; }
- ::ConvertUInt32ToString(value, s);
+ if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
+ else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
+ ::ConvertUInt32ToString(val, s);
s += MyStringLen(s);
*s++ = c;
*s = 0;
}
+static char *AddProp32(char *s, const char *name, UInt32 v)
+{
+ *s++ = ':';
+ s = MyStpCpy(s, name);
+ ::ConvertUInt32ToString(v, s);
+ return s + MyStringLen(s);
+}
+
+void CHandler::GetMethod(NCOM::CPropVariant &prop)
+{
+ if (!_stream)
+ return;
+
+ char sz[64];
+ char *s = sz;
+ if (_header.FilterID != 0)
+ s = MyStpCpy(s, "BCJ ");
+ s = MyStpCpy(s, "LZMA:");
+ DictSizeToString(_header.GetDicSize(), s);
+ s += strlen(s);
+
+ UInt32 d = _header.GetProp();
+ // if (d != 0x5D)
+ {
+ UInt32 lc = d % 9;
+ d /= 9;
+ UInt32 pb = d / 5;
+ UInt32 lp = d % 5;
+ if (lc != 3) s = AddProp32(s, "lc", lc);
+ if (lp != 0) s = AddProp32(s, "lp", lp);
+ if (pb != 2) s = AddProp32(s, "pb", pb);
+ }
+ prop = sz;
+}
+
+
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant prop;
@@ -265,18 +308,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
{
case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break;
case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;
- case kpidMethod:
- if (_stream)
- {
- char sz[64];
- char *s = sz;
- if (_header.FilterID != 0)
- s = MyStpCpy(s, "BCJ ");
- s = MyStpCpy(s, "LZMA:");
- DictSizeToString(_header.GetDicSize(), s);
- prop = sz;
- }
- break;
+ case kpidMethod: GetMethod(prop); break;
}
prop.Detach(value);
return S_OK;
@@ -396,9 +428,9 @@ STDMETHODIMP CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const
{
if (Callback)
{
- UInt64 files = 0;
- UInt64 value = Offset + *inSize;
- return Callback->SetCompleted(&files, &value);
+ const UInt64 files = 0;
+ const UInt64 val = Offset + *inSize;
+ return Callback->SetCompleted(&files, &val);
}
return S_OK;
}
@@ -510,7 +542,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
if (dataAfterEnd)
_dataAfterEnd = true;
- else if (decoder._lzmaDecoderSpec->NeedMoreInput)
+ else if (decoder._lzmaDecoderSpec->NeedsMoreInput())
_needMoreInput = true;
_packSize = packSize;
diff --git a/CPP/7zip/Archive/MachoHandler.cpp b/CPP/7zip/Archive/MachoHandler.cpp
index 26260686..1f65574d 100644
--- a/CPP/7zip/Archive/MachoHandler.cpp
+++ b/CPP/7zip/Archive/MachoHandler.cpp
@@ -37,6 +37,7 @@ namespace NMacho {
#define CPU_TYPE_PPC64 (CPU_ARCH_ABI64 | CPU_TYPE_PPC)
#define CPU_TYPE_AMD64 (CPU_ARCH_ABI64 | CPU_TYPE_386)
+#define CPU_TYPE_ARM64 (CPU_ARCH_ABI64 | CPU_TYPE_ARM)
#define CPU_SUBTYPE_LIB64 (1 << 31)
@@ -60,6 +61,8 @@ static const char * const k_PowerPc_SubTypes[] =
static const CUInt32PCharPair g_CpuPairs[] =
{
+ { CPU_TYPE_AMD64, "x64" },
+ { CPU_TYPE_ARM64, "ARM64" },
{ CPU_TYPE_386, "x86" },
{ CPU_TYPE_ARM, "ARM" },
{ CPU_TYPE_SPARC, "SPARC" },
@@ -168,7 +171,7 @@ static const CUInt32PCharPair g_Flags[] =
{ 8, "LOC_RELOC" }
};
-static const int kNameSize = 16;
+static const unsigned kNameSize = 16;
struct CSegment
{
@@ -255,16 +258,16 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
AString s;
char temp[16];
UInt32 cpu = _cpuType & ~(UInt32)CPU_ARCH_ABI64;
- if (_cpuType == CPU_TYPE_AMD64)
- s = "x64";
- else
+ UInt32 flag64 = _cpuType & (UInt32)CPU_ARCH_ABI64;
{
const char *n = NULL;
for (unsigned i = 0; i < ARRAY_SIZE(g_CpuPairs); i++)
{
const CUInt32PCharPair &pair = g_CpuPairs[i];
- if (pair.Value == cpu)
+ if (pair.Value == cpu || pair.Value == _cpuType)
{
+ if (pair.Value == _cpuType)
+ flag64 = 0;
n = pair.Name;
break;
}
@@ -276,10 +279,10 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
}
s = n;
- if (_cpuType & CPU_ARCH_ABI64)
+ if (flag64 != 0)
s += " 64-bit";
- else if (_cpuSubType & CPU_SUBTYPE_LIB64)
- s += " 64-bit lib";
+ else if ((_cpuSubType & CPU_SUBTYPE_LIB64) && _cpuType != CPU_TYPE_AMD64)
+ s += " 64-bit-lib";
}
UInt32 t = _cpuSubType & ~(UInt32)CPU_SUBTYPE_LIB64;
if (t != 0 && (t != CPU_SUBTYPE_I386_ALL || cpu != CPU_TYPE_386))
@@ -306,8 +309,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidCharacts:
{
// TYPE_TO_PROP(g_FileTypes, _type, prop); break;
- AString res = TypeToString(g_FileTypes, ARRAY_SIZE(g_FileTypes), _type);
- AString s = FlagsToString(g_ArcFlags, ARRAY_SIZE(g_ArcFlags), _flags);
+ AString res (TypeToString(g_FileTypes, ARRAY_SIZE(g_FileTypes), _type));
+ AString s (FlagsToString(g_ArcFlags, ARRAY_SIZE(g_ArcFlags), _flags));
if (!s.IsEmpty())
{
res.Add_Space();
@@ -345,20 +348,9 @@ static AString GetName(const char *name)
char res[kNameSize + 1];
memcpy(res, name, kNameSize);
res[kNameSize] = 0;
- return res;
+ return (AString)res;
}
-static AString SectFlagsToString(UInt32 flags)
-{
- AString res = TypeToString(g_SectTypes, ARRAY_SIZE(g_SectTypes), flags & SECT_TYPE_MASK);
- AString s = FlagsToString(g_Flags, ARRAY_SIZE(g_Flags), flags & SECT_ATTR_MASK);
- if (!s.IsEmpty())
- {
- res.Add_Space();
- res += s;
- }
- return res;
-}
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
@@ -369,7 +361,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
case kpidPath:
{
- AString s = GetName(_segments[item.SegmentIndex].Name);
+ AString s (GetName(_segments[item.SegmentIndex].Name));
if (!item.IsDummy)
s += GetName(item.Name);
prop = MultiByteToUnicodeString(s);
@@ -377,7 +369,19 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
}
case kpidSize: /* prop = (UInt64)item.VSize; break; */
case kpidPackSize: prop = (UInt64)item.GetPackSize(); break;
- case kpidCharacts: if (!item.IsDummy) prop = SectFlagsToString(item.Flags); break;
+ case kpidCharacts:
+ if (!item.IsDummy)
+ {
+ AString res (TypeToString(g_SectTypes, ARRAY_SIZE(g_SectTypes), item.Flags & SECT_TYPE_MASK));
+ AString s (FlagsToString(g_Flags, ARRAY_SIZE(g_Flags), item.Flags & SECT_ATTR_MASK));
+ if (!s.IsEmpty())
+ {
+ res.Add_Space();
+ res += s;
+ }
+ prop = res;
+ }
+ break;
case kpidOffset: prop = item.Pa; break;
case kpidVa: prop = item.Va; break;
}
@@ -386,6 +390,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END
}
+
HRESULT CHandler::Open2(ISequentialInStream *stream)
{
const UInt32 kStartHeaderSize = 7 * 4;
@@ -402,6 +407,9 @@ HRESULT CHandler::Open2(ISequentialInStream *stream)
default: return S_FALSE;
}
+ _mode64 = mode64;
+ _be = be;
+
UInt32 numCommands = Get32(header + 0x10, be);
UInt32 commandsSize = Get32(header + 0x14, be);
diff --git a/CPP/7zip/Archive/MbrHandler.cpp b/CPP/7zip/Archive/MbrHandler.cpp
index b92755ae..14a1224c 100644
--- a/CPP/7zip/Archive/MbrHandler.cpp
+++ b/CPP/7zip/Archive/MbrHandler.cpp
@@ -63,21 +63,14 @@ static int CompareChs(const CChs &c1, const CChs &c2)
}
*/
-static void AddUIntToString(UInt32 val, AString &res)
-{
- char s[16];
- ConvertUInt32ToString(val, s);
- res += s;
-}
-
void CChs::ToString(NCOM::CPropVariant &prop) const
{
AString s;
- AddUIntToString(GetCyl(), s);
+ s.Add_UInt32(GetCyl());
s += '-';
- AddUIntToString(Head, s);
+ s.Add_UInt32(Head);
s += '-';
- AddUIntToString(GetSector(), s);
+ s.Add_UInt32(GetSector());
prop = s;
}
@@ -137,7 +130,7 @@ struct CPartType
const char *Name;
};
-static const char *kFat = "fat";
+#define kFat "fat"
static const CPartType kPartTypes[] =
{
@@ -156,6 +149,7 @@ static const CPartType kPartTypes[] =
{ 0x1B, kFat, "FAT32-Hidden" },
{ 0x1C, kFat, "FAT32-LBA-Hidden" },
{ 0x1E, kFat, "FAT16-LBA-WIN95-Hidden" },
+ { 0x27, "ntfs", "NTFS-WinRE" },
{ 0x82, 0, "Solaris x86 / Linux swap" },
{ 0x83, 0, "Linux" },
{ 0x8E, "lvm", "Linux LVM" },
@@ -399,14 +393,16 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidPath:
{
AString s;
- AddUIntToString(index, s);
+ s.Add_UInt32(index);
if (item.IsReal)
{
- int typeIndex = FindPartType(part.Type);
s += '.';
- const char *ext = "img";
- if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Ext)
+ const char *ext = NULL;
+ int typeIndex = FindPartType(part.Type);
+ if (typeIndex >= 0)
ext = kPartTypes[(unsigned)typeIndex].Ext;
+ if (!ext)
+ ext = "img";
s += ext;
}
prop = s;
diff --git a/CPP/7zip/Archive/MslzHandler.cpp b/CPP/7zip/Archive/MslzHandler.cpp
index ec375733..6f9057a6 100644
--- a/CPP/7zip/Archive/MslzHandler.cpp
+++ b/CPP/7zip/Archive/MslzHandler.cpp
@@ -159,7 +159,7 @@ void CHandler::ParseName(Byte replaceByte, IArchiveOpenCallback *callback)
}
if (replaceByte >= 0x20 && replaceByte < 0x80)
- _name += (wchar_t)replaceByte;
+ _name += (char)replaceByte;
}
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */,
diff --git a/CPP/7zip/Archive/MubHandler.cpp b/CPP/7zip/Archive/MubHandler.cpp
index 56b8aa32..6d054356 100644
--- a/CPP/7zip/Archive/MubHandler.cpp
+++ b/CPP/7zip/Archive/MubHandler.cpp
@@ -31,6 +31,7 @@ namespace NMub {
#define MACH_CPU_TYPE_PPC64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_PPC)
#define MACH_CPU_TYPE_AMD64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_386)
+#define MACH_CPU_TYPE_ARM64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_ARM)
#define MACH_CPU_SUBTYPE_LIB64 (1 << 31)
@@ -105,17 +106,20 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
const char *ext = 0;
switch (item.Type)
{
- case MACH_CPU_TYPE_386: ext = "x86"; break;
+ case MACH_CPU_TYPE_386: ext = "x86"; break;
case MACH_CPU_TYPE_ARM: ext = "arm"; break;
case MACH_CPU_TYPE_SPARC: ext = "sparc"; break;
case MACH_CPU_TYPE_PPC: ext = "ppc"; break;
- case MACH_CPU_TYPE_PPC64: ext = "ppc64"; break;
case MACH_CPU_TYPE_AMD64: ext = "x64"; break;
+ case MACH_CPU_TYPE_ARM64: ext = "arm64"; break;
+ case MACH_CPU_TYPE_PPC64: ext = "ppc64"; break;
default:
temp[0] = 'c';
temp[1] = 'p';
temp[2] = 'u';
- ConvertUInt32ToString(item.Type, temp + 3);
+ ConvertUInt32ToString(item.Type & ~MACH_CPU_ARCH_ABI64, temp + 3);
+ if (item.Type & MACH_CPU_ARCH_ABI64)
+ MyStringCopy(temp + MyStringLen(temp), "_64");
break;
}
if (ext)
diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.cpp b/CPP/7zip/Archive/Nsis/NsisDecode.cpp
index daf3df6e..e2822184 100644
--- a/CPP/7zip/Archive/Nsis/NsisDecode.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisDecode.cpp
@@ -11,13 +11,24 @@
#include "../../Common/MethodId.h"
#include "../../Compress/BcjCoder.h"
-#include "../../Compress/BZip2Decoder.h"
#define Get32(p) GetUi32(p)
namespace NArchive {
namespace NNsis {
+UInt64 CDecoder::GetInputProcessedSize() const
+{
+ if (_lzmaDecoder)
+ return _lzmaDecoder->GetInputProcessedSize();
+ if (_deflateDecoder)
+ return _deflateDecoder->GetInputProcessedSize();
+ if (_bzDecoder)
+ return _bzDecoder->GetInputProcessedSize();
+ return 0;
+}
+
+
HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter)
{
useFilter = false;
@@ -36,7 +47,10 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter)
_deflateDecoder = new NCompress::NDeflate::NDecoder::CCOMCoder();
_codecInStream = _deflateDecoder;
break;
- case NMethodType::kBZip2: _codecInStream = new NCompress::NBZip2::CNsisDecoder(); break;
+ case NMethodType::kBZip2:
+ _bzDecoder = new NCompress::NBZip2::CNsisDecoder();
+ _codecInStream = _bzDecoder;
+ break;
case NMethodType::kLZMA:
_lzmaDecoder = new NCompress::NLzma::CDecoder();
_codecInStream = _lzmaDecoder;
@@ -103,15 +117,15 @@ HRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter)
return S_OK;
}
+
static const UInt32 kMask_IsCompressed = (UInt32)1 << 31;
+
HRESULT CDecoder::SetToPos(UInt64 pos, ICompressProgressInfo *progress)
{
if (StreamPos > pos)
return E_FAIL;
- UInt64 inSizeStart = 0;
- if (_lzmaDecoder)
- inSizeStart = _lzmaDecoder->GetInputProcessedSize();
+ const UInt64 inSizeStart = GetInputProcessedSize();
UInt64 offset = 0;
while (StreamPos < pos)
{
@@ -122,14 +136,13 @@ HRESULT CDecoder::SetToPos(UInt64 pos, ICompressProgressInfo *progress)
StreamPos += size;
offset += size;
- UInt64 inSize = 0;
- if (_lzmaDecoder)
- inSize = _lzmaDecoder->GetInputProcessedSize() - inSizeStart;
+ const UInt64 inSize = GetInputProcessedSize() - inSizeStart;
RINOK(progress->SetRatioInfo(&inSize, &offset));
}
return S_OK;
}
+
HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unpackSize,
ISequentialOutStream *realOutStream, ICompressProgressInfo *progress,
UInt32 &packSizeRes, UInt32 &unpackSizeRes)
@@ -144,9 +157,9 @@ HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unp
Byte temp[4];
size_t processedSize = 4;
RINOK(Read(temp, &processedSize));
+ StreamPos += processedSize;
if (processedSize != 4)
return S_FALSE;
- StreamPos += processedSize;
UInt32 size = Get32(temp);
if (unpackSizeDefined && size != unpackSize)
return S_FALSE;
@@ -156,8 +169,13 @@ HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unp
else
{
Byte temp[4];
- RINOK(ReadStream_FALSE(InputStream, temp, 4));
- StreamPos += 4;
+ {
+ size_t processedSize = 4;
+ RINOK(ReadStream(InputStream, temp, &processedSize));
+ StreamPos += processedSize;
+ if (processedSize != 4)
+ return S_FALSE;
+ }
UInt32 size = Get32(temp);
if ((size & kMask_IsCompressed) == 0)
@@ -209,9 +227,7 @@ HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unp
outBuf->Alloc(unpackSize);
}
- UInt64 inSizeStart = 0;
- if (_lzmaDecoder)
- inSizeStart = _lzmaDecoder->GetInputProcessedSize();
+ const UInt64 inSizeStart = GetInputProcessedSize();
// we don't allow files larger than 4 GB;
if (!unpackSizeDefined)
@@ -254,9 +270,8 @@ HRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unp
StreamPos += size;
offset += (UInt32)size;
- UInt64 inSize = 0; // it can be improved: we need inSize for Deflate and BZip2 too.
- if (_lzmaDecoder)
- inSize = _lzmaDecoder->GetInputProcessedSize() - inSizeStart;
+ const UInt64 inSize = GetInputProcessedSize() - inSizeStart;
+
if (Solid)
packSizeRes = (UInt32)inSize;
unpackSizeRes += (UInt32)size;
diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.h b/CPP/7zip/Archive/Nsis/NsisDecode.h
index ec713d05..2153d785 100644
--- a/CPP/7zip/Archive/Nsis/NsisDecode.h
+++ b/CPP/7zip/Archive/Nsis/NsisDecode.h
@@ -8,6 +8,7 @@
#include "../../Common/FilterCoder.h"
#include "../../Common/StreamUtils.h"
+#include "../../Compress/BZip2Decoder.h"
#include "../../Compress/DeflateDecoder.h"
#include "../../Compress/LzmaDecoder.h"
@@ -38,6 +39,7 @@ class CDecoder
CMyComPtr<ISequentialInStream> _codecInStream;
CMyComPtr<ISequentialInStream> _decoderInStream;
+ NCompress::NBZip2::CNsisDecoder *_bzDecoder;
NCompress::NDeflate::NDecoder::CCOMCoder *_deflateDecoder;
NCompress::NLzma::CDecoder *_lzmaDecoder;
@@ -50,13 +52,17 @@ public:
bool Solid;
bool IsNsisDeflate;
- CByteBuffer Buffer; // temp buf.
+ CByteBuffer Buffer; // temp buf
CDecoder():
FilterFlag(false),
Solid(true),
IsNsisDeflate(true)
- {}
+ {
+ _bzDecoder = NULL;
+ _deflateDecoder = NULL;
+ _lzmaDecoder = NULL;
+ }
void Release()
{
@@ -64,10 +70,16 @@ public:
_codecInStream.Release();
_decoderInStream.Release();
InputStream.Release();
+
+ _bzDecoder = NULL;
+ _deflateDecoder = NULL;
_lzmaDecoder = NULL;
}
+
+ UInt64 GetInputProcessedSize() const;
HRESULT Init(ISequentialInStream *inStream, bool &useFilter);
+
HRESULT Read(void *data, size_t *processedSize)
{
return ReadStream(_decoderInStream, data, processedSize);;
diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp
index 971c8464..095105fe 100644
--- a/CPP/7zip/Archive/Nsis/NsisHandler.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisHandler.cpp
@@ -23,8 +23,8 @@ using namespace NWindows;
namespace NArchive {
namespace NNsis {
-static const char *kBcjMethod = "BCJ";
-static const char *kUnknownMethod = "Unknown";
+#define kBcjMethod "BCJ"
+#define kUnknownMethod "Unknown"
static const char * const kMethods[] =
{
@@ -64,7 +64,7 @@ static AString UInt32ToString(UInt32 val)
{
char s[16];
ConvertUInt32ToString(val, s);
- return s;
+ return (AString)s;
}
static AString GetStringForSizeValue(UInt32 val)
@@ -123,7 +123,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
// case kpidCodePage: if (_archive.IsUnicode) prop = "UTF-16"; break;
case kpidSubType:
{
- AString s = _archive.GetFormatDescription();
+ AString s (_archive.GetFormatDescription());
if (!_archive.IsInstaller)
{
s.Add_Space_if_NotEmpty();
@@ -308,7 +308,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidOffset: prop = item.Pos; break;
case kpidPath:
{
- UString s = NItemName::WinNameToOSName(_archive.GetReducedName(index));
+ UString s = NItemName::WinPathToOsPath(_archive.GetReducedName(index));
if (!s.IsEmpty())
prop = (const wchar_t *)s;
break;
@@ -481,7 +481,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
- UInt32 index = allFilesMode ? i : indices[i];
+ const UInt32 index = allFilesMode ? i : indices[i];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
@@ -647,6 +647,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
UInt32 curPacked2 = 0;
UInt32 curUnpacked2 = 0;
+
+ if (!_archive.IsSolid)
+ {
+ RINOK(_archive.SeekTo(_archive.GetPosOfNonSolidItem(index) + 4 + curPacked ));
+ }
+
HRESULT res = _archive.Decoder.Decode(
writeToTemp ? &tempBuf2 : NULL,
false, 0,
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp
index a3bfcaec..f739b0ff 100644
--- a/CPP/7zip/Archive/Nsis/NsisIn.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp
@@ -398,11 +398,9 @@ static const char * const kShellStrings[] =
};
-static void UIntToString(AString &s, UInt32 v)
+static inline void UIntToString(AString &s, UInt32 v)
{
- char sz[16];
- ConvertUInt32ToString(v, sz);
- s += sz;
+ s.Add_UInt32(v);
}
#ifdef NSIS_SCRIPT
@@ -461,7 +459,7 @@ void CInArchive::AddLicense(UInt32 param, Int32 langID)
}
}
}
- AString fileName = "[LICENSE]";
+ AString fileName ("[LICENSE]");
if (langID >= 0)
{
fileName += "\\license-";
@@ -940,7 +938,7 @@ void CInArchive::GetNsisString_Unicode_Raw(const Byte *p)
break;
if (c < 0x80)
{
- Raw_UString += (wchar_t)c;
+ Raw_UString += (char)c;
continue;
}
@@ -963,7 +961,7 @@ void CInArchive::GetNsisString_Unicode_Raw(const Byte *p)
else // if (c == PARK_CODE_LANG)
Add_LangStr(Raw_AString, n);
}
- Raw_UString.AddAscii(Raw_AString);
+ Raw_UString += Raw_AString.Ptr(); // check it !
continue;
}
c = n;
@@ -1009,7 +1007,7 @@ void CInArchive::GetNsisString_Unicode_Raw(const Byte *p)
else // if (c == NS_3_CODE_LANG)
Add_LangStr(Raw_AString, n);
}
- Raw_UString.AddAscii(Raw_AString);
+ Raw_UString += Raw_AString.Ptr();
}
}
@@ -1145,7 +1143,7 @@ void CInArchive::ReadString2_Raw(UInt32 pos)
GetNsisString_Raw(_data + _stringsPos + pos);
return;
}
- Raw_UString.SetFromAscii(Raw_AString);
+ Raw_UString = Raw_AString.Ptr();
}
bool CInArchive::IsGoodString(UInt32 param) const
@@ -2309,7 +2307,7 @@ static void AddString(AString &dest, const char *src)
AString CInArchive::GetFormatDescription() const
{
- AString s = "NSIS-";
+ AString s ("NSIS-");
char c;
if (IsPark())
{
@@ -3185,8 +3183,8 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
UString spec_outdir_U;
AString spec_outdir_A;
- UPrefixes.Add(L"$INSTDIR");
- APrefixes.Add("$INSTDIR");
+ UPrefixes.Add(UString("$INSTDIR"));
+ APrefixes.Add(AString("$INSTDIR"));
p = _data + bh.Offset;
@@ -4021,7 +4019,7 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
case EW_INTOP:
{
AddParam_Var(params[0]);
- const char *kOps = "+-*/|&^!|&%<>"; // NSIS 2.01+
+ const char * const kOps = "+-*/|&^!|&%<>"; // NSIS 2.01+
// "+-*/|&^!|&%"; // NSIS 2.0b4+
// "+-*/|&^~!|&%"; // NSIS old
UInt32 opIndex = params[3];
@@ -4857,11 +4855,11 @@ static int CompareItems(void *const *p1, void *const *p2, void *param)
{
if (i1.Prefix < 0) return -1;
if (i2.Prefix < 0) return 1;
- RINOZ(wcscmp(
- inArchive->UPrefixes[i1.Prefix],
+ RINOZ(
+ inArchive->UPrefixes[i1.Prefix].Compare(
inArchive->UPrefixes[i2.Prefix]));
}
- RINOZ(wcscmp(i1.NameU, i2.NameU));
+ RINOZ(i1.NameU.Compare(i2.NameU));
}
else
{
@@ -4934,7 +4932,7 @@ HRESULT CInArchive::SortItems()
for (i = 0; i < Items.Size(); i++)
{
CItem &item = Items[i];
- RINOK(_stream->Seek(GetPosOfNonSolidItem(i), STREAM_SEEK_SET, NULL));
+ RINOK(SeekToNonSolidItem(i));
const UInt32 kSigSize = 4 + 1 + 1 + 4; // size,[flag],prop,dict
BYTE sig[kSigSize];
size_t processedSize = kSigSize;
@@ -4997,6 +4995,9 @@ HRESULT CInArchive::Parse()
// ???? offset == FirstHeader.HeaderSize
const Byte *p = _data;
+ if (_size < 4 + 8 * 8)
+ return S_FALSE;
+
CBlockHeader bhEntries, bhStrings, bhLangTables;
bhEntries.Parse(p + 4 + 8 * 2);
bhStrings.Parse(p + 4 + 8 * 3);
@@ -5014,12 +5015,14 @@ HRESULT CInArchive::Parse()
#endif
_stringsPos = bhStrings.Offset;
- if (_stringsPos > _size)
+ if (_stringsPos > _size
+ || bhLangTables.Offset > _size
+ || bhEntries.Offset > _size)
return S_FALSE;
{
if (bhLangTables.Offset < bhStrings.Offset)
return S_FALSE;
- UInt32 stringTableSize = bhLangTables.Offset - bhStrings.Offset;
+ const UInt32 stringTableSize = bhLangTables.Offset - bhStrings.Offset;
if (stringTableSize < 2)
return S_FALSE;
const Byte *strData = _data + _stringsPos;
@@ -5035,13 +5038,10 @@ HRESULT CInArchive::Parse()
if (strData[stringTableSize - 2] != 0)
return S_FALSE;
}
-
}
if (bhEntries.Num > (1 << 25))
return S_FALSE;
- if (bhEntries.Offset > _size)
- return S_FALSE;
if (bhEntries.Num * kCmdSize > _size - bhEntries.Offset)
return S_FALSE;
@@ -5595,16 +5595,19 @@ HRESULT CInArchive::Open2(const Byte *sig, size_t size)
if (IsSolid)
{
- RINOK(_stream->Seek(DataStreamOffset, STREAM_SEEK_SET, NULL));
+ RINOK(SeekTo_DataStreamOffset());
}
else
{
_headerIsCompressed = ((compressedHeaderSize & kMask_IsCompressed) != 0);
compressedHeaderSize &= ~kMask_IsCompressed;
_nonSolidStartOffset = compressedHeaderSize;
- RINOK(_stream->Seek(DataStreamOffset + 4, STREAM_SEEK_SET, NULL));
+ RINOK(SeekTo(DataStreamOffset + 4));
}
+ if (FirstHeader.HeaderSize == 0)
+ return S_FALSE;
+
_data.Alloc(FirstHeader.HeaderSize);
_size = (size_t)FirstHeader.HeaderSize;
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h
index d8e6808b..028e4a5d 100644
--- a/CPP/7zip/Archive/Nsis/NsisIn.h
+++ b/CPP/7zip/Archive/Nsis/NsisIn.h
@@ -350,14 +350,19 @@ public:
return Decoder.Init(_stream, useFilter);
}
+ HRESULT SeekTo(UInt64 pos)
+ {
+ return _stream->Seek(pos, STREAM_SEEK_SET, NULL);
+ }
+
HRESULT SeekTo_DataStreamOffset()
{
- return _stream->Seek(DataStreamOffset, STREAM_SEEK_SET, NULL);
+ return SeekTo(DataStreamOffset);
}
HRESULT SeekToNonSolidItem(unsigned index)
{
- return _stream->Seek(GetPosOfNonSolidItem(index), STREAM_SEEK_SET, NULL);
+ return SeekTo(GetPosOfNonSolidItem(index));
}
void Clear();
@@ -403,23 +408,23 @@ public:
s = MultiByteToUnicodeString(APrefixes[item.Prefix]);
if (s.Len() > 0)
if (s.Back() != L'\\')
- s += L'\\';
+ s += '\\';
}
if (IsUnicode)
{
s += item.NameU;
if (item.NameU.IsEmpty())
- s += L"file";
+ s += "file";
}
else
{
s += MultiByteToUnicodeString(item.NameA);
if (item.NameA.IsEmpty())
- s += L"file";
+ s += "file";
}
- const char *kRemoveStr = "$INSTDIR\\";
+ const char * const kRemoveStr = "$INSTDIR\\";
if (s.IsPrefixedBy_Ascii_NoCase(kRemoveStr))
{
s.Delete(0, MyStringLen(kRemoveStr));
@@ -427,7 +432,7 @@ public:
s.DeleteFrontal(1);
}
if (item.IsUninstaller && ExeStub.Size() == 0)
- s += L".nsis";
+ s += ".nsis";
return s;
}
diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp
index a6350944..dff7701d 100644
--- a/CPP/7zip/Archive/NtfsHandler.cpp
+++ b/CPP/7zip/Archive/NtfsHandler.cpp
@@ -56,9 +56,9 @@ using namespace NWindows;
namespace NArchive {
namespace Ntfs {
-static const wchar_t *kVirtualFolder_System = L"[SYSTEM]";
-static const wchar_t *kVirtualFolder_Lost_Normal = L"[LOST]";
-static const wchar_t *kVirtualFolder_Lost_Deleted = L"[UNKNOWN]";
+static const wchar_t * const kVirtualFolder_System = L"[SYSTEM]";
+static const wchar_t * const kVirtualFolder_Lost_Normal = L"[LOST]";
+static const wchar_t * const kVirtualFolder_Lost_Deleted = L"[UNKNOWN]";
static const unsigned kNumSysRecs = 16;
@@ -394,7 +394,7 @@ static int CompareAttr(void *const *elem1, void *const *elem2, void *)
return 1;
else
{
- RINOZ(wcscmp(a1.Name.GetRawPtr(), a2.Name.GetRawPtr()));
+ RINOZ(a1.Name.Compare(a2.Name.GetRawPtr()));
}
return MyCompare(a1.LowVcn, a2.LowVcn);
}
@@ -2340,7 +2340,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
}
case kpidFileSystem:
{
- AString s = "NTFS";
+ AString s ("NTFS");
FOR_VECTOR (i, VolAttrs)
{
const CAttr &attr = VolAttrs[i];
@@ -2350,12 +2350,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
if (attr.ParseVolInfo(vi))
{
s.Add_Space();
- char temp[16];
- ConvertUInt32ToString(vi.MajorVer, temp);
- s += temp;
+ s.Add_UInt32(vi.MajorVer);
s += '.';
- ConvertUInt32ToString(vi.MinorVer, temp);
- s += temp;
+ s.Add_UInt32(vi.MinorVer);
}
break;
}
@@ -2722,18 +2719,14 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
for (UInt32 i = 0; i < numProps; i++)
{
- UString name = names[i];
- name.MakeLower_Ascii();
- if (name.IsEmpty())
- return E_INVALIDARG;
-
+ const wchar_t *name = names[i];
const PROPVARIANT &prop = values[i];
- if (name.IsEqualTo("ld"))
+ if (StringsAreEqualNoCase_Ascii(name, "ld"))
{
RINOK(PROPVARIANT_to_bool(prop, _showDeletedFiles));
}
- else if (name.IsEqualTo("ls"))
+ else if (StringsAreEqualNoCase_Ascii(name, "ls"))
{
RINOK(PROPVARIANT_to_bool(prop, _showSystemFiles));
}
diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp
index 7175cef3..30a60843 100644
--- a/CPP/7zip/Archive/PeHandler.cpp
+++ b/CPP/7zip/Archive/PeHandler.cpp
@@ -85,12 +85,6 @@ static HRESULT CalcCheckSum(ISequentialInStream *stream, UInt32 size, UInt32 exc
return S_OK;
}
-static AString GetDecString(UInt32 v)
-{
- char sz[16];
- ConvertUInt32ToString(v, sz);
- return sz;
-}
struct CVersion
{
@@ -407,13 +401,16 @@ static const CUInt32PCharPair g_HeaderCharacts[] =
static const CUInt32PCharPair g_DllCharacts[] =
{
+ { 5, "HighEntropyVA" },
{ 6, "Relocated" },
{ 7, "Integrity" },
{ 8, "NX-Compatible" },
{ 9, "NoIsolation" },
{ 10, "NoSEH" },
{ 11, "NoBind" },
+ { 12, "AppContainer" },
{ 13, "WDM" },
+ { 14, "GuardCF" },
{ 15, "TerminalServerAware" }
};
@@ -467,22 +464,30 @@ static const CUInt32PCharPair g_MachinePairs[] =
{ 0x0EBC, "EFI" },
{ 0x8664, "x64" },
{ 0x9041, "M32R" },
+ { 0xAA64, "ARM64" },
{ 0xC0EE, "CEE" }
};
-static const CUInt32PCharPair g_SubSystems[] =
-{
- { 0, "Unknown" },
- { 1, "Native" },
- { 2, "Windows GUI" },
- { 3, "Windows CUI" },
- { 7, "Posix" },
- { 9, "Windows CE" },
- { 10, "EFI" },
- { 11, "EFI Boot" },
- { 12, "EFI Runtime" },
- { 13, "EFI ROM" },
- { 14, "XBOX" }
+static const char * const g_SubSystems[] =
+{
+ "Unknown"
+ , "Native"
+ , "Windows GUI"
+ , "Windows CUI"
+ , NULL // "Old Windows CE"
+ , "OS2"
+ , NULL
+ , "Posix"
+ , "Win9x"
+ , "Windows CE"
+ , "EFI"
+ , "EFI Boot"
+ , "EFI Runtime"
+ , "EFI ROM"
+ , "XBOX"
+ , NULL
+ , "Windows Boot"
+ , "XBOX Catalog" // 17
};
static const char * const g_ResTypes[] =
@@ -878,7 +883,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidCpu: PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop); break;
case kpidBit64: if (_optHeader.Is64Bit()) prop = true; break;
- case kpidSubSystem: PAIR_TO_PROP(g_SubSystems, _optHeader.SubSystem, prop); break;
+ case kpidSubSystem: TYPE_TO_PROP(g_SubSystems, _optHeader.SubSystem, prop); break;
case kpidMTime:
case kpidCTime: TimeToProp(_header.Time, prop); break;
@@ -950,9 +955,7 @@ void CHandler::AddResNameToString(UString &s, UInt32 id) const
return;
}
}
- wchar_t sz[16];
- ConvertUInt32ToString(id, sz);
- s += sz;
+ s.Add_UInt32(id);
}
void CHandler::AddLangPrefix(UString &s, UInt32 lang) const
@@ -978,7 +981,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
UString s = _resourcesPrefix;
AddLangPrefix(s, item.Lang);
- s.AddAscii("string.txt");
+ s += "string.txt";
prop = s;
break;
}
@@ -996,7 +999,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
UString s = _resourcesPrefix;
AddLangPrefix(s, item.Lang);
- s.AddAscii("version.txt");
+ s += "version.txt";
prop = s;
break;
}
@@ -1019,7 +1022,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
if (item.Type < ARRAY_SIZE(g_ResTypes))
p = g_ResTypes[item.Type];
if (p)
- s.AddAscii(p);
+ s += p;
else
AddResNameToString(s, item.Type);
}
@@ -1028,9 +1031,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
if (item.HeaderSize != 0)
{
if (item.IsBmp())
- s.AddAscii(".bmp");
+ s += ".bmp";
else if (item.IsIcon())
- s.AddAscii(".ico");
+ s += ".ico";
}
prop = s;
break;
@@ -1112,7 +1115,8 @@ HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection)
thereIsSection = true;
CSection &sect = _sections.AddNew();
- sect.Name = ".debug" + GetDecString(i);
+ sect.Name = ".debug";
+ sect.Name.Add_UInt32(i);
sect.IsDebug = true;
sect.Time = de.Time;
sect.Va = de.Va;
@@ -1384,11 +1388,9 @@ static void PrintUInt32(CTextFile &f, UInt32 v)
f.AddString(s);
}
-static void PrintUInt32(UString &dest, UInt32 v)
+static inline void PrintUInt32(UString &dest, UInt32 v)
{
- wchar_t s[16];
- ConvertUInt32ToString(v, s);
- dest += s;
+ dest.Add_UInt32(v);
}
static void PrintHex(CTextFile &f, UInt32 val)
@@ -1410,9 +1412,9 @@ static void PrintVersion(CTextFile &f, UInt32 ms, UInt32 ls)
static void PrintVersion(UString &s, UInt32 ms, UInt32 ls)
{
- PrintUInt32(s, HIWORD(ms)); s += L'.';
- PrintUInt32(s, LOWORD(ms)); s += L'.';
- PrintUInt32(s, HIWORD(ls)); s += L'.';
+ PrintUInt32(s, HIWORD(ms)); s += '.';
+ PrintUInt32(s, LOWORD(ms)); s += '.';
+ PrintUInt32(s, HIWORD(ls)); s += '.';
PrintUInt32(s, LOWORD(ls));
}
@@ -1694,7 +1696,7 @@ bool CVersionBlock::Parse(const Byte *p, UInt32 size)
return false;
TotalLen = Get16(p);
ValueLen = Get16(p + 2);
- if (TotalLen == 0 || TotalLen > size)
+ if (TotalLen < k_ResoureBlockHeader_Size || TotalLen > size)
return false;
switch (Get16(p + 4))
{
@@ -2114,7 +2116,8 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi
static inline bool CheckPeOffset(UInt32 pe)
{
- return (pe >= 0x40 && pe <= 0x1000 && (pe & 7) == 0);
+ // ((pe & 7) == 0) is for most PE files. But there is unusual EFI-PE file that uses unaligned pe value.
+ return pe >= 0x40 && pe <= 0x1000 /* && (pe & 7) == 0 */ ;
}
static const unsigned kStartSize = 0x40;
@@ -2290,7 +2293,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
s2.PSize = s2.VSize = s.Pa - limit;
s2.IsAdditionalSection = true;
s2.Name = '[';
- s2.Name += GetDecString(num++);
+ s2.Name.Add_UInt32(num++);
s2.Name += ']';
limit = s.Pa;
}
@@ -2332,10 +2335,11 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
mixItem.SectionIndex = i;
if (_parseResources && sect.Name == ".rsrc" && _items.IsEmpty())
{
+ const unsigned numMixItems = _mixItems.Size();
HRESULT res = OpenResources(i, stream, callback);
if (res == S_OK)
{
- _resourcesPrefix.SetFromAscii(sect.Name);
+ _resourcesPrefix = sect.Name.Ptr();
_resourcesPrefix.Add_PathSepar();
FOR_VECTOR (j, _items)
{
@@ -2387,6 +2391,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
}
if (res != S_FALSE)
return res;
+ _mixItems.DeleteFrom(numMixItems);
CloseResources();
}
if (sect.IsAdditionalSection)
@@ -2422,7 +2427,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
_versionFullString.Add_LF();
const CStringKeyValue &k = _versionKeys[i];
_versionFullString += k.Key;
- _versionFullString += L": ";
+ _versionFullString += ": ";
_versionFullString += k.Value;
}
@@ -2702,7 +2707,8 @@ static bool FindValue(const CUInt32PCharPair *pairs, unsigned num, UInt32 value)
return false;
}
-#define MY_FIND_VALUE(pairs, value) FindValue(pairs, ARRAY_SIZE(pairs), value)
+#define MY_FIND_VALUE(pairs, val) FindValue(pairs, ARRAY_SIZE(pairs), val)
+#define MY_FIND_VALUE_2(strings, val) (val < ARRAY_SIZE(strings) && strings[val])
static const UInt32 kNumSection_MAX = 32;
@@ -2751,7 +2757,7 @@ bool CHeader::Parse(const Byte *p)
}
return
MY_FIND_VALUE(NPe::g_MachinePairs, Machine) &&
- MY_FIND_VALUE(NPe::g_SubSystems, SubSystem);
+ MY_FIND_VALUE_2(NPe::g_SubSystems, SubSystem);
}
API_FUNC_static_IsArc IsArc_Te(const Byte *p, size_t size)
@@ -2864,7 +2870,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
case kpidPhySize: prop = _totalSize; break;
case kpidCpu: PAIR_TO_PROP(NPe::g_MachinePairs, _h.Machine, prop); break;
- case kpidSubSystem: PAIR_TO_PROP(NPe::g_SubSystems, _h.SubSystem, prop); break;
+ case kpidSubSystem: TYPE_TO_PROP(NPe::g_SubSystems, _h.SubSystem, prop); break;
/*
case kpidImageBase: prop = _h.ImageBase; break;
case kpidAddressOfEntryPoint: prop = _h.AddressOfEntryPoint; break;
diff --git a/CPP/7zip/Archive/PpmdHandler.cpp b/CPP/7zip/Archive/PpmdHandler.cpp
index 528c5ceb..c80400bc 100644
--- a/CPP/7zip/Archive/PpmdHandler.cpp
+++ b/CPP/7zip/Archive/PpmdHandler.cpp
@@ -12,7 +12,6 @@ This code is based on:
#include "../../../C/Ppmd8.h"
#include "../../Common/ComTry.h"
-#include "../../Common/IntToString.h"
#include "../../Common/StringConvert.h"
#include "../../Windows/PropVariant.h"
@@ -104,6 +103,8 @@ class CHandler:
UInt64 _packSize;
CMyComPtr<ISequentialInStream> _stream;
+ void GetVersion(NCOM::CPropVariant &prop);
+
public:
MY_UNKNOWN_IMP2(IInArchive, IArchiveOpenSeq)
INTERFACE_IInArchive(;)
@@ -118,8 +119,30 @@ static const Byte kProps[] =
kpidMethod
};
+static const Byte kArcProps[] =
+{
+ kpidMethod
+};
+
IMP_IInArchive_Props
-IMP_IInArchive_ArcProps_NO_Table
+IMP_IInArchive_ArcProps
+
+void CHandler::GetVersion(NCOM::CPropVariant &prop)
+{
+ AString s ("PPMd");
+ s += (char)('A' + _item.Ver);
+ s += ":o";
+ s.Add_UInt32(_item.Order);
+ s += ":mem";
+ s.Add_UInt32(_item.MemInMB);
+ s += 'm';
+ if (_item.Ver >= kNewHeaderVer && _item.Restor != 0)
+ {
+ s += ":r";
+ s.Add_UInt32(_item.Restor);
+ }
+ prop = s;
+}
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
@@ -127,6 +150,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
switch (propID)
{
case kpidPhySize: if (_packSize_Defined) prop = _packSize; break;
+ case kpidMethod: GetVersion(prop); break;
}
prop.Detach(value);
return S_OK;
@@ -139,14 +163,6 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
return S_OK;
}
-static void UIntToString(AString &s, const char *prefix, unsigned value)
-{
- s += prefix;
- char temp[16];
- ::ConvertUInt32ToString((UInt32)value, temp);
- s += temp;
-}
-
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
@@ -164,17 +180,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
}
case kpidAttrib: prop = _item.Attrib; break;
case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;
- case kpidMethod:
- {
- AString s = "PPMd";
- s += (char)('A' + _item.Ver);
- UIntToString(s, ":o", _item.Order);
- UIntToString(s, ":mem", _item.MemInMB);
- s += 'm';
- if (_item.Ver >= kNewHeaderVer && _item.Restor != 0)
- UIntToString(s, ":r", _item.Restor);
- prop = s;
- }
+ case kpidMethod: GetVersion(prop); break;
}
prop.Detach(value);
return S_OK;
@@ -217,7 +223,7 @@ static const UInt32 kBot = (1 << 15);
struct CRangeDecoder
{
- IPpmd7_RangeDec s;
+ IPpmd7_RangeDec vt;
UInt32 Range;
UInt32 Code;
UInt32 Low;
@@ -251,15 +257,17 @@ public:
extern "C" {
-static UInt32 Range_GetThreshold(void *pp, UInt32 total)
+#define GET_RangeDecoder CRangeDecoder *p = CONTAINER_FROM_VTBL(pp, CRangeDecoder, vt);
+
+static UInt32 Range_GetThreshold(const IPpmd7_RangeDec *pp, UInt32 total)
{
- CRangeDecoder *p = (CRangeDecoder *)pp;
+ GET_RangeDecoder
return p->Code / (p->Range /= total);
}
-static void Range_Decode(void *pp, UInt32 start, UInt32 size)
+static void Range_Decode(const IPpmd7_RangeDec *pp, UInt32 start, UInt32 size)
{
- CRangeDecoder *p = (CRangeDecoder *)pp;
+ GET_RangeDecoder
start *= p->Range;
p->Low += start;
p->Code -= start;
@@ -267,17 +275,17 @@ static void Range_Decode(void *pp, UInt32 start, UInt32 size)
p->Normalize();
}
-static UInt32 Range_DecodeBit(void *pp, UInt32 size0)
+static UInt32 Range_DecodeBit(const IPpmd7_RangeDec *pp, UInt32 size0)
{
- CRangeDecoder *p = (CRangeDecoder *)pp;
+ GET_RangeDecoder
if (p->Code / (p->Range >>= 14) < size0)
{
- Range_Decode(p, 0, size0);
+ Range_Decode(&p->vt, 0, size0);
return 0;
}
else
{
- Range_Decode(p, size0, (1 << 14) - size0);
+ Range_Decode(&p->vt, size0, (1 << 14) - size0);
return 1;
}
}
@@ -286,9 +294,9 @@ static UInt32 Range_DecodeBit(void *pp, UInt32 size0)
CRangeDecoder::CRangeDecoder()
{
- s.GetThreshold = Range_GetThreshold;
- s.Decode = Range_Decode;
- s.DecodeBit = Range_DecodeBit;
+ vt.GetThreshold = Range_GetThreshold;
+ vt.Decode = Range_Decode;
+ vt.DecodeBit = Range_DecodeBit;
}
struct CPpmdCpp
@@ -336,7 +344,7 @@ struct CPpmdCpp
}
else
{
- _ppmd8.Stream.In = &inStream->p;
+ _ppmd8.Stream.In = &inStream->vt;
return Ppmd8_RangeDec_Init(&_ppmd8) != 0;
}
}
@@ -412,7 +420,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{
for (i = 0; i < kBufSize; i++)
{
- sym = Ppmd7_DecodeSymbol(&ppmd._ppmd7, &ppmd._rc.s);
+ sym = Ppmd7_DecodeSymbol(&ppmd._ppmd7, &ppmd._rc.vt);
if (inBuf.Extra || sym < 0)
break;
outBuf.Buf[i] = (Byte)sym;
diff --git a/CPP/7zip/Archive/QcowHandler.cpp b/CPP/7zip/Archive/QcowHandler.cpp
index a84fdc9b..065f59b3 100644
--- a/CPP/7zip/Archive/QcowHandler.cpp
+++ b/CPP/7zip/Archive/QcowHandler.cpp
@@ -284,11 +284,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
if (_cryptMethod == 1)
s += "AES";
else
- {
- char temp[16];
- ConvertUInt32ToString(_cryptMethod, temp);
- s += temp;
- }
+ s.Add_UInt32(_cryptMethod);
}
if (!s.IsEmpty())
diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.cpp b/CPP/7zip/Archive/Rar/Rar5Handler.cpp
index d70a5686..f166730e 100644
--- a/CPP/7zip/Archive/Rar/Rar5Handler.cpp
+++ b/CPP/7zip/Archive/Rar/Rar5Handler.cpp
@@ -50,22 +50,59 @@ static const Byte kMarker[kMarkerSize] = SIGNATURE;
static const size_t kCommentSize_Max = (size_t)1 << 16;
+
static const char * const kHostOS[] =
{
"Windows"
, "Unix"
};
-static const CUInt32PCharPair k_ArcFlags[] =
+
+static const char * const k_ArcFlags[] =
+{
+ "Volume"
+ , "VolumeField"
+ , "Solid"
+ , "Recovery"
+ , "Lock" // 4
+};
+
+
+static const char * const k_FileFlags[] =
+{
+ "Dir"
+ , "UnixTime"
+ , "CRC"
+ , "UnknownSize"
+};
+
+
+static const char * const g_ExtraTypes[] =
+{
+ "0"
+ , "Crypto"
+ , "Hash"
+ , "Time"
+ , "Version"
+ , "Link"
+ , "UnixOwner"
+ , "Subdata"
+};
+
+
+static const char * const g_LinkTypes[] =
{
- { 0, "Volume" },
- { 1, "VolumeField" },
- { 2, "Solid" },
- { 3, "Recovery" },
- { 4, "Lock" }
+ "0"
+ , "UnixSymLink"
+ , "WinSymLink"
+ , "WinJunction"
+ , "HardLink"
+ , "FileCopy"
};
+static const char g_ExtraTimeFlags[] = { 'u', 'M', 'C', 'A', 'n' };
+
template <unsigned alignMask>
struct CAlignedBuffer
@@ -106,7 +143,8 @@ static unsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val)
{
Byte b = p[i];
if (i < 10)
- *val |= (UInt64)(b & 0x7F) << (7 * i++);
+ *val |= (UInt64)(b & 0x7F) << (7 * i);
+ i++;
if ((b & 0x80) == 0)
return i;
}
@@ -114,7 +152,54 @@ static unsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val)
}
-int CItem::FindExtra(unsigned type, unsigned &recordDataSize) const
+bool CLinkInfo::Parse(const Byte *p, unsigned size)
+{
+ const Byte *pStart = p;
+ unsigned num = ReadVarInt(p, size, &Type);
+ if (num == 0) return false; p += num; size -= num;
+
+ num = ReadVarInt(p, size, &Flags);
+ if (num == 0) return false; p += num; size -= num;
+
+ UInt64 len;
+ num = ReadVarInt(p, size, &len);
+ if (num == 0) return false; p += num; size -= num;
+
+ if (size != len)
+ return false;
+
+ NameLen = (unsigned)len;
+ NameOffset = (unsigned)(p - pStart);
+ return true;
+}
+
+
+static void AddHex64(AString &s, UInt64 v)
+{
+ char sz[32];
+ sz[0] = '0';
+ sz[1] = 'x';
+ ConvertUInt64ToHex(v, sz + 2);
+ s += sz;
+}
+
+
+static void PrintType(AString &s, const char * const table[], unsigned num, UInt64 val)
+{
+ char sz[32];
+ const char *p = NULL;
+ if (val < num)
+ p = table[(unsigned)val];
+ if (!p)
+ {
+ ConvertUInt64ToString(val, sz);
+ p = sz;
+ }
+ s += p;
+}
+
+
+int CItem::FindExtra(unsigned extraID, unsigned &recordDataSize) const
{
recordDataSize = 0;
size_t offset = 0;
@@ -137,8 +222,8 @@ int CItem::FindExtra(unsigned type, unsigned &recordDataSize) const
rem = (size_t)size;
}
{
- UInt64 type2;
- unsigned num = ReadVarInt(Extra + offset, rem, &type2);
+ UInt64 id;
+ unsigned num = ReadVarInt(Extra + offset, rem, &id);
if (num == 0)
return -1;
offset += num;
@@ -147,12 +232,12 @@ int CItem::FindExtra(unsigned type, unsigned &recordDataSize) const
// There was BUG in RAR 5.21- : it stored (size-1) instead of (size)
// for Subdata record in Service header.
// That record always was last in bad archives, so we can fix that case.
- if (type2 == NExtraRecordType::kSubdata
+ if (id == NExtraID::kSubdata
&& RecordType == NHeaderType::kService
&& rem + 1 == Extra.Size() - offset)
rem++;
- if (type2 == type)
+ if (id == extraID)
{
recordDataSize = (unsigned)rem;
return (int)offset;
@@ -164,19 +249,118 @@ int CItem::FindExtra(unsigned type, unsigned &recordDataSize) const
}
+void CItem::PrintInfo(AString &s) const
+{
+ size_t offset = 0;
+
+ for (;;)
+ {
+ size_t rem = Extra.Size() - offset;
+ if (rem == 0)
+ return;
+
+ {
+ UInt64 size;
+ unsigned num = ReadVarInt(Extra + offset, rem, &size);
+ if (num == 0)
+ return;
+ offset += num;
+ rem -= num;
+ if (size > rem)
+ break;
+ rem = (size_t)size;
+ }
+ {
+ UInt64 id;
+ {
+ unsigned num = ReadVarInt(Extra + offset, rem, &id);
+ if (num == 0)
+ break;
+ offset += num;
+ rem -= num;
+ }
+
+ // There was BUG in RAR 5.21- : it stored (size-1) instead of (size)
+ // for Subdata record in Service header.
+ // That record always was last in bad archives, so we can fix that case.
+ if (id == NExtraID::kSubdata
+ && RecordType == NHeaderType::kService
+ && rem + 1 == Extra.Size() - offset)
+ rem++;
+
+ s.Add_Space_if_NotEmpty();
+ PrintType(s, g_ExtraTypes, ARRAY_SIZE(g_ExtraTypes), id);
+
+ if (id == NExtraID::kTime)
+ {
+ const Byte *p = Extra + offset;
+ UInt64 flags;
+ unsigned num = ReadVarInt(p, rem, &flags);
+ if (num != 0)
+ {
+ s += ':';
+ for (unsigned i = 0; i < ARRAY_SIZE(g_ExtraTimeFlags); i++)
+ if ((flags & ((UInt64)1 << i)) != 0)
+ s += g_ExtraTimeFlags[i];
+ flags &= ~(((UInt64)1 << ARRAY_SIZE(g_ExtraTimeFlags)) - 1);
+ if (flags != 0)
+ {
+ s += '_';
+ AddHex64(s, flags);
+ }
+ }
+ }
+ else if (id == NExtraID::kLink)
+ {
+ CLinkInfo linkInfo;
+ if (linkInfo.Parse(Extra + offset, (unsigned)rem))
+ {
+ s += ':';
+ PrintType(s, g_LinkTypes, ARRAY_SIZE(g_LinkTypes), linkInfo.Type);
+ UInt64 flags = linkInfo.Flags;
+ if (flags != 0)
+ {
+ s += ':';
+ if (flags & NLinkFlags::kTargetIsDir)
+ {
+ s += 'D';
+ flags &= ~((UInt64)NLinkFlags::kTargetIsDir);
+ }
+ if (flags != 0)
+ {
+ s += '_';
+ AddHex64(s, flags);
+ }
+ }
+ }
+ }
+
+ offset += rem;
+ }
+ }
+
+ s.Add_OptSpaced("ERROR");
+}
+
+
bool CCryptoInfo::Parse(const Byte *p, size_t size)
{
+ Algo = 0;
+ Flags = 0;
+ Cnt = 0;
+
unsigned num = ReadVarInt(p, size, &Algo);
if (num == 0) return false; p += num; size -= num;
num = ReadVarInt(p, size, &Flags);
if (num == 0) return false; p += num; size -= num;
+ if (size > 0)
+ Cnt = p[0];
+
if (size != 1 + 16 + 16 + (unsigned)(IsThereCheck() ? 12 : 0))
return false;
- Cnt = p[0];
-
return true;
}
@@ -184,7 +368,7 @@ bool CCryptoInfo::Parse(const Byte *p, size_t size)
bool CItem::FindExtra_Version(UInt64 &version) const
{
unsigned size;
- int offset = FindExtra(NExtraRecordType::kVersion, size);
+ int offset = FindExtra(NExtraID::kVersion, size);
if (offset < 0)
return false;
const Byte *p = Extra + (unsigned)offset;
@@ -202,26 +386,12 @@ bool CItem::FindExtra_Version(UInt64 &version) const
bool CItem::FindExtra_Link(CLinkInfo &link) const
{
unsigned size;
- int offset = FindExtra(NExtraRecordType::kLink, size);
+ int offset = FindExtra(NExtraID::kLink, size);
if (offset < 0)
return false;
- const Byte *p = Extra + (unsigned)offset;
-
- unsigned num = ReadVarInt(p, size, &link.Type);
- if (num == 0) return false; p += num; size -= num;
-
- num = ReadVarInt(p, size, &link.Flags);
- if (num == 0) return false; p += num; size -= num;
-
- UInt64 len;
- num = ReadVarInt(p, size, &len);
- if (num == 0) return false; p += num; size -= num;
-
- if (size != len)
+ if (!link.Parse(Extra + (unsigned)offset, size))
return false;
-
- link.NameLen = (unsigned)len;
- link.NameOffset = (unsigned)(p - Extra);
+ link.NameOffset += offset;
return true;
}
@@ -268,14 +438,14 @@ void CItem::Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop)
UString unicode;
if (ConvertUTF8ToUnicode(s, unicode))
- prop = NItemName::GetOSName(unicode);
+ prop = NItemName::GetOsPath(unicode);
}
bool CItem::GetAltStreamName(AString &name) const
{
name.Empty();
unsigned size;
- int offset = FindExtra(NExtraRecordType::kSubdata, size);
+ int offset = FindExtra(NExtraID::kSubdata, size);
if (offset < 0)
return false;
name.SetFrom_CalcLen((const char *)(Extra + (unsigned)offset), size);
@@ -578,7 +748,7 @@ HRESULT CInArchive::ReadBlockHeader(CHeader &h)
/*
-int CInArcInfo::FindExtra(unsigned type, unsigned &recordDataSize) const
+int CInArcInfo::FindExtra(unsigned extraID, unsigned &recordDataSize) const
{
recordDataSize = 0;
size_t offset = 0;
@@ -601,14 +771,14 @@ int CInArcInfo::FindExtra(unsigned type, unsigned &recordDataSize) const
rem = (size_t)size;
}
{
- UInt64 type2;
- unsigned num = ReadVarInt(Extra + offset, rem, &type2);
+ UInt64 id;
+ unsigned num = ReadVarInt(Extra + offset, rem, &id);
if (num == 0)
return -1;
offset += num;
rem -= num;
- if (type2 == type)
+ if (id == extraID)
{
recordDataSize = (unsigned)rem;
return (int)offset;
@@ -929,7 +1099,7 @@ HRESULT CUnpacker::Create(DECL_EXTERNAL_CODECS_LOC_VARS const CItem &item, bool
}
unsigned cryptoSize = 0;
- int cryptoOffset = item.FindExtra(NExtraRecordType::kCrypto, cryptoSize);
+ int cryptoOffset = item.FindExtra(NExtraID::kCrypto, cryptoSize);
if (cryptoOffset >= 0)
{
@@ -1023,7 +1193,7 @@ HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSiz
// if (res == S_OK)
{
unsigned cryptoSize = 0;
- int cryptoOffset = lastItem.FindExtra(NExtraRecordType::kCrypto, cryptoSize);
+ int cryptoOffset = lastItem.FindExtra(NExtraID::kCrypto, cryptoSize);
NCrypto::NRar5::CDecoder *crypto = NULL;
if (cryptoOffset >= 0)
@@ -1190,7 +1360,7 @@ static const Byte kProps[] =
kpidCRC,
kpidHostOS,
kpidMethod,
-
+ kpidCharacts,
kpidSymLink,
kpidHardLink,
kpidCopyLink,
@@ -1308,8 +1478,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
if (/* &_missingVol || */ !_missingVolName.IsEmpty())
{
- UString s;
- s.SetFromAscii("Missing volume : ");
+ UString s ("Missing volume : ");
s += _missingVolName;
prop = s;
}
@@ -1339,13 +1508,11 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
if (arcInfo->IsVolume())
{
- char sz[32];
- ConvertUInt64ToString(arcInfo->GetVolIndex() + 1, sz);
- unsigned len = MyStringLen(sz);
- AString s = "part";
- for (; len < 2; len++)
+ AString s ("part");
+ UInt32 v = (UInt32)arcInfo->GetVolIndex() + 1;
+ if (v < 10)
s += '0';
- s += sz;
+ s.Add_UInt32(v);
s += ".rar";
prop = s;
}
@@ -1452,7 +1619,7 @@ STDMETHODIMP CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data
static void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CPropVariant &prop)
{
unsigned size;
- int offset = item.FindExtra(NExtraRecordType::kTime, size);
+ int offset = item.FindExtra(NExtraID::kTime, size);
if (offset < 0)
return;
@@ -1470,29 +1637,43 @@ static void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CProp
return;
unsigned numStamps = 0;
+ unsigned curStamp = 0;
unsigned i;
for (i = 0; i < 3; i++)
if ((flags & (NTimeRecord::NFlags::kMTime << i)) != 0)
+ {
+ if (i == stampIndex)
+ curStamp = numStamps;
numStamps++;
- unsigned stampSizeLog = ((flags & NTimeRecord::NFlags::kUnixTime) != 0) ? 2 : 3;
-
- if ((numStamps << stampSizeLog) != size)
- return;
-
- numStamps = 0;
- for (i = 0; i < stampIndex; i++)
- if ((flags & (NTimeRecord::NFlags::kMTime << i)) != 0)
- numStamps++;
-
- p += (numStamps << stampSizeLog);
+ }
FILETIME ft;
+
if ((flags & NTimeRecord::NFlags::kUnixTime) != 0)
- NWindows::NTime::UnixTimeToFileTime(Get32(p), ft);
+ {
+ curStamp *= 4;
+ if (curStamp + 4 > size)
+ return;
+ const Byte *p2 = p + curStamp;
+ UInt64 val = NTime::UnixTimeToFileTime64(Get32(p2));
+ numStamps *= 4;
+ if ((flags & NTimeRecord::NFlags::kUnixNs) != 0 && numStamps * 2 <= size)
+ {
+ const UInt32 ns = Get32(p2 + numStamps) & 0x3FFFFFFF;
+ if (ns < 1000000000)
+ val += ns / 100;
+ }
+ ft.dwLowDateTime = (DWORD)val;
+ ft.dwHighDateTime = (DWORD)(val >> 32);
+ }
else
{
- ft.dwLowDateTime = Get32(p);
- ft.dwHighDateTime = Get32(p + 4);
+ curStamp *= 8;
+ if (curStamp + 8 > size)
+ return;
+ const Byte *p2 = p + curStamp;
+ ft.dwLowDateTime = Get32(p2);
+ ft.dwHighDateTime = Get32(p2 + 4);
}
prop = ft;
@@ -1537,19 +1718,19 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
break;
if (item.Version_Defined)
{
- wchar_t temp[32];
+ char temp[32];
// temp[0] = ';';
// ConvertUInt64ToString(item.Version, temp + 1);
// unicodeName += temp;
ConvertUInt64ToString(item.Version, temp);
- UString s2 = L"[VER]" WSTRING_PATH_SEPARATOR;
+ UString s2 ("[VER]" STRING_PATH_SEPARATOR);
s2 += temp;
s2.Add_PathSepar();
unicodeName.Insert(0, s2);
}
}
- NItemName::ConvertToOSName2(unicodeName);
+ NItemName::ReplaceToOsSlashes_Remove_TailSlash(unicodeName);
prop = unicodeName;
break;
@@ -1623,7 +1804,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidMethod:
{
- char temp[64];
+ char temp[128];
unsigned algo = item.GetAlgoVersion();
char *s = temp;
if (algo != 0)
@@ -1645,16 +1826,28 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
}
unsigned cryptoSize = 0;
- int cryptoOffset = item.FindExtra(NExtraRecordType::kCrypto, cryptoSize);
+ int cryptoOffset = item.FindExtra(NExtraID::kCrypto, cryptoSize);
if (cryptoOffset >= 0)
{
s = temp + strlen(temp);
*s++ = ' ';
- strcpy(s, "AES:");
+
CCryptoInfo cryptoInfo;
- if (cryptoInfo.Parse(item.Extra + (unsigned)cryptoOffset, cryptoSize))
+
+ bool isOK = cryptoInfo.Parse(item.Extra + (unsigned)cryptoOffset, cryptoSize);
+
+ if (cryptoInfo.Algo == 0)
+ s = MyStpCpy(s, "AES");
+ else
{
+ s = MyStpCpy(s, "Crypto_");
+ ConvertUInt64ToString(cryptoInfo.Algo, s);
s += strlen(s);
+ }
+
+ if (isOK)
+ {
+ *s++ = ':';
ConvertUInt32ToString(cryptoInfo.Cnt, s);
s += strlen(s);
*s++ = ':';
@@ -1666,6 +1859,35 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
break;
}
+ case kpidCharacts:
+ {
+ AString s;
+
+ if (item.ACL >= 0)
+ {
+ s.Add_OptSpaced("ACL");
+ }
+
+ UInt32 flags = item.Flags;
+ // flags &= ~(6); // we don't need compression related bits here.
+
+ if (flags != 0)
+ {
+ AString s2 = FlagsToString(k_FileFlags, ARRAY_SIZE(k_FileFlags), flags);
+ if (!s2.IsEmpty())
+ {
+ s.Add_OptSpaced(s2);
+ }
+ }
+
+ item.PrintInfo(s);
+
+ if (!s.IsEmpty())
+ prop = s;
+ break;
+ }
+
+
case kpidHostOS:
if (item.HostOS < ARRAY_SIZE(kHostOS))
prop = kHostOS[(size_t)item.HostOS];
@@ -1788,7 +2010,7 @@ void CHandler::FillLinks()
const CItem &item = _items[ref.Item];
if (item.IsDir() || item.IsService() || item.PackSize != 0)
continue;
- CItem::CLinkInfo linkInfo;
+ CLinkInfo linkInfo;
if (!item.FindExtra_Link(linkInfo) || linkInfo.Type != NLinkType::kFileCopy)
continue;
link.SetFrom_CalcLen((const char *)(item.Extra + linkInfo.NameOffset), linkInfo.NameLen);
diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.h b/CPP/7zip/Archive/Rar/Rar5Handler.h
index 27e937de..d3e33d7c 100644
--- a/CPP/7zip/Archive/Rar/Rar5Handler.h
+++ b/CPP/7zip/Archive/Rar/Rar5Handler.h
@@ -85,7 +85,7 @@ enum EHostOS
// ---------- Extra ----------
-namespace NExtraRecordType
+namespace NExtraID
{
enum
{
@@ -99,7 +99,7 @@ namespace NExtraRecordType
};
}
-// const unsigned kCryptoAlgo_AES = 0;
+const unsigned kCryptoAlgo_AES = 0;
namespace NCryptoFlags
{
@@ -133,8 +133,9 @@ namespace NTimeRecord
{
const unsigned kUnixTime = 1 << 0;
const unsigned kMTime = 1 << 1;
- // const unsigned kCTime = 1 << 2;
- // const unsigned kATime = 1 << 3;
+ const unsigned kCTime = 1 << 2;
+ const unsigned kATime = 1 << 3;
+ const unsigned kUnixNs = 1 << 4;
}
}
@@ -156,6 +157,17 @@ namespace NLinkFlags
}
+struct CLinkInfo
+{
+ UInt64 Type;
+ UInt64 Flags;
+ unsigned NameOffset;
+ unsigned NameLen;
+
+ bool Parse(const Byte *p, unsigned size);
+};
+
+
struct CItem
{
UInt32 CommonFlags;
@@ -230,18 +242,20 @@ struct CItem
bool Is_ACL() const { return IsService() && Name == "ACL"; }
// bool Is_QO() const { return IsService() && Name == "QO"; }
- int FindExtra(unsigned type, unsigned &recordDataSize) const;
+ int FindExtra(unsigned extraID, unsigned &recordDataSize) const;
+ void PrintInfo(AString &s) const;
+
bool IsEncrypted() const
{
unsigned size;
- return FindExtra(NExtraRecordType::kCrypto, size) >= 0;
+ return FindExtra(NExtraID::kCrypto, size) >= 0;
}
int FindExtra_Blake() const
{
unsigned size = 0;
- int offset = FindExtra(NExtraRecordType::kHash, size);
+ int offset = FindExtra(NExtraID::kHash, size);
if (offset >= 0
&& size == BLAKE2S_DIGEST_SIZE + 1
&& Extra[(unsigned)offset] == kHashID_Blake2sp)
@@ -251,14 +265,6 @@ struct CItem
bool FindExtra_Version(UInt64 &version) const;
- struct CLinkInfo
- {
- UInt64 Type;
- UInt64 Flags;
- unsigned NameOffset;
- unsigned NameLen;
- };
-
bool FindExtra_Link(CLinkInfo &link) const;
void Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) const;
bool Is_CopyLink() const;
@@ -313,7 +319,7 @@ struct CInArcInfo
bool Is_Recovery() const { return (Flags & NLocatorFlags::kRecovery) != 0; }
};
- int FindExtra(unsigned type, unsigned &recordDataSize) const;
+ int FindExtra(unsigned extraID, unsigned &recordDataSize) const;
bool FindExtra_Locator(CLocator &locator) const;
*/
diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp
index e858c1ea..c097b15c 100644
--- a/CPP/7zip/Archive/Rar/RarHandler.cpp
+++ b/CPP/7zip/Archive/Rar/RarHandler.cpp
@@ -104,20 +104,18 @@ static const char * const kHostOS[] =
, "BeOS"
};
-static const char *kUnknownOS = "Unknown";
-
-static const CUInt32PCharPair k_Flags[] =
+static const char * const k_Flags[] =
{
- { 0, "Volume" },
- { 1, "Comment" },
- { 2, "Lock" },
- { 3, "Solid" },
- { 4, "NewVolName" }, // pack_comment in old versuons
- { 5, "Authenticity" },
- { 6, "Recovery" },
- { 7, "BlockEncryption" },
- { 8, "FirstVolume" },
- { 9, "EncryptVer" }
+ "Volume"
+ , "Comment"
+ , "Lock"
+ , "Solid"
+ , "NewVolName" // pack_comment in old versuons
+ , "Authenticity"
+ , "Recovery"
+ , "BlockEncryption"
+ , "FirstVolume"
+ , "EncryptVer" // 9
};
enum EErrorType
@@ -132,13 +130,13 @@ class CInArchive
{
IInStream *m_Stream;
UInt64 m_StreamStartPosition;
- CBuffer<wchar_t> _unicodeNameBuffer;
+ UString _unicodeNameBuffer;
CByteBuffer _comment;
CByteBuffer m_FileHeaderData;
NHeader::NBlock::CBlock m_BlockHeader;
NCrypto::NRar3::CDecoder *m_RarAESSpec;
CMyComPtr<ICompressFilter> m_RarAES;
- CBuffer<Byte> m_DecryptedData;
+ CByteBuffer m_DecryptedData;
Byte *m_DecryptedDataAligned;
UInt32 m_DecryptedDataSize;
bool m_CryptoMode;
@@ -272,14 +270,19 @@ bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size)
return processed == size;
}
-static void DecodeUnicodeFileName(const Byte *name, const Byte *encName,
+
+static unsigned DecodeUnicodeFileName(const Byte *name, const Byte *encName,
unsigned encSize, wchar_t *unicodeName, unsigned maxDecSize)
{
unsigned encPos = 0;
unsigned decPos = 0;
unsigned flagBits = 0;
Byte flags = 0;
- Byte highByte = encName[encPos++];
+
+ if (encPos >= encSize)
+ return 0; // error
+ const unsigned highBits = ((unsigned)encName[encPos++]) << 8;
+
while (encPos < encSize && decPos < maxDecSize)
{
if (flagBits == 0)
@@ -287,40 +290,46 @@ static void DecodeUnicodeFileName(const Byte *name, const Byte *encName,
flags = encName[encPos++];
flagBits = 8;
}
- switch (flags >> 6)
+
+ if (encPos >= encSize)
+ break; // error
+ unsigned len = encName[encPos++];
+
+ flagBits -= 2;
+ const unsigned mode = (flags >> flagBits) & 3;
+
+ if (mode != 3)
{
- case 0:
- unicodeName[decPos++] = encName[encPos++];
- break;
- case 1:
- unicodeName[decPos++] = (wchar_t)(encName[encPos++] + (highByte << 8));
- break;
- case 2:
- unicodeName[decPos++] = (wchar_t)(encName[encPos] + (encName[encPos + 1] << 8));
- encPos += 2;
- break;
- case 3:
- {
- unsigned len = encName[encPos++];
- if (len & 0x80)
- {
- Byte correction = encName[encPos++];
- for (len = (len & 0x7f) + 2;
- len > 0 && decPos < maxDecSize; len--, decPos++)
- unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + (highByte << 8));
- }
- else
- for (len += 2; len > 0 && decPos < maxDecSize; len--, decPos++)
- unicodeName[decPos] = name[decPos];
- }
- break;
+ if (mode == 1)
+ len += highBits;
+ else if (mode == 2)
+ {
+ if (encPos >= encSize)
+ break; // error
+ len += ((unsigned)encName[encPos++] << 8);
+ }
+ unicodeName[decPos++] = (wchar_t)len;
+ }
+ else
+ {
+ if (len & 0x80)
+ {
+ if (encPos >= encSize)
+ break; // error
+ Byte correction = encName[encPos++];
+ for (len = (len & 0x7f) + 2; len > 0 && decPos < maxDecSize; len--, decPos++)
+ unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + highBits);
+ }
+ else
+ for (len += 2; len > 0 && decPos < maxDecSize; len--, decPos++)
+ unicodeName[decPos] = name[decPos];
}
- flags <<= 2;
- flagBits -= 2;
}
- unicodeName[decPos < maxDecSize ? decPos : maxDecSize - 1] = 0;
+
+ return decPos < maxDecSize ? decPos : maxDecSize - 1;
}
+
void CInArchive::ReadName(const Byte *p, unsigned nameSize, CItem &item)
{
item.UnicodeName.Empty();
@@ -336,8 +345,8 @@ void CInArchive::ReadName(const Byte *p, unsigned nameSize, CItem &item)
{
i++;
unsigned uNameSizeMax = MyMin(nameSize, (unsigned)0x400);
- _unicodeNameBuffer.AllocAtLeast(uNameSizeMax + 1);
- DecodeUnicodeFileName(p, p + i, nameSize - i, _unicodeNameBuffer, uNameSizeMax);
+ unsigned len = DecodeUnicodeFileName(p, p + i, nameSize - i, _unicodeNameBuffer.GetBuf(uNameSizeMax), uNameSizeMax);
+ _unicodeNameBuffer.ReleaseBuf_SetEnd(len);
item.UnicodeName = _unicodeNameBuffer;
}
else if (!ConvertUTF8ToUnicode(item.Name, item.UnicodeName))
@@ -818,7 +827,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidSolid: prop = _arcInfo.IsSolid(); break;
case kpidCharacts:
{
- AString s = FlagsToString(k_Flags, ARRAY_SIZE(k_Flags), _arcInfo.Flags);
+ AString s (FlagsToString(k_Flags, ARRAY_SIZE(k_Flags), _arcInfo.Flags));
// FLAGS_TO_PROP(k_Flags, _arcInfo.Flags, prop);
if (_arcInfo.Is_DataCRC_Defined())
{
@@ -871,8 +880,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
if (/* &_missingVol || */ !_missingVolName.IsEmpty())
{
- UString s;
- s.SetFromAscii("Missing volume : ");
+ UString s ("Missing volume : ");
s += _missingVolName;
prop = s;
}
@@ -900,13 +908,11 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
if (_arcInfo.Is_VolNumber_Defined())
{
- char sz[16];
- ConvertUInt32ToString((UInt32)_arcInfo.VolNumber + 1, sz);
- unsigned len = MyStringLen(sz);
- AString s = "part";
- for (; len < 2; len++)
+ AString s ("part");
+ UInt32 v = (UInt32)_arcInfo.VolNumber + 1;
+ if (v < 10)
s += '0';
- s += sz;
+ s.Add_UInt32(v);
s += ".rar";
prop = s;
}
@@ -974,7 +980,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
u = mainItem->GetName();
u += item.GetName();
*/
- prop = (const wchar_t *)NItemName::WinNameToOSName(item.GetName());
+ prop = (const wchar_t *)NItemName::WinPathToOsPath(item.GetName());
break;
}
case kpidIsDir: prop = item.IsDir(); break;
@@ -1015,7 +1021,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = s;
break;
}
- case kpidHostOS: prop = (item.HostOS < ARRAY_SIZE(kHostOS)) ? kHostOS[item.HostOS] : kUnknownOS; break;
+ case kpidHostOS:
+ TYPE_TO_PROP(kHostOS, item.HostOS, prop);
+ break;
}
prop.Detach(value);
return S_OK;
@@ -1324,7 +1332,13 @@ STDMETHODIMP CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
if (_curIndex >= _refItem.NumItems)
break;
const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex];
- IInStream *s = (*_arcs)[_refItem.VolumeIndex + _curIndex].Stream;
+ unsigned volIndex = _refItem.VolumeIndex + _curIndex;
+ if (volIndex >= _arcs->Size())
+ {
+ return S_OK;
+ // return S_FALSE;
+ }
+ IInStream *s = (*_arcs)[volIndex].Stream;
RINOK(s->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL));
_stream = s;
_calcCrc = (CrcIsOK && item.IsSplitAfter());
diff --git a/CPP/7zip/Archive/Rar/RarVol.h b/CPP/7zip/Archive/Rar/RarVol.h
index 2d2ce473..310369d4 100644
--- a/CPP/7zip/Archive/Rar/RarVol.h
+++ b/CPP/7zip/Archive/Rar/RarVol.h
@@ -41,7 +41,7 @@ public:
}
else if (ext.IsEqualTo_Ascii_NoCase("exe"))
{
- _after.SetFromAscii(".rar");
+ _after = ".rar";
base.DeleteFrom(dotPos);
}
else if (!newStyle)
@@ -76,8 +76,8 @@ public:
_after.Empty();
_before = base;
- _before += L'.';
- _changed.SetFromAscii("r00");
+ _before += '.';
+ _changed = "r00";
_needChangeForNext = false;
return true;
}
diff --git a/CPP/7zip/Archive/RpmHandler.cpp b/CPP/7zip/Archive/RpmHandler.cpp
index 08df1ae7..e0ec28ce 100644
--- a/CPP/7zip/Archive/RpmHandler.cpp
+++ b/CPP/7zip/Archive/RpmHandler.cpp
@@ -11,6 +11,7 @@
#include "../../Common/UTFConvert.h"
#include "../../Windows/PropVariant.h"
+#include "../../Windows/PropVariantUtils.h"
#include "../../Windows/TimeUtils.h"
#include "../Common/RegisterArc.h"
@@ -167,6 +168,16 @@ struct CEntry
}
};
+
+#ifdef _SHOW_RPM_METADATA
+struct CMetaFile
+{
+ UInt32 Tag;
+ UInt32 Offset;
+ UInt32 Size;
+};
+#endif
+
class CHandler: public CHandlerCont
{
UInt64 _headersSize; // is equal to start offset of payload data
@@ -198,6 +209,7 @@ class CHandler: public CHandlerCont
#ifdef _SHOW_RPM_METADATA
AString _metadata;
+ CRecordVector<CMetaFile> _metaFiles;
#endif
void SetTime(NCOM::CPropVariant &prop) const
@@ -205,8 +217,8 @@ class CHandler: public CHandlerCont
if (_time_Defined && _buildTime != 0)
{
FILETIME ft;
- if (NTime::UnixTime64ToFileTime(_buildTime, ft))
- prop = ft;
+ NTime::UnixTimeToFileTime(_buildTime, ft);
+ prop = ft;
}
}
@@ -266,16 +278,10 @@ void CHandler::AddCPU(AString &s) const
{
if (_lead.Type == kRpmType_Bin)
{
- char temp[16];
- const char *p;
if (_lead.Cpu < ARRAY_SIZE(k_CPUs))
- p = k_CPUs[_lead.Cpu];
+ s += k_CPUs[_lead.Cpu];
else
- {
- ConvertUInt32ToString(_lead.Cpu, temp);
- p = temp;
- }
- s += p;
+ s.Add_UInt32(_lead.Cpu);
}
}
}
@@ -376,29 +382,18 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
SetStringProp(_os, prop);
else
{
- char temp[16];
- const char *p;
- if (_lead.Os < ARRAY_SIZE(k_OS))
- p = k_OS[_lead.Os];
- else
- {
- ConvertUInt32ToString(_lead.Os, temp);
- p = temp;
- }
- prop = p;
+ TYPE_TO_PROP(k_OS, _lead.Os, prop);
}
break;
}
#ifdef _SHOW_RPM_METADATA
- case kpidComment: SetStringProp(_metadata, prop); break;
+ // case kpidComment: SetStringProp(_metadata, prop); break;
#endif
case kpidName:
{
- AString s = GetBaseName();
- s += ".rpm";
- SetStringProp(s, prop);
+ SetStringProp(GetBaseName() + ".rpm", prop);
break;
}
}
@@ -408,9 +403,10 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
}
-STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
NWindows::NCOM::CPropVariant prop;
+ if (index == 0)
switch (propID)
{
case kpidSize:
@@ -425,7 +421,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
case kpidPath:
{
- AString s = GetBaseName();
+ AString s (GetBaseName());
s += '.';
AddSubFileExtension(s);
SetStringProp(s, prop);
@@ -440,6 +436,37 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
}
*/
}
+ #ifdef _SHOW_RPM_METADATA
+ else
+ {
+ index--;
+ if (index > _metaFiles.Size())
+ return E_INVALIDARG;
+ const CMetaFile &meta = _metaFiles[index];
+ switch (propID)
+ {
+ case kpidSize:
+ case kpidPackSize:
+ prop = meta.Size;
+ break;
+
+ case kpidMTime:
+ case kpidCTime:
+ SetTime(prop);
+ break;
+
+ case kpidPath:
+ {
+ AString s ("[META]");
+ s.Add_PathSepar();
+ s.Add_UInt32(meta.Tag);
+ prop = s;
+ break;
+ }
+ }
+ }
+ #endif
+
prop.Detach(value);
return S_OK;
}
@@ -499,10 +526,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader)
{
#ifdef _SHOW_RPM_METADATA
{
- char temp[16];
- ConvertUInt32ToString(entry.Tag, temp);
-
- _metadata += temp;
+ _metadata.Add_UInt32(entry.Tag);
_metadata += ": ";
}
#endif
@@ -515,7 +539,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader)
for (j = 0; j < rem && p[j] != 0; j++);
if (j == rem)
return S_FALSE;
- AString s = (const char *)p;
+ AString s((const char *)p);
switch (entry.Tag)
{
case RPMTAG_NAME: _name = s; break;
@@ -548,9 +572,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader)
{
if (t != 0)
_metadata.Add_Space();
- char temp[16];
- ConvertUInt32ToString(Get32(p + t * 4), temp);
- _metadata += temp;
+ _metadata.Add_UInt32(Get32(p + t * 4));
}
#endif
}
@@ -587,9 +609,7 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader)
{
if (t != 0)
_metadata.Add_Space();
- char temp[16];
- ConvertUInt32ToString(Get16(p + t * 2), temp);
- _metadata += temp;
+ _metadata.Add_UInt32(Get16(p + t * 2));
}
}
else if (entry.Type == k_EntryType_BIN)
@@ -607,9 +627,18 @@ HRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader)
{
// p = p;
}
+
_metadata += '\n';
#endif
}
+
+ #ifdef _SHOW_RPM_METADATA
+ CMetaFile meta;
+ meta.Offset = entry.Offset;
+ meta.Tag = entry.Tag;
+ meta.Size = entry.Count;
+ _metaFiles.Add(meta);
+ #endif
}
headerSize += k_HeaderSig_Size;
@@ -715,6 +744,7 @@ STDMETHODIMP CHandler::Close()
#ifdef _SHOW_RPM_METADATA
_metadata.Empty();
+ _metaFiles.Size();
#endif
_stream.Release();
@@ -723,7 +753,12 @@ STDMETHODIMP CHandler::Close()
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
- *numItems = 1;
+ *numItems = 1
+ #ifdef _SHOW_RPM_METADATA
+ + _metaFiles.Size()
+ #endif
+ ;
+
return S_OK;
}
diff --git a/CPP/7zip/Archive/SplitHandler.cpp b/CPP/7zip/Archive/SplitHandler.cpp
index 72b52fe7..f4a10b1d 100644
--- a/CPP/7zip/Archive/SplitHandler.cpp
+++ b/CPP/7zip/Archive/SplitHandler.cpp
@@ -181,7 +181,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
seqName._splitStyle = splitStyle;
if (prefix.Len() < 1)
- _subName.SetFromAscii("file");
+ _subName = "file";
else
_subName.SetFrom(prefix, prefix.Len() - 1);
diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp
index 3bcb2862..29e3bb6c 100644
--- a/CPP/7zip/Archive/SquashfsHandler.cpp
+++ b/CPP/7zip/Archive/SquashfsHandler.cpp
@@ -11,6 +11,7 @@
#include "../../Common/MyLinux.h"
#include "../../Common/IntToString.h"
#include "../../Common/StringConvert.h"
+#include "../../Common/UTFConvert.h"
#include "../../Windows/PropVariantUtils.h"
#include "../../Windows/TimeUtils.h"
@@ -67,7 +68,7 @@ static const UInt32 kSignature32_LZ = 0x71736873;
static const char * const k_Methods[] =
{
- "Unknown"
+ "0"
, "ZLIB"
, "LZMA"
, "LZO"
@@ -109,16 +110,16 @@ enum
kFlag_EXPORT
};
-static const CUInt32PCharPair k_Flags[] =
+static const char * const k_Flags[] =
{
- { kFlag_UNC_INODES, "UNCOMPRESSED_INODES" },
- { kFlag_UNC_DATA, "UNCOMPRESSED_DATA" },
- { kFlag_CHECK, "CHECK" },
- { kFlag_UNC_FRAGS, "UNCOMPRESSED_FRAGMENTS" },
- { kFlag_NO_FRAGS, "NO_FRAGMENTS" },
- { kFlag_ALWAYS_FRAG, "ALWAYS_FRAGMENTS" },
- { kFlag_DUPLICATE, "DUPLICATES_REMOVED" },
- { kFlag_EXPORT, "EXPORTABLE" }
+ "UNCOMPRESSED_INODES"
+ , "UNCOMPRESSED_DATA"
+ , "CHECK"
+ , "UNCOMPRESSED_FRAGMENTS"
+ , "NO_FRAGMENTS"
+ , "ALWAYS_FRAGMENTS"
+ , "DUPLICATES_REMOVED"
+ , "EXPORTABLE"
};
static const UInt32 kNotCompressedBit16 = (1 << 15);
@@ -841,6 +842,8 @@ class CHandler:
CHeader _h;
bool _noPropsLZMA;
bool _needCheckLzma;
+
+ UInt32 _openCodePage;
CMyComPtr<IInStream> _stream;
UInt64 _sizeCalculated;
@@ -944,7 +947,8 @@ static const Byte kArcProps[] =
kpidClusterSize,
kpidBigEndian,
kpidCTime,
- kpidCharacts
+ kpidCharacts,
+ kpidCodePage
// kpidNumBlocks
};
@@ -1333,6 +1337,8 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned
return S_FALSE;
rem = fileSize;
+ AString tempString;
+
CRecordVector<CTempItem> tempItems;
while (rem != 0)
{
@@ -1398,7 +1404,7 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned
}
CItem item;
- item.Ptr = (UInt32)(p - _dirs.Data);
+ item.Ptr = (UInt32)(p - (const Byte *)_dirs.Data);
UInt32 size;
if (_h.IsOldVersion())
@@ -1432,6 +1438,14 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned
size++;
if (rem < size)
return S_FALSE;
+
+ if (_openCodePage == CP_UTF8)
+ {
+ tempString.SetFrom_CalcLen((const char *)p, size);
+ if (!CheckUTF8(tempString))
+ _openCodePage = CP_OEMCP;
+ }
+
p += size;
rem -= size;
item.Parent = parent;
@@ -1706,6 +1720,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
STDMETHODIMP CHandler::Close()
{
+ _openCodePage = CP_UTF8;
_sizeCalculated = 0;
_limitedInStreamSpec->ReleaseStream();
@@ -1829,6 +1844,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
case kpidMethod:
{
+ char sz[16];
const char *s;
if (_noPropsLZMA)
s = "LZMA Spec";
@@ -1836,25 +1852,27 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
s = "LZMA ZLIB";
else
{
- s = k_Methods[0];
+ s = NULL;
if (_h.Method < ARRAY_SIZE(k_Methods))
s = k_Methods[_h.Method];
+ if (!s)
+ {
+ ConvertUInt32ToString(_h.Method, sz);
+ s = sz;
+ }
}
prop = s;
break;
}
case kpidFileSystem:
{
- AString res = "SquashFS";
+ AString res ("SquashFS");
if (_h.SeveralMethods)
res += "-LZMA";
res.Add_Space();
- char s[16];
- ConvertUInt32ToString(_h.Major, s);
- res += s;
+ res.Add_UInt32(_h.Major);
res += '.';
- ConvertUInt32ToString(_h.Minor, s);
- res += s;
+ res.Add_UInt32(_h.Minor);
prop = res;
break;
}
@@ -1875,6 +1893,24 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
if (_sizeCalculated >= _h.InodeTable)
prop = _sizeCalculated - _h.InodeTable;
break;
+
+ case kpidCodePage:
+ {
+ char sz[16];
+ const char *name = NULL;
+ switch (_openCodePage)
+ {
+ case CP_OEMCP: name = "OEM"; break;
+ case CP_UTF8: name = "UTF-8"; break;
+ }
+ if (!name)
+ {
+ ConvertUInt32ToString(_openCodePage, sz);
+ name = sz;
+ }
+ prop = name;
+ break;
+ }
}
prop.Detach(value);
return S_OK;
@@ -1892,7 +1928,17 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
switch (propID)
{
- case kpidPath: prop = MultiByteToUnicodeString(GetPath(index), CP_OEMCP); break;
+ case kpidPath:
+ {
+ AString path (GetPath(index));
+ UString s;
+ if (_openCodePage == CP_UTF8)
+ ConvertUTF8ToUnicode(path, s);
+ else
+ MultiByteToUnicodeString2(s, path, _openCodePage);
+ prop = s;
+ break;
+ }
case kpidIsDir: prop = isDir; break;
// case kpidOffset: if (!node.IsLink()) prop = (UInt64)node.StartBlock; break;
case kpidSize: if (!isDir) prop = node.GetSize(); break;
diff --git a/CPP/7zip/Archive/SwfHandler.cpp b/CPP/7zip/Archive/SwfHandler.cpp
index 06ed2106..16a6e6f9 100644
--- a/CPP/7zip/Archive/SwfHandler.cpp
+++ b/CPP/7zip/Archive/SwfHandler.cpp
@@ -10,6 +10,7 @@
#include "../../Common/MyString.h"
#include "../../Windows/PropVariant.h"
+#include "../../Windows/PropVariantUtils.h"
#include "../Common/InBuffer.h"
#include "../Common/LimitedStreams.h"
@@ -562,14 +563,13 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
{
_lzmaMode = false;
RINOK(_props.SetProperties(names, values, numProps));
- AString m = _props.MethodName;
- m.MakeLower_Ascii();
- if (m.IsEqualTo("lzma"))
+ const AString &m = _props.MethodName;
+ if (m.IsEqualTo_Ascii_NoCase("lzma"))
{
return E_NOTIMPL;
// _lzmaMode = true;
}
- else if (m.IsEqualTo("deflate") || m.IsEmpty())
+ else if (m.IsEqualTo_Ascii_NoCase("Deflate") || m.IsEmpty())
_lzmaMode = false;
else
return E_INVALIDARG;
@@ -762,12 +762,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidPackSize:
prop = (UInt64)tag.Buf.Size(); break;
case kpidComment:
- if (tag.Type < ARRAY_SIZE(g_TagDesc))
- {
- const char *s = g_TagDesc[tag.Type];
- if (s != NULL)
- prop = s;
- }
+ TYPE_TO_PROP(g_TagDesc, tag.Type, prop);
break;
}
prop.Detach(value);
diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp
index baa43c79..72fbf74e 100644
--- a/CPP/7zip/Archive/Tar/TarHandler.cpp
+++ b/CPP/7zip/Archive/Tar/TarHandler.cpp
@@ -81,20 +81,19 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidCodePage:
{
+ char sz[16];
const char *name = NULL;
switch (_openCodePage)
{
case CP_OEMCP: name = "OEM"; break;
- case CP_UTF8: name = "UTF-8"; break;
+ case CP_UTF8: name = "UTF-8"; break;
}
- if (name != NULL)
- prop = name;
- else
+ if (!name)
{
- char sz[16];
ConvertUInt32ToString(_openCodePage, sz);
- prop = sz;
- };
+ name = sz;
+ }
+ prop = name;
break;
}
}
@@ -316,7 +315,7 @@ void CHandler::TarStringToUnicode(const AString &s, NWindows::NCOM::CPropVariant
else
MultiByteToUnicodeString2(dest, s, _curCodePage);
if (toOs)
- NItemName::ConvertToOSName2(dest);
+ NItemName::ReplaceToOsSlashes_Remove_TailSlash(dest);
prop = dest;
}
@@ -353,7 +352,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = ft;
}
break;
- case kpidPosixAttrib: prop = item->Mode; break;
+ case kpidPosixAttrib: prop = item->Get_Combined_Mode(); break;
case kpidUser: TarStringToUnicode(item->User, prop); break;
case kpidGroup: TarStringToUnicode(item->Group, prop); break;
case kpidSymLink: if (item->LinkFlag == NFileHeader::NLinkFlag::kSymLink && !item->LinkName.IsEmpty()) TarStringToUnicode(item->LinkName, prop); break;
diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
index 0b67a285..41934339 100644
--- a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
+++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
@@ -35,7 +35,7 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro
{
UString s = prop.bstrVal;
if (convertSlash)
- s = NItemName::MakeLegalName(s);
+ NItemName::ReplaceSlashes_OsToUnix(s);
if (codePage == CP_UTF8)
{
@@ -123,6 +123,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
return E_INVALIDARG;
else
ui.Mode = prop.ulVal;
+ // FIXME : we can clear high file type bits to be more compatible with tars created by GNU TAR.
+ // ui.Mode &= ~(UInt32)MY_LIN_S_IFMT;
}
{
diff --git a/CPP/7zip/Archive/Tar/TarHeader.cpp b/CPP/7zip/Archive/Tar/TarHeader.cpp
index 70be09f3..a22f36bd 100644
--- a/CPP/7zip/Archive/Tar/TarHeader.cpp
+++ b/CPP/7zip/Archive/Tar/TarHeader.cpp
@@ -8,15 +8,15 @@ namespace NArchive {
namespace NTar {
namespace NFileHeader {
- const char *kLongLink = "././@LongLink";
- const char *kLongLink2 = "@LongLink";
+ const char * const kLongLink = "././@LongLink";
+ const char * const kLongLink2 = "@LongLink";
// The magic field is filled with this if uname and gname are valid.
namespace NMagic
{
- // const char *kUsTar = "ustar"; // 5 chars
- // const char *kGNUTar = "GNUtar "; // 7 chars and a null
- // const char *kEmpty = "\0\0\0\0\0\0\0\0";
+ // const char * const kUsTar = "ustar"; // 5 chars
+ // const char * const kGNUTar = "GNUtar "; // 7 chars and a null
+ // const char * const kEmpty = "\0\0\0\0\0\0\0\0";
const char kUsTar_00[8] = { 'u', 's', 't', 'a', 'r', 0, '0', '0' } ;
}
diff --git a/CPP/7zip/Archive/Tar/TarHeader.h b/CPP/7zip/Archive/Tar/TarHeader.h
index df594d81..47971b58 100644
--- a/CPP/7zip/Archive/Tar/TarHeader.h
+++ b/CPP/7zip/Archive/Tar/TarHeader.h
@@ -67,15 +67,15 @@ namespace NFileHeader
the last file name. */
}
- extern const char *kLongLink; // = "././@LongLink";
- extern const char *kLongLink2; // = "@LongLink";
+ extern const char * const kLongLink; // = "././@LongLink";
+ extern const char * const kLongLink2; // = "@LongLink";
namespace NMagic
{
- // extern const char *kUsTar; // = "ustar"; // 5 chars
- // extern const char *kGNUTar; // = "GNUtar "; // 7 chars and a null
- // extern const char *kEmpty; // = "\0\0\0\0\0\0\0\0"
- extern const char kUsTar_00[];
+ // extern const char * const kUsTar; // = "ustar"; // 5 chars
+ // extern const char * const kGNUTar; // = "GNUtar "; // 7 chars and a null
+ // extern const char * const kEmpty; // = "\0\0\0\0\0\0\0\0"
+ extern const char kUsTar_00[8];
}
}
diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp
index 57e18ac0..64807bfc 100644
--- a/CPP/7zip/Archive/Tar/TarIn.cpp
+++ b/CPP/7zip/Archive/Tar/TarIn.cpp
@@ -91,6 +91,16 @@ static bool ParseInt64(const char *p, Int64 &val)
return res;
}
+static bool ParseInt64_MTime(const char *p, Int64 &val)
+{
+ // rare case tar contains spaces instead of MTime
+ for (unsigned i = 0; i < 12; i++)
+ if (p[i] != ' ')
+ return ParseInt64(p, val);
+ val = 0;
+ return true;
+}
+
static bool ParseSize(const char *p, UInt64 &val)
{
if (GetBe32(p) == (UInt32)1 << 31)
@@ -124,7 +134,7 @@ API_FUNC_IsArc IsArc_Tar(const Byte *p2, size_t size)
Int64 time;
UInt32 checkSum;
CHECK(ParseSize(p, packSize)); p += 12;
- CHECK(ParseInt64(p, time)); p += 12;
+ CHECK(ParseInt64_MTime(p, time)); p += 12;
CHECK(OctalToNumber32(p, 8, checkSum));
return k_IsArc_Res_YES;
}
@@ -192,7 +202,7 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
RIF(ParseSize(p, item.PackSize));
item.Size = item.PackSize;
p += 12;
- RIF(ParseInt64(p, item.MTime)); p += 12;
+ RIF(ParseInt64_MTime(p, item.MTime)); p += 12;
UInt32 checkSum;
RIF(OctalToNumber32(p, 8, checkSum));
diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h
index 5245aaa4..bc3b4084 100644
--- a/CPP/7zip/Archive/Tar/TarItem.h
+++ b/CPP/7zip/Archive/Tar/TarItem.h
@@ -3,6 +3,8 @@
#ifndef __ARCHIVE_TAR_ITEM_H
#define __ARCHIVE_TAR_ITEM_H
+#include "../../../Common/MyLinux.h"
+
#include "../Common/ItemNameUtils.h"
#include "TarHeader.h"
@@ -56,6 +58,32 @@ struct CItem
return false;
}
+ UInt32 Get_Combined_Mode() const
+ {
+ return (Mode & ~(UInt32)MY_LIN_S_IFMT) | Get_FileTypeMode_from_LinkFlag();
+ }
+
+ UInt32 Get_FileTypeMode_from_LinkFlag() const
+ {
+ switch (LinkFlag)
+ {
+ /*
+ case NFileHeader::NLinkFlag::kDirectory:
+ case NFileHeader::NLinkFlag::kDumpDir:
+ return MY_LIN_S_IFDIR;
+ */
+ case NFileHeader::NLinkFlag::kSymLink: return MY_LIN_S_IFLNK;
+ case NFileHeader::NLinkFlag::kBlock: return MY_LIN_S_IFBLK;
+ case NFileHeader::NLinkFlag::kCharacter: return MY_LIN_S_IFCHR;
+ case NFileHeader::NLinkFlag::kFIFO: return MY_LIN_S_IFIFO;
+ // case return MY_LIN_S_IFSOCK;
+ }
+
+ if (IsDir())
+ return MY_LIN_S_IFDIR;
+ return MY_LIN_S_IFREG;
+ }
+
bool IsDir() const
{
switch (LinkFlag)
diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp
index d52db9f4..cfe6c5ad 100644
--- a/CPP/7zip/Archive/Udf/UdfIn.cpp
+++ b/CPP/7zip/Archive/Udf/UdfIn.cpp
@@ -51,13 +51,13 @@ void MY_FAST_CALL Crc16GenerateTable(void)
for (i = 0; i < 256; i++)
{
UInt32 r = (i << 8);
- for (int j = 8; j > 0; j--)
- r = ((r & 0x8000) ? ((r << 1) ^ kCrc16Poly) : (r << 1)) & 0xFFFF;
+ for (unsigned j = 0; j < 8; j++)
+ r = ((r << 1) ^ (kCrc16Poly & ((UInt32)0 - (r >> 15)))) & 0xFFFF;
g_Crc16Table[i] = (UInt16)r;
}
}
-UInt16 MY_FAST_CALL Crc16_Update(UInt16 v, const void *data, size_t size)
+UInt32 MY_FAST_CALL Crc16_Update(UInt32 v, const void *data, size_t size)
{
const Byte *p = (const Byte *)data;
for (; size > 0 ; size--, p++)
@@ -65,12 +65,12 @@ UInt16 MY_FAST_CALL Crc16_Update(UInt16 v, const void *data, size_t size)
return v;
}
-UInt16 MY_FAST_CALL Crc16Calc(const void *data, size_t size)
+UInt32 MY_FAST_CALL Crc16Calc(const void *data, size_t size)
{
return Crc16_Update(CRC16_INIT_VAL, data, size);
}
-struct CCrc16TableInit { CCrc16TableInit() { Crc16GenerateTable(); } } g_Crc16TableInit;
+static struct CCrc16TableInit { CCrc16TableInit() { Crc16GenerateTable(); } } g_Crc16TableInit;
@@ -109,7 +109,7 @@ static UString ParseDString(const Byte *data, unsigned size)
}
}
else
- return L"[unknow]";
+ return UString("[unknow]");
*p = 0;
res.ReleaseBuf_SetLen((unsigned)(p - (const wchar_t *)res));
}
@@ -179,12 +179,12 @@ HRESULT CTag::Parse(const Byte *buf, size_t size)
Id = Get16(buf);
Version = Get16(buf + 2);
// SerialNumber = Get16(buf + 6);
- UInt16 crc = Get16(buf + 8);
- UInt16 crcLen = Get16(buf + 10);
+ UInt32 crc = Get16(buf + 8);
+ UInt32 crcLen = Get16(buf + 10);
// TagLocation = Get32(buf + 12);
- if (size >= 16 + (size_t)crcLen)
- if (crc == Crc16Calc(buf + 16, crcLen))
+ if (size >= 16 + crcLen)
+ if (crc == Crc16Calc(buf + 16, (size_t)crcLen))
return S_OK;
return S_FALSE;
}
@@ -1077,14 +1077,7 @@ static UString GetSpecName(const UString &name)
UString name2 = name;
name2.Trim();
if (name2.IsEmpty())
- {
- /*
- wchar_t s[32];
- ConvertUInt64ToString(id, s);
- return L"[" + (UString)s + L"]";
- */
- return L"[]";
- }
+ return UString("[]");
return name;
}
@@ -1116,22 +1109,19 @@ UString CInArchive::GetItemPath(int volIndex, int fsIndex, int refIndex,
if (showFsName)
{
- wchar_t s[32];
- ConvertUInt32ToString(fsIndex, s);
- UString newName = L"File Set ";
- newName += s;
+ UString newName ("File Set ");
+ newName.Add_UInt32(fsIndex);
UpdateWithName(name, newName);
}
if (showVolName)
{
- wchar_t s[32];
- ConvertUInt32ToString(volIndex, s);
- UString newName = s;
+ UString newName;
+ newName.Add_UInt32(volIndex);
UString newName2 = vol.GetName();
if (newName2.IsEmpty())
- newName2 = L"Volume";
- newName += L'-';
+ newName2 = "Volume";
+ newName += '-';
newName += newName2;
UpdateWithName(name, newName);
}
diff --git a/CPP/7zip/Archive/UefiHandler.cpp b/CPP/7zip/Archive/UefiHandler.cpp
index ff0737a0..f49b62c8 100644
--- a/CPP/7zip/Archive/UefiHandler.cpp
+++ b/CPP/7zip/Archive/UefiHandler.cpp
@@ -46,20 +46,58 @@ static const size_t kBufTotalSizeMax = (1 << 29);
static const unsigned kNumFilesMax = (1 << 18);
static const unsigned kLevelMax = 64;
+static const Byte k_IntelMeSignature[] =
+{
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0x5A, 0xA5, 0xF0, 0x0F
+};
+
+bool IsIntelMe(const Byte *p)
+{
+ return memcmp(p, k_IntelMeSignature, sizeof(k_IntelMeSignature)) == 0;
+}
+
static const unsigned kFvHeaderSize = 0x38;
static const unsigned kGuidSize = 16;
-#define CAPSULE_SIGNATURE \
- { 0xBD,0x86,0x66,0x3B,0x76,0x0D,0x30,0x40,0xB7,0x0E,0xB5,0x51,0x9E,0x2F,0xC5,0xA0 }
-static const Byte kCapsuleSig[kGuidSize] = CAPSULE_SIGNATURE;
+
+#define CAPSULE_SIGNATURE 0xBD,0x86,0x66,0x3B,0x76,0x0D,0x30,0x40,0xB7,0x0E,0xB5,0x51,0x9E,0x2F,0xC5,0xA0
+#define CAPSULE2_SIGNATURE 0x8B,0xA6,0x3C,0x4A,0x23,0x77,0xFB,0x48,0x80,0x3D,0x57,0x8C,0xC1,0xFE,0xC4,0x4D
+#define CAPSULE_UEFI_SIGNATURE 0xB9,0x82,0x91,0x53,0xB5,0xAB,0x91,0x43,0xB6,0x9A,0xE3,0xA9,0x43,0xF7,0x2F,0xCC
+/*
+ 6dcbd5ed-e82d-4c44-bda1-7194199ad92a : Firmware Management `
+*/
+
+static const Byte k_Guids_Capsules[][kGuidSize] =
+{
+ { CAPSULE_SIGNATURE },
+ { CAPSULE2_SIGNATURE },
+ { CAPSULE_UEFI_SIGNATURE }
+};
+
static const unsigned kFfsGuidOffset = 16;
-#define FFS_SIGNATURE \
- { 0xD9,0x54,0x93,0x7A,0x68,0x04,0x4A,0x44,0x81,0xCE,0x0B,0xF6,0x17,0xD8,0x90,0xDF }
-static const Byte k_FFS_Guid[kGuidSize] = FFS_SIGNATURE;
-static const Byte k_MacFS_Guid[kGuidSize] =
- { 0xAD,0xEE,0xAD,0x04,0xFF,0x61,0x31,0x4D,0xB6,0xBA,0x64,0xF8,0xBF,0x90,0x1F,0x5A };
+#define FFS1_SIGNATURE 0xD9,0x54,0x93,0x7A,0x68,0x04,0x4A,0x44,0x81,0xCE,0x0B,0xF6,0x17,0xD8,0x90,0xDF
+#define FFS2_SIGNATURE 0x78,0xE5,0x8C,0x8C,0x3D,0x8A,0x1C,0x4F,0x99,0x35,0x89,0x61,0x85,0xC3,0x2D,0xD3
+#define MACFS_SIGNATURE 0xAD,0xEE,0xAD,0x04,0xFF,0x61,0x31,0x4D,0xB6,0xBA,0x64,0xF8,0xBF,0x90,0x1F,0x5A
+// APPLE_BOOT
+/*
+ "FFS3": "5473c07a-3dcb-4dca-bd6f-1e9689e7349a",
+ "NVRAM_EVSA": "fff12b8d-7696-4c8b-a985-2747075b4f50",
+ "NVRAM_NVAR": "cef5b9a3-476d-497f-9fdc-e98143e0422c",
+ "NVRAM_EVSA2": "00504624-8a59-4eeb-bd0f-6b36e96128e0",
+static const Byte k_NVRAM_NVAR_Guid[kGuidSize] =
+ { 0xA3,0xB9,0xF5,0xCE,0x6D,0x47,0x7F,0x49,0x9F,0xDC,0xE9,0x81,0x43,0xE0,0x42,0x2C };
+*/
+
+static const Byte k_Guids_FS[][kGuidSize] =
+{
+ { FFS1_SIGNATURE },
+ { FFS2_SIGNATURE },
+ { MACFS_SIGNATURE }
+};
+
static const UInt32 kFvSignature = 0x4856465F; // "_FVH"
@@ -80,6 +118,8 @@ static const Byte kGuids[][kGuidSize] =
{ 0x18,0x88,0x53,0x4A,0xE0,0x5A,0xB2,0x4E,0xB2,0xEB,0x48,0x8B,0x23,0x65,0x70,0x22 }
};
+static const Byte k_Guid_LZMA_COMPRESSED[kGuidSize] =
+ { 0x98,0x58,0x4E,0xEE,0x14,0x39,0x59,0x42,0x9D,0x6E,0xDC,0x7B,0xD7,0x94,0x03,0xCF };
static const char * const kGuidNames[] =
{
@@ -180,7 +220,12 @@ static int FindGuid(const Byte *p)
static bool IsFfs(const Byte *p)
{
- return (Get32(p + 0x28) == kFvSignature && AreGuidsEq(p + kFfsGuidOffset, k_FFS_Guid));
+ if (Get32(p + 0x28) != kFvSignature)
+ return false;
+ for (unsigned i = 0; i < ARRAY_SIZE(k_Guids_FS); i++)
+ if (AreGuidsEq(p + kFfsGuidOffset, k_Guids_FS[i]))
+ return true;
+ return false;
}
#define FVB_ERASE_POLARITY (1 << 11)
@@ -329,39 +374,15 @@ static const char * const g_Methods[] =
, "LZMA"
};
-static AString UInt32ToString(UInt32 val)
-{
- char sz[16];
- ConvertUInt32ToString(val, sz);
- return sz;
-}
-static void ConvertByteToHex(unsigned value, char *s)
+static void AddGuid(AString &dest, const Byte *p, bool full)
{
- for (int i = 0; i < 2; i++)
- {
- unsigned t = value & 0xF;
- value >>= 4;
- s[1 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
- }
-}
-
-static AString GuidToString(const Byte *p, bool full)
-{
- char s[16 * 2 + 8];
- int i;
- for (i = 0; i < 4; i++)
- ConvertByteToHex(p[3 - i], s + i * 2);
- s[8] = 0;
-
- if (full)
- {
- s[8] = '-';
- for (i = 4; i < kGuidSize; i++)
- ConvertByteToHex(p[i], s + 1 + i * 2);
- s[32 + 1] = 0;
- }
- return s;
+ char s[64];
+ ::RawLeGuidToString(p, s);
+ // MyStringUpper_Ascii(s);
+ if (!full)
+ s[8] = 0;
+ dest += s;
}
static const char * const kExpressionCommands[] =
@@ -383,7 +404,7 @@ static bool ParseDepedencyExpression(const Byte *p, UInt32 size, AString &res)
if (i + kGuidSize > size)
return false;
res.Add_Space();
- res += GuidToString(p + i, false);
+ AddGuid(res, p + i, false);
i += kGuidSize;
}
res += "; ";
@@ -433,6 +454,7 @@ static void AddSpaceAndString(AString &res, const AString &newString)
class CFfsFileHeader
{
+PRF(public:)
Byte CheckHeader;
Byte CheckFile;
Byte Attrib;
@@ -530,7 +552,7 @@ public:
if (align != 0)
{
s += " Align:";
- s += UInt32ToString((UInt32)1 << g_Allignment[align]);
+ s.Add_UInt32((UInt32)1 << g_Allignment[align]);
}
*/
return s;
@@ -538,6 +560,7 @@ public:
};
#define G32(_offs_, dest) dest = Get32(p + (_offs_));
+#define G16(_offs_, dest) dest = Get16(p + (_offs_));
struct CCapsuleHeader
{
@@ -557,23 +580,51 @@ struct CCapsuleHeader
void Clear() { memset(this, 0, sizeof(*this)); }
- void Parse(const Byte *p)
+ bool Parse(const Byte *p)
{
+ Clear();
G32(0x10, HeaderSize);
G32(0x14, Flags);
G32(0x18, CapsuleImageSize);
- G32(0x1C, SequenceNumber);
- G32(0x30, OffsetToSplitInformation);
- G32(0x34, OffsetToCapsuleBody);
- G32(0x38, OffsetToOemDefinedHeader);
- G32(0x3C, OffsetToAuthorInformation);
- G32(0x40, OffsetToRevisionInformation);
- G32(0x44, OffsetToShortDescription);
- G32(0x48, OffsetToLongDescription);
- G32(0x4C, OffsetToApplicableDevices);
+ if (HeaderSize < 0x1C)
+ return false;
+ if (AreGuidsEq(p, k_Guids_Capsules[0]))
+ {
+ const unsigned kHeaderSize = 80;
+ if (HeaderSize != kHeaderSize)
+ return false;
+ G32(0x1C, SequenceNumber);
+ G32(0x30, OffsetToSplitInformation);
+ G32(0x34, OffsetToCapsuleBody);
+ G32(0x38, OffsetToOemDefinedHeader);
+ G32(0x3C, OffsetToAuthorInformation);
+ G32(0x40, OffsetToRevisionInformation);
+ G32(0x44, OffsetToShortDescription);
+ G32(0x48, OffsetToLongDescription);
+ G32(0x4C, OffsetToApplicableDevices);
+ return true;
+ }
+ else if (AreGuidsEq(p, k_Guids_Capsules[1]))
+ {
+ // capsule v2
+ G16(0x1C, OffsetToCapsuleBody);
+ G16(0x1E, OffsetToOemDefinedHeader);
+ return true;
+ }
+ else if (AreGuidsEq(p, k_Guids_Capsules[2]))
+ {
+ OffsetToCapsuleBody = HeaderSize;
+ return true;
+ }
+ else
+ {
+ // here we must check for another capsule types
+ return false;
+ }
}
};
+
struct CItem
{
AString Name;
@@ -605,7 +656,10 @@ void CItem::SetGuid(const Byte *guidName, bool full)
if (index >= 0)
Name = kGuidNames[(unsigned)index];
else
- Name = GuidToString(guidName, full);
+ {
+ Name.Empty();
+ AddGuid(Name, guidName, full);
+ }
}
AString CItem::GetName(int numChildsInParent) const
@@ -616,11 +670,14 @@ AString CItem::GetName(int numChildsInParent) const
char sz2[32];
ConvertUInt32ToString(NameIndex, sz);
ConvertUInt32ToString(numChildsInParent - 1, sz2);
- unsigned numZeros = (unsigned)strlen(sz2) - (unsigned)strlen(sz);
+ int numZeros = (int)strlen(sz2) - (int)strlen(sz);
AString res;
- for (unsigned i = 0; i < numZeros; i++)
+ for (int i = 0; i < numZeros; i++)
res += '0';
- return res + (AString)sz + '.' + Name;
+ res += sz;
+ res += '.';
+ res += Name;
+ return res;
}
struct CItem2
@@ -644,21 +701,30 @@ class CHandler:
UString _comment;
UInt32 _methodsMask;
bool _capsuleMode;
+ bool _headersError;
size_t _totalBufsSize;
CCapsuleHeader _h;
UInt64 _phySize;
- void AddCommentString(const wchar_t *name, UInt32 pos);
+ void AddCommentString(const char *name, UInt32 pos);
int AddItem(const CItem &item);
int AddFileItemWithIndex(CItem &item);
int AddDirItem(CItem &item);
unsigned AddBuf(size_t size);
- HRESULT ParseSections(int bufIndex, UInt32 pos, UInt32 size, int parent, int method, unsigned level);
+ HRESULT DecodeLzma(const Byte *data, size_t inputSize);
+
+ HRESULT ParseSections(int bufIndex, UInt32 pos, UInt32 size, int parent, int method, unsigned level, bool &error);
+
+ HRESULT ParseIntelMe(int bufIndex, UInt32 posBase,
+ UInt32 exactSize, UInt32 limitSize,
+ int parent, int method, int level);
+
HRESULT ParseVolume(int bufIndex, UInt32 posBase,
UInt32 exactSize, UInt32 limitSize,
int parent, int method, int level);
+
HRESULT OpenCapsule(IInStream *stream);
HRESULT OpenFv(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback);
HRESULT Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback);
@@ -674,6 +740,7 @@ static const Byte kProps[] =
kpidPath,
kpidIsDir,
kpidSize,
+ // kpidOffset,
kpidMethod,
kpidCharacts
};
@@ -698,7 +765,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
case kpidPath:
{
- AString path = item2.Name;
+ AString path (item2.Name);
int cur = item2.Parent;
while (cur >= 0)
{
@@ -714,13 +781,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidMethod: if (item.Method >= 0) prop = g_Methods[(unsigned)item.Method]; break;
case kpidCharacts: if (!item2.Characts.IsEmpty()) prop = item2.Characts; break;
case kpidSize: if (!item.IsDir) prop = (UInt64)item.Size; break;
+ // case kpidOffset: if (!item.IsDir) prop = item.Offset; break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
-void CHandler::AddCommentString(const wchar_t *name, UInt32 pos)
+void CHandler::AddCommentString(const char *name, UInt32 pos)
{
UString s;
const Byte *buf = _bufs[0];
@@ -747,7 +815,7 @@ void CHandler::AddCommentString(const wchar_t *name, UInt32 pos)
return;
_comment.Add_LF();
_comment += name;
- _comment.AddAscii(": ");
+ _comment += ": ";
_comment += s;
}
@@ -762,13 +830,22 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
AString s;
for (unsigned i = 0; i < 32; i++)
if ((_methodsMask & ((UInt32)1 << i)) != 0)
- AddSpaceAndString(s, g_Methods[i]);
+ AddSpaceAndString(s, (AString)g_Methods[i]);
if (!s.IsEmpty())
prop = s;
break;
}
case kpidComment: if (!_comment.IsEmpty()) prop = _comment; break;
case kpidPhySize: prop = (UInt64)_phySize; break;
+
+ case kpidErrorFlags:
+ {
+ UInt32 v = 0;
+ if (!_headersError) v |= kpv_ErrorFlags_HeadersError;
+ if (v != 0)
+ prop = v;
+ break;
+ }
}
prop.Detach(value);
return S_OK;
@@ -785,7 +862,7 @@ static void PrintLevel(int level)
static void MyPrint(UInt32 posBase, UInt32 size, int level, const char *name)
{
PrintLevel(level);
- PRF(printf("%s, pos = %6x, size = %6d", name, posBase, size));
+ PRF(printf("%s, pos = %6x, size = %6x", name, posBase, size));
}
#else
#define PrintLevel(level)
@@ -829,8 +906,36 @@ unsigned CHandler::AddBuf(size_t size)
return index;
}
-HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, unsigned level)
+
+HRESULT CHandler::DecodeLzma(const Byte *data, size_t inputSize)
+{
+ if (inputSize < 5 + 8)
+ return S_FALSE;
+ const UInt64 unpackSize = Get64(data + 5);
+ if (unpackSize > ((UInt32)1 << 30))
+ return S_FALSE;
+ SizeT destLen = (SizeT)unpackSize;
+ const unsigned newBufIndex = AddBuf((size_t)unpackSize);
+ CByteBuffer &buf = _bufs[newBufIndex];
+ ELzmaStatus status;
+ SizeT srcLen = inputSize - (5 + 8);
+ const SizeT srcLen2 = srcLen;
+ SRes res = LzmaDecode(buf, &destLen, data + 13, &srcLen,
+ data, 5, LZMA_FINISH_END, &status, &g_Alloc);
+ if (res != 0)
+ return S_FALSE;
+ if (srcLen != srcLen2 || destLen != unpackSize || (
+ status != LZMA_STATUS_FINISHED_WITH_MARK &&
+ status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
+ return S_FALSE;
+ return S_OK;
+}
+
+
+HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int parent, int method, unsigned level, bool &error)
{
+ error = false;
+
if (level > kLevelMax)
return S_FALSE;
MyPrint(posBase, size, level, "Sections");
@@ -842,7 +947,7 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
if (size == pos)
return S_OK;
PrintLevel(level);
- PRF(printf("%s, pos = %6x", "Sect", pos));
+ PRF(printf("%s, abs = %6x, relat = %6x", "Sect", posBase + pos, pos));
pos = (pos + 3) & ~(UInt32)3;
if (pos > size)
return S_FALSE;
@@ -851,14 +956,23 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
return S_OK;
if (rem < 4)
return S_FALSE;
+
const Byte *p = bufData + posBase + pos;
- UInt32 sectSize = Get24(p);
- if (sectSize > rem || sectSize < 4)
- return S_FALSE;
- Byte type = p[3];
- PrintLevel(level);
- PRF(printf("%s, type = %2x, pos = %6x, size = %6d", "Sect", type, pos, sectSize));
+ const UInt32 sectSize = Get24(p);
+ const Byte type = p[3];
+
+ // PrintLevel(level);
+ PRF(printf(" type = %2x, sectSize = %6x", type, sectSize));
+
+ if (sectSize > rem || sectSize < 4)
+ {
+ _headersError = true;
+ error = true;
+ return S_OK;
+ // return S_FALSE;
+ }
+
CItem item;
item.Method = method;
item.BufIndex = bufIndex;
@@ -891,7 +1005,8 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
// int parent = AddDirItem(item);
if (compressionType == COMPRESSION_TYPE_NONE)
{
- RINOK(ParseSections(bufIndex, newOffset, newSectSize, parent, method, level));
+ bool error2;
+ RINOK(ParseSections(bufIndex, newOffset, newSectSize, parent, method, level, error2));
}
else if (compressionType == COMPRESSION_TYPE_LZH)
{
@@ -910,6 +1025,9 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
return S_FALSE;
UInt32 packSize = Get32(src);
UInt32 unpackSize = Get32(src + 4);
+
+ PRF(printf(" LZH packSize = %6x, unpackSize = %6x", packSize, unpackSize));
+
if (uncompressedSize != unpackSize || newSectSize - 8 != packSize)
return S_FALSE;
if (packSize < 1)
@@ -921,30 +1039,34 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
CBufInStream *inStreamSpec = new CBufInStream;
CMyComPtr<IInStream> inStream = inStreamSpec;
- inStreamSpec->Init(src, packSize);
CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;
CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
- outStreamSpec->Init(buf, uncompressedSize);
UInt64 uncompressedSize64 = uncompressedSize;
lzhDecoderSpec->FinishMode = true;
/*
- EFI 1.1 probably used small dictionary and (pbit = 4) in LZH. We don't support such archives.
+ EFI 1.1 probably used LZH with small dictionary and (pbit = 4). It was named "Efi compression".
New version of compression code (named Tiano) uses LZH with (1 << 19) dictionary.
But maybe LZH decoder in UEFI decoder supports larger than (1 << 19) dictionary.
+ We check both LZH versions: Tiano and then Efi.
*/
- lzhDecoderSpec->SetDictSize(1 << 19);
-
- HRESULT res = lzhDecoder->Code(inStream, outStream, NULL, &uncompressedSize64, NULL);
- if (res != S_OK)
- return res;
-
- if (lzhDecoderSpec->GetInputProcessedSize() != packSize)
- return S_FALSE;
+ HRESULT res = S_FALSE;
+
+ for (unsigned m = 0 ; m < 2; m++)
+ {
+ inStreamSpec->Init(src, packSize);
+ outStreamSpec->Init(buf, uncompressedSize);
+ lzhDecoderSpec->SetDictSize((m == 0) ? ((UInt32)1 << 19) : ((UInt32)1 << 14));
+ res = lzhDecoder->Code(inStream, outStream, NULL, &uncompressedSize64, NULL);
+ if (res == S_OK)
+ break;
+ }
+ RINOK(res);
}
- RINOK(ParseSections(newBufIndex, 0, uncompressedSize, parent, compressionType, level));
+ bool error2;
+ RINOK(ParseSections(newBufIndex, 0, uncompressedSize, parent, compressionType, level, error2));
}
else
{
@@ -964,26 +1086,14 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
// firstSectType can be 0 in some archives
}
pStart += addSize;
- UInt64 lzmaUncompressedSize = Get64(pStart + 5);
- if (lzmaUncompressedSize > (1 << 30))
- return S_FALSE;
+
+ RINOK(DecodeLzma(pStart, newSectSize - addSize));
+ const size_t lzmaUncompressedSize = _bufs.Back().Size();
+ // if (lzmaUncompressedSize != uncompressedSize)
if (lzmaUncompressedSize < uncompressedSize)
return S_FALSE;
- SizeT destLen = (SizeT)lzmaUncompressedSize;
- unsigned newBufIndex = AddBuf((size_t)lzmaUncompressedSize);
- CByteBuffer &buf = _bufs[newBufIndex];
- ELzmaStatus status;
- SizeT srcLen = newSectSize - (addSize + 5 + 8);
- SizeT srcLen2 = srcLen;
- SRes res = LzmaDecode(buf, &destLen, pStart + 13, &srcLen,
- pStart, 5, LZMA_FINISH_END, &status, &g_Alloc);
- if (res != 0)
- return S_FALSE;
- if (srcLen != srcLen2 || destLen != lzmaUncompressedSize || (
- status != LZMA_STATUS_FINISHED_WITH_MARK &&
- status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
- return S_FALSE;
- RINOK(ParseSections(newBufIndex, 0, (UInt32)lzmaUncompressedSize, parent, compressionType, level));
+ bool error2;
+ RINOK(ParseSections(_bufs.Size() - 1, 0, (UInt32)lzmaUncompressedSize, parent, compressionType, level, error2));
}
_methodsMask |= (1 << compressionType);
}
@@ -1003,9 +1113,26 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
UInt32 newOffset = posBase + pos + dataOffset;
item.Offset = newOffset;
UInt32 propsSize = dataOffset - kHeaderSize;
- bool needDir = true;
AddSpaceAndString(item.Characts, FLAGS_TO_STRING(g_GUIDED_SECTION_ATTRIBUTES, attrib));
- if (AreGuidsEq(p + 0x4, kGuids[kGuidIndex_CRC]) && propsSize == 4)
+
+ bool needDir = true;
+ unsigned newBufIndex = bufIndex;
+ int newMethod = method;
+
+ if (AreGuidsEq(p + 0x4, k_Guid_LZMA_COMPRESSED))
+ {
+ // item.Name = "guid.lzma";
+ // AddItem(item);
+ const Byte *pStart = bufData + newOffset;
+ // do we need correct pStart here for lzma steram offset?
+ RINOK(DecodeLzma(pStart, newSectSize));
+ _methodsMask |= (1 << COMPRESSION_TYPE_LZMA);
+ newBufIndex = _bufs.Size() - 1;
+ newOffset = 0;
+ newSectSize = (UInt32)_bufs.Back().Size();
+ newMethod = COMPRESSION_TYPE_LZMA;
+ }
+ else if (AreGuidsEq(p + 0x4, kGuids[kGuidIndex_CRC]) && propsSize == 4)
{
needDir = false;
item.KeepName = false;
@@ -1023,10 +1150,12 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
AddItem(item2);
}
}
+
int newParent = parent;
if (needDir)
newParent = AddDirItem(item);
- RINOK(ParseSections(bufIndex, newOffset, newSectSize, newParent, method, level));
+ bool error2;
+ RINOK(ParseSections(newBufIndex, newOffset, newSectSize, newParent, newMethod, level, error2));
}
else if (type == SECTION_FIRMWARE_VOLUME_IMAGE)
{
@@ -1100,8 +1229,8 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
AString s;
if (ParseUtf16zString2(p + 6, sectDataSize - 2, s))
{
- AString s2 = "ver:";
- s2 += UInt32ToString(Get16(p + 4));
+ AString s2 ("ver:");
+ s2.Add_UInt32(Get16(p + 4));
s2.Add_Space();
s2 += s;
AddSpaceAndString(_items[item.Parent].Characts, s2);
@@ -1135,6 +1264,7 @@ HRESULT CHandler::ParseSections(int bufIndex, UInt32 posBase, UInt32 size, int p
if (needAdd)
AddFileItemWithIndex(item);
}
+
pos += sectSize;
}
}
@@ -1174,6 +1304,7 @@ bool CVolFfsHeader::Parse(const Byte *p)
return true;
};
+
HRESULT CHandler::ParseVolume(
int bufIndex, UInt32 posBase,
UInt32 exactSize, UInt32 limitSize,
@@ -1181,14 +1312,13 @@ HRESULT CHandler::ParseVolume(
{
if (level > kLevelMax)
return S_FALSE;
- MyPrint(posBase, size, level, "Volume");
+ MyPrint(posBase, exactSize, level, "Volume");
level++;
if (exactSize < kFvHeaderSize)
return S_FALSE;
const Byte *p = _bufs[bufIndex] + posBase;
// first 16 bytes must be zeros, but they are not zeros sometimes.
- if (!AreGuidsEq(p + kFfsGuidOffset, k_FFS_Guid) &&
- !AreGuidsEq(p + kFfsGuidOffset, k_MacFS_Guid))
+ if (!IsFfs(p))
{
CItem item;
item.Method = method;
@@ -1196,8 +1326,10 @@ HRESULT CHandler::ParseVolume(
item.Parent = parent;
item.Offset = posBase;
item.Size = exactSize;
- item.SetGuid(p + kFfsGuidOffset);
- item.Name += " [VOLUME]";
+ if (!Is_FF_Stream(p + kFfsGuidOffset, 16))
+ item.SetGuid(p + kFfsGuidOffset);
+ // if (item.Name.IsEmpty())
+ item.Name += "[VOL]";
AddItem(item);
return S_OK;
}
@@ -1268,9 +1400,13 @@ HRESULT CHandler::ParseVolume(
item.Size = rem - num_FF_bytes;
AddItem(item);
}
+ PrintLevel(level); PRF(printf("== FF FF reminder"));
+
break;
}
- PrintLevel(level); PRF(printf("%s, pos = %6x, size = %6d", "FILE", posBase + pos, fh.Size));
+
+ PrintLevel(level); PRF(printf("%s, type = %3d, pos = %7x, size = %7x", "FILE", fh.Type, posBase + pos, fh.Size));
+
if (!fh.Check(pFile, rem))
return S_FALSE;
@@ -1295,9 +1431,16 @@ HRESULT CHandler::ParseVolume(
item.SetGuid(fh.GuidName, full);
item.Characts = fh.GetCharacts();
- PrintLevel(level);
- PRF(printf("%s", item.Characts));
-
+ // PrintLevel(level);
+ PRF(printf(" : %s", item.Characts));
+
+ {
+ PRF(printf(" attrib = %2d State = %3d ", (unsigned)fh.Attrib, (unsigned)fh.State));
+ PRF(char s[64]);
+ PRF(RawLeGuidToString(fh.GuidName, s));
+ PRF(printf(" : %s ", s));
+ }
+
if (fh.Type == FV_FILETYPE_FFS_PAD ||
fh.Type == FV_FILETYPE_RAW)
{
@@ -1321,23 +1464,127 @@ HRESULT CHandler::ParseVolume(
}
else
{
- int newParent = AddDirItem(item);
- RINOK(ParseSections(bufIndex, offset, sectSize, newParent, method, level));
+ /*
+ if (fh.Type == FV_FILETYPE_FREEFORM)
+ {
+ // in intel bio example: one FV_FILETYPE_FREEFORM file is wav file (not sections)
+ // AddItem(item);
+ }
+ else
+ */
+ {
+ int newParent = AddDirItem(item);
+ bool error2;
+ RINOK(ParseSections(bufIndex, offset, sectSize, newParent, method, level + 1, error2));
+ if (error2)
+ {
+ // in intel bio example: one FV_FILETYPE_FREEFORM file is wav file (not sections)
+ item.IsDir = false;
+ item.Size = sectSize;
+ item.Name.Insert(0, "[ERROR]");
+ AddItem(item);
+ }
+ }
}
}
+
+ return S_OK;
+}
+
+
+static const char * const kRegionName[] =
+{
+ "Descriptor"
+ , "BIOS"
+ , "ME"
+ , "GbE"
+ , "PDR"
+ , "Region5"
+ , "Region6"
+ , "Region7"
+};
+
+
+HRESULT CHandler::ParseIntelMe(
+ int bufIndex, UInt32 posBase,
+ UInt32 exactSize, UInt32 limitSize,
+ int parent, int method, int level)
+{
+ UNUSED_VAR(limitSize)
+ level++;
+ const Byte *p = _bufs[bufIndex] + posBase;
+ if (exactSize < 16 + 16)
+ return S_FALSE;
+ if (!IsIntelMe(p))
+ return S_FALSE;
+
+ UInt32 v0 = GetUi32(p + 20);
+ // UInt32 numRegions = (v0 >> 24) & 0x7;
+ UInt32 regAddr = (v0 >> 12) & 0xFF0;
+ // UInt32 numComps = (v0 >> 8) & 0x3;
+ // UInt32 fcba = (v0 << 4) & 0xFF0;
+
+ // (numRegions == 0) in header in some new images.
+ // So we don't use the value from header
+ UInt32 numRegions = 7;
+
+ for (unsigned i = 0; i <= numRegions; i++)
+ {
+ UInt32 offset = regAddr + i * 4;
+ if (offset + 4 > exactSize)
+ break;
+ UInt32 val = GetUi32(p + offset);
+
+ // only 12 bits probably are OK.
+ // How does it work for files larger than 16 MB?
+ const UInt32 kMask = 0xFFF;
+ // const UInt32 kMask = 0xFFFF; // 16-bit is more logical
+ const UInt32 lim = (val >> 16) & kMask;
+ const UInt32 base = (val & kMask);
+
+ /*
+ strange combinations:
+ PDR: base = 0x1FFF lim = 0;
+ empty: base = 0xFFFF lim = 0xFFFF;
+
+ PDR: base = 0x7FFF lim = 0;
+ empty: base = 0x7FFF lim = 0;
+ */
+ if (base == kMask && lim == 0)
+ continue; // unused
+
+ if (lim < base)
+ continue; // unused
+
+ CItem item;
+ item.Name = kRegionName[i];
+ item.Method = method;
+ item.BufIndex = bufIndex;
+ item.Parent = parent;
+ item.Offset = posBase + (base << 12);
+ if (item.Offset > exactSize)
+ continue;
+ item.Size = (lim + 1 - base) << 12;
+ // item.SetGuid(p + kFfsGuidOffset);
+ // item.Name += " [VOLUME]";
+ AddItem(item);
+ }
return S_OK;
}
+
HRESULT CHandler::OpenCapsule(IInStream *stream)
{
const unsigned kHeaderSize = 80;
Byte buf[kHeaderSize];
RINOK(ReadStream_FALSE(stream, buf, kHeaderSize));
- _h.Parse(buf);
- if (_h.HeaderSize != kHeaderSize ||
- _h.CapsuleImageSize < kHeaderSize ||
- _h.OffsetToCapsuleBody < kHeaderSize ||
- _h.OffsetToCapsuleBody > _h.CapsuleImageSize)
+ if (!_h.Parse(buf))
+ return S_FALSE;
+ if (_h.CapsuleImageSize < kHeaderSize
+ || _h.CapsuleImageSize < _h.HeaderSize
+ || _h.OffsetToCapsuleBody < _h.HeaderSize
+ || _h.OffsetToCapsuleBody > _h.CapsuleImageSize
+ )
return S_FALSE;
_phySize = _h.CapsuleImageSize;
@@ -1350,17 +1597,21 @@ HRESULT CHandler::OpenCapsule(IInStream *stream)
memcpy(buf0, buf, kHeaderSize);
ReadStream_FALSE(stream, buf0 + kHeaderSize, _h.CapsuleImageSize - kHeaderSize);
- AddCommentString(L"Author", _h.OffsetToAuthorInformation);
- AddCommentString(L"Revision", _h.OffsetToRevisionInformation);
- AddCommentString(L"Short Description", _h.OffsetToShortDescription);
- AddCommentString(L"Long Description", _h.OffsetToLongDescription);
+ AddCommentString("Author", _h.OffsetToAuthorInformation);
+ AddCommentString("Revision", _h.OffsetToRevisionInformation);
+ AddCommentString("Short Description", _h.OffsetToShortDescription);
+ AddCommentString("Long Description", _h.OffsetToLongDescription);
+
+
+ const UInt32 size = _h.CapsuleImageSize - _h.OffsetToCapsuleBody;
- return ParseVolume(bufIndex, _h.OffsetToCapsuleBody,
- _h.CapsuleImageSize - _h.OffsetToCapsuleBody,
- _h.CapsuleImageSize - _h.OffsetToCapsuleBody,
- -1, -1, 0);
+ if (size >= 32 && IsIntelMe(buf0 + _h.OffsetToCapsuleBody))
+ return ParseIntelMe(bufIndex, _h.OffsetToCapsuleBody, size, size, -1, -1, 0);
+
+ return ParseVolume(bufIndex, _h.OffsetToCapsuleBody, size, size, -1, -1, 0);
}
+
HRESULT CHandler::OpenFv(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback * /* callback */)
{
Byte buf[kFvHeaderSize];
@@ -1380,6 +1631,7 @@ HRESULT CHandler::OpenFv(IInStream *stream, const UInt64 * /* maxCheckStartPosit
return ParseVolume(bufIndex, 0, fvSize32, fvSize32, -1, -1, 0);
}
+
HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback)
{
if (_capsuleMode)
@@ -1432,8 +1684,8 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition,
int parent = item.Parent;
if (parent >= 0)
numItems = numChilds[(unsigned)parent];
- AString name2 = item.GetName(numItems);
- AString characts2 = item.Characts;
+ AString name2 (item.GetName(numItems));
+ AString characts2 (item.Characts);
if (item.KeepName)
name = name2;
@@ -1444,7 +1696,7 @@ HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition,
break;
if (item3.KeepName)
{
- AString name3 = item3.GetName(-1);
+ AString name3 (item3.GetName(-1));
if (name.IsEmpty())
name = name3;
else
@@ -1500,6 +1752,7 @@ STDMETHODIMP CHandler::Close()
_items2.Clear();
_bufs.Clear();
_comment.Empty();
+ _headersError = false;
_h.Clear();
return S_OK;
}
@@ -1580,11 +1833,12 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
CBufInStream *streamSpec = new CBufInStream;
CMyComPtr<IInStream> streamTemp = streamSpec;
const CByteBuffer &buf = _bufs[item.BufIndex];
- /*
- if (item.Offset + item.Size > buf.GetCapacity())
+ if (item.Offset > buf.Size())
return S_FALSE;
- */
- streamSpec->Init(buf + item.Offset, item.Size, (IInArchive *)this);
+ size_t size = buf.Size() - item.Offset;
+ if (size > item.Size)
+ size = item.Size;
+ streamSpec->Init(buf + item.Offset, size, (IInArchive *)this);
*stream = streamTemp.Detach();
return S_OK;
COM_TRY_END
@@ -1593,11 +1847,19 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
namespace UEFIc {
+static const Byte k_Capsule_Signatures[] =
+{
+ 16, CAPSULE_SIGNATURE,
+ 16, CAPSULE2_SIGNATURE,
+ 16, CAPSULE_UEFI_SIGNATURE
+};
+
REGISTER_ARC_I_CLS(
CHandler(true),
"UEFIc", "scap", 0, 0xD0,
- kCapsuleSig,
+ k_Capsule_Signatures,
0,
+ NArcInfoFlags::kMultiSignature |
NArcInfoFlags::kFindSignature,
NULL)
@@ -1605,11 +1867,19 @@ REGISTER_ARC_I_CLS(
namespace UEFIf {
+static const Byte k_FFS_Signatures[] =
+{
+ 16, FFS1_SIGNATURE,
+ 16, FFS2_SIGNATURE
+};
+
+
REGISTER_ARC_I_CLS(
CHandler(false),
"UEFIf", "uefif", 0, 0xD1,
- k_FFS_Guid,
+ k_FFS_Signatures,
kFfsGuidOffset,
+ NArcInfoFlags::kMultiSignature |
NArcInfoFlags::kFindSignature,
NULL)
diff --git a/CPP/7zip/Archive/VdiHandler.cpp b/CPP/7zip/Archive/VdiHandler.cpp
index a8d3fe36..b8ef35bb 100644
--- a/CPP/7zip/Archive/VdiHandler.cpp
+++ b/CPP/7zip/Archive/VdiHandler.cpp
@@ -11,12 +11,14 @@
#include "../../Common/MyBuffer.h"
#include "../../Windows/PropVariant.h"
+#include "../../Windows/PropVariantUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h"
#include "HandlerCont.h"
+#define Get16(p) GetUi16(p)
#define Get32(p) GetUi32(p)
#define Get64(p) GetUi64(p)
@@ -33,6 +35,7 @@ static const unsigned k_ClusterBits = 20;
static const UInt32 k_ClusterSize = (UInt32)1 << k_ClusterBits;
static const UInt32 k_UnusedCluster = 0xFFFFFFFF;
+
// static const UInt32 kDiskType_Dynamic = 1;
// static const UInt32 kDiskType_Static = 2;
@@ -41,8 +44,38 @@ static const char * const kDiskTypes[] =
"0"
, "Dynamic"
, "Static"
+ , "Undo"
+ , "Diff"
+};
+
+
+enum EGuidType
+{
+ k_GuidType_Creat,
+ k_GuidType_Modif,
+ k_GuidType_Link,
+ k_GuidType_PModif
};
+static const unsigned kNumGuids = 4;
+static const char * const kGuidNames[kNumGuids] =
+{
+ "Creat "
+ , "Modif "
+ , "Link "
+ , "PModif"
+};
+
+static bool IsEmptyGuid(const Byte *data)
+{
+ for (unsigned i = 0; i < 16; i++)
+ if (data[i] != 0)
+ return false;
+ return true;
+}
+
+
+
class CHandler: public CHandlerImg
{
UInt32 _dataOffset;
@@ -52,6 +85,8 @@ class CHandler: public CHandlerImg
bool _isArc;
bool _unsupported;
+ Byte Guids[kNumGuids][16];
+
HRESULT Seek(UInt64 offset)
{
_posInArc = offset;
@@ -137,7 +172,9 @@ static const Byte kProps[] =
static const Byte kArcProps[] =
{
kpidHeadersSize,
- kpidMethod
+ kpidMethod,
+ kpidComment,
+ kpidName
};
IMP_IInArchive_Props
@@ -156,16 +193,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidMethod:
{
- char s[16];
- const char *ptr;
- if (_imageType < ARRAY_SIZE(kDiskTypes))
- ptr = kDiskTypes[_imageType];
- else
- {
- ConvertUInt32ToString(_imageType, s);
- ptr = s;
- }
- prop = ptr;
+ TYPE_TO_PROP(kDiskTypes, _imageType, prop);
break;
}
@@ -181,6 +209,42 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
prop = v;
break;
}
+
+ case kpidComment:
+ {
+ AString s;
+ for (unsigned i = 0; i < kNumGuids; i++)
+ {
+ const Byte *guid = Guids[i];
+ if (!IsEmptyGuid(guid))
+ {
+ s.Add_LF();
+ s += kGuidNames[i];
+ s += " : ";
+ char temp[64];
+ RawLeGuidToString_Braced(guid, temp);
+ MyStringLower_Ascii(temp);
+ s += temp;
+ }
+ }
+ if (!s.IsEmpty())
+ prop = s;
+ break;
+ }
+
+ case kpidName:
+ {
+ const Byte *guid = Guids[k_GuidType_Creat];
+ if (!IsEmptyGuid(guid))
+ {
+ char temp[64];
+ RawLeGuidToString_Braced(guid, temp);
+ MyStringLower_Ascii(temp);
+ strcat(temp, ".vdi");
+ prop = temp;
+ }
+ break;
+ }
}
prop.Detach(value);
@@ -207,15 +271,6 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
}
-static bool IsEmptyGuid(const Byte *data)
-{
- for (unsigned i = 0; i < 16; i++)
- if (data[i] != 0)
- return false;
- return true;
-}
-
-
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallback */)
{
const unsigned kHeaderSize = 512;
@@ -225,45 +280,65 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallbac
if (memcmp(buf + 0x40, k_Signature, sizeof(k_Signature)) != 0)
return S_FALSE;
- UInt32 version = Get32(buf + 0x44);
+ const UInt32 version = Get32(buf + 0x44);
if (version >= 0x20000)
return S_FALSE;
+ if (version < 0x10000)
+ {
+ _unsupported = true;
+ return S_FALSE;
+ }
- UInt32 headerSize = Get32(buf + 0x48);
- if (headerSize < 0x140 || headerSize > 0x1B8)
+ const unsigned kHeaderOffset = 0x48;
+ const unsigned kGuidsOffsets = 0x188;
+ const UInt32 headerSize = Get32(buf + kHeaderOffset);
+ if (headerSize < kGuidsOffsets - kHeaderOffset || headerSize > 0x200 - kHeaderOffset)
return S_FALSE;
_imageType = Get32(buf + 0x4C);
- _dataOffset = Get32(buf + 0x158);
+ // Int32 flags = Get32(buf + 0x50);
+ // Byte Comment[0x100]
- UInt32 tableOffset = Get32(buf + 0x154);
+ const UInt32 tableOffset = Get32(buf + 0x154);
if (tableOffset < 0x200)
return S_FALSE;
+
+ _dataOffset = Get32(buf + 0x158);
+
+ // UInt32 geometry[3];
- UInt32 sectorSize = Get32(buf + 0x168);
+ const UInt32 sectorSize = Get32(buf + 0x168);
if (sectorSize != 0x200)
return S_FALSE;
_size = Get64(buf + 0x170);
+ const UInt32 blockSize = Get32(buf + 0x178);
+ const UInt32 totalBlocks = Get32(buf + 0x180);
+ const UInt32 numAllocatedBlocks = Get32(buf + 0x184);
+
_isArc = true;
- if (_imageType > 2)
- {
- _unsupported = true;
- return S_FALSE;
- }
-
if (_dataOffset < tableOffset)
return S_FALSE;
- UInt32 blockSize = Get32(buf + 0x178);
- if (blockSize != ((UInt32)1 << k_ClusterBits))
+ if (_imageType > 4)
+ _unsupported = true;
+
+ if (blockSize != k_ClusterSize)
{
_unsupported = true;
return S_FALSE;
}
- UInt32 totalBlocks = Get32(buf + 0x180);
+ if (headerSize >= kGuidsOffsets + kNumGuids * 16 - kHeaderOffset)
+ {
+ for (unsigned i = 0; i < kNumGuids; i++)
+ memcpy(Guids[i], buf + kGuidsOffsets + 16 * i, 16);
+
+ if (!IsEmptyGuid(Guids[k_GuidType_Link]) ||
+ !IsEmptyGuid(Guids[k_GuidType_PModif]))
+ _unsupported = true;
+ }
{
UInt64 size2 = (UInt64)totalBlocks << k_ClusterBits;
@@ -278,18 +353,6 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallbac
*/
}
- if (headerSize >= 0x180)
- {
- if (!IsEmptyGuid(buf + 0x1A8) ||
- !IsEmptyGuid(buf + 0x1B8))
- {
- _unsupported = true;
- return S_FALSE;
- }
- }
-
- UInt32 numAllocatedBlocks = Get32(buf + 0x184);
-
{
UInt32 tableReserved = _dataOffset - tableOffset;
if ((tableReserved >> 2) < totalBlocks)
@@ -298,11 +361,11 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallbac
_phySize = _dataOffset + ((UInt64)numAllocatedBlocks << k_ClusterBits);
- size_t numBytes = (size_t)totalBlocks * 4;
+ const size_t numBytes = (size_t)totalBlocks * 4;
if ((numBytes >> 2) != totalBlocks)
{
_unsupported = true;
- return S_FALSE;
+ return E_OUTOFMEMORY;
}
_table.Alloc(numBytes);
@@ -316,7 +379,10 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallbac
if (v == k_UnusedCluster)
continue;
if (v >= numAllocatedBlocks)
+ {
+ _unsupported = true;
return S_FALSE;
+ }
}
Stream = stream;
@@ -332,6 +398,9 @@ STDMETHODIMP CHandler::Close()
_isArc = false;
_unsupported = false;
+ for (unsigned i = 0; i < kNumGuids; i++)
+ memset(Guids[i], 0, 16);
+
_imgExt = NULL;
Stream.Release();
return S_OK;
diff --git a/CPP/7zip/Archive/VhdHandler.cpp b/CPP/7zip/Archive/VhdHandler.cpp
index 12cbfa04..d79ae907 100644
--- a/CPP/7zip/Archive/VhdHandler.cpp
+++ b/CPP/7zip/Archive/VhdHandler.cpp
@@ -5,7 +5,6 @@
#include "../../../C/CpuArch.h"
#include "../../Common/ComTry.h"
-#include "../../Common/IntToString.h"
#include "../../Windows/PropVariant.h"
@@ -69,17 +68,16 @@ struct CFooter
UInt32 NumCyls() const { return DiskGeometry >> 16; }
UInt32 NumHeads() const { return (DiskGeometry >> 8) & 0xFF; }
UInt32 NumSectorsPerTrack() const { return DiskGeometry & 0xFF; }
- AString GetTypeString() const;
+ void AddTypeString(AString &s) const;
bool Parse(const Byte *p);
};
-AString CFooter::GetTypeString() const
+void CFooter::AddTypeString(AString &s) const
{
if (Type < ARRAY_SIZE(kDiskTypes))
- return kDiskTypes[Type];
- char s[16];
- ConvertUInt32ToString(Type, s);
- return s;
+ s += kDiskTypes[Type];
+ else
+ s.Add_UInt32(Type);
}
static bool CheckBlock(const Byte *p, unsigned size, unsigned checkSumOffset, unsigned zeroOffset)
@@ -234,12 +232,15 @@ class CHandler: public CHandlerImg
UString _errorMessage;
// bool _unexpectedEnd;
- void AddErrorMessage(const wchar_t *s)
+ void AddErrorMessage(const char *message, const wchar_t *name = NULL)
{
if (!_errorMessage.IsEmpty())
_errorMessage.Add_LF();
- _errorMessage += s;
+ _errorMessage += message;
+ if (name)
+ _errorMessage += name;
}
+
void UpdatePhySize(UInt64 value)
{
if (_phySize < value)
@@ -262,7 +263,7 @@ class CHandler: public CHandlerImg
while (p && p->NeedParent())
{
if (!res.IsEmpty())
- res.AddAscii(" -> ");
+ res += " -> ";
UString mainName;
UString anotherName;
if (Dyn.RelativeNameWasUsed)
@@ -279,9 +280,9 @@ class CHandler: public CHandlerImg
if (mainName != anotherName && !anotherName.IsEmpty())
{
res.Add_Space();
- res += L'(';
+ res += '(';
res += anotherName;
- res += L')';
+ res += ')';
}
p = p->Parent;
}
@@ -522,7 +523,7 @@ HRESULT CHandler::Open3()
}
_posInArcLimit = _phySize;
_phySize += kHeaderSize;
- AddErrorMessage(L"Can't find footer");
+ AddErrorMessage("Can't find footer");
return S_OK;
}
@@ -679,7 +680,8 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
case kpidShortComment:
case kpidMethod:
{
- AString s = Footer.GetTypeString();
+ AString s;
+ Footer.AddTypeString(s);
if (NeedParent())
{
s += " -> ";
@@ -689,7 +691,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
if (!p)
s += '?';
else
- s += p->Footer.GetTypeString();
+ p->Footer.AddTypeString(s);
}
prop = s;
break;
@@ -698,14 +700,12 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
char s[16];
StringToAString(s, Footer.CreatorApp);
- AString res = s;
+ AString res (s);
res.Trim();
- ConvertUInt32ToString(Footer.CreatorVersion >> 16, s);
res.Add_Space();
- res += s;
+ res.Add_UInt32(Footer.CreatorVersion >> 16);
res += '.';
- ConvertUInt32ToString(Footer.CreatorVersion & 0xFFFF, s);
- res += s;
+ res.Add_UInt32(Footer.CreatorVersion & 0xFFFF);
prop = res;
break;
}
@@ -806,10 +806,7 @@ HRESULT CHandler::Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback
if (res == S_FALSE || !nextStream)
{
- UString s;
- s.SetFromAscii("Missing volume : ");
- s += name;
- AddErrorMessage(s);
+ AddErrorMessage("Missing volume : ", name);
return S_OK;
}
@@ -837,8 +834,7 @@ HRESULT CHandler::Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback
p = p->Parent;
if (!p)
{
- AddErrorMessage(L"Can't open parent VHD file:");
- AddErrorMessage(Dyn.ParentName);
+ AddErrorMessage("Can't open parent VHD file : ", Dyn.ParentName);
break;
}
}
diff --git a/CPP/7zip/Archive/VmdkHandler.cpp b/CPP/7zip/Archive/VmdkHandler.cpp
index 5f93c738..942bd792 100644
--- a/CPP/7zip/Archive/VmdkHandler.cpp
+++ b/CPP/7zip/Archive/VmdkHandler.cpp
@@ -296,10 +296,15 @@ bool CDescriptor::Parse(const Byte *p, size_t size)
AString name;
AString val;
- for (size_t i = 0;; i++)
+ for (;;)
{
- const char c = p[i];
- if (i == size || c == 0 || c == 0xA || c == 0xD)
+ char c = 0;
+ if (size != 0)
+ {
+ size--;
+ c = *p++;
+ }
+ if (c == 0 || c == 0xA || c == 0xD)
{
if (!s.IsEmpty() && s[0] != '#')
{
@@ -322,14 +327,12 @@ bool CDescriptor::Parse(const Byte *p, size_t size)
}
s.Empty();
- if (c == 0 || i >= size)
- break;
+ if (c == 0)
+ return true;
}
else
s += (char)c;
}
-
- return true;
}
@@ -819,9 +822,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
else if (algo != (int)h.algo)
{
s.Add_Space_if_NotEmpty();
- char temp[16];
- ConvertUInt32ToString(h.algo, temp);
- s += temp;
+ s.Add_UInt32(h.algo);
algo = h.algo;
}
}
@@ -831,16 +832,10 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
}
if (zlib)
- {
- s.Add_Space_if_NotEmpty();
- s += "zlib";
- }
+ s.Add_OptSpaced("zlib");
if (marker)
- {
- s.Add_Space_if_NotEmpty();
- s += "Marker";
- }
+ s.Add_OptSpaced("Marker");
if (!s.IsEmpty())
prop = s;
@@ -888,8 +883,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
if (_missingVol || !_missingVolName.IsEmpty())
{
- UString s;
- s.SetFromAscii("Missing volume : ");
+ UString s ("Missing volume : ");
if (!_missingVolName.IsEmpty())
s += _missingVolName;
prop = s;
@@ -983,6 +977,9 @@ void CHandler::CloseAtError()
}
+static const char * const kSignature_Descriptor = "# Disk DescriptorFile";
+
+
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
{
const unsigned kSectoreSize = 512;
@@ -997,7 +994,6 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
if (memcmp(buf, k_Signature, sizeof(k_Signature)) != 0)
{
- const char *kSignature_Descriptor = "# Disk DescriptorFile";
const size_t k_SigDesc_Size = strlen(kSignature_Descriptor);
if (headerSize < k_SigDesc_Size)
return S_FALSE;
diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp
index 234780dd..927a0b38 100644
--- a/CPP/7zip/Archive/Wim/WimHandler.cpp
+++ b/CPP/7zip/Archive/Wim/WimHandler.cpp
@@ -94,15 +94,6 @@ static void AddErrorMessage(AString &s, const char *message)
s += message;
}
-static void ConvertByteToHex(unsigned value, char *s)
-{
- for (int i = 0; i < 2; i++)
- {
- unsigned t = value & 0xF;
- value >>= 4;
- s[1 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
- }
-}
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
@@ -177,17 +168,14 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
UInt32 ver2 = (_version >> 8) & 0xFF;
UInt32 ver3 = (_version) & 0xFF;
- char s[16];
- ConvertUInt32ToString(ver1, s);
- AString res = s;
+ AString res;
+ res.Add_UInt32(ver1);
res += '.';
- ConvertUInt32ToString(ver2, s);
- res += s;
+ res.Add_UInt32(ver2);
if (ver3 != 0)
{
res += '.';
- ConvertUInt32ToString(ver3, s);
- res += s;
+ res.Add_UInt32(ver3);
}
prop = res;
break;
@@ -229,22 +217,16 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
const CHeader &h = _volumes[_firstVolumeIndex].Header;
if (GetUi32(h.Guid) != 0)
{
- char temp[16 * 2 + 4];
- int i;
- for (i = 0; i < 4; i++)
- ConvertByteToHex(h.Guid[i], temp + i * 2);
- temp[i * 2] = 0;
- AString s = temp;
+ char temp[64];
+ RawLeGuidToString(h.Guid, temp);
+ temp[8] = 0; // for reduced GUID
+ AString s (temp);
const char *ext = ".wim";
if (h.NumParts != 1)
{
s += '_';
if (h.PartNumber != 1)
- {
- char sz[16];
- ConvertUInt32ToString(h.PartNumber, sz);
- s += sz;
- }
+ s.Add_UInt32(h.PartNumber);
ext = ".swm";
}
s += ext;
@@ -262,9 +244,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
AString s;
if (h.PartNumber != 1)
{
- char sz[16];
- ConvertUInt32ToString(h.PartNumber, sz);
- s = sz;
+ s.Add_UInt32(h.PartNumber);
s += '.';
}
s += "swm";
@@ -312,19 +292,15 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
if (methodUnknown != 0)
{
- char temp[32];
- ConvertUInt32ToString(methodUnknown, temp);
res.Add_Space_if_NotEmpty();
- res += temp;
+ res.Add_UInt32(methodUnknown);
numMethods++;
}
if (numMethods == 1 && chunkSizeBits != 0)
{
- char temp[32];
- temp[0] = ':';
- ConvertUInt32ToString((UInt32)chunkSizeBits, temp + 1);
- res += temp;
+ res += ':';
+ res.Add_UInt32((UInt32)chunkSizeBits);
}
prop = res;
@@ -391,7 +367,7 @@ static void MethodToProp(int method, int chunksSizeBits, NCOM::CPropVariant &pro
if ((unsigned)method < ARRAY_SIZE(k_Methods))
strcpy(temp, k_Methods[(unsigned)method]);
else
- ConvertUInt32ToString((unsigned)method, temp);
+ ConvertUInt32ToString((UInt32)(unsigned)method, temp);
if (chunksSizeBits >= 0)
{
@@ -436,9 +412,6 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
_db.GetItemPath(realIndex, _showImageNumber, prop);
else
{
- char sz[16];
- ConvertUInt32ToString(item.StreamIndex, sz);
- AString s = sz;
/*
while (s.Len() < _nameLenForStreams)
s = '0' + s;
@@ -448,7 +421,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
s = (AString)("[Free]" STRING_PATH_SEPARATOR) + sz;
else
*/
- s = (AString)(FILES_DIR_NAME STRING_PATH_SEPARATOR) + sz;
+ AString s (FILES_DIR_NAME STRING_PATH_SEPARATOR);
+ s.Add_UInt32(item.StreamIndex);
prop = s;
}
break;
@@ -874,9 +848,10 @@ public:
UString GetNextName(UInt32 index) const
{
- wchar_t s[16];
- ConvertUInt32ToString(index, s);
- return _before + (UString)s + _after;
+ UString s = _before;
+ s.Add_UInt32(index);
+ s += _after;
+ return s;
}
};
@@ -970,11 +945,9 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCal
if (_xmls.IsEmpty() || xml.Data != _xmls[0].Data)
{
- char sz[16];
- ConvertUInt32ToString(xml.VolIndex, sz);
- xml.FileName = L'[';
- xml.FileName.AddAscii(sz);
- xml.FileName.AddAscii("].xml");
+ xml.FileName = '[';
+ xml.FileName.Add_UInt32(xml.VolIndex);
+ xml.FileName += "].xml";
_xmls.Add(xml);
}
diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
index 1d198df0..99fd46ef 100644
--- a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
+++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
@@ -1828,7 +1828,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
curPos += kStreamInfoSize;
}
- AString xml = "<WIM>";
+ AString xml ("<WIM>");
AddTagUInt64_ToString(xml, "TOTALBYTES", curPos);
for (i = 0; i < trees.Size(); i++)
{
diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp
index f35c2d50..b934478e 100644
--- a/CPP/7zip/Archive/Wim/WimIn.cpp
+++ b/CPP/7zip/Archive/Wim/WimIn.cpp
@@ -442,7 +442,7 @@ static inline void ParseStream(bool oldVersion, const Byte *p, CStreamInfo &s)
}
-static const char *kLongPath = "[LongPath]";
+#define kLongPath "[LongPath]"
void CDatabase::GetShortName(unsigned index, NWindows::NCOM::CPropVariant &name) const
{
diff --git a/CPP/7zip/Archive/Wim/WimRegister.cpp b/CPP/7zip/Archive/Wim/WimRegister.cpp
index 6ad28acc..ecebe8d9 100644
--- a/CPP/7zip/Archive/Wim/WimRegister.cpp
+++ b/CPP/7zip/Archive/Wim/WimRegister.cpp
@@ -10,7 +10,7 @@ namespace NArchive {
namespace NWim {
REGISTER_ARC_IO(
- "wim", "wim swm esd", 0, 0xE6,
+ "wim", "wim swm esd ppkg", 0, 0xE6,
kSignature,
0,
NArcInfoFlags::kAltStreams |
diff --git a/CPP/7zip/Archive/XarHandler.cpp b/CPP/7zip/Archive/XarHandler.cpp
index 96386809..f20b1eb9 100644
--- a/CPP/7zip/Archive/XarHandler.cpp
+++ b/CPP/7zip/Archive/XarHandler.cpp
@@ -153,7 +153,7 @@ IMP_IInArchive_ArcProps
static bool ParseUInt64(const CXmlItem &item, const char *name, UInt64 &res)
{
- const AString s = item.GetSubStringForTag(name);
+ const AString s (item.GetSubStringForTag(name));
if (s.IsEmpty())
return false;
const char *end;
@@ -163,7 +163,7 @@ static bool ParseUInt64(const CXmlItem &item, const char *name, UInt64 &res)
static UInt64 ParseTime(const CXmlItem &item, const char *name)
{
- const AString s = item.GetSubStringForTag(name);
+ const AString s (item.GetSubStringForTag(name));
if (s.Len() < 20)
return 0;
const char *p = s;
@@ -198,10 +198,10 @@ static bool ParseSha1(const CXmlItem &item, const char *name, Byte *digest)
if (index < 0)
return false;
const CXmlItem &checkItem = item.SubItems[index];
- const AString style = checkItem.GetPropVal("style");
+ const AString style (checkItem.GetPropVal("style"));
if (style == "SHA1")
{
- const AString s = checkItem.GetSubString();
+ const AString s (checkItem.GetSubString());
if (s.Len() != SHA1_DIGEST_SIZE * 2)
return false;
for (unsigned i = 0; i < s.Len(); i += 2)
@@ -227,7 +227,7 @@ static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int paren
file.Parent = parent;
parent = files.Size();
file.Name = item.GetSubStringForTag("name");
- AString type = item.GetSubStringForTag("type");
+ const AString type (item.GetSubStringForTag("type"));
if (type == "directory")
file.IsDir = true;
else if (type == "file")
@@ -254,14 +254,14 @@ static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int paren
const CXmlItem &encodingItem = dataItem.SubItems[encodingIndex];
if (encodingItem.IsTag)
{
- AString s = encodingItem.GetPropVal("style");
+ AString s (encodingItem.GetPropVal("style"));
if (!s.IsEmpty())
{
- const AString appl = "application/";
+ const AString appl ("application/");
if (s.IsPrefixedBy(appl))
{
s.DeleteFrontal(appl.Len());
- const AString xx = "x-";
+ const AString xx ("x-");
if (s.IsPrefixedBy(xx))
{
s.DeleteFrontal(xx.Len());
@@ -280,7 +280,7 @@ static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int paren
file.ATime = ParseTime(item, "atime");
{
- const AString s = item.GetSubStringForTag("mode");
+ const AString s (item.GetSubStringForTag("mode"));
if (s[0] == '0')
{
const char *end;
diff --git a/CPP/7zip/Archive/XzHandler.cpp b/CPP/7zip/Archive/XzHandler.cpp
index 318be190..fd90c88d 100644
--- a/CPP/7zip/Archive/XzHandler.cpp
+++ b/CPP/7zip/Archive/XzHandler.cpp
@@ -3,8 +3,6 @@
#include "StdAfx.h"
#include "../../../C/Alloc.h"
-#include "../../../C/XzCrc64.h"
-#include "../../../C/XzEnc.h"
#include "../../Common/ComTry.h"
#include "../../Common/Defs.h"
@@ -12,14 +10,14 @@
#include "../../Windows/PropVariant.h"
-#include "../ICoder.h"
-
#include "../Common/CWrappers.h"
#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h"
#include "../Compress/CopyCoder.h"
+#include "../Compress/XzDecoder.h"
+#include "../Compress/XzEncoder.h"
#include "IArchive.h"
@@ -27,46 +25,13 @@
#include "Common/HandlerOut.h"
#endif
-#include "XzHandler.h"
-
using namespace NWindows;
-namespace NCompress {
-namespace NLzma2 {
-
-HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props);
-
-}}
-
namespace NArchive {
namespace NXz {
-struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit;
-
-static const char *k_LZMA2_Name = "LZMA2";
+#define k_LZMA2_Name "LZMA2"
-void CStatInfo::Clear()
-{
- InSize = 0;
- OutSize = 0;
- PhySize = 0;
-
- NumStreams = 0;
- NumBlocks = 0;
-
- UnpackSize_Defined = false;
-
- NumStreams_Defined = false;
- NumBlocks_Defined = false;
-
- IsArc = false;
- UnexpectedEnd = false;
- DataAfterEnd = false;
- Unsupported = false;
- HeadersError = false;
- DataError = false;
- CrcError = false;
-}
class CHandler:
public IInArchive,
@@ -78,7 +43,7 @@ class CHandler:
#endif
public CMyUnknownImp
{
- CStatInfo _stat;
+ NCompress::NXz::CStatInfo _stat;
bool _isArc;
bool _needSeekToStart;
@@ -104,9 +69,12 @@ class CHandler:
HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback);
HRESULT Decode2(ISequentialInStream *seqInStream, ISequentialOutStream *outStream,
- CDecoder &decoder, ICompressProgressInfo *progress)
+ NCompress::NXz::CDecoder &decoder, ICompressProgressInfo *progress)
{
- RINOK(decoder.Decode(seqInStream, outStream, progress));
+ RINOK(decoder.Decode(seqInStream, outStream,
+ NULL, // *outSizeLimit
+ true, // finishStream
+ progress));
_stat = decoder;
_phySize_Defined = true;
return S_OK;
@@ -169,13 +137,6 @@ static inline void AddHexToString(AString &s, Byte value)
s += GetHex(value & 0xF);
}
-static void AddUInt32ToString(AString &s, UInt32 value)
-{
- char temp[16];
- ConvertUInt32ToString(value, temp);
- s += temp;
-}
-
static void Lzma2PropToString(AString &s, unsigned prop)
{
char c = 0;
@@ -192,7 +153,7 @@ static void Lzma2PropToString(AString &s, unsigned prop)
c = 'm';
}
}
- AddUInt32ToString(s, size);
+ s.Add_UInt32(size);
if (c != 0)
s += c;
}
@@ -232,7 +193,7 @@ static AString GetMethodString(const CXzFilter &f)
p = temp;
}
- AString s = p;
+ AString s (p);
if (f.propsSize > 0)
{
@@ -240,7 +201,7 @@ static AString GetMethodString(const CXzFilter &f)
if (f.id == XZ_ID_LZMA2 && f.propsSize == 1)
Lzma2PropToString(s, f.props[0]);
else if (f.id == XZ_ID_Delta && f.propsSize == 1)
- AddUInt32ToString(s, (UInt32)f.props[0] + 1);
+ s.Add_UInt32((UInt32)f.props[0] + 1);
else
{
s += '[';
@@ -294,7 +255,7 @@ static AString GetCheckString(const CXzs &xzs)
else
{
s2 = "Check-";
- AddUInt32ToString(s2, (UInt32)i);
+ s2.Add_UInt32((UInt32)i);
}
AddString(s, s2);
}
@@ -354,27 +315,28 @@ STDMETHODIMP CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value)
struct COpenCallbackWrap
{
- ICompressProgress p;
+ ICompressProgress vt;
IArchiveOpenCallback *OpenCallback;
HRESULT Res;
COpenCallbackWrap(IArchiveOpenCallback *progress);
};
-static SRes OpenCallbackProgress(void *pp, UInt64 inSize, UInt64 /* outSize */)
+static SRes OpenCallbackProgress(const ICompressProgress *pp, UInt64 inSize, UInt64 /* outSize */)
{
- COpenCallbackWrap *p = (COpenCallbackWrap *)pp;
+ COpenCallbackWrap *p = CONTAINER_FROM_VTBL(pp, COpenCallbackWrap, vt);
if (p->OpenCallback)
p->Res = p->OpenCallback->SetCompleted(NULL, &inSize);
- return (SRes)p->Res;
+ return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS);
}
COpenCallbackWrap::COpenCallbackWrap(IArchiveOpenCallback *callback)
{
- p.Progress = OpenCallbackProgress;
+ vt.Progress = OpenCallbackProgress;
OpenCallback = callback;
Res = SZ_OK;
}
+
struct CXzsCPP
{
CXzs p;
@@ -382,6 +344,30 @@ struct CXzsCPP
~CXzsCPP() { Xzs_Free(&p, &g_Alloc); }
};
+#define kInputBufSize ((size_t)1 << 10)
+
+struct CLookToRead2_CPP: public CLookToRead2
+{
+ CLookToRead2_CPP()
+ {
+ buf = NULL;
+ LookToRead2_CreateVTable(this,
+ True // Lookahead ?
+ );
+ }
+ void Alloc(size_t allocSize)
+ {
+ buf = (Byte *)MyAlloc(allocSize);
+ if (buf)
+ this->bufSize = allocSize;
+ }
+ ~CLookToRead2_CPP()
+ {
+ MyFree(buf);
+ }
+};
+
+
static HRESULT SRes_to_Open_HRESULT(SRes res)
{
switch (res)
@@ -401,14 +387,18 @@ static HRESULT SRes_to_Open_HRESULT(SRes res)
return S_FALSE;
}
+
+
HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback)
{
_needSeekToStart = true;
{
CXzStreamFlags st;
- CSeqInStreamWrap inStreamWrap(inStream);
- SRes res = Xz_ReadHeader(&st, &inStreamWrap.p);
+ CSeqInStreamWrap inStreamWrap;
+
+ inStreamWrap.Init(inStream);
+ SRes res = Xz_ReadHeader(&st, &inStreamWrap.vt);
if (res != SZ_OK)
return SRes_to_Open_HRESULT(res);
@@ -416,7 +406,7 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
CXzBlock block;
Bool isIndex;
UInt32 headerSizeRes;
- SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.p, &isIndex, &headerSizeRes);
+ SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.vt, &isIndex, &headerSizeRes);
if (res2 == SZ_OK && !isIndex)
{
unsigned numFilters = XzBlock_GetNumFilters(&block);
@@ -432,18 +422,25 @@ HRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCal
RINOK(callback->SetTotal(NULL, &_stat.PhySize));
}
- CSeekInStreamWrap inStreamImp(inStream);
+ CSeekInStreamWrap inStreamImp;;
+
+ inStreamImp.Init(inStream);
+
+ CLookToRead2_CPP lookStream;
+
+ lookStream.Alloc(kInputBufSize);
+
+ if (!lookStream.buf)
+ return E_OUTOFMEMORY;
- CLookToRead lookStream;
- LookToRead_CreateVTable(&lookStream, True);
- lookStream.realStream = &inStreamImp.p;
- LookToRead_Init(&lookStream);
+ lookStream.realStream = &inStreamImp.vt;
+ LookToRead2_Init(&lookStream);
COpenCallbackWrap openWrap(callback);
CXzsCPP xzs;
Int64 startPosition;
- SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.s, &startPosition, &openWrap.p, &g_Alloc);
+ SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.vt, &startPosition, &openWrap.vt, &g_Alloc);
if (res == SZ_ERROR_PROGRESS)
return (openWrap.Res == S_OK) ? E_FAIL : openWrap.Res;
/*
@@ -511,6 +508,8 @@ STDMETHODIMP CHandler::Close()
return S_OK;
}
+
+
class CSeekToSeqStream:
public IInStream,
public CMyUnknownImp
@@ -530,169 +529,12 @@ STDMETHODIMP CSeekToSeqStream::Read(void *data, UInt32 size, UInt32 *processedSi
STDMETHODIMP CSeekToSeqStream::Seek(Int64, UInt32, UInt64 *) { return E_NOTIMPL; }
-CXzUnpackerCPP::CXzUnpackerCPP(): InBuf(0), OutBuf(0)
-{
- XzUnpacker_Construct(&p, &g_Alloc);
-}
-
-CXzUnpackerCPP::~CXzUnpackerCPP()
-{
- XzUnpacker_Free(&p);
- MyFree(InBuf);
- MyFree(OutBuf);
-}
-
-HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)
-{
- const size_t kInBufSize = 1 << 15;
- const size_t kOutBufSize = 1 << 21;
-
- Clear();
- DecodeRes = SZ_OK;
-
- XzUnpacker_Init(&xzu.p);
- if (!xzu.InBuf)
- xzu.InBuf = (Byte *)MyAlloc(kInBufSize);
- if (!xzu.OutBuf)
- xzu.OutBuf = (Byte *)MyAlloc(kOutBufSize);
-
- UInt32 inSize = 0;
- SizeT inPos = 0;
- SizeT outPos = 0;
-
- for (;;)
- {
- if (inPos == inSize)
- {
- inPos = inSize = 0;
- RINOK(seqInStream->Read(xzu.InBuf, kInBufSize, &inSize));
- }
-
- SizeT inLen = inSize - inPos;
- SizeT outLen = kOutBufSize - outPos;
- ECoderStatus status;
-
- SRes res = XzUnpacker_Code(&xzu.p,
- xzu.OutBuf + outPos, &outLen,
- xzu.InBuf + inPos, &inLen,
- (inSize == 0 ? CODER_FINISH_END : CODER_FINISH_ANY), &status);
- inPos += inLen;
- outPos += outLen;
- InSize += inLen;
- OutSize += outLen;
- DecodeRes = res;
- bool finished = ((inLen == 0 && outLen == 0) || res != SZ_OK);
- if (outStream)
- {
- if (outPos == kOutBufSize || finished)
- {
- if (outPos != 0)
- {
- RINOK(WriteStream(outStream, xzu.OutBuf, outPos));
- outPos = 0;
- }
- }
- }
- else
- outPos = 0;
-
- if (progress)
- {
- RINOK(progress->SetRatioInfo(&InSize, &OutSize));
- }
-
- if (finished)
- {
- PhySize = InSize;
- NumStreams = xzu.p.numStartedStreams;
- if (NumStreams > 0)
- IsArc = true;
- NumBlocks = xzu.p.numTotalBlocks;
- UnpackSize_Defined = true;
- NumStreams_Defined = true;
- NumBlocks_Defined = true;
-
- UInt64 extraSize = XzUnpacker_GetExtraSize(&xzu.p);
-
- if (res == SZ_OK)
- {
- if (status == CODER_STATUS_NEEDS_MORE_INPUT)
- {
- extraSize = 0;
- if (!XzUnpacker_IsStreamWasFinished(&xzu.p))
- {
- // finished at padding bytes, but padding is not aligned for 4
- UnexpectedEnd = true;
- res = SZ_ERROR_DATA;
- }
- }
- else // status == CODER_STATUS_NOT_FINISHED
- res = SZ_ERROR_DATA;
- }
- else if (res == SZ_ERROR_NO_ARCHIVE)
- {
- if (InSize == extraSize)
- IsArc = false;
- else
- {
- if (extraSize != 0 || inPos != inSize)
- {
- DataAfterEnd = true;
- res = SZ_OK;
- }
- }
- }
-
- DecodeRes = res;
- PhySize -= extraSize;
-
- switch (res)
- {
- case SZ_OK: break;
- case SZ_ERROR_NO_ARCHIVE: IsArc = false; break;
- case SZ_ERROR_ARCHIVE: HeadersError = true; break;
- case SZ_ERROR_UNSUPPORTED: Unsupported = true; break;
- case SZ_ERROR_CRC: CrcError = true; break;
- case SZ_ERROR_DATA: DataError = true; break;
- default: DataError = true; break;
- }
-
- break;
- }
- }
-
- return S_OK;
-}
-
-Int32 CDecoder::Get_Extract_OperationResult() const
-{
- Int32 opRes;
- if (!IsArc)
- opRes = NExtract::NOperationResult::kIsNotArc;
- else if (UnexpectedEnd)
- opRes = NExtract::NOperationResult::kUnexpectedEnd;
- else if (DataAfterEnd)
- opRes = NExtract::NOperationResult::kDataAfterEnd;
- else if (CrcError)
- opRes = NExtract::NOperationResult::kCRCError;
- else if (Unsupported)
- opRes = NExtract::NOperationResult::kUnsupportedMethod;
- else if (HeadersError)
- opRes = NExtract::NOperationResult::kDataError;
- else if (DataError)
- opRes = NExtract::NOperationResult::kDataError;
- else if (DecodeRes != SZ_OK)
- opRes = NExtract::NOperationResult::kDataError;
- else
- opRes = NExtract::NOperationResult::kOK;
- return opRes;
-}
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
@@ -733,7 +575,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
else
_needSeekToStart = true;
- CDecoder decoder;
+ NCompress::NXz::CDecoder decoder;
RINOK(Decode2(_seqStream, realOutStream, decoder, lpsRef));
Int32 opRes = decoder.Get_Extract_OperationResult();
@@ -755,11 +597,13 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
{
COM_TRY_BEGIN
- CSeqOutStreamWrap seqOutStream(outStream);
if (numItems == 0)
{
- SRes res = Xz_EncodeEmpty(&seqOutStream.p);
+ CSeqOutStreamWrap seqOutStream;
+
+ seqOutStream.Init(outStream);
+ SRes res = Xz_EncodeEmpty(&seqOutStream.vt);
return SResToHRESULT(res);
}
@@ -795,34 +639,36 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
RINOK(updateCallback->SetTotal(size));
}
- CLzma2EncProps lzma2Props;
- Lzma2EncProps_Init(&lzma2Props);
+ NCompress::NXz::CEncoder *encoderSpec = new NCompress::NXz::CEncoder;
+ CMyComPtr<ICompressCoder> encoder = encoderSpec;
+ CLzma2EncProps &lzma2Props = encoderSpec->_lzma2Props;
lzma2Props.lzmaProps.level = GetLevel();
CMyComPtr<ISequentialInStream> fileInStream;
RINOK(updateCallback->GetStream(0, &fileInStream));
- CSeqInStreamWrap seqInStream(fileInStream);
-
{
NCOM::CPropVariant prop = (UInt64)size;
- RINOK(NCompress::NLzma2::SetLzma2Prop(NCoderPropID::kReduceSize, prop, lzma2Props));
+ RINOK(encoderSpec->SetCoderProp(NCoderPropID::kReduceSize, prop));
}
FOR_VECTOR (i, _methods)
{
COneMethodInfo &m = _methods[i];
- SetGlobalLevelAndThreads(m
+
+ /*
+ SetGlobalLevelTo(m);
#ifndef _7ZIP_ST
- , _numThreads
+ CMultiMethodProps::SetMethodThreads(m, _numThreads);
#endif
- );
+ */
+
{
FOR_VECTOR (j, m.Props)
{
const CProp &prop = m.Props[j];
- RINOK(NCompress::NLzma2::SetLzma2Prop(prop.Id, prop.Value, lzma2Props));
+ RINOK(encoderSpec->SetCoderProp(prop.Id, prop.Value));
}
}
}
@@ -835,11 +681,12 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(updateCallback, true);
- CCompressProgressWrap progressWrap(progress);
- CXzProps xzProps;
- CXzFilterProps filter;
+ CXzProps &xzProps = encoderSpec->xzProps;
+ CXzFilterProps &filter = encoderSpec->filter;
+
XzProps_Init(&xzProps);
XzFilterProps_Init(&filter);
+
xzProps.lzma2Props = &lzma2Props;
xzProps.filterProps = (_filterId != 0 ? &filter : NULL);
switch (_crcSize)
@@ -869,10 +716,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (!deltaDefined)
return E_INVALIDARG;
}
- SRes res = Xz_Encode(&seqOutStream.p, &seqInStream.p, &xzProps, &progressWrap.p);
- if (res == SZ_OK)
- return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
- return SResToHRESULT(res);
+
+ return encoderSpec->Code(fileInStream, outStream, NULL, NULL, progress);
}
if (indexInArchive != 0)
@@ -901,6 +746,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
COM_TRY_END
}
+
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
COM_TRY_BEGIN
diff --git a/CPP/7zip/Archive/XzHandler.h b/CPP/7zip/Archive/XzHandler.h
index 4a59e356..24e8eeb4 100644
--- a/CPP/7zip/Archive/XzHandler.h
+++ b/CPP/7zip/Archive/XzHandler.h
@@ -3,63 +3,9 @@
#ifndef __XZ_HANDLER_H
#define __XZ_HANDLER_H
-#include "../../../C/Xz.h"
-
-#include "../ICoder.h"
-
namespace NArchive {
namespace NXz {
-struct CXzUnpackerCPP
-{
- Byte *InBuf;
- Byte *OutBuf;
- CXzUnpacker p;
-
- CXzUnpackerCPP();
- ~CXzUnpackerCPP();
-};
-
-struct CStatInfo
-{
- UInt64 InSize;
- UInt64 OutSize;
- UInt64 PhySize;
-
- UInt64 NumStreams;
- UInt64 NumBlocks;
-
- bool UnpackSize_Defined;
-
- bool NumStreams_Defined;
- bool NumBlocks_Defined;
-
- bool IsArc;
- bool UnexpectedEnd;
- bool DataAfterEnd;
- bool Unsupported;
- bool HeadersError;
- bool DataError;
- bool CrcError;
-
- CStatInfo() { Clear(); }
-
- void Clear();
-};
-
-struct CDecoder: public CStatInfo
-{
- CXzUnpackerCPP xzu;
- SRes DecodeRes; // it's not HRESULT
-
- CDecoder(): DecodeRes(SZ_OK) {}
-
- /* Decode() can return ERROR code only if there is progress or stream error.
- Decode() returns S_OK in case of xz decoding error, but DecodeRes and CStatInfo contain error information */
- HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, ICompressProgressInfo *compressProgress);
- Int32 Get_Extract_OperationResult() const;
-};
-
}}
#endif
diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
index 06fbe22f..dd83f87f 100644
--- a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
+++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp
@@ -17,6 +17,7 @@
#include "../../Compress/LzmaEncoder.h"
#include "../../Compress/PpmdZip.h"
+#include "../../Compress/XzEncoder.h"
#include "../Common/InStreamWithCRC.h"
@@ -26,8 +27,8 @@
namespace NArchive {
namespace NZip {
-static const CMethodId kMethodId_ZipBase = 0x040100;
-static const CMethodId kMethodId_BZip2 = 0x040202;
+using namespace NFileHeader;
+
static const UInt32 kLzmaPropsSize = 5;
static const UInt32 kLzmaHeaderSize = 4 + kLzmaPropsSize;
@@ -37,10 +38,11 @@ class CLzmaEncoder:
public ICompressSetCoderProperties,
public CMyUnknownImp
{
+public:
NCompress::NLzma::CEncoder *EncoderSpec;
CMyComPtr<ICompressCoder> Encoder;
Byte Header[kLzmaHeaderSize];
-public:
+
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
@@ -81,7 +83,8 @@ CAddCommon::CAddCommon(const CCompressionMethodMode &options):
_options(options),
_copyCoderSpec(NULL),
_cryptoStreamSpec(NULL),
- _buf(NULL)
+ _buf(NULL),
+ _isLzmaEos(false)
{}
CAddCommon::~CAddCommon()
@@ -114,49 +117,100 @@ HRESULT CAddCommon::CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultC
}
}
+
+HRESULT CAddCommon::Set_Pre_CompressionResult(bool seqMode, UInt64 unpackSize, CCompressingResult &opRes) const
+{
+ // We use Zip64, if unPackSize size is larger than 0xF8000000 to support
+ // cases when compressed size can be about 3% larger than uncompressed size
+
+ const UInt32 kUnpackZip64Limit = 0xF8000000;
+
+ opRes.UnpackSize = unpackSize;
+ opRes.PackSize = (UInt64)1 << 60; // we use big value to force Zip64 mode.
+
+ if (unpackSize < kUnpackZip64Limit)
+ opRes.PackSize = (UInt32)0xFFFFFFFF - 1; // it will not use Zip64 for that size
+
+ if (opRes.PackSize < unpackSize)
+ opRes.PackSize = unpackSize;
+
+ Byte method = _options.MethodSequence[0];
+
+ if (method == NCompressionMethod::kStore && !_options.PasswordIsDefined)
+ opRes.PackSize = unpackSize;
+
+ opRes.CRC = 0;
+
+ opRes.LzmaEos = false;
+
+ opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;
+ opRes.FileTimeWasUsed = false;
+
+ if (_options.PasswordIsDefined)
+ {
+ opRes.ExtractVersion = NCompressionMethod::kExtractVersion_ZipCrypto;
+ if (_options.IsAesMode)
+ opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Aes;
+ else
+ {
+ if (seqMode)
+ opRes.FileTimeWasUsed = true;
+ }
+ }
+
+ opRes.Method = method;
+ Byte ver = 0;
+
+ switch (method)
+ {
+ case NCompressionMethod::kStore: break;
+ case NCompressionMethod::kDeflate: ver = NCompressionMethod::kExtractVersion_Deflate; break;
+ case NCompressionMethod::kDeflate64: ver = NCompressionMethod::kExtractVersion_Deflate64; break;
+ case NCompressionMethod::kXz : ver = NCompressionMethod::kExtractVersion_Xz; break;
+ case NCompressionMethod::kPPMd : ver = NCompressionMethod::kExtractVersion_PPMd; break;
+ case NCompressionMethod::kBZip2: ver = NCompressionMethod::kExtractVersion_BZip2; break;
+ case NCompressionMethod::kLZMA :
+ {
+ ver = NCompressionMethod::kExtractVersion_LZMA;
+ const COneMethodInfo *oneMethodMain = &_options._methods[0];
+ opRes.LzmaEos = oneMethodMain->Get_Lzma_Eos();
+ break;
+ }
+ }
+ if (opRes.ExtractVersion < ver)
+ opRes.ExtractVersion = ver;
+
+ return S_OK;
+}
+
+
HRESULT CAddCommon::Compress(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream, IOutStream *outStream,
- UInt32 /* fileTime */,
+ bool seqMode, UInt32 fileTime,
ICompressProgressInfo *progress, CCompressingResult &opRes)
{
+ opRes.LzmaEos = false;
+
if (!inStream)
{
// We can create empty stream here. But it was already implemented in caller code in 9.33+
return E_INVALIDARG;
}
- // CSequentialInStreamWithCRC *inSecCrcStreamSpec = NULL;
- CInStreamWithCRC *inCrcStreamSpec = NULL;
- CMyComPtr<ISequentialInStream> inCrcStream;
- {
- CMyComPtr<IInStream> inStream2;
-
+ CSequentialInStreamWithCRC *inSecCrcStreamSpec = new CSequentialInStreamWithCRC;
+ CMyComPtr<ISequentialInStream> inCrcStream = inSecCrcStreamSpec;
+
+ CMyComPtr<IInStream> inStream2;
+ if (!seqMode)
inStream->QueryInterface(IID_IInStream, (void **)&inStream2);
- if (inStream2)
- {
- inCrcStreamSpec = new CInStreamWithCRC;
- inCrcStream = inCrcStreamSpec;
- inCrcStreamSpec->SetStream(inStream2);
- inCrcStreamSpec->Init();
- }
- else
- {
- // we don't support stdin, since stream from stdin can require 64-bit size header
- return E_NOTIMPL;
- /*
- inSecCrcStreamSpec = new CSequentialInStreamWithCRC;
- inCrcStream = inSecCrcStreamSpec;
- inSecCrcStreamSpec->SetStream(inStream);
- inSecCrcStreamSpec->Init();
- */
- }
- }
+ inSecCrcStreamSpec->SetStream(inStream);
+ inSecCrcStreamSpec->Init();
unsigned numTestMethods = _options.MethodSequence.Size();
- if (numTestMethods > 1 && !inCrcStreamSpec)
+ if (seqMode || (numTestMethods > 1 && !inStream2))
numTestMethods = 1;
UInt32 crc = 0;
@@ -164,20 +218,24 @@ HRESULT CAddCommon::Compress(
Byte method = 0;
CFilterCoder::C_OutStream_Releaser outStreamReleaser;
- opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default;
+ opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;
opRes.FileTimeWasUsed = false;
for (unsigned i = 0; i < numTestMethods; i++)
{
- opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Default;
- if (inCrcStreamSpec)
- RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
+ opRes.LzmaEos = false;
+ opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;
+ if (inStream2 && i != 0)
+ {
+ inSecCrcStreamSpec->Init();
+ RINOK(inStream2->Seek(0, STREAM_SEEK_SET, NULL));
+ }
RINOK(outStream->SetSize(0));
RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL));
if (_options.PasswordIsDefined)
{
- opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_ZipCrypto;
+ opRes.ExtractVersion = NCompressionMethod::kExtractVersion_ZipCrypto;
if (!_cryptoStream)
{
@@ -187,7 +245,7 @@ HRESULT CAddCommon::Compress(
if (_options.IsAesMode)
{
- opRes.ExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_Aes;
+ opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Aes;
if (!_cryptoStreamSpec->Filter)
{
_cryptoStreamSpec->Filter = _filterAesSpec = new NCrypto::NWzAes::CEncoder;
@@ -206,23 +264,22 @@ HRESULT CAddCommon::Compress(
UInt32 check;
- // if (inCrcStreamSpec)
+ if (inStream2)
{
if (!crc_IsCalculated)
{
RINOK(CalcStreamCRC(inStream, crc));
crc_IsCalculated = true;
- RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL));
+ RINOK(inStream2->Seek(0, STREAM_SEEK_SET, NULL));
+ inSecCrcStreamSpec->Init();
}
check = (crc >> 16);
}
- /*
else
{
opRes.FileTimeWasUsed = true;
check = (fileTime & 0xFFFF);
}
- */
RINOK(_filterSpec->WriteHeader_Check16(outStream, (UInt16)check));
}
@@ -236,7 +293,7 @@ HRESULT CAddCommon::Compress(
switch (method)
{
- case NFileHeader::NCompressionMethod::kStored:
+ case NCompressionMethod::kStore:
{
if (_copyCoderSpec == NULL)
{
@@ -256,15 +313,22 @@ HRESULT CAddCommon::Compress(
{
if (!_compressEncoder)
{
- if (method == NFileHeader::NCompressionMethod::kLZMA)
+ CLzmaEncoder *_lzmaEncoder = NULL;
+ if (method == NCompressionMethod::kLZMA)
{
- _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_LZMA;
- CLzmaEncoder *_lzmaEncoder = new CLzmaEncoder();
+ _compressExtractVersion = NCompressionMethod::kExtractVersion_LZMA;
+ _lzmaEncoder = new CLzmaEncoder();
_compressEncoder = _lzmaEncoder;
}
- else if (method == NFileHeader::NCompressionMethod::kPPMd)
+ else if (method == NCompressionMethod::kXz)
+ {
+ _compressExtractVersion = NCompressionMethod::kExtractVersion_Xz;
+ NCompress::NXz::CEncoder *encoder = new NCompress::NXz::CEncoder();
+ _compressEncoder = encoder;
+ }
+ else if (method == NCompressionMethod::kPPMd)
{
- _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_PPMd;
+ _compressExtractVersion = NCompressionMethod::kExtractVersion_PPMd;
NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder();
_compressEncoder = encoder;
}
@@ -273,14 +337,14 @@ HRESULT CAddCommon::Compress(
CMethodId methodId;
switch (method)
{
- case NFileHeader::NCompressionMethod::kBZip2:
+ case NCompressionMethod::kBZip2:
methodId = kMethodId_BZip2;
- _compressExtractVersion = NFileHeader::NCompressionMethod::kExtractVersion_BZip2;
+ _compressExtractVersion = NCompressionMethod::kExtractVersion_BZip2;
break;
default:
- _compressExtractVersion = ((method == NFileHeader::NCompressionMethod::kDeflated64) ?
- NFileHeader::NCompressionMethod::kExtractVersion_Deflate64 :
- NFileHeader::NCompressionMethod::kExtractVersion_Deflate);
+ _compressExtractVersion = ((method == NCompressionMethod::kDeflate64) ?
+ NCompressionMethod::kExtractVersion_Deflate64 :
+ NCompressionMethod::kExtractVersion_Deflate);
methodId = kMethodId_ZipBase + method;
break;
}
@@ -290,11 +354,11 @@ HRESULT CAddCommon::Compress(
if (!_compressEncoder)
return E_NOTIMPL;
- if (method == NFileHeader::NCompressionMethod::kDeflated ||
- method == NFileHeader::NCompressionMethod::kDeflated64)
+ if (method == NCompressionMethod::kDeflate ||
+ method == NCompressionMethod::kDeflate64)
{
}
- else if (method == NFileHeader::NCompressionMethod::kBZip2)
+ else if (method == NCompressionMethod::kBZip2)
{
}
}
@@ -303,11 +367,22 @@ HRESULT CAddCommon::Compress(
_compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProps);
if (setCoderProps)
{
- RINOK(_options.MethodInfo.SetCoderProps(setCoderProps,
- _options._dataSizeReduceDefined ? &_options._dataSizeReduce : NULL));
+ if (!_options._methods.IsEmpty())
+ {
+ COneMethodInfo *oneMethodMain = &_options._methods[0];
+
+ RINOK(oneMethodMain->SetCoderProps(setCoderProps,
+ _options._dataSizeReduceDefined ? &_options._dataSizeReduce : NULL));
+ }
}
}
+ if (method == NCompressionMethod::kLZMA)
+ _isLzmaEos = _lzmaEncoder->EncoderSpec->IsWriteEndMark();
}
+
+ if (method == NCompressionMethod::kLZMA)
+ opRes.LzmaEos = _isLzmaEos;
+
CMyComPtr<ISequentialOutStream> outStreamNew;
if (_options.PasswordIsDefined)
outStreamNew = _cryptoStream;
@@ -332,18 +407,10 @@ HRESULT CAddCommon::Compress(
RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize));
- // if (inCrcStreamSpec)
- {
- opRes.CRC = inCrcStreamSpec->GetCRC();
- opRes.UnpackSize = inCrcStreamSpec->GetSize();
- }
- /*
- else
{
opRes.CRC = inSecCrcStreamSpec->GetCRC();
opRes.UnpackSize = inSecCrcStreamSpec->GetSize();
}
- */
if (_options.PasswordIsDefined)
{
diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.h b/CPP/7zip/Archive/Zip/ZipAddCommon.h
index 1e0c3bfa..ea5f8180 100644
--- a/CPP/7zip/Archive/Zip/ZipAddCommon.h
+++ b/CPP/7zip/Archive/Zip/ZipAddCommon.h
@@ -27,6 +27,7 @@ struct CCompressingResult
UInt16 Method;
Byte ExtractVersion;
bool FileTimeWasUsed;
+ bool LzmaEos;
};
class CAddCommon
@@ -37,6 +38,7 @@ class CAddCommon
CMyComPtr<ICompressCoder> _compressEncoder;
Byte _compressExtractVersion;
+ bool _isLzmaEos;
CFilterCoder *_cryptoStreamSpec;
CMyComPtr<ISequentialOutStream> _cryptoStream;
@@ -50,11 +52,14 @@ class CAddCommon
public:
CAddCommon(const CCompressionMethodMode &options);
~CAddCommon();
+
+ HRESULT Set_Pre_CompressionResult(bool seqMode, UInt64 unpackSize, CCompressingResult &opRes) const;
+
HRESULT Compress(
DECL_EXTERNAL_CODECS_LOC_VARS
ISequentialInStream *inStream, IOutStream *outStream,
- UInt32 fileTime,
- ICompressProgressInfo *progress, CCompressingResult &operationResult);
+ bool seqMode, UInt32 fileTime,
+ ICompressProgressInfo *progress, CCompressingResult &opRes);
};
}}
diff --git a/CPP/7zip/Archive/Zip/ZipCompressionMode.h b/CPP/7zip/Archive/Zip/ZipCompressionMode.h
index 86548d95..1125f6ed 100644
--- a/CPP/7zip/Archive/Zip/ZipCompressionMode.h
+++ b/CPP/7zip/Archive/Zip/ZipCompressionMode.h
@@ -14,26 +14,18 @@
namespace NArchive {
namespace NZip {
-struct CBaseProps
-{
- CMethodProps MethodInfo;
- Int32 Level;
+const CMethodId kMethodId_ZipBase = 0x040100;
+const CMethodId kMethodId_BZip2 = 0x040202;
- #ifndef _7ZIP_ST
- UInt32 NumThreads;
- bool NumThreadsWasChanged;
- #endif
+struct CBaseProps: public CMultiMethodProps
+{
bool IsAesMode;
Byte AesKeyMode;
void Init()
{
- MethodInfo.Clear();
- Level = -1;
- #ifndef _7ZIP_ST
- NumThreads = NWindows::NSystem::GetNumberOfProcessors();;
- NumThreadsWasChanged = false;
- #endif
+ CMultiMethodProps::Init();
+
IsAesMode = false;
AesKeyMode = 3;
}
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp
index 75034de0..75fad760 100644
--- a/CPP/7zip/Archive/Zip/ZipHandler.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp
@@ -3,10 +3,10 @@
#include "StdAfx.h"
#include "../../../Common/ComTry.h"
-#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
#include "../../../Windows/PropVariant.h"
+#include "../../../Windows/PropVariantUtils.h"
#include "../../../Windows/TimeUtils.h"
#include "../../IPassword.h"
@@ -22,6 +22,7 @@
#include "../../Compress/ImplodeDecoder.h"
#include "../../Compress/PpmdZip.h"
#include "../../Compress/ShrinkDecoder.h"
+#include "../../Compress/XzDecoder.h"
#include "../../Crypto/WzAes.h"
#include "../../Crypto/ZipCrypto.h"
@@ -30,7 +31,6 @@
#include "../Common/ItemNameUtils.h"
#include "../Common/OutStreamWithCRC.h"
-#include "../XzHandler.h"
#include "ZipHandler.h"
@@ -39,9 +39,6 @@ using namespace NWindows;
namespace NArchive {
namespace NZip {
-static const CMethodId kMethodId_ZipBase = 0x040100;
-static const CMethodId kMethodId_BZip2 = 0x040202;
-
static const char * const kHostOS[] =
{
"FAT"
@@ -66,24 +63,57 @@ static const char * const kHostOS[] =
, "OS/X"
};
-static const char * const kMethods[] =
+
+const char * const kMethodNames1[kNumMethodNames1] =
{
"Store"
, "Shrink"
- , "Reduced1"
- , "Reduced2"
- , "Reduced3"
- , "Reduced4"
+ , "Reduce1"
+ , "Reduce2"
+ , "Reduce3"
+ , "Reduce4"
, "Implode"
- , "Tokenizing"
+ , NULL // "Tokenize"
, "Deflate"
, "Deflate64"
, "PKImploding"
+ , NULL
+ , "BZip2"
+ , NULL
+ , "LZMA"
+};
+
+
+const char * const kMethodNames2[kNumMethodNames2] =
+{
+ "xz"
+ , "Jpeg"
+ , "WavPack"
+ , "PPMd"
+ , "WzAES"
};
-static const char *kMethod_AES = "AES";
-static const char *kMethod_ZipCrypto = "ZipCrypto";
-static const char *kMethod_StrongCrypto = "StrongCrypto";
+#define kMethod_AES "AES"
+#define kMethod_ZipCrypto "ZipCrypto"
+#define kMethod_StrongCrypto "StrongCrypto"
+
+static const char * const kDeflateLevels[4] =
+{
+ "Normal"
+ , "Maximum"
+ , "Fast"
+ , "Fastest"
+};
+
+
+static const CUInt32PCharPair g_HeaderCharacts[] =
+{
+ { 0, "Encrypt" },
+ { 3, "Descriptor" },
+ // { 5, "Patched" },
+ { 6, kMethod_StrongCrypto },
+ { 11, "UTF8" }
+};
struct CIdToNamePair
{
@@ -91,15 +121,6 @@ struct CIdToNamePair
const char *Name;
};
-static const CIdToNamePair k_MethodIdNamePairs[] =
-{
- { NFileHeader::NCompressionMethod::kBZip2, "BZip2" },
- { NFileHeader::NCompressionMethod::kLZMA, "LZMA" },
- { NFileHeader::NCompressionMethod::kXz, "xz" },
- { NFileHeader::NCompressionMethod::kJpeg, "Jpeg" },
- { NFileHeader::NCompressionMethod::kWavPack, "WavPack" },
- { NFileHeader::NCompressionMethod::kPPMd, "PPMd" }
-};
static const CIdToNamePair k_StrongCryptoPairs[] =
{
@@ -116,7 +137,7 @@ static const CIdToNamePair k_StrongCryptoPairs[] =
{ NStrongCrypto_AlgId::kRC4, "RC4" }
};
-const char *FindNameForId(const CIdToNamePair *pairs, unsigned num, unsigned id)
+static const char *FindNameForId(const CIdToNamePair *pairs, unsigned num, unsigned id)
{
for (unsigned i = 0; i < num; i++)
{
@@ -127,6 +148,7 @@ const char *FindNameForId(const CIdToNamePair *pairs, unsigned num, unsigned id)
return NULL;
}
+
static const Byte kProps[] =
{
kpidPath,
@@ -142,9 +164,11 @@ static const Byte kProps[] =
kpidComment,
kpidCRC,
kpidMethod,
+ kpidCharacts,
kpidHostOS,
kpidUnpackVer,
- kpidVolumeIndex
+ kpidVolumeIndex,
+ kpidOffset
};
static const Byte kArcProps[] =
@@ -152,6 +176,7 @@ static const Byte kArcProps[] =
kpidEmbeddedStubSize,
kpidBit64,
kpidComment,
+ kpidCharacts,
kpidTotalPhySize,
kpidIsVolume,
kpidVolumeIndex,
@@ -193,11 +218,34 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
break;
}
- case kpidTotalPhySize: if (m_Archive.IsMultiVol) prop = m_Archive.Vols.GetTotalSize(); break;
+ case kpidTotalPhySize: if (m_Archive.IsMultiVol) prop = m_Archive.Vols.TotalBytesSize; break;
case kpidVolumeIndex: if (m_Archive.IsMultiVol) prop = (UInt32)m_Archive.Vols.StartVolIndex; break;
case kpidIsVolume: if (m_Archive.IsMultiVol) prop = true; break;
case kpidNumVolumes: if (m_Archive.IsMultiVol) prop = (UInt32)m_Archive.Vols.Streams.Size(); break;
+ case kpidCharacts:
+ {
+ AString s;
+
+ if (m_Archive.LocalsWereRead)
+ {
+ s.Add_OptSpaced("Local");
+
+ if (m_Archive.LocalsCenterMerged)
+ s.Add_OptSpaced("Central");
+ }
+
+ if (m_Archive.IsZip64)
+ s.Add_OptSpaced("Zip64");
+
+ if (m_Archive.ExtraMinorError)
+ s.Add_OptSpaced("Minor_Extra_ERROR");
+
+ if (!s.IsEmpty())
+ prop = s;
+ break;
+ }
+
case kpidWarningFlags:
{
UInt32 v = 0;
@@ -208,12 +256,23 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
break;
}
+ case kpidWarning:
+ {
+ AString s;
+ if (m_Archive.Overflow32bit)
+ s.Add_OptSpaced("32-bit overflow in headers");
+ if (m_Archive.Cd_NumEntries_Overflow_16bit)
+ s.Add_OptSpaced("16-bit overflow for number of files in headers");
+ if (!s.IsEmpty())
+ prop = s;
+ break;
+ }
+
case kpidError:
{
if (!m_Archive.Vols.MissingName.IsEmpty())
{
- UString s;
- s.SetFromAscii("Missing volume : ");
+ UString s("Missing volume : ");
s += m_Archive.Vols.MissingName;
prop = s;
}
@@ -273,13 +332,19 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
UString res;
item.GetUnicodeString(res, item.Name, false, _forceCodePage, _specifiedCodePage);
- NItemName::ConvertToOSName2(res);
+ NItemName::ReplaceToOsSlashes_Remove_TailSlash(res);
prop = res;
break;
}
case kpidIsDir: prop = item.IsDir(); break;
- case kpidSize: prop = item.Size; break;
+ case kpidSize:
+ {
+ if (item.FromCentral || !item.FromLocal || !item.HasDescriptor() || item.DescriptorWasRead)
+ prop = item.Size;
+ break;
+ }
+
case kpidPackSize: prop = item.PackSize; break;
case kpidTimeType:
@@ -299,17 +364,36 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidCTime:
{
- FILETIME ft;
- if (extra.GetNtfsTime(NFileHeader::NNtfsExtra::kCTime, ft))
- prop = ft;
+ FILETIME utc;
+ bool defined = true;
+ if (!extra.GetNtfsTime(NFileHeader::NNtfsExtra::kCTime, utc))
+ {
+ UInt32 unixTime = 0;
+ if (extra.GetUnixTime(true, NFileHeader::NUnixTime::kCTime, unixTime))
+ NTime::UnixTimeToFileTime(unixTime, utc);
+ else
+ defined = false;
+ }
+ if (defined)
+ prop = utc;
break;
}
case kpidATime:
{
- FILETIME ft;
- if (extra.GetNtfsTime(NFileHeader::NNtfsExtra::kATime, ft))
- prop = ft;
+ FILETIME utc;
+ bool defined = true;
+ if (!extra.GetNtfsTime(NFileHeader::NNtfsExtra::kATime, utc))
+ {
+ UInt32 unixTime = 0;
+ if (extra.GetUnixTime(true, NFileHeader::NUnixTime::kATime, unixTime))
+ NTime::UnixTimeToFileTime(unixTime, utc);
+ else
+ defined = false;
+ }
+ if (defined)
+ prop = utc;
+
break;
}
@@ -375,10 +459,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
CWzAesExtra aesField;
if (extra.GetWzAes(aesField))
{
- char s[16];
- s[0] = '-';
- ConvertUInt32ToString(((unsigned)aesField.Strength + 1) * 64 , s + 1);
- m += s;
+ m += '-';
+ m.Add_UInt32(((unsigned)aesField.Strength + 1) * 64);
id = aesField.Method;
}
}
@@ -394,10 +476,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
else
{
m += kMethod_StrongCrypto;
- char temp[16];
- temp[0] = ':';
- ConvertUInt32ToString(f.AlgId, temp + 1);
- m += temp;
+ m += ':';
+ m.Add_UInt32(f.AlgId);
}
if (f.CertificateIsUsed())
m += "-Cert";
@@ -411,41 +491,96 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
}
{
- char temp[16];
const char *s = NULL;
- if (id < ARRAY_SIZE(kMethods))
- s = kMethods[id];
+ if (id < kNumMethodNames1)
+ s = kMethodNames1[id];
else
{
- s = FindNameForId(k_MethodIdNamePairs, ARRAY_SIZE(k_MethodIdNamePairs), id);
- if (!s)
+ int id2 = (int)id - (int)kMethodNames2Start;
+ if (id2 >= 0 && id2 < kNumMethodNames2)
+ s = kMethodNames2[id2];
+ }
+ if (s)
+ m += s;
+ else
+ m.Add_UInt32(id);
+ }
+ {
+ unsigned level = item.GetDeflateLevel();
+ if (level != 0)
+ {
+ if (id == NFileHeader::NCompressionMethod::kLZMA)
+ {
+ if (level & 1)
+ m += ":eos";
+ level &= ~1;
+ }
+ else if (id == NFileHeader::NCompressionMethod::kDeflate)
{
- ConvertUInt32ToString(id, temp);
- s = temp;
+ m += ':';
+ m += kDeflateLevels[level];
+ level = 0;
+ }
+
+ if (level != 0)
+ {
+ m += ":v";
+ m.Add_UInt32(level);
}
}
- m += s;
- if (id == NFileHeader::NCompressionMethod::kLZMA && item.IsLzmaEOS())
- m += ":EOS";
}
prop = m;
break;
}
- case kpidHostOS:
+ case kpidCharacts:
{
- Byte hostOS = item.GetHostOS();
- char temp[16];
- const char *s = NULL;
- if (hostOS < ARRAY_SIZE(kHostOS))
- s = kHostOS[hostOS];
- else
+ AString s;
+
+ if (item.FromLocal)
+ {
+ s.Add_OptSpaced("Local");
+
+ item.LocalExtra.PrintInfo(s);
+
+ if (item.FromCentral)
+ {
+ s.Add_OptSpaced(":");
+ s.Add_OptSpaced("Central");
+ }
+ }
+
+ if (item.FromCentral)
{
- ConvertUInt32ToString(hostOS, temp);
- s = temp;
+ item.CentralExtra.PrintInfo(s);
}
- prop = s;
+
+ UInt32 flags = item.Flags;
+ flags &= ~(6); // we don't need compression related bits here.
+
+ if (flags != 0)
+ {
+ AString s2 = FlagsToString(g_HeaderCharacts, ARRAY_SIZE(g_HeaderCharacts), flags);
+ if (!s2.IsEmpty())
+ {
+ s.Add_OptSpaced(":");
+ s.Add_OptSpaced(s2);
+ }
+ }
+
+ if (!item.FromCentral && item.FromLocal && item.HasDescriptor() && !item.DescriptorWasRead)
+ s.Add_OptSpaced("Descriptor_ERROR");
+
+ if (!s.IsEmpty())
+ prop = s;
+ break;
+ }
+
+ case kpidHostOS:
+ {
+ const Byte hostOS = item.GetHostOS();
+ TYPE_TO_PROP(kHostOS, hostOS, prop);
break;
}
@@ -456,6 +591,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidVolumeIndex:
prop = item.Disk;
break;
+
+ case kpidOffset:
+ prop = item.LocalHeaderPos;
+ break;
}
prop.Detach(value);
@@ -475,7 +614,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
if (res != S_OK)
{
m_Items.Clear();
- m_Archive.ClearRefs();
+ m_Archive.ClearRefs(); // we don't want to clear error flags
}
return res;
}
@@ -493,16 +632,24 @@ STDMETHODIMP CHandler::Close()
class CLzmaDecoder:
public ICompressCoder,
+ public ICompressSetFinishMode,
+ public ICompressGetInStreamProcessedSize,
public CMyUnknownImp
{
+public:
NCompress::NLzma::CDecoder *DecoderSpec;
CMyComPtr<ICompressCoder> Decoder;
-public:
- CLzmaDecoder();
+
+ MY_UNKNOWN_IMP2(
+ ICompressSetFinishMode,
+ ICompressGetInStreamProcessedSize)
+
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
+ STDMETHOD(SetFinishMode)(UInt32 finishMode);
+ STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
- MY_UNKNOWN_IMP
+ CLzmaDecoder();
};
CLzmaDecoder::CLzmaDecoder()
@@ -511,44 +658,45 @@ CLzmaDecoder::CLzmaDecoder()
Decoder = DecoderSpec;
}
+static const unsigned kZipLzmaPropsSize = 4 + LZMA_PROPS_SIZE;
+
HRESULT CLzmaDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
- const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
+ const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
{
- Byte buf[9];
- RINOK(ReadStream_FALSE(inStream, buf, 9));
- if (buf[2] != 5 || buf[3] != 0)
+ Byte buf[kZipLzmaPropsSize];
+ RINOK(ReadStream_FALSE(inStream, buf, kZipLzmaPropsSize));
+ if (buf[2] != LZMA_PROPS_SIZE || buf[3] != 0)
return E_NOTIMPL;
- RINOK(DecoderSpec->SetDecoderProperties2(buf + 4, 5));
- return Decoder->Code(inStream, outStream, NULL, outSize, progress);
+ RINOK(DecoderSpec->SetDecoderProperties2(buf + 4, LZMA_PROPS_SIZE));
+ UInt64 inSize2 = 0;
+ if (inSize)
+ {
+ inSize2 = *inSize;
+ if (inSize2 < kZipLzmaPropsSize)
+ return S_FALSE;
+ inSize2 -= kZipLzmaPropsSize;
+ }
+ return Decoder->Code(inStream, outStream, inSize ? &inSize2 : NULL, outSize, progress);
}
-
-class CXzDecoder:
- public ICompressCoder,
- public CMyUnknownImp
+STDMETHODIMP CLzmaDecoder::SetFinishMode(UInt32 finishMode)
{
- NArchive::NXz::CDecoder _decoder;
-public:
-
- STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
- const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
-
- MY_UNKNOWN_IMP
-};
+ DecoderSpec->FinishStream = (finishMode != 0);
+ return S_OK;
+}
-HRESULT CXzDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
- const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
+STDMETHODIMP CLzmaDecoder::GetInStreamProcessedSize(UInt64 *value)
{
- RINOK(_decoder.Decode(inStream, outStream, progress));
- Int32 opRes = _decoder.Get_Extract_OperationResult();
- if (opRes == NExtract::NOperationResult::kUnsupportedMethod)
- return E_NOTIMPL;
- if (opRes != NExtract::NOperationResult::kOK)
- return S_FALSE;
+ *value = DecoderSpec->GetInputProcessedSize() + kZipLzmaPropsSize;
return S_OK;
}
+
+
+
+
+
struct CMethodItem
{
unsigned ZipMethod;
@@ -572,12 +720,15 @@ class CZipDecoder
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
CObjectVector<CMethodItem> methodItems;
+ CLzmaDecoder *lzmaDecoderSpec;
public:
CZipDecoder():
_zipCryptoDecoderSpec(0),
_pkAesDecoderSpec(0),
_wzAesDecoderSpec(0),
- filterStreamSpec(0) {}
+ filterStreamSpec(0),
+ lzmaDecoderSpec(0)
+ {}
HRESULT Decode(
DECL_EXTERNAL_CODECS_LOC_VARS
@@ -592,19 +743,18 @@ public:
};
-static HRESULT SkipStreamData(ISequentialInStream *stream, UInt64 size)
+static HRESULT SkipStreamData(ISequentialInStream *stream, bool &thereAreData)
{
+ thereAreData = false;
const size_t kBufSize = 1 << 12;
Byte buf[kBufSize];
for (;;)
{
+ size_t size = kBufSize;
+ RINOK(ReadStream(stream, buf, &size));
if (size == 0)
return S_OK;
- size_t curSize = kBufSize;
- if (curSize > size)
- curSize = (size_t)size;
- RINOK(ReadStream_FALSE(stream, buf, curSize));
- size -= curSize;
+ thereAreData = true;
}
}
@@ -620,12 +770,15 @@ HRESULT CZipDecoder::Decode(
#endif
Int32 &res)
{
- res = NExtract::NOperationResult::kDataError;
+ res = NExtract::NOperationResult::kHeadersError;
+
CFilterCoder::C_InStream_Releaser inStreamReleaser;
+ CFilterCoder::C_Filter_Releaser filterReleaser;
bool needCRC = true;
bool wzAesMode = false;
bool pkAesMode = false;
+
unsigned id = item.Method;
if (item.IsEncrypted())
@@ -633,27 +786,23 @@ HRESULT CZipDecoder::Decode(
if (item.IsStrongEncrypted())
{
CStrongCryptoExtra f;
- if (item.CentralExtra.GetStrongCrypto(f))
- {
- pkAesMode = true;
- }
- if (!pkAesMode)
+ if (!item.CentralExtra.GetStrongCrypto(f))
{
res = NExtract::NOperationResult::kUnsupportedMethod;
return S_OK;
}
+ pkAesMode = true;
}
- if (!pkAesMode && id == NFileHeader::NCompressionMethod::kWzAES)
+ else if (id == NFileHeader::NCompressionMethod::kWzAES)
{
CWzAesExtra aesField;
- if (item.GetMainExtra().GetWzAes(aesField))
- {
- wzAesMode = true;
- needCRC = aesField.NeedCrc();
- }
+ if (!item.GetMainExtra().GetWzAes(aesField))
+ return S_OK;
+ wzAesMode = true;
+ needCRC = aesField.NeedCrc();
}
}
-
+
COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
outStreamSpec->SetStream(realOutStream);
@@ -681,6 +830,9 @@ HRESULT CZipDecoder::Decode(
limitedStreamSpec->SetStream(packStream);
limitedStreamSpec->Init(packSize);
}
+
+
+ res = NExtract::NOperationResult::kDataError;
CMyComPtr<ICompressFilter> cryptoFilter;
@@ -725,6 +877,8 @@ HRESULT CZipDecoder::Decode(
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
RINOK(cryptoFilter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
+ if (!cryptoSetPassword)
+ return E_FAIL;
if (!getTextPassword)
extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);
@@ -736,39 +890,35 @@ HRESULT CZipDecoder::Decode(
AString charPassword;
if (password)
{
+ UnicodeStringToMultiByte2(charPassword, (const wchar_t *)password, CP_ACP);
+ /*
if (wzAesMode || pkAesMode)
{
- charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_ACP);
- /*
- for (unsigned i = 0;; i++)
- {
- wchar_t c = password[i];
- if (c == 0)
- break;
- if (c >= 0x80)
- {
- res = NExtract::NOperationResult::kDataError;
- return S_OK;
- }
- charPassword += (char)c;
- }
- */
}
else
{
- /* pkzip25 / WinZip / Windows probably use ANSI for some files
- We use OEM for compatibility with previous versions of 7-Zip? */
- charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP);
+ // PASSWORD encoding for ZipCrypto:
+ // pkzip25 / WinZip / Windows probably use ANSI
+ // 7-Zip < 4.43 creates ZIP archives with OEM encoding in password
+ // 7-Zip >= 4.43 creates ZIP archives only with ASCII characters in password
+ // 7-Zip < 17.00 uses CP_OEMCP for password decoding
+ // 7-Zip >= 17.00 uses CP_ACP for password decoding
}
+ */
}
HRESULT result = cryptoSetPassword->CryptoSetPassword(
(const Byte *)(const char *)charPassword, charPassword.Len());
if (result != S_OK)
+ {
+ res = NExtract::NOperationResult::kWrongPassword;
return S_OK;
+ }
}
else
{
- RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
+ res = NExtract::NOperationResult::kWrongPassword;
+ return S_OK;
+ // RINOK(cryptoSetPassword->CryptoSetPassword(NULL, 0));
}
}
@@ -781,16 +931,19 @@ HRESULT CZipDecoder::Decode(
{
CMethodItem mi;
mi.ZipMethod = id;
- if (id == NFileHeader::NCompressionMethod::kStored)
+ if (id == NFileHeader::NCompressionMethod::kStore)
mi.Coder = new NCompress::CCopyCoder;
- else if (id == NFileHeader::NCompressionMethod::kShrunk)
+ else if (id == NFileHeader::NCompressionMethod::kShrink)
mi.Coder = new NCompress::NShrink::CDecoder;
- else if (id == NFileHeader::NCompressionMethod::kImploded)
+ else if (id == NFileHeader::NCompressionMethod::kImplode)
mi.Coder = new NCompress::NImplode::NDecoder::CCoder;
else if (id == NFileHeader::NCompressionMethod::kLZMA)
- mi.Coder = new CLzmaDecoder;
+ {
+ lzmaDecoderSpec = new CLzmaDecoder;
+ mi.Coder = lzmaDecoderSpec;
+ }
else if (id == NFileHeader::NCompressionMethod::kXz)
- mi.Coder = new CXzDecoder;
+ mi.Coder = new NCompress::NXz::CComDecoder;
else if (id == NFileHeader::NCompressionMethod::kPPMd)
mi.Coder = new NCompress::NPpmdZip::CDecoder(true);
else
@@ -810,7 +963,7 @@ HRESULT CZipDecoder::Decode(
RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS szMethodID, false, mi.Coder));
- if (mi.Coder == 0)
+ if (!mi.Coder)
{
res = NExtract::NOperationResult::kUnsupportedMethod;
return S_OK;
@@ -842,9 +995,17 @@ HRESULT CZipDecoder::Decode(
}
#endif
+ CMyComPtr<ISequentialInStream> inStreamNew;
+
+ bool isFullStreamExpected = (!item.HasDescriptor() || item.PackSize != 0);
+ bool needReminderCheck = false;
+
+ bool dataAfterEnd = false;
+ bool truncatedError = false;
+ bool lzmaEosError = false;
+
{
HRESULT result = S_OK;
- CMyComPtr<ISequentialInStream> inStreamNew;
if (item.IsEncrypted())
{
if (!filterStream)
@@ -853,6 +1014,7 @@ HRESULT CZipDecoder::Decode(
filterStream = filterStreamSpec;
}
+ filterReleaser.FilterCoder = filterStreamSpec;
filterStreamSpec->Filter = cryptoFilter;
if (wzAesMode)
@@ -869,6 +1031,7 @@ HRESULT CZipDecoder::Decode(
}
else if (pkAesMode)
{
+ isFullStreamExpected = false;
result =_pkAesDecoderSpec->ReadHeader(inStream, item.Crc, item.Size);
if (result == S_OK)
{
@@ -926,7 +1089,70 @@ HRESULT CZipDecoder::Decode(
inStreamNew = inStream;
if (result == S_OK)
- result = coder->Code(inStreamNew, outStream, NULL, &item.Size, compressProgress);
+ {
+ CMyComPtr<ICompressSetFinishMode> setFinishMode;
+ coder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);
+ if (setFinishMode)
+ {
+ RINOK(setFinishMode->SetFinishMode(BoolToInt(true)));
+ }
+
+ const UInt64 coderPackSize = limitedStreamSpec->GetRem();
+
+ bool useUnpackLimit = (id == 0
+ || !item.HasDescriptor()
+ || item.Size >= ((UInt64)1 << 32)
+ || item.LocalExtra.IsZip64
+ || item.CentralExtra.IsZip64
+ );
+
+ result = coder->Code(inStreamNew, outStream,
+ isFullStreamExpected ? &coderPackSize : NULL,
+ // NULL,
+ useUnpackLimit ? &item.Size : NULL,
+ compressProgress);
+
+ if (result == S_OK)
+ {
+ CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize;
+ coder->QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize);
+ if (getInStreamProcessedSize && setFinishMode)
+ {
+ UInt64 processed;
+ RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&processed));
+ if (processed != (UInt64)(Int64)-1)
+ {
+ if (pkAesMode)
+ {
+ const UInt32 padSize = _pkAesDecoderSpec->GetPadSize((UInt32)processed);
+ if (processed + padSize > coderPackSize)
+ truncatedError = true;
+ else
+ {
+ if (processed + padSize < coderPackSize)
+ dataAfterEnd = true;
+ // also here we can check PKCS7 padding data from reminder (it can be inside stream buffer in coder).
+ }
+ }
+ else
+ {
+ if (processed < coderPackSize)
+ {
+ if (isFullStreamExpected)
+ dataAfterEnd = true;
+ }
+ else if (processed > coderPackSize)
+ truncatedError = true;
+ needReminderCheck = isFullStreamExpected;
+ }
+ }
+ }
+ }
+
+ if (result == S_OK && id == NFileHeader::NCompressionMethod::kLZMA)
+ if (!lzmaDecoderSpec->DecoderSpec->CheckFinishStatus(item.IsLzmaEOS()))
+ lzmaEosError = true;
+ }
if (result == S_FALSE)
return S_OK;
@@ -947,19 +1173,40 @@ HRESULT CZipDecoder::Decode(
if (wzAesMode)
{
- const UInt64 rem = limitedStreamSpec->GetRem();
- if (rem != 0)
- if (SkipStreamData(inStream, rem) != S_OK)
- authOk = false;
+ bool thereAreData = false;
+ if (SkipStreamData(inStreamNew, thereAreData) != S_OK)
+ authOk = false;
+ if (needReminderCheck && thereAreData)
+ dataAfterEnd = true;
+
limitedStreamSpec->Init(NCrypto::NWzAes::kMacSize);
if (_wzAesDecoderSpec->CheckMac(inStream, authOk) != S_OK)
authOk = false;
}
-
- res = ((crcOK && authOk) ?
- NExtract::NOperationResult::kOK :
- NExtract::NOperationResult::kCRCError);
+
+ res = NExtract::NOperationResult::kCRCError;
+
+ if (crcOK && authOk)
+ {
+ res = NExtract::NOperationResult::kOK;
+
+ if (dataAfterEnd)
+ res = NExtract::NOperationResult::kDataAfterEnd;
+ else if (truncatedError)
+ res = NExtract::NOperationResult::kUnexpectedEnd;
+ else if (lzmaEosError)
+ res = NExtract::NOperationResult::kHeadersError;
+
+ // CheckDescriptor() supports only data descriptor with signature and
+ // it doesn't support "old" pkzip's data descriptor without signature.
+ // So we disable that check.
+ /*
+ if (item.HasDescriptor() && archive.CheckDescriptor(item) != S_OK)
+ res = NExtract::NOperationResult::kHeadersError;
+ */
+ }
+
return S_OK;
}
@@ -1026,11 +1273,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnavailable));
continue;
}
+
+ bool headersError = false;
if (!item.FromLocal)
{
bool isAvail = true;
- HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item, isAvail);
+ HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item, isAvail, headersError);
if (res == S_FALSE)
{
if (item.IsDir() || realOutStream || testMode)
@@ -1069,12 +1318,16 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
m_Archive, item, realOutStream, extractCallback,
progress,
#ifndef _7ZIP_ST
- _props.NumThreads,
+ _props._numThreads,
#endif
res);
+
RINOK(hres);
realOutStream.Release();
+ if (res == NExtract::NOperationResult::kOK && headersError)
+ res = NExtract::NOperationResult::kHeadersError;
+
RINOK(extractCallback->SetOperationResult(res))
}
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h
index c2a362a7..53e6a460 100644
--- a/CPP/7zip/Archive/Zip/ZipHandler.h
+++ b/CPP/7zip/Archive/Zip/ZipHandler.h
@@ -9,12 +9,20 @@
#include "../../Common/CreateCoder.h"
-#include "ZipIn.h"
#include "ZipCompressionMode.h"
+#include "ZipIn.h"
namespace NArchive {
namespace NZip {
+const unsigned kNumMethodNames1 = NFileHeader::NCompressionMethod::kLZMA + 1;
+const unsigned kMethodNames2Start = NFileHeader::NCompressionMethod::kXz;
+const unsigned kNumMethodNames2 = NFileHeader::NCompressionMethod::kWzAES + 1 - kMethodNames2Start;
+
+extern const char * const kMethodNames1[kNumMethodNames1];
+extern const char * const kMethodNames2[kNumMethodNames2];
+
+
class CHandler:
public IInArchive,
public IOutArchive,
diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
index 8a8de511..8ecf7942 100644
--- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
@@ -46,6 +46,30 @@ static bool IsSimpleAsciiString(const wchar_t *s)
}
}
+
+static int FindZipMethod(const char *s, const char * const *names, unsigned num)
+{
+ for (unsigned i = 0; i < num; i++)
+ {
+ const char *name = names[i];
+ if (name && StringsAreEqualNoCase_Ascii(s, name))
+ return i;
+ }
+ return -1;
+}
+
+static int FindZipMethod(const char *s)
+{
+ int k = FindZipMethod(s, kMethodNames1, kNumMethodNames1);
+ if (k >= 0)
+ return k;
+ k = FindZipMethod(s, kMethodNames2, kNumMethodNames2);
+ if (k >= 0)
+ return kMethodNames2Start + k;
+ return -1;
+}
+
+
#define COM_TRY_BEGIN2 try {
#define COM_TRY_END2 } \
catch(const CSystemException &e) { return e.ErrorCode; } \
@@ -63,6 +87,7 @@ static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propI
return S_OK;
}
+
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
IArchiveUpdateCallback *callback)
{
@@ -75,31 +100,46 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
}
CObjectVector<CUpdateItem> updateItems;
+ updateItems.ClearAndReserve(numItems);
+
bool thereAreAesUpdates = false;
UInt64 largestSize = 0;
bool largestSizeDefined = false;
+ UString name;
+ CUpdateItem ui;
+
for (UInt32 i = 0; i < numItems; i++)
{
- CUpdateItem ui;
Int32 newData;
Int32 newProps;
- UInt32 indexInArchive;
+ UInt32 indexInArc;
+
if (!callback)
return E_FAIL;
- RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
+
+ RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArc));
+
+ name.Empty();
+ ui.Clear();
+
ui.NewProps = IntToBool(newProps);
ui.NewData = IntToBool(newData);
- ui.IndexInArc = indexInArchive;
+ ui.IndexInArc = indexInArc;
ui.IndexInClient = i;
- bool existInArchive = (indexInArchive != (UInt32)(Int32)-1);
- if (existInArchive && newData)
- if (m_Items[indexInArchive].IsAesEncrypted())
+
+ bool existInArchive = (indexInArc != (UInt32)(Int32)-1);
+ if (existInArchive)
+ {
+ const CItemEx &inputItem = m_Items[indexInArc];
+ if (inputItem.IsAesEncrypted())
thereAreAesUpdates = true;
+ if (!IntToBool(newProps))
+ ui.IsDir = inputItem.IsDir();
+ }
if (IntToBool(newProps))
{
- UString name;
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidAttrib, &prop));
@@ -115,12 +155,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidPath, &prop));
if (prop.vt == VT_EMPTY)
- name.Empty();
+ {
+ // name.Empty();
+ }
else if (prop.vt != VT_BSTR)
return E_INVALIDARG;
else
name = prop.bstrVal;
}
+
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidIsDir, &prop));
@@ -153,7 +196,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
FileTimeToDosTime(localFileTime, ui.Time);
}
- name = NItemName::MakeLegalName(name);
+ NItemName::ReplaceSlashes_OsToUnix(name);
+
bool needSlash = ui.IsDir;
const wchar_t kSlash = L'/';
if (!name.IsEmpty())
@@ -188,11 +232,37 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
if (ui.Name.Len() >= (1 << 16))
return E_INVALIDARG;
- ui.IndexInClient = i;
+ {
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidComment, &prop));
+ if (prop.vt == VT_EMPTY)
+ {
+ // ui.Comment.Free();
+ }
+ else if (prop.vt != VT_BSTR)
+ return E_INVALIDARG;
+ else
+ {
+ UString s = prop.bstrVal;
+ AString a;
+ if (ui.IsUtf8)
+ ConvertUnicodeToUTF8(s, a);
+ else
+ {
+ bool defaultCharWasUsed;
+ a = UnicodeStringToMultiByte(s, codePage, '_', defaultCharWasUsed);
+ }
+ if (a.Len() >= (1 << 16))
+ return E_INVALIDARG;
+ ui.Comment.CopyFrom((const Byte *)(const char *)a, a.Len());
+ }
+ }
+
+
/*
if (existInArchive)
{
- const CItemEx &itemInfo = m_Items[indexInArchive];
+ const CItemEx &itemInfo = m_Items[indexInArc];
// ui.Commented = itemInfo.IsCommented();
ui.Commented = false;
if (ui.Commented)
@@ -205,6 +275,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
ui.Commented = false;
*/
}
+
+
if (IntToBool(newData))
{
UInt64 size = 0;
@@ -220,12 +292,12 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
largestSizeDefined = true;
}
ui.Size = size;
-
- // ui.Size -= ui.Size / 2;
}
+
updateItems.Add(ui);
}
+
CMyComPtr<ICryptoGetTextPassword2> getTextPassword;
{
CMyComPtr<IArchiveUpdateCallback> udateCallBack2(callback);
@@ -261,16 +333,52 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
}
}
- Byte mainMethod;
- if (m_MainMethod < 0)
- mainMethod = (Byte)(((_props.Level == 0) ?
- NFileHeader::NCompressionMethod::kStored :
- NFileHeader::NCompressionMethod::kDeflated));
+
+ int mainMethod = m_MainMethod;
+
+ if (mainMethod < 0)
+ {
+ if (!_props._methods.IsEmpty())
+ {
+ const AString &methodName = _props._methods.Front().MethodName;
+ if (!methodName.IsEmpty())
+ {
+ mainMethod = FindZipMethod(methodName);
+ if (mainMethod < 0)
+ {
+ CMethodId methodId;
+ UInt32 numStreams;
+ if (!FindMethod(EXTERNAL_CODECS_VARS methodName, methodId, numStreams))
+ return E_NOTIMPL;
+ if (numStreams != 1)
+ return E_NOTIMPL;
+ if (methodId == kMethodId_BZip2)
+ mainMethod = NFileHeader::NCompressionMethod::kBZip2;
+ else
+ {
+ if (methodId < kMethodId_ZipBase)
+ return E_NOTIMPL;
+ methodId -= kMethodId_ZipBase;
+ if (methodId > 0xFF)
+ return E_NOTIMPL;
+ mainMethod = (int)methodId;
+ }
+ }
+ }
+ }
+ }
+
+ if (mainMethod < 0)
+ mainMethod = (Byte)(((_props.GetLevel() == 0) ?
+ NFileHeader::NCompressionMethod::kStore :
+ NFileHeader::NCompressionMethod::kDeflate));
else
- mainMethod = (Byte)m_MainMethod;
- options.MethodSequence.Add(mainMethod);
- if (mainMethod != NFileHeader::NCompressionMethod::kStored)
- options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStored);
+ mainMethod = (Byte)mainMethod;
+
+ options.MethodSequence.Add((Byte)mainMethod);
+
+ if (mainMethod != NFileHeader::NCompressionMethod::kStore)
+ options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStore);
return Update(
EXTERNAL_CODECS_VARS
@@ -281,28 +389,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
COM_TRY_END2
}
-struct CMethodIndexToName
-{
- unsigned Method;
- const char *Name;
-};
-static const CMethodIndexToName k_SupportedMethods[] =
-{
- { NFileHeader::NCompressionMethod::kStored, "copy" },
- { NFileHeader::NCompressionMethod::kDeflated, "deflate" },
- { NFileHeader::NCompressionMethod::kDeflated64, "deflate64" },
- { NFileHeader::NCompressionMethod::kBZip2, "bzip2" },
- { NFileHeader::NCompressionMethod::kLZMA, "lzma" },
- { NFileHeader::NCompressionMethod::kPPMd, "ppmd" }
-};
STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
InitMethodProps();
- #ifndef _7ZIP_ST
- const UInt32 numProcessors = _props.NumThreads;
- #endif
for (UInt32 i = 0; i < numProps; i++)
{
@@ -313,82 +404,27 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
const PROPVARIANT &prop = values[i];
- if (name[0] == L'x')
- {
- UInt32 level = 9;
- RINOK(ParsePropToUInt32(name.Ptr(1), prop, level));
- _props.Level = level;
- _props.MethodInfo.AddProp_Level(level);
- }
- else if (name == L"m")
- {
- if (prop.vt == VT_BSTR)
- {
- UString m = prop.bstrVal, m2;
- m.MakeLower_Ascii();
- int colonPos = m.Find(L':');
- if (colonPos >= 0)
- {
- m2 = m.Ptr(colonPos + 1);
- m.DeleteFrom(colonPos);
- }
- unsigned k;
- for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++)
- {
- const CMethodIndexToName &pair = k_SupportedMethods[k];
- if (m.IsEqualTo(pair.Name))
- {
- if (!m2.IsEmpty())
- {
- RINOK(_props.MethodInfo.ParseParamsFromString(m2));
- }
- m_MainMethod = pair.Method;
- break;
- }
- }
- if (k == ARRAY_SIZE(k_SupportedMethods))
- return E_INVALIDARG;
- }
- else if (prop.vt == VT_UI4)
- {
- unsigned k;
- for (k = 0; k < ARRAY_SIZE(k_SupportedMethods); k++)
- {
- unsigned method = k_SupportedMethods[k].Method;
- if (prop.ulVal == method)
- {
- m_MainMethod = method;
- break;
- }
- }
- if (k == ARRAY_SIZE(k_SupportedMethods))
- return E_INVALIDARG;
- }
- else
- return E_INVALIDARG;
- }
- else if (name.IsPrefixedBy(L"em"))
+ if (name.IsEqualTo_Ascii_NoCase("em"))
{
if (prop.vt != VT_BSTR)
return E_INVALIDARG;
{
- UString m = prop.bstrVal;
- m.MakeLower_Ascii();
- if (m.IsPrefixedBy(L"aes"))
+ const wchar_t *m = prop.bstrVal;
+ if (IsString1PrefixedByString2_NoCase_Ascii(m, "aes"))
{
- m.DeleteFrontal(3);
- if (m == L"128")
+ m += 3;
+ if (StringsAreEqual_Ascii(m, "128"))
_props.AesKeyMode = 1;
- else if (m == L"192")
+ else if (StringsAreEqual_Ascii(m, "192"))
_props.AesKeyMode = 2;
- else if (m == L"256" || m.IsEmpty())
+ else if (StringsAreEqual_Ascii(m, "256") || m[0] == 0)
_props.AesKeyMode = 3;
else
return E_INVALIDARG;
_props.IsAesMode = true;
m_ForceAesMode = true;
}
- else if (m == L"zipcrypto")
+ else if (StringsAreEqualNoCase_Ascii(m, "ZipCrypto"))
{
_props.IsAesMode = false;
m_ForceAesMode = true;
@@ -397,13 +433,6 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
return E_INVALIDARG;
}
}
- else if (name.IsPrefixedBy(L"mt"))
- {
- #ifndef _7ZIP_ST
- RINOK(ParseMtProp(name.Ptr(2), prop, numProcessors, _props.NumThreads));
- _props.NumThreadsWasChanged = true;
- #endif
- }
else if (name.IsEqualTo("tc"))
{
RINOK(PROPVARIANT_to_bool(prop, m_WriteNtfsTimeExtra));
@@ -433,9 +462,39 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVAR
}
else
{
- RINOK(_props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop));
+ if (name.IsEqualTo_Ascii_NoCase("m") && prop.vt == VT_UI4)
+ {
+ UInt32 id = prop.ulVal;
+ if (id > 0xFF)
+ return E_INVALIDARG;
+ m_MainMethod = id;
+ }
+ else
+ {
+ RINOK(_props.SetProperty(name, prop));
+ }
+ // RINOK(_props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop));
}
}
+
+ _props._methods.DeleteFrontal(_props.GetNumEmptyMethods());
+ if (_props._methods.Size() > 1)
+ return E_INVALIDARG;
+ if (_props._methods.Size() == 1)
+ {
+ const AString &methodName = _props._methods[0].MethodName;
+
+ if (!methodName.IsEmpty())
+ {
+ const char *end;
+ UInt32 id = ConvertStringToUInt32(methodName, &end);
+ if (*end == 0 && id <= 0xFF)
+ m_MainMethod = id;
+ else if (methodName.IsEqualTo_Ascii_NoCase("Copy")) // it's alias for "Store"
+ m_MainMethod = 0;
+ }
+ }
+
return S_OK;
}
diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h
index fead0192..61b4ea4b 100644
--- a/CPP/7zip/Archive/Zip/ZipHeader.h
+++ b/CPP/7zip/Archive/Zip/ZipHeader.h
@@ -23,7 +23,8 @@ namespace NSignature
}
const unsigned kLocalHeaderSize = 4 + 26; // including signature
-const unsigned kDataDescriptorSize = 4 + 12; // including signature
+const unsigned kDataDescriptorSize32 = 4 + 4 + 4 * 2; // including signature
+const unsigned kDataDescriptorSize64 = 4 + 4 + 8 * 2; // including signature
const unsigned kCentralHeaderSize = 4 + 42; // including signature
const unsigned kEcdSize = 22; // including signature
@@ -37,28 +38,30 @@ namespace NFileHeader
{
enum EType
{
- kStored = 0,
- kShrunk = 1,
- kReduced1 = 2,
- kReduced2 = 3,
- kReduced3 = 4,
- kReduced4 = 5,
- kImploded = 6,
- kReservedTokenizing = 7, // reserved for tokenizing
- kDeflated = 8,
- kDeflated64 = 9,
+ kStore = 0,
+ kShrink = 1,
+ kReduce1 = 2,
+ kReduce2 = 3,
+ kReduce3 = 4,
+ kReduce4 = 5,
+ kImplode = 6,
+ kTokenize = 7,
+ kDeflate = 8,
+ kDeflate64 = 9,
kPKImploding = 10,
kBZip2 = 12,
+
kLZMA = 14,
+
kTerse = 18,
kLz77 = 19,
- kXz = 0x5F,
- kJpeg = 0x60,
- kWavPack = 0x61,
- kPPMd = 0x62,
- kWzAES = 0x63
+ kXz = 95,
+ kJpeg = 96,
+ kWavPack = 97,
+ kPPMd = 98,
+ kWzAES = 99
};
const Byte kMadeByProgramVersion = 63;
@@ -73,6 +76,7 @@ namespace NFileHeader
const Byte kExtractVersion_Aes = 51;
const Byte kExtractVersion_LZMA = 63;
const Byte kExtractVersion_PPMd = 63;
+ const Byte kExtractVersion_Xz = 20; // test it
}
namespace NExtraID
@@ -83,6 +87,7 @@ namespace NFileHeader
kNTFS = 0x0A,
kStrongEncrypt = 0x17,
kUnixTime = 0x5455,
+ kUnixExtra = 0x5855,
kIzUnicodeComment = 0x6375,
kIzUnicodeName = 0x7075,
kWzAES = 0x9901
@@ -110,6 +115,15 @@ namespace NFileHeader
};
}
+ namespace NUnixExtra
+ {
+ enum
+ {
+ kATime = 0,
+ kMTime
+ };
+ }
+
namespace NFlags
{
const unsigned kEncrypted = 1 << 0;
@@ -121,10 +135,12 @@ namespace NFileHeader
const unsigned kImplodeDictionarySizeMask = 1 << 1;
const unsigned kImplodeLiteralsOnMask = 1 << 2;
+ /*
const unsigned kDeflateTypeBitStart = 1;
const unsigned kNumDeflateTypeBits = 2;
const unsigned kNumDeflateTypes = (1 << kNumDeflateTypeBits);
const unsigned kDeflateTypeMask = (1 << kNumDeflateTypeBits) - 1;
+ */
}
namespace NHostOS
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp
index 6361dc5c..09443a61 100644
--- a/CPP/7zip/Archive/Zip/ZipIn.cpp
+++ b/CPP/7zip/Archive/Zip/ZipIn.cpp
@@ -6,6 +6,7 @@
#include "../../../Common/DynamicBuffer.h"
#include "../../../Common/IntToString.h"
+#include "../../../Common/MyException.h"
#include "../../../Common/StringToInt.h"
#include "../../../Windows/PropVariant.h"
@@ -27,6 +28,19 @@
namespace NArchive {
namespace NZip {
+// (kBufferSize >= kDataDescriptorSize64 + 4)
+
+static const size_t kSeqBufferSize = (size_t)1 << 14;
+
+/*
+ if (not defined ZIP_SELF_CHECK) : it reads CD and if error in first pass CD reading, it reads LOCALS-CD-MODE
+ if ( defined ZIP_SELF_CHECK) : it always reads CD and LOCALS-CD-MODE
+ use ZIP_SELF_CHECK to check LOCALS-CD-MODE for any zip archive
+*/
+
+// #define ZIP_SELF_CHECK
+
+
struct CEcd
{
UInt16 ThisDisk;
@@ -66,6 +80,7 @@ void CEcd::Parse(const Byte *p)
void CCdInfo::ParseEcd32(const Byte *p)
{
+ IsFromEcd64 = false;
// (p) includes signature
p += 4;
G16(0, ThisDisk);
@@ -79,6 +94,7 @@ void CCdInfo::ParseEcd32(const Byte *p)
void CCdInfo::ParseEcd64e(const Byte *p)
{
+ IsFromEcd64 = true;
// (p) exclude signature
G16(0, VersionMade);
G16(2, VersionNeedExtract);
@@ -106,9 +122,14 @@ struct CLocator
G64(4, Ecd64Offset);
G32(12, NumDisks);
}
-};
+ bool IsEmptyArc() const
+ {
+ return Ecd64Disk == 0 && NumDisks == 0 && Ecd64Offset == 0;
+ }
+};
+
void CInArchive::ClearRefs()
@@ -123,27 +144,174 @@ void CInArchive::ClearRefs()
void CInArchive::Close()
{
- _processedCnt = 0;
- IsArc = false;
+ _cnt = 0;
+ DisableBufMode();
+
IsArcOpen = false;
- IsMultiVol = false;
- UseDisk_in_SingleVol = false;
- EcdVolIndex = 0;
+
+ IsArc = false;
+ IsZip64 = false;
+
HeadersError = false;
HeadersWarning = false;
ExtraMinorError = false;
UnexpectedEnd = false;
+ LocalsWereRead = false;
+ LocalsCenterMerged = false;
NoCentralDir = false;
- IsZip64 = false;
+ Overflow32bit = false;
+ Cd_NumEntries_Overflow_16bit = false;
+
MarkerIsFound = false;
+ MarkerIsSafe = false;
+
+ IsMultiVol = false;
+ UseDisk_in_SingleVol = false;
+ EcdVolIndex = 0;
+ ArcInfo.Clear();
+
ClearRefs();
}
-HRESULT CInArchive::Seek(UInt64 offset)
+
+HRESULT CInArchive::Seek_SavePos(UInt64 offset)
+{
+ // InitBuf();
+ // if (!Stream) return S_FALSE;
+ return Stream->Seek(offset, STREAM_SEEK_SET, &_streamPos);
+}
+
+HRESULT CInArchive::SeekToVol(int volIndex, UInt64 offset)
+{
+ if (volIndex != Vols.StreamIndex)
+ {
+ InitBuf();
+ if (IsMultiVol && volIndex >= 0)
+ {
+ if ((unsigned)volIndex >= Vols.Streams.Size())
+ return S_FALSE;
+ if (!Vols.Streams[volIndex].Stream)
+ return S_FALSE;
+ Stream = Vols.Streams[volIndex].Stream;
+ }
+ else if (volIndex == -2)
+ {
+ if (!Vols.ZipStream)
+ return S_FALSE;
+ Stream = Vols.ZipStream;
+ }
+ else
+ Stream = StartStream;
+ Vols.StreamIndex = volIndex;
+ }
+ else
+ {
+ if (offset <= _streamPos)
+ {
+ const UInt64 back = _streamPos - offset;
+ if (back <= _bufCached)
+ {
+ _bufPos = _bufCached - (size_t)back;
+ return S_OK;
+ }
+ }
+ InitBuf();
+ }
+ return Seek_SavePos(offset);
+}
+
+
+// ---------- ReadFromCache ----------
+// reads from cache and from Stream
+// move to next volume can be allowed if (CanStartNewVol) and only before first byte reading
+
+HRESULT CInArchive::ReadFromCache(Byte *data, unsigned size, unsigned &processed)
{
- return Stream->Seek(offset, STREAM_SEEK_SET, NULL);
+ HRESULT result = S_OK;
+ processed = 0;
+
+ for (;;)
+ {
+ if (size == 0)
+ return S_OK;
+
+ const size_t avail = GetAvail();
+
+ if (avail != 0)
+ {
+ unsigned cur = size;
+ if (cur > avail)
+ cur = (unsigned)avail;
+ memcpy(data, (const Byte *)Buffer + _bufPos, cur);
+
+ data += cur;
+ size -= cur;
+ processed += cur;
+
+ _bufPos += cur;
+ _cnt += cur;
+
+ CanStartNewVol = false;
+
+ continue;
+ }
+
+ InitBuf();
+
+ if (_inBufMode)
+ {
+ UInt32 cur = 0;
+ result = Stream->Read(Buffer, (UInt32)Buffer.Size(), &cur);
+ _bufPos = 0;
+ _bufCached = cur;
+ _streamPos += cur;
+ if (cur != 0)
+ CanStartNewVol = false;
+ if (result != S_OK)
+ break;
+ if (cur != 0)
+ continue;
+ }
+ else
+ {
+ UInt32 cur = 0;
+ result = Stream->Read(data, size, &cur);
+ data += cur;
+ size -= cur;
+ processed += cur;
+ _streamPos += cur;
+ _cnt += cur;
+ if (cur != 0)
+ {
+ CanStartNewVol = false;
+ break;
+ }
+ if (result != S_OK)
+ break;
+ }
+
+ if ( !IsMultiVol
+ || !CanStartNewVol
+ || Vols.StreamIndex < 0
+ || (unsigned)Vols.StreamIndex + 1 >= Vols.Streams.Size())
+ break;
+
+ const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex + 1];
+ if (!s.Stream)
+ break;
+ result = s.SeekToStart();
+ if (result != S_OK)
+ break;
+ Vols.StreamIndex++;
+ _streamPos = 0;
+ // Vols.NeedSeek = false;
+
+ Stream = s.Stream;
+ }
+
+ return result;
}
@@ -168,18 +336,33 @@ API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size)
if (p[0] != 'P')
return k_IsArc_Res_NO;
- UInt32 value = Get32(p);
+ UInt32 sig = Get32(p);
- if (value == NSignature::kNoSpan
- || value == NSignature::kSpan)
+ if (sig == NSignature::kNoSpan || sig == NSignature::kSpan)
{
p += 4;
size -= 4;
}
- value = Get32(p);
+ sig = Get32(p);
- if (value == NSignature::kEcd)
+ if (sig == NSignature::kEcd64)
+ {
+ if (size < kEcd64_FullSize)
+ return k_IsArc_Res_NEED_MORE;
+
+ const UInt64 recordSize = Get64(p + 4);
+ if ( recordSize < kEcd64_MainSize
+ || recordSize > kEcd64_MainSize + (1 << 20))
+ return k_IsArc_Res_NO;
+ CCdInfo cdInfo;
+ cdInfo.ParseEcd64e(p + 12);
+ if (!cdInfo.IsEmptyArc())
+ return k_IsArc_Res_NO;
+ return k_IsArc_Res_YES; // k_IsArc_Res_YES_2;
+ }
+
+ if (sig == NSignature::kEcd)
{
if (size < kEcdSize)
return k_IsArc_Res_NEED_MORE;
@@ -190,8 +373,8 @@ API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size)
return k_IsArc_Res_NO;
return k_IsArc_Res_YES; // k_IsArc_Res_YES_2;
}
-
- if (value != NSignature::kLocalFileHeader)
+
+ if (sig != NSignature::kLocalFileHeader)
return k_IsArc_Res_NO;
if (size < kLocalHeaderSize)
@@ -240,8 +423,17 @@ API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size)
const Byte *p2 = p + kLocalHeaderSize;
for (size_t i = 0; i < rem; i++)
if (p2[i] == 0)
+ {
+ // we support some "bad" zip archives that contain zeros after name
+ for (size_t k = i + 1; k < rem; k++)
+ if (p2[k] != 0)
+ return k_IsArc_Res_NO;
+ break;
+ /*
if (i != nameSize - 1)
return k_IsArc_Res_NO;
+ */
+ }
}
if (size < extraOffset)
@@ -288,398 +480,562 @@ static UInt32 IsArc_Zip_2(const Byte *p, size_t size, bool isFinal)
}
+
+MY_NO_INLINE
+static const Byte *FindPK(const Byte *p, const Byte *limit)
+{
+ for (;;)
+ {
+ for (;;)
+ {
+ Byte b0 = p[0];
+ if (p >= limit)
+ return p;
+ p++;
+ if (b0 == 0x50)
+ break;
+ }
+ if (p[0] == 0x4B)
+ return p - 1;
+ }
+}
+
-HRESULT CInArchive::FindMarker(IInStream *stream, const UInt64 *searchLimit)
+/*
+---------- FindMarker ----------
+returns:
+ S_OK:
+ ArcInfo.MarkerVolIndex : volume of marker
+ ArcInfo.MarkerPos : Pos of first signature
+ ArcInfo.MarkerPos2 : Pos of main signature (local item signature in most cases)
+ _streamPos : stream pos
+ _cnt : The number of virtal Bytes after start of search to offset after signature
+ _signature : main signature
+
+ S_FALSE: can't find marker, or there is some non-zip data after marker
+
+ Error code: stream reading error.
+*/
+
+HRESULT CInArchive::FindMarker(const UInt64 *searchLimit)
{
- ArcInfo.MarkerPos = m_Position;
- ArcInfo.MarkerPos2 = m_Position;
+ ArcInfo.MarkerPos = GetVirtStreamPos();
+ ArcInfo.MarkerPos2 = ArcInfo.MarkerPos;
+ ArcInfo.MarkerVolIndex = Vols.StreamIndex;
+
+ _cnt = 0;
+
+ CanStartNewVol = false;
if (searchLimit && *searchLimit == 0)
{
Byte startBuf[kMarkerSize];
- {
- size_t processed = kMarkerSize;
- RINOK(ReadStream(stream, startBuf, &processed));
- m_Position += processed;
- if (processed != kMarkerSize)
- return S_FALSE;
- }
+ unsigned processed;
+ RINOK(ReadFromCache(startBuf, kMarkerSize, processed));
+ if (processed != kMarkerSize)
+ return S_FALSE;
- m_Signature = Get32(startBuf);
+ UInt32 marker = Get32(startBuf);
+ _signature = marker;
- if (m_Signature != NSignature::kEcd &&
- m_Signature != NSignature::kLocalFileHeader)
+ if ( marker == NSignature::kNoSpan
+ || marker == NSignature::kSpan)
{
- if (m_Signature != NSignature::kNoSpan)
- {
- if (m_Signature != NSignature::kSpan)
- return S_FALSE;
- if (m_Position != 4) // we don't support multivol archives with sfx stub
- return S_FALSE;
- ArcInfo.IsSpanMode = true;
- }
- size_t processed = kMarkerSize;
- RINOK(ReadStream(stream, startBuf, &processed));
- m_Position += processed;
+ RINOK(ReadFromCache(startBuf, kMarkerSize, processed));
if (processed != kMarkerSize)
return S_FALSE;
- m_Signature = Get32(startBuf);
- if (m_Signature != NSignature::kEcd &&
- m_Signature != NSignature::kLocalFileHeader)
- return S_FALSE;
- ArcInfo.MarkerPos2 += 4;
+ _signature = Get32(startBuf);
}
+
+ if ( _signature != NSignature::kEcd
+ && _signature != NSignature::kEcd64
+ && _signature != NSignature::kLocalFileHeader)
+ return S_FALSE;
+
+ ArcInfo.MarkerPos2 = GetVirtStreamPos() - 4;
+ ArcInfo.IsSpanMode = (marker == NSignature::kSpan);
// we use weak test in case of (*searchLimit == 0)
// since error will be detected later in Open function
- return S_OK; // maybe we need to search backward.
+ return S_OK;
}
- const size_t kBufSize = (size_t)1 << 18; // must be larger than kCheckSize
const size_t kCheckSize = (size_t)1 << 16; // must be smaller than kBufSize
- CByteArr buffer(kBufSize);
-
- size_t numBytesInBuffer = 0;
- UInt64 curScanPos = 0;
+ const size_t kBufSize = (size_t)1 << 17; // must be larger than kCheckSize
+
+ if (Buffer.Size() < kBufSize)
+ {
+ InitBuf();
+ Buffer.AllocAtLeast(kBufSize);
+ if (!Buffer.IsAllocated())
+ return E_OUTOFMEMORY;
+ }
+
+ _inBufMode = true;
+
+ UInt64 progressPrev = 0;
for (;;)
{
- size_t numReadBytes = kBufSize - numBytesInBuffer;
- RINOK(ReadStream(stream, buffer + numBytesInBuffer, &numReadBytes));
- m_Position += numReadBytes;
- numBytesInBuffer += numReadBytes;
- const bool isFinished = (numBytesInBuffer != kBufSize);
+ RINOK(LookAhead(kBufSize));
- size_t limit = numBytesInBuffer;;
+ const size_t avail = GetAvail();
+
+ size_t limitPos;
+ const bool isFinished = (avail != kBufSize);
if (isFinished)
{
- if (limit == 0)
- break;
- limit--;
+ const unsigned kMinAllowed = 4;
+ if (avail <= kMinAllowed)
+ {
+ if ( !IsMultiVol
+ || Vols.StreamIndex < 0
+ || (unsigned)Vols.StreamIndex + 1 >= Vols.Streams.Size())
+ break;
+
+ SkipLookahed(avail);
+
+ const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex + 1];
+ if (!s.Stream)
+ break;
+
+ RINOK(s.SeekToStart());
+
+ InitBuf();
+ Vols.StreamIndex++;
+ _streamPos = 0;
+ Stream = s.Stream;
+ continue;
+ }
+ limitPos = avail - kMinAllowed;
}
else
- limit -= kCheckSize;
+ limitPos = (avail - kCheckSize);
- if (searchLimit && curScanPos + limit > *searchLimit)
- limit = (size_t)(*searchLimit - curScanPos + 1);
+ // we don't check at (limitPos) for good fast aligned operations
- if (limit < 1)
+ if (searchLimit)
+ {
+ if (_cnt > *searchLimit)
+ break;
+ UInt64 rem = *searchLimit - _cnt;
+ if (limitPos > rem)
+ limitPos = (size_t)rem + 1;
+ }
+
+ if (limitPos == 0)
break;
- const Byte *buf = buffer;
- for (size_t pos = 0; pos < limit; pos++)
+ const Byte * const pStart = Buffer + _bufPos;
+ const Byte * p = pStart;
+ const Byte * const limit = pStart + limitPos;
+
+ for (;; p++)
{
- if (buf[pos] != 0x50)
- continue;
- if (buf[pos + 1] != 0x4B)
- continue;
- size_t rem = numBytesInBuffer - pos;
- UInt32 res = IsArc_Zip_2(buf + pos, rem, isFinished);
+ p = FindPK(p, limit);
+ if (p >= limit)
+ break;
+ const size_t rem = pStart + avail - p;
+ UInt32 res = IsArc_Zip_2(p, rem, isFinished);
if (res != k_IsArc_Res_NO)
{
if (rem < kMarkerSize)
return S_FALSE;
- m_Signature = Get32(buf + pos);
- ArcInfo.MarkerPos += curScanPos + pos;
+ _signature = Get32(p);
+ SkipLookahed(p - pStart);
+ ArcInfo.MarkerVolIndex = Vols.StreamIndex;
+ ArcInfo.MarkerPos = GetVirtStreamPos();
ArcInfo.MarkerPos2 = ArcInfo.MarkerPos;
- if (m_Signature == NSignature::kNoSpan
- || m_Signature == NSignature::kSpan)
+ SkipLookahed(4);
+ if ( _signature == NSignature::kNoSpan
+ || _signature == NSignature::kSpan)
{
- m_Signature = Get32(buf + pos + 4);
+ if (rem < kMarkerSize * 2)
+ return S_FALSE;
+ ArcInfo.IsSpanMode = (_signature == NSignature::kSpan);
+ _signature = Get32(p + 4);
ArcInfo.MarkerPos2 += 4;
+ SkipLookahed(4);
}
- m_Position = ArcInfo.MarkerPos2 + kMarkerSize;
return S_OK;
}
}
- if (isFinished)
+ if (!IsMultiVol && isFinished)
break;
- curScanPos += limit;
- numBytesInBuffer -= limit;
- memmove(buffer, buffer + limit, numBytesInBuffer);
+ SkipLookahed(p - pStart);
+
+ if (Callback && (_cnt - progressPrev) >= ((UInt32)1 << 23))
+ {
+ progressPrev = _cnt;
+ // const UInt64 numFiles64 = 0;
+ RINOK(Callback->SetCompleted(NULL, &_cnt));
+ }
}
return S_FALSE;
}
-HRESULT CInArchive::IncreaseRealPosition(Int64 addValue, bool &isFinished)
+/*
+---------- IncreaseRealPosition ----------
+moves virtual offset in virtual stream.
+changing to new volumes is allowed
+*/
+
+HRESULT CInArchive::IncreaseRealPosition(UInt64 offset, bool &isFinished)
{
isFinished = false;
+
+ for (;;)
+ {
+ const size_t avail = GetAvail();
+
+ if (offset <= avail)
+ {
+ _bufPos += (size_t)offset;
+ _cnt += offset;
+ return S_OK;
+ }
+
+ _cnt += avail;
+ offset -= avail;
+
+ _bufCached = 0;
+ _bufPos = 0;
+
+ if (!_inBufMode)
+ break;
+
+ CanStartNewVol = true;
+ LookAhead(1);
+
+ if (GetAvail() == 0)
+ return S_OK;
+ }
+
if (!IsMultiVol)
- return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position);
+ {
+ _cnt += offset;
+ return Stream->Seek(offset, STREAM_SEEK_CUR, &_streamPos);
+ }
for (;;)
{
- if (addValue == 0)
+ if (offset == 0)
return S_OK;
- if (addValue > 0)
+
+ if (Vols.StreamIndex < 0)
+ return S_FALSE;
+ if ((unsigned)Vols.StreamIndex >= Vols.Streams.Size())
{
- if (Vols.StreamIndex < 0)
- return S_FALSE;
- if ((unsigned)Vols.StreamIndex >= Vols.Streams.Size())
+ isFinished = true;
+ return S_OK;
+ }
+ {
+ const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex];
+ if (!s.Stream)
{
isFinished = true;
return S_OK;
}
+ if (_streamPos > s.Size)
+ return S_FALSE;
+ const UInt64 rem = s.Size - _streamPos;
+ if ((UInt64)offset <= rem)
{
- const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex];
- if (!s.Stream)
- {
- isFinished = true;
- return S_OK;
- }
- if (m_Position > s.Size)
- return S_FALSE;
- UInt64 rem = s.Size - m_Position;
- if ((UInt64)addValue <= rem)
- return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position);
- RINOK(Stream->Seek(s.Size, STREAM_SEEK_SET, &m_Position));
- addValue -= rem;
- Stream = NULL;
- Vols.StreamIndex++;
- if ((unsigned)Vols.StreamIndex >= Vols.Streams.Size())
- {
- isFinished = true;
- return S_OK;
- }
- }
- const CVols::CSubStreamInfo &s2 = Vols.Streams[Vols.StreamIndex];
- if (!s2.Stream)
- {
- isFinished = true;
- return S_OK;
+ _cnt += offset;
+ return Stream->Seek(offset, STREAM_SEEK_CUR, &_streamPos);
}
- Stream = s2.Stream;
- m_Position = 0;
- RINOK(Stream->Seek(0, STREAM_SEEK_SET, &m_Position));
+ RINOK(Seek_SavePos(s.Size));
+ offset -= rem;
+ _cnt += rem;
}
- else
+
+ Stream = NULL;
+ _streamPos = 0;
+ Vols.StreamIndex++;
+ if ((unsigned)Vols.StreamIndex >= Vols.Streams.Size())
{
- if (!Stream)
- return S_FALSE;
- {
- if (m_Position >= (UInt64)(-addValue))
- return Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position);
- addValue += m_Position;
- RINOK(Stream->Seek(0, STREAM_SEEK_SET, &m_Position));
- m_Position = 0;
- Stream = NULL;
- if (--Vols.StreamIndex < 0)
- return S_FALSE;
- }
- const CVols::CSubStreamInfo &s2 = Vols.Streams[Vols.StreamIndex];
- if (!s2.Stream)
- return S_FALSE;
- Stream = s2.Stream;
- m_Position = s2.Size;
- RINOK(Stream->Seek(s2.Size, STREAM_SEEK_SET, &m_Position));
+ isFinished = true;
+ return S_OK;
+ }
+ const CVols::CSubStreamInfo &s2 = Vols.Streams[Vols.StreamIndex];
+ if (!s2.Stream)
+ {
+ isFinished = true;
+ return S_OK;
}
+ Stream = s2.Stream;
+ RINOK(Seek_SavePos(0));
}
}
-class CUnexpectEnd {};
+/*
+---------- LookAhead ----------
+Reads data to buffer, if required.
-HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize)
-{
- size_t realProcessedSize = size;
- HRESULT result = S_OK;
- if (_inBufMode)
- {
- try { realProcessedSize = _inBuffer.ReadBytes((Byte *)data, size); }
- catch (const CInBufferException &e) { return e.ErrorCode; }
- }
- else
- result = ReadStream(Stream, data, &realProcessedSize);
- if (processedSize)
- *processedSize = (UInt32)realProcessedSize;
- m_Position += realProcessedSize;
- return result;
-}
+It can read from volumes as long as Buffer.Size().
+But it moves to new volume, only if it's required to provide minRequired bytes in buffer.
-void CInArchive::SafeReadBytes(void *data, unsigned size)
-{
- size_t processed = size;
-
- HRESULT result = S_OK;
+in:
+ (minRequired <= Buffer.Size())
- if (!_inBufMode)
- result = ReadStream(Stream, data, &processed);
- else
+return:
+ S_OK : if (GetAvail() < minRequired) after function return, it's end of stream(s) data, or no new volume stream.
+ Error codes: IInStream::Read() error or IInStream::Seek() error for multivol
+*/
+
+HRESULT CInArchive::LookAhead(size_t minRequired)
+{
+ for (;;)
{
- for (;;)
+ const size_t avail = GetAvail();
+
+ if (minRequired <= avail)
+ return S_OK;
+
+ if (_bufPos != 0)
{
- processed = _inBuffer.ReadBytes((Byte *)data, size);
- if (processed != 0
- || IsMultiVol
- || !CanStartNewVol
- || Vols.StreamIndex < 0
- || (unsigned)Vols.StreamIndex >= Vols.Streams.Size())
- break;
- Vols.StreamIndex++;
- const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex];
- if (!s.Stream)
- break;
- // if (Vols.NeedSeek)
- {
- result = s.Stream->Seek(0, STREAM_SEEK_SET, NULL);
- m_Position = 0;
- if (result != S_OK)
- break;
- Vols.NeedSeek = false;
- }
- _inBuffer.SetStream(s.Stream);
- _inBuffer.Init();
+ if (avail != 0)
+ memmove(Buffer, Buffer + _bufPos, avail);
+ _bufPos = 0;
+ _bufCached = avail;
}
- CanStartNewVol = false;
+
+ const size_t pos = _bufCached;
+ UInt32 processed = 0;
+ HRESULT res = Stream->Read(Buffer + pos, (UInt32)(Buffer.Size() - pos), &processed);
+ _streamPos += processed;
+ _bufCached += processed;
+
+ if (res != S_OK)
+ return res;
+
+ if (processed != 0)
+ continue;
+
+ if ( !IsMultiVol
+ || !CanStartNewVol
+ || Vols.StreamIndex < 0
+ || (unsigned)Vols.StreamIndex + 1 >= Vols.Streams.Size())
+ return S_OK;
+
+ const CVols::CSubStreamInfo &s = Vols.Streams[Vols.StreamIndex + 1];
+ if (!s.Stream)
+ return S_OK;
+
+ RINOK(s.SeekToStart());
+
+ Vols.StreamIndex++;
+ _streamPos = 0;
+ Stream = s.Stream;
+ // Vols.NeedSeek = false;
}
+}
+
+
+class CUnexpectEnd {};
+
+
+/*
+---------- SafeRead ----------
+
+reads data of exact size from stream(s)
- m_Position += processed;
- _processedCnt += processed;
+in:
+ _inBufMode
+ if (CanStartNewVol) it can go to next volume before first byte reading, if there is end of volume data.
+in, out:
+ _streamPos : position in Stream
+ Stream
+ Vols : if (IsMultiVol)
+ _cnt
+
+out:
+ (CanStartNewVol == false), if some data was read
+
+return:
+ S_OK : success reading of requested data
+
+exceptions:
+ CSystemException() - stream reading error
+ CUnexpectEnd() : could not read data of requested size
+*/
+
+void CInArchive::SafeRead(Byte *data, unsigned size)
+{
+ unsigned processed;
+ HRESULT result = ReadFromCache(data, size, processed);
if (result != S_OK)
throw CSystemException(result);
-
- if (processed != size)
+ if (size != processed)
throw CUnexpectEnd();
}
void CInArchive::ReadBuffer(CByteBuffer &buffer, unsigned size)
{
buffer.Alloc(size);
- if (size > 0)
- SafeReadBytes(buffer, size);
+ if (size != 0)
+ SafeRead(buffer, size);
}
-Byte CInArchive::ReadByte()
+// Byte CInArchive::ReadByte () { Byte b; SafeRead(&b, 1); return b; }
+// UInt16 CInArchive::ReadUInt16() { Byte buf[2]; SafeRead(buf, 2); return Get16(buf); }
+UInt32 CInArchive::ReadUInt32() { Byte buf[4]; SafeRead(buf, 4); return Get32(buf); }
+UInt64 CInArchive::ReadUInt64() { Byte buf[8]; SafeRead(buf, 8); return Get64(buf); }
+
+void CInArchive::ReadSignature()
{
- Byte b;
- SafeReadBytes(&b, 1);
- return b;
+ CanStartNewVol = true;
+ _signature = ReadUInt32();
+ // CanStartNewVol = false; // it's already changed in SafeRead
}
-UInt16 CInArchive::ReadUInt16() { Byte buf[2]; SafeReadBytes(buf, 2); return Get16(buf); }
-UInt32 CInArchive::ReadUInt32() { Byte buf[4]; SafeReadBytes(buf, 4); return Get32(buf); }
-UInt64 CInArchive::ReadUInt64() { Byte buf[8]; SafeReadBytes(buf, 8); return Get64(buf); }
-// we use Skip() inside headers only, so no need for stream change in multivol.
+// we Skip() inside headers only, so no need for stream change in multivol.
-void CInArchive::Skip(unsigned num)
+void CInArchive::Skip(size_t num)
{
- if (_inBufMode)
- {
- size_t skip = _inBuffer.Skip(num);
- m_Position += skip;
- _processedCnt += skip;
- if (skip != num)
- throw CUnexpectEnd();
- }
- else
+ while (num != 0)
{
- for (unsigned i = 0; i < num; i++)
- ReadByte();
+ const unsigned kBufSize = (size_t)1 << 10;
+ Byte buf[kBufSize];
+ unsigned step = kBufSize;
+ if (step > num)
+ step = (unsigned)num;
+ SafeRead(buf, step);
+ num -= step;
}
}
-void CInArchive::Skip64(UInt64 num)
+/*
+HRESULT CInArchive::Callback_Completed(unsigned numFiles)
+{
+ const UInt64 numFiles64 = numFiles;
+ return Callback->SetCompleted(&numFiles64, &_cnt);
+}
+*/
+
+HRESULT CInArchive::Skip64(UInt64 num, unsigned numFiles)
{
- for (UInt64 i = 0; i < num; i++)
- ReadByte();
+ if (num == 0)
+ return S_OK;
+
+ for (;;)
+ {
+ size_t step = (size_t)1 << 24;
+ if (step > num)
+ step = (size_t)num;
+ Skip(step);
+ num -= step;
+ if (num == 0)
+ return S_OK;
+ if (Callback)
+ {
+ const UInt64 numFiles64 = numFiles;
+ RINOK(Callback->SetCompleted(&numFiles64, &_cnt));
+ }
+ }
}
-void CInArchive::ReadFileName(unsigned size, AString &s)
+bool CInArchive::ReadFileName(unsigned size, AString &s)
{
if (size == 0)
{
s.Empty();
- return;
+ return true;
+ }
+ char *p = s.GetBuf(size);
+ SafeRead((Byte *)p, size);
+ unsigned i = size;
+ do
+ {
+ if (p[i - 1] != 0)
+ break;
}
- SafeReadBytes(s.GetBuf(size), size);
+ while (--i);
s.ReleaseBuf_CalcLen(size);
+ return s.Len() == i;
}
-bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extraBlock,
- UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber)
+#define ZIP64_IS_32_MAX(n) ((n) == 0xFFFFFFFF)
+#define ZIP64_IS_16_MAX(n) ((n) == 0xFFFF)
+
+
+bool CInArchive::ReadExtra(unsigned extraSize, CExtraBlock &extra,
+ UInt64 &unpackSize, UInt64 &packSize, UInt64 &localOffset, UInt32 &disk)
{
- extraBlock.Clear();
+ extra.Clear();
- UInt32 remain = extraSize;
-
- while (remain >= 4)
+ while (extraSize >= 4)
{
CExtraSubBlock subBlock;
- subBlock.ID = ReadUInt16();
- unsigned dataSize = ReadUInt16();
- remain -= 4;
- if (dataSize > remain) // it's bug
+ const UInt32 pair = ReadUInt32();
+ subBlock.ID = (pair & 0xFFFF);
+ unsigned size = (unsigned)(pair >> 16);
+
+ extraSize -= 4;
+
+ if (size > extraSize)
{
+ // it's error in extra
HeadersWarning = true;
- Skip(remain);
+ extra.Error = true;
+ Skip(extraSize);
return false;
}
+
+ extraSize -= size;
+
if (subBlock.ID == NFileHeader::NExtraID::kZip64)
{
- if (unpackSize == 0xFFFFFFFF)
- {
- if (dataSize < 8)
- {
- HeadersWarning = true;
- Skip(remain);
- return false;
- }
- unpackSize = ReadUInt64();
- remain -= 8;
- dataSize -= 8;
- }
- if (packSize == 0xFFFFFFFF)
- {
- if (dataSize < 8)
- break;
- packSize = ReadUInt64();
- remain -= 8;
- dataSize -= 8;
- }
- if (localHeaderOffset == 0xFFFFFFFF)
- {
- if (dataSize < 8)
- break;
- localHeaderOffset = ReadUInt64();
- remain -= 8;
- dataSize -= 8;
- }
- if (diskStartNumber == 0xFFFF)
+ extra.IsZip64 = true;
+ bool isOK = true;
+
+ if (ZIP64_IS_32_MAX(unpackSize))
+ if (size < 8) isOK = false; else { size -= 8; unpackSize = ReadUInt64(); }
+
+ if (isOK && ZIP64_IS_32_MAX(packSize))
+ if (size < 8) isOK = false; else { size -= 8; packSize = ReadUInt64(); }
+
+ if (isOK && ZIP64_IS_32_MAX(localOffset))
+ if (size < 8) isOK = false; else { size -= 8; localOffset = ReadUInt64(); }
+
+ if (isOK && ZIP64_IS_16_MAX(disk))
+ if (size < 4) isOK = false; else { size -= 4; disk = ReadUInt32(); }
+
+ if (!isOK || size != 0)
{
- if (dataSize < 4)
- break;
- diskStartNumber = ReadUInt32();
- remain -= 4;
- dataSize -= 4;
+ HeadersWarning = true;
+ extra.Error = true;
+ extra.IsZip64_Error = true;
+ Skip(size);
}
- Skip(dataSize);
}
else
{
- ReadBuffer(subBlock.Data, dataSize);
- extraBlock.SubBlocks.Add(subBlock);
+ ReadBuffer(subBlock.Data, size);
+ extra.SubBlocks.Add(subBlock);
}
- remain -= dataSize;
}
- if (remain != 0)
+ if (extraSize != 0)
{
ExtraMinorError = true;
+ extra.MinorError = true;
// 7-Zip before 9.31 created incorrect WsAES Extra in folder's local headers.
// so we don't return false, but just set warning flag
// return false;
+ Skip(extraSize);
}
-
- Skip(remain);
+
return true;
}
@@ -691,7 +1047,7 @@ bool CInArchive::ReadLocalItem(CItemEx &item)
item.Disk = Vols.StreamIndex;
const unsigned kPureHeaderSize = kLocalHeaderSize - 4;
Byte p[kPureHeaderSize];
- SafeReadBytes(p, kPureHeaderSize);
+ SafeRead(p, kPureHeaderSize);
{
unsigned i;
for (i = 0; i < kPureHeaderSize && p[i] == 0; i++);
@@ -709,8 +1065,9 @@ bool CInArchive::ReadLocalItem(CItemEx &item)
G32(18, item.Size);
const unsigned nameSize = Get16(p + 22);
const unsigned extraSize = Get16(p + 24);
- ReadFileName(nameSize, item.Name);
+ bool isOkName = ReadFileName(nameSize, item.Name);
item.LocalFullHeaderSize = kLocalHeaderSize + (UInt32)nameSize + extraSize;
+ item.DescriptorWasRead = false;
/*
if (item.IsDir())
@@ -719,10 +1076,9 @@ bool CInArchive::ReadLocalItem(CItemEx &item)
if (extraSize > 0)
{
- UInt64 localHeaderOffset = 0;
- UInt32 diskStartNumber = 0;
- if (!ReadExtra(extraSize, item.LocalExtra, item.Size, item.PackSize,
- localHeaderOffset, diskStartNumber))
+ UInt64 localOffset = 0;
+ UInt32 disk = 0;
+ if (!ReadExtra(extraSize, item.LocalExtra, item.Size, item.PackSize, localOffset, disk))
{
/* Most of archives are OK for Extra. But there are some rare cases
that have error. And if error in first item, it can't open archive.
@@ -739,8 +1095,8 @@ bool CInArchive::ReadLocalItem(CItemEx &item)
if (item.Name.Len() != nameSize)
{
- // we support "bad" archives with null-terminated name.
- if (item.Name.Len() + 1 != nameSize)
+ // we support some "bad" zip archives that contain zeros after name
+ if (!isOkName)
return false;
HeadersWarning = true;
}
@@ -758,11 +1114,11 @@ static bool FlagsAreSame(const CItem &i1, const CItem &i2)
UInt32 mask = 0xFFFF;
switch (i1.Method)
{
- case NFileHeader::NCompressionMethod::kDeflated:
+ case NFileHeader::NCompressionMethod::kDeflate:
mask = 0x7FF9;
break;
default:
- if (i1.Method <= NFileHeader::NCompressionMethod::kImploded)
+ if (i1.Method <= NFileHeader::NCompressionMethod::kImplode)
mask = 0x7FFF;
}
@@ -805,9 +1161,9 @@ static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem)
return false;
if (!localItem.HasDescriptor())
{
- if (cdItem.Crc != localItem.Crc ||
- cdItem.PackSize != localItem.PackSize ||
- cdItem.Size != localItem.Size)
+ if (cdItem.PackSize != localItem.PackSize
+ || cdItem.Size != localItem.Size
+ || cdItem.Crc != localItem.Crc && cdItem.Crc != 0) // some program writes 0 to crc field in central directory
return false;
}
/* pkzip 2.50 creates incorrect archives. It uses
@@ -833,7 +1189,8 @@ static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem)
// pkzip 2.50 uses DOS encoding in central dir and WIN encoding in local header.
// so we ignore that error
if (hostOs != NFileHeader::NHostOS::kFAT
- || cdItem.MadeByVersion.Version != 25)
+ || cdItem.MadeByVersion.Version < 25
+ || cdItem.MadeByVersion.Version > 40)
return false;
}
}
@@ -847,9 +1204,13 @@ static bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem)
}
-HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail)
+HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail, bool &headersError)
{
+ InitBuf();
+ _inBufMode = false;
+
isAvail = true;
+ headersError = false;
if (item.FromLocal)
return S_OK;
try
@@ -863,15 +1224,13 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail)
isAvail = false;
return S_FALSE;
}
- IInStream *str2 = Vols.Streams[item.Disk].Stream;
- if (!str2)
+ Stream = Vols.Streams[item.Disk].Stream;
+ Vols.StreamIndex = item.Disk;
+ if (!Stream)
{
isAvail = false;
return S_FALSE;
}
- RINOK(str2->Seek(offset, STREAM_SEEK_SET, NULL));
- Stream = str2;
- Vols.StreamIndex = item.Disk;
}
else
{
@@ -888,9 +1247,16 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail)
isAvail = false;
return S_FALSE;
}
- RINOK(Seek(offset));
}
+ RINOK(Seek_SavePos(offset));
+
+ /*
+ // we can check buf mode
+ InitBuf();
+ _inBufMode = true;
+ Buffer.AllocAtLeast(1 << 10);
+ */
CItemEx localItem;
if (ReadUInt32() != NSignature::kLocalFileHeader)
@@ -900,6 +1266,11 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail)
return S_FALSE;
item.LocalFullHeaderSize = localItem.LocalFullHeaderSize;
item.LocalExtra = localItem.LocalExtra;
+ if (item.Crc != localItem.Crc && !localItem.HasDescriptor())
+ {
+ item.Crc = localItem.Crc;
+ headersError = true;
+ }
item.FromLocal = true;
}
catch(...) { return S_FALSE; }
@@ -907,53 +1278,202 @@ HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail)
}
-HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item)
+/*
+---------- FindDescriptor ----------
+
+in:
+ _streamPos : position in Stream
+ Stream :
+ Vols : if (IsMultiVol)
+
+action:
+ searches descriptor in input stream(s).
+ sets
+ item.DescriptorWasRead = true;
+ item.Size
+ item.PackSize
+ item.Crc
+ if descriptor was found
+
+out:
+ S_OK:
+ if ( item.DescriptorWasRead) : if descriptor was found
+ if (!item.DescriptorWasRead) : if descriptor was not found : unexpected end of stream(s)
+
+ S_FALSE: if no items or there is just one item with strange properies that doesn't look like real archive.
+
+ another error code: Callback error.
+
+exceptions :
+ CSystemException() : stream reading error
+*/
+
+HRESULT CInArchive::FindDescriptor(CItemEx &item, unsigned numFiles)
{
- const unsigned kBufSize = (1 << 12);
- Byte buf[kBufSize];
+ // const size_t kBufSize = (size_t)1 << 5; // don't increase it too much. It reads data look ahead.
+
+ // Buffer.Alloc(kBufSize);
+ // Byte *buf = Buffer;
- UInt32 numBytesInBuffer = 0;
- UInt32 packedSize = 0;
+ UInt64 packedSize = 0;
+ UInt64 progressPrev = _cnt;
+
for (;;)
{
- UInt32 processedSize;
- RINOK(ReadBytes(buf + numBytesInBuffer, kBufSize - numBytesInBuffer, &processedSize));
- numBytesInBuffer += processedSize;
- if (numBytesInBuffer < kDataDescriptorSize)
- return S_FALSE;
+ /* appnote specification claims that we must use 64-bit descriptor, if there is zip64 extra.
+ But some old third-party xps archives used 64-bit descriptor without zip64 extra. */
+ // unsigned descriptorSize = kDataDescriptorSize64 + kNextSignatureSize;
+
+ // const unsigned kNextSignatureSize = 0; // we can disable check for next signatuire
+ const unsigned kNextSignatureSize = 4; // we check also for signature for next File headear
+
+ const unsigned descriptorSize4 = item.GetDescriptorSize() + kNextSignatureSize;
+
+ if (descriptorSize4 > Buffer.Size()) return E_FAIL;
+
+ // size_t processedSize;
+ CanStartNewVol = true;
+ RINOK(LookAhead(descriptorSize4));
+ const size_t avail = GetAvail();
+
+ if (avail < descriptorSize4)
+ {
+ // we write to packSize all these available bytes.
+ // later it's simpler to work with such value than with 0
+ if (item.PackSize == 0)
+ item.PackSize = packedSize + avail;
+ return S_OK;
+ }
+
+ const Byte * const pStart = Buffer + _bufPos;
+ const Byte * p = pStart;
+ const Byte * const limit = pStart + (avail - descriptorSize4);
- UInt32 i;
- for (i = 0; i <= numBytesInBuffer - kDataDescriptorSize; i++)
+ for (; p <= limit; p++)
{
// descriptor signature field is Info-ZIP's extension to pkware Zip specification.
// New ZIP specification also allows descriptorSignature.
- if (buf[i] != 0x50)
+
+ p = FindPK(p, limit + 1);
+ if (p > limit)
+ break;
+
+ /*
+ if (*p != 0x50)
+ continue;
+ */
+
+ if (Get32(p) != NSignature::kDataDescriptor)
continue;
- // !!!! It must be fixed for Zip64 archives
- if (Get32(buf + i) == NSignature::kDataDescriptor)
+
+ // we check next signatuire after descriptor
+ // maybe we need check only 2 bytes "PK" instead of 4 bytes, if some another type of header is possible after descriptor
+ const UInt32 sig = Get32(p + descriptorSize4 - kNextSignatureSize);
+ if ( sig != NSignature::kLocalFileHeader
+ && sig != NSignature::kCentralFileHeader)
+ continue;
+
+ const UInt64 packSizeCur = packedSize + (p - pStart);
+ if (descriptorSize4 == kDataDescriptorSize64 + kNextSignatureSize) // if (item.LocalExtra.IsZip64)
{
- UInt32 descriptorPackSize = Get32(buf + i + 8);
- if (descriptorPackSize == packedSize + i)
- {
- item.Crc = Get32(buf + i + 4);
- item.PackSize = descriptorPackSize;
- item.Size = Get32(buf + i + 12);
- bool isFinished;
- return IncreaseRealPosition((Int64)(Int32)(0 - (numBytesInBuffer - i - kDataDescriptorSize)), isFinished);
- }
+ const UInt64 descriptorPackSize = Get64(p + 8);
+ if (descriptorPackSize != packSizeCur)
+ continue;
+ item.Size = Get64(p + 16);
}
+ else
+ {
+ const UInt32 descriptorPackSize = Get32(p + 8);
+ if (descriptorPackSize != (UInt32)packSizeCur)
+ continue;
+ item.Size = Get32(p + 12);
+ // that item.Size can be truncated to 32-bit value here
+ }
+ // We write calculated 64-bit packSize, even if descriptor64 was not used
+ item.PackSize = packSizeCur;
+
+ item.DescriptorWasRead = true;
+ item.Crc = Get32(p + 4);
+
+ const size_t skip = (p - pStart) + descriptorSize4 - kNextSignatureSize;
+
+ SkipLookahed(skip);
+
+ return S_OK;
}
- packedSize += i;
- unsigned j;
- for (j = 0; i < numBytesInBuffer; i++, j++)
- buf[j] = buf[i];
- numBytesInBuffer = j;
+ const size_t skip = (p - pStart);
+ SkipLookahed(skip);
+
+ packedSize += skip;
+
+ if (Callback)
+ if (_cnt - progressPrev >= ((UInt32)1 << 22))
+ {
+ progressPrev = _cnt;
+ const UInt64 numFiles64 = numFiles;
+ RINOK(Callback->SetCompleted(&numFiles64, &_cnt));
+ }
}
}
+HRESULT CInArchive::CheckDescriptor(const CItemEx &item)
+{
+ if (!item.HasDescriptor())
+ return S_OK;
+
+ // pkzip's version without descriptor signature is not supported
+
+ bool isFinished = false;
+ RINOK(IncreaseRealPosition(item.PackSize, isFinished));
+ if (isFinished)
+ return S_FALSE;
+
+ /*
+ if (!IsMultiVol)
+ {
+ RINOK(Seek_SavePos(ArcInfo.Base + item.GetDataPosition() + item.PackSize));
+ }
+ */
+
+ Byte buf[kDataDescriptorSize64];
+ try
+ {
+ CanStartNewVol = true;
+ SafeRead(buf, item.GetDescriptorSize());
+ }
+ catch (const CSystemException &e) { return e.ErrorCode; }
+ // catch (const CUnexpectEnd &)
+ catch(...)
+ {
+ return S_FALSE;
+ }
+ // RINOK(ReadStream_FALSE(Stream, buf, item.GetDescriptorSize()));
+
+ if (Get32(buf) != NSignature::kDataDescriptor)
+ return S_FALSE;
+ UInt32 crc = Get32(buf + 4);
+ UInt64 packSize, unpackSize;
+
+ if (item.LocalExtra.IsZip64)
+ {
+ packSize = Get64(buf + 8);
+ unpackSize = Get64(buf + 16);
+ }
+ else
+ {
+ packSize = Get32(buf + 8);
+ unpackSize = Get32(buf + 12);
+ }
+
+ if (crc != item.Crc || item.PackSize != packSize || item.Size != unpackSize)
+ return S_FALSE;
+ return S_OK;
+}
+
+
HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item)
{
if (item.FromLocal)
@@ -961,32 +1481,12 @@ HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item)
try
{
bool isAvail = true;
- RINOK(ReadLocalItemAfterCdItem(item, isAvail));
+ bool headersError = false;
+ RINOK(ReadLocalItemAfterCdItem(item, isAvail, headersError));
+ if (headersError)
+ return S_FALSE;
if (item.HasDescriptor())
- {
- // pkzip's version without descriptor is not supported
- RINOK(Seek(ArcInfo.Base + item.GetDataPosition() + item.PackSize));
- if (ReadUInt32() != NSignature::kDataDescriptor)
- return S_FALSE;
- UInt32 crc = ReadUInt32();
- UInt64 packSize, unpackSize;
-
- /*
- if (IsZip64)
- {
- packSize = ReadUInt64();
- unpackSize = ReadUInt64();
- }
- else
- */
- {
- packSize = ReadUInt32();
- unpackSize = ReadUInt32();
- }
-
- if (crc != item.Crc || item.PackSize != packSize || item.Size != unpackSize)
- return S_FALSE;
- }
+ return CheckDescriptor(item);
}
catch(...) { return S_FALSE; }
return S_OK;
@@ -997,7 +1497,7 @@ HRESULT CInArchive::ReadCdItem(CItemEx &item)
{
item.FromCentral = true;
Byte p[kCentralHeaderSize - 4];
- SafeReadBytes(p, kCentralHeaderSize - 4);
+ SafeRead(p, kCentralHeaderSize - 4);
item.MadeByVersion.Version = p[0];
item.MadeByVersion.HostOS = p[1];
@@ -1036,15 +1536,19 @@ HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo)
{
if (offset >= ((UInt64)1 << 63))
return S_FALSE;
- RINOK(Seek(offset));
Byte buf[kEcd64_FullSize];
- RINOK(ReadStream_FALSE(Stream, buf, kEcd64_FullSize));
+ RINOK(SeekToVol(Vols.StreamIndex, offset));
+ unsigned processed = 0;
+ ReadFromCache(buf, kEcd64_FullSize, processed);
+
+ if (processed != kEcd64_FullSize)
+ return S_FALSE;
if (Get32(buf) != NSignature::kEcd64)
return S_FALSE;
UInt64 mainSize = Get64(buf + 4);
- if (mainSize < kEcd64_MainSize || mainSize > ((UInt64)1 << 32))
+ if (mainSize < kEcd64_MainSize || mainSize > ((UInt64)1 << 40))
return S_FALSE;
cdInfo.ParseEcd64e(buf + 12);
return S_OK;
@@ -1057,27 +1561,49 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode)
UInt64 endPos;
+ // There are no useful data in cache in most cases here.
+ // So here we don't use cache data from previous operations .
+
+ InitBuf();
RINOK(Stream->Seek(0, STREAM_SEEK_END, &endPos));
+ _streamPos = endPos;
+
+ // const UInt32 kBufSizeMax2 = ((UInt32)1 << 16) + kEcdSize + kEcd64Locator_Size + kEcd64_FullSize;
+ const size_t kBufSizeMax = ((size_t)1 << 17); // must be larger than kBufSizeMax2
- const UInt32 kBufSizeMax = ((UInt32)1 << 16) + kEcdSize + kEcd64Locator_Size + kEcd64_FullSize;
- const UInt32 bufSize = (endPos < kBufSizeMax) ? (UInt32)endPos : kBufSizeMax;
+ const size_t bufSize = (endPos < kBufSizeMax) ? (size_t)endPos : kBufSizeMax;
if (bufSize < kEcdSize)
return S_FALSE;
- CByteArr byteBuffer(bufSize);
+ // CByteArr byteBuffer(bufSize);
+
+ if (Buffer.Size() < kBufSizeMax)
+ {
+ // InitBuf();
+ Buffer.AllocAtLeast(kBufSizeMax);
+ if (!Buffer.IsAllocated())
+ return E_OUTOFMEMORY;
+ }
- const UInt64 startPos = endPos - bufSize;
- RINOK(Stream->Seek(startPos, STREAM_SEEK_SET, &m_Position));
- if (m_Position != startPos)
+ RINOK(Seek_SavePos(endPos - bufSize));
+
+ size_t processed = bufSize;
+ HRESULT res = ReadStream(Stream, Buffer, &processed);
+ _streamPos += processed;
+ _bufCached = processed;
+ _bufPos = 0;
+ _cnt += processed;
+ if (res != S_OK)
+ return res;
+ if (processed != bufSize)
return S_FALSE;
+
- RINOK(ReadStream_FALSE(Stream, byteBuffer, bufSize));
-
- for (UInt32 i = bufSize - kEcdSize + 1;;)
+ for (size_t i = bufSize - kEcdSize + 1;;)
{
if (i == 0)
return S_FALSE;
- const Byte *buf = byteBuffer;
+ const Byte *buf = Buffer;
for (;;)
{
@@ -1095,24 +1621,26 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode)
if (i >= kEcd64Locator_Size)
{
- const Byte *locatorPtr = buf + i - kEcd64Locator_Size;
- if (Get32(locatorPtr) == NSignature::kEcd64Locator)
+ const size_t locatorIndex = i - kEcd64Locator_Size;
+ if (Get32(buf + locatorIndex) == NSignature::kEcd64Locator)
{
CLocator locator;
- locator.Parse(locatorPtr + 4);
- if ((cdInfo.ThisDisk == locator.NumDisks - 1 || cdInfo.ThisDisk == 0xFFFF)
+ locator.Parse(buf + locatorIndex + 4);
+ if ((cdInfo.ThisDisk == locator.NumDisks - 1 || ZIP64_IS_16_MAX(cdInfo.ThisDisk))
&& locator.Ecd64Disk < locator.NumDisks)
{
- if (locator.Ecd64Disk != cdInfo.ThisDisk && cdInfo.ThisDisk != 0xFFFF)
+ if (locator.Ecd64Disk != cdInfo.ThisDisk && !ZIP64_IS_16_MAX(cdInfo.ThisDisk))
return E_NOTIMPL;
// Most of the zip64 use fixed size Zip64 ECD
// we try relative backward reading.
UInt64 absEcd64 = endPos - bufSize + i - (kEcd64Locator_Size + kEcd64_FullSize);
+
+ if (locatorIndex >= kEcd64_FullSize)
if (checkOffsetMode || absEcd64 == locator.Ecd64Offset)
{
- const Byte *ecd64 = locatorPtr - kEcd64_FullSize;
+ const Byte *ecd64 = buf + locatorIndex - kEcd64_FullSize;
if (Get32(ecd64) == NSignature::kEcd64)
{
UInt64 mainEcd64Size = Get64(ecd64 + 4);
@@ -1193,42 +1721,25 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdIn
{
items.Clear();
- ISequentialInStream *stream;
-
- if (!IsMultiVol)
- {
- stream = this->StartStream;
- Vols.StreamIndex = -1;
- RINOK(this->StartStream->Seek(cdOffset, STREAM_SEEK_SET, &m_Position));
- if (m_Position != cdOffset)
- return S_FALSE;
- }
- else
- {
- if (cdInfo.CdDisk >= Vols.Streams.Size())
- return S_FALSE;
- IInStream *str2 = Vols.Streams[cdInfo.CdDisk].Stream;
- if (!str2)
- return S_FALSE;
- RINOK(str2->Seek(cdOffset, STREAM_SEEK_SET, NULL));
- stream = str2;
- Vols.NeedSeek = false;
- Vols.StreamIndex = cdInfo.CdDisk;
- m_Position = cdOffset;
- }
+ RINOK(SeekToVol(IsMultiVol ? cdInfo.CdDisk : -1, cdOffset));
- _inBuffer.SetStream(stream);
-
- _inBuffer.Init();
_inBufMode = true;
+ _cnt = 0;
- _processedCnt = 0;
+ if (Callback)
+ {
+ RINOK(Callback->SetTotal(&cdInfo.NumEntries, IsMultiVol ? &Vols.TotalBytesSize : NULL));
+ }
+ UInt64 numFileExpected = cdInfo.NumEntries;
+ const UInt64 *totalFilesPtr = &numFileExpected;
+ bool isCorrect_NumEntries = (cdInfo.IsFromEcd64 || numFileExpected >= ((UInt32)1 << 16));
- while (_processedCnt < cdSize)
+ while (_cnt < cdSize)
{
CanStartNewVol = true;
if (ReadUInt32() != NSignature::kCentralFileHeader)
return S_FALSE;
+ CanStartNewVol = false;
{
CItemEx cdItem;
RINOK(ReadCdItem(cdItem));
@@ -1237,13 +1748,24 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdIn
if (Callback && (items.Size() & 0xFFF) == 0)
{
const UInt64 numFiles = items.Size();
- RINOK(Callback->SetCompleted(&numFiles, NULL));
+
+ if (numFiles > numFileExpected && totalFilesPtr)
+ {
+ if (isCorrect_NumEntries)
+ totalFilesPtr = NULL;
+ else
+ while (numFiles > numFileExpected)
+ numFileExpected += (UInt32)1 << 16;
+ RINOK(Callback->SetTotal(totalFilesPtr, NULL));
+ }
+
+ RINOK(Callback->SetCompleted(&numFiles, &_cnt));
}
}
CanStartNewVol = true;
- return (_processedCnt == cdSize) ? S_OK : S_FALSE;
+ return (_cnt == cdSize) ? S_OK : S_FALSE;
}
@@ -1275,11 +1797,12 @@ HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64
cdOffset = cdInfo.Offset;
cdDisk = cdInfo.CdDisk;
- if (Callback)
+ if (!IsMultiVol)
{
- RINOK(Callback->SetTotal(&cdInfo.NumEntries, NULL));
+ if (cdInfo.ThisDisk != cdInfo.CdDisk)
+ return S_FALSE;
}
-
+
const UInt64 base = (IsMultiVol ? 0 : ArcInfo.Base);
res = TryReadCd(items, cdInfo, base + cdOffset, cdSize);
@@ -1323,47 +1846,83 @@ static bool IsStrangeItem(const CItem &item)
}
+
+/*
+ ---------- ReadLocals ----------
+
+in:
+ (_signature == NSignature::kLocalFileHeader)
+ VirtStreamPos : after _signature : position in Stream
+ Stream :
+ Vols : if (IsMultiVol)
+ (_inBufMode == false)
+
+action:
+ it parses local items.
+
+ if ( IsMultiVol) it writes absolute offsets to CItemEx::LocalHeaderPos
+ if (!IsMultiVol) it writes relative (from ArcInfo.Base) offsets to CItemEx::LocalHeaderPos
+ later we can correct CItemEx::LocalHeaderPos values, if
+ some new value for ArcInfo.Base will be detected
+out:
+ S_OK:
+ (_signature != NSignature::kLocalFileHeade)
+ _streamPos : after _signature
+
+ S_FALSE: if no items or there is just one item with strange properies that doesn't look like real archive.
+
+ another error code: stream reading error or Callback error.
+
+ CUnexpectEnd() exception : it's not fatal exception here.
+ It means that reading was interrupted by unexpected end of input stream,
+ but some CItemEx items were parsed OK.
+ We can stop further archive parsing.
+ But we can use all filled CItemEx items.
+*/
+
HRESULT CInArchive::ReadLocals(CObjectVector<CItemEx> &items)
{
items.Clear();
+
+ UInt64 progressPrev = _cnt;
- while (m_Signature == NSignature::kLocalFileHeader)
+ if (Callback)
+ {
+ RINOK(Callback->SetTotal(NULL, IsMultiVol ? &Vols.TotalBytesSize : NULL));
+ }
+
+ while (_signature == NSignature::kLocalFileHeader)
{
CItemEx item;
- item.LocalHeaderPos = m_Position - 4;
- if (!IsMultiVol)
- item.LocalHeaderPos -= ArcInfo.MarkerPos;
- // we write ralative LocalHeaderPos here. Later we can correct it to real Base.
+ item.LocalHeaderPos = GetVirtStreamPos() - 4;
+ if (!IsMultiVol)
+ item.LocalHeaderPos -= ArcInfo.Base;
try
{
ReadLocalItem(item);
item.FromLocal = true;
bool isFinished = false;
-
+
if (item.HasDescriptor())
- ReadLocalItemDescriptor(item);
+ {
+ RINOK(FindDescriptor(item, items.Size()));
+ isFinished = !item.DescriptorWasRead;
+ }
else
{
- /*
- if (IsMultiVol)
- {
- const int kStep = 10000;
- RINOK(IncreaseRealPosition(-kStep, isFinished));
- RINOK(IncreaseRealPosition(item.PackSize + kStep, isFinished));
- }
- else
- */
+ if (item.PackSize >= ((UInt64)1 << 62))
+ throw CUnexpectEnd();
RINOK(IncreaseRealPosition(item.PackSize, isFinished));
}
-
+
items.Add(item);
if (isFinished)
throw CUnexpectEnd();
-
- m_Signature = ReadUInt32();
+
+ ReadSignature();
}
catch (CUnexpectEnd &)
{
@@ -1372,17 +1931,18 @@ HRESULT CInArchive::ReadLocals(CObjectVector<CItemEx> &items)
throw;
}
- if (Callback && (items.Size() & 0xFF) == 0)
+
+ if (Callback)
+ if ((items.Size() & 0xFF) == 0
+ || _cnt - progressPrev >= ((UInt32)1 << 22))
{
+ progressPrev = _cnt;
const UInt64 numFiles = items.Size();
- UInt64 numBytes = 0;
- // if (!sMultiVol)
- numBytes = item.LocalHeaderPos;
- RINOK(Callback->SetCompleted(&numFiles, &numBytes));
+ RINOK(Callback->SetCompleted(&numFiles, &_cnt));
}
}
- if (items.Size() == 1 && m_Signature != NSignature::kCentralFileHeader)
+ if (items.Size() == 1 && _signature != NSignature::kCentralFileHeader)
if (IsStrangeItem(items[0]))
return S_FALSE;
@@ -1402,26 +1962,22 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback)
name = prop.bstrVal;
}
- UString base = name;
int dotPos = name.ReverseFind_Dot();
-
if (dotPos < 0)
return S_OK;
-
- base.DeleteFrom(dotPos + 1);
-
const UString ext = name.Ptr(dotPos + 1);
+ name.DeleteFrom(dotPos + 1);
+
StartVolIndex = (Int32)(-1);
if (ext.IsEmpty())
return S_OK;
- else
{
wchar_t c = ext[0];
IsUpperCase = (c >= 'A' && c <= 'Z');
if (ext.IsEqualTo_Ascii_NoCase("zip"))
{
- BaseName = base;
+ BaseName = name;
StartIsZ = true;
StartIsZip = true;
return S_OK;
@@ -1429,8 +1985,13 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback)
else if (ext.IsEqualTo_Ascii_NoCase("exe"))
{
StartIsExe = true;
- BaseName = base;
+ BaseName = name;
StartVolIndex = 0;
+ /* sfx-zip can use both arc.exe and arc.zip
+ We can open arc.zip, if it was requesed to open arc.exe.
+ But it's possible that arc.exe and arc.zip are not parts of same archive.
+ So we can disable such operation */
+ return S_FALSE; // don't open arc.zip instead of arc.exe
}
else if (ext[0] == 'z' || ext[0] == 'Z')
{
@@ -1441,7 +2002,7 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback)
if (*end != 0 || volNum < 1 || volNum > ((UInt32)1 << 30))
return S_OK;
StartVolIndex = volNum - 1;
- BaseName = base;
+ BaseName = name;
StartIsZ = true;
}
else
@@ -1449,9 +2010,11 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback)
}
UString volName = BaseName;
- volName.AddAscii(IsUpperCase ? "ZIP" : "zip");
- HRESULT result = volCallback->GetStream(volName, &ZipStream);
- if (result == S_FALSE || !ZipStream)
+ volName += (IsUpperCase ? "ZIP" : "zip");
+
+ HRESULT res = volCallback->GetStream(volName, &ZipStream);
+
+ if (res == S_FALSE || !ZipStream)
{
if (MissingName.IsEmpty())
{
@@ -1461,7 +2024,7 @@ HRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback)
return S_OK;
}
- return result;
+ return res;
}
@@ -1493,24 +2056,30 @@ HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback,
{
UString volName = Vols.BaseName;
{
- volName += (wchar_t)(Vols.IsUpperCase ? 'Z' : 'z');
+ volName += (char)(Vols.IsUpperCase ? 'Z' : 'z');
+ unsigned v = i + 1;
+ if (v < 10)
+ volName += '0';
+ volName.Add_UInt32(v);
+ }
+
+ HRESULT res = volCallback->GetStream(volName, &stream);
+ if (res != S_OK && res != S_FALSE)
+ return res;
+ if (res == S_FALSE || !stream)
+ {
+ if (i == 0)
{
- char s[32];
- ConvertUInt32ToString(i + 1, s);
- unsigned len = (unsigned)strlen(s);
- while (len < 2)
- {
- volName += (wchar_t)'0';
- len++;
- }
- volName.AddAscii(s);
+ UString volName_exe = Vols.BaseName;
+ volName_exe += (Vols.IsUpperCase ? "EXE" : "exe");
+
+ HRESULT res2 = volCallback->GetStream(volName_exe, &stream);
+ if (res2 != S_OK && res2 != S_FALSE)
+ return res2;
+ res = res2;
}
}
-
- HRESULT result = volCallback->GetStream(volName, &stream);
- if (result != S_OK && result != S_FALSE)
- return result;
- if (result == S_FALSE || !stream)
+ if (res == S_FALSE || !stream)
{
if (Vols.MissingName.IsEmpty())
Vols.MissingName = volName;
@@ -1524,7 +2093,6 @@ HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback,
}
UInt64 size;
-
UInt64 pos;
RINOK(stream->Seek(0, STREAM_SEEK_CUR, &pos));
RINOK(stream->Seek(0, STREAM_SEEK_END, &size));
@@ -1535,6 +2103,8 @@ HRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback,
CVols::CSubStreamInfo &ss = Vols.Streams[i];
Vols.NumVols++;
+ Vols.TotalBytesSize += size;
+
ss.Stream = stream;
ss.Size = size;
@@ -1559,11 +2129,11 @@ HRESULT CInArchive::ReadVols()
RINOK(Vols.ParseArcName(volCallback));
- int startZIndex = Vols.StartVolIndex;
+ // const int startZIndex = Vols.StartVolIndex;
if (!Vols.StartIsZ)
{
- // if (!Vols.StartIsExe)
+ if (!Vols.StartIsExe)
return S_OK;
}
@@ -1573,35 +2143,46 @@ HRESULT CInArchive::ReadVols()
if (Vols.StartIsZip)
Vols.ZipStream = StartStream;
- // bool cdOK = false;
-
if (Vols.ZipStream)
{
Stream = Vols.ZipStream;
+
+ if (Vols.StartIsZip)
+ Vols.StreamIndex = -1;
+ else
+ {
+ Vols.StreamIndex = -2;
+ InitBuf();
+ }
+
HRESULT res = FindCd(true);
+
CCdInfo &ecd = Vols.ecd;
if (res == S_OK)
{
zipDisk = ecd.ThisDisk;
Vols.ecd_wasRead = true;
+
+ // if is not multivol or bad multivol, we return to main single stream code
if (ecd.ThisDisk == 0
|| ecd.ThisDisk >= ((UInt32)1 << 30)
|| ecd.ThisDisk < ecd.CdDisk)
return S_OK;
+
cdDisk = ecd.CdDisk;
if (Vols.StartVolIndex < 0)
Vols.StartVolIndex = ecd.ThisDisk;
+ else if ((UInt32)Vols.StartVolIndex >= ecd.ThisDisk)
+ return S_OK;
+
// Vols.StartVolIndex = ecd.ThisDisk;
// Vols.EndVolIndex = ecd.ThisDisk;
unsigned numMissingVols;
- if (cdDisk == zipDisk)
- {
- // cdOK = true;
- }
- else
+ if (cdDisk != zipDisk)
{
+ // get volumes required for cd.
RINOK(ReadVols2(volCallback, cdDisk, zipDisk, zipDisk, 0, numMissingVols));
- if (numMissingVols == 0)
+ if (numMissingVols != 0)
{
// cdOK = false;
}
@@ -1611,25 +2192,50 @@ HRESULT CInArchive::ReadVols()
return res;
}
- if (Vols.Streams.Size() > 0)
- IsMultiVol = true;
-
if (Vols.StartVolIndex < 0)
+ {
+ // is not mutivol;
return S_OK;
+ }
+ /*
+ if (!Vols.Streams.IsEmpty())
+ IsMultiVol = true;
+ */
+
unsigned numMissingVols;
if (cdDisk != 0)
{
- RINOK(ReadVols2(volCallback, 0, cdDisk < 0 ? -1 : cdDisk, zipDisk, 1 << 10, numMissingVols));
+ // get volumes that were no requested still
+ const unsigned kNumMissingVolsMax = 1 << 12;
+ RINOK(ReadVols2(volCallback, 0, cdDisk < 0 ? -1 : cdDisk, zipDisk, kNumMissingVolsMax, numMissingVols));
+ }
+
+ // if (Vols.StartVolIndex >= 0)
+ {
+ if (Vols.Streams.IsEmpty())
+ if (Vols.StartVolIndex > (1 << 20))
+ return S_OK;
+ if ((unsigned)Vols.StartVolIndex >= Vols.Streams.Size()
+ || !Vols.Streams[Vols.StartVolIndex].Stream)
+ {
+ // we get volumes starting from StartVolIndex, if they we not requested before know the volume index (if FindCd() was ok)
+ RINOK(ReadVols2(volCallback, Vols.StartVolIndex, zipDisk, zipDisk, 0, numMissingVols));
+ }
}
if (Vols.ZipStream)
{
+ // if there is no another volumes and volumeIndex is too big, we don't use multivol mode
if (Vols.Streams.IsEmpty())
if (zipDisk > (1 << 10))
return S_OK;
- RINOK(ReadVols2(volCallback, zipDisk, zipDisk + 1, zipDisk, 0, numMissingVols));
+ if (zipDisk >= 0)
+ {
+ // we create item in Streams for ZipStream, if we know the volume index (if FindCd() was ok)
+ RINOK(ReadVols2(volCallback, zipDisk, zipDisk + 1, zipDisk, 0, numMissingVols));
+ }
}
if (!Vols.Streams.IsEmpty())
@@ -1639,11 +2245,14 @@ HRESULT CInArchive::ReadVols()
if (cdDisk)
IsMultiVol = true;
*/
+ const int startZIndex = Vols.StartVolIndex;
if (startZIndex >= 0)
{
- if (Vols.Streams.Size() >= (unsigned)startZIndex)
+ // if all volumes before start volume are OK, we can start parsing from 0
+ // if there are missing volumes before startZIndex, we start parsing in current startZIndex
+ if ((unsigned)startZIndex < Vols.Streams.Size())
{
- for (unsigned i = 0; i < (unsigned)startZIndex; i++)
+ for (unsigned i = 0; i <= (unsigned)startZIndex; i++)
if (!Vols.Streams[i].Stream)
{
Vols.StartParsingVol = startZIndex;
@@ -1658,10 +2267,6 @@ HRESULT CInArchive::ReadVols()
-
-
-
-
HRESULT CVols::Read(void *data, UInt32 size, UInt32 *processedSize)
{
if (processedSize)
@@ -1680,7 +2285,7 @@ HRESULT CVols::Read(void *data, UInt32 size, UInt32 *processedSize)
return S_FALSE;
if (NeedSeek)
{
- RINOK(s.Stream->Seek(0, STREAM_SEEK_SET, NULL));
+ RINOK(s.SeekToStart());
NeedSeek = false;
}
UInt32 realProcessedSize = 0;
@@ -1704,47 +2309,112 @@ STDMETHODIMP CVolStream::Read(void *data, UInt32 size, UInt32 *processedSize)
-#define COPY_ECD_ITEM_16(n) if (!isZip64 || ecd. n != 0xFFFF) ecd64. n = ecd. n;
-#define COPY_ECD_ITEM_32(n) if (!isZip64 || ecd. n != 0xFFFFFFFF) ecd64. n = ecd. n;
+#define COPY_ECD_ITEM_16(n) if (!isZip64 || !ZIP64_IS_16_MAX(ecd. n)) cdInfo. n = ecd. n;
+#define COPY_ECD_ITEM_32(n) if (!isZip64 || !ZIP64_IS_32_MAX(ecd. n)) cdInfo. n = ecd. n;
-HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items)
+HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)
{
+ if (Buffer.Size() < kSeqBufferSize)
+ {
+ InitBuf();
+ Buffer.AllocAtLeast(kSeqBufferSize);
+ if (!Buffer.IsAllocated())
+ return E_OUTOFMEMORY;
+ }
+
+ _inBufMode = false;
+
HRESULT res = S_OK;
bool localsWereRead = false;
- UInt64 cdSize = 0, cdRelatOffset = 0, cdAbsOffset = 0;
+
+ /* we try to open archive with the following modes:
+ 1) CD-MODE : fast mode : we read backward ECD and CD, compare CD items with first Local item.
+ 2) LOCALS-CD-MODE : slow mode, if CD-MODE fails : we sequentially read all Locals and then CD.
+ Then we read sequentially ECD64, Locator, ECD again at the end.
+
+ - in LOCALS-CD-MODE we use use the following
+ variables (with real cd properties) to set Base archive offset
+ and check real cd properties with values from ECD/ECD64.
+ */
+
+ UInt64 cdSize = 0;
+ UInt64 cdRelatOffset = 0;
UInt32 cdDisk = 0;
- if (!_inBuffer.Create(1 << 15))
- return E_OUTOFMEMORY;
+ UInt64 cdAbsOffset = 0; // absolute cd offset, for LOCALS-CD-MODE only.
- if (!MarkerIsFound)
+ if (!MarkerIsFound || !MarkerIsSafe)
{
IsArc = true;
res = ReadCd(items, cdDisk, cdRelatOffset, cdSize);
if (res == S_OK)
- m_Signature = ReadUInt32();
+ ReadSignature();
+ else if (res != S_FALSE)
+ return res;
}
else
{
- // m_Signature must be kLocalFileHeader or kEcd
- // m_Position points to next byte after signature
- RINOK(Stream->Seek(m_Position, STREAM_SEEK_SET, NULL));
+ // _signature must be kLocalFileHeader or kEcd or kEcd64
+
+ SeekToVol(ArcInfo.MarkerVolIndex, ArcInfo.MarkerPos2 + 4);
+
+ CanStartNewVol = false;
+
+ if (_signature == NSignature::kEcd64)
+ {
+ // UInt64 ecd64Offset = GetVirtStreamPos() - 4;
+ IsZip64 = true;
- _inBuffer.SetStream(Stream);
+ {
+ const UInt64 recordSize = ReadUInt64();
+ if (recordSize < kEcd64_MainSize)
+ return S_FALSE;
+ if (recordSize >= ((UInt64)1 << 62))
+ return S_FALSE;
+
+ {
+ const unsigned kBufSize = kEcd64_MainSize;
+ Byte buf[kBufSize];
+ SafeRead(buf, kBufSize);
+ CCdInfo cdInfo;
+ cdInfo.ParseEcd64e(buf);
+ if (!cdInfo.IsEmptyArc())
+ return S_FALSE;
+ }
+
+ RINOK(Skip64(recordSize - kEcd64_MainSize, 0));
+ }
+
+ ReadSignature();
+ if (_signature != NSignature::kEcd64Locator)
+ return S_FALSE;
- bool needReadCd = true;
+ {
+ const unsigned kBufSize = 16;
+ Byte buf[kBufSize];
+ SafeRead(buf, kBufSize);
+ CLocator locator;
+ locator.Parse(buf);
+ if (!locator.IsEmptyArc())
+ return S_FALSE;
+ }
- if (m_Signature == NSignature::kEcd)
+ ReadSignature();
+ if (_signature != NSignature::kEcd)
+ return S_FALSE;
+ }
+
+ if (_signature == NSignature::kEcd)
{
// It must be empty archive or backware archive
// we don't support backware archive still
const unsigned kBufSize = kEcdSize - 4;
Byte buf[kBufSize];
- SafeReadBytes(buf, kBufSize);
+ SafeRead(buf, kBufSize);
CEcd ecd;
ecd.Parse(buf);
// if (ecd.cdSize != 0)
@@ -1753,15 +2423,15 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items)
return S_FALSE;
ArcInfo.Base = ArcInfo.MarkerPos;
- needReadCd = false;
IsArc = true; // check it: we need more tests?
- RINOK(Stream->Seek(ArcInfo.MarkerPos2 + 4, STREAM_SEEK_SET, &m_Position));
- }
- if (needReadCd)
+ RINOK(SeekToVol(ArcInfo.MarkerVolIndex, ArcInfo.MarkerPos2));
+ ReadSignature();
+ }
+ else
{
CItemEx firstItem;
- // try
+ try
{
try
{
@@ -1776,9 +2446,10 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items)
IsArc = true;
res = ReadCd(items, cdDisk, cdRelatOffset, cdSize);
if (res == S_OK)
- m_Signature = ReadUInt32();
+ ReadSignature();
}
- // catch() { res = S_FALSE; }
+ catch(CUnexpectEnd &) { res = S_FALSE; }
+
if (res != S_FALSE && res != S_OK)
return res;
@@ -1812,52 +2483,93 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items)
CObjectVector<CItemEx> cdItems;
- bool needSetBase = false;
+ bool needSetBase = false; // we set needSetBase only for LOCALS_CD_MODE
unsigned numCdItems = items.Size();
- if (res == S_FALSE)
+ #ifdef ZIP_SELF_CHECK
+ res = S_FALSE; // if uncommented, it uses additional LOCALS-CD-MODE mode to check the code
+ #endif
+
+ if (res != S_OK)
{
+ // ---------- LOCALS-CD-MODE ----------
// CD doesn't match firstItem,
- // so we clear items and read Locals.
+ // so we clear items and read Locals and CD.
+
items.Clear();
localsWereRead = true;
+
+ // 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
+
_inBufMode = false;
- ArcInfo.Base = ArcInfo.MarkerPos;
+ // _inBufMode = true;
- if (IsMultiVol)
+ InitBuf();
+
+ ArcInfo.Base = 0;
+
+ if (!MarkerIsFound)
{
- Vols.StreamIndex = Vols.StartParsingVol;
- if (Vols.StartParsingVol >= (int)Vols.Streams.Size())
+ if (!IsMultiVol)
return S_FALSE;
- Stream = Vols.Streams[Vols.StartParsingVol].Stream;
- if (!Stream)
+ if (Vols.StartParsingVol != 0)
return S_FALSE;
+ // if (StartParsingVol == 0) and we didn't find marker, we use default zero marker.
+ // so we suppose that there is no sfx stub
+ RINOK(SeekToVol(0, ArcInfo.MarkerPos2));
}
+ else
+ {
+ if (ArcInfo.MarkerPos != 0)
+ {
+ /*
+ If multi-vol or there is (No)Span-marker at start of stream, we set (Base) as 0.
+ In another caes:
+ (No)Span-marker is supposed as false positive. So we set (Base) as main marker (MarkerPos2).
+ The (Base) can be corrected later after ECD reading.
+ But sfx volume with stub and (No)Span-marker in (!IsMultiVol) mode will have incorrect (Base) here.
+ */
+ ArcInfo.Base = ArcInfo.MarkerPos2;
+ }
+
+ RINOK(SeekToVol(ArcInfo.MarkerVolIndex, ArcInfo.MarkerPos2));
+ }
+
+ _cnt = 0;
- RINOK(Stream->Seek(ArcInfo.MarkerPos2, STREAM_SEEK_SET, &m_Position));
- m_Signature = ReadUInt32();
+ ReadSignature();
+ LocalsWereRead = true;
+
RINOK(ReadLocals(items));
- if (m_Signature != NSignature::kCentralFileHeader)
+ if (_signature != NSignature::kCentralFileHeader)
{
- // if (!UnexpectedEnd)
- m_Position -= 4;
+ // GetVirtStreamPos() - 4
+ if (items.IsEmpty())
+ return S_FALSE;
NoCentralDir = true;
HeadersError = true;
return S_OK;
}
_inBufMode = true;
- _inBuffer.Init();
-
- cdAbsOffset = m_Position - 4;
+
+ cdAbsOffset = GetVirtStreamPos() - 4;
cdDisk = Vols.StreamIndex;
+ #ifdef ZIP_SELF_CHECK
+ if (!IsMultiVol && _cnt != GetVirtStreamPos() - ArcInfo.MarkerPos2)
+ return E_FAIL;
+ #endif
+
+ const UInt64 processedCnt_start = _cnt;
+
for (;;)
{
CItemEx cdItem;
- CanStartNewVol = true;
RINOK(ReadCdItem(cdItem));
@@ -1865,17 +2577,29 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items)
if (Callback && (cdItems.Size() & 0xFFF) == 0)
{
const UInt64 numFiles = items.Size();
- RINOK(Callback->SetCompleted(&numFiles, NULL));
+ const UInt64 numBytes = _cnt;
+ RINOK(Callback->SetCompleted(&numFiles, &numBytes));
}
- CanStartNewVol = true;
- m_Signature = ReadUInt32();
- if (m_Signature != NSignature::kCentralFileHeader)
+ ReadSignature();
+ if (_signature != NSignature::kCentralFileHeader)
break;
}
- cdSize = (m_Position - 4) - cdAbsOffset;
+ cdSize = _cnt - processedCnt_start;
+
+ #ifdef ZIP_SELF_CHECK
+ if (!IsMultiVol)
+ {
+ if (_cnt != GetVirtStreamPos() - ArcInfo.MarkerPos2)
+ return E_FAIL;
+ if (cdSize != (GetVirtStreamPos() - 4) - cdAbsOffset)
+ return E_FAIL;
+ }
+ #endif
+
needSetBase = true;
numCdItems = cdItems.Size();
+ cdRelatOffset = cdAbsOffset - ArcInfo.Base;
if (!cdItems.IsEmpty())
{
@@ -1886,13 +2610,13 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items)
- CCdInfo ecd64;
+ CCdInfo cdInfo;
CLocator locator;
bool isZip64 = false;
- const UInt64 ecd64AbsOffset = m_Position - 4;
+ const UInt64 ecd64AbsOffset = GetVirtStreamPos() - 4;
int ecd64Disk = -1;
- if (m_Signature == NSignature::kEcd64)
+ if (_signature == NSignature::kEcd64)
{
ecd64Disk = Vols.StreamIndex;
@@ -1900,26 +2624,27 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items)
{
const UInt64 recordSize = ReadUInt64();
- if (recordSize < kEcd64_MainSize)
+ if (recordSize < kEcd64_MainSize
+ || recordSize >= ((UInt64)1 << 62))
{
HeadersError = true;
return S_OK;
}
-
+
{
const unsigned kBufSize = kEcd64_MainSize;
Byte buf[kBufSize];
- SafeReadBytes(buf, kBufSize);
- ecd64.ParseEcd64e(buf);
+ SafeRead(buf, kBufSize);
+ cdInfo.ParseEcd64e(buf);
}
- Skip64(recordSize - kEcd64_MainSize);
+ RINOK(Skip64(recordSize - kEcd64_MainSize, items.Size()));
}
- m_Signature = ReadUInt32();
+ ReadSignature();
- if (m_Signature != NSignature::kEcd64Locator)
+ if (_signature != NSignature::kEcd64Locator)
{
HeadersError = true;
return S_OK;
@@ -1928,28 +2653,30 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items)
{
const unsigned kBufSize = 16;
Byte buf[kBufSize];
- SafeReadBytes(buf, kBufSize);
+ SafeRead(buf, kBufSize);
locator.Parse(buf);
}
- m_Signature = ReadUInt32();
+ ReadSignature();
}
- if (m_Signature != NSignature::kEcd)
+ if (_signature != NSignature::kEcd)
{
HeadersError = true;
return S_OK;
}
+ CanStartNewVol = false;
+
// ---------- ECD ----------
CEcd ecd;
{
const unsigned kBufSize = kEcdSize - 4;
Byte buf[kBufSize];
- SafeReadBytes(buf, kBufSize);
+ SafeRead(buf, kBufSize);
ecd.Parse(buf);
}
@@ -1960,34 +2687,103 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items)
COPY_ECD_ITEM_32(Size);
COPY_ECD_ITEM_32(Offset);
+ bool cdOK = true;
+
+ if ((UInt32)cdInfo.Size != (UInt32)cdSize)
+ {
+ // return S_FALSE;
+ cdOK = false;
+ }
+
+ if (isZip64)
+ {
+ if (cdInfo.NumEntries != numCdItems
+ || cdInfo.Size != cdSize)
+ {
+ cdOK = false;
+ }
+ }
+
+
if (IsMultiVol)
{
- if (cdDisk != (int)ecd64.CdDisk)
+ if (cdDisk != (int)cdInfo.CdDisk)
HeadersError = true;
}
- else if (needSetBase)
+ else if (needSetBase && cdOK)
{
+ const UInt64 oldBase = ArcInfo.Base;
+ // localsWereRead == true
+ // ArcInfo.Base == ArcInfo.MarkerPos2
+ // cdRelatOffset == (cdAbsOffset - ArcInfo.Base)
+
if (isZip64)
{
if (ecd64Disk == Vols.StartVolIndex)
{
- ArcInfo.Base = ecd64AbsOffset - locator.Ecd64Offset;
- // cdRelatOffset = ecd64.Offset;
- needSetBase = false;
+ const Int64 newBase = (Int64)ecd64AbsOffset - locator.Ecd64Offset;
+ if (newBase <= (Int64)ecd64AbsOffset)
+ {
+ if (!localsWereRead || newBase <= (Int64)ArcInfo.MarkerPos2)
+ {
+ ArcInfo.Base = newBase;
+ cdRelatOffset = cdAbsOffset - newBase;
+ }
+ else
+ cdOK = false;
+ }
}
}
- else
+ else if (numCdItems != 0) // we can't use ecd.Offset in empty archive?
{
if ((int)cdDisk == Vols.StartVolIndex)
{
- ArcInfo.Base = cdAbsOffset - ecd64.Offset;
- cdRelatOffset = ecd64.Offset;
- needSetBase = false;
+ const Int64 newBase = (Int64)cdAbsOffset - cdInfo.Offset;
+ if (newBase <= (Int64)cdAbsOffset)
+ {
+ if (!localsWereRead || newBase <= (Int64)ArcInfo.MarkerPos2)
+ {
+ // cd can be more accurate, when it points before Locals
+ // so we change Base and cdRelatOffset
+ ArcInfo.Base = newBase;
+ cdRelatOffset = cdInfo.Offset;
+ }
+ else
+ {
+ // const UInt64 delta = ((UInt64)cdRelatOffset - cdInfo.Offset);
+ const UInt64 delta = ((UInt64)(newBase - ArcInfo.Base));
+ if ((UInt32)delta == 0)
+ {
+ // we set Overflow32bit mode, only if there is (x<<32) offset
+ // between real_CD_offset_from_MarkerPos and CD_Offset_in_ECD.
+ // Base and cdRelatOffset unchanged
+ Overflow32bit = true;
+ }
+ else
+ cdOK = false;
+ }
+ }
+ else
+ cdOK = false;
+ }
+ }
+ // cdRelatOffset = cdAbsOffset - ArcInfo.Base;
+
+ if (localsWereRead)
+ {
+ const UInt64 delta = oldBase - ArcInfo.Base;
+ if (delta != 0)
+ {
+ FOR_VECTOR (i, items)
+ items[i].LocalHeaderPos += delta;
}
}
}
- EcdVolIndex = ecd64.ThisDisk;
+ if (!cdOK)
+ HeadersError = true;
+
+ EcdVolIndex = cdInfo.ThisDisk;
if (!IsMultiVol)
{
@@ -1997,54 +2793,80 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items)
Vols.MissingZip = false;
}
- UseDisk_in_SingleVol = true;
-
if (localsWereRead)
{
- if ((UInt64)ArcInfo.Base != ArcInfo.MarkerPos)
- {
- const UInt64 delta = ArcInfo.MarkerPos - ArcInfo.Base;
- FOR_VECTOR (i, items)
- items[i].LocalHeaderPos += delta;
- }
-
if (EcdVolIndex != 0)
{
FOR_VECTOR (i, items)
items[i].Disk = EcdVolIndex;
}
}
+
+ UseDisk_in_SingleVol = true;
}
if (isZip64)
{
- if (ecd64.ThisDisk == 0 && ecd64AbsOffset != ArcInfo.Base + locator.Ecd64Offset
- // || ecd64.NumEntries_in_ThisDisk != numCdItems
- || ecd64.NumEntries != numCdItems
- || ecd64.Size != cdSize
- || (ecd64.Offset != cdRelatOffset && !items.IsEmpty()))
+ if (cdInfo.ThisDisk == 0 && ecd64AbsOffset != ArcInfo.Base + locator.Ecd64Offset
+ // || cdInfo.NumEntries_in_ThisDisk != numCdItems
+ || cdInfo.NumEntries != numCdItems
+ || cdInfo.Size != cdSize
+ || (cdInfo.Offset != cdRelatOffset && !items.IsEmpty()))
{
HeadersError = true;
return S_OK;
}
}
- // ---------- merge Central Directory Items ----------
-
- if (!cdItems.IsEmpty())
+ if (cdOK && !cdItems.IsEmpty())
{
- CObjectVector<CItemEx> items2;
+ // ---------- merge Central Directory Items ----------
+
+ CRecordVector<unsigned> items2;
+
+ int nextLocalIndex = 0;
+
+ LocalsCenterMerged = true;
FOR_VECTOR (i, cdItems)
{
+ if (Callback)
+ if ((i & 0x3FFF) == 0)
+ {
+ const UInt64 numFiles64 = items.Size() + items2.Size();
+ RINOK(Callback->SetCompleted(&numFiles64, &_cnt));
+ }
+
const CItemEx &cdItem = cdItems[i];
- int index = FindItem(items, cdItem);
+
+ int index = -1;
+
+ if (nextLocalIndex != -1)
+ {
+ if ((unsigned)nextLocalIndex < items.Size())
+ {
+ CItemEx &item = items[nextLocalIndex];
+ if (item.Disk == cdItem.Disk &&
+ (item.LocalHeaderPos == cdItem.LocalHeaderPos
+ || Overflow32bit && (UInt32)item.LocalHeaderPos == cdItem.LocalHeaderPos))
+ index = nextLocalIndex++;
+ else
+ nextLocalIndex = -1;
+ }
+ }
+
+ if (index == -1)
+ index = FindItem(items, cdItem);
+
+ // index = -1;
+
if (index == -1)
{
- items2.Add(cdItem);
+ items2.Add(i);
HeadersError = true;
continue;
}
+
CItemEx &item = items[index];
if (item.Name != cdItem.Name
// || item.Name.Len() != cdItem.Name.Len()
@@ -2067,10 +2889,10 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items)
item.FromCentral = cdItem.FromCentral;
}
- items += items2;
+ FOR_VECTOR (k, items2)
+ items.Add(cdItems[items2[k]]);
}
-
if (ecd.NumEntries < ecd.NumEntries_in_ThisDisk)
HeadersError = true;
@@ -2083,35 +2905,56 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items)
}
}
- if (ecd.NumEntries > items.Size())
- HeadersError = true;
-
if (isZip64)
{
- if (ecd64.NumEntries != items.Size())
+ if (cdInfo.NumEntries != items.Size()
+ || ecd.NumEntries != items.Size() && ecd.NumEntries != 0xFFFF)
HeadersError = true;
}
else
{
// old 7-zip could store 32-bit number of CD items to 16-bit field.
- /*
- if ((UInt16)ecd64.NumEntries == (UInt16)items.Size())
+ // if (ecd.NumEntries != items.Size())
+ if (ecd.NumEntries > items.Size())
HeadersError = true;
- */
+
+ if (cdInfo.NumEntries != numCdItems)
+ {
+ if ((UInt16)cdInfo.NumEntries != (UInt16)numCdItems)
+ HeadersError = true;
+ else
+ Cd_NumEntries_Overflow_16bit = true;
+ }
}
ReadBuffer(ArcInfo.Comment, ecd.CommentSize);
+
_inBufMode = false;
- _inBuffer.Free();
- if ((UInt16)ecd64.NumEntries != (UInt16)numCdItems
- || (UInt32)ecd64.Size != (UInt32)cdSize
- || ((UInt32)ecd64.Offset != (UInt32)cdRelatOffset && !items.IsEmpty()))
+ // DisableBufMode();
+ // Buffer.Free();
+ /* we can't clear buf varibles. we need them to calculate PhySize of archive */
+
+ if ((UInt16)cdInfo.NumEntries != (UInt16)numCdItems
+ || (UInt32)cdInfo.Size != (UInt32)cdSize
+ || ((UInt32)cdInfo.Offset != (UInt32)cdRelatOffset && !items.IsEmpty()))
{
// return S_FALSE;
HeadersError = true;
}
-
+
+ #ifdef ZIP_SELF_CHECK
+ if (localsWereRead)
+ {
+ const UInt64 endPos = ArcInfo.MarkerPos2 + _cnt;
+ if (endPos != (IsMultiVol ? Vols.TotalBytesSize : ArcInfo.FileEndPos))
+ {
+ // there are some data after the end of archive or error in code;
+ return E_FAIL;
+ }
+ }
+ #endif
+
// printf("\nOpen OK");
return S_OK;
}
@@ -2121,40 +2964,47 @@ HRESULT CInArchive::ReadHeaders2(CObjectVector<CItemEx> &items)
HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit,
IArchiveOpenCallback *callback, CObjectVector<CItemEx> &items)
{
- _inBufMode = false;
items.Clear();
Close();
- ArcInfo.Clear();
UInt64 startPos;
RINOK(stream->Seek(0, STREAM_SEEK_CUR, &startPos));
RINOK(stream->Seek(0, STREAM_SEEK_END, &ArcInfo.FileEndPos));
- m_Position = ArcInfo.FileEndPos;
+ _streamPos = ArcInfo.FileEndPos;
StartStream = stream;
+ Stream = stream;
Callback = callback;
+
+ DisableBufMode();
bool volWasRequested = false;
if (callback
&& (startPos == 0 || !searchLimit || *searchLimit != 0))
{
+ // we try to read volumes only if it's first call (offset == 0) or scan is allowed.
volWasRequested = true;
RINOK(ReadVols());
}
- if (IsMultiVol && Vols.StartVolIndex != 0)
+ if (IsMultiVol && Vols.StartParsingVol == 0 && (unsigned)Vols.StartParsingVol < Vols.Streams.Size())
{
- Stream = Vols.Streams[0].Stream;
- if (Stream)
+ // only StartParsingVol = 0 is safe search.
+ RINOK(SeekToVol(0, 0));
+ // if (Stream)
{
- m_Position = 0;
- RINOK(Stream->Seek(0, STREAM_SEEK_SET, NULL));
- UInt64 limit = 0;
- HRESULT res = FindMarker(Stream, &limit);
+ // UInt64 limit = 1 << 22; // for sfx
+ UInt64 limit = 0; // without sfx
+
+ HRESULT res = FindMarker(&limit);
+
if (res == S_OK)
+ {
MarkerIsFound = true;
+ MarkerIsSafe = true;
+ }
else if (res != S_FALSE)
return res;
}
@@ -2162,56 +3012,93 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit,
else
{
// printf("\nOpen offset = %u\n", (unsigned)startPos);
- RINOK(stream->Seek(startPos, STREAM_SEEK_SET, NULL));
- m_Position = startPos;
- HRESULT res = FindMarker(stream, searchLimit);
- UInt64 curPos = m_Position;
+ if (IsMultiVol && (unsigned)Vols.StartParsingVol < Vols.Streams.Size() && Vols.Streams[Vols.StartParsingVol].Stream)
+ {
+ RINOK(SeekToVol(Vols.StartParsingVol, Vols.StreamIndex == Vols.StartVolIndex ? startPos : 0));
+ }
+ else
+ {
+ RINOK(SeekToVol(-1, startPos));
+ }
+
+ // UInt64 limit = 1 << 22;
+ // HRESULT res = FindMarker(&limit);
+
+ HRESULT res = FindMarker(searchLimit);
+
+ // const UInt64 curPos = GetVirtStreamPos();
+ const UInt64 curPos = ArcInfo.MarkerPos2 + 4;
+
if (res == S_OK)
MarkerIsFound = true;
- else
+ else if (!IsMultiVol)
{
- // if (res != S_FALSE)
+ /*
+ // if (startPos != 0), probably CD copuld be already tested with another call with (startPos == 0).
+ // so we don't want to try to open CD again in that ase.
+ if (startPos != 0)
+ return res;
+ // we can try to open CD, if there is no Marker and (startPos == 0).
+ // is it OK to open such files as ZIP, or big number of false positive, when CD can be find in end of file ?
+ */
return res;
}
-
- MarkerIsFound = true;
if (ArcInfo.IsSpanMode && !volWasRequested)
{
RINOK(ReadVols());
+ if (IsMultiVol && MarkerIsFound && ArcInfo.MarkerVolIndex < 0)
+ ArcInfo.MarkerVolIndex = Vols.StartVolIndex;
}
+
+ MarkerIsSafe = !IsMultiVol
+ || (ArcInfo.MarkerVolIndex == 0 && ArcInfo.MarkerPos == 0)
+ ;
- if (IsMultiVol && (unsigned)Vols.StartVolIndex < Vols.Streams.Size())
+
+ if (IsMultiVol)
{
- Stream = Vols.Streams[Vols.StartVolIndex].Stream;
- if (!Stream)
- IsMultiVol = false;
- else
+ if ((unsigned)Vols.StartVolIndex < Vols.Streams.Size())
{
- RINOK(Stream->Seek(curPos, STREAM_SEEK_SET, NULL));
- m_Position = curPos;
+ Stream = Vols.Streams[Vols.StartVolIndex].Stream;
+ if (Stream)
+ {
+ RINOK(Seek_SavePos(curPos));
+ }
+ else
+ IsMultiVol = false;
}
+ else
+ IsMultiVol = false;
}
- else
- IsMultiVol = false;
if (!IsMultiVol)
{
- RINOK(stream->Seek(curPos, STREAM_SEEK_SET, NULL));
- m_Position = curPos;
+ if (Vols.StreamIndex != -1)
+ {
+ Stream = StartStream;
+ Vols.StreamIndex = -1;
+ InitBuf();
+ RINOK(Seek_SavePos(curPos));
+ }
+
+ ArcInfo.MarkerVolIndex = -1;
StreamRef = stream;
Stream = stream;
}
}
+ if (!IsMultiVol)
+ Vols.ClearRefs();
+
{
HRESULT res;
try
{
- res = ReadHeaders2(items);
+ res = ReadHeaders(items);
}
- catch (const CInBufferException &e) { res = e.ErrorCode; }
+ catch (const CSystemException &e) { res = e.ErrorCode; }
catch (const CUnexpectEnd &)
{
if (items.IsEmpty())
@@ -2221,7 +3108,7 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit,
}
catch (...)
{
- _inBufMode = false;
+ DisableBufMode();
throw;
}
@@ -2229,16 +3116,17 @@ HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit,
{
ArcInfo.FinishPos = ArcInfo.FileEndPos;
if ((unsigned)Vols.StreamIndex < Vols.Streams.Size())
- if (m_Position < Vols.Streams[Vols.StreamIndex].Size)
+ if (GetVirtStreamPos() < Vols.Streams[Vols.StreamIndex].Size)
ArcInfo.ThereIsTail = true;
}
else
{
- ArcInfo.FinishPos = m_Position;
- ArcInfo.ThereIsTail = (ArcInfo.FileEndPos > m_Position);
+ ArcInfo.FinishPos = GetVirtStreamPos();
+ ArcInfo.ThereIsTail = (ArcInfo.FileEndPos > ArcInfo.FinishPos);
}
- _inBufMode = false;
+ DisableBufMode();
+
IsArcOpen = true;
if (!IsMultiVol)
Vols.Streams.Clear();
diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h
index 9b0afe28..a312c36a 100644
--- a/CPP/7zip/Archive/Zip/ZipIn.h
+++ b/CPP/7zip/Archive/Zip/ZipIn.h
@@ -3,12 +3,11 @@
#ifndef __ZIP_IN_H
#define __ZIP_IN_H
+#include "../../../Common/MyBuffer2.h"
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
-#include "../../Common/InBuffer.h"
-
#include "ZipHeader.h"
#include "ZipItem.h"
@@ -22,8 +21,12 @@ class CItemEx: public CItem
public:
UInt32 LocalFullHeaderSize; // including Name and Extra
+ bool DescriptorWasRead;
+
+ CItemEx(): DescriptorWasRead(false) {}
+
UInt64 GetLocalFullSize() const
- { return LocalFullHeaderSize + PackSize + (HasDescriptor() ? kDataDescriptorSize : 0); }
+ { return LocalFullHeaderSize + GetPackSizeWithDescriptor(); }
UInt64 GetDataPosition() const
{ return LocalHeaderPos + LocalFullHeaderSize; }
};
@@ -52,6 +55,10 @@ struct CInArchiveInfo
UInt64 FirstItemRelatOffset; /* Relative offset of first local (read from cd) (relative to Base).
= 0 in most archives
= size of stub for some SFXs */
+
+
+ int MarkerVolIndex;
+
bool CdWasRead;
bool IsSpanMode;
bool ThereIsTail;
@@ -68,6 +75,7 @@ struct CInArchiveInfo
FinishPos(0),
FileEndPos(0),
FirstItemRelatOffset(0),
+ MarkerVolIndex(-1),
CdWasRead(false),
IsSpanMode(false),
ThereIsTail(false)
@@ -82,6 +90,7 @@ struct CInArchiveInfo
MarkerPos2 = 0;
FinishPos = 0;
FileEndPos = 0;
+ MarkerVolIndex = -1;
ThereIsTail = false;
FirstItemRelatOffset = 0;
@@ -96,6 +105,10 @@ struct CInArchiveInfo
struct CCdInfo
{
+ bool IsFromEcd64;
+
+ UInt16 CommentSize;
+
// 64
UInt16 VersionMade;
UInt16 VersionNeedExtract;
@@ -108,39 +121,55 @@ struct CCdInfo
UInt64 Size;
UInt64 Offset;
- UInt16 CommentSize;
-
- CCdInfo() { memset(this, 0, sizeof(*this)); }
+ CCdInfo() { memset(this, 0, sizeof(*this)); IsFromEcd64 = false; }
void ParseEcd32(const Byte *p); // (p) includes signature
void ParseEcd64e(const Byte *p); // (p) exclude signature
+
+ bool IsEmptyArc() const
+ {
+ return ThisDisk == 0
+ && CdDisk == 0
+ && NumEntries_in_ThisDisk == 0
+ && NumEntries == 0
+ && Size == 0
+ && Offset == 0 // test it
+ ;
+ }
};
-class CVols
+struct CVols
{
-public:
-
struct CSubStreamInfo
{
CMyComPtr<IInStream> Stream;
UInt64 Size;
+ HRESULT SeekToStart() const { return Stream->Seek(0, STREAM_SEEK_SET, NULL); }
+
CSubStreamInfo(): Size(0) {}
};
CObjectVector<CSubStreamInfo> Streams;
- int StreamIndex;
+
+ int StreamIndex; // -1 for StartStream
+ // -2 for ZipStream at multivol detection code
+ // >=0 volume index in multivol
+
bool NeedSeek;
- CMyComPtr<IInStream> ZipStream;
-
bool StartIsExe; // is .exe
bool StartIsZ; // is .zip or .zNN
bool StartIsZip; // is .zip
bool IsUpperCase;
bool MissingZip;
- Int32 StartVolIndex; // = (NN - 1), if StartStream is .zNN
+
+ bool ecd_wasRead;
+
+ Int32 StartVolIndex; // -1, if unknown vol index
+ // = (NN - 1), if StartStream is .zNN
+ // = 0, if start vol is exe
Int32 StartParsingVol; // if we need local parsing, we must use that stream
unsigned NumVols;
@@ -148,19 +177,27 @@ public:
int EndVolIndex; // index of last volume (ecd volume),
// -1, if is not multivol
- UString BaseName; // including '.'
-
+ UString BaseName; // name of archive including '.'
UString MissingName;
+ CMyComPtr<IInStream> ZipStream;
+
CCdInfo ecd;
- bool ecd_wasRead;
+
+ UInt64 TotalBytesSize; // for MultiVol only
+
+ void ClearRefs()
+ {
+ Streams.Clear();
+ ZipStream.Release();
+ TotalBytesSize = 0;
+ }
void Clear()
{
StreamIndex = -1;
NeedSeek = false;
-
StartIsExe = false;
StartIsZ = false;
StartIsZip = false;
@@ -177,21 +214,12 @@ public:
MissingZip = false;
ecd_wasRead = false;
- Streams.Clear();
- ZipStream.Release();
+ ClearRefs();
}
HRESULT ParseArcName(IArchiveOpenVolumeCallback *volCallback);
HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);
-
- UInt64 GetTotalSize() const
- {
- UInt64 total = 0;
- FOR_VECTOR (i, Streams)
- total += Streams[i].Size;
- return total;
- }
};
@@ -210,44 +238,69 @@ public:
class CInArchive
{
- CInBuffer _inBuffer;
+ CMidBuffer Buffer;
+ size_t _bufPos;
+ size_t _bufCached;
+
+ UInt64 _streamPos;
+ UInt64 _cnt;
+
+ size_t GetAvail() const { return _bufCached - _bufPos; }
+
+ void InitBuf() { _bufPos = 0; _bufCached = 0; }
+ void DisableBufMode() { InitBuf(); _inBufMode = false; }
+
+ void SkipLookahed(size_t skip)
+ {
+ _bufPos += skip;
+ _cnt += skip;
+ }
+
+ UInt64 GetVirtStreamPos() { return _streamPos - _bufCached + _bufPos; }
+
bool _inBufMode;
- UInt32 m_Signature;
- UInt64 m_Position;
- UInt64 _processedCnt;
-
+ bool IsArcOpen;
bool CanStartNewVol;
+ UInt32 _signature;
+
CMyComPtr<IInStream> StreamRef;
IInStream *Stream;
IInStream *StartStream;
+ IArchiveOpenCallback *Callback;
- bool IsArcOpen;
+ HRESULT Seek_SavePos(UInt64 offset);
+ HRESULT SeekToVol(int volIndex, UInt64 offset);
+
+ HRESULT ReadFromCache(Byte *data, unsigned size, unsigned &processed);
HRESULT ReadVols2(IArchiveOpenVolumeCallback *volCallback,
unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols);
HRESULT ReadVols();
- HRESULT Seek(UInt64 offset);
- HRESULT FindMarker(IInStream *stream, const UInt64 *searchLimit);
- HRESULT IncreaseRealPosition(Int64 addValue, bool &isFinished);
+ HRESULT FindMarker(const UInt64 *searchLimit);
+ HRESULT IncreaseRealPosition(UInt64 addValue, bool &isFinished);
- HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize);
- void SafeReadBytes(void *data, unsigned size);
+ HRESULT LookAhead(size_t minRequiredInBuffer);
+ void SafeRead(Byte *data, unsigned size);
void ReadBuffer(CByteBuffer &buffer, unsigned size);
- Byte ReadByte();
- UInt16 ReadUInt16();
+ // Byte ReadByte();
+ // UInt16 ReadUInt16();
UInt32 ReadUInt32();
UInt64 ReadUInt64();
- void Skip(unsigned num);
- void Skip64(UInt64 num);
- void ReadFileName(unsigned nameSize, AString &dest);
- bool ReadExtra(unsigned extraSize, CExtraBlock &extraBlock,
- UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber);
+ void ReadSignature();
+
+ void Skip(size_t num);
+ HRESULT Skip64(UInt64 num, unsigned numFiles);
+
+ bool ReadFileName(unsigned nameSize, AString &dest);
+
+ bool ReadExtra(unsigned extraSize, CExtraBlock &extra,
+ UInt64 &unpackSize, UInt64 &packSize, UInt64 &localOffset, UInt32 &disk);
bool ReadLocalItem(CItemEx &item);
- HRESULT ReadLocalItemDescriptor(CItemEx &item);
+ HRESULT FindDescriptor(CItemEx &item, unsigned numFiles);
HRESULT ReadCdItem(CItemEx &item);
HRESULT TryEcd64(UInt64 offset, CCdInfo &cdInfo);
HRESULT FindCd(bool checkOffsetMode);
@@ -255,21 +308,28 @@ class CInArchive
HRESULT ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 &cdOffset, UInt64 &cdSize);
HRESULT ReadLocals(CObjectVector<CItemEx> &localItems);
- HRESULT ReadHeaders2(CObjectVector<CItemEx> &items);
+ HRESULT ReadHeaders(CObjectVector<CItemEx> &items);
HRESULT GetVolStream(unsigned vol, UInt64 pos, CMyComPtr<ISequentialInStream> &stream);
+
public:
CInArchiveInfo ArcInfo;
bool IsArc;
bool IsZip64;
+
bool HeadersError;
bool HeadersWarning;
bool ExtraMinorError;
bool UnexpectedEnd;
+ bool LocalsWereRead;
+ bool LocalsCenterMerged;
bool NoCentralDir;
+ bool Overflow32bit; // = true, if zip without Zip64 extension support and it has some fields values truncated to 32-bits.
+ bool Cd_NumEntries_Overflow_16bit; // = true, if no Zip64 and 16-bit ecd:NumEntries was overflowed.
bool MarkerIsFound;
+ bool MarkerIsSafe;
bool IsMultiVol;
bool UseDisk_in_SingleVol;
@@ -277,9 +337,7 @@ public:
CVols Vols;
- IArchiveOpenCallback *Callback;
-
- CInArchive(): Stream(NULL), Callback(NULL), IsArcOpen(false) {}
+ CInArchive(): Stream(NULL), StartStream(NULL), Callback(NULL), IsArcOpen(false) {}
UInt64 GetPhySize() const
{
@@ -301,7 +359,6 @@ public:
void ClearRefs();
void Close();
HRESULT Open(IInStream *stream, const UInt64 *searchLimit, IArchiveOpenCallback *callback, CObjectVector<CItemEx> &items);
- HRESULT ReadHeaders(CObjectVector<CItemEx> &items);
bool IsOpen() const { return IsArcOpen; }
@@ -329,7 +386,8 @@ public:
}
- HRESULT ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail);
+ HRESULT CheckDescriptor(const CItemEx &item);
+ HRESULT ReadLocalItemAfterCdItem(CItemEx &item, bool &isAvail, bool &headersError);
HRESULT ReadLocalItemAfterCdItemFull(CItemEx &item);
HRESULT GetItemStream(const CItemEx &item, bool seekPackData, CMyComPtr<ISequentialInStream> &stream);
diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp
index e732df7c..4fc59f79 100644
--- a/CPP/7zip/Archive/Zip/ZipItem.cpp
+++ b/CPP/7zip/Archive/Zip/ZipItem.cpp
@@ -5,9 +5,12 @@
#include "../../../../C/CpuArch.h"
#include "../../../../C/7zCrc.h"
+#include "../../../Common/IntToString.h"
#include "../../../Common/MyLinux.h"
#include "../../../Common/StringConvert.h"
+#include "../../../Windows/PropVariantUtils.h"
+
#include "../Common/ItemNameUtils.h"
#include "ZipItem.h"
@@ -17,6 +20,62 @@ namespace NZip {
using namespace NFileHeader;
+static const CUInt32PCharPair g_ExtraTypes[] =
+{
+ { NExtraID::kZip64, "Zip64" },
+ { NExtraID::kNTFS, "NTFS" },
+ { NExtraID::kStrongEncrypt, "StrongCrypto" },
+ { NExtraID::kUnixTime, "UT" },
+ { NExtraID::kUnixExtra, "UX" },
+ { NExtraID::kIzUnicodeComment, "uc" },
+ { NExtraID::kIzUnicodeName, "up" },
+ { NExtraID::kWzAES, "WzAES" }
+};
+
+void CExtraSubBlock::PrintInfo(AString &s) const
+{
+ for (unsigned i = 0; i < ARRAY_SIZE(g_ExtraTypes); i++)
+ {
+ const CUInt32PCharPair &pair = g_ExtraTypes[i];
+ if (pair.Value == ID)
+ {
+ s += pair.Name;
+ return;
+ }
+ }
+ {
+ char sz[32];
+ sz[0] = '0';
+ sz[1] = 'x';
+ ConvertUInt32ToHex(ID, sz + 2);
+ s += sz;
+ }
+}
+
+
+void CExtraBlock::PrintInfo(AString &s) const
+{
+ if (Error)
+ s.Add_OptSpaced("Extra_ERROR");
+
+ if (MinorError)
+ s.Add_OptSpaced("Minor_Extra_ERROR");
+
+ if (IsZip64 || IsZip64_Error)
+ {
+ s.Add_OptSpaced("Zip64");
+ if (IsZip64_Error)
+ s += "_ERROR";
+ }
+
+ FOR_VECTOR (i, SubBlocks)
+ {
+ s.Add_Space_if_NotEmpty();
+ SubBlocks[i].PrintInfo(s);
+ }
+}
+
+
bool CExtraSubBlock::ExtractNtfsTime(unsigned index, FILETIME &ft) const
{
ft.dwHighDateTime = ft.dwLowDateTime = 0;
@@ -83,6 +142,19 @@ bool CExtraSubBlock::ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res
}
+bool CExtraSubBlock::ExtractUnixExtraTime(unsigned index, UInt32 &res) const
+{
+ res = 0;
+ const size_t size = Data.Size();
+ unsigned offset = index * 4;
+ if (ID != NExtraID::kUnixExtra || size < offset + 4)
+ return false;
+ const Byte *p = (const Byte *)Data + offset;
+ res = GetUi32(p);
+ return true;
+}
+
+
bool CExtraBlock::GetNtfsTime(unsigned index, FILETIME &ft) const
{
FOR_VECTOR (i, SubBlocks)
@@ -96,11 +168,29 @@ bool CExtraBlock::GetNtfsTime(unsigned index, FILETIME &ft) const
bool CExtraBlock::GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const
{
- FOR_VECTOR (i, SubBlocks)
{
- const CExtraSubBlock &sb = SubBlocks[i];
- if (sb.ID == NFileHeader::NExtraID::kUnixTime)
- return sb.ExtractUnixTime(isCentral, index, res);
+ FOR_VECTOR (i, SubBlocks)
+ {
+ const CExtraSubBlock &sb = SubBlocks[i];
+ if (sb.ID == NFileHeader::NExtraID::kUnixTime)
+ return sb.ExtractUnixTime(isCentral, index, res);
+ }
+ }
+
+ switch (index)
+ {
+ case NUnixTime::kMTime: index = NUnixExtra::kMTime; break;
+ case NUnixTime::kATime: index = NUnixExtra::kATime; break;
+ default: return false;
+ }
+
+ {
+ FOR_VECTOR (i, SubBlocks)
+ {
+ const CExtraSubBlock &sb = SubBlocks[i];
+ if (sb.ID == NFileHeader::NExtraID::kUnixExtra)
+ return sb.ExtractUnixExtraTime(index, res);
+ }
}
return false;
}
diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h
index c134ec79..0cf9bd09 100644
--- a/CPP/7zip/Archive/Zip/ZipItem.h
+++ b/CPP/7zip/Archive/Zip/ZipItem.h
@@ -22,11 +22,12 @@ struct CVersion
struct CExtraSubBlock
{
- UInt16 ID;
+ UInt32 ID;
CByteBuffer Data;
bool ExtractNtfsTime(unsigned index, FILETIME &ft) const;
bool ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const;
+ bool ExtractUnixExtraTime(unsigned index, UInt32 &res) const;
bool ExtractIzUnicode(UInt32 crc, AString &name) const
{
@@ -44,6 +45,8 @@ struct CExtraSubBlock
return false;
return CheckUTF8(name, false);
}
+
+ void PrintInfo(AString &s) const;
};
const unsigned k_WzAesExtra_Size = 7;
@@ -129,11 +132,22 @@ struct CStrongCryptoExtra
bool CertificateIsUsed() const { return (Flags > 0x0001); }
};
+
struct CExtraBlock
{
CObjectVector<CExtraSubBlock> SubBlocks;
+ bool Error;
+ bool MinorError;
+ bool IsZip64;
+ bool IsZip64_Error;
- void Clear() { SubBlocks.Clear(); }
+ CExtraBlock(): Error(false), MinorError(false), IsZip64(false), IsZip64_Error(false) {}
+
+ void Clear()
+ {
+ SubBlocks.Clear();
+ IsZip64 = false;
+ }
size_t GetSize() const
{
@@ -176,6 +190,8 @@ struct CExtraBlock
bool GetNtfsTime(unsigned index, FILETIME &ft) const;
bool GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const;
+ void PrintInfo(AString &s) const;
+
void RemoveUnknownSubBlocks()
{
for (unsigned i = SubBlocks.Size(); i != 0;)
@@ -206,12 +222,19 @@ public:
CExtraBlock LocalExtra;
+ unsigned GetDescriptorSize() const { return LocalExtra.IsZip64 ? kDataDescriptorSize64 : kDataDescriptorSize32; }
+
+ UInt64 GetPackSizeWithDescriptor() const
+ { return PackSize + (HasDescriptor() ? GetDescriptorSize() : 0); }
+
bool IsUtf8() const { return (Flags & NFileHeader::NFlags::kUtf8) != 0; }
bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kEncrypted) != 0; }
bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; }
bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); }
bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; }
bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }
+
+ unsigned GetDeflateLevel() const { return (Flags >> 1) & 3; }
bool IsDir() const;
diff --git a/CPP/7zip/Archive/Zip/ZipOut.cpp b/CPP/7zip/Archive/Zip/ZipOut.cpp
index 2a1ba2c4..1fdc24f8 100644
--- a/CPP/7zip/Archive/Zip/ZipOut.cpp
+++ b/CPP/7zip/Archive/Zip/ZipOut.cpp
@@ -21,48 +21,20 @@ HRESULT COutArchive::Create(IOutStream *outStream)
return m_Stream->Seek(0, STREAM_SEEK_CUR, &m_Base);
}
-void COutArchive::MoveCurPos(UInt64 distanceToMove)
-{
- m_CurPos += distanceToMove; // test overflow
-}
-
-void COutArchive::SeekToRelatPos(UInt64 offset)
+void COutArchive::SeekToCurPos()
{
- HRESULT res = m_Stream->Seek(m_Base + offset, STREAM_SEEK_SET, NULL);
+ HRESULT res = m_Stream->Seek(m_Base + m_CurPos, STREAM_SEEK_SET, NULL);
if (res != S_OK)
throw CSystemException(res);
}
-void COutArchive::PrepareWriteCompressedDataZip64(unsigned fileNameLen, bool isZip64, bool aesEncryption)
-{
- m_IsZip64 = isZip64;
- m_ExtraSize = isZip64 ? (4 + 8 + 8) : 0;
- if (aesEncryption)
- m_ExtraSize += 4 + k_WzAesExtra_Size;
- m_LocalFileHeaderSize = kLocalHeaderSize + fileNameLen + m_ExtraSize;
-}
-
-void COutArchive::PrepareWriteCompressedData(unsigned fileNameLen, UInt64 unPackSize, bool aesEncryption)
-{
- // We use Zip64, if unPackSize size is larger than 0xF8000000 to support
- // cases when compressed size can be about 3% larger than uncompressed size
-
- PrepareWriteCompressedDataZip64(fileNameLen, unPackSize >= (UInt32)0xF8000000, aesEncryption);
-}
-
#define DOES_NEED_ZIP64(v) (v >= (UInt32)0xFFFFFFFF)
+// #define DOES_NEED_ZIP64(v) (v >= 0)
-void COutArchive::PrepareWriteCompressedData2(unsigned fileNameLen, UInt64 unPackSize, UInt64 packSize, bool aesEncryption)
-{
- bool isZip64 =
- DOES_NEED_ZIP64(unPackSize) ||
- DOES_NEED_ZIP64(packSize);
- PrepareWriteCompressedDataZip64(fileNameLen, isZip64, aesEncryption);
-}
-void COutArchive::WriteBytes(const void *buffer, UInt32 size)
+void COutArchive::WriteBytes(const void *data, size_t size)
{
- m_OutBuffer.WriteBytes(buffer, size);
+ m_OutBuffer.WriteBytes(data, size);
m_CurPos += size;
}
@@ -74,11 +46,8 @@ void COutArchive::Write8(Byte b)
void COutArchive::Write16(UInt16 val)
{
- for (int i = 0; i < 2; i++)
- {
- Write8((Byte)val);
- val >>= 8;
- }
+ Write8((Byte)val);
+ Write8((Byte)(val >> 8));
}
void COutArchive::Write32(UInt32 val)
@@ -101,15 +70,12 @@ void COutArchive::Write64(UInt64 val)
void COutArchive::WriteExtra(const CExtraBlock &extra)
{
- if (extra.SubBlocks.Size() != 0)
+ FOR_VECTOR (i, extra.SubBlocks)
{
- FOR_VECTOR (i, extra.SubBlocks)
- {
- const CExtraSubBlock &subBlock = extra.SubBlocks[i];
- Write16(subBlock.ID);
- Write16((UInt16)subBlock.Data.Size());
- WriteBytes(subBlock.Data, (UInt32)subBlock.Data.Size());
- }
+ const CExtraSubBlock &subBlock = extra.SubBlocks[i];
+ Write16((UInt16)subBlock.ID);
+ Write16((UInt16)subBlock.Data.Size());
+ WriteBytes(subBlock.Data, (UInt16)subBlock.Data.Size());
}
}
@@ -125,40 +91,65 @@ void COutArchive::WriteCommonItemInfo(const CLocalItem &item, bool isZip64)
Write16(item.Flags);
Write16(item.Method);
Write32(item.Time);
- Write32(item.Crc);
}
+
#define WRITE_32_VAL_SPEC(__v, __isZip64) Write32((__isZip64) ? 0xFFFFFFFF : (UInt32)(__v));
-void COutArchive::WriteLocalHeader(const CLocalItem &item)
+
+void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck)
{
- SeekToCurPos();
+ m_LocalHeaderPos = m_CurPos;
+ item.LocalHeaderPos = m_CurPos;
- bool isZip64 = m_IsZip64 ||
+ bool isZip64 =
DOES_NEED_ZIP64(item.PackSize) ||
DOES_NEED_ZIP64(item.Size);
-
+
+ if (needCheck && m_IsZip64)
+ isZip64 = true;
+
+ const UInt32 localExtraSize = (UInt32)((isZip64 ? (4 + 8 + 8): 0) + item.LocalExtra.GetSize());
+ if ((UInt16)localExtraSize != localExtraSize)
+ throw CSystemException(E_FAIL);
+ if (needCheck && m_ExtraSize != localExtraSize)
+ throw CSystemException(E_FAIL);
+
+ m_IsZip64 = isZip64;
+ m_ExtraSize = localExtraSize;
+
+ item.LocalExtra.IsZip64 = isZip64;
+
Write32(NSignature::kLocalFileHeader);
+
WriteCommonItemInfo(item, isZip64);
+
+ Write32(item.HasDescriptor() ? 0 : item.Crc);
- WRITE_32_VAL_SPEC(item.PackSize, isZip64);
- WRITE_32_VAL_SPEC(item.Size, isZip64);
-
- Write16((UInt16)item.Name.Len());
+ UInt64 packSize = item.PackSize;
+ UInt64 size = item.Size;
+
+ if (item.HasDescriptor())
{
- UInt16 localExtraSize = (UInt16)((isZip64 ? (4 + 8 + 8): 0) + item.LocalExtra.GetSize());
- if (localExtraSize != m_ExtraSize)
- throw CSystemException(E_FAIL);
+ packSize = 0;
+ size = 0;
}
- Write16((UInt16)m_ExtraSize);
- WriteBytes((const char *)item.Name, item.Name.Len());
+
+ WRITE_32_VAL_SPEC(packSize, isZip64);
+ WRITE_32_VAL_SPEC(size, isZip64);
+
+ Write16((UInt16)item.Name.Len());
+
+ Write16((UInt16)localExtraSize);
+
+ WriteBytes((const char *)item.Name, (UInt16)item.Name.Len());
if (isZip64)
{
Write16(NFileHeader::NExtraID::kZip64);
Write16(8 + 8);
- Write64(item.Size);
- Write64(item.PackSize);
+ Write64(size);
+ Write64(packSize);
}
WriteExtra(item.LocalExtra);
@@ -166,10 +157,57 @@ void COutArchive::WriteLocalHeader(const CLocalItem &item)
// Why don't we write NTFS timestamps to local header?
// Probably we want to reduce size of archive?
+ const UInt32 localFileHeaderSize = (UInt32)(m_CurPos - m_LocalHeaderPos);
+ if (needCheck && m_LocalFileHeaderSize != localFileHeaderSize)
+ throw CSystemException(E_FAIL);
+ m_LocalFileHeaderSize = localFileHeaderSize;
+
m_OutBuffer.FlushWithCheck();
- MoveCurPos(item.PackSize);
}
+
+void COutArchive::WriteLocalHeader_Replace(CItemOut &item)
+{
+ m_CurPos = m_LocalHeaderPos + m_LocalFileHeaderSize + item.PackSize;
+
+ if (item.HasDescriptor())
+ {
+ WriteDescriptor(item);
+ m_OutBuffer.FlushWithCheck();
+ }
+
+ const UInt64 nextPos = m_CurPos;
+ m_CurPos = m_LocalHeaderPos;
+ SeekToCurPos();
+ WriteLocalHeader(item, true);
+ m_CurPos = nextPos;
+ SeekToCurPos();
+}
+
+
+void COutArchive::WriteDescriptor(const CItemOut &item)
+{
+ Byte buf[kDataDescriptorSize64];
+ SetUi32(buf, NSignature::kDataDescriptor);
+ SetUi32(buf + 4, item.Crc);
+ unsigned descriptorSize;
+ if (m_IsZip64)
+ {
+ SetUi64(buf + 8, item.PackSize);
+ SetUi64(buf + 16, item.Size);
+ descriptorSize = kDataDescriptorSize64;
+ }
+ else
+ {
+ SetUi32(buf + 8, (UInt32)item.PackSize);
+ SetUi32(buf + 12, (UInt32)item.Size);
+ descriptorSize = kDataDescriptorSize32;
+ }
+ WriteBytes(buf, descriptorSize);
+}
+
+
+
void COutArchive::WriteCentralHeader(const CItemOut &item)
{
bool isUnPack64 = DOES_NEED_ZIP64(item.Size);
@@ -182,6 +220,7 @@ void COutArchive::WriteCentralHeader(const CItemOut &item)
Write8(item.MadeByVersion.HostOS);
WriteCommonItemInfo(item, isZip64);
+ Write32(item.Crc);
WRITE_32_VAL_SPEC(item.PackSize, isPack64);
WRITE_32_VAL_SPEC(item.Size, isUnPack64);
@@ -196,7 +235,10 @@ void COutArchive::WriteCentralHeader(const CItemOut &item)
item.CentralExtra.GetSize());
Write16(centralExtraSize); // test it;
- Write16((UInt16)item.Comment.Size());
+
+ const UInt16 commentSize = (UInt16)item.Comment.Size();
+
+ Write16(commentSize);
Write16(0); // DiskNumberStart;
Write16(item.InternalAttrib);
Write32(item.ExternalAttrib);
@@ -228,14 +270,12 @@ void COutArchive::WriteCentralHeader(const CItemOut &item)
}
WriteExtra(item.CentralExtra);
- if (item.Comment.Size() > 0)
- WriteBytes(item.Comment, (UInt32)item.Comment.Size());
+ if (commentSize != 0)
+ WriteBytes(item.Comment, commentSize);
}
void COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment)
{
- SeekToCurPos();
-
UInt64 cdOffset = GetCurPos();
FOR_VECTOR (i, items)
WriteCentralHeader(items[i]);
@@ -252,6 +292,11 @@ void COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CB
{
Write32(NSignature::kEcd64);
Write64(kEcd64_MainSize);
+
+ // to test extra block:
+ // const UInt32 extraSize = 1 << 26;
+ // Write64(kEcd64_MainSize + extraSize);
+
Write16(45); // made by version
Write16(45); // extract version
Write32(0); // ThisDiskNumber = 0;
@@ -261,6 +306,8 @@ void COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CB
Write64((UInt64)cdSize);
Write64((UInt64)cdOffset);
+ // for (UInt32 iii = 0; iii < extraSize; iii++) Write8(1);
+
Write32(NSignature::kEcd64Locator);
Write32(0); // number of the disk with the start of the zip64 end of central directory
Write64(cd64EndOffset);
@@ -276,37 +323,23 @@ void COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CB
WRITE_32_VAL_SPEC(cdSize, cdSize64);
WRITE_32_VAL_SPEC(cdOffset, cdOffset64);
- UInt32 commentSize = (UInt32)(comment ? comment->Size() : 0);
+ const UInt16 commentSize = (UInt16)(comment ? comment->Size() : 0);
Write16((UInt16)commentSize);
- if (commentSize > 0)
+ if (commentSize != 0)
WriteBytes((const Byte *)*comment, commentSize);
m_OutBuffer.FlushWithCheck();
}
-void COutArchive::CreateStreamForCompressing(IOutStream **outStream)
+void COutArchive::CreateStreamForCompressing(CMyComPtr<IOutStream> &outStream)
{
COffsetOutStream *streamSpec = new COffsetOutStream;
- CMyComPtr<IOutStream> tempStream(streamSpec);
- streamSpec->Init(m_Stream, m_Base + m_CurPos + m_LocalFileHeaderSize);
- *outStream = tempStream.Detach();
-}
-
-/*
-void COutArchive::SeekToPackedDataPosition()
-{
- SeekTo(m_BasePosition + m_LocalFileHeaderSize);
-}
-*/
-
-void COutArchive::SeekToCurPos()
-{
- SeekToRelatPos(m_CurPos);
+ outStream = streamSpec;
+ streamSpec->Init(m_Stream, m_Base + m_CurPos);
}
-void COutArchive::CreateStreamForCopying(ISequentialOutStream **outStream)
+void COutArchive::CreateStreamForCopying(CMyComPtr<ISequentialOutStream> &outStream)
{
- CMyComPtr<ISequentialOutStream> tempStream(m_Stream);
- *outStream = tempStream.Detach();
+ outStream = m_Stream;
}
}}
diff --git a/CPP/7zip/Archive/Zip/ZipOut.h b/CPP/7zip/Archive/Zip/ZipOut.h
index 056d0d09..0a0ac0c8 100644
--- a/CPP/7zip/Archive/Zip/ZipOut.h
+++ b/CPP/7zip/Archive/Zip/ZipOut.h
@@ -5,7 +5,6 @@
#include "../../../Common/MyCom.h"
-#include "../../IStream.h"
#include "../../Common/OutBuffer.h"
#include "ZipItem.h"
@@ -13,8 +12,6 @@
namespace NArchive {
namespace NZip {
-// can throw CSystemException and COutBufferException
-
class CItemOut: public CItem
{
public:
@@ -28,21 +25,23 @@ public:
CItemOut(): NtfsTimeIsDefined(false) {}
};
+
+// COutArchive can throw CSystemException and COutBufferException
+
class COutArchive
{
- CMyComPtr<IOutStream> m_Stream;
COutBuffer m_OutBuffer;
+ CMyComPtr<IOutStream> m_Stream;
- UInt64 m_Base; // Base of arc (offset in output Stream)
+ UInt64 m_Base; // Base of archive (offset in output Stream)
UInt64 m_CurPos; // Curent position in archive (relative from m_Base)
+ UInt64 m_LocalHeaderPos; // LocalHeaderPos (relative from m_Base) for last WriteLocalHeader() call
UInt32 m_LocalFileHeaderSize;
UInt32 m_ExtraSize;
bool m_IsZip64;
- void SeekToRelatPos(UInt64 offset);
-
- void WriteBytes(const void *buffer, UInt32 size);
+ void WriteBytes(const void *data, size_t size);
void Write8(Byte b);
void Write16(UInt16 val);
void Write32(UInt32 val);
@@ -57,30 +56,26 @@ class COutArchive
void WriteCommonItemInfo(const CLocalItem &item, bool isZip64);
void WriteCentralHeader(const CItemOut &item);
- void PrepareWriteCompressedDataZip64(unsigned fileNameLen, bool isZip64, bool aesEncryption);
-
+ void SeekToCurPos();
public:
HRESULT Create(IOutStream *outStream);
- void MoveCurPos(UInt64 distanceToMove);
UInt64 GetCurPos() const { return m_CurPos; }
- void SeekToCurPos();
-
- void PrepareWriteCompressedData(unsigned fileNameLen, UInt64 unPackSize, bool aesEncryption);
- void PrepareWriteCompressedData2(unsigned fileNameLen, UInt64 unPackSize, UInt64 packSize, bool aesEncryption);
- void WriteLocalHeader(const CLocalItem &item);
-
- void WriteLocalHeader_And_SeekToNextFile(const CLocalItem &item)
+ void MoveCurPos(UInt64 distanceToMove)
{
- WriteLocalHeader(item);
- SeekToCurPos();
+ m_CurPos += distanceToMove;
}
+ void WriteLocalHeader(CItemOut &item, bool needCheck = false);
+ void WriteLocalHeader_Replace(CItemOut &item);
+
+ void WriteDescriptor(const CItemOut &item);
+
void WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment);
- void CreateStreamForCompressing(IOutStream **outStream);
- void CreateStreamForCopying(ISequentialOutStream **outStream);
+ void CreateStreamForCompressing(CMyComPtr<IOutStream> &outStream);
+ void CreateStreamForCopying(CMyComPtr<ISequentialOutStream> &outStream);
};
}}
diff --git a/CPP/7zip/Archive/Zip/ZipRegister.cpp b/CPP/7zip/Archive/Zip/ZipRegister.cpp
index 6674189f..e6929f1b 100644
--- a/CPP/7zip/Archive/Zip/ZipRegister.cpp
+++ b/CPP/7zip/Archive/Zip/ZipRegister.cpp
@@ -10,13 +10,14 @@ namespace NArchive {
namespace NZip {
static const Byte k_Signature[] = {
- 4, 0x50, 0x4B, 0x03, 0x04,
- 4, 0x50, 0x4B, 0x05, 0x06,
- 6, 0x50, 0x4B, 0x07, 0x08, 0x50, 0x4B,
- 6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B };
+ 4, 0x50, 0x4B, 0x03, 0x04, // Local
+ 4, 0x50, 0x4B, 0x05, 0x06, // Ecd
+ 4, 0x50, 0x4B, 0x06, 0x06, // Ecd64
+ 6, 0x50, 0x4B, 0x07, 0x08, 0x50, 0x4B, // Span / Descriptor
+ 6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B }; // NoSpan
REGISTER_ARC_IO(
- "zip", "zip z01 zipx jar xpi odt ods docx xlsx epub", 0, 1,
+ "zip", "zip z01 zipx jar xpi odt ods docx xlsx epub ipa apk appx", 0, 1,
k_Signature,
0,
NArcInfoFlags::kFindSignature |
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
index bc50c1d7..81f48a2a 100644
--- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
@@ -42,32 +42,38 @@ static const Byte kHostOS =
static const Byte kMadeByHostOS = kHostOS;
static const Byte kExtractHostOS = kHostOS;
-static const Byte kMethodForDirectory = NFileHeader::NCompressionMethod::kStored;
+static const Byte kMethodForDirectory = NFileHeader::NCompressionMethod::kStore;
-static HRESULT CopyBlockToArchive(ISequentialInStream *inStream, UInt64 size,
- COutArchive &outArchive, ICompressProgressInfo *progress)
+
+static void AddAesExtra(CItem &item, Byte aesKeyMode, UInt16 method)
{
- CMyComPtr<ISequentialOutStream> outStream;
- outArchive.CreateStreamForCopying(&outStream);
- return NCompress::CopyStream_ExactSize(inStream, outStream, size, progress);
+ CWzAesExtra wzAesField;
+ wzAesField.Strength = aesKeyMode;
+ wzAesField.Method = method;
+ item.Method = NFileHeader::NCompressionMethod::kWzAES;
+ item.Crc = 0;
+ CExtraSubBlock sb;
+ wzAesField.SetSubBlock(sb);
+ item.LocalExtra.SubBlocks.Add(sb);
+ item.CentralExtra.SubBlocks.Add(sb);
}
+
static void SetFileHeader(
- COutArchive &archive,
const CCompressionMethodMode &options,
const CUpdateItem &ui,
// bool isSeqMode,
CItemOut &item)
{
item.Size = ui.Size;
- bool isDir;
+ bool isDir = ui.IsDir;
item.ClearFlags();
if (ui.NewProps)
{
- isDir = ui.IsDir;
item.Name = ui.Name;
+ item.Comment = ui.Comment;
item.SetUtf8(ui.IsUtf8);
item.ExternalAttrib = ui.Attrib;
item.Time = ui.Time;
@@ -76,10 +82,11 @@ static void SetFileHeader(
item.Ntfs_CTime = ui.Ntfs_CTime;
item.NtfsTimeIsDefined = ui.NtfsTimeIsDefined;
}
+ /*
else
isDir = item.IsDir();
+ */
- item.LocalHeaderPos = archive.GetCurPos();
item.MadeByVersion.HostOS = kMadeByHostOS;
item.MadeByVersion.Version = NFileHeader::NCompressionMethod::kMadeByProgramVersion;
@@ -97,14 +104,32 @@ static void SetFileHeader(
item.Size = 0;
item.Crc = 0;
}
+
+ item.LocalExtra.Clear();
+ item.CentralExtra.Clear();
+
+ if (isDir)
+ {
+ item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir;
+ item.Method = kMethodForDirectory;
+ item.PackSize = 0;
+ item.Size = 0;
+ item.Crc = 0;
+ }
+ else if (options.IsRealAesMode())
+ AddAesExtra(item, options.AesKeyMode, (Byte)(options.MethodSequence.IsEmpty() ? 8 : options.MethodSequence[0]));
}
+// we call SetItemInfoFromCompressingResult() after SetFileHeader()
+
static void SetItemInfoFromCompressingResult(const CCompressingResult &compressingResult,
bool isAesMode, Byte aesKeyMode, CItem &item)
{
item.ExtractVersion.Version = compressingResult.ExtractVersion;
item.Method = compressingResult.Method;
+ if (compressingResult.Method == NFileHeader::NCompressionMethod::kLZMA && compressingResult.LzmaEos)
+ item.Flags |= NFileHeader::NFlags::kLzmaEOS;
item.Crc = compressingResult.CRC;
item.Size = compressingResult.UnpackSize;
item.PackSize = compressingResult.PackSize;
@@ -113,17 +138,7 @@ static void SetItemInfoFromCompressingResult(const CCompressingResult &compressi
item.CentralExtra.Clear();
if (isAesMode)
- {
- CWzAesExtra wzAesField;
- wzAesField.Strength = aesKeyMode;
- wzAesField.Method = compressingResult.Method;
- item.Method = NFileHeader::NCompressionMethod::kWzAES;
- item.Crc = 0;
- CExtraSubBlock sb;
- wzAesField.SetSubBlock(sb);
- item.LocalExtra.SubBlocks.Add(sb);
- item.CentralExtra.SubBlocks.Add(sb);
- }
+ AddAesExtra(item, aesKeyMode, compressingResult.Method);
}
@@ -151,6 +166,7 @@ struct CThreadInfo
HRESULT Result;
CCompressingResult CompressingResult;
+ bool SeqMode;
bool IsFree;
UInt32 UpdateIndex;
UInt32 FileTime;
@@ -160,6 +176,7 @@ struct CThreadInfo
ProgressSpec(0),
OutStreamSpec(0),
Coder(options),
+ SeqMode(false),
FileTime(0)
{}
@@ -193,7 +210,7 @@ void CThreadInfo::WaitAndCode()
Result = Coder.Compress(
EXTERNAL_CODECS_LOC_VARS
- InStream, OutStream, FileTime, Progress, CompressingResult);
+ InStream, OutStream, SeqMode, FileTime, Progress, CompressingResult);
if (Result == S_OK && Progress)
Result = Progress->SetRatioInfo(&CompressingResult.UnpackSize, &CompressingResult.PackSize);
@@ -342,6 +359,8 @@ static HRESULT UpdateItemOldData(
NUpdateNotifyOp::kReplicate))
}
+ UInt64 rangeSize;
+
if (ui.NewProps)
{
if (item.HasDescriptor())
@@ -349,14 +368,11 @@ static HRESULT UpdateItemOldData(
// use old name size.
- CMyComPtr<ISequentialInStream> packStream;
- RINOK(inArchive->GetItemStream(itemEx, true, packStream));
- if (!packStream)
- return E_NOTIMPL;
-
// we keep ExternalAttrib and some another properties from old archive
// item.ExternalAttrib = ui.Attrib;
+ // if we don't change Comment, we keep Comment from OldProperties
+ item.Comment = ui.Comment;
item.Name = ui.Name;
item.SetUtf8(ui.IsUtf8);
item.Time = ui.Time;
@@ -367,46 +383,37 @@ static HRESULT UpdateItemOldData(
item.CentralExtra.RemoveUnknownSubBlocks();
item.LocalExtra.RemoveUnknownSubBlocks();
- item.LocalHeaderPos = archive.GetCurPos();
- archive.PrepareWriteCompressedData2(item.Name.Len(), item.Size, item.PackSize, item.LocalExtra.HasWzAes());
archive.WriteLocalHeader(item);
-
- RINOK(CopyBlockToArchive(packStream, itemEx.PackSize, archive, progress));
-
- complexity += itemEx.PackSize;
+ rangeSize = item.GetPackSizeWithDescriptor();
}
else
{
- CMyComPtr<ISequentialInStream> packStream;
- RINOK(inArchive->GetItemStream(itemEx, false, packStream));
- if (!packStream)
- return E_NOTIMPL;
-
- // set new header position
item.LocalHeaderPos = archive.GetCurPos();
-
- const UInt64 rangeSize = itemEx.GetLocalFullSize();
-
- RINOK(CopyBlockToArchive(packStream, rangeSize, archive, progress));
-
- complexity += rangeSize;
- archive.MoveCurPos(rangeSize);
+ rangeSize = itemEx.GetLocalFullSize();
}
- return S_OK;
+ CMyComPtr<ISequentialInStream> packStream;
+
+ RINOK(inArchive->GetItemStream(itemEx, ui.NewProps, packStream));
+ if (!packStream)
+ return E_NOTIMPL;
+
+ complexity += rangeSize;
+
+ CMyComPtr<ISequentialOutStream> outStream;
+ archive.CreateStreamForCopying(outStream);
+ HRESULT res = NCompress::CopyStream_ExactSize(packStream, outStream, rangeSize, progress);
+ archive.MoveCurPos(rangeSize);
+ return res;
}
static void WriteDirHeader(COutArchive &archive, const CCompressionMethodMode *options,
const CUpdateItem &ui, CItemOut &item)
{
- SetFileHeader(archive, *options, ui, item);
- archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size,
- // options->IsRealAesMode()
- false // fixed 9.31
- );
- archive.WriteLocalHeader_And_SeekToNextFile(item);
+ SetFileHeader(*options, ui, item);
+ archive.WriteLocalHeader(item);
}
@@ -490,6 +497,8 @@ static HRESULT Update2St(
if (!ui.NewProps || !ui.NewData)
{
+ // Note: for (ui.NewProps && !ui.NewData) it copies Props from old archive,
+ // But we will rewrite all important properties later. But we can keep some properties like Comment
itemEx = inputItems[ui.IndexInArc];
if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK)
return E_NOTIMPL;
@@ -498,7 +507,8 @@ static HRESULT Update2St(
if (ui.NewData)
{
- bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir());
+ // bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir());
+ bool isDir = ui.IsDir;
if (isDir)
{
WriteDirHeader(archive, options, ui, item);
@@ -517,28 +527,39 @@ static HRESULT Update2St(
if (!fileInStream)
return E_INVALIDARG;
- // bool isSeqMode = false;
- /*
+ bool seqMode;
{
CMyComPtr<IInStream> inStream2;
fileInStream->QueryInterface(IID_IInStream, (void **)&inStream2);
- isSeqMode = (inStream2 == NULL);
+ seqMode = (inStream2 == NULL);
}
- */
+ // seqMode = true; // to test seqMode
UpdatePropsFromStream(ui, fileInStream, updateCallback, totalComplexity);
- SetFileHeader(archive, *options, ui, item);
+ SetFileHeader(*options, ui, item);
+
+ item.SetDescriptorMode(seqMode);
// file Size can be 64-bit !!!
- archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, options->IsRealAesMode());
+
CCompressingResult compressingResult;
+
+ RINOK(compressor.Set_Pre_CompressionResult(
+ seqMode,
+ ui.Size,
+ compressingResult));
+
+ SetItemInfoFromCompressingResult(compressingResult, options->IsRealAesMode(), options->AesKeyMode, item);
+
+ archive.WriteLocalHeader(item);
+
CMyComPtr<IOutStream> outStream;
- archive.CreateStreamForCompressing(&outStream);
+ archive.CreateStreamForCompressing(outStream);
RINOK(compressor.Compress(
EXTERNAL_CODECS_LOC_VARS
fileInStream, outStream,
- ui.Time,
+ seqMode, ui.Time,
progress, compressingResult));
if (compressingResult.FileTimeWasUsed)
@@ -551,7 +572,9 @@ static HRESULT Update2St(
}
SetItemInfoFromCompressingResult(compressingResult, options->IsRealAesMode(), options->AesKeyMode, item);
- archive.WriteLocalHeader_And_SeekToNextFile(item);
+
+ archive.WriteLocalHeader_Replace(item);
+
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
unpackSizeTotal += item.Size;
packSizeTotal += item.PackSize;
@@ -561,7 +584,9 @@ static HRESULT Update2St(
{
UInt64 complexity = 0;
lps->SendRatio = false;
+
RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, opCallback, complexity));
+
lps->SendRatio = true;
lps->ProgressOffset += complexity;
}
@@ -591,6 +616,7 @@ static HRESULT Update2(
CMyComPtr<IArchiveUpdateCallbackFile> opCallback;
updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);
+ bool unknownComplexity = false;
UInt64 complexity = 0;
UInt64 numFilesToCompress = 0;
UInt64 numBytesToCompress = 0;
@@ -602,7 +628,10 @@ static HRESULT Update2(
const CUpdateItem &ui = updateItems[i];
if (ui.NewData)
{
- complexity += ui.Size;
+ if (ui.Size == (UInt64)(Int64)-1)
+ unknownComplexity = true;
+ else
+ complexity += ui.Size;
numBytesToCompress += ui.Size;
numFilesToCompress++;
/*
@@ -625,19 +654,49 @@ static HRESULT Update2(
if (comment)
complexity += comment->Size();
complexity++; // end of central
- updateCallback->SetTotal(complexity);
+
+ if (!unknownComplexity)
+ updateCallback->SetTotal(complexity);
UInt64 totalComplexity = complexity;
- CAddCommon compressor(options);
+ CCompressionMethodMode options2 = options;
+
+ if (options2._methods.IsEmpty())
+ {
+ // we need method item, if default method was used
+ options2._methods.AddNew();
+ }
+
+ CAddCommon compressor(options2);
complexity = 0;
- CCompressionMethodMode options2 = options;
+ const Byte method = options.MethodSequence.Front();
+
+ COneMethodInfo *oneMethodMain = NULL;
+ if (!options2._methods.IsEmpty())
+ oneMethodMain = &options2._methods[0];
+
+ {
+ FOR_VECTOR (mi, options2._methods)
+ {
+ options2.SetGlobalLevelTo(options2._methods[mi]);
+ }
+ }
+
+ if (oneMethodMain)
+ {
+ // appnote recommends to use EOS marker for LZMA.
+ if (method == NFileHeader::NCompressionMethod::kLZMA)
+ oneMethodMain->AddProp_EndMarker_if_NotFound(true);
+ }
+
#ifndef _7ZIP_ST
- UInt32 numThreads = options.NumThreads;
+ UInt32 numThreads = options._numThreads;
+
const UInt32 kNumMaxThreads = 64;
if (numThreads > kNumMaxThreads)
numThreads = kNumMaxThreads;
@@ -646,7 +705,6 @@ static HRESULT Update2(
if (numThreads < 1)
numThreads = 1;
-
const size_t kMemPerThread = (1 << 25);
const size_t kBlockSize = 1 << 16;
@@ -655,44 +713,69 @@ static HRESULT Update2(
if (numFilesToCompress <= 1)
mtMode = false;
- Byte method = options.MethodSequence.Front();
-
if (!mtMode)
{
- if (options2.MethodInfo.FindProp(NCoderPropID::kNumThreads) < 0)
+ FOR_VECTOR (mi, options2._methods)
{
- // fixed for 9.31. bzip2 default is just one thread.
- if (options2.NumThreadsWasChanged || method == NFileHeader::NCompressionMethod::kBZip2)
- options2.MethodInfo.AddProp_NumThreads(numThreads);
+ COneMethodInfo &onem = options2._methods[mi];
+
+ if (onem.FindProp(NCoderPropID::kNumThreads) < 0)
+ {
+ // fixed for 9.31. bzip2 default is just one thread.
+ onem.AddProp_NumThreads(numThreads);
+ }
}
}
else
{
- if (method == NFileHeader::NCompressionMethod::kStored && !options.PasswordIsDefined)
+ if (method == NFileHeader::NCompressionMethod::kStore && !options.PasswordIsDefined)
numThreads = 1;
+
+ if (oneMethodMain)
+ {
+
if (method == NFileHeader::NCompressionMethod::kBZip2)
{
bool fixedNumber;
- UInt32 numBZip2Threads = options2.MethodInfo.Get_BZip2_NumThreads(fixedNumber);
+ UInt32 numBZip2Threads = oneMethodMain->Get_BZip2_NumThreads(fixedNumber);
if (!fixedNumber)
{
- UInt64 averageSize = numBytesToCompress / numFilesToCompress;
- UInt32 blockSize = options2.MethodInfo.Get_BZip2_BlockSize();
- UInt64 averageNumberOfBlocks = averageSize / blockSize + 1;
+ const UInt64 averageSize = numBytesToCompress / numFilesToCompress;
+ const UInt32 blockSize = oneMethodMain->Get_BZip2_BlockSize();
+ const UInt64 averageNumberOfBlocks = averageSize / blockSize + 1;
numBZip2Threads = 32;
- if (averageNumberOfBlocks < numBZip2Threads)
+ if (numBZip2Threads > averageNumberOfBlocks)
numBZip2Threads = (UInt32)averageNumberOfBlocks;
- options2.MethodInfo.AddProp_NumThreads(numBZip2Threads);
+ oneMethodMain->AddProp_NumThreads(numBZip2Threads);
}
numThreads /= numBZip2Threads;
}
- if (method == NFileHeader::NCompressionMethod::kLZMA)
+
+ if (method == NFileHeader::NCompressionMethod::kXz)
{
bool fixedNumber;
+ UInt32 numLzma2Threads = oneMethodMain->Get_Lzma2_NumThreads(fixedNumber);
+ if (!fixedNumber)
+ {
+ const UInt64 averageSize = numBytesToCompress / numFilesToCompress;
+ const UInt64 blockSize = oneMethodMain->Get_Lzma2_BlockSize();
+ const UInt64 averageNumberOfBlocks = averageSize / blockSize + 1;
+ numLzma2Threads = 2;
+ if (numLzma2Threads > averageNumberOfBlocks)
+ numLzma2Threads = (UInt32)averageNumberOfBlocks;
+ oneMethodMain->AddProp_NumThreads(numLzma2Threads);
+ }
+ numThreads /= numLzma2Threads;
+ }
+
+ if (method == NFileHeader::NCompressionMethod::kLZMA)
+ {
// we suppose that default LZMA is 2 thread. So we don't change it
- UInt32 numLZMAThreads = options2.MethodInfo.Get_Lzma_NumThreads(fixedNumber);
+ UInt32 numLZMAThreads = oneMethodMain->Get_Lzma_NumThreads();
numThreads /= numLZMAThreads;
}
+ }
+
if (numThreads > numFilesToCompress)
numThreads = (UInt32)numFilesToCompress;
if (numThreads <= 1)
@@ -747,6 +830,7 @@ static HRESULT Update2(
threadInfo.ProgressSpec = new CMtCompressProgress();
threadInfo.Progress = threadInfo.ProgressSpec;
threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, (int)i);
+ threadInfo.SeqMode = false; // fix it !
threadInfo.FileTime = 0; // fix it !
RINOK(threadInfo.CreateThread());
}
@@ -777,7 +861,9 @@ static HRESULT Update2(
if (inArchive->ReadLocalItemAfterCdItemFull(itemEx) != S_OK)
return E_NOTIMPL;
(CItem &)item = itemEx;
- if (item.IsDir())
+ if (item.IsDir() != ui.IsDir)
+ return E_NOTIMPL;
+ if (ui.IsDir)
continue;
}
@@ -849,7 +935,8 @@ static HRESULT Update2(
if (ui.NewData)
{
- bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir());
+ // bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir());
+ bool isDir = ui.IsDir;
if (isDir)
{
@@ -857,39 +944,51 @@ static HRESULT Update2(
}
else
{
- if (lastRealStreamItemIndex < (int)itemIndex)
- {
- lastRealStreamItemIndex = itemIndex;
- SetFileHeader(archive, options, ui, item);
- // file Size can be 64-bit !!!
- archive.PrepareWriteCompressedData(item.Name.Len(), ui.Size, options.IsRealAesMode());
- }
-
CMemBlocks2 &memRef = refs.Refs[itemIndex];
if (memRef.Defined)
{
- CMyComPtr<IOutStream> outStream;
- archive.CreateStreamForCompressing(&outStream);
- memRef.WriteToStream(memManager.GetBlockSize(), outStream);
- SetFileHeader(archive, options, ui, item);
+ if (lastRealStreamItemIndex < (int)itemIndex)
+ lastRealStreamItemIndex = itemIndex;
+
+ SetFileHeader(options, ui, item);
// the BUG was fixed in 9.26:
// SetItemInfoFromCompressingResult must be after SetFileHeader
// to write correct Size.
SetItemInfoFromCompressingResult(memRef.CompressingResult,
options.IsRealAesMode(), options.AesKeyMode, item);
- archive.WriteLocalHeader_And_SeekToNextFile(item);
+ archive.WriteLocalHeader(item);
// RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+ CMyComPtr<ISequentialOutStream> outStream;
+ archive.CreateStreamForCopying(outStream);
+ memRef.WriteToStream(memManager.GetBlockSize(), outStream);
+ archive.MoveCurPos(item.PackSize);
memRef.FreeOpt(&memManager);
}
else
{
+ if (lastRealStreamItemIndex < (int)itemIndex)
+ {
+ lastRealStreamItemIndex = itemIndex;
+ SetFileHeader(options, ui, item);
+
+ CCompressingResult compressingResult;
+ RINOK(compressor.Set_Pre_CompressionResult(
+ false, // seqMode
+ ui.Size,
+ compressingResult));
+ SetItemInfoFromCompressingResult(compressingResult, options.IsRealAesMode(), options.AesKeyMode, item);
+
+ // file Size can be 64-bit !!!
+ archive.WriteLocalHeader(item);
+ }
+
{
CThreadInfo &thread = threads.Threads[threadIndices.Front()];
if (!thread.OutStreamSpec->WasUnlockEventSent())
{
CMyComPtr<IOutStream> outStream;
- archive.CreateStreamForCompressing(&outStream);
+ archive.CreateStreamForCompressing(outStream);
thread.OutStreamSpec->SetOutStream(outStream);
thread.OutStreamSpec->SetRealStreamMode();
}
@@ -918,10 +1017,10 @@ static HRESULT Update2(
{
RINOK(threadInfo.OutStreamSpec->WriteToRealStream());
threadInfo.OutStreamSpec->ReleaseOutStream();
- SetFileHeader(archive, options, ui, item);
+ SetFileHeader(options, ui, item);
SetItemInfoFromCompressingResult(threadInfo.CompressingResult,
options.IsRealAesMode(), options.AesKeyMode, item);
- archive.WriteLocalHeader_And_SeekToNextFile(item);
+ archive.WriteLocalHeader_Replace(item);
}
else
{
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.h b/CPP/7zip/Archive/Zip/ZipUpdate.h
index 15cbf69d..d5fda855 100644
--- a/CPP/7zip/Archive/Zip/ZipUpdate.h
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.h
@@ -14,6 +14,7 @@
namespace NArchive {
namespace NZip {
+/*
struct CUpdateRange
{
UInt64 Position;
@@ -22,6 +23,7 @@ struct CUpdateRange
// CUpdateRange() {};
CUpdateRange(UInt64 position, UInt64 size): Position(position), Size(size) {};
};
+*/
struct CUpdateItem
{
@@ -36,12 +38,23 @@ struct CUpdateItem
UInt32 Time;
UInt64 Size;
AString Name;
+ CByteBuffer Comment;
// bool Commented;
// CUpdateRange CommentRange;
FILETIME Ntfs_MTime;
FILETIME Ntfs_ATime;
FILETIME Ntfs_CTime;
+ void Clear()
+ {
+ IsDir = false;
+ NtfsTimeIsDefined = false;
+ IsUtf8 = false;
+ Size = 0;
+ Name.Empty();
+ Comment.Free();
+ }
+
CUpdateItem(): NtfsTimeIsDefined(false), IsUtf8(false), Size(0) {}
};