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
path: root/CPP
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2010-06-04 04:00:00 +0400
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:16:03 +0300
commit708873490ee36691d84cc06336aac87c5129f8a0 (patch)
treebbe6e5aa922a158e5810c1a2ff7c78927cc6d973 /CPP
parent3dacb5eb8afda99aad81f4723cb966c0fa91ba1d (diff)
9.149.14
Diffstat (limited to 'CPP')
-rwxr-xr-xCPP/7zip/Archive/7z/7zExtract.cpp2
-rwxr-xr-xCPP/7zip/Archive/7z/7zFolderInStream.cpp63
-rwxr-xr-xCPP/7zip/Archive/7z/7zFolderInStream.h38
-rwxr-xr-xCPP/7zip/Archive/7z/7zFolderOutStream.cpp13
-rwxr-xr-xCPP/7zip/Archive/7z/7zFolderOutStream.h12
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixer2.cpp2
-rwxr-xr-xCPP/7zip/Archive/Common/InStreamWithCRC.cpp2
-rwxr-xr-xCPP/7zip/Archive/Common/InStreamWithCRC.h6
-rwxr-xr-xCPP/7zip/Archive/DebHandler.cpp2
-rwxr-xr-xCPP/7zip/Archive/Iso/IsoHandler.cpp4
-rwxr-xr-xCPP/7zip/Archive/Iso/IsoRegister.cpp2
-rwxr-xr-xCPP/7zip/Archive/LzhHandler.cpp2
-rwxr-xr-xCPP/7zip/Archive/Nsis/NsisHandler.cpp1
-rwxr-xr-xCPP/7zip/Archive/NtfsHandler.cpp6
-rwxr-xr-xCPP/7zip/Archive/Rar/RarHandler.cpp2
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHandler.cpp4
-rwxr-xr-xCPP/7zip/Archive/Tar/TarIn.cpp19
-rwxr-xr-xCPP/7zip/Archive/Udf/UdfHandler.cpp5
-rwxr-xr-xCPP/7zip/Archive/Udf/UdfRegister.cpp2
-rwxr-xr-xCPP/7zip/Archive/Wim/WimHandler.cpp236
-rwxr-xr-xCPP/7zip/Archive/Wim/WimHandler.h23
-rwxr-xr-xCPP/7zip/Archive/Wim/WimHandlerOut.cpp647
-rwxr-xr-xCPP/7zip/Archive/Wim/WimIn.cpp445
-rwxr-xr-xCPP/7zip/Archive/Wim/WimIn.h84
-rwxr-xr-xCPP/7zip/Archive/Wim/WimRegister.cpp7
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHandler.h8
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHandlerOut.cpp16
-rwxr-xr-xCPP/7zip/Bundles/Alone/makefile1
-rwxr-xr-xCPP/7zip/Bundles/Fm/makefile1
-rwxr-xr-xCPP/7zip/Bundles/Format7zF/Format7z.dsp4
-rwxr-xr-xCPP/7zip/Bundles/Format7zF/makefile1
-rwxr-xr-xCPP/7zip/MyVersion.h8
-rwxr-xr-xCPP/7zip/UI/Common/PropIDUtils.cpp37
-rwxr-xr-xCPP/7zip/UI/Console/UserInputUtils.cpp1
-rwxr-xr-xCPP/7zip/UI/FileManager/PanelItemOpen.cpp47
-rwxr-xr-xCPP/7zip/UI/GUI/CompressDialog.cpp8
36 files changed, 1350 insertions, 411 deletions
diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp
index 6913d8fb..eb3ee502 100755
--- a/CPP/7zip/Archive/7z/7zExtract.cpp
+++ b/CPP/7zip/Archive/7z/7zExtract.cpp
@@ -138,7 +138,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
}
- extractCallback->SetTotal(importantTotalUnpacked);
+ RINOK(extractCallback->SetTotal(importantTotalUnpacked));
CDecoder decoder(
#ifdef _ST_MODE
diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
index b029ae15..edd276bc 100755
--- a/CPP/7zip/Archive/7z/7zFolderInStream.cpp
+++ b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
@@ -32,7 +32,6 @@ HRESULT CFolderInStream::OpenStream()
_filePos = 0;
while (_fileIndex < _numFiles)
{
- _currentSizeIsDefined = false;
CMyComPtr<ISequentialInStream> stream;
HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream);
if (result != S_OK && result != S_FALSE)
@@ -40,26 +39,22 @@ HRESULT CFolderInStream::OpenStream()
_fileIndex++;
_inStreamWithHashSpec->SetStream(stream);
_inStreamWithHashSpec->Init();
- if (!stream)
+ if (stream)
{
- RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
- Sizes.Add(0);
- Processed.Add(result == S_OK);
- AddDigest();
- continue;
- }
- CMyComPtr<IStreamGetSize> streamGetSize;
- if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK)
- {
- if(streamGetSize)
+ _fileIsOpen = true;
+ CMyComPtr<IStreamGetSize> streamGetSize;
+ stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);
+ if (streamGetSize)
{
- _currentSizeIsDefined = true;
RINOK(streamGetSize->GetSize(&_currentSize));
+ _currentSizeIsDefined = true;
}
+ return S_OK;
}
-
- _fileIsOpen = true;
- return S_OK;
+ RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+ Sizes.Add(0);
+ Processed.Add(result == S_OK);
+ AddDigest();
}
return S_OK;
}
@@ -74,6 +69,7 @@ HRESULT CFolderInStream::CloseStream()
RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
_inStreamWithHashSpec->ReleaseStream();
_fileIsOpen = false;
+ _currentSizeIsDefined = false;
Processed.Add(true);
Sizes.Add(_filePos);
AddDigest();
@@ -82,43 +78,40 @@ HRESULT CFolderInStream::CloseStream()
STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
- UInt32 realProcessedSize = 0;
- while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0)
+ if (processedSize != 0)
+ *processedSize = 0;
+ while (size > 0)
{
if (_fileIsOpen)
{
- UInt32 localProcessedSize;
- RINOK(_inStreamWithHash->Read(
- ((Byte *)data) + realProcessedSize, size, &localProcessedSize));
- if (localProcessedSize == 0)
+ UInt32 processed2;
+ RINOK(_inStreamWithHash->Read(data, size, &processed2));
+ if (processed2 == 0)
{
RINOK(CloseStream());
continue;
}
- realProcessedSize += localProcessedSize;
- _filePos += localProcessedSize;
- size -= localProcessedSize;
+ if (processedSize != 0)
+ *processedSize = processed2;
+ _filePos += processed2;
break;
}
- else
- {
- RINOK(OpenStream());
- }
+ if (_fileIndex >= _numFiles)
+ break;
+ RINOK(OpenStream());
}
- if (processedSize != 0)
- *processedSize = realProcessedSize;
return S_OK;
}
STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
{
*value = 0;
- int subStreamIndex = (int)subStream;
- if (subStreamIndex < 0 || subStream > Sizes.Size())
+ int index2 = (int)subStream;
+ if (index2 < 0 || subStream > Sizes.Size())
return E_FAIL;
- if (subStreamIndex < Sizes.Size())
+ if (index2 < Sizes.Size())
{
- *value= Sizes[subStreamIndex];
+ *value = Sizes[index2];
return S_OK;
}
if (!_currentSizeIsDefined)
diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.h b/CPP/7zip/Archive/7z/7zFolderInStream.h
index 68e2b27b..6df3672a 100755
--- a/CPP/7zip/Archive/7z/7zFolderInStream.h
+++ b/CPP/7zip/Archive/7z/7zFolderInStream.h
@@ -1,15 +1,13 @@
-// 7z/FolderInStream.h
+// 7zFolderInStream.h
-#ifndef __7Z_FOLDERINSTREAM_H
-#define __7Z_FOLDERINSTREAM_H
-
-#include "7zItem.h"
-#include "7zHeader.h"
+#ifndef __7Z_FOLDER_IN_STREAM_H
+#define __7Z_FOLDER_IN_STREAM_H
+#include "../../ICoder.h"
#include "../IArchive.h"
#include "../Common/InStreamWithCRC.h"
-#include "../../IStream.h"
-#include "../../ICoder.h"
+
+#include "7zItem.h"
namespace NArchive {
namespace N7z {
@@ -19,26 +17,14 @@ class CFolderInStream:
public ICompressGetSubStreamSize,
public CMyUnknownImp
{
-public:
-
- MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
-
- CFolderInStream();
-
- STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
-
- STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
-private:
CSequentialInStreamWithCRC *_inStreamWithHashSpec;
CMyComPtr<ISequentialInStream> _inStreamWithHash;
CMyComPtr<IArchiveUpdateCallback> _updateCallback;
bool _currentSizeIsDefined;
- UInt64 _currentSize;
-
bool _fileIsOpen;
+ UInt64 _currentSize;
UInt64 _filePos;
-
const UInt32 *_fileIndices;
UInt32 _numFiles;
UInt32 _fileIndex;
@@ -46,12 +32,18 @@ private:
HRESULT OpenStream();
HRESULT CloseStream();
void AddDigest();
+
public:
- void Init(IArchiveUpdateCallback *updateCallback,
- const UInt32 *fileIndices, UInt32 numFiles);
CRecordVector<bool> Processed;
CRecordVector<UInt32> CRCs;
CRecordVector<UInt64> Sizes;
+
+ MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
+
+ CFolderInStream();
+ void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *fileIndices, UInt32 numFiles);
UInt64 GetFullSize() const
{
UInt64 size = 0;
diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
index c5dbfa6d..22c4600e 100755
--- a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
+++ b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
@@ -14,13 +14,13 @@ CFolderOutStream::CFolderOutStream()
}
HRESULT CFolderOutStream::Init(
- const CArchiveDatabaseEx *archiveDatabase,
+ const CArchiveDatabaseEx *db,
UInt32 ref2Offset, UInt32 startIndex,
const CBoolVector *extractStatuses,
IArchiveExtractCallback *extractCallback,
bool testMode, bool checkCrc)
{
- _db = archiveDatabase;
+ _db = db;
_ref2Offset = ref2Offset;
_startIndex = startIndex;
@@ -121,6 +121,15 @@ STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *proc
return S_OK;
}
+STDMETHODIMP CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
+{
+ *value = 0;
+ if ((int)subStream >= _extractStatuses->Size())
+ return S_FALSE;
+ *value = _db->Files[_startIndex + (int)subStream].Size;
+ return S_OK;
+}
+
HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
{
while (_currentIndex < _extractStatuses->Size())
diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.h b/CPP/7zip/Archive/7z/7zFolderOutStream.h
index e6e05b85..f9bb1af4 100755
--- a/CPP/7zip/Archive/7z/7zFolderOutStream.h
+++ b/CPP/7zip/Archive/7z/7zFolderOutStream.h
@@ -3,17 +3,18 @@
#ifndef __7Z_FOLDER_OUT_STREAM_H
#define __7Z_FOLDER_OUT_STREAM_H
-#include "7zIn.h"
-
#include "../../IStream.h"
#include "../IArchive.h"
#include "../Common/OutStreamWithCRC.h"
+#include "7zIn.h"
+
namespace NArchive {
namespace N7z {
class CFolderOutStream:
public ISequentialOutStream,
+ public ICompressGetSubStreamSize,
public CMyUnknownImp
{
COutStreamWithCRC *_crcStreamSpec;
@@ -34,14 +35,15 @@ class CFolderOutStream:
HRESULT CloseFileAndSetResult();
HRESULT ProcessEmptyFiles();
public:
- MY_UNKNOWN_IMP
-
+ MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
+
CFolderOutStream();
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
HRESULT Init(
- const CArchiveDatabaseEx *archiveDatabase,
+ const CArchiveDatabaseEx *db,
UInt32 ref2Offset, UInt32 startIndex,
const CBoolVector *extractStatuses,
IArchiveExtractCallback *extractCallback,
diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp
index aed94f9c..0b06a489 100755
--- a/CPP/7zip/Archive/Common/CoderMixer2.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp
@@ -87,7 +87,7 @@ CCoderInfo2::CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams):
{
InSizes.Reserve(NumInStreams);
InSizePointers.Reserve(NumInStreams);
- OutSizePointers.Reserve(NumOutStreams);
+ OutSizes.Reserve(NumOutStreams);
OutSizePointers.Reserve(NumOutStreams);
}
diff --git a/CPP/7zip/Archive/Common/InStreamWithCRC.cpp b/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
index 1d9e5556..569a56f3 100755
--- a/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
+++ b/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
@@ -21,8 +21,10 @@ STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSi
{
UInt32 realProcessedSize;
HRESULT result = _stream->Read(data, size, &realProcessedSize);
+ /*
if (size > 0 && realProcessedSize == 0)
_wasFinished = true;
+ */
_size += realProcessedSize;
_crc = CrcUpdate(_crc, data, realProcessedSize);
if(processedSize != NULL)
diff --git a/CPP/7zip/Archive/Common/InStreamWithCRC.h b/CPP/7zip/Archive/Common/InStreamWithCRC.h
index 0492a5f8..31b761e4 100755
--- a/CPP/7zip/Archive/Common/InStreamWithCRC.h
+++ b/CPP/7zip/Archive/Common/InStreamWithCRC.h
@@ -49,19 +49,19 @@ private:
CMyComPtr<IInStream> _stream;
UInt64 _size;
UInt32 _crc;
- bool _wasFinished;
+ // bool _wasFinished;
public:
void SetStream(IInStream *stream) { _stream = stream; }
void Init()
{
_size = 0;
- _wasFinished = false;
+ // _wasFinished = false;
_crc = CRC_INIT_VAL;
}
void ReleaseStream() { _stream.Release(); }
UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
UInt64 GetSize() const { return _size; }
- bool WasFinished() const { return _wasFinished; }
+ // bool WasFinished() const { return _wasFinished; }
};
#endif
diff --git a/CPP/7zip/Archive/DebHandler.cpp b/CPP/7zip/Archive/DebHandler.cpp
index b9724c2a..82d2cde8 100755
--- a/CPP/7zip/Archive/DebHandler.cpp
+++ b/CPP/7zip/Archive/DebHandler.cpp
@@ -3,8 +3,6 @@
#include "StdAfx.h"
#include "Common/ComTry.h"
-#include "Common/Defs.h"
-#include "Common/NewHandler.h"
#include "Common/StringConvert.h"
#include "Common/StringToInt.h"
diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp
index 9c20fec3..dc20c240 100755
--- a/CPP/7zip/Archive/Iso/IsoHandler.cpp
+++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp
@@ -3,9 +3,7 @@
#include "StdAfx.h"
#include "Common/ComTry.h"
-#include "Common/Defs.h"
#include "Common/IntToString.h"
-#include "Common/NewHandler.h"
#include "Common/StringConvert.h"
#include "Windows/PropVariant.h"
@@ -26,7 +24,7 @@ using namespace NTime;
namespace NArchive {
namespace NIso {
-STATPROPSTG kProps[] =
+static STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL},
diff --git a/CPP/7zip/Archive/Iso/IsoRegister.cpp b/CPP/7zip/Archive/Iso/IsoRegister.cpp
index 39f91198..67a09c76 100755
--- a/CPP/7zip/Archive/Iso/IsoRegister.cpp
+++ b/CPP/7zip/Archive/Iso/IsoRegister.cpp
@@ -8,6 +8,6 @@
static IInArchive *CreateArc() { return new NArchive::NIso::CHandler; }
static CArcInfo g_ArcInfo =
- { L"Iso", L"iso", 0, 0xE7, { 'C', 'D', '0', '0', '1', 0x1 }, 7, false, CreateArc, 0 };
+ { L"Iso", L"iso img", 0, 0xE7, { 'C', 'D', '0', '0', '1', 0x1 }, 7, false, CreateArc, 0 };
REGISTER_ARC(Iso)
diff --git a/CPP/7zip/Archive/LzhHandler.cpp b/CPP/7zip/Archive/LzhHandler.cpp
index b9d953b9..a7fcd676 100755
--- a/CPP/7zip/Archive/LzhHandler.cpp
+++ b/CPP/7zip/Archive/LzhHandler.cpp
@@ -646,7 +646,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
totalUnPacked += item.Size;
totalPacked += item.PackSize;
}
- extractCallback->SetTotal(totalUnPacked);
+ RINOK(extractCallback->SetTotal(totalUnPacked));
UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0;
UInt64 currentItemUnPacked, currentItemPacked;
diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp
index 8005ddbc..818b0a88 100755
--- a/CPP/7zip/Archive/Nsis/NsisHandler.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisHandler.cpp
@@ -6,7 +6,6 @@
#include "Common/ComTry.h"
#include "Common/IntToString.h"
-#include "Common/NewHandler.h"
#include "Windows/PropVariant.h"
diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp
index f88dd012..8670e164 100755
--- a/CPP/7zip/Archive/NtfsHandler.cpp
+++ b/CPP/7zip/Archive/NtfsHandler.cpp
@@ -1283,9 +1283,11 @@ HRESULT CDatabase::Open()
{
if (OpenCallback)
{
- // Sleep(0);
UInt64 numFiles = Recs.Size();
- RINOK(OpenCallback->SetCompleted(&numFiles, &pos64));
+ if ((numFiles & 0x3FF) == 0)
+ {
+ RINOK(OpenCallback->SetCompleted(&numFiles, &pos64));
+ }
}
UInt32 readSize = kBufSize;
UInt64 rem = mftSize - pos64;
diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp
index b5decec8..8906614a 100755
--- a/CPP/7zip/Archive/Rar/RarHandler.cpp
+++ b/CPP/7zip/Archive/Rar/RarHandler.cpp
@@ -520,7 +520,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
lastIndex = index + 1;
}
- extractCallback->SetTotal(importantTotalUnPacked);
+ RINOK(extractCallback->SetTotal(importantTotalUnPacked));
UInt64 currentImportantTotalUnPacked = 0;
UInt64 currentImportantTotalPacked = 0;
UInt64 currentUnPackSize, currentPackSize;
diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp
index 31e30573..e25463de 100755
--- a/CPP/7zip/Archive/Tar/TarHandler.cpp
+++ b/CPP/7zip/Archive/Tar/TarHandler.cpp
@@ -3,8 +3,6 @@
#include "StdAfx.h"
#include "Common/ComTry.h"
-#include "Common/Defs.h"
-#include "Common/NewHandler.h"
#include "Common/StringConvert.h"
#include "Windows/PropVariant.h"
@@ -23,7 +21,7 @@ using namespace NWindows;
namespace NArchive {
namespace NTar {
-STATPROPSTG kProps[] =
+static STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL},
diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp
index b8409195..939c6c0a 100755
--- a/CPP/7zip/Archive/Tar/TarIn.cpp
+++ b/CPP/7zip/Archive/Tar/TarIn.cpp
@@ -69,11 +69,20 @@ static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemE
filled = false;
- processedSize = NFileHeader::kRecordSize;
- RINOK(ReadStream(stream, buf, &processedSize));
- if (processedSize == 0 || (processedSize == NFileHeader::kRecordSize && IsRecordLast(buf)))
- return S_OK;
- if (processedSize < NFileHeader::kRecordSize)
+ bool thereAreEmptyRecords = false;
+ for (;;)
+ {
+ processedSize = NFileHeader::kRecordSize;
+ RINOK(ReadStream(stream, buf, &processedSize));
+ if (processedSize == 0)
+ return S_OK;
+ if (processedSize != NFileHeader::kRecordSize)
+ return S_FALSE;
+ if (!IsRecordLast(buf))
+ break;
+ thereAreEmptyRecords = true;
+ }
+ if (thereAreEmptyRecords)
return S_FALSE;
ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize;
diff --git a/CPP/7zip/Archive/Udf/UdfHandler.cpp b/CPP/7zip/Archive/Udf/UdfHandler.cpp
index 42419a9d..c7085272 100755
--- a/CPP/7zip/Archive/Udf/UdfHandler.cpp
+++ b/CPP/7zip/Archive/Udf/UdfHandler.cpp
@@ -3,7 +3,6 @@
#include "StdAfx.h"
#include "Common/ComTry.h"
-#include "Common/NewHandler.h"
#include "Windows/PropVariant.h"
#include "Windows/Time.h"
@@ -34,7 +33,7 @@ void UdfTimeToFileTime(const CTime &t, NWindows::NCOM::CPropVariant &prop)
prop = ft;
}
-STATPROPSTG kProps[] =
+static STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL},
@@ -44,7 +43,7 @@ STATPROPSTG kProps[] =
{ NULL, kpidATime, VT_FILETIME}
};
-STATPROPSTG kArcProps[] =
+static STATPROPSTG kArcProps[] =
{
{ NULL, kpidComment, VT_BSTR},
{ NULL, kpidClusterSize, VT_UI4},
diff --git a/CPP/7zip/Archive/Udf/UdfRegister.cpp b/CPP/7zip/Archive/Udf/UdfRegister.cpp
index 5dc7db6a..1b08d120 100755
--- a/CPP/7zip/Archive/Udf/UdfRegister.cpp
+++ b/CPP/7zip/Archive/Udf/UdfRegister.cpp
@@ -8,6 +8,6 @@
static IInArchive *CreateArc() { return new NArchive::NUdf::CHandler; }
static CArcInfo g_ArcInfo =
- { L"Udf", L"iso", 0, 0xE0, { 0, 'N', 'S', 'R', '0' }, 5, false, CreateArc, 0 };
+ { L"Udf", L"iso img", 0, 0xE0, { 0, 'N', 'S', 'R', '0' }, 5, false, CreateArc, 0 };
REGISTER_ARC(Udf)
diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp
index 8093af77..8092a34c 100755
--- a/CPP/7zip/Archive/Wim/WimHandler.cpp
+++ b/CPP/7zip/Archive/Wim/WimHandler.cpp
@@ -2,18 +2,17 @@
#include "StdAfx.h"
-#include "Common/IntToString.h"
-#include "Common/Defs.h"
+#include "../../../../C/CpuArch.h"
+
#include "Common/ComTry.h"
+#include "Common/IntToString.h"
#include "Common/StringToInt.h"
#include "Common/UTFConvert.h"
#include "Windows/PropVariant.h"
-#include "../../Common/StreamUtils.h"
#include "../../Common/ProgressUtils.h"
-
-#include "../../../../C/CpuArch.h"
+#include "../../Common/StreamUtils.h"
#include "WimHandler.h"
@@ -28,17 +27,18 @@ namespace NWim {
#define WIM_DETAILS
-STATPROPSTG kProps[] =
+static STATPROPSTG kProps[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsDir, VT_BOOL},
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidPackSize, VT_UI8},
- { NULL, kpidAttrib, VT_UI4},
- { NULL, kpidMethod, VT_BSTR},
{ NULL, kpidMTime, VT_FILETIME},
{ NULL, kpidCTime, VT_FILETIME},
- { NULL, kpidATime, VT_FILETIME}
+ { NULL, kpidATime, VT_FILETIME},
+ { NULL, kpidAttrib, VT_UI4},
+ { NULL, kpidMethod, VT_BSTR},
+ { NULL, kpidShortName, VT_BSTR}
#ifdef WIM_DETAILS
, { NULL, kpidVolume, VT_UI4}
@@ -47,14 +47,14 @@ STATPROPSTG kProps[] =
#endif
};
-STATPROPSTG kArcProps[] =
+static STATPROPSTG kArcProps[] =
{
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidPackSize, VT_UI8},
{ NULL, kpidMethod, VT_BSTR},
{ NULL, kpidCTime, VT_FILETIME},
{ NULL, kpidMTime, VT_FILETIME},
- { NULL, kpidComment, VT_FILETIME},
+ { NULL, kpidComment, VT_BSTR},
{ NULL, kpidIsVolume, VT_BOOL},
{ NULL, kpidVolume, VT_UI4},
{ NULL, kpidNumVolumes, VT_UI4}
@@ -87,49 +87,51 @@ static bool ParseNumber32(const AString &s, UInt32 &res)
return true;
}
-void ParseTime(const CXmlItem &item, bool &defined, FILETIME &ft, const AString &s)
+bool ParseTime(const CXmlItem &item, FILETIME &ft, const char *tag)
{
- defined = false;
- int cTimeIndex = item.FindSubTag(s);
- if (cTimeIndex >= 0)
+ int index = item.FindSubTag(tag);
+ if (index >= 0)
{
- const CXmlItem &timeItem = item.SubItems[cTimeIndex];
- UInt32 high = 0, low = 0;
- if (ParseNumber32(timeItem.GetSubStringForTag("HIGHPART"), high) &&
- ParseNumber32(timeItem.GetSubStringForTag("LOWPART"), low))
+ const CXmlItem &timeItem = item.SubItems[index];
+ UInt32 low = 0, high = 0;
+ if (ParseNumber32(timeItem.GetSubStringForTag("LOWPART"), low) &&
+ ParseNumber32(timeItem.GetSubStringForTag("HIGHPART"), high))
{
- defined = true;
- ft.dwHighDateTime = high;
ft.dwLowDateTime = low;
+ ft.dwHighDateTime = high;
+ return true;
}
}
+ return false;
}
void CImageInfo::Parse(const CXmlItem &item)
{
- ParseTime(item, CTimeDefined, CTime, "CREATIONTIME");
- ParseTime(item, MTimeDefined, MTime, "LASTMODIFICATIONTIME");
+ CTimeDefined = ParseTime(item, CTime, "CREATIONTIME");
+ MTimeDefined = ParseTime(item, MTime, "LASTMODIFICATIONTIME");
NameDefined = ConvertUTF8ToUnicode(item.GetSubStringForTag("NAME"), Name);
// IndexDefined = ParseNumber32(item.GetPropertyValue("INDEX"), Index);
}
-void CXml::Parse()
+void CXml::ToUnicode(UString &s)
{
size_t size = Data.GetCapacity();
- if (size < 2 || (size & 1) != 0 || (size > 1 << 24))
+ if (size < 2 || (size & 1) != 0 || size > (1 << 24))
return;
const Byte *p = Data;
if (Get16(p) != 0xFEFF)
return;
- UString s;
- {
- wchar_t *chars = s.GetBuffer((int)size / 2 + 1);
- for (size_t i = 2; i < size; i += 2)
- *chars++ = (wchar_t)Get16(p + i);
- *chars = 0;
- s.ReleaseBuffer();
- }
+ wchar_t *chars = s.GetBuffer((int)size / 2);
+ for (size_t i = 2; i < size; i += 2)
+ *chars++ = (wchar_t)Get16(p + i);
+ *chars = 0;
+ s.ReleaseBuffer();
+}
+void CXml::Parse()
+{
+ UString s;
+ ToUnicode(s);
AString utf;
if (!ConvertUnicodeToUTF8(s, utf))
return;
@@ -151,10 +153,9 @@ void CXml::Parse()
}
}
-static const wchar_t *kStreamsNamePrefix = L"Files" WSTRING_PATH_SEPARATOR;
-static const wchar_t *kMethodLZX = L"LZX";
-static const wchar_t *kMethodXpress = L"XPress";
-static const wchar_t *kMethodCopy = L"Copy";
+static const char *kMethodLZX = "LZX";
+static const char *kMethodXpress = "XPress";
+static const char *kMethodCopy = "Copy";
IMP_IInArchive_Props
IMP_IInArchive_ArcProps
@@ -165,22 +166,22 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
NWindows::NCOM::CPropVariant prop;
const CImageInfo *image = NULL;
- if (m_Xmls.Size() == 1)
+ if (_xmls.Size() == 1)
{
- const CXml &xml = m_Xmls[0];
+ const CXml &xml = _xmls[0];
if (xml.Images.Size() == 1)
image = &xml.Images[0];
}
switch(propID)
{
- case kpidSize: prop = m_Database.GetUnpackSize(); break;
- case kpidPackSize: prop = m_Database.GetPackSize(); break;
+ case kpidSize: prop = _db.GetUnpackSize(); break;
+ case kpidPackSize: prop = _db.GetPackSize(); break;
case kpidCTime:
- if (m_Xmls.Size() == 1)
+ if (_xmls.Size() == 1)
{
- const CXml &xml = m_Xmls[0];
+ const CXml &xml = _xmls[0];
int index = -1;
for (int i = 0; i < xml.Images.Size(); i++)
{
@@ -195,9 +196,9 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
break;
case kpidMTime:
- if (m_Xmls.Size() == 1)
+ if (_xmls.Size() == 1)
{
- const CXml &xml = m_Xmls[0];
+ const CXml &xml = _xmls[0];
int index = -1;
for (int i = 0; i < xml.Images.Size(); i++)
{
@@ -211,32 +212,43 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
}
break;
- case kpidComment: if (image != NULL && image->NameDefined) prop = image->Name; break;
+ case kpidComment:
+ if (image != NULL)
+ {
+ if (_xmlInComments)
+ {
+ UString s;
+ _xmls[0].ToUnicode(s);
+ prop = s;
+ }
+ else if (image->NameDefined)
+ prop = image->Name;
+ }
+ break;
case kpidIsVolume:
- if (m_Xmls.Size() > 0)
+ if (_xmls.Size() > 0)
{
- UInt16 volIndex = m_Xmls[0].VolIndex;
- if (volIndex < m_Volumes.Size())
- prop = (m_Volumes[volIndex].Header.NumParts > 1);
+ UInt16 volIndex = _xmls[0].VolIndex;
+ if (volIndex < _volumes.Size())
+ prop = (_volumes[volIndex].Header.NumParts > 1);
}
break;
case kpidVolume:
- if (m_Xmls.Size() > 0)
+ if (_xmls.Size() > 0)
{
- UInt16 volIndex = m_Xmls[0].VolIndex;
- if (volIndex < m_Volumes.Size())
- prop = (UInt32)m_Volumes[volIndex].Header.PartNumber;
+ UInt16 volIndex = _xmls[0].VolIndex;
+ if (volIndex < _volumes.Size())
+ prop = (UInt32)_volumes[volIndex].Header.PartNumber;
}
break;
- case kpidNumVolumes: if (m_Volumes.Size() > 0) prop = (UInt32)(m_Volumes.Size() - 1); break;
+ case kpidNumVolumes: if (_volumes.Size() > 0) prop = (UInt32)(_volumes.Size() - 1); break;
case kpidMethod:
{
bool lzx = false, xpress = false, copy = false;
- for (int i = 0; i < m_Xmls.Size(); i++)
+ for (int i = 0; i < _xmls.Size(); i++)
{
- const CVolume &vol = m_Volumes[m_Xmls[i].VolIndex];
- const CHeader &header = vol.Header;
+ const CHeader &header = _volumes[_xmls[i].VolIndex].Header;
if (header.IsCompressed())
if (header.IsLzxMode())
lzx = true;
@@ -245,19 +257,19 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
else
copy = true;
}
- UString res;
+ AString res;
if (lzx)
res = kMethodLZX;
if (xpress)
{
if (!res.IsEmpty())
- res += L' ';
+ res += ' ';
res += kMethodXpress;
}
if (copy)
{
if (!res.IsEmpty())
- res += L' ';
+ res += ' ';
res += kMethodCopy;
}
prop = res;
@@ -272,35 +284,41 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
- if (index < (UInt32)m_Database.Items.Size())
+ if (index < (UInt32)_db.SortedItems.Size())
{
- const CItem &item = m_Database.Items[index];
+ int realIndex = _db.SortedItems[index];
+ const CItem &item = _db.Items[realIndex];
const CStreamInfo *si = NULL;
const CVolume *vol = NULL;
if (item.StreamIndex >= 0)
{
- si = &m_Database.Streams[item.StreamIndex];
- vol = &m_Volumes[si->PartNumber];
+ si = &_db.Streams[item.StreamIndex];
+ vol = &_volumes[si->PartNumber];
}
switch(propID)
{
case kpidPath:
if (item.HasMetadata)
- prop = item.Name;
+ prop = _db.GetItemPath(realIndex);
else
{
- wchar_t sz[32];
+ char sz[32];
ConvertUInt64ToString(item.StreamIndex, sz);
- UString s = sz;
- while (s.Length() < m_NameLenForStreams)
- s = L'0' + s;
- s = UString(kStreamsNamePrefix) + s;
+ AString s = sz;
+ while (s.Length() < _nameLenForStreams)
+ s = '0' + s;
+ /*
+ if (si->Resource.IsFree())
+ prefix = "[Free]";
+ */
+ s = "[Files]" STRING_PATH_SEPARATOR + s;
prop = s;
- break;
}
break;
- case kpidIsDir: prop = item.isDir(); break;
+ case kpidShortName: if (item.HasMetadata) prop = item.ShortName; break;
+
+ case kpidIsDir: prop = item.IsDir(); break;
case kpidAttrib: if (item.HasMetadata) prop = item.Attrib; break;
case kpidCTime: if (item.HasMetadata) prop = item.CTime; break;
case kpidATime: if (item.HasMetadata) prop = item.ATime; break;
@@ -318,22 +336,21 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
}
else
{
- index -= m_Database.Items.Size();
+ index -= _db.SortedItems.Size();
{
switch(propID)
{
case kpidPath:
{
- wchar_t sz[32];
- ConvertUInt64ToString(m_Xmls[index].VolIndex, sz);
- UString s = (UString)sz + L".xml";
- prop = s;
+ char sz[32];
+ ConvertUInt64ToString(_xmls[index].VolIndex, sz);
+ prop = (AString)"[" + (AString)sz + "].xml";
break;
}
case kpidIsDir: prop = false; break;
case kpidPackSize:
- case kpidSize: prop = (UInt64)m_Xmls[index].Data.GetCapacity(); break;
- case kpidMethod: prop = L"Copy"; break;
+ case kpidSize: prop = (UInt64)_xmls[index].Data.GetCapacity(); break;
+ case kpidMethod: prop = kMethodCopy; break;
}
}
}
@@ -411,13 +428,13 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
return res;
}
if (firstVolumeIndex >= 0)
- if (!header.AreFromOnArchive(m_Volumes[firstVolumeIndex].Header))
+ if (!header.AreFromOnArchive(_volumes[firstVolumeIndex].Header))
break;
- if (m_Volumes.Size() > header.PartNumber && m_Volumes[header.PartNumber].Stream)
+ if (_volumes.Size() > header.PartNumber && _volumes[header.PartNumber].Stream)
break;
CXml xml;
xml.VolIndex = header.PartNumber;
- res = OpenArchive(curStream, header, xml.Data, m_Database);
+ res = _db.Open(curStream, header, xml.Data, openArchiveCallback);
if (res != S_OK)
{
if (i == 1)
@@ -427,22 +444,22 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
return res;
}
- while (m_Volumes.Size() <= header.PartNumber)
- m_Volumes.Add(CVolume());
- CVolume &volume = m_Volumes[header.PartNumber];
+ while (_volumes.Size() <= header.PartNumber)
+ _volumes.Add(CVolume());
+ CVolume &volume = _volumes[header.PartNumber];
volume.Header = header;
volume.Stream = curStream;
firstVolumeIndex = header.PartNumber;
bool needAddXml = true;
- if (m_Xmls.Size() != 0)
- if (xml.Data == m_Xmls[0].Data)
+ if (_xmls.Size() != 0)
+ if (xml.Data == _xmls[0].Data)
needAddXml = false;
if (needAddXml)
{
xml.Parse();
- m_Xmls.Add(xml);
+ _xmls.Add(xml);
}
if (i == 1)
@@ -462,11 +479,14 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
}
}
- RINOK(SortDatabase(m_Database));
+ _db.DetectPathMode();
+ RINOK(_db.Sort(_db.SkipRoot));
wchar_t sz[32];
- ConvertUInt64ToString(m_Database.Streams.Size(), sz);
- m_NameLenForStreams = MyStringLen(sz);
+ ConvertUInt64ToString(_db.Streams.Size(), sz);
+ _nameLenForStreams = MyStringLen(sz);
+
+ _xmlInComments = (_xmls.Size() == 1 && !_db.ShowImageNumber);
}
catch(...)
{
@@ -478,10 +498,10 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
STDMETHODIMP CHandler::Close()
{
- m_Database.Clear();
- m_Volumes.Clear();
- m_Xmls.Clear();
- m_NameLenForStreams = 0;
+ _db.Clear();
+ _volumes.Clear();
+ _xmls.Clear();
+ _nameLenForStreams = 0;
return S_OK;
}
@@ -492,7 +512,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
bool allFilesMode = (numItems == (UInt32)-1);
if (allFilesMode)
- numItems = m_Database.Items.Size() + m_Xmls.Size();
+ numItems = _db.SortedItems.Size() + _xmls.Size();
if (numItems == 0)
return S_OK;
@@ -501,17 +521,17 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
for (i = 0; i < numItems; i++)
{
UInt32 index = allFilesMode ? i : indices[i];
- if (index < (UInt32)m_Database.Items.Size())
+ if (index < (UInt32)_db.SortedItems.Size())
{
- int streamIndex = m_Database.Items[index].StreamIndex;
+ int streamIndex = _db.Items[_db.SortedItems[index]].StreamIndex;
if (streamIndex >= 0)
{
- const CStreamInfo &si = m_Database.Streams[streamIndex];
+ const CStreamInfo &si = _db.Streams[streamIndex];
totalSize += si.Resource.UnpackSize;
}
}
else
- totalSize += m_Xmls[index - (UInt32)m_Database.Items.Size()].Data.GetCapacity();
+ totalSize += _xmls[index - (UInt32)_db.SortedItems.Size()].Data.GetCapacity();
}
RINOK(extractCallback->SetTotal(totalSize));
@@ -546,12 +566,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CMyComPtr<ISequentialOutStream> realOutStream;
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
- if (index >= (UInt32)m_Database.Items.Size())
+ if (index >= (UInt32)_db.SortedItems.Size())
{
if (!testMode && !realOutStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode));
- const CByteBuffer &data = m_Xmls[index - (UInt32)m_Database.Items.Size()].Data;
+ const CByteBuffer &data = _xmls[index - (UInt32)_db.SortedItems.Size()].Data;
currentItemUnPacked = data.GetCapacity();
if (realOutStream)
{
@@ -562,7 +582,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
continue;
}
- const CItem &item = m_Database.Items[index];
+ const CItem &item = _db.Items[_db.SortedItems[index]];
int streamIndex = item.StreamIndex;
if (streamIndex < 0)
{
@@ -576,7 +596,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
continue;
}
- const CStreamInfo &si = m_Database.Streams[streamIndex];
+ const CStreamInfo &si = _db.Streams[streamIndex];
currentItemUnPacked = si.Resource.UnpackSize;
currentItemPacked = si.Resource.PackSize;
@@ -587,7 +607,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (streamIndex != prevSuccessStreamIndex || realOutStream)
{
Byte digest[20];
- const CVolume &vol = m_Volumes[si.PartNumber];
+ const CVolume &vol = _volumes[si.PartNumber];
HRESULT res = unpacker.Unpack(vol.Stream, si.Resource, vol.Header.IsLzxMode(),
realOutStream, progress, digest);
if (res == S_OK)
@@ -611,7 +631,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
- *numItems = m_Database.Items.Size() + m_Xmls.Size();
+ *numItems = _db.SortedItems.Size();
+ if (!_xmlInComments)
+ *numItems += _xmls.Size();
return S_OK;
}
diff --git a/CPP/7zip/Archive/Wim/WimHandler.h b/CPP/7zip/Archive/Wim/WimHandler.h
index b7df3606..d105e548 100755
--- a/CPP/7zip/Archive/Wim/WimHandler.h
+++ b/CPP/7zip/Archive/Wim/WimHandler.h
@@ -6,7 +6,6 @@
#include "Common/MyCom.h"
#include "Common/MyXml.h"
-#include "../IArchive.h"
#include "WimIn.h"
namespace NArchive {
@@ -40,25 +39,35 @@ struct CXml
{
CByteBuffer Data;
UInt16 VolIndex;
-
CObjectVector<CImageInfo> Images;
+ void ToUnicode(UString &s);
void Parse();
};
+
class CHandler:
public IInArchive,
public CMyUnknownImp
{
+ CDatabase _db;
+ CObjectVector<CVolume> _volumes;
+ CObjectVector<CXml> _xmls;
+ int _nameLenForStreams;
+ bool _xmlInComments;
+
public:
MY_UNKNOWN_IMP1(IInArchive)
INTERFACE_IInArchive(;)
+};
-private:
- CDatabase m_Database;
- CObjectVector<CVolume> m_Volumes;
- CObjectVector<CXml> m_Xmls;
- int m_NameLenForStreams;
+class COutHandler:
+ public IOutArchive,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(IOutArchive)
+ INTERFACE_IOutArchive(;)
};
}}
diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
new file mode 100755
index 00000000..d51eb81a
--- /dev/null
+++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
@@ -0,0 +1,647 @@
+// WimHandlerOut.cpp
+
+#include "StdAfx.h"
+
+#include "../../../../C/CpuArch.h"
+
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/StreamUtils.h"
+
+#include "../../Crypto/RandGen.h"
+#include "../../Crypto/Sha1.h"
+
+#include "WimHandler.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NWim {
+
+struct CSha1Hash
+{
+ Byte Hash[kHashSize];
+};
+
+struct CHashList
+{
+ CRecordVector<CSha1Hash> Digests;
+ CIntVector Sorted;
+
+ int AddUnique(const CSha1Hash &h);
+};
+
+int CHashList::AddUnique(const CSha1Hash &h)
+{
+ int left = 0, right = Sorted.Size();
+ while (left != right)
+ {
+ int mid = (left + right) / 2;
+ int index = Sorted[mid];
+ UInt32 i;
+ const Byte *hash2 = Digests[index].Hash;
+ for (i = 0; i < kHashSize; i++)
+ if (h.Hash[i] != hash2[i])
+ break;
+ if (i == kHashSize)
+ return index;
+ if (h.Hash[i] < hash2[i])
+ right = mid;
+ else
+ left = mid + 1;
+ }
+ Sorted.Insert(left, Digests.Add(h));
+ return -1;
+}
+
+struct CUpdateItem
+{
+ UString Name;
+ UInt64 Size;
+ FILETIME CTime;
+ FILETIME ATime;
+ FILETIME MTime;
+ UInt32 Attrib;
+ bool IsDir;
+ int HashIndex;
+
+ CUpdateItem(): HashIndex(-1) {}
+};
+
+struct CDir
+{
+ int Index;
+ UString Name;
+ CObjectVector<CDir> Dirs;
+ CIntVector Files;
+
+ CDir(): Index(-1) {}
+ bool IsLeaf() const { return Index >= 0; }
+ UInt64 GetNumDirs() const;
+ UInt64 GetNumFiles() const;
+ CDir* AddDir(CObjectVector<CUpdateItem> &items, const UString &name, int index);
+};
+
+UInt64 CDir::GetNumDirs() const
+{
+ UInt64 num = Dirs.Size();
+ for (int i = 0; i < Dirs.Size(); i++)
+ num += Dirs[i].GetNumDirs();
+ return num;
+}
+
+UInt64 CDir::GetNumFiles() const
+{
+ UInt64 num = Files.Size();
+ for (int i = 0; i < Dirs.Size(); i++)
+ num += Dirs[i].GetNumFiles();
+ return num;
+}
+
+CDir* CDir::AddDir(CObjectVector<CUpdateItem> &items, const UString &name, int index)
+{
+ int left = 0, right = Dirs.Size();
+ while (left != right)
+ {
+ int mid = (left + right) / 2;
+ CDir &d = Dirs[mid];
+ int compare = name.CompareNoCase(d.IsLeaf() ? items[Dirs[mid].Index].Name : d.Name);
+ if (compare == 0)
+ {
+ if (index >= 0)
+ d.Index = index;
+ return &d;
+ }
+ if (compare < 0)
+ right = mid;
+ else
+ left = mid + 1;
+ }
+ Dirs.Insert(left, CDir());
+ CDir &d = Dirs[left];
+ d.Index = index;
+ if (index < 0)
+ d.Name = name;
+ return &d;
+}
+
+
+STDMETHODIMP COutHandler::GetFileTimeType(UInt32 *type)
+{
+ *type = NFileTimeType::kWindows;
+ return S_OK;
+}
+
+static HRESULT GetTime(IArchiveUpdateCallback *callback, int index, PROPID propID, FILETIME &ft)
+{
+ ft.dwLowDateTime = ft.dwHighDateTime = 0;
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(index, propID, &prop));
+ if (prop.vt == VT_FILETIME)
+ ft = prop.filetime;
+ else if (prop.vt != VT_EMPTY)
+ return E_INVALIDARG;
+ return S_OK;
+}
+
+#define Set16(p, d) SetUi16(p, d)
+#define Set32(p, d) SetUi32(p, d)
+#define Set64(p, d) SetUi64(p, d)
+
+void CResource::WriteTo(Byte *p) const
+{
+ Set64(p, PackSize);
+ p[7] = Flags;
+ Set64(p + 8, Offset);
+ Set64(p + 16, UnpackSize);
+}
+
+void CHeader::WriteTo(Byte *p) const
+{
+ memcpy(p, kSignature, kSignatureSize);
+ Set32(p + 8, kHeaderSizeMax);
+ Set32(p + 0xC, Version);
+ Set32(p + 0x10, Flags);
+ Set32(p + 0x14, ChunkSize);
+ memcpy(p + 0x18, Guid, 16);
+ Set16(p + 0x28, PartNumber);
+ Set16(p + 0x2A, NumParts);
+ Set32(p + 0x2C, NumImages);
+ OffsetResource.WriteTo(p + 0x30);
+ XmlResource.WriteTo(p + 0x48);
+ MetadataResource.WriteTo(p + 0x60);
+ IntegrityResource.WriteTo(p + 0x7C);
+ Set32(p + 0x78, BootIndex);
+ memset(p + 0x94, 0, 60);
+}
+
+void CStreamInfo::WriteTo(Byte *p) const
+{
+ Resource.WriteTo(p);
+ Set16(p + 0x18, PartNumber);
+ Set32(p + 0x1A, RefCount);
+ memcpy(p + 0x1E, Hash, kHashSize);
+}
+
+class CInStreamWithSha1:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ CMyComPtr<ISequentialInStream> _stream;
+ UInt64 _size;
+ NCrypto::NSha1::CContext _sha;
+public:
+ MY_UNKNOWN_IMP1(IInStream)
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+ void SetStream(ISequentialInStream *stream) { _stream = stream; }
+ void Init()
+ {
+ _size = 0;
+ _sha.Init();
+ }
+ void ReleaseStream() { _stream.Release(); }
+ UInt64 GetSize() const { return _size; }
+ void Final(Byte *digest) { _sha.Final(digest); }
+};
+
+STDMETHODIMP CInStreamWithSha1::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize;
+ HRESULT result = _stream->Read(data, size, &realProcessedSize);
+ _size += realProcessedSize;
+ _sha.Update((const Byte *)data, realProcessedSize);
+ if (processedSize != NULL)
+ *processedSize = realProcessedSize;
+ return result;
+}
+
+static void SetFileTimeToMem(Byte *p, const FILETIME &ft)
+{
+ Set32(p, ft.dwLowDateTime);
+ Set32(p + 4, ft.dwHighDateTime);
+}
+
+static size_t WriteItem(const CUpdateItem &item, Byte *p, const Byte *hash)
+{
+ int fileNameLen = item.Name.Length() * 2;
+ int fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);
+
+ size_t totalLen = ((kDirRecordSize + fileNameLen2 + 6) & ~7);
+ if (p)
+ {
+ memset(p, 0, totalLen);
+ Set64(p, totalLen);
+ Set64(p + 8, item.Attrib);
+ Set32(p + 0xC, (UInt32)(Int32)-1); // item.SecurityId
+ // Set64(p + 0x10, 0); // subdirOffset
+ SetFileTimeToMem(p + 0x28, item.CTime);
+ SetFileTimeToMem(p + 0x30, item.ATime);
+ SetFileTimeToMem(p + 0x38, item.MTime);
+ if (hash)
+ memcpy(p + 0x40, hash, kHashSize);
+ /*
+ else
+ memset(p + 0x40, 0, kHashSize);
+ */
+ // Set16(p + 98, 0); // shortNameLen
+ Set16(p + 100, (UInt16)fileNameLen);
+ for (int i = 0; i * 2 < fileNameLen; i++)
+ Set16(p + kDirRecordSize + i * 2, item.Name[i]);
+ }
+ return totalLen;
+}
+
+void WriteTree(const CDir &tree, CRecordVector<CSha1Hash> &digests,
+ CUpdateItem &defaultDirItem,
+ CObjectVector<CUpdateItem> &updateItems, Byte *dest, size_t &pos)
+{
+ int i;
+ for (i = 0; i < tree.Files.Size(); i++)
+ {
+ const CUpdateItem &ui = updateItems[tree.Files[i]];
+ pos += WriteItem(ui, dest ? dest + pos : NULL,
+ ui.HashIndex >= 0 ? digests[ui.HashIndex].Hash : NULL);
+ }
+
+ size_t posStart = pos;
+ for (i = 0; i < tree.Dirs.Size(); i++)
+ {
+ const CDir &subfolder = tree.Dirs[i];
+ CUpdateItem *item = &defaultDirItem;
+ if (subfolder.IsLeaf())
+ item = &updateItems[subfolder.Index];
+ else
+ defaultDirItem.Name = subfolder.Name;
+ pos += WriteItem(*item, NULL, NULL);
+ }
+
+ if (dest)
+ Set64(dest + pos, 0);
+
+ pos += 8;
+
+ for (i = 0; i < tree.Dirs.Size(); i++)
+ {
+ const CDir &subfolder = tree.Dirs[i];
+ if (dest)
+ {
+ CUpdateItem *item = &defaultDirItem;
+ if (subfolder.IsLeaf())
+ item = &updateItems[subfolder.Index];
+ else
+ defaultDirItem.Name = subfolder.Name;
+ size_t len = WriteItem(*item, dest + posStart, NULL);
+ Set64(dest + posStart + 0x10, pos);
+ posStart += len;
+ }
+ WriteTree(subfolder, digests, defaultDirItem, updateItems, dest, pos);
+ }
+}
+
+static void AddTag(AString &s, const char *name, const AString &value)
+{
+ s += "<";
+ s += name;
+ s += ">";
+ s += value;
+ s += "</";
+ s += name;
+ s += ">";
+}
+
+static void AddTagUInt64(AString &s, const char *name, UInt64 value)
+{
+ char temp[32];
+ ConvertUInt64ToString(value, temp);
+ AddTag(s, name, temp);
+}
+
+static void ConvertUInt32ToHex(UInt32 value, char *s)
+{
+ for (int i = 0; i < 8; i++)
+ {
+ int t = value & 0xF;
+ value >>= 4;
+ s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
+ }
+ s[8] = '\0';
+}
+
+
+static AString TimeToXml(FILETIME &ft)
+{
+ AString res;
+ char temp[16] = { '0', 'x' };
+ ConvertUInt32ToHex(ft.dwHighDateTime, temp + 2);
+ AddTag(res, "HIGHPART", temp);
+ ConvertUInt32ToHex(ft.dwLowDateTime, temp + 2);
+ AddTag(res, "LOWPART", temp);
+ return res;
+}
+
+void CHeader::SetDefaultFields(bool useLZX)
+{
+ Version = kWimVersion;
+ Flags = NHeaderFlags::kRpFix;
+ ChunkSize = 0;
+ if (useLZX)
+ {
+ Flags |= NHeaderFlags::kCompression | NHeaderFlags::kLZX;
+ ChunkSize = kChunkSize;
+ }
+ g_RandomGenerator.Generate(Guid, 16);
+ PartNumber = 1;
+ NumParts = 1;
+ NumImages = 1;
+ BootIndex = 0;
+ OffsetResource.Clear();
+ XmlResource.Clear();
+ MetadataResource.Clear();
+ IntegrityResource.Clear();
+}
+
+static HRESULT UpdateArchive(ISequentialOutStream *seqOutStream,
+ CDir &rootFolder,
+ CObjectVector<CUpdateItem> &updateItems,
+ IArchiveUpdateCallback *callback)
+{
+ CMyComPtr<IOutStream> outStream;
+ RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream));
+ if (!outStream)
+ return E_NOTIMPL;
+
+ UInt64 complexity = 0;
+
+ int i;
+ for (i = 0; i < updateItems.Size(); i++)
+ complexity += updateItems[i].Size;
+
+ RINOK(callback->SetTotal(complexity));
+
+ NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
+ CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(callback, true);
+
+ complexity = 0;
+
+ bool useCompression = false;
+
+ CHeader header;
+ header.SetDefaultFields(useCompression);
+ Byte buf[kHeaderSizeMax];
+ header.WriteTo(buf);
+ RINOK(WriteStream(outStream, buf, kHeaderSizeMax));
+
+ CHashList hashes;
+ CObjectVector<CStreamInfo> streams;
+
+ UInt64 curPos = kHeaderSizeMax;
+ UInt64 unpackTotalSize = 0;
+ for (i = 0; i < updateItems.Size(); i++)
+ {
+ lps->InSize = lps->OutSize = complexity;
+ RINOK(lps->SetCur());
+
+ CUpdateItem &ui = updateItems[i];
+ if (ui.IsDir || ui.Size == 0)
+ continue;
+
+ CInStreamWithSha1 *inShaStreamSpec = new CInStreamWithSha1;
+ CMyComPtr<ISequentialInStream> inShaStream = inShaStreamSpec;
+
+ {
+ CMyComPtr<ISequentialInStream> fileInStream;
+ HRESULT res = callback->GetStream(i, &fileInStream);
+ if (res != S_FALSE)
+ {
+ RINOK(res);
+ inShaStreamSpec->SetStream(fileInStream);
+ fileInStream.Release();
+ inShaStreamSpec->Init();
+ UInt64 offsetBlockSize = 0;
+ if (useCompression)
+ {
+ for (UInt64 t = kChunkSize; t < ui.Size; t += kChunkSize)
+ {
+ Byte buf[8];
+ SetUi32(buf, (UInt32)t);
+ RINOK(WriteStream(outStream, buf, 4));
+ offsetBlockSize += 4;
+ }
+ }
+
+ RINOK(copyCoder->Code(inShaStream, outStream, NULL, NULL, progress));
+ ui.Size = copyCoderSpec->TotalSize;
+
+ CSha1Hash hash;
+ unpackTotalSize += ui.Size;
+ UInt64 packSize = offsetBlockSize + ui.Size;
+ inShaStreamSpec->Final(hash.Hash);
+ int index = hashes.AddUnique(hash);
+ if (index >= 0)
+ {
+ ui.HashIndex = index;
+ streams[index].RefCount++;
+ outStream->Seek(-(Int64)packSize, STREAM_SEEK_CUR, &curPos);
+ outStream->SetSize(curPos);
+ }
+ else
+ {
+ ui.HashIndex = hashes.Digests.Size() - 1;
+ CStreamInfo s;
+ s.Resource.PackSize = packSize;
+ s.Resource.Offset = curPos;
+ s.Resource.UnpackSize = ui.Size;
+ s.Resource.Flags = 0;
+ if (useCompression)
+ s.Resource.Flags = NResourceFlags::Compressed;
+ s.PartNumber = 1;
+ s.RefCount = 1;
+ memcpy(s.Hash, hash.Hash, kHashSize);
+ streams.Add(s);
+ curPos += packSize;
+ }
+ }
+ fileInStream.Release();
+ complexity += ui.Size;
+ RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+ }
+ }
+
+
+ CUpdateItem ri;
+ FILETIME ft;
+ NTime::GetCurUtcFileTime(ft);
+ ri.MTime = ri.ATime = ri.CTime = ft;
+ ri.Attrib = FILE_ATTRIBUTE_DIRECTORY;
+
+ const UInt32 kSecuritySize = 8;
+ size_t pos = kSecuritySize;
+ WriteTree(rootFolder, hashes.Digests, ri, updateItems, NULL, pos);
+ CByteBuffer meta;
+ meta.SetCapacity(pos);
+ // memset(meta, 0, kSecuritySize);
+ Set32((Byte *)meta, 0); // only if there is no security data, we can use 0 here.
+ Set32((Byte *)meta + 4, 0); // num security entries
+ pos = kSecuritySize;
+ WriteTree(rootFolder, hashes.Digests, ri, updateItems, (Byte *)meta, pos);
+
+ {
+ NCrypto::NSha1::CContext sha;
+ sha.Init();
+ sha.Update((const Byte *)meta, pos);
+ CSha1Hash digest;
+ sha.Final(digest.Hash);
+
+ CStreamInfo s;
+ s.Resource.PackSize = pos;
+ s.Resource.Offset = curPos;
+ s.Resource.UnpackSize = pos;
+ s.Resource.Flags = NResourceFlags::kMetadata;
+ s.PartNumber = 1;
+ s.RefCount = 1;
+ memcpy(s.Hash, digest.Hash, kHashSize);
+ streams.Add(s);
+ RINOK(WriteStream(outStream, (const Byte *)meta, pos));
+ meta.Free();
+ curPos += pos;
+ }
+
+
+ header.OffsetResource.UnpackSize = header.OffsetResource.PackSize = (UInt64)streams.Size() * kStreamInfoSize;
+ header.OffsetResource.Offset = curPos;
+ header.OffsetResource.Flags = NResourceFlags::kMetadata;
+
+ for (i = 0; i < streams.Size(); i++)
+ {
+ Byte buf[kStreamInfoSize];
+ streams[i].WriteTo(buf);
+ RINOK(WriteStream(outStream, buf, kStreamInfoSize));
+ curPos += kStreamInfoSize;
+ }
+
+ AString xml = "<WIM>";
+ AddTagUInt64(xml, "TOTALBYTES", curPos);
+ xml += "<IMAGE INDEX=\"1\"><NAME>1</NAME>";
+ AddTagUInt64(xml, "DIRCOUNT", rootFolder.GetNumDirs());
+ AddTagUInt64(xml, "FILECOUNT", rootFolder.GetNumFiles());
+ AddTagUInt64(xml, "TOTALBYTES", unpackTotalSize);
+ NTime::GetCurUtcFileTime(ft);
+ AddTag(xml, "CREATIONTIME", TimeToXml(ft));
+ AddTag(xml, "LASTMODIFICATIONTIME", TimeToXml(ft));
+ xml += "</IMAGE></WIM>";
+
+ size_t xmlSize = (xml.Length() + 1) * 2;
+ meta.SetCapacity(xmlSize);
+ Set16((Byte *)meta, 0xFEFF);
+ for (i = 0; i < xml.Length(); i++)
+ Set16((Byte *)meta + 2 + i * 2, xml[i]);
+ RINOK(WriteStream(outStream, (const Byte *)meta, xmlSize));
+ meta.Free();
+
+ header.XmlResource.UnpackSize = header.XmlResource.PackSize = xmlSize;
+ header.XmlResource.Offset = curPos;
+ header.XmlResource.Flags = NResourceFlags::kMetadata;
+
+ outStream->Seek(0, STREAM_SEEK_SET, NULL);
+ header.WriteTo(buf);
+ return WriteStream(outStream, buf, kHeaderSizeMax);
+}
+
+STDMETHODIMP COutHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+ IArchiveUpdateCallback *callback)
+{
+ COM_TRY_BEGIN
+ CObjectVector<CUpdateItem> updateItems;
+ CDir tree;
+ tree.Dirs.Add(CDir());
+ CDir &rootFolder = tree.Dirs.Back();
+
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ CUpdateItem ui;
+ Int32 newData, newProps;
+ UInt32 indexInArchive;
+ if (!callback)
+ return E_FAIL;
+ RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidIsDir, &prop));
+ if (prop.vt == VT_EMPTY)
+ ui.IsDir = false;
+ else if (prop.vt != VT_BOOL)
+ return E_INVALIDARG;
+ else
+ ui.IsDir = (prop.boolVal != VARIANT_FALSE);
+ }
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidAttrib, &prop));
+ if (prop.vt == VT_EMPTY)
+ ui.Attrib = (ui.IsDir ? FILE_ATTRIBUTE_DIRECTORY : 0);
+ else if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ else
+ ui.Attrib = prop.ulVal;
+ }
+
+ RINOK(GetTime(callback, i, kpidCTime, ui.CTime));
+ RINOK(GetTime(callback, i, kpidATime, ui.ATime));
+ RINOK(GetTime(callback, i, kpidMTime, ui.MTime));
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidSize, &prop));
+ if (prop.vt != VT_UI8)
+ return E_INVALIDARG;
+ ui.Size = prop.uhVal.QuadPart;
+ }
+
+ UString path;
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidPath, &prop));
+ if (prop.vt == VT_BSTR)
+ path = prop.bstrVal;
+ else if (prop.vt != VT_EMPTY)
+ return E_INVALIDARG;
+
+ CDir *curItem = &rootFolder;
+ int len = path.Length();
+ UString fileName;
+ for (int j = 0; j < len; j++)
+ {
+ wchar_t c = path[j];
+ if (c == WCHAR_PATH_SEPARATOR || c == L'/')
+ {
+ curItem = curItem->AddDir(updateItems, fileName, -1);
+ fileName.Empty();
+ }
+ else
+ fileName += c;
+ }
+
+ ui.Name = fileName;
+ updateItems.Add(ui);
+ if (ui.IsDir)
+ curItem->AddDir(updateItems, fileName, (int)i);
+ else
+ curItem->Files.Add(i);
+ }
+ return UpdateArchive(outStream, tree, updateItems, callback);
+ COM_TRY_END
+}
+
+}}
diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp
index 90c3c2c2..b65b4c44 100755
--- a/CPP/7zip/Archive/Wim/WimIn.cpp
+++ b/CPP/7zip/Archive/Wim/WimIn.cpp
@@ -18,11 +18,8 @@
#define Get32(p) GetUi32(p)
#define Get64(p) GetUi64(p)
-namespace NArchive{
-namespace NWim{
-
-static const int kChunkSizeBits = 15;
-static const UInt32 kChunkSize = (1 << kChunkSizeBits);
+namespace NArchive {
+namespace NWim {
namespace NXpress {
@@ -44,7 +41,7 @@ HRESULT CDecoder::CodeSpec(UInt32 outSize)
{
{
Byte levels[kMainTableSize];
- for (int i = 0; i < kMainTableSize; i += 2)
+ for (unsigned i = 0; i < kMainTableSize; i += 2)
{
Byte b = m_InBitStream.DirectReadByte();
levels[i] = b & 0xF;
@@ -128,12 +125,6 @@ HRESULT CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outS
}
-static void GetFileTimeFromMem(const Byte *p, FILETIME *ft)
-{
- ft->dwLowDateTime = Get32(p);
- ft->dwHighDateTime = Get32(p + 4);
-}
-
HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource, bool lzxMode,
ISequentialOutStream *outStream, ICompressProgressInfo *progress)
{
@@ -257,9 +248,6 @@ static HRESULT UnpackData(IInStream *inStream, const CResource &resource, bool l
return unpacker.Unpack(inStream, resource, lzxMode, outStream, NULL, digest);
}
-static const UInt32 kSignatureSize = 8;
-static const Byte kSignature[kSignatureSize] = { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 };
-
void CResource::Parse(const Byte *p)
{
Flags = p[7];
@@ -278,19 +266,152 @@ static void GetStream(const Byte *p, CStreamInfo &s)
memcpy(s.Hash, p + 30, kHashSize);
}
-static HRESULT ParseDirItem(const Byte *base, size_t pos, size_t size,
- const UString &prefix, CObjectVector<CItem> &items)
+static const wchar_t *kLongPath = L"[LongPath]";
+
+UString CDatabase::GetItemPath(const int index1) const
{
- for (;;)
+ int size = 0;
+ int index = index1;
+ int newLevel;
+ for (newLevel = 0;; newLevel = 1)
+ {
+ const CItem &item = Items[index];
+ index = item.Parent;
+ if (index >= 0 || !SkipRoot)
+ size += item.Name.Length() + newLevel;
+ if (index < 0)
+ break;
+ if ((UInt32)size >= ((UInt32)1 << 16))
+ return kLongPath;
+ }
+
+ wchar_t temp[16];
+ int imageLen = 0;
+ if (ShowImageNumber)
{
- if (pos + 8 > size)
+ ConvertUInt32ToString(-1 - index, temp);
+ imageLen = MyStringLen(temp);
+ size += imageLen + 1;
+ }
+ if ((UInt32)size >= ((UInt32)1 << 16))
+ return kLongPath;
+
+ UString path;
+ wchar_t *s = path.GetBuffer(size);
+ s[size] = 0;
+ if (ShowImageNumber)
+ {
+ memcpy(s, temp, imageLen * sizeof(wchar_t));
+ s[imageLen] = WCHAR_PATH_SEPARATOR;
+ }
+
+ index = index1;
+
+ for (newLevel = 0;; newLevel = 1)
+ {
+ const CItem &item = Items[index];
+ index = item.Parent;
+ if (index >= 0 || !SkipRoot)
+ {
+ if (newLevel)
+ s[--size] = WCHAR_PATH_SEPARATOR;
+ size -= item.Name.Length();
+ memcpy(s + size, item.Name, sizeof(wchar_t) * item.Name.Length());
+ }
+ if (index < 0)
+ {
+ path.ReleaseBuffer();
+ return path;
+ }
+ }
+}
+
+static void GetFileTimeFromMem(const Byte *p, FILETIME *ft)
+{
+ ft->dwLowDateTime = Get32(p);
+ ft->dwHighDateTime = Get32(p + 4);
+}
+
+static HRESULT ReadName(const Byte *p, int size, UString &dest)
+{
+ if (size == 0)
+ return S_OK;
+ if (Get16(p + size) != 0)
+ return S_FALSE;
+ wchar_t *s = dest.GetBuffer(size / 2);
+ for (int i = 0; i <= size; i += 2)
+ *s++ = Get16(p + i);
+ dest.ReleaseBuffer();
+ return S_OK;
+}
+
+HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
+{
+ if ((pos & 7) != 0)
+ return S_FALSE;
+
+ int prevIndex = -1;
+ for (int numItems = 0;; numItems++)
+ {
+ if (OpenCallback)
+ {
+ UInt64 numFiles = Items.Size();
+ if ((numFiles & 0x3FF) == 0)
+ {
+ RINOK(OpenCallback->SetCompleted(&numFiles, NULL));
+ }
+ }
+ size_t rem = DirSize - pos;
+ if (pos < DirStartOffset || pos > DirSize || rem < 8)
return S_FALSE;
- const Byte *p = base + pos;
- UInt64 length = Get64(p);
- if (length == 0)
+ const Byte *p = DirData + pos;
+ UInt64 len = Get64(p);
+ if (len == 0)
+ {
+ if (parent < 0 && numItems != 1)
+ SkipRoot = false;
+ DirProcessed += 8;
return S_OK;
- if (pos + 102 > size || pos + length + 8 > size || length > ((UInt64)1 << 62))
+ }
+ if ((len & 7) != 0 || len < 0x28 || rem < len)
+ return S_FALSE;
+ DirProcessed += (size_t)len;
+ if (DirProcessed > DirSize)
+ return S_FALSE;
+ if (Get64(p + 8) == 0)
+ {
+ if (prevIndex == -1)
+ return S_FALSE;
+
+ UInt32 fileNameLen = Get16(p + 0x24);
+ if ((fileNameLen & 1) != 0 || ((0x26 + fileNameLen + 6) & ~7) != len)
+ return S_FALSE;
+
+ UString name;
+ RINOK(ReadName(p + 0x26, fileNameLen, name));
+
+ CItem &prevItem = Items[prevIndex];
+ if (name.IsEmpty() && !prevItem.HasStream())
+ memcpy(prevItem.Hash, p + 0x10, kHashSize);
+ else
+ {
+ CItem item;
+ item.Name = prevItem.Name + L':' + name;
+ item.CTime = prevItem.CTime;
+ item.ATime = prevItem.ATime;
+ item.MTime = prevItem.MTime;
+ memcpy(item.Hash, p + 0x10, kHashSize);
+ item.Attrib = 0;
+ item.Order = Order++;
+ item.Parent = parent;
+ Items.Add(item);
+ }
+ pos += (size_t)len;
+ continue;
+ }
+ if (len < kDirRecordSize)
return S_FALSE;
+
CItem item;
item.Attrib = Get32(p + 8);
// item.SecurityId = Get32(p + 0xC);
@@ -300,43 +421,64 @@ static HRESULT ParseDirItem(const Byte *base, size_t pos, size_t size,
GetFileTimeFromMem(p + 0x38, &item.MTime);
memcpy(item.Hash, p + 0x40, kHashSize);
- // UInt16 shortNameLen = Get16(p + 98);
- UInt16 fileNameLen = Get16(p + 100);
-
- size_t tempPos = pos + 102;
- if (tempPos + fileNameLen > size)
+ UInt32 shortNameLen = Get16(p + 98);
+ UInt32 fileNameLen = Get16(p + 100);
+ if ((shortNameLen & 1) != 0 || (fileNameLen & 1) != 0)
return S_FALSE;
+
+ UInt32 shortNameLen2 = (shortNameLen == 0 ? shortNameLen : shortNameLen + 2);
+ UInt32 fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);
+
+ if (((kDirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7) > len)
+ return S_FALSE;
+
+ p += kDirRecordSize;
- wchar_t *sz = item.Name.GetBuffer(prefix.Length() + fileNameLen / 2 + 1);
- MyStringCopy(sz, (const wchar_t *)prefix);
- sz += prefix.Length();
- for (UInt16 i = 0; i + 2 <= fileNameLen; i += 2)
- *sz++ = Get16(base + tempPos + i);
- *sz++ = '\0';
- item.Name.ReleaseBuffer();
- if (fileNameLen == 0 && item.isDir() && !item.HasStream())
+ RINOK(ReadName(p, fileNameLen, item.Name));
+ RINOK(ReadName(p + fileNameLen2, shortNameLen, item.ShortName));
+
+ if (parent < 0 && (shortNameLen || fileNameLen || !item.IsDir()))
+ SkipRoot = false;
+
+ /*
+ // there are some extra data for some files.
+ p -= kDirRecordSize;
+ p += ((kDirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7);
+ if (((kDirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~7) != len)
+ p = p;
+ */
+
+ /*
+ if (parent >= 0)
{
- item.Attrib = 0x10; // some swm archives have system/hidden attributes for root
- item.Name.Delete(item.Name.Length() - 1);
+ UString s = GetItemPath(parent) + L"\\" + item.Name;
+ printf("\n%s %8x %S", item.IsDir() ? "D" : " ", (int)subdirOffset, (const wchar_t *)s);
}
- items.Add(item);
- pos += (size_t)length;
- if (item.isDir() && (subdirOffset != 0))
+ */
+
+ if (fileNameLen == 0 && item.IsDir() && !item.HasStream())
+ item.Attrib = 0x10; // some swm archives have system/hidden attributes for root
+
+ item.Parent = parent;
+ prevIndex = Items.Add(item);
+ if (item.IsDir() && subdirOffset != 0)
{
- if (subdirOffset >= size)
- return S_FALSE;
- RINOK(ParseDirItem(base, (size_t)subdirOffset, size, item.Name + WCHAR_PATH_SEPARATOR, items));
+ RINOK(ParseDirItem((size_t)subdirOffset, prevIndex));
}
+ Items[prevIndex].Order = Order++;
+ pos += (size_t)len;
}
}
-static HRESULT ParseDir(const Byte *base, size_t size,
- const UString &prefix, CObjectVector<CItem> &items)
+HRESULT CDatabase::ParseImageDirs(const CByteBuffer &buf, int parent)
{
+ DirData = buf;
+ DirSize = buf.GetCapacity();
+
size_t pos = 0;
- if (pos + 8 > size)
+ if (DirSize < 8)
return S_FALSE;
- const Byte *p = base + pos;
+ const Byte *p = DirData;
UInt32 totalLength = Get32(p);
// UInt32 numEntries = Get32(p + 4);
pos += 8;
@@ -346,7 +488,7 @@ static HRESULT ParseDir(const Byte *base, size_t size,
UInt64 sum = 0;
for (UInt32 i = 0; i < numEntries; i++)
{
- if (pos + 8 > size)
+ if (pos + 8 > DirSize)
return S_FALSE;
UInt64 len = Get64(p + pos);
entryLens.Add(len);
@@ -359,62 +501,23 @@ static HRESULT ParseDir(const Byte *base, size_t size,
if (pos != totalLength)
return S_FALSE;
*/
- pos = totalLength;
- }
- return ParseDirItem(base, pos, size, prefix, items);
-}
-
-static int CompareHashRefs(const int *p1, const int *p2, void *param)
-{
- const CRecordVector<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)param;
- return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize);
-}
-
-static int CompareStreamsByPos(const CStreamInfo *p1, const CStreamInfo *p2, void * /* param */)
-{
- int res = MyCompare(p1->PartNumber, p2->PartNumber);
- if (res != 0)
- return res;
- return MyCompare(p1->Resource.Offset, p2->Resource.Offset);
-}
-
-int CompareItems(void *const *a1, void *const *a2, void * /* param */)
-{
- const CItem &i1 = **((const CItem **)a1);
- const CItem &i2 = **((const CItem **)a2);
-
- if (i1.isDir() != i2.isDir())
- return (i1.isDir()) ? 1 : -1;
- if (i1.isDir())
- return -MyStringCompareNoCase(i1.Name, i2.Name);
-
- int res = MyCompare(i1.StreamIndex, i2.StreamIndex);
- if (res != 0)
- return res;
- return MyStringCompareNoCase(i1.Name, i2.Name);
-}
-
-static int FindHash(const CRecordVector<CStreamInfo> &streams,
- const CRecordVector<int> &sortedByHash, const Byte *hash)
-{
- int left = 0, right = streams.Size();
- while (left != right)
- {
- int mid = (left + right) / 2;
- int streamIndex = sortedByHash[mid];
- UInt32 i;
- const Byte *hash2 = streams[streamIndex].Hash;
- for (i = 0; i < kHashSize; i++)
- if (hash[i] != hash2[i])
- break;
- if (i == kHashSize)
- return streamIndex;
- if (hash[i] < hash2[i])
- right = mid;
+ if (totalLength == 0)
+ pos = 8;
+ else if (totalLength < 8)
+ return S_FALSE;
else
- left = mid + 1;
+ pos = totalLength;
}
- return -1;
+ DirStartOffset = DirProcessed = pos;
+ RINOK(ParseDirItem(pos, parent));
+ if (DirProcessed == DirSize)
+ return S_OK;
+ /* Original program writes additional 8 bytes (END_OF_ROOT_FOLDER), but
+ reference to that folder is empty */
+ if (DirProcessed == DirSize - 8 && DirProcessed - DirStartOffset == 112 &&
+ Get64(p + DirSize - 8) == 0)
+ return S_OK;
+ return S_FALSE;
}
HRESULT CHeader::Parse(const Byte *p)
@@ -426,8 +529,8 @@ HRESULT CHeader::Parse(const Byte *p)
Flags = Get32(p + 0x10);
if (!IsSupported())
return S_FALSE;
- UInt32 chunkSize = Get32(p + 0x14);
- if (chunkSize != kChunkSize && chunkSize != 0)
+ ChunkSize = Get32(p + 0x14);
+ if (ChunkSize != kChunkSize && ChunkSize != 0)
return S_FALSE;
memcpy(Guid, p + 0x18, 16);
PartNumber = Get16(p + 0x28);
@@ -441,21 +544,20 @@ HRESULT CHeader::Parse(const Byte *p)
GetResource(p + offset, OffsetResource);
GetResource(p + offset + 0x18, XmlResource);
GetResource(p + offset + 0x30, MetadataResource);
- /*
if (IsNewVersion())
{
if (haderSize < 0xD0)
return S_FALSE;
- IntegrityResource.Parse(p + offset + 0x4C);
BootIndex = Get32(p + 0x48);
+ IntegrityResource.Parse(p + offset + 0x4C);
}
- */
return S_OK;
}
+const Byte kSignature[kSignatureSize] = { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 };
+
HRESULT ReadHeader(IInStream *inStream, CHeader &h)
{
- const UInt32 kHeaderSizeMax = 0xD0;
Byte p[kHeaderSizeMax];
RINOK(ReadStream_FALSE(inStream, p, kHeaderSizeMax));
if (memcmp(p, kSignature, kSignatureSize) != 0)
@@ -463,33 +565,35 @@ HRESULT ReadHeader(IInStream *inStream, CHeader &h)
return h.Parse(p);
}
-HRESULT ReadStreams(IInStream *inStream, const CHeader &h, CDatabase &db)
+static HRESULT ReadStreams(IInStream *inStream, const CHeader &h, CDatabase &db)
{
CByteBuffer offsetBuf;
RINOK(UnpackData(inStream, h.OffsetResource, h.IsLzxMode(), offsetBuf, NULL));
- for (size_t i = 0; i + kStreamInfoSize <= offsetBuf.GetCapacity(); i += kStreamInfoSize)
+ size_t i;
+ for (i = 0; offsetBuf.GetCapacity() - i >= kStreamInfoSize; i += kStreamInfoSize)
{
CStreamInfo s;
GetStream((const Byte *)offsetBuf + i, s);
if (s.PartNumber == h.PartNumber)
db.Streams.Add(s);
}
- return S_OK;
+ return (i == offsetBuf.GetCapacity()) ? S_OK : S_FALSE;
}
-HRESULT OpenArchive(IInStream *inStream, const CHeader &h, CByteBuffer &xml, CDatabase &db)
+HRESULT CDatabase::Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml, IArchiveOpenCallback *openCallback)
{
+ OpenCallback = openCallback;
RINOK(UnpackData(inStream, h.XmlResource, h.IsLzxMode(), xml, NULL));
-
- RINOK(ReadStreams(inStream, h, db));
+ RINOK(ReadStreams(inStream, h, *this));
bool needBootMetadata = !h.MetadataResource.IsEmpty();
+ Order = 0;
if (h.PartNumber == 1)
{
int imageIndex = 1;
- for (int j = 0; j < db.Streams.Size(); j++)
+ for (int i = 0; i < Streams.Size(); i++)
{
// if (imageIndex > 1) break;
- const CStreamInfo &si = db.Streams[j];
+ const CStreamInfo &si = Streams[i];
if (!si.Resource.IsMetadata() || si.PartNumber != h.PartNumber)
continue;
Byte hash[kHashSize];
@@ -497,11 +601,8 @@ HRESULT OpenArchive(IInStream *inStream, const CHeader &h, CByteBuffer &xml, CDa
RINOK(UnpackData(inStream, si.Resource, h.IsLzxMode(), metadata, hash));
if (memcmp(hash, si.Hash, kHashSize) != 0)
return S_FALSE;
- wchar_t sz[16];
- ConvertUInt32ToString(imageIndex++, sz);
- UString s = sz;
- s += WCHAR_PATH_SEPARATOR;
- RINOK(ParseDir(metadata, metadata.GetCapacity(), s, db.Items));
+ NumImages++;
+ RINOK(ParseImageDirs(metadata, -(int)(++imageIndex)));
if (needBootMetadata)
if (h.MetadataResource.Offset == si.Resource.Offset)
needBootMetadata = false;
@@ -512,58 +613,114 @@ HRESULT OpenArchive(IInStream *inStream, const CHeader &h, CByteBuffer &xml, CDa
{
CByteBuffer metadata;
RINOK(UnpackData(inStream, h.MetadataResource, h.IsLzxMode(), metadata, NULL));
- RINOK(ParseDir(metadata, metadata.GetCapacity(), L"0" WSTRING_PATH_SEPARATOR, db.Items));
+ RINOK(ParseImageDirs(metadata, -1));
+ NumImages++;
}
return S_OK;
}
-HRESULT SortDatabase(CDatabase &db)
+static int CompareStreamsByPos(const CStreamInfo *p1, const CStreamInfo *p2, void * /* param */)
{
- db.Streams.Sort(CompareStreamsByPos, NULL);
+ int res = MyCompare(p1->PartNumber, p2->PartNumber);
+ if (res != 0)
+ return res;
+ return MyCompare(p1->Resource.Offset, p2->Resource.Offset);
+}
+
+static int CompareHashRefs(const int *p1, const int *p2, void *param)
+{
+ const CRecordVector<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)param;
+ return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize);
+}
+
+static int FindHash(const CRecordVector<CStreamInfo> &streams,
+ const CIntVector &sortedByHash, const Byte *hash)
+{
+ int left = 0, right = streams.Size();
+ while (left != right)
+ {
+ int mid = (left + right) / 2;
+ int streamIndex = sortedByHash[mid];
+ UInt32 i;
+ const Byte *hash2 = streams[streamIndex].Hash;
+ for (i = 0; i < kHashSize; i++)
+ if (hash[i] != hash2[i])
+ break;
+ if (i == kHashSize)
+ return streamIndex;
+ if (hash[i] < hash2[i])
+ right = mid;
+ else
+ left = mid + 1;
+ }
+ return -1;
+}
+
+static int CompareItems(const int *a1, const int *a2, void *param)
+{
+ const CObjectVector<CItem> &items = ((CDatabase *)param)->Items;
+ const CItem &i1 = items[*a1];
+ const CItem &i2 = items[*a2];
+
+ if (i1.IsDir() != i2.IsDir())
+ return i1.IsDir() ? 1 : -1;
+ int res = MyCompare(i1.StreamIndex, i2.StreamIndex);
+ if (res != 0)
+ return res;
+ return MyCompare(i1.Order, i2.Order);
+}
+
+HRESULT CDatabase::Sort(bool skipRootDir)
+{
+ Streams.Sort(CompareStreamsByPos, NULL);
{
- CRecordVector<int> sortedByHash;
+ CIntVector sortedByHash;
{
- for (int j = 0; j < db.Streams.Size(); j++)
- sortedByHash.Add(j);
- sortedByHash.Sort(CompareHashRefs, &db.Streams);
+ for (int i = 0; i < Streams.Size(); i++)
+ sortedByHash.Add(i);
+ sortedByHash.Sort(CompareHashRefs, &Streams);
}
- for (int i = 0; i < db.Items.Size(); i++)
+ for (int i = 0; i < Items.Size(); i++)
{
- CItem &item = db.Items[i];
+ CItem &item = Items[i];
item.StreamIndex = -1;
if (item.HasStream())
- item.StreamIndex = FindHash(db.Streams, sortedByHash, item.Hash);
+ item.StreamIndex = FindHash(Streams, sortedByHash, item.Hash);
}
}
{
CRecordVector<bool> used;
- int j;
- for (j = 0; j < db.Streams.Size(); j++)
+ int i;
+ for (i = 0; i < Streams.Size(); i++)
{
- const CStreamInfo &s = db.Streams[j];
+ const CStreamInfo &s = Streams[i];
used.Add(s.Resource.IsMetadata() && s.PartNumber == 1);
+ // used.Add(false);
}
- for (int i = 0; i < db.Items.Size(); i++)
+ for (i = 0; i < Items.Size(); i++)
{
- CItem &item = db.Items[i];
+ CItem &item = Items[i];
if (item.StreamIndex >= 0)
used[item.StreamIndex] = true;
}
- for (j = 0; j < db.Streams.Size(); j++)
- if (!used[j])
+ for (i = 0; i < Streams.Size(); i++)
+ if (!used[i])
{
CItem item;
- item.StreamIndex = j;
+ item.StreamIndex = i;
item.HasMetadata = false;
- db.Items.Add(item);
- }
+ Items.Add(item);
+ }
}
-
- db.Items.Sort(CompareItems, NULL);
+
+ SortedItems.Reserve(Items.Size());
+ for (int i = (skipRootDir ? 1 : 0); i < Items.Size(); i++)
+ SortedItems.Add(i);
+ SortedItems.Sort(CompareItems, this);
return S_OK;
}
diff --git a/CPP/7zip/Archive/Wim/WimIn.h b/CPP/7zip/Archive/Wim/WimIn.h
index e51a301a..5bca71db 100755
--- a/CPP/7zip/Archive/Wim/WimIn.h
+++ b/CPP/7zip/Archive/Wim/WimIn.h
@@ -9,6 +9,8 @@
#include "../../Compress/CopyCoder.h"
#include "../../Compress/LzxDecoder.h"
+#include "../IArchive.h"
+
namespace NArchive {
namespace NWim {
@@ -56,7 +58,7 @@ public:
}
};
-const int kNumHuffmanBits = 16;
+const unsigned kNumHuffmanBits = 16;
const UInt32 kMatchMinLen = 3;
const UInt32 kNumLenSlots = 16;
const UInt32 kNumPosSlots = 16;
@@ -85,8 +87,10 @@ public:
namespace NResourceFlags
{
- const Byte Compressed = 4;
+ const Byte kFree = 1;
const Byte kMetadata = 2;
+ const Byte Compressed = 4;
+ const Byte Spanned = 4;
}
struct CResource
@@ -96,9 +100,18 @@ struct CResource
UInt64 UnpackSize;
Byte Flags;
+ void Clear()
+ {
+ PackSize = 0;
+ Offset = 0;
+ UnpackSize = 0;
+ Flags = 0;
+ }
void Parse(const Byte *p);
- bool IsCompressed() const { return (Flags & NResourceFlags::Compressed) != 0; }
+ void WriteTo(Byte *p) const;
+ bool IsFree() const { return (Flags & NResourceFlags::kFree) != 0; }
bool IsMetadata() const { return (Flags & NResourceFlags::kMetadata) != 0; }
+ bool IsCompressed() const { return (Flags & NResourceFlags::Compressed) != 0; }
bool IsEmpty() const { return (UnpackSize == 0); }
};
@@ -111,30 +124,37 @@ namespace NHeaderFlags
const UInt32 kLZX = 0x40000;
}
+const UInt32 kWimVersion = 0x010D00;
+const UInt32 kHeaderSizeMax = 0xD0;
+const UInt32 kSignatureSize = 8;
+extern const Byte kSignature[kSignatureSize];
+const unsigned kChunkSizeBits = 15;
+const UInt32 kChunkSize = (1 << kChunkSizeBits);
+
struct CHeader
{
- UInt32 Flags;
UInt32 Version;
- // UInt32 ChunkSize;
+ UInt32 Flags;
+ UInt32 ChunkSize;
+ Byte Guid[16];
UInt16 PartNumber;
UInt16 NumParts;
UInt32 NumImages;
- Byte Guid[16];
CResource OffsetResource;
CResource XmlResource;
CResource MetadataResource;
- /*
CResource IntegrityResource;
UInt32 BootIndex;
- */
+ void SetDefaultFields(bool useLZX);
+
+ void WriteTo(Byte *p) const;
HRESULT Parse(const Byte *p);
bool IsCompressed() const { return (Flags & NHeaderFlags::kCompression) != 0; }
bool IsSupported() const { return (!IsCompressed() || (Flags & NHeaderFlags::kLZX) != 0 || (Flags & NHeaderFlags::kXPRESS) != 0 ) ; }
bool IsLzxMode() const { return (Flags & NHeaderFlags::kLZX) != 0; }
bool IsSpanned() const { return (!IsCompressed() || (Flags & NHeaderFlags::kSpanned) != 0); }
-
bool IsNewVersion()const { return (Version > 0x010C00); }
bool AreFromOnArchive(const CHeader &h)
@@ -152,11 +172,16 @@ struct CStreamInfo
UInt16 PartNumber;
UInt32 RefCount;
BYTE Hash[kHashSize];
+
+ void WriteTo(Byte *p) const;
};
+const UInt32 kDirRecordSize = 102;
+
struct CItem
{
UString Name;
+ UString ShortName;
UInt32 Attrib;
// UInt32 SecurityId;
BYTE Hash[kHashSize];
@@ -168,22 +193,39 @@ struct CItem
// UInt16 NumStreams;
// UInt16 ShortNameLen;
int StreamIndex;
+ int Parent;
+ unsigned Order;
bool HasMetadata;
CItem(): HasMetadata(true), StreamIndex(-1) {}
- bool isDir() const { return HasMetadata && ((Attrib & 0x10) != 0); }
+ bool IsDir() const { return HasMetadata && ((Attrib & 0x10) != 0); }
bool HasStream() const
{
- for (int i = 0; i < kHashSize; i++)
+ for (unsigned i = 0; i < kHashSize; i++)
if (Hash[i] != 0)
return true;
return false;
}
};
-struct CDatabase
+class CDatabase
{
+ const Byte *DirData;
+ size_t DirSize;
+ size_t DirProcessed;
+ size_t DirStartOffset;
+ int Order;
+ IArchiveOpenCallback *OpenCallback;
+
+ HRESULT ParseDirItem(size_t pos, int parent);
+ HRESULT ParseImageDirs(const CByteBuffer &buf, int parent);
+
+public:
CRecordVector<CStreamInfo> Streams;
CObjectVector<CItem> Items;
+ CIntVector SortedItems;
+ int NumImages;
+ bool SkipRoot;
+ bool ShowImageNumber;
UInt64 GetUnpackSize() const
{
@@ -205,12 +247,26 @@ struct CDatabase
{
Streams.Clear();
Items.Clear();
+ SortedItems.Clear();
+ NumImages = 0;
+
+ SkipRoot = true;
+ ShowImageNumber = true;
}
+
+ UString GetItemPath(int index) const;
+
+ HRESULT Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml, IArchiveOpenCallback *openCallback);
+
+ void DetectPathMode()
+ {
+ ShowImageNumber = (NumImages != 1);
+ }
+
+ HRESULT Sort(bool skipRootDir);
};
HRESULT ReadHeader(IInStream *inStream, CHeader &header);
-HRESULT OpenArchive(IInStream *inStream, const CHeader &header, CByteBuffer &xml, CDatabase &database);
-HRESULT SortDatabase(CDatabase &database);
class CUnpacker
{
diff --git a/CPP/7zip/Archive/Wim/WimRegister.cpp b/CPP/7zip/Archive/Wim/WimRegister.cpp
index 3c8e216f..8da91436 100755
--- a/CPP/7zip/Archive/Wim/WimRegister.cpp
+++ b/CPP/7zip/Archive/Wim/WimRegister.cpp
@@ -6,8 +6,13 @@
#include "WimHandler.h"
static IInArchive *CreateArc() { return new NArchive::NWim::CHandler; }
+#ifndef EXTRACT_ONLY
+static IOutArchive *CreateArcOut() { return new NArchive::NWim::COutHandler; }
+#else
+#define CreateArcOut 0
+#endif
static CArcInfo g_ArcInfo =
- { L"Wim", L"wim swm", 0, 0xE6, { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 }, 8, false, CreateArc, 0 };
+ { L"wim", L"wim swm", 0, 0xE6, { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 }, 8, false, CreateArc, CreateArcOut };
REGISTER_ARC(Wim)
diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h
index 68dd60dc..fdb60aaf 100755
--- a/CPP/7zip/Archive/Zip/ZipHandler.h
+++ b/CPP/7zip/Archive/Zip/ZipHandler.h
@@ -63,8 +63,8 @@ private:
Byte m_AesKeyMode;
bool m_WriteNtfsTimeExtra;
- bool m_ForseLocal;
- bool m_ForseUtf8;
+ bool m_ForceLocal;
+ bool m_ForceUtf8;
#ifndef _7ZIP_ST
UInt32 _numThreads;
@@ -88,8 +88,8 @@ private:
m_IsAesMode = false;
m_AesKeyMode = 3; // aes-256
m_WriteNtfsTimeExtra = true;
- m_ForseLocal = false;
- m_ForseUtf8 = false;
+ m_ForceLocal = false;
+ m_ForceUtf8 = false;
#ifndef _7ZIP_ST
_numThreads = NWindows::NSystem::GetNumberOfProcessors();;
#endif
diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
index fa7a4480..a5e0f59d 100755
--- a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
+++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp
@@ -189,11 +189,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
name += kSlash;
bool tryUtf8 = true;
- if (m_ForseLocal || !m_ForseUtf8)
+ if (m_ForceLocal || !m_ForceUtf8)
{
bool defaultCharWasUsed;
ui.Name = UnicodeStringToMultiByte(name, CP_OEMCP, '_', defaultCharWasUsed);
- tryUtf8 = (!m_ForseLocal && (defaultCharWasUsed ||
+ tryUtf8 = (!m_ForceLocal && (defaultCharWasUsed ||
MultiByteToUnicodeString(ui.Name, CP_OEMCP) != name));
}
@@ -512,15 +512,15 @@ STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *v
}
else if (name.CompareNoCase(L"CL") == 0)
{
- RINOK(SetBoolProperty(m_ForseLocal, prop));
- if (m_ForseLocal)
- m_ForseUtf8 = false;
+ RINOK(SetBoolProperty(m_ForceLocal, prop));
+ if (m_ForceLocal)
+ m_ForceUtf8 = false;
}
else if (name.CompareNoCase(L"CU") == 0)
{
- RINOK(SetBoolProperty(m_ForseUtf8, prop));
- if (m_ForseUtf8)
- m_ForseLocal = false;
+ RINOK(SetBoolProperty(m_ForceUtf8, prop));
+ if (m_ForceUtf8)
+ m_ForceLocal = false;
}
else
return E_INVALIDARG;
diff --git a/CPP/7zip/Bundles/Alone/makefile b/CPP/7zip/Bundles/Alone/makefile
index 9dd02872..862d695a 100755
--- a/CPP/7zip/Bundles/Alone/makefile
+++ b/CPP/7zip/Bundles/Alone/makefile
@@ -97,7 +97,6 @@ AR_OBJS = \
$O\DeflateProps.obj \
$O\GzHandler.obj \
$O\LzmaHandler.obj \
- $O\PpmdHandler.obj \
$O\SplitHandler.obj \
$O\XzHandler.obj \
$O\ZHandler.obj \
diff --git a/CPP/7zip/Bundles/Fm/makefile b/CPP/7zip/Bundles/Fm/makefile
index 8b01a739..74703a99 100755
--- a/CPP/7zip/Bundles/Fm/makefile
+++ b/CPP/7zip/Bundles/Fm/makefile
@@ -322,6 +322,7 @@ UDF_OBJS = \
WIM_OBJS = \
$O\WimHandler.obj \
+ $O\WimHandlerOut.obj \
$O\WimIn.obj \
$O\WimRegister.obj \
diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp
index 4be37b86..4b24d0b9 100755
--- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp
+++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp
@@ -2229,6 +2229,10 @@ SOURCE=..\..\Archive\Wim\WimHandler.h
# End Source File
# Begin Source File
+SOURCE=..\..\Archive\Wim\WimHandlerOut.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Archive\Wim\WimIn.cpp
# End Source File
# Begin Source File
diff --git a/CPP/7zip/Bundles/Format7zF/makefile b/CPP/7zip/Bundles/Format7zF/makefile
index b72468c0..5afa115e 100755
--- a/CPP/7zip/Bundles/Format7zF/makefile
+++ b/CPP/7zip/Bundles/Format7zF/makefile
@@ -173,6 +173,7 @@ UDF_OBJS = \
WIM_OBJS = \
$O\WimHandler.obj \
+ $O\WimHandlerOut.obj \
$O\WimIn.obj \
$O\WimRegister.obj \
diff --git a/CPP/7zip/MyVersion.h b/CPP/7zip/MyVersion.h
index 337e5725..d46b673b 100755
--- a/CPP/7zip/MyVersion.h
+++ b/CPP/7zip/MyVersion.h
@@ -1,8 +1,8 @@
#define MY_VER_MAJOR 9
-#define MY_VER_MINOR 13
+#define MY_VER_MINOR 14
#define MY_VER_BUILD 0
-#define MY_VERSION "9.13 beta"
-#define MY_7ZIP_VERSION "7-Zip 9.13 beta"
-#define MY_DATE "2010-04-15"
+#define MY_VERSION "9.14 beta"
+#define MY_7ZIP_VERSION "7-Zip 9.14 beta"
+#define MY_DATE "2010-06-04"
#define MY_COPYRIGHT "Copyright (c) 1999-2010 Igor Pavlov"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE
diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp
index d8c0e7d6..daa57ef6 100755
--- a/CPP/7zip/UI/Common/PropIDUtils.cpp
+++ b/CPP/7zip/UI/Common/PropIDUtils.cpp
@@ -24,6 +24,27 @@ void ConvertUInt32ToHex(UInt32 value, wchar_t *s)
s[8] = L'\0';
}
+static const char g_WinAttrib[17] = "RHS8DAdNTsrCOnE_";
+/*
+0 READONLY
+1 HIDDEN
+3 SYSTEM
+
+4 DIRECTORY
+5 ARCHIVE
+6 DEVICE
+7 NORMAL
+8 TEMPORARY
+9 SPARSE_FILE
+10 REPARSE_POINT
+11 COMPRESSED
+12 OFFLINE
+13 NOT_CONTENT_INDEXED
+14 ENCRYPTED
+
+16 VIRTUAL
+*/
+
#define MY_ATTR_CHAR(a, n, c) ((a )& (1 << (n))) ? c : L'-';
UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool full)
@@ -55,16 +76,14 @@ UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool ful
{
if (prop.vt != VT_UI4)
break;
- UString res;
UInt32 a = prop.ulVal;
- if (NFile::NFind::NAttributes::IsReadOnly(a)) res += L'R';
- if (NFile::NFind::NAttributes::IsHidden(a)) res += L'H';
- if (NFile::NFind::NAttributes::IsSystem(a)) res += L'S';
- if (NFile::NFind::NAttributes::IsDir(a)) res += L'D';
- if (NFile::NFind::NAttributes::IsArchived(a)) res += L'A';
- if (NFile::NFind::NAttributes::IsCompressed(a)) res += L'C';
- if (NFile::NFind::NAttributes::IsEncrypted(a)) res += L'E';
- return res;
+ wchar_t sz[32];
+ int pos = 0;
+ for (int i = 0; i < 16; i++)
+ if (a & (1 << i) && i != 7)
+ sz[pos++] = g_WinAttrib[i];
+ sz[pos] = '\0';
+ return sz;
}
case kpidPosixAttrib:
{
diff --git a/CPP/7zip/UI/Console/UserInputUtils.cpp b/CPP/7zip/UI/Console/UserInputUtils.cpp
index 0e55a868..bae33478 100755
--- a/CPP/7zip/UI/Console/UserInputUtils.cpp
+++ b/CPP/7zip/UI/Console/UserInputUtils.cpp
@@ -26,6 +26,7 @@ NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)
for (;;)
{
(*outStream) << kHelpQuestionMessage;
+ outStream->Flush();
AString scannedString = g_StdIn.ScanStringUntilNewLine();
scannedString.Trim();
if (!scannedString.IsEmpty())
diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
index 15e01483..12206786 100755
--- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
+++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
@@ -163,40 +163,51 @@ HRESULT CPanel::OpenParentArchiveFolder()
return S_OK;
}
-static const wchar_t *kStartExtensions[] =
-{
+static const char *kStartExtensions =
#ifdef UNDER_CE
- L"cab",
+ " cab"
#endif
- L"exe", L"bat", L"com",
- L"chm",
- L"msi", L"doc", L"xls", L"ppt", L"pps", L"wps", L"wpt", L"wks", L"xlr", L"wdb",
+ " exe bat com"
+ " chm"
+ " msi doc xls ppt pps wps wpt wks xlr wdb"
- L"docx", L"docm", L"dotx", L"dotm", L"xlsx", L"xlsm", L"xltx", L"xltm", L"xlsb",
- L"xlam", L"pptx", L"pptm", L"potx", L"potm", L"ppam", L"ppsx", L"ppsm", L"xsn",
- L"msg",
- L"dwf",
+ " docx docm dotx dotm xlsx xlsm xltx xltm xlsb"
+ " xlam pptx pptm potx potm ppam ppsx ppsm xsn"
+ " mpp"
+ " msg"
+ " dwf"
- L"flv", L"swf",
+ " flv swf"
- L"odt", L"ods",
- L"wb3",
- L"pdf"
-};
+ " odt ods"
+ " wb3"
+ " pdf"
+ " ";
-static bool DoItemAlwaysStart(const UString &name)
+static bool FindExt(const char *p, const UString &name)
{
int extPos = name.ReverseFind('.');
if (extPos < 0)
return false;
UString ext = name.Mid(extPos + 1);
ext.MakeLower();
- for (int i = 0; i < sizeof(kStartExtensions) / sizeof(kStartExtensions[0]); i++)
- if (ext.Compare(kStartExtensions[i]) == 0)
+ AString ext2 = UnicodeStringToMultiByte(ext);
+ for (int i = 0; p[i] != 0;)
+ {
+ int j;
+ for (j = i; p[j] != ' '; j++);
+ if (ext2.Length() == j - i && memcmp(p + i, (const char *)ext2, ext2.Length()) == 0)
return true;
+ i = j + 1;
+ }
return false;
}
+static bool DoItemAlwaysStart(const UString &name)
+{
+ return FindExt(kStartExtensions, name);
+}
+
static UString GetQuotedString(const UString &s)
{
return UString(L'\"') + s + UString(L'\"');
diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp
index 75a1f9ed..25c20c29 100755
--- a/CPP/7zip/UI/GUI/CompressDialog.cpp
+++ b/CPP/7zip/UI/GUI/CompressDialog.cpp
@@ -229,6 +229,12 @@ static const CFormatInfo g_Formats[] =
(1 << 0),
0, 0,
false, false, false, false, false, false
+ },
+ {
+ L"wim",
+ (1 << 0),
+ 0, 0,
+ false, false, false, false, false, false
}
};
@@ -1032,7 +1038,7 @@ void CCompressDialog::SetDictionary()
if (i == 20 && j > 0)
continue;
UInt32 dictionary = (1 << i) + (j << (i - 1));
- if (dictionary >= (1 << 31))
+ if (dictionary > (1 << 30))
continue;
AddDictionarySize(dictionary);
UInt64 decomprSize;