summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/unix/CPP/7zip/Archive/Wim/WimHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/7zip/unix/CPP/7zip/Archive/Wim/WimHandler.cpp')
-rw-r--r--src/libs/7zip/unix/CPP/7zip/Archive/Wim/WimHandler.cpp660
1 files changed, 0 insertions, 660 deletions
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Wim/WimHandler.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/Wim/WimHandler.cpp
deleted file mode 100644
index eaad1e7ca..000000000
--- a/src/libs/7zip/unix/CPP/7zip/Archive/Wim/WimHandler.cpp
+++ /dev/null
@@ -1,660 +0,0 @@
-// WimHandler.cpp
-
-#include "StdAfx.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/ProgressUtils.h"
-#include "../../Common/StreamUtils.h"
-
-#include "WimHandler.h"
-
-#define Get16(p) GetUi16(p)
-#define Get32(p) GetUi32(p)
-#define Get64(p) GetUi64(p)
-
-using namespace NWindows;
-
-namespace NArchive {
-namespace NWim {
-
-#define WIM_DETAILS
-
-static STATPROPSTG kProps[] =
-{
- { NULL, kpidPath, VT_BSTR},
- { NULL, kpidIsDir, VT_BOOL},
- { NULL, kpidSize, VT_UI8},
- { NULL, kpidPackSize, VT_UI8},
- { NULL, kpidMTime, VT_FILETIME},
- { NULL, kpidCTime, 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}
- , { NULL, kpidOffset, VT_UI8}
- , { NULL, kpidLinks, VT_UI4}
- #endif
-};
-
-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_BSTR},
- { NULL, kpidUnpackVer, VT_BSTR},
- { NULL, kpidIsVolume, VT_BOOL},
- { NULL, kpidVolume, VT_UI4},
- { NULL, kpidNumVolumes, VT_UI4}
-};
-
-static bool ParseNumber64(const AString &s, UInt64 &res)
-{
- const char *end;
- if (s.Left(2) == "0x")
- {
- if (s.Length() == 2)
- return false;
- res = ConvertHexStringToUInt64((const char *)s + 2, &end);
- }
- else
- {
- if (s.IsEmpty())
- return false;
- res = ConvertStringToUInt64(s, &end);
- }
- return *end == 0;
-}
-
-static bool ParseNumber32(const AString &s, UInt32 &res)
-{
- UInt64 res64;
- if (!ParseNumber64(s, res64) || res64 >= ((UInt64)1 << 32))
- return false;
- res = (UInt32)res64;
- return true;
-}
-
-bool ParseTime(const CXmlItem &item, FILETIME &ft, const char *tag)
-{
- int index = item.FindSubTag(tag);
- if (index >= 0)
- {
- const CXmlItem &timeItem = item.SubItems[index];
- UInt32 low = 0, high = 0;
- if (ParseNumber32(timeItem.GetSubStringForTag("LOWPART"), low) &&
- ParseNumber32(timeItem.GetSubStringForTag("HIGHPART"), high))
- {
- ft.dwLowDateTime = low;
- ft.dwHighDateTime = high;
- return true;
- }
- }
- return false;
-}
-
-void CImageInfo::Parse(const CXmlItem &item)
-{
- CTimeDefined = ParseTime(item, CTime, "CREATIONTIME");
- MTimeDefined = ParseTime(item, MTime, "LASTMODIFICATIONTIME");
- NameDefined = ConvertUTF8ToUnicode(item.GetSubStringForTag("NAME"), Name);
- // IndexDefined = ParseNumber32(item.GetPropertyValue("INDEX"), Index);
-}
-
-void CXml::ToUnicode(UString &s)
-{
- size_t size = Data.GetCapacity();
- if (size < 2 || (size & 1) != 0 || size > (1 << 24))
- return;
- const Byte *p = Data;
- if (Get16(p) != 0xFEFF)
- return;
- 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;
- ::CXml xml;
- if (!xml.Parse(utf))
- return;
- if (xml.Root.Name != "WIM")
- return;
-
- for (int i = 0; i < xml.Root.SubItems.Size(); i++)
- {
- const CXmlItem &item = xml.Root.SubItems[i];
- if (item.IsTagged("IMAGE"))
- {
- CImageInfo imageInfo;
- imageInfo.Parse(item);
- Images.Add(imageInfo);
- }
- }
-}
-
-static const char *kMethodLZX = "LZX";
-static const char *kMethodXpress = "XPress";
-static const char *kMethodCopy = "Copy";
-
-IMP_IInArchive_Props
-IMP_IInArchive_ArcProps
-
-STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
-{
- COM_TRY_BEGIN
- NWindows::NCOM::CPropVariant prop;
-
- const CImageInfo *image = NULL;
- if (_xmls.Size() == 1)
- {
- const CXml &xml = _xmls[0];
- if (xml.Images.Size() == 1)
- image = &xml.Images[0];
- }
-
- switch(propID)
- {
- case kpidSize: prop = _db.GetUnpackSize(); break;
- case kpidPackSize: prop = _db.GetPackSize(); break;
-
- case kpidCTime:
- if (_xmls.Size() == 1)
- {
- const CXml &xml = _xmls[0];
- int index = -1;
- for (int i = 0; i < xml.Images.Size(); i++)
- {
- const CImageInfo &image = xml.Images[i];
- if (image.CTimeDefined)
- if (index < 0 || ::CompareFileTime(&image.CTime, &xml.Images[index].CTime) < 0)
- index = i;
- }
- if (index >= 0)
- prop = xml.Images[index].CTime;
- }
- break;
-
- case kpidMTime:
- if (_xmls.Size() == 1)
- {
- const CXml &xml = _xmls[0];
- int index = -1;
- for (int i = 0; i < xml.Images.Size(); i++)
- {
- const CImageInfo &image = xml.Images[i];
- if (image.MTimeDefined)
- if (index < 0 || ::CompareFileTime(&image.MTime, &xml.Images[index].MTime) > 0)
- index = i;
- }
- if (index >= 0)
- prop = xml.Images[index].MTime;
- }
- 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 kpidUnpackVer:
- {
- UInt32 ver1 = _version >> 16;
- UInt32 ver2 = (_version >> 8) & 0xFF;
- UInt32 ver3 = (_version) & 0xFF;
-
- char s[16];
- ConvertUInt32ToString(ver1, s);
- AString res = s;
- res += '.';
- ConvertUInt32ToString(ver2, s);
- res += s;
- if (ver3 != 0)
- {
- res += '.';
- ConvertUInt32ToString(ver3, s);
- res += s;
- }
- prop = res;
- break;
- }
-
- case kpidIsVolume:
- if (_xmls.Size() > 0)
- {
- UInt16 volIndex = _xmls[0].VolIndex;
- if (volIndex < _volumes.Size())
- prop = (_volumes[volIndex].Header.NumParts > 1);
- }
- break;
- case kpidVolume:
- if (_xmls.Size() > 0)
- {
- UInt16 volIndex = _xmls[0].VolIndex;
- if (volIndex < _volumes.Size())
- prop = (UInt32)_volumes[volIndex].Header.PartNumber;
- }
- 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 < _xmls.Size(); i++)
- {
- const CHeader &header = _volumes[_xmls[i].VolIndex].Header;
- if (header.IsCompressed())
- if (header.IsLzxMode())
- lzx = true;
- else
- xpress = true;
- else
- copy = true;
- }
- AString res;
- if (lzx)
- res = kMethodLZX;
- if (xpress)
- {
- if (!res.IsEmpty())
- res += ' ';
- res += kMethodXpress;
- }
- if (copy)
- {
- if (!res.IsEmpty())
- res += ' ';
- res += kMethodCopy;
- }
- prop = res;
- }
- }
- prop.Detach(value);
- return S_OK;
- COM_TRY_END
-}
-
-STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
-{
- COM_TRY_BEGIN
- NWindows::NCOM::CPropVariant prop;
- if (index < (UInt32)_db.SortedItems.Size())
- {
- int realIndex = _db.SortedItems[index];
- const CItem &item = _db.Items[realIndex];
- const CStreamInfo *si = NULL;
- const CVolume *vol = NULL;
- if (item.StreamIndex >= 0)
- {
- si = &_db.Streams[item.StreamIndex];
- vol = &_volumes[si->PartNumber];
- }
-
- switch(propID)
- {
- case kpidPath:
- if (item.HasMetadata)
- prop = _db.GetItemPath(realIndex);
- else
- {
- char sz[16];
- ConvertUInt32ToString(item.StreamIndex, sz);
- 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;
- 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;
- case kpidMTime: if (item.HasMetadata) prop = item.MTime; break;
- case kpidPackSize: prop = si ? si->Resource.PackSize : (UInt64)0; break;
- case kpidSize: prop = si ? si->Resource.UnpackSize : (UInt64)0; break;
- case kpidMethod: if (si) prop = si->Resource.IsCompressed() ?
- (vol->Header.IsLzxMode() ? kMethodLZX : kMethodXpress) : kMethodCopy; break;
- #ifdef WIM_DETAILS
- case kpidVolume: if (si) prop = (UInt32)si->PartNumber; break;
- case kpidOffset: if (si) prop = (UInt64)si->Resource.Offset; break;
- case kpidLinks: prop = si ? (UInt32)si->RefCount : (UInt32)0; break;
- #endif
- }
- }
- else
- {
- index -= _db.SortedItems.Size();
- {
- switch(propID)
- {
- case kpidPath:
- {
- char sz[16];
- ConvertUInt32ToString(_xmls[index].VolIndex, sz);
- prop = (AString)"[" + (AString)sz + "].xml";
- break;
- }
- case kpidIsDir: prop = false; break;
- case kpidPackSize:
- case kpidSize: prop = (UInt64)_xmls[index].Data.GetCapacity(); break;
- case kpidMethod: prop = kMethodCopy; break;
- }
- }
- }
- prop.Detach(value);
- return S_OK;
- COM_TRY_END
-}
-
-class CVolumeName
-{
- // UInt32 _volIndex;
- UString _before;
- UString _after;
-public:
- CVolumeName() {};
-
- void InitName(const UString &name)
- {
- // _volIndex = 1;
- int dotPos = name.ReverseFind('.');
- if (dotPos < 0)
- dotPos = name.Length();
- _before = name.Left(dotPos);
- _after = name.Mid(dotPos);
- }
-
- UString GetNextName(UInt32 index)
- {
- wchar_t s[16];
- ConvertUInt32ToString(index, s);
- return _before + (UString)s + _after;
- }
-};
-
-STDMETHODIMP CHandler::Open(IInStream *inStream,
- const UInt64 * /* maxCheckStartPosition */,
- IArchiveOpenCallback *openArchiveCallback)
-{
- COM_TRY_BEGIN
- Close();
- {
- CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
-
- CVolumeName seqName;
- if (openArchiveCallback != NULL)
- openArchiveCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
-
- UInt32 numVolumes = 1;
- int firstVolumeIndex = -1;
- for (UInt32 i = 1; i <= numVolumes; i++)
- {
- CMyComPtr<IInStream> curStream;
- if (i != 1)
- {
- UString fullName = seqName.GetNextName(i);
- HRESULT result = openVolumeCallback->GetStream(fullName, &curStream);
- if (result == S_FALSE)
- continue;
- if (result != S_OK)
- return result;
- if (!curStream)
- break;
- }
- else
- curStream = inStream;
- CHeader header;
- HRESULT res = NWim::ReadHeader(curStream, header);
- if (res != S_OK)
- {
- if (i == 1)
- return res;
- if (res == S_FALSE)
- continue;
- return res;
- }
- _version = header.Version;
- _isOldVersion = header.IsOldVersion();
- if (firstVolumeIndex >= 0)
- if (!header.AreFromOnArchive(_volumes[firstVolumeIndex].Header))
- break;
- if (_volumes.Size() > header.PartNumber && _volumes[header.PartNumber].Stream)
- break;
- CXml xml;
- xml.VolIndex = header.PartNumber;
- res = _db.Open(curStream, header, xml.Data, openArchiveCallback);
- if (res != S_OK)
- {
- if (i == 1)
- return res;
- if (res == S_FALSE)
- continue;
- return res;
- }
-
- 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 (_xmls.Size() != 0)
- if (xml.Data == _xmls[0].Data)
- needAddXml = false;
- if (needAddXml)
- {
- xml.Parse();
- _xmls.Add(xml);
- }
-
- if (i == 1)
- {
- if (header.PartNumber != 1)
- break;
- if (!openVolumeCallback)
- break;
- numVolumes = header.NumParts;
- {
- NCOM::CPropVariant prop;
- RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
- if (prop.vt != VT_BSTR)
- break;
- seqName.InitName(prop.bstrVal);
- }
- }
- }
-
- _db.DetectPathMode();
- RINOK(_db.Sort(_db.SkipRoot));
-
- wchar_t sz[16];
- ConvertUInt32ToString(_db.Streams.Size(), sz);
- _nameLenForStreams = MyStringLen(sz);
-
- _xmlInComments = (_xmls.Size() == 1 && !_db.ShowImageNumber);
- }
- return S_OK;
- COM_TRY_END
-}
-
-STDMETHODIMP CHandler::Close()
-{
- _db.Clear();
- _volumes.Clear();
- _xmls.Clear();
- _nameLenForStreams = 0;
- return S_OK;
-}
-
-STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
- Int32 testMode, IArchiveExtractCallback *extractCallback)
-{
- COM_TRY_BEGIN
- bool allFilesMode = (numItems == (UInt32)-1);
-
- if (allFilesMode)
- numItems = _db.SortedItems.Size() + _xmls.Size();
- if (numItems == 0)
- return S_OK;
-
- UInt32 i;
- UInt64 totalSize = 0;
- for (i = 0; i < numItems; i++)
- {
- UInt32 index = allFilesMode ? i : indices[i];
- if (index < (UInt32)_db.SortedItems.Size())
- {
- int streamIndex = _db.Items[_db.SortedItems[index]].StreamIndex;
- if (streamIndex >= 0)
- {
- const CStreamInfo &si = _db.Streams[streamIndex];
- totalSize += si.Resource.UnpackSize;
- }
- }
- else
- totalSize += _xmls[index - (UInt32)_db.SortedItems.Size()].Data.GetCapacity();
- }
-
- RINOK(extractCallback->SetTotal(totalSize));
-
- UInt64 currentTotalPacked = 0;
- UInt64 currentTotalUnPacked = 0;
- UInt64 currentItemUnPacked, currentItemPacked;
-
- int prevSuccessStreamIndex = -1;
-
- CUnpacker unpacker;
-
- CLocalProgress *lps = new CLocalProgress;
- CMyComPtr<ICompressProgressInfo> progress = lps;
- lps->Init(extractCallback, false);
-
- for (i = 0; i < numItems; currentTotalUnPacked += currentItemUnPacked,
- currentTotalPacked += currentItemPacked)
- {
- currentItemUnPacked = 0;
- currentItemPacked = 0;
-
- lps->InSize = currentTotalPacked;
- lps->OutSize = currentTotalUnPacked;
-
- RINOK(lps->SetCur());
- UInt32 index = allFilesMode ? i : indices[i];
- i++;
- Int32 askMode = testMode ?
- NExtract::NAskMode::kTest :
- NExtract::NAskMode::kExtract;
-
- CMyComPtr<ISequentialOutStream> realOutStream;
- RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
- if (index >= (UInt32)_db.SortedItems.Size())
- {
- if (!testMode && !realOutStream)
- continue;
- RINOK(extractCallback->PrepareOperation(askMode));
- const CByteBuffer &data = _xmls[index - (UInt32)_db.SortedItems.Size()].Data;
- currentItemUnPacked = data.GetCapacity();
- if (realOutStream)
- {
- RINOK(WriteStream(realOutStream, (const Byte *)data, data.GetCapacity()));
- realOutStream.Release();
- }
- RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
- continue;
- }
-
- const CItem &item = _db.Items[_db.SortedItems[index]];
- int streamIndex = item.StreamIndex;
- if (streamIndex < 0)
- {
- if (!testMode && !realOutStream)
- continue;
- RINOK(extractCallback->PrepareOperation(askMode));
- realOutStream.Release();
- RINOK(extractCallback->SetOperationResult(item.HasStream() ?
- NExtract::NOperationResult::kDataError :
- NExtract::NOperationResult::kOK));
- continue;
- }
-
- const CStreamInfo &si = _db.Streams[streamIndex];
- currentItemUnPacked = si.Resource.UnpackSize;
- currentItemPacked = si.Resource.PackSize;
-
- if (!testMode && !realOutStream)
- continue;
- RINOK(extractCallback->PrepareOperation(askMode));
- Int32 opRes = NExtract::NOperationResult::kOK;
- if (streamIndex != prevSuccessStreamIndex || realOutStream)
- {
- Byte digest[20];
- const CVolume &vol = _volumes[si.PartNumber];
- HRESULT res = unpacker.Unpack(vol.Stream, si.Resource, vol.Header.IsLzxMode(),
- realOutStream, progress, digest);
- if (res == S_OK)
- {
- if (memcmp(digest, si.Hash, kHashSize) == 0)
- prevSuccessStreamIndex = streamIndex;
- else
- opRes = NExtract::NOperationResult::kCRCError;
- }
- else if (res == S_FALSE)
- opRes = NExtract::NOperationResult::kDataError;
- else
- return res;
- }
- realOutStream.Release();
- RINOK(extractCallback->SetOperationResult(opRes));
- }
- return S_OK;
- COM_TRY_END
-}
-
-STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
-{
- *numItems = _db.SortedItems.Size();
- if (!_xmlInComments)
- *numItems += _xmls.Size();
- return S_OK;
-}
-
-}}