diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2009-06-02 04:00:00 +0400 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:15:59 +0300 |
commit | 829409452d85cd6dd9dfc9151f109d6e13a2bb1c (patch) | |
tree | e0acaea47044d167f35fa197584dee1bde41c329 /CPP/7zip/UI/Common | |
parent | 8874e4fbc9faabdcff719b9b2ac8ebad4f282bbe (diff) |
9.04 beta
Diffstat (limited to 'CPP/7zip/UI/Common')
24 files changed, 867 insertions, 805 deletions
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp index 46e8a2a1..96d47c08 100755 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp @@ -11,18 +11,18 @@ #include "Common/StringConvert.h" #include "Common/StringToInt.h" -#include "Windows/FileName.h" #include "Windows/FileDir.h" +#include "Windows/FileName.h" #ifdef _WIN32 #include "Windows/FileMapping.h" #include "Windows/Synchronization.h" #endif #include "ArchiveCommandLine.h" -#include "UpdateAction.h" -#include "Update.h" -#include "SortUtils.h" #include "EnumDirItems.h" +#include "SortUtils.h" +#include "Update.h" +#include "UpdateAction.h" extern bool g_CaseSensitive; @@ -38,6 +38,8 @@ using namespace NCommandLineParser; using namespace NWindows; using namespace NFile; +int g_CodePage = -1; + namespace NKey { enum Enum { @@ -69,10 +71,12 @@ enum Enum kEmail, kShowDialog, kLargePages, - kCharSet, + kListfileCharSet, + kConsoleCharSet, kTechMode, kShareForWrite, - kCaseSensitive + kCaseSensitive, + kCalcCrc, }; } @@ -137,9 +141,11 @@ static const CSwitchForm kSwitchForms[] = { L"AD", NSwitchType::kSimple, false }, { L"SLP", NSwitchType::kUnLimitedPostString, false, 0}, { L"SCS", NSwitchType::kUnLimitedPostString, false, 0}, + { L"SCC", NSwitchType::kUnLimitedPostString, false, 0}, { L"SLT", NSwitchType::kSimple, false }, { L"SSW", NSwitchType::kSimple, false }, - { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" } + { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" }, + { L"SCRC", NSwitchType::kSimple, false } }; static const CCommandForm g_CommandForms[] = @@ -412,9 +418,9 @@ static void ConvertToLongName(const UString &prefix, UString &name) { if (name.IsEmpty() || DoesNameContainWildCard(name)) return; - NFind::CFileInfoW fileInfo; - if (NFind::FindFile(prefix + name, fileInfo)) - name = fileInfo.Name; + NFind::CFileInfoW fi; + if (fi.Find(prefix + name)) + name = fi.Name; } static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::CItem> &items) @@ -698,6 +704,7 @@ void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings, options.IsInTerminal = MY_IS_TERMINAL(stdin); options.IsStdOutTerminal = MY_IS_TERMINAL(stdout); options.IsStdErrTerminal = MY_IS_TERMINAL(stderr); + options.StdInMode = parser[NKey::kStdIn].ThereIs; options.StdOutMode = parser[NKey::kStdOut].ThereIs; options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs; options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs || parser[NKey::kHelp3].ThereIs; @@ -722,11 +729,28 @@ struct CCodePagePair static CCodePagePair g_CodePagePairs[] = { { L"UTF-8", CP_UTF8 }, - { L"WIN", CP_ACP }, - { L"DOS", CP_OEMCP } + { L"WIN", CP_ACP }, + { L"DOS", CP_OEMCP } }; -static const int kNumCodePages = sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]); +static int FindCharset(const NCommandLineParser::CParser &parser, int keyIndex, int defaultVal) +{ + if (!parser[keyIndex].ThereIs) + return defaultVal; + + UString name = parser[keyIndex].PostStrings.Back(); + name.MakeUpper(); + int i; + for (i = 0; i < sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]); i++) + { + const CCodePagePair &pair = g_CodePagePairs[i]; + if (name.Compare(pair.Name) == 0) + return pair.CodePage; + } + if (i == sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0])) + ThrowUserErrorException(); + return -1; +} static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v) { @@ -751,6 +775,7 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) ThrowUserErrorException(); options.TechMode = parser[NKey::kTechMode].ThereIs; + options.CalcCrc = parser[NKey::kCalcCrc].ThereIs; if (parser[NKey::kCaseSensitive].ThereIs) g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0); @@ -761,24 +786,8 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) else recursedType = NRecursedType::kNonRecursed; - UINT codePage = CP_UTF8; - if (parser[NKey::kCharSet].ThereIs) - { - UString name = parser[NKey::kCharSet].PostStrings.Front(); - name.MakeUpper(); - int i; - for (i = 0; i < kNumCodePages; i++) - { - const CCodePagePair &pair = g_CodePagePairs[i]; - if (name.Compare(pair.Name) == 0) - { - codePage = pair.CodePage; - break; - } - } - if (i >= kNumCodePages) - ThrowUserErrorException(); - } + g_CodePage = FindCharset(parser, NKey::kConsoleCharSet, -1); + UINT codePage = FindCharset(parser, NKey::kListfileCharSet, CP_UTF8); bool thereAreSwitchIncludes = false; if (parser[NKey::kInclude].ThereIs) @@ -795,6 +804,13 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && options.Command.CommandType != NCommandType::kBenchmark && options.Command.CommandType != NCommandType::kInfo; + + bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); + bool isExtractOrList = isExtractGroupCommand || options.Command.CommandType == NCommandType::kList; + + if (isExtractOrList && options.StdInMode) + thereIsArchiveName = false; + if (thereIsArchiveName) { if (curCommandIndex >= numNonSwitchStrings) @@ -808,7 +824,6 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) options.YesToAll = parser[NKey::kYes].ThereIs; - bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); #ifndef _NO_CRYPTO options.PasswordEnabled = parser[NKey::kPassword].ThereIs; @@ -816,16 +831,13 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) options.Password = parser[NKey::kPassword].PostStrings[0]; #endif - options.StdInMode = parser[NKey::kStdIn].ThereIs; options.ShowDialog = parser[NKey::kShowDialog].ThereIs; if (parser[NKey::kArchiveType].ThereIs) options.ArcType = parser[NKey::kArchiveType].PostStrings[0]; - if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kList) + if (isExtractOrList) { - if (options.StdInMode) - ThrowException("Reading archives from stdin is not implemented"); if (!options.WildcardCensor.AllAreRelative()) ThrowException("Cannot use absolute pathnames for this command"); @@ -849,6 +861,15 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) archiveWildcardCensor.ExtendExclude(); + if (options.StdInMode) + { + UString arcName = parser[NKey::kStdIn].PostStrings.Front(); + options.ArchivePathsSorted.Add(arcName); + options.ArchivePathsFullSorted.Add(arcName); + } + else + { + UStringVector archivePaths; { @@ -889,6 +910,8 @@ void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options) options.ArchivePathsSorted.Add(archivePaths[indices[i]]); options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]); } + + } if (isExtractGroupCommand) { diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.h b/CPP/7zip/UI/Common/ArchiveCommandLine.h index 9c37f336..6f79b7ee 100755 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.h +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.h @@ -73,6 +73,7 @@ struct CArchiveCommandLineOptions bool TechMode; // Extract + bool CalcCrc; bool AppendName; UString OutputDir; NExtract::NOverwriteMode::EEnum OverwriteMode; diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp index 5af5286b..4c0cc90b 100755 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp @@ -2,24 +2,19 @@ #include "StdAfx.h" -#include "ArchiveExtractCallback.h" - -#include "Common/Wildcard.h" -#include "Common/StringConvert.h" #include "Common/ComTry.h" +#include "Common/Wildcard.h" #include "Windows/FileDir.h" #include "Windows/FileFind.h" -#include "Windows/Time.h" -#include "Windows/Defs.h" #include "Windows/PropVariant.h" - #include "Windows/PropVariantConversions.h" #include "../../Common/FilePathAutoRename.h" #include "../Common/ExtractingFilePath.h" -#include "OpenArchive.h" + +#include "ArchiveExtractCallback.h" using namespace NWindows; @@ -27,20 +22,20 @@ static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto n static const wchar_t *kCantRenameFile = L"ERROR: Can not rename existing file "; static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file "; - void CArchiveExtractCallback::Init( - IInArchive *archiveHandler, + const NWildcard::CCensorNode *wildcardCensor, + const CArc *arc, IFolderArchiveExtractCallback *extractCallback2, - bool stdOutMode, + bool stdOutMode, bool testMode, bool crcMode, const UString &directoryPath, const UStringVector &removePathParts, - const UString &itemDefaultName, - const FILETIME &utcMTimeDefault, - UInt32 attributesDefault, UInt64 packSize) { + _wildcardCensor = wildcardCensor; + _stdOutMode = stdOutMode; - _numErrors = 0; + _testMode = testMode; + _crcMode = crcMode; _unpTotal = 1; _packTotal = packSize; @@ -51,11 +46,9 @@ void CArchiveExtractCallback::Init( LocalProgressSpec->Init(extractCallback2, true); LocalProgressSpec->SendProgress = false; - _itemDefaultName = itemDefaultName; - _utcMTimeDefault = utcMTimeDefault; - _attributesDefault = attributesDefault; + _removePathParts = removePathParts; - _archiveHandler = archiveHandler; + _arc = arc; _directoryPath = directoryPath; NFile::NName::NormalizeDirPathPrefix(_directoryPath); } @@ -117,7 +110,7 @@ STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const U void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath) { fullPath = _directoryPath; - for(int i = 0; i < dirPathParts.Size(); i++) + for (int i = 0; i < dirPathParts.Size(); i++) { if (i > 0) fullPath += wchar_t(NFile::NName::kDirDelimiter); @@ -126,24 +119,11 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat } } -static UString MakePathNameFromParts(const UStringVector &parts) -{ - UString result; - for(int i = 0; i < parts.Size(); i++) - { - if(i != 0) - result += wchar_t(NFile::NName::kDirDelimiter); - result += parts[i]; - } - return result; -} - - HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined) { filetimeIsDefined = false; NCOM::CPropVariant prop; - RINOK(_archiveHandler->GetProperty(index, propID, &prop)); + RINOK(_arc->Archive->GetProperty(index, propID, &prop)); if (prop.vt == VT_FILETIME) { filetime = prop.filetime; @@ -154,26 +134,40 @@ HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &fil return S_OK; } +HRESULT CArchiveExtractCallback::GetUnpackSize() +{ + NCOM::CPropVariant prop; + RINOK(_arc->Archive->GetProperty(_index, kpidSize, &prop)); + _curSizeDefined = (prop.vt != VT_EMPTY); + if (_curSizeDefined) + _curSize = ConvertPropVariantToUInt64(prop); + return S_OK; +} + STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { COM_TRY_BEGIN + _crcStream.Release(); *outStream = 0; _outFileStream.Release(); _encrypted = false; _isSplit = false; _curSize = 0; + _curSizeDefined = false; + _index = index; UString fullPath; - RINOK(GetArchiveItemPath(_archiveHandler, index, _itemDefaultName, fullPath)); - RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDir)); + IInArchive *archive = _arc->Archive; + RINOK(_arc->GetItemPath(index, fullPath)); + RINOK(IsArchiveItemFolder(archive, index, _fi.IsDir)); _filePath = fullPath; { NCOM::CPropVariant prop; - RINOK(_archiveHandler->GetProperty(index, kpidPosition, &prop)); + RINOK(archive->GetProperty(index, kpidPosition, &prop)); if (prop.vt != VT_EMPTY) { if (prop.vt != VT_UI8) @@ -183,22 +177,17 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre } } - RINOK(IsArchiveItemProp(_archiveHandler, index, kpidEncrypted, _encrypted)); + RINOK(GetArchiveItemBoolProp(archive, index, kpidEncrypted, _encrypted)); + + RINOK(GetUnpackSize()); - bool newFileSizeDefined; - UInt64 newFileSize; + if (_wildcardCensor) { - NCOM::CPropVariant prop; - RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); - newFileSizeDefined = (prop.vt != VT_EMPTY); - if (newFileSizeDefined) - { - newFileSize = ConvertPropVariantToUInt64(prop); - _curSize = newFileSize; - } + if (!_wildcardCensor->CheckPath(fullPath, !_fi.IsDir)) + return S_OK; } - if(askExtractMode == NArchive::NExtract::NAskMode::kExtract) + if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) { if (_stdOutMode) { @@ -209,32 +198,29 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre { NCOM::CPropVariant prop; - RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)); - if (prop.vt == VT_EMPTY) + RINOK(archive->GetProperty(index, kpidAttrib, &prop)); + if (prop.vt == VT_UI4) { - _processedFileInfo.Attributes = _attributesDefault; - _processedFileInfo.AttributesAreDefined = false; + _fi.Attrib = prop.ulVal; + _fi.AttribDefined = true; } + else if (prop.vt == VT_EMPTY) + _fi.AttribDefined = false; else - { - if (prop.vt != VT_UI4) - return E_FAIL; - _processedFileInfo.Attributes = prop.ulVal; - _processedFileInfo.AttributesAreDefined = true; - } + return E_FAIL; } - RINOK(GetTime(index, kpidCTime, _processedFileInfo.CTime, _processedFileInfo.CTimeDefined)); - RINOK(GetTime(index, kpidATime, _processedFileInfo.ATime, _processedFileInfo.ATimeDefined)); - RINOK(GetTime(index, kpidMTime, _processedFileInfo.MTime, _processedFileInfo.MTimeDefined)); + RINOK(GetTime(index, kpidCTime, _fi.CTime, _fi.CTimeDefined)); + RINOK(GetTime(index, kpidATime, _fi.ATime, _fi.ATimeDefined)); + RINOK(GetTime(index, kpidMTime, _fi.MTime, _fi.MTimeDefined)); bool isAnti = false; - RINOK(IsArchiveItemProp(_archiveHandler, index, kpidIsAnti, isAnti)); + RINOK(_arc->IsItemAnti(index, isAnti)); UStringVector pathParts; SplitPathToParts(fullPath, pathParts); - if(pathParts.IsEmpty()) + if (pathParts.IsEmpty()) return E_FAIL; int numRemovePathParts = 0; switch(_pathMode) @@ -262,7 +248,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre UString processedPath = MakePathNameFromParts(pathParts); if (!isAnti) { - if (!_processedFileInfo.IsDir) + if (!_fi.IsDir) { if (!pathParts.IsEmpty()) pathParts.DeleteBack(); @@ -272,18 +258,18 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre { UString fullPathNew; CreateComplexDirectory(pathParts, fullPathNew); - if (_processedFileInfo.IsDir) + if (_fi.IsDir) NFile::NDirectory::SetDirTime(fullPathNew, - (WriteCTime && _processedFileInfo.CTimeDefined) ? &_processedFileInfo.CTime : NULL, - (WriteATime && _processedFileInfo.ATimeDefined) ? &_processedFileInfo.ATime : NULL, - (WriteMTime && _processedFileInfo.MTimeDefined) ? &_processedFileInfo.MTime : &_utcMTimeDefault); + (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL, + (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL, + (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL)); } } UString fullProcessedPath = _directoryPath + processedPath; - if(_processedFileInfo.IsDir) + if (_fi.IsDir) { _diskFilePath = fullProcessedPath; if (isAnti) @@ -294,7 +280,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre if (!_isSplit) { NFile::NFind::CFileInfoW fileInfo; - if(NFile::NFind::FindFile(fullProcessedPath, fileInfo)) + if (fileInfo.Find(fullProcessedPath)) { switch(_overwriteMode) { @@ -305,8 +291,8 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre Int32 overwiteResult; RINOK(_extractCallback2->AskOverwrite( fullProcessedPath, &fileInfo.MTime, &fileInfo.Size, fullPath, - _processedFileInfo.MTimeDefined ? &_processedFileInfo.MTime : NULL, - newFileSizeDefined ? &newFileSize : NULL, + _fi.MTimeDefined ? &_fi.MTime : NULL, + _curSizeDefined ? &_curSize : NULL, &overwiteResult)) switch(overwiteResult) @@ -349,7 +335,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre RINOK(_extractCallback2->MessageError(message)); return E_FAIL; } - if(!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath)) + if (!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath)) { UString message = UString(kCantRenameFile) + fullProcessedPath; RINOK(_extractCallback2->MessageError(message)); @@ -392,6 +378,17 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre { *outStream = NULL; } + if (_crcMode) + { + _crcStreamSpec = new COutStreamWithCRC; + _crcStream = _crcStreamSpec; + CMyComPtr<ISequentialOutStream> crcStream = _crcStreamSpec; + _crcStreamSpec->SetStream(*outStream); + if (*outStream) + (*outStream)->Release(); + *outStream = crcStream.Detach(); + _crcStreamSpec->Init(true); + } return S_OK; COM_TRY_END } @@ -403,9 +400,13 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode) switch (askExtractMode) { case NArchive::NExtract::NAskMode::kExtract: - _extractMode = true; + if (_testMode) + askExtractMode = NArchive::NExtract::NAskMode::kTest; + else + _extractMode = true; + break; }; - return _extractCallback2->PrepareOperation(_filePath, _processedFileInfo.IsDir, + return _extractCallback2->PrepareOperation(_filePath, _fi.IsDir, askExtractMode, _isSplit ? &_position: 0); COM_TRY_END } @@ -424,24 +425,35 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult) _outFileStream.Release(); return E_FAIL; } - if (_outFileStream != NULL) + if (_crcStream) + { + CrcSum += _crcStreamSpec->GetCRC(); + _curSize = _crcStreamSpec->GetSize(); + _curSizeDefined = true; + _crcStream.Release(); + } + if (_outFileStream) { _outFileStreamSpec->SetTime( - (WriteCTime && _processedFileInfo.CTimeDefined) ? &_processedFileInfo.CTime : NULL, - (WriteATime && _processedFileInfo.ATimeDefined) ? &_processedFileInfo.ATime : NULL, - (WriteMTime && _processedFileInfo.MTimeDefined) ? &_processedFileInfo.MTime : &_utcMTimeDefault); + (WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL, + (WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL, + (WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL)); _curSize = _outFileStreamSpec->ProcessedSize; + _curSizeDefined = true; RINOK(_outFileStreamSpec->Close()); _outFileStream.Release(); } - UnpackSize += _curSize; - if (_processedFileInfo.IsDir) + if (!_curSizeDefined) + GetUnpackSize(); + if (_curSizeDefined) + UnpackSize += _curSize; + if (_fi.IsDir) NumFolders++; else NumFiles++; - if (_extractMode && _processedFileInfo.AttributesAreDefined) - NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes); + if (_extractMode && _fi.AttribDefined) + NFile::NDirectory::MySetFileAttributes(_diskFilePath, _fi.Attrib); RINOK(_extractCallback2->SetOperationResult(operationResult, _encrypted)); return S_OK; COM_TRY_END diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h index e895c54b..367e4b07 100755 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h @@ -1,19 +1,23 @@ // ArchiveExtractCallback.h -#ifndef __ARCHIVEEXTRACTCALLBACK_H -#define __ARCHIVEEXTRACTCALLBACK_H +#ifndef __ARCHIVE_EXTRACT_CALLBACK_H +#define __ARCHIVE_EXTRACT_CALLBACK_H -#include "../../Archive/IArchive.h" -#include "IFileExtractCallback.h" - -#include "Common/MyString.h" #include "Common/MyCom.h" +#include "Common/Wildcard.h" + +#include "../../IPassword.h" #include "../../Common/FileStreams.h" #include "../../Common/ProgressUtils.h" -#include "../../IPassword.h" + +#include "../../Archive/IArchive.h" + +#include "../../Archive/Common/OutStreamWithCRC.h" #include "ExtractMode.h" +#include "IFileExtractCallback.h" +#include "OpenArchive.h" class CArchiveExtractCallback: public IArchiveExtractCallback, @@ -22,22 +26,8 @@ class CArchiveExtractCallback: public ICompressProgressInfo, public CMyUnknownImp { -public: - MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo) - // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback) - - INTERFACE_IArchiveExtractCallback(;) - - STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); - - // IArchiveVolumeExtractCallback - // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream); - - // ICryptoGetTextPassword - STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword); - -private: - CMyComPtr<IInArchive> _archiveHandler; + const CArc *_arc; + const NWildcard::CCensorNode *_wildcardCensor; CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2; CMyComPtr<ICompressProgressInfo> _compressProgress; CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword; @@ -45,12 +35,11 @@ private: NExtract::NPathMode::EEnum _pathMode; NExtract::NOverwriteMode::EEnum _overwriteMode; + UString _diskFilePath; UString _filePath; UInt64 _position; bool _isSplit; - UString _diskFilePath; - bool _extractMode; bool WriteCTime; @@ -64,29 +53,61 @@ private: FILETIME CTime; FILETIME ATime; FILETIME MTime; - UInt32 Attributes; + UInt32 Attrib; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; + bool AttribDefined; bool IsDir; - bool AttributesAreDefined; - } _processedFileInfo; + } _fi; + UInt32 _index; UInt64 _curSize; + bool _curSizeDefined; COutFileStream *_outFileStreamSpec; CMyComPtr<ISequentialOutStream> _outFileStream; + + COutStreamWithCRC *_crcStreamSpec; + CMyComPtr<ISequentialOutStream> _crcStream; + UStringVector _removePathParts; - UString _itemDefaultName; - FILETIME _utcMTimeDefault; - UInt32 _attributesDefault; bool _stdOutMode; + bool _testMode; + bool _crcMode; + bool _multiArchives; + + CMyComPtr<ICompressProgressInfo> _localProgress; + UInt64 _packTotal; + UInt64 _unpTotal; void CreateComplexDirectory(const UStringVector &dirPathParts, UString &fullPath); HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined); + HRESULT GetUnpackSize(); + public: + + CLocalProgress *LocalProgressSpec; + + UInt64 NumFolders; + UInt64 NumFiles; + UInt64 UnpackSize; + UInt32 CrcSum; + + MY_UNKNOWN_IMP2(ICryptoGetTextPassword, ICompressProgressInfo) + // COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback) + + INTERFACE_IArchiveExtractCallback(;) + + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + + // IArchiveVolumeExtractCallback + // STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream); + + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + CArchiveExtractCallback(): WriteCTime(true), WriteATime(true), @@ -97,37 +118,26 @@ public: _localProgress = LocalProgressSpec; } - CLocalProgress *LocalProgressSpec; - CMyComPtr<ICompressProgressInfo> _localProgress; - UInt64 _packTotal; - UInt64 _unpTotal; - - bool _multiArchives; - UInt64 NumFolders; - UInt64 NumFiles; - UInt64 UnpackSize; - void InitForMulti(bool multiArchives, NExtract::NPathMode::EEnum pathMode, NExtract::NOverwriteMode::EEnum overwriteMode) { - _multiArchives = multiArchives; NumFolders = NumFiles = UnpackSize = 0; + _multiArchives = multiArchives; _pathMode = pathMode; _overwriteMode = overwriteMode; + NumFolders = NumFiles = UnpackSize = 0; + CrcSum = 0; } void Init( - IInArchive *archiveHandler, + const NWildcard::CCensorNode *wildcardCensor, + const CArc *arc, IFolderArchiveExtractCallback *extractCallback2, - bool stdOutMode, + bool stdOutMode, bool testMode, bool crcMode, const UString &directoryPath, const UStringVector &removePathParts, - const UString &itemDefaultName, - const FILETIME &utcMTimeDefault, - UInt32 attributesDefault, UInt64 packSize); - UInt64 _numErrors; }; #endif diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp index 9b9a4fe6..c3684def 100755 --- a/CPP/7zip/UI/Common/ArchiveName.cpp +++ b/CPP/7zip/UI/Common/ArchiveName.cpp @@ -2,12 +2,14 @@ #include "StdAfx.h" -#include "Windows/FileFind.h" #include "Windows/FileDir.h" +#include "Windows/FileFind.h" + +#include "ExtractingFilePath.h" using namespace NWindows; -UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) +static UString CreateArchiveName2(const UString &srcName, bool fromPrev, bool keepName) { UString resultName = L"Archive"; if (fromPrev) @@ -20,7 +22,7 @@ UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) { dirPrefix.Delete(dirPrefix.Length() - 1); NFile::NFind::CFileInfoW fileInfo; - if (NFile::NFind::FindFile(dirPrefix, fileInfo)) + if (fileInfo.Find(dirPrefix)) resultName = fileInfo.Name; } } @@ -28,8 +30,9 @@ UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) else { NFile::NFind::CFileInfoW fileInfo; - if (!NFile::NFind::FindFile(srcName, fileInfo)) - return resultName; + if (!fileInfo.Find(srcName)) + // return resultName; + return srcName; resultName = fileInfo.Name; if (!fileInfo.IsDir() && !keepName) { @@ -44,3 +47,8 @@ UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) } return resultName; } + +UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) +{ + return GetCorrectFsPath(CreateArchiveName2(srcName, fromPrev, keepName)); +} diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp index 8f289d1b..7188bcb6 100755 --- a/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp @@ -2,14 +2,15 @@ #include "StdAfx.h" -#include "ArchiveOpenCallback.h" - #include "Common/StringConvert.h" #include "Common/ComTry.h" + #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" +#include "ArchiveOpenCallback.h" + using namespace NWindows; STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes) @@ -91,7 +92,7 @@ STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStre } *inStream = NULL; UString fullPath = _folderPrefix + name; - if (!NFile::NFind::FindFile(fullPath, _fileInfo)) + if (!_fileInfo.Find(fullPath)) return S_FALSE; if (_fileInfo.IsDir()) return S_FALSE; diff --git a/CPP/7zip/UI/Common/ArchiveOpenCallback.h b/CPP/7zip/UI/Common/ArchiveOpenCallback.h index ca445974..c6651e8f 100755 --- a/CPP/7zip/UI/Common/ArchiveOpenCallback.h +++ b/CPP/7zip/UI/Common/ArchiveOpenCallback.h @@ -3,8 +3,9 @@ #ifndef __ARCHIVE_OPEN_CALLBACK_H #define __ARCHIVE_OPEN_CALLBACK_H -#include "Common/MyString.h" #include "Common/MyCom.h" +#include "Common/MyString.h" + #include "Windows/FileFind.h" #ifndef _NO_CRYPTO @@ -71,6 +72,7 @@ public: { _subArchiveMode = true; _subArchiveName = name; + TotalSize = 0; return S_OK; } @@ -86,10 +88,10 @@ public: UInt64 TotalSize; COpenCallbackImp(): Callback(NULL) {} - void Init(const UString &folderPrefix, const UString &fileName) + void Init(const UString &folderPrefix, const UString &fileName) { _folderPrefix = folderPrefix; - if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo)) + if (!_fileInfo.Find(_folderPrefix + fileName)) throw 1; FileNames.Clear(); _subArchiveMode = false; diff --git a/CPP/7zip/UI/Common/CompressCall.cpp b/CPP/7zip/UI/Common/CompressCall.cpp index 3564c950..47f89ed6 100755 --- a/CPP/7zip/UI/Common/CompressCall.cpp +++ b/CPP/7zip/UI/Common/CompressCall.cpp @@ -2,20 +2,20 @@ #include "StdAfx.h" -#include "CompressCall.h" - -#include "Common/Random.h" #include "Common/IntToString.h" #include "Common/MyCom.h" +#include "Common/Random.h" #include "Common/StringConvert.h" -#include "Windows/Synchronization.h" -#include "Windows/FileMapping.h" #include "Windows/FileDir.h" +#include "Windows/FileMapping.h" +#include "Windows/Synchronization.h" #include "../FileManager/ProgramLocation.h" #include "../FileManager/RegistryUtils.h" +#include "CompressCall.h" + #ifndef _UNICODE extern bool g_IsNT; #endif _UNICODE @@ -122,8 +122,8 @@ static HRESULT CreateTempEvent(const wchar_t *name, for (;;) { int number = random.Generate(); - wchar_t temp[32]; - ConvertUInt64ToString((UInt32)number, temp); + wchar_t temp[16]; + ConvertUInt32ToString((UInt32)number, temp); eventName = name; eventName += temp; RINOK(event.CreateWithName(false, GetSystemString(eventName))); @@ -151,8 +151,8 @@ static HRESULT CreateMap(const UStringVector &names, for (;;) { int number = random.Generate(); - wchar_t temp[32]; - ConvertUInt64ToString(UInt32(number), temp); + wchar_t temp[16]; + ConvertUInt32ToString(UInt32(number), temp); mappingName = id; mappingName += L"Mapping"; mappingName += temp; @@ -169,8 +169,8 @@ static HRESULT CreateMap(const UStringVector &names, params += mappingName; params += L":"; - wchar_t string[10]; - ConvertUInt64ToString(totalSize, string); + wchar_t string[16]; + ConvertUInt32ToString(totalSize, string); params += string; params += L":"; @@ -231,8 +231,8 @@ HRESULT CompressFiles( for (;;) { int number = random.Generate(); - wchar_t temp[32]; - ConvertUInt64ToString(UInt32(number), temp); + wchar_t temp[16]; + ConvertUInt32ToString(UInt32(number), temp); mappingName = L"7zCompressMapping"; mappingName += temp; if (!fileMapping.Create(INVALID_HANDLE_VALUE, NULL, @@ -252,8 +252,8 @@ HRESULT CompressFiles( params += mappingName; params += L":"; - wchar_t string[10]; - ConvertUInt64ToString(totalSize, string); + wchar_t string[16]; + ConvertUInt32ToString(totalSize, string); params += string; params += L":"; diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h index 0f289483..29cc60d9 100755 --- a/CPP/7zip/UI/Common/DirItem.h +++ b/CPP/7zip/UI/Common/DirItem.h @@ -58,11 +58,12 @@ struct CArcItem UString Name; bool IsDir; bool SizeDefined; + bool MTimeDefined; bool Censored; UInt32 IndexInServer; int TimeType; - CArcItem(): IsDir(false), SizeDefined(false), Censored(false), TimeType(-1) {} + CArcItem(): IsDir(false), SizeDefined(false), MTimeDefined(false), Censored(false), TimeType(-1) {} }; #endif diff --git a/CPP/7zip/UI/Common/EnumDirItems.cpp b/CPP/7zip/UI/Common/EnumDirItems.cpp index b83edf2a..ba03ea35 100755 --- a/CPP/7zip/UI/Common/EnumDirItems.cpp +++ b/CPP/7zip/UI/Common/EnumDirItems.cpp @@ -2,12 +2,6 @@ #include "StdAfx.h" -#include <stdio.h> - -#include "Common/StringConvert.h" -#include "Common/Wildcard.h" -#include "Common/MyCom.h" - #include "EnumDirItems.h" using namespace NWindows; @@ -122,7 +116,7 @@ void CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logP const UString &filePath = filePaths[i]; NFind::CFileInfoW fi; const UString phyPath = phyPrefix + filePath; - if (!NFind::FindFile(phyPath, fi)) + if (!fi.Find(phyPath)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPath); @@ -218,7 +212,7 @@ static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, const UString &name = item.PathParts.Front(); const UString fullPath = phyPrefix + name; NFind::CFileInfoW fi; - if (!NFind::FindFile(fullPath, fi)) + if (!fi.Find(fullPath)) { errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); @@ -268,7 +262,7 @@ static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; const UString fullPath = phyPrefix + nextNode.Name; NFind::CFileInfoW fi; - if (!NFind::FindFile(fullPath, fi)) + if (!fi.Find(fullPath)) { if (!nextNode.AreThereIncludeItems()) continue; diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp index 3ac497f4..93329091 100755 --- a/CPP/7zip/UI/Common/Extract.cpp +++ b/CPP/7zip/UI/Common/Extract.cpp @@ -2,55 +2,65 @@ #include "StdAfx.h" -#include "Extract.h" +#include <stdio.h> -#include "Windows/Defs.h" #include "Windows/FileDir.h" +#include "Windows/PropVariant.h" +#include "Windows/PropVariantConversions.h" + +#include "../Common/ExtractingFilePath.h" -#include "OpenArchive.h" +#include "Extract.h" #include "SetProperties.h" using namespace NWindows; static HRESULT DecompressArchive( - IInArchive *archive, + const CArc &arc, UInt64 packSize, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IExtractCallbackUI *callback, CArchiveExtractCallback *extractCallbackSpec, - UString &errorMessage) + UString &errorMessage, + UInt64 &stdInProcessed) { + stdInProcessed = 0; + IInArchive *archive = arc.Archive; CRecordVector<UInt32> realIndices; - UInt32 numItems; - RINOK(archive->GetNumberOfItems(&numItems)); - - for(UInt32 i = 0; i < numItems; i++) - { - UString filePath; - RINOK(GetArchiveItemPath(archive, i, options.DefaultItemName, filePath)); - bool isFolder; - RINOK(IsArchiveItemFolder(archive, i, isFolder)); - if (!wildcardCensor.CheckPath(filePath, !isFolder)) - continue; - realIndices.Add(i); - } - if (realIndices.Size() == 0) + if (!options.StdInMode) { - callback->ThereAreNoFiles(); - return S_OK; + UInt32 numItems; + RINOK(archive->GetNumberOfItems(&numItems)); + + for (UInt32 i = 0; i < numItems; i++) + { + UString filePath; + RINOK(arc.GetItemPath(i, filePath)); + bool isFolder; + RINOK(IsArchiveItemFolder(archive, i, isFolder)); + if (!wildcardCensor.CheckPath(filePath, !isFolder)) + continue; + realIndices.Add(i); + } + if (realIndices.Size() == 0) + { + callback->ThereAreNoFiles(); + return S_OK; + } } UStringVector removePathParts; UString outDir = options.OutputDir; - outDir.Replace(L"*", options.DefaultItemName); + outDir.Replace(L"*", GetCorrectFsPath(arc.DefaultName)); #ifdef _WIN32 outDir.TrimRight(); + outDir = GetCorrectFullFsPath(outDir); #endif - if(!outDir.IsEmpty()) - if(!NFile::NDirectory::CreateComplexDirectory(outDir)) + if (!outDir.IsEmpty()) + if (!NFile::NDirectory::CreateComplexDirectory(outDir)) { HRESULT res = ::GetLastError(); if (res == S_OK) @@ -60,91 +70,108 @@ static HRESULT DecompressArchive( } extractCallbackSpec->Init( - archive, + options.StdInMode ? &wildcardCensor : NULL, + &arc, callback, - options.StdOutMode, + options.StdOutMode, options.TestMode, options.CalcCrc, outDir, removePathParts, - options.DefaultItemName, - options.ArchiveFileInfo.MTime, - options.ArchiveFileInfo.Attrib, packSize); #ifdef COMPRESS_MT RINOK(SetProperties(archive, options.Properties)); #endif - HRESULT result = archive->Extract(&realIndices.Front(), - realIndices.Size(), options.TestMode? 1: 0, extractCallbackSpec); + HRESULT result; + Int32 testMode = (options.TestMode && !options.CalcCrc) ? 1: 0; + if (options.StdInMode) + { + result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, extractCallbackSpec); + NCOM::CPropVariant prop; + if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK) + if (prop.vt == VT_UI8 || prop.vt == VT_UI4) + stdInProcessed = ConvertPropVariantToUInt64(prop); + } + else + result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, extractCallbackSpec); return callback->ExtractResult(result); } HRESULT DecompressArchives( CCodecs *codecs, const CIntVector &formatIndices, - UStringVector &archivePaths, UStringVector &archivePathsFull, + UStringVector &arcPaths, UStringVector &arcPathsFull, const NWildcard::CCensorNode &wildcardCensor, - const CExtractOptions &optionsSpec, + const CExtractOptions &options, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat) { stat.Clear(); - CExtractOptions options = optionsSpec; int i; UInt64 totalPackSize = 0; CRecordVector<UInt64> archiveSizes; - for (i = 0; i < archivePaths.Size(); i++) + + int numArcs = options.StdInMode ? 1 : arcPaths.Size(); + + for (i = 0; i < numArcs; i++) { - const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW fi; - if (!NFile::NFind::FindFile(archivePath, fi)) - throw "there is no such archive"; - if (fi.IsDir()) - throw "can't decompress folder"; + fi.Size = 0; + if (!options.StdInMode) + { + const UString &arcPath = arcPaths[i]; + if (!fi.Find(arcPath)) + throw "there is no such archive"; + if (fi.IsDir()) + throw "can't decompress folder"; + } archiveSizes.Add(fi.Size); totalPackSize += fi.Size; } CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec); - bool multi = (archivePaths.Size() > 1); + bool multi = (numArcs > 1); extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode); if (multi) { RINOK(extractCallback->SetTotal(totalPackSize)); } - for (i = 0; i < archivePaths.Size(); i++) + for (i = 0; i < numArcs; i++) { - const UString &archivePath = archivePaths[i]; + const UString &arcPath = arcPaths[i]; NFile::NFind::CFileInfoW fi; - if (!NFile::NFind::FindFile(archivePath, fi)) - throw "there is no such archive"; - - if (fi.IsDir()) - throw "there is no such archive"; - - options.ArchiveFileInfo = fi; + if (options.StdInMode) + { + fi.Size = 0; + fi.Attrib = 0; + } + else + { + if (!fi.Find(arcPath) || fi.IsDir()) + throw "there is no such archive"; + } #ifndef _NO_CRYPTO openCallback->Open_ClearPasswordWasAskedFlag(); #endif - RINOK(extractCallback->BeforeOpen(archivePath)); + RINOK(extractCallback->BeforeOpen(arcPath)); CArchiveLink archiveLink; CIntVector formatIndices2 = formatIndices; #ifndef _SFX if (formatIndices.IsEmpty()) { - int pos = archivePath.ReverseFind(L'.'); + int pos = arcPath.ReverseFind(L'.'); if (pos >= 0) { - UString s = archivePath.Mid(pos + 1); + UString s = arcPath.Mid(pos + 1); int index = codecs->FindFormatForExtension(s); if (index >= 0 && s == L"001") { - s = archivePath.Left(pos); + s = arcPath.Left(pos); pos = s.ReverseFind(L'.'); if (pos >= 0) { @@ -159,7 +186,7 @@ HRESULT DecompressArchives( } } #endif - HRESULT result = MyOpenArchive(codecs, formatIndices2, archivePath, archiveLink, openCallback); + HRESULT result = archiveLink.Open2(codecs, formatIndices2, options.StdInMode, NULL, arcPath, openCallback); if (result == E_ABORT) return result; @@ -168,19 +195,21 @@ HRESULT DecompressArchives( crypted = openCallback->Open_WasPasswordAsked(); #endif - RINOK(extractCallback->OpenResult(archivePath, result, crypted)); + RINOK(extractCallback->OpenResult(arcPath, result, crypted)); if (result != S_OK) continue; + if (!options.StdInMode) for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { - int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); + int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { - archivePaths.Delete(index); - archivePathsFull.Delete(index); + arcPaths.Delete(index); + arcPathsFull.Delete(index); totalPackSize -= archiveSizes[index]; archiveSizes.Delete(index); + numArcs = arcPaths.Size(); } } if (archiveLink.VolumePaths.Size() != 0) @@ -198,13 +227,17 @@ HRESULT DecompressArchives( } #endif - options.DefaultItemName = archiveLink.GetDefaultItemName(); - RINOK(DecompressArchive( - archiveLink.GetArchive(), + CArc &arc = archiveLink.Arcs.Back(); + arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice); + arc.MTime = fi.MTime; + + UInt64 packProcessed; + RINOK(DecompressArchive(arc, fi.Size + archiveLink.VolumesSize, - wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage)); - extractCallbackSpec->LocalProgressSpec->InSize += fi.Size + - archiveLink.VolumesSize; + wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage, packProcessed)); + if (!options.StdInMode) + packProcessed = fi.Size + archiveLink.VolumesSize; + extractCallbackSpec->LocalProgressSpec->InSize += packProcessed; extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize; if (!errorMessage.IsEmpty()) return E_FAIL; @@ -212,7 +245,9 @@ HRESULT DecompressArchives( stat.NumFolders = extractCallbackSpec->NumFolders; stat.NumFiles = extractCallbackSpec->NumFiles; stat.UnpackSize = extractCallbackSpec->UnpackSize; - stat.NumArchives = archivePaths.Size(); + stat.CrcSum = extractCallbackSpec->CrcSum; + + stat.NumArchives = arcPaths.Size(); stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize; return S_OK; } diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h index 37add18b..442dd2b0 100755 --- a/CPP/7zip/UI/Common/Extract.h +++ b/CPP/7zip/UI/Common/Extract.h @@ -3,7 +3,6 @@ #ifndef __EXTRACT_H #define __EXTRACT_H -#include "Common/Wildcard.h" #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" @@ -15,17 +14,16 @@ #include "../Common/LoadCodecs.h" -class CExtractOptions +struct CExtractOptions { -public: + bool StdInMode; bool StdOutMode; + bool YesToAll; bool TestMode; + bool CalcCrc; NExtract::NPathMode::EEnum PathMode; - + NExtract::NOverwriteMode::EEnum OverwriteMode; UString OutputDir; - bool YesToAll; - UString DefaultItemName; - NWindows::NFile::NFind::CFileInfoW ArchiveFileInfo; // bool ShowDialog; // bool PasswordEnabled; @@ -34,24 +32,19 @@ public: CObjectVector<CProperty> Properties; #endif - NExtract::NOverwriteMode::EEnum OverwriteMode; - #ifdef EXTERNAL_CODECS CCodecs *Codecs; #endif CExtractOptions(): + StdInMode(false), StdOutMode(false), YesToAll(false), TestMode(false), + CalcCrc(false), PathMode(NExtract::NPathMode::kFullPathnames), OverwriteMode(NExtract::NOverwriteMode::kAskBefore) {} - - /* - bool FullPathMode() const { return (ExtractMode == NExtractMode::kTest) || - (ExtractMode == NExtractMode::kFullPath); } - */ }; struct CDecompressStat @@ -61,7 +54,13 @@ struct CDecompressStat UInt64 PackSize; UInt64 NumFolders; UInt64 NumFiles; - void Clear() { NumArchives = PackSize = UnpackSize = NumFolders = NumFiles = 0; } + UInt32 CrcSum; + + void Clear() + { + NumArchives = UnpackSize = PackSize = NumFolders = NumFiles = 0; + CrcSum = 0; + } }; HRESULT DecompressArchives( diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp index 5de388dd..67a58372 100755 --- a/CPP/7zip/UI/Common/ExtractingFilePath.cpp +++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp @@ -1,6 +1,9 @@ // ExtractingFilePath.cpp #include "StdAfx.h" + +#include "Common/Wildcard.h" + #include "ExtractingFilePath.h" static UString ReplaceIncorrectChars(const UString &s) @@ -15,6 +18,8 @@ static UString ReplaceIncorrectChars(const UString &s) res += c; } res.TrimRight(); + while (!res.IsEmpty() && res[res.Length() - 1] == '.') + res.Delete(res.Length() - 1); return res; #else return s; @@ -95,3 +100,41 @@ void MakeCorrectPath(UStringVector &pathParts) } } +UString MakePathNameFromParts(const UStringVector &parts) +{ + UString result; + for (int i = 0; i < parts.Size(); i++) + { + if (i != 0) + result += WCHAR_PATH_SEPARATOR; + result += parts[i]; + } + return result; +} + +UString GetCorrectFsPath(const UString &path) +{ + UString res = GetCorrectFileName(path); + #ifdef _WIN32 + if (!IsSupportedName(res)) + res = (UString)L"_" + res; + #endif + return res; +} + +UString GetCorrectFullFsPath(const UString &path) +{ + UStringVector parts; + SplitPathToParts(path, parts); + for (int i = 0; i < parts.Size(); i++) + { + UString &s = parts[i]; + #ifdef _WIN32 + while (!s.IsEmpty() && s[s.Length() - 1] == '.') + s.Delete(s.Length() - 1); + if (!IsSupportedName(s)) + s = (UString)L"_" + s; + #endif + } + return MakePathNameFromParts(parts); +} diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.h b/CPP/7zip/UI/Common/ExtractingFilePath.h index a86a6a9b..da28bfc2 100755 --- a/CPP/7zip/UI/Common/ExtractingFilePath.h +++ b/CPP/7zip/UI/Common/ExtractingFilePath.h @@ -1,10 +1,13 @@ // ExtractingFilePath.h -#ifndef __EXTRACTINGFILEPATH_H -#define __EXTRACTINGFILEPATH_H +#ifndef __EXTRACTING_FILE_PATH_H +#define __EXTRACTING_FILE_PATH_H #include "Common/MyString.h" +UString MakePathNameFromParts(const UStringVector &parts); void MakeCorrectPath(UStringVector &pathParts); +UString GetCorrectFsPath(const UString &path); +UString GetCorrectFullFsPath(const UString &path); #endif diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp index 4b5639ee..dac8c4d2 100755 --- a/CPP/7zip/UI/Common/LoadCodecs.cpp +++ b/CPP/7zip/UI/Common/LoadCodecs.cpp @@ -69,22 +69,17 @@ static bool ReadPathFromRegistry(HKEY baseKey, CSysString &path) CSysString GetBaseFolderPrefixFromRegistry() { CSysString moduleFolderPrefix = GetLibraryFolderPrefix(); - NFind::CFileInfo fi; - if (NFind::FindFile(moduleFolderPrefix + kMainDll, fi)) - if (!fi.IsDir()) - return moduleFolderPrefix; - if (NFind::FindFile(moduleFolderPrefix + kCodecsFolderName, fi)) - if (fi.IsDir()) - return moduleFolderPrefix; - if (NFind::FindFile(moduleFolderPrefix + kFormatsFolderName, fi)) - if (fi.IsDir()) - return moduleFolderPrefix; #ifdef _WIN32 - CSysString path; - if (ReadPathFromRegistry(HKEY_CURRENT_USER, path)) - return path; - if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path)) - return path; + if (!NFind::DoesFileExist(moduleFolderPrefix + kMainDll) && + !NFind::DoesDirExist(moduleFolderPrefix + kCodecsFolderName) && + !NFind::DoesDirExist(moduleFolderPrefix + kFormatsFolderName)) + { + CSysString path; + if (ReadPathFromRegistry(HKEY_CURRENT_USER, path)) + return path; + if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path)) + return path; + } #endif return moduleFolderPrefix; } @@ -181,7 +176,7 @@ static HRESULT ReadStringProp( #endif -static const unsigned int kNumArcsMax = 32; +static const unsigned int kNumArcsMax = 48; static unsigned int g_NumArcs = 0; static const CArcInfo *g_Arcs[kNumArcsMax]; void RegisterArc(const CArcInfo *arcInfo) @@ -457,9 +452,7 @@ int CCodecs::FindFormatForArchiveName(const UString &arcPath) const const CArcInfoEx &arc = Formats[i]; if (!arc.UpdateEnabled) continue; - // if (arc.FindExtension(ext) >= 0) - UString mainExt = arc.GetMainExt(); - if (!mainExt.IsEmpty() && ext.CompareNoCase(mainExt) == 0) + if (arc.FindExtension(ext) >= 0) return i; } return -1; diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp index 364ddff5..ec9f9a45 100755 --- a/CPP/7zip/UI/Common/OpenArchive.cpp +++ b/CPP/7zip/UI/Common/OpenArchive.cpp @@ -2,45 +2,56 @@ #include "StdAfx.h" -#include "OpenArchive.h" - #include "Common/Wildcard.h" -#include "Windows/FileName.h" #include "Windows/FileDir.h" -#include "Windows/Defs.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" #include "../../Common/StreamUtils.h" -#include "Common/StringConvert.h" - #include "DefaultName.h" +#include "OpenArchive.h" using namespace NWindows; -HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result) +// Static-SFX (for Linux) can be big. +const UInt64 kMaxCheckStartPosition = 1 << 22; + +HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) { NCOM::CPropVariant prop; - RINOK(archive->GetProperty(index, kpidPath, &prop)); - if(prop.vt == VT_BSTR) - result = prop.bstrVal; - else if (prop.vt == VT_EMPTY) - result.Empty(); - else + result = false; + RINOK(archive->GetProperty(index, propID, &prop)); + if (prop.vt == VT_BOOL) + result = VARIANT_BOOLToBool(prop.boolVal); + else if (prop.vt != VT_EMPTY) return E_FAIL; return S_OK; } -HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result) +HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) { - RINOK(GetArchiveItemPath(archive, index, result)); + return GetArchiveItemBoolProp(archive, index, kpidIsDir, result); +} + +HRESULT CArc::GetItemPath(UInt32 index, UString &result) const +{ + { + NCOM::CPropVariant prop; + RINOK(Archive->GetProperty(index, kpidPath, &prop)); + if (prop.vt == VT_BSTR) + result = prop.bstrVal; + else if (prop.vt == VT_EMPTY) + result.Empty(); + else + return E_FAIL; + } if (result.IsEmpty()) { - result = defaultName; + result = DefaultName; NCOM::CPropVariant prop; - RINOK(archive->GetProperty(index, kpidExtension, &prop)); + RINOK(Archive->GetProperty(index, kpidExtension, &prop)); if (prop.vt == VT_BSTR) { result += L'.'; @@ -52,54 +63,27 @@ HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &def return S_OK; } -HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, - const FILETIME &defaultFileTime, FILETIME &fileTime) +HRESULT CArc::GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const { NCOM::CPropVariant prop; - RINOK(archive->GetProperty(index, kpidMTime, &prop)); + defined = false; + ft.dwHighDateTime = ft.dwLowDateTime = 0; + RINOK(Archive->GetProperty(index, kpidMTime, &prop)); if (prop.vt == VT_FILETIME) - fileTime = prop.filetime; - else if (prop.vt == VT_EMPTY) - fileTime = defaultFileTime; - else - return E_FAIL; - return S_OK; -} - -HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) -{ - NCOM::CPropVariant prop; - RINOK(archive->GetProperty(index, propID, &prop)); - if(prop.vt == VT_BOOL) - result = VARIANT_BOOLToBool(prop.boolVal); - else if (prop.vt == VT_EMPTY) - result = false; - else + { + ft = prop.filetime; + defined = true; + } + else if (prop.vt != VT_EMPTY) return E_FAIL; + else if (MTimeDefined) + { + ft = MTime; + defined = true; + } return S_OK; } -HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result) -{ - return IsArchiveItemProp(archive, index, kpidIsDir, result); -} - -HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result) -{ - return IsArchiveItemProp(archive, index, kpidIsAnti, result); -} - -// Static-SFX (for Linux) can be big. -const UInt64 kMaxCheckStartPosition = 1 << 22; - -HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback) -{ - CInFileStream *inStreamSpec = new CInFileStream; - CMyComPtr<IInStream> inStream(inStreamSpec); - inStreamSpec->Open(fileName); - return archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); -} - #ifndef _SFX static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) { @@ -110,17 +94,15 @@ static inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size) } #endif -HRESULT OpenArchive( +HRESULT CArc::OpenStream( CCodecs *codecs, - int arcTypeIndex, - IInStream *inStream, - const UString &fileName, - IInArchive **archiveResult, - int &formatIndex, - UString &defaultItemName, - IArchiveOpenCallback *openArchiveCallback) + int formatIndex, + IInStream *stream, + ISequentialInStream *seqStream, + IArchiveOpenCallback *callback) { - *archiveResult = NULL; + Archive.Release(); + const UString fileName = ExtractFileNameFromPath(Path); UString extension; { int dotPos = fileName.ReverseFind(L'.'); @@ -128,8 +110,8 @@ HRESULT OpenArchive( extension = fileName.Mid(dotPos + 1); } CIntVector orderIndices; - if (arcTypeIndex >= 0) - orderIndices.Add(arcTypeIndex); + if (formatIndex >= 0) + orderIndices.Add(formatIndex); else { @@ -141,16 +123,23 @@ HRESULT OpenArchive( else orderIndices.Add(i); + if (!stream) + { + if (numFinded != 1) + return E_NOTIMPL; + orderIndices.DeleteFrom(1); + } + #ifndef _SFX - if (numFinded != 1) + if (numFinded == 0) { CIntVector orderIndices2; CByteBuffer byteBuffer; const size_t kBufferSize = (1 << 21); byteBuffer.SetCapacity(kBufferSize); - RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); size_t processedSize = kBufferSize; - RINOK(ReadStream(inStream, byteBuffer, &processedSize)); + RINOK(ReadStream(stream, byteBuffer, &processedSize)); if (processedSize == 0) return S_FALSE; @@ -206,24 +195,6 @@ HRESULT OpenArchive( orderIndices2.Add(val); } orderIndices = orderIndices2; - - if (orderIndices.Size() >= 2) - { - int isoIndex = codecs->FindFormatForArchiveType(L"iso"); - int udfIndex = codecs->FindFormatForArchiveType(L"udf"); - int iIso = -1; - int iUdf = -1; - for (int i = 0; i < orderIndices.Size(); i++) - { - if (orderIndices[i] == isoIndex) iIso = i; - if (orderIndices[i] == udfIndex) iUdf = i; - } - if (iUdf == iIso + 1) - { - orderIndices[iUdf] = isoIndex; - orderIndices[iIso] = udfIndex; - } - } } else if (extension == L"000" || extension == L"001") { @@ -231,9 +202,9 @@ HRESULT OpenArchive( const size_t kBufferSize = (1 << 10); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; - RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); size_t processedSize = kBufferSize; - RINOK(ReadStream(inStream, buffer, &processedSize)); + RINOK(ReadStream(stream, buffer, &processedSize)); if (processedSize >= 16) { Byte kRarHeader[] = {0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}; @@ -252,17 +223,37 @@ HRESULT OpenArchive( } } } + if (orderIndices.Size() >= 2) + { + int isoIndex = codecs->FindFormatForArchiveType(L"iso"); + int udfIndex = codecs->FindFormatForArchiveType(L"udf"); + int iIso = -1; + int iUdf = -1; + for (int i = 0; i < orderIndices.Size(); i++) + { + if (orderIndices[i] == isoIndex) iIso = i; + if (orderIndices[i] == udfIndex) iUdf = i; + } + if (iUdf > iIso && iIso >= 0) + { + orderIndices[iUdf] = isoIndex; + orderIndices[iIso] = udfIndex; + } + } + #endif } - for(int i = 0; i < orderIndices.Size(); i++) + for (int i = 0; i < orderIndices.Size(); i++) { - inStream->Seek(0, STREAM_SEEK_SET, NULL); - + if (stream) + { + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); + } CMyComPtr<IInArchive> archive; - formatIndex = orderIndices[i]; - RINOK(codecs->CreateInArchive(formatIndex, archive)); + FormatIndex = orderIndices[i]; + RINOK(codecs->CreateInArchive(FormatIndex, archive)); if (!archive) continue; @@ -277,274 +268,239 @@ HRESULT OpenArchive( } #endif - HRESULT result = archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback); + // OutputDebugStringW(codecs->Formats[FormatIndex].Name); + + HRESULT result; + if (stream) + result = archive->Open(stream, &kMaxCheckStartPosition, callback); + else + { + CMyComPtr<IArchiveOpenSeq> openSeq; + archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq); + if (!openSeq) + return E_NOTIMPL; + result = openSeq->OpenSeq(seqStream); + } + if (result == S_FALSE) continue; RINOK(result); - *archiveResult = archive.Detach(); - const CArcInfoEx &format = codecs->Formats[formatIndex]; + + Archive = archive; + const CArcInfoEx &format = codecs->Formats[FormatIndex]; if (format.Exts.Size() == 0) - { - defaultItemName = GetDefaultName2(fileName, L"", L""); - } + DefaultName = GetDefaultName2(fileName, L"", L""); else { int subExtIndex = format.FindExtension(extension); if (subExtIndex < 0) subExtIndex = 0; - defaultItemName = GetDefaultName2(fileName, - format.Exts[subExtIndex].Ext, - format.Exts[subExtIndex].AddExt); + const CArcExtInfo &extInfo = format.Exts[subExtIndex]; + DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt); } return S_OK; } return S_FALSE; } -HRESULT OpenArchive( +HRESULT CArc::OpenStreamOrFile( CCodecs *codecs, - int arcTypeIndex, - const UString &filePath, - IInArchive **archiveResult, - int &formatIndex, - UString &defaultItemName, - IArchiveOpenCallback *openArchiveCallback) + int formatIndex, + bool stdInMode, + IInStream *stream, + IArchiveOpenCallback *callback) { - CInFileStream *inStreamSpec = new CInFileStream; - CMyComPtr<IInStream> inStream(inStreamSpec); - if (!inStreamSpec->Open(filePath)) - return GetLastError(); - return OpenArchive(codecs, arcTypeIndex, inStream, ExtractFileNameFromPath(filePath), - archiveResult, formatIndex, - defaultItemName, openArchiveCallback); + CMyComPtr<IInStream> fileStream; + CMyComPtr<ISequentialInStream> seqStream; + if (stdInMode) + seqStream = new CStdInFileStream; + else if (!stream) + { + CInFileStream *fileStreamSpec = new CInFileStream; + fileStream = fileStreamSpec; + if (!fileStreamSpec->Open(Path)) + return GetLastError(); + stream = fileStream; + } + + return OpenStream(codecs, formatIndex, stream, seqStream, callback); } -static void MakeDefaultName(UString &name) +HRESULT CArchiveLink::Close() { - int dotPos = name.ReverseFind(L'.'); - if (dotPos < 0) - return; - UString ext = name.Mid(dotPos + 1); - if (ext.IsEmpty()) - return; - for (int pos = 0; pos < ext.Length(); pos++) - if (ext[pos] < L'0' || ext[pos] > L'9') - return; - name = name.Left(dotPos); + for (int i = Arcs.Size() - 1; i >= 0; i--) + { + RINOK(Arcs[i].Archive->Close()); + } + IsOpen = false; + return S_OK; } -HRESULT OpenArchive( +void CArchiveLink::Release() +{ + while (!Arcs.IsEmpty()) + Arcs.DeleteBack(); +} + +HRESULT CArchiveLink::Open( CCodecs *codecs, const CIntVector &formatIndices, - const UString &fileName, - IInArchive **archive0, - IInArchive **archive1, - int &formatIndex0, - int &formatIndex1, - UString &defaultItemName0, - UString &defaultItemName1, - IArchiveOpenCallback *openArchiveCallback) + bool stdInMode, + IInStream *stream, + const UString &filePath, + IArchiveOpenCallback *callback) { - if (formatIndices.Size() >= 3) + Release(); + if (formatIndices.Size() >= 32) return E_NOTIMPL; - int arcTypeIndex = -1; - if (formatIndices.Size() >= 1) - arcTypeIndex = formatIndices[formatIndices.Size() - 1]; - - HRESULT result = OpenArchive(codecs, arcTypeIndex, fileName, - archive0, formatIndex0, defaultItemName0, openArchiveCallback); - RINOK(result); + HRESULT resSpec; - if (formatIndices.Size() == 1) - return S_OK; - arcTypeIndex = -1; - if (formatIndices.Size() >= 2) - arcTypeIndex = formatIndices[formatIndices.Size() - 2]; - - HRESULT resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL); - - CMyComPtr<IInArchiveGetStream> getStream; - result = (*archive0)->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream); - if (result != S_OK || !getStream) - return resSpec; - - CMyComPtr<ISequentialInStream> subSeqStream; - result = getStream->GetStream(0, &subSeqStream); - if (result != S_OK || !subSeqStream) - return resSpec; - - CMyComPtr<IInStream> subStream; - result = subSeqStream.QueryInterface(IID_IInStream, &subStream); - if (result != S_OK || !subStream) - return resSpec; - - UInt32 numItems; - RINOK((*archive0)->GetNumberOfItems(&numItems)); - if (numItems < 1) - return resSpec; - - UString subPath; - RINOK(GetArchiveItemPath(*archive0, 0, subPath)) - if (subPath.IsEmpty()) + for (;;) { - MakeDefaultName(defaultItemName0); - subPath = defaultItemName0; - const CArcInfoEx &format = codecs->Formats[formatIndex0]; - if (format.Name.CompareNoCase(L"7z") == 0) + resSpec = S_OK; + int formatIndex = -1; + if (formatIndices.Size() >= 1) + { + if (Arcs.Size() >= formatIndices.Size()) + break; + formatIndex = formatIndices[formatIndices.Size() - Arcs.Size() - 1]; + } + else if (Arcs.Size() >= 32) + break; + + if (Arcs.IsEmpty()) + { + CArc arc; + arc.Path = filePath; + arc.SubfileIndex = (UInt32)(Int32)-1; + RINOK(arc.OpenStreamOrFile(codecs, formatIndex, stdInMode, stream, callback)); + Arcs.Add(arc); + continue; + } + + const CArc &arc = Arcs.Back(); + + resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL); + + UInt32 mainSubfile; { - if (subPath.Right(3).CompareNoCase(L".7z") != 0) - subPath += L".7z"; + NCOM::CPropVariant prop; + RINOK(arc.Archive->GetArchiveProperty(kpidMainSubfile, &prop)); + if (prop.vt == VT_UI4) + mainSubfile = prop.ulVal; + else + break; + UInt32 numItems; + RINOK(arc.Archive->GetNumberOfItems(&numItems)); + if (mainSubfile >= numItems) + break; } + + + CMyComPtr<IInArchiveGetStream> getStream; + if (arc.Archive->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream) != S_OK || !getStream) + break; + + CMyComPtr<ISequentialInStream> subSeqStream; + if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK || !subSeqStream) + break; + + CMyComPtr<IInStream> subStream; + if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK || !subStream) + break; + + CArc arc2; + RINOK(arc.GetItemPath(mainSubfile, arc2.Path)); + + CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName; + callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); + if (setSubArchiveName) + setSubArchiveName->SetSubArchiveName(arc2.Path); + + arc2.SubfileIndex = mainSubfile; + HRESULT result = arc2.OpenStream(codecs, formatIndex, subStream, NULL, callback); + resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE); + if (result == S_FALSE) + break; + RINOK(result); + RINOK(arc.GetItemMTime(mainSubfile, arc2.MTime, arc2.MTimeDefined)); + Arcs.Add(arc2); } - else - subPath = ExtractFileNameFromPath(subPath); - - CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName; - openArchiveCallback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName); - if (setSubArchiveName) - setSubArchiveName->SetSubArchiveName(subPath); - - result = OpenArchive(codecs, arcTypeIndex, subStream, subPath, - archive1, formatIndex1, defaultItemName1, openArchiveCallback); - resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE); - if (result != S_OK) - return resSpec; + IsOpen = !Arcs.IsEmpty(); return S_OK; } -static void SetCallback(const UString &archiveName, - IOpenCallbackUI *openCallbackUI, +static void SetCallback(const UString &filePath, + IOpenCallbackUI *callbackUI, IArchiveOpenCallback *reOpenCallback, - CMyComPtr<IArchiveOpenCallback> &openCallback) + CMyComPtr<IArchiveOpenCallback> &callback) { COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; - openCallback = openCallbackSpec; - openCallbackSpec->Callback = openCallbackUI; + callback = openCallbackSpec; + openCallbackSpec->Callback = callbackUI; openCallbackSpec->ReOpenCallback = reOpenCallback; UString fullName; int fileNamePartStartIndex; - NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); + NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex); openCallbackSpec->Init( fullName.Left(fileNamePartStartIndex), fullName.Mid(fileNamePartStartIndex)); } -HRESULT MyOpenArchive( - CCodecs *codecs, - int arcTypeIndex, - const UString &archiveName, - IInArchive **archive, UString &defaultItemName, IOpenCallbackUI *openCallbackUI) -{ - CMyComPtr<IArchiveOpenCallback> openCallback; - SetCallback(archiveName, openCallbackUI, NULL, openCallback); - int formatInfo; - return OpenArchive(codecs, arcTypeIndex, archiveName, archive, formatInfo, defaultItemName, openCallback); -} - -HRESULT MyOpenArchive( - CCodecs *codecs, +HRESULT CArchiveLink::Open2(CCodecs *codecs, const CIntVector &formatIndices, - const UString &archiveName, - IInArchive **archive0, - IInArchive **archive1, - UString &defaultItemName0, - UString &defaultItemName1, - UStringVector &volumePaths, - UInt64 &volumesSize, - IOpenCallbackUI *openCallbackUI) + bool stdInMode, + IInStream *stream, + const UString &filePath, + IOpenCallbackUI *callbackUI) { - volumesSize = 0; + VolumesSize = 0; COpenCallbackImp *openCallbackSpec = new COpenCallbackImp; - CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec; - openCallbackSpec->Callback = openCallbackUI; + CMyComPtr<IArchiveOpenCallback> callback = openCallbackSpec; + openCallbackSpec->Callback = callbackUI; - UString fullName; - int fileNamePartStartIndex; - NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex); - UString prefix = fullName.Left(fileNamePartStartIndex); - UString name = fullName.Mid(fileNamePartStartIndex); - openCallbackSpec->Init(prefix, name); - - int formatIndex0, formatIndex1; - RINOK(OpenArchive(codecs, formatIndices, archiveName, - archive0, - archive1, - formatIndex0, - formatIndex1, - defaultItemName0, - defaultItemName1, - openCallback)); - volumePaths.Add(prefix + name); - for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++) - volumePaths.Add(prefix + openCallbackSpec->FileNames[i]); - volumesSize = openCallbackSpec->TotalSize; - return S_OK; -} + UString fullName, prefix, name; + if (!stream && !stdInMode) + { + int fileNamePartStartIndex; + if (!NFile::NDirectory::MyGetFullPathName(filePath, fullName, fileNamePartStartIndex)) + return GetLastError(); + prefix = fullName.Left(fileNamePartStartIndex); + name = fullName.Mid(fileNamePartStartIndex); + openCallbackSpec->Init(prefix, name); + } + else + { + openCallbackSpec->SetSubArchiveName(filePath); + } -HRESULT CArchiveLink::Close() -{ - if (Archive1 != 0) - RINOK(Archive1->Close()); - if (Archive0 != 0) - RINOK(Archive0->Close()); - IsOpen = false; + RINOK(Open(codecs, formatIndices, stdInMode, stream, filePath, callback)); + VolumePaths.Add(prefix + name); + for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++) + VolumePaths.Add(prefix + openCallbackSpec->FileNames[i]); + VolumesSize = openCallbackSpec->TotalSize; return S_OK; } -void CArchiveLink::Release() -{ - IsOpen = false; - Archive1.Release(); - Archive0.Release(); -} - -HRESULT OpenArchive( - CCodecs *codecs, - const CIntVector &formatIndices, - const UString &archiveName, - CArchiveLink &archiveLink, - IArchiveOpenCallback *openCallback) -{ - HRESULT res = OpenArchive(codecs, formatIndices, archiveName, - &archiveLink.Archive0, &archiveLink.Archive1, - archiveLink.FormatIndex0, archiveLink.FormatIndex1, - archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, - openCallback); - archiveLink.IsOpen = (res == S_OK); - return res; -} - -HRESULT MyOpenArchive(CCodecs *codecs, - const CIntVector &formatIndices, - const UString &archiveName, - CArchiveLink &archiveLink, - IOpenCallbackUI *openCallbackUI) +HRESULT CArchiveLink::ReOpen(CCodecs *codecs, const UString &filePath, + IArchiveOpenCallback *callback) { - HRESULT res = MyOpenArchive(codecs, formatIndices, archiveName, - &archiveLink.Archive0, &archiveLink.Archive1, - archiveLink.DefaultItemName0, archiveLink.DefaultItemName1, - archiveLink.VolumePaths, - archiveLink.VolumesSize, - openCallbackUI); - archiveLink.IsOpen = (res == S_OK); - return res; -} - -HRESULT ReOpenArchive(CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName, - IArchiveOpenCallback *openCallback) -{ - if (archiveLink.GetNumLevels() > 1) + if (Arcs.Size() > 1) return E_NOTIMPL; - if (archiveLink.GetNumLevels() == 0) - return MyOpenArchive(codecs, CIntVector(), fileName, archiveLink, 0); + if (Arcs.Size() == 0) + return Open2(codecs, CIntVector(), false, NULL, filePath, 0); CMyComPtr<IArchiveOpenCallback> openCallbackNew; - SetCallback(fileName, NULL, openCallback, openCallbackNew); + SetCallback(filePath, NULL, callback, openCallbackNew); - HRESULT res = ReOpenArchive(archiveLink.GetArchive(), fileName, openCallbackNew); - archiveLink.IsOpen = (res == S_OK); + CInFileStream *fileStreamSpec = new CInFileStream; + CMyComPtr<IInStream> stream(fileStreamSpec); + if (!fileStreamSpec->Open(filePath)) + return GetLastError(); + HRESULT res = GetArchive()->Open(stream, &kMaxCheckStartPosition, callback); + IsOpen = (res == S_OK); return res; } diff --git a/CPP/7zip/UI/Common/OpenArchive.h b/CPP/7zip/UI/Common/OpenArchive.h index f1b4fda7..92103623 100755 --- a/CPP/7zip/UI/Common/OpenArchive.h +++ b/CPP/7zip/UI/Common/OpenArchive.h @@ -1,117 +1,86 @@ // OpenArchive.h -#ifndef __OPENARCHIVE_H -#define __OPENARCHIVE_H +#ifndef __OPEN_ARCHIVE_H +#define __OPEN_ARCHIVE_H #include "Common/MyString.h" + #include "Windows/FileFind.h" #include "../../Archive/IArchive.h" -#include "LoadCodecs.h" + #include "ArchiveOpenCallback.h" +#include "LoadCodecs.h" -HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &result); -HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result); -HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index, - const FILETIME &defaultFileTime, FILETIME &fileTime); -HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result); +HRESULT GetArchiveItemBoolProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result); HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result); -HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result); -struct ISetSubArchiveName +struct CArc { - virtual void SetSubArchiveName(const wchar_t *name) = 0; -}; - -HRESULT OpenArchive( + CMyComPtr<IInArchive> Archive; + UString Path; + UString DefaultName; + int FormatIndex; + int SubfileIndex; + FILETIME MTime; + bool MTimeDefined; + + CArc(): MTimeDefined(false) {} + + HRESULT GetItemPath(UInt32 index, UString &result) const; + HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const; + HRESULT IsItemAnti(UInt32 index, bool &result) const + { return GetArchiveItemBoolProp(Archive, index, kpidIsAnti, result); } + + HRESULT OpenStream( CCodecs *codecs, - int arcTypeIndex, - IInStream *inStream, - const UString &fileName, - IInArchive **archiveResult, - int &formatIndex, - UString &defaultItemName, - IArchiveOpenCallback *openArchiveCallback); - -HRESULT OpenArchive( - CCodecs *codecs, - int arcTypeIndex, - const UString &filePath, - IInArchive **archive, - int &formatIndex, - UString &defaultItemName, - IArchiveOpenCallback *openArchiveCallback); + int formatIndex, + IInStream *stream, + ISequentialInStream *seqStream, + IArchiveOpenCallback *callback); -HRESULT OpenArchive( + HRESULT OpenStreamOrFile( CCodecs *codecs, - const CIntVector &formatIndices, - const UString &filePath, - IInArchive **archive0, - IInArchive **archive1, - int &formatIndex0, - int &formatIndex1, - UString &defaultItemName0, - UString &defaultItemName1, - IArchiveOpenCallback *openArchiveCallback); - - -HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName, IArchiveOpenCallback *openArchiveCallback); + int formatIndex, + bool stdInMode, + IInStream *stream, + IArchiveOpenCallback *callback); +}; struct CArchiveLink { - CMyComPtr<IInArchive> Archive0; - CMyComPtr<IInArchive> Archive1; - UString DefaultItemName0; - UString DefaultItemName1; - - int FormatIndex0; - int FormatIndex1; - + CObjectVector<CArc> Arcs; UStringVector VolumePaths; - - bool IsOpen; UInt64 VolumesSize; + bool IsOpen; - int GetNumLevels() const - { - int result = 0; - if (Archive0) - { - result++; - if (Archive1) - result++; - } - return result; - } - - CArchiveLink(): IsOpen(false), VolumesSize(0) {}; - - IInArchive *GetArchive() { return Archive1 != 0 ? Archive1: Archive0; } - UString GetDefaultItemName() { return Archive1 != 0 ? DefaultItemName1: DefaultItemName0; } - int GetArchiverIndex() const { return Archive1 != 0 ? FormatIndex1: FormatIndex0; } + CArchiveLink(): VolumesSize(0), IsOpen(false) {} HRESULT Close(); void Release(); -}; + ~CArchiveLink() { Release(); } + + IInArchive *GetArchive() const { return Arcs.Back().Archive; } -HRESULT OpenArchive( + HRESULT Open( CCodecs *codecs, const CIntVector &formatIndices, - const UString &archiveName, - CArchiveLink &archiveLink, - IArchiveOpenCallback *openCallback); + bool stdInMode, + IInStream *stream, + const UString &filePath, + IArchiveOpenCallback *callback); -HRESULT MyOpenArchive( + HRESULT Open2( CCodecs *codecs, const CIntVector &formatIndices, - const UString &archiveName, - CArchiveLink &archiveLink, - IOpenCallbackUI *openCallbackUI); + bool stdInMode, + IInStream *stream, + const UString &filePath, + IOpenCallbackUI *callbackUI); -HRESULT ReOpenArchive( + HRESULT ReOpen( CCodecs *codecs, - CArchiveLink &archiveLink, - const UString &fileName, - IArchiveOpenCallback *openCallback); + const UString &filePath, + IArchiveOpenCallback *callback); +}; #endif - diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp index bf11ea15..d8c0e7d6 100755 --- a/CPP/7zip/UI/Common/PropIDUtils.cpp +++ b/CPP/7zip/UI/Common/PropIDUtils.cpp @@ -2,26 +2,18 @@ #include "StdAfx.h" -#include "PropIDUtils.h" - #include "Common/IntToString.h" -#include "Common/StringConvert.h" #include "Windows/FileFind.h" #include "Windows/PropVariantConversions.h" #include "../../PropID.h" -using namespace NWindows; +#include "PropIDUtils.h" -static UString ConvertUInt32ToString(UInt32 value) -{ - wchar_t buffer[32]; - ConvertUInt64ToString(value, buffer); - return buffer; -} +using namespace NWindows; -static void ConvertUInt32ToHex(UInt32 value, wchar_t *s) +void ConvertUInt32ToHex(UInt32 value, wchar_t *s) { for (int i = 0; i < 8; i++) { @@ -32,7 +24,9 @@ static void ConvertUInt32ToHex(UInt32 value, wchar_t *s) s[8] = L'\0'; } -UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full) +#define MY_ATTR_CHAR(a, n, c) ((a )& (1 << (n))) ? c : L'-'; + +UString ConvertPropertyToString(const PROPVARIANT &prop, PROPID propID, bool full) { switch(propID) { @@ -40,50 +34,63 @@ UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, b case kpidATime: case kpidMTime: { - if (propVariant.vt != VT_FILETIME) - return UString(); // It is error; + if (prop.vt != VT_FILETIME) + break; FILETIME localFileTime; - if (propVariant.filetime.dwHighDateTime == 0 && - propVariant.filetime.dwLowDateTime == 0) + if ((prop.filetime.dwHighDateTime == 0 && + prop.filetime.dwLowDateTime == 0) || + !::FileTimeToLocalFileTime(&prop.filetime, &localFileTime)) return UString(); - if (!::FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime)) - return UString(); // It is error; return ConvertFileTimeToString(localFileTime, true, full); } case kpidCRC: { - if(propVariant.vt != VT_UI4) + if (prop.vt != VT_UI4) break; wchar_t temp[12]; - ConvertUInt32ToHex(propVariant.ulVal, temp); + ConvertUInt32ToHex(prop.ulVal, temp); return temp; } case kpidAttrib: { - if(propVariant.vt != VT_UI4) + if (prop.vt != VT_UI4) break; - UString result; - UInt32 attributes = propVariant.ulVal; - if (NFile::NFind::NAttributes::IsReadOnly(attributes)) result += L'R'; - if (NFile::NFind::NAttributes::IsHidden(attributes)) result += L'H'; - if (NFile::NFind::NAttributes::IsSystem(attributes)) result += L'S'; - if (NFile::NFind::NAttributes::IsDir(attributes)) result += L'D'; - if (NFile::NFind::NAttributes::IsArchived(attributes)) result += L'A'; - if (NFile::NFind::NAttributes::IsCompressed(attributes)) result += L'C'; - if (NFile::NFind::NAttributes::IsEncrypted(attributes)) result += L'E'; - return result; + 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; } - case kpidDictionarySize: + case kpidPosixAttrib: { - if(propVariant.vt != VT_UI4) + if (prop.vt != VT_UI4) break; - UInt32 size = propVariant.ulVal; - if (size % (1 << 20) == 0) - return ConvertUInt32ToString(size >> 20) + L"MB"; - if (size % (1 << 10) == 0) - return ConvertUInt32ToString(size >> 10) + L"KB"; - return ConvertUInt32ToString(size); + UString res; + UInt32 a = prop.ulVal; + wchar_t temp[16]; + temp[0] = MY_ATTR_CHAR(a, 14, L'd'); + for (int i = 6; i >= 0; i -= 3) + { + temp[7 - i] = MY_ATTR_CHAR(a, i + 2, L'r'); + temp[8 - i] = MY_ATTR_CHAR(a, i + 1, L'w'); + temp[9 - i] = MY_ATTR_CHAR(a, i + 0, L'x'); + } + temp[10] = 0; + res = temp; + a &= ~0x1FF; + a &= ~0xC000; + if (a != 0) + { + ConvertUInt32ToHex(a, temp); + res = UString(temp) + L' ' + res; + } + return res; } } - return ConvertPropVariantToString(propVariant); + return ConvertPropVariantToString(prop); } diff --git a/CPP/7zip/UI/Common/PropIDUtils.h b/CPP/7zip/UI/Common/PropIDUtils.h index 1d820976..ca14d091 100755 --- a/CPP/7zip/UI/Common/PropIDUtils.h +++ b/CPP/7zip/UI/Common/PropIDUtils.h @@ -1,10 +1,12 @@ // PropIDUtils.h -#ifndef __PROPIDUTILS_H -#define __PROPIDUTILS_H +#ifndef __PROPID_UTILS_H +#define __PROPID_UTILS_H #include "Common/MyString.h" +#include "Common/Types.h" +void ConvertUInt32ToHex(UInt32 value, wchar_t *s); UString ConvertPropertyToString(const PROPVARIANT &propVariant, PROPID propID, bool full = true); #endif diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp index d8fee28b..8c8db8de 100755 --- a/CPP/7zip/UI/Common/Update.cpp +++ b/CPP/7zip/UI/Common/Update.cpp @@ -44,12 +44,6 @@ static const wchar_t *kTempFolderPrefix = L"7zE"; using namespace NUpdateArchive; -static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream) -{ - CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; - return copyCoder->Code(inStream, outStream, NULL, NULL, NULL); -} - class COutMultiVolStream: public IOutStream, public CMyUnknownImp @@ -111,7 +105,7 @@ HRESULT COutMultiVolStream::Close() STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize) { - if(processedSize != NULL) + if (processedSize != NULL) *processedSize = 0; while(size > 0) { @@ -119,15 +113,15 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr { CSubStreamInfo subStream; - wchar_t temp[32]; - ConvertUInt64ToString(_streamIndex + 1, temp); + wchar_t temp[16]; + ConvertUInt32ToString(_streamIndex + 1, temp); UString res = temp; while (res.Length() < 3) res = UString(L'0') + res; UString name = Prefix + res; subStream.StreamSpec = new COutFileStream; subStream.Stream = subStream.StreamSpec; - if(!subStream.StreamSpec->Create(name, false)) + if (!subStream.StreamSpec->Create(name, false)) return ::GetLastError(); { // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS); @@ -173,7 +167,7 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr _length = _absPos; if (_offsetPos > subStream.RealSize) subStream.RealSize = _offsetPos; - if(processedSize != NULL) + if (processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == volSize) { @@ -189,7 +183,7 @@ STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) { - if(seekOrigin >= 3) + if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { @@ -261,6 +255,7 @@ bool CUpdateOptions::Init(const CCodecs *codecs, const CIntVector &formatIndices else { MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath); + // It works incorrectly for update command if archive has some non-default extension! if (MethodMode.FormatIndex < 0) MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveType); } @@ -292,7 +287,7 @@ struct CUpdateProduceCallbackImp: public IUpdateProduceCallback const CObjectVector<CArcItem> *_arcItems; IUpdateCallbackUI *_callback; - CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a, + CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a, IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {} virtual HRESULT ShowDeleteFile(int arcIndex); }; @@ -323,11 +318,11 @@ static HRESULT Compress( IUpdateCallbackUI *callback) { CMyComPtr<IOutArchive> outArchive; - if(archive != NULL) + if (archive != NULL) { CMyComPtr<IInArchive> archive2 = archive; HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive); - if(result != S_OK) + if (result != S_OK) throw kUpdateIsNotSupoorted; } else @@ -397,7 +392,7 @@ static HRESULT Compress( { UString resultPath; int pos; - if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) + if (!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos)) throw 1417161; NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos)); } @@ -421,8 +416,8 @@ static HRESULT Compress( { if (i > 0) { - wchar_t s[32]; - ConvertUInt64ToString(i, s); + wchar_t s[16]; + ConvertUInt32ToString(i, s); archivePath.TempPostfix = s; } realPath = archivePath.GetTempPath(); @@ -499,7 +494,7 @@ static HRESULT Compress( return E_FAIL; } } - RINOK(CopyBlock(sfxStream, sfxOutStream)); + RINOK(NCompress::CopyStream(sfxStream, sfxOutStream, NULL)); if (outStreamSpec) { RINOK(outStreamSpec->Close()); @@ -517,26 +512,22 @@ static HRESULT Compress( } HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor, - IInArchive *archive, - const UString &defaultItemName, - const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo, + const CArc &arc, CObjectVector<CArcItem> &arcItems) { arcItems.Clear(); UInt32 numItems; + IInArchive *archive = arc.Archive; RINOK(archive->GetNumberOfItems(&numItems)); arcItems.Reserve(numItems); for (UInt32 i = 0; i < numItems; i++) { CArcItem ai; - RINOK(GetArchiveItemPath(archive, i, ai.Name)); - // check it: defaultItemName !!! - if (ai.Name.IsEmpty()) - ai.Name = defaultItemName; + RINOK(arc.GetItemPath(i, ai.Name)); RINOK(IsArchiveItemFolder(archive, i, ai.IsDir)); ai.Censored = censor.CheckPath(ai.Name, !ai.IsDir); - RINOK(GetArchiveItemFileTime(archive, i, archiveFileInfo.MTime, ai.MTime)); + RINOK(arc.GetItemMTime(i, ai.MTime, ai.MTimeDefined)); { CPropVariant prop; @@ -586,7 +577,7 @@ static HRESULT UpdateWithItemLists( CUpdateArchiveCommand &command = options.Commands[i]; if (options.StdOutMode) { - RINOK(callback->StartArchive(0, archive != 0)); + RINOK(callback->StartArchive(L"stdout", archive != 0)); } else { @@ -684,12 +675,10 @@ HRESULT UpdateArchive( const UString archiveName = options.ArchivePath.GetFinalPath(); - UString defaultItemName; + CArchiveLink archiveLink; NFind::CFileInfoW archiveFileInfo; - CArchiveLink archiveLink; - IInArchive *archive = 0; - if (NFind::FindFile(archiveName, archiveFileInfo)) + if (archiveFileInfo.Find(archiveName)) { if (archiveFileInfo.IsDir()) throw "there is no such archive"; @@ -698,7 +687,7 @@ HRESULT UpdateArchive( CIntVector formatIndices; if (options.MethodMode.FormatIndex >= 0) formatIndices.Add(options.MethodMode.FormatIndex); - HRESULT result = MyOpenArchive(codecs, formatIndices, archiveName, archiveLink, openCallback); + HRESULT result = archiveLink.Open2(codecs, formatIndices, false, NULL, archiveName, openCallback); if (result == E_ABORT) return result; RINOK(callback->OpenResult(archiveName, result)); @@ -709,8 +698,10 @@ HRESULT UpdateArchive( errorInfo.Message = L"Updating for multivolume archives is not implemented"; return E_NOTIMPL; } - archive = archiveLink.GetArchive(); - defaultItemName = archiveLink.GetDefaultItemName(); + + CArc &arc = archiveLink.Arcs.Back(); + arc.MTimeDefined = !archiveFileInfo.IsDevice; + arc.MTime = archiveFileInfo.MTime; } else { @@ -777,12 +768,15 @@ HRESULT UpdateArchive( CTempFiles tempFiles; bool createTempFile = false; - if(!options.StdOutMode && options.UpdateArchiveItself) + + bool thereIsInArchive = archiveLink.IsOpen; + + if (!options.StdOutMode && options.UpdateArchiveItself) { CArchivePath &ap = options.Commands[0].ArchivePath; ap = options.ArchivePath; // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty()) - if ((archive != 0 || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0) + if ((thereIsInArchive || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0) { createTempFile = true; ap.Temp = true; @@ -807,7 +801,7 @@ HRESULT UpdateArchive( if (i > 0 || !createTempFile) { const UString &path = ap.GetFinalPath(); - if (NFind::DoesFileExist(path)) + if (NFind::DoesFileOrDirExist(path)) { errorInfo.SystemError = 0; errorInfo.Message = L"File already exists"; @@ -818,29 +812,30 @@ HRESULT UpdateArchive( } CObjectVector<CArcItem> arcItems; - if (archive != NULL) + if (thereIsInArchive) { - RINOK(EnumerateInArchiveItems(censor, - archive, defaultItemName, archiveFileInfo, arcItems)); + RINOK(EnumerateInArchiveItems(censor, archiveLink.Arcs.Back(), arcItems)); } - RINOK(UpdateWithItemLists(codecs, options, archive, arcItems, dirItems, + RINOK(UpdateWithItemLists(codecs, options, + thereIsInArchive ? archiveLink.GetArchive() : 0, + arcItems, dirItems, tempFiles, errorInfo, callback)); - if (archive != NULL) + if (thereIsInArchive) { RINOK(archiveLink.Close()); archiveLink.Release(); } tempFiles.Paths.Clear(); - if(createTempFile) + if (createTempFile) { try { CArchivePath &ap = options.Commands[0].ArchivePath; const UString &tempPath = ap.GetTempPath(); - if (archive != NULL) + if (thereIsInArchive) if (!NDirectory::DeleteFileAlways(archiveName)) { errorInfo.SystemError = ::GetLastError(); @@ -887,7 +882,7 @@ HRESULT UpdateArchive( { CArchivePath &ap = options.Commands[i].ArchivePath; UString arcPath; - if(!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath)) + if (!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath)) { errorInfo.SystemError = ::GetLastError(); return E_FAIL; diff --git a/CPP/7zip/UI/Common/UpdateCallback.cpp b/CPP/7zip/UI/Common/UpdateCallback.cpp index dcca2a1a..0f229058 100755 --- a/CPP/7zip/UI/Common/UpdateCallback.cpp +++ b/CPP/7zip/UI/Common/UpdateCallback.cpp @@ -2,17 +2,17 @@ #include "StdAfx.h" -#include "UpdateCallback.h" - -#include "Common/StringConvert.h" -#include "Common/IntToString.h" -#include "Common/Defs.h" #include "Common/ComTry.h" +#include "Common/Defs.h" +#include "Common/IntToString.h" +#include "Common/StringConvert.h" #include "Windows/PropVariant.h" #include "../../Common/FileStreams.h" +#include "UpdateCallback.h" + using namespace NWindows; CArchiveUpdateCallback::CArchiveUpdateCallback(): @@ -216,8 +216,8 @@ STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size) STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream) { COM_TRY_BEGIN - wchar_t temp[32]; - ConvertUInt64ToString(index + 1, temp); + wchar_t temp[16]; + ConvertUInt32ToString(index + 1, temp); UString res = temp; while (res.Length() < 2) res = UString(L'0') + res; @@ -240,3 +240,10 @@ STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDef return Callback->CryptoGetTextPassword2(passwordIsDefined, password); COM_TRY_END } + +STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword(BSTR *password) +{ + COM_TRY_BEGIN + return Callback->CryptoGetTextPassword(password); + COM_TRY_END +} diff --git a/CPP/7zip/UI/Common/UpdateCallback.h b/CPP/7zip/UI/Common/UpdateCallback.h index 2a814b37..50803f52 100755 --- a/CPP/7zip/UI/Common/UpdateCallback.h +++ b/CPP/7zip/UI/Common/UpdateCallback.h @@ -23,6 +23,7 @@ virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) x; \ virtual HRESULT SetOperationResult(Int32 operationResult) x; \ virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x; \ + virtual HRESULT CryptoGetTextPassword(BSTR *password) x; \ // virtual HRESULT ShowDeleteFile(const wchar_t *name) x; \ // virtual HRESULT CloseProgress() { return S_OK; }; @@ -34,13 +35,15 @@ struct IUpdateCallbackUI class CArchiveUpdateCallback: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, + public ICryptoGetTextPassword, public ICompressProgressInfo, public CMyUnknownImp { public: - MY_UNKNOWN_IMP3( + MY_UNKNOWN_IMP4( IArchiveUpdateCallback2, ICryptoGetTextPassword2, + ICryptoGetTextPassword, ICompressProgressInfo) STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); @@ -48,6 +51,7 @@ public: INTERFACE_IArchiveUpdateCallback2(;) STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); + STDMETHOD(CryptoGetTextPassword)(BSTR *password); public: CRecordVector<UInt64> VolumesSizes; diff --git a/CPP/7zip/UI/Common/UpdatePair.cpp b/CPP/7zip/UI/Common/UpdatePair.cpp index f6727cbf..a43a9e77 100755 --- a/CPP/7zip/UI/Common/UpdatePair.cpp +++ b/CPP/7zip/UI/Common/UpdatePair.cpp @@ -6,10 +6,11 @@ #include "Common/Defs.h" #include "Common/Wildcard.h" + #include "Windows/Time.h" -#include "UpdatePair.h" #include "SortUtils.h" +#include "UpdatePair.h" using namespace NWindows; using namespace NTime; @@ -117,20 +118,16 @@ void GetUpdatePairInfoList( ThrowError(kNotCensoredCollisionMessaged, dirNames[dirIndex2], ai.Name); pair.DirIndex = dirIndex2; pair.ArcIndex = arcIndex2; - switch (MyCompareTime( + switch (ai.MTimeDefined ? MyCompareTime( ai.TimeType != - 1 ? (NFileTimeType::EEnum)ai.TimeType : fileTimeType, - di.MTime, ai.MTime)) + di.MTime, ai.MTime): 0) { case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break; case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break; default: - if (ai.SizeDefined) - if (di.Size != ai.Size) - pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; - else - pair.State = NUpdateArchive::NPairState::kSameFiles; - else - pair.State = NUpdateArchive::NPairState::kUnknowNewerFiles; + pair.State = (ai.SizeDefined && di.Size == ai.Size) ? + NUpdateArchive::NPairState::kSameFiles : + NUpdateArchive::NPairState::kUnknowNewerFiles; } dirIndex++; arcIndex++; diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp index 4bba19f8..16df878f 100755 --- a/CPP/7zip/UI/Common/ZipRegistry.cpp +++ b/CPP/7zip/UI/Common/ZipRegistry.cpp @@ -46,7 +46,7 @@ void SaveExtractionInfo(const NExtract::CInfo &info) for(int i = 0; i < info.Paths.Size(); i++) { wchar_t numberString[16]; - ConvertUInt64ToString(i, numberString); + ConvertUInt32ToString(i, numberString); pathHistoryKey.SetValue(numberString, info.Paths[i]); } } @@ -75,7 +75,7 @@ void ReadExtractionInfo(NExtract::CInfo &info) for (;;) { wchar_t numberString[16]; - ConvertUInt64ToString(info.Paths.Size(), numberString); + ConvertUInt32ToString(info.Paths.Size(), numberString); UString path; if (pathHistoryKey.QueryValue(numberString, path) != ERROR_SUCCESS) break; @@ -180,7 +180,7 @@ void SaveCompressionInfo(const NCompression::CInfo &info) for(int i = 0; i < info.HistoryArchives.Size(); i++) { wchar_t numberString[16]; - ConvertUInt64ToString(i, numberString); + ConvertUInt32ToString(i, numberString); historyArchivesKey.SetValue(numberString, info.HistoryArchives[i]); } } @@ -246,7 +246,7 @@ void ReadCompressionInfo(NCompression::CInfo &info) for (;;) { wchar_t numberString[16]; - ConvertUInt64ToString(info.HistoryArchives.Size(), numberString); + ConvertUInt32ToString(info.HistoryArchives.Size(), numberString); UString path; if (historyArchivesKey.QueryValue(numberString, path) != ERROR_SUCCESS) break; |